diff --git a/.all-contributorsrc b/.all-contributorsrc index f0018ca9..66f56d8e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -3,15 +3,19 @@ "projectOwner": "adaures", "repoType": "gitlab", "repoHost": "https://code.castopod.org", - "files": ["README.md"], + "files": [ + "README.md", + "docs/src/index.md" + ], "imageSize": 100, "commit": false, + "contributorsPerLine": 7, "contributors": [ { "login": "yassinedoghri", "name": "Yassine Doghri", - "avatar_url": "https://avatars.githubusercontent.com/u/11021441?v=4", - "profile": "https://yassinedoghri.com", + "avatar_url": "https://code.castopod.org/uploads/-/system/user/avatar/3/avatar.png", + "profile": "https://github.com/yassinedoghri", "contributions": [ "code", "bug", @@ -96,14 +100,24 @@ "name": "Lyonel Bernard", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://twitter.com/lyonelbernard", - "contributions": ["bug", "question", "audio", "ideas"] + "contributions": [ + "bug", + "question", + "audio", + "ideas" + ] }, { "login": "ctlw83", "name": "Christopher Lagonick-Weitzel", "avatar_url": "https://secure.gravatar.com/avatar/7c2a721b52d0763673a600e8f01bd745?s=80&d=identicon", "profile": "https://www.crypticchameleon.com/", - "contributions": ["bug", "question", "audio", "ideas"] + "contributions": [ + "bug", + "question", + "audio", + "ideas" + ] }, { "login": "ernestoacostame", @@ -121,33 +135,24 @@ "ideas" ] }, - { - "login": "3wen", - "name": "Ewen", - "avatar_url": "https://mastodon.fedi.bzh/system/accounts/avatars/000/000/002/original/6f387690a504ae46.jpg", - "profile": "https://mastodon.fedi.bzh/@ewen", - "contributions": [ - { - "type": "translation", - "url": "https://translate.castopod.org" - }, - "ideas", - "code" - ] - }, { "login": "Behel", "name": "Bastien Luneteau", "avatar_url": "https://secure.gravatar.com/avatar/ad63ee8ef8e3db8253d21e5012d2724f?s=80&d=identicon", "profile": "https://code.castopod.org/Behel", - "contributions": ["code", "bug"] + "contributions": [ + "code", + "bug" + ] }, { "login": "cecillie", "name": "Cécile Ricordeau", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://www.cecillie.fr/", - "contributions": ["design"] + "contributions": [ + "design" + ] }, { "login": "PatrykMis", @@ -166,35 +171,48 @@ "name": "Marcin Lewandowski", "avatar_url": "https://secure.gravatar.com/avatar/eed8337939641eac5ad0b570bd6acf96?s=80&d=identicon", "profile": "https://code.castopod.org/mspanc", - "contributions": ["bug", "ideas"] + "contributions": [ + "bug", + "ideas" + ] }, { "login": "SJanik", "name": "Sebastian Janik", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://code.castopod.org/SJanik", - "contributions": ["code"] + "contributions": [ + "code" + ] }, { "login": "patryk", "name": "Patryk Karczmarczyk", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://code.castopod.org/patryk", - "contributions": ["code"] + "contributions": [ + "code" + ] }, { "login": "ddenis", "name": "denis d", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://code.castopod.org/ddenis", - "contributions": ["bug", "ideas"] + "contributions": [ + "bug", + "ideas" + ] }, { "login": "douglaskastle", "name": "Douglas Kastle", "avatar_url": "https://secure.gravatar.com/avatar/b7e652ba4b6bcd440afa069e7f7bc9e6?s=80&d=identicon", "profile": "https://code.castopod.org/douglaskastle", - "contributions": ["bug", "ideas"] + "contributions": [ + "bug", + "ideas" + ] }, { "login": "cExplorer", @@ -214,49 +232,66 @@ "name": "ImaCrea", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://code.castopod.org/imacrea", - "contributions": ["bug", "ideas"] + "contributions": [ + "bug", + "ideas" + ] }, { "login": "jonas", "name": "Jonas S", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://code.castopod.org/jonas", - "contributions": ["code"] + "contributions": [ + "code" + ] }, { "login": "yannL", "name": "LEFEBVRE Yann", "avatar_url": "https://secure.gravatar.com/avatar/9c46600ce566ec6d526370d8e104b1c8?s=80&d=identicon", "profile": "https://code.castopod.org/yannL", - "contributions": ["bug"] + "contributions": [ + "bug" + ] }, { "login": "spaetz", "name": "Sebastian Späth", "avatar_url": "https://secure.gravatar.com/avatar/278e1af65e82993efd0ba7bbbacf6435?s=80&d=identicon", "profile": "https://code.castopod.org/spaetz", - "contributions": ["bug", "ideas"] + "contributions": [ + "bug", + "ideas" + ] }, { "login": "rocky", "name": "rocky III", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://code.castopod.org/rocky", - "contributions": ["bug"] + "contributions": [ + "bug" + ] }, { "login": "Regenpfeifer", "name": "Hermann Josef Eckl", "avatar_url": "https://code.castopod.org/uploads/-/system/user/avatar/103/avatar.png", "profile": "https://code.castopod.org/Regenpfeifer", - "contributions": ["bug"] + "contributions": [ + "bug" + ] }, { "login": "cyrilledel", "name": "Delhaye Cyrille", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://code.castopod.org/cyrilledel", - "contributions": ["bug", "ideas"] + "contributions": [ + "bug", + "ideas" + ] }, { "login": "otetranome", @@ -295,6 +330,19 @@ } ] }, + { + "login": "3wen", + "name": "Ewen", + "avatar_url": "https://mastodon.fedi.bzh/system/accounts/avatars/000/000/002/original/6f387690a504ae46.jpg", + "profile": "https://mastodon.fedi.bzh/@ewen", + "contributions": [ + { + "type": "translation", + "url": "https://translate.castopod.org" + }, + "ideas" + ] + }, { "login": "forght", "name": "forght", @@ -322,7 +370,7 @@ { "login": "BoFFire", "name": "ButterflyOfFire", - "avatar_url": "https://static.mstdn.fr/static/accounts/avatars/000/065/901/original/5908e93ad5447f15.png", + "avatar_url": "https://static.mstdn.fr/static/accounts/avatars/000/065/901/original/e18d44b28edd0ada.png", "profile": "https://mstdn.fr/@ButterflyOfFire", "contributions": [ { @@ -444,12 +492,14 @@ "name": "Dimitri Regnier", "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", "profile": "https://dimitriregnier.net/", - "contributions": ["ideas"] + "contributions": [ + "ideas" + ] }, { "login": "irithys", "name": "irithys", - "avatar_url": "https://crowdin-static.downloads.crowdin.com/avatar/15405614/large/3086461c47cce0a0c031925e5f943412.png", + "avatar_url": "https://crowdin-static.downloads.crowdin.com/avatar/15405614/large/e46d7f8e9f7c05997827563c3a3cf942.jpeg", "profile": "https://im.irithys.com/@thy", "contributions": [ { @@ -471,104 +521,16 @@ ] }, { - "login": "basen1982", - "name": "Andreas Olsson", - "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", - "profile": "https://crowdin.com/profile/basen1982", + "login": "ghose", + "name": "ghose (XoseM)", + "avatar_url": "https://crowdin-static.downloads.crowdin.com/avatar/12617257/large/a201650da44fed28890b0e0d8477a663.jpg", + "profile": "https://crowdin.com/profile/xosem", "contributions": [ { "type": "translation", "url": "https://translate.castopod.org" } ] - }, - { - "login": "leonfrom", - "name": "leonfrom", - "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", - "profile": "https://crowdin.com/profile/leonfrom", - "contributions": [ - { - "type": "translation", - "url": "https://translate.castopod.org" - } - ] - }, - { - "login": "agentcobra57", - "name": "agentcobra", - "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", - "profile": "https://crowdin.com/profile/agentcobra57", - "contributions": [ - { - "type": "translation", - "url": "https://translate.castopod.org" - } - ] - }, - { - "login": "alephoto85", - "name": "Alessandro", - "avatar_url": "https://crowdin-static.downloads.crowdin.com/avatar/15094649/large/530391f54157af52ae33058ec15b0f99.jpg", - "profile": "https://crowdin.com/profile/alephoto85", - "contributions": [ - { - "type": "translation", - "url": "https://translate.castopod.org" - } - ] - }, - { - "login": "liimee", - "name": "liimee", - "avatar_url": "https://castopod.org/assets/images/castopod-avatar.jpg", - "profile": "https://crowdin.com/profile/liimee", - "contributions": [ - { - "type": "translation", - "url": "https://translate.castopod.org" - } - ] - }, - { - "login": "ahmedsabouni", - "name": "Ahmed Sabouni", - "avatar_url": "https://avatars.githubusercontent.com/u/74497842?v=4", - "profile": "https://github.com/ahmedsabouni", - "contributions": [ - { - "type": "translation", - "url": "https://translate.castopod.org" - } - ] - }, - { - "login": "KrzysztofDomanczyk", - "name": "KrzysztofDomanczyk", - "avatar_url": "https://avatars.githubusercontent.com/u/75178474?v=4", - "profile": "https://github.com/KrzysztofDomanczyk", - "contributions": ["code"] - }, - { - "login": "Dwev", - "name": "Guy Martin", - "avatar_url": "https://avatars.githubusercontent.com/u/46626050?v=4", - "profile": "https://github.com/Dwev", - "contributions": ["bug", "code"] - }, - { - "login": "prcutler", - "name": "Paul Cutler", - "avatar_url": "https://avatars.githubusercontent.com/u/67276?v=4", - "profile": "https://github.com/prcutler", - "contributions": ["doc", "question", "ideas"] - }, - { - "login": "nateritter", - "name": "Nate Ritter", - "avatar_url": "https://avatars.githubusercontent.com/u/198798?v=4", - "profile": "https://github.com/nateritter", - "contributions": ["code"] } ], "commitConvention": "none" diff --git a/.devcontainer/crontab b/.devcontainer/crontab deleted file mode 100644 index 8cef165a..00000000 --- a/.devcontainer/crontab +++ /dev/null @@ -1 +0,0 @@ -* * * * * /usr/local/bin/php /workspaces/castopod/spark tasks:run >> /dev/null 2>&1 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f1c12034..fbd4eb36 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,70 +1,46 @@ // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.117.1/containers/docker-existing-dockerfile { - "name": "castopod.local", - "dockerComposeFile": ["./docker-compose.yml"], + "name": "Castopod dev", + "dockerComposeFile": ["../docker-compose.yml", "./docker-compose.yml"], "service": "app", - "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", - "postCreateCommand": "composer install && pnpm install && pnpm run build:static && php spark migrate --all && php spark db:seed DevSeeder", - "postStartCommand": "git config --global --add safe.directory ${containerWorkspaceFolder} && crontab .devcontainer/crontab && cron && php spark serve --host 0.0.0.0 --port ${APP_PORT:-8080}", - "postAttachCommand": "crontab .devcontainer/crontab && service cron reload", + "workspaceFolder": "/castopod", + "postCreateCommand": "composer install && npm install && npm run build:static", + "postStartCommand": "crontab ./crontab && cron && php spark serve --host 0.0.0.0", + "postAttachCommand": "crontab ./crontab && service cron reload", "shutdownAction": "stopCompose", - "features": { - "ghcr.io/devcontainers/features/git:1": {}, - "ghcr.io/guiyomh/features/vim:0": {}, - "ghcr.io/NicoVIII/devcontainer-features/pnpm:2": {} - }, - "customizations": { - "vscode": { - "settings": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "[php]": { - "editor.defaultFormatter": "bmewburn.vscode-intelephense-client", - "editor.formatOnSave": false - }, - "css.validate": false, - "color-highlight.markerType": "dot-before", - "files.associations": { - "*.xml.dist": "xml", - "spark": "php", - "env": "dotenv", - ".rsync-filter": "diff" - }, - "json.schemas": [ - { - "fileMatch": [ - "plugins/**/manifest.json", - "tests/modules/Plugins/mocks/manifests/*.json", - "tests/modules/Plugins/mocks/plugins/**/manifest.json" - ], - "url": "/workspaces/castopod/modules/Plugins/Manifest/manifest.schema.json" - } - ] - }, - "extensions": [ - "astro-build.astro-vscode", - "bmewburn.vscode-intelephense-client", - "bradlc.vscode-tailwindcss", - "breezelin.phpstan", - "DavidAnson.vscode-markdownlint", - "dbaeumer.vscode-eslint", - "eamodio.gitlens", - "esbenp.prettier-vscode", - "heybourn.headwind", - "jamesbirtles.svelte-vscode", - "kasik96.latte", - "mikestead.dotenv", - "naumovs.color-highlight", - "pflannery.vscode-versionlens", - "runem.lit-plugin", - "streetsidesoftware.code-spell-checker", - "stylelint.vscode-stylelint", - "unifiedjs.vscode-mdx", - "wayou.vscode-todo-highlight", - "yzhang.markdown-all-in-one", - "42Crunch.vscode-openapi" - ] + "settings": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[php]": { + "editor.defaultFormatter": "bmewburn.vscode-intelephense-client", + "editor.formatOnSave": false + }, + "css.validate": false, + "color-highlight.markerType": "dot-before", + "files.associations": { + "*.xml.dist": "xml", + "spark": "php", + "env": "dotenv", + ".rsync-filter": "diff" } - } + }, + "extensions": [ + "bmewburn.vscode-intelephense-client", + "bradlc.vscode-tailwindcss", + "breezelin.phpstan", + "dbaeumer.vscode-eslint", + "eamodio.gitlens", + "esbenp.prettier-vscode", + "heybourn.headwind", + "jamesbirtles.svelte-vscode", + "kasik96.latte", + "mikestead.dotenv", + "naumovs.color-highlight", + "pflannery.vscode-versionlens", + "runem.lit-plugin", + "streetsidesoftware.code-spell-checker", + "stylelint.vscode-stylelint", + "wayou.vscode-todo-highlight" + ] } diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 665b78e9..ec3827cf 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,76 +1,10 @@ +version: "3" services: app: - build: - context: . - dockerfile: Dockerfile volumes: - - ../..:/workspaces:cached - - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini - environment: - APP_PORT: ${APP_PORT:-8080} # used in devcontainer.json file - VITE_PORT: ${VITE_PORT:-5173} # used in ../vite.config.js file - CI_ENVIRONMENT: development - vite_environment: development - app_forceGlobalSecureRequests: 0 #false - app_baseURL: http://localhost:${APP_PORT:-8080}/ - media_baseURL: http://localhost:${APP_PORT:-8080}/ - admin_gateway: cp-admin - auth_gateway: cp-auth - analytics_salt: dev_analytics_salt - database_default_hostname: mariadb - database_default_database: castopod - database_default_username: castopod - database_default_password: castopod - database_default_DBPrefix: cp_ - restapi_enabled: 1 #true - email_fromEmail: hello@castopod.local - email_SMTPCrypto: "" - email_SMTPHost: mailpit - email_SMTPUser: castopod - email_SMTPPass: castopod - email_SMTPPort: ${MAILPIT_SMTP_PORT:-1025} - depends_on: - - mariadb + # Mounts the project folder to '/workspace'. While this file is in .devcontainer, + # mounts are relative to the first file in the list, which is a level up. + - .:/castopod:cached - mariadb: - image: mariadb:10.2 - volumes: - - ./initdb:/docker-entrypoint-initdb.d - - mariadb:/var/lib/mysql - environment: - MYSQL_ROOT_PASSWORD: root - MYSQL_DATABASE: castopod - MYSQL_USER: castopod - MYSQL_PASSWORD: castopod - - phpmyadmin: - image: phpmyadmin/phpmyadmin:latest - environment: - PMA_HOST: mariadb - PMA_PORT: 3306 - UPLOAD_LIMIT: 300M - ports: - - 8888:80 - volumes: - - phpmyadmin:/sessions - depends_on: - - mariadb - - mailpit: - image: axllent/mailpit - restart: always - volumes: - - mailpit:/data - ports: - - ${MAILPIT_WEBUI_PORT:-8025}:8025 - - ${MAILPIT_SMTP_PORT:-1025}:1025 - environment: - MP_MAX_MESSAGES: 5000 - MP_DATA_FILE: /data/mailpit.db - MP_SMTP_AUTH_ACCEPT_ANY: 1 - MP_SMTP_AUTH_ALLOW_INSECURE: 1 - -volumes: - mariadb: - phpmyadmin: - mailpit: + # Overrides default command so things don't shut down after the process ends. + command: /bin/sh -c "while sleep 1000; do :; done" diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 1b773dc8..00000000 --- a/.dockerignore +++ /dev/null @@ -1,68 +0,0 @@ -.env - -.git/ -node_modules/ -vendor/ -build/ -docs/ -scripts/ -tests/ - -#------------------------- -# Temporary Files -#------------------------- -writable/cache/* -!writable/cache/index.html - -writable/logs/* -!writable/logs/index.html - -writable/session/* -!writable/session/index.html - -writable/temp/* -!writable/temp/index.html - -writable/uploads/* -!writable/uploads/index.html - -writable/debugbar/* -!writable/debugbar/index.html - -# public folder -public/* -!public/media -!public/.htaccess -!public/favicon.ico -!public/icon* -!public/castopod-banner* -!public/castopod-avatar* -!public/index.php -!public/robots.txt -!public/.well-known -!public/.well-known/GDPR.yml - -public/assets/* -!public/assets/index.html - -# public media folder -!public/media/podcasts -!public/media/persons -!public/media/site - -public/media/podcasts/* -!public/media/podcasts/index.html - -public/media/persons/* -!public/media/persons/index.html - -public/media/site/* -!public/media/site/index.html - -# Generated files -modules/Admin/Language/*/PersonsTaxonomy.php - -# Castopod bundle & packages -castopod/ -castopod-*.zip -castopod-*.tar.gz diff --git a/.env.example b/.env.example index 40e4c336..9a486a1f 100644 --- a/.env.example +++ b/.env.example @@ -14,10 +14,9 @@ # Instance configuration #-------------------------------------------------------------------- app.baseURL="https://YOUR_DOMAIN_NAME/" -media.baseURL="https://YOUR_MEDIA_DOMAIN_NAME/" +app.mediaBaseURL="https://YOUR_MEDIA_DOMAIN_NAME/" admin.gateway="cp-admin" auth.gateway="cp-auth" -analytics.salt="RANDOM_STRING_OF_64_CHARACTERS" #-------------------------------------------------------------------- # Database configuration @@ -51,20 +50,9 @@ cache.handler="file" # cache.redis.port=6379 # cache.redis.database=0 -#-------------------------------------------------------------------- -# S3 configuration -#-------------------------------------------------------------------- -# media.fileManager="s3" -# media.s3.endpoint="your_s3_host" -# media.s3.key="your_s3_key" -# media.s3.secret="your_s3_secret" -# media.s3.region="your_s3_region" - #-------------------------------------------------------------------- # REST API configuration #-------------------------------------------------------------------- # restapi.enabled=true -# restapi.basicAuthUsername=castopod -# restapi.basicAuthPassword=password -# restapi.basicAuth=true + diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..cff4e85e --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "env": { + "browser": true, + "es2020": true + }, + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "parserOptions": { + "ecmaVersion": 11, + "sourceType": "module" + }, + "rules": {} +} diff --git a/.gitignore b/.gitignore index b7ea048c..35dd7290 100644 --- a/.gitignore +++ b/.gitignore @@ -67,7 +67,6 @@ writable/uploads/* !writable/uploads/index.html writable/debugbar/* -!writable/debugbar/index.html php_errors.log @@ -86,7 +85,6 @@ tests/coverage* # Don't save phpunit under version control. phpunit -.phpunit.cache #------------------------- # Composer @@ -107,15 +105,15 @@ _modules/* .idea/ *.iml -# NetBeans -/nbproject/ -/build/ -/nbbuild/ -/dist/ -/nbdist/ -/nbactions.xml -/nb-configuration.xml -/.nb-gradle/ +# Netbeans +nbproject/ +build/ +nbbuild/ +dist/ +nbdist/ +nbactions.xml +nb-configuration.xml +.nb-gradle/ # Sublime Text *.tmlanguage.cache @@ -128,36 +126,30 @@ _modules/* # Visual Studio Code .vscode/ -.history/ -tmp/ /results/ /phpunit*.xml +/.phpunit.*.cache -# js package manager +# npm yarn.lock node_modules -.pnpm-store # JS .cache # public folder public/* +public/media/site !public/media !public/.htaccess !public/favicon.ico !public/icon* -!public/castopod-banner* -!public/castopod-avatar* !public/index.php !public/robots.txt !public/.well-known !public/.well-known/GDPR.yml -public/assets/* -!public/assets/index.html - # public media folder !public/media/podcasts !public/media/persons @@ -175,13 +167,15 @@ public/media/site/* # Generated files modules/Admin/Language/*/PersonsTaxonomy.php +#------------------------- +# Docker volumes +#------------------------- + +mariadb +phpmyadmin +sessions + # Castopod bundle & packages castopod/ castopod-*.zip castopod-*.tar.gz - -# Plugins -plugins/* -!plugins/.gitkeep -writable/plugins.json -writable/plugins-lock.json diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 32076043..d17fbda3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,52 +1,32 @@ -image: code.castopod.org:5050/adaures/castopod:ci-php8.5 +image: code.castopod.org:5050/adaures/castopod:latest stages: - prepare - quality - bundle - release - - deploy - build + - deploy php-dependencies: stage: prepare script: # Install all php dependencies - composer install --prefer-dist --no-ansi --no-interaction --no-progress --ignore-platform-reqs - cache: - key: - files: - - composer.lock - paths: - - .composer-cache artifacts: - expire_in: 30 mins paths: - vendor/ - rules: - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ - when: never - - when: on_success + expire_in: 30 mins js-dependencies: stage: prepare script: - # Install all js dependencies - - pnpm install - cache: - key: - files: - - pnpm-lock.yaml - paths: - - .pnpm-store + # Install all npm dependencies + - npm ci artifacts: - expire_in: 30 mins paths: - node_modules/ - rules: - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ - when: never - - when: on_success + expire_in: 30 mins lint-commit-msg: stage: quality @@ -56,10 +36,11 @@ lint-commit-msg: - ./scripts/lint-commit-msg.sh dependencies: - js-dependencies - rules: - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ - when: never - - if: $CI_COMMIT_BRANCH =~ /^(develop|main|alpha|beta|next)$/ + only: + - develop + - main + - beta + - alpha lint-php: stage: quality @@ -72,46 +53,37 @@ lint-php: - vendor/bin/rector process --dry-run --ansi dependencies: - php-dependencies - rules: - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ - when: never - - when: on_success lint-js: stage: quality script: - - pnpm run format - - pnpm run typecheck - - pnpm run lint - - pnpm run lint:css + - npm run prettier + - npm run typecheck + - npm run lint + - npm run lint:css dependencies: - js-dependencies - rules: - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ - when: never - - when: on_success tests: stage: quality services: - - mariadb:10.11 + - mariadb variables: MYSQL_ROOT_PASSWORD: "R00Tp4ssW0RD" MYSQL_DATABASE: "test" MYSQL_USER: "castopod" MYSQL_PASSWORD: "castopod" + script: - - echo "SHOW DATABASES;" | mariadb --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mariadb "$MYSQL_DATABASE" --skip_ssl + - apt-get update && apt-get install -y mariadb-client libmariadb-dev + + - echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mariadb "$MYSQL_DATABASE" # run phpunit without code coverage # TODO: add code coverage - vendor/bin/phpunit --no-coverage dependencies: - php-dependencies - rules: - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ - when: never - - when: on_success bundle: stage: bundle @@ -132,12 +104,13 @@ bundle: name: "castopod-${CI_COMMIT_REF_SLUG}_${CI_COMMIT_SHORT_SHA}" paths: - castopod - rules: - - if: $CI_PROJECT_NAMESPACE != "adaures" - when: never - - if: $CI_COMMIT_BRANCH =~ /^(main|alpha|beta|next)$/ || $CI_COMMIT_TAG - when: never - - when: on_success + only: + variables: + - $CI_PROJECT_NAMESPACE == "adaures" + except: + - main + - beta + - alpha release: stage: release @@ -154,45 +127,48 @@ release: - chmod +x ./scripts/package.sh # run semantic-release script (configured in `.releaserc.json` file) - - pnpm run release + - npm run release dependencies: - php-dependencies - js-dependencies artifacts: paths: - castopod - rules: - - if: $CI_PROJECT_NAMESPACE != "adaures" - when: never - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ - when: never - - if: $CI_COMMIT_BRANCH =~ /^(main|alpha|beta|next)$/ + - CP_VERSION.env + only: + - main + - beta + - alpha website: stage: deploy trigger: adaures/castopod.org - rules: - - if: $CI_PROJECT_NAMESPACE != "adaures" - when: never - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ && $CI_COMMIT_TAG + only: + - main + - beta + - alpha documentation: stage: deploy trigger: include: docs/.gitlab-ci.yml strategy: depend - rules: - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ - when: never - - when: on_success + only: + changes: + - docs/**/* docker: stage: build trigger: include: docker/production/.gitlab-ci.yml strategy: depend - rules: - - if: $CI_PROJECT_NAMESPACE != "adaures" - when: never - - if: $CI_COMMIT_BRANCH == "develop" - - if: $CI_COMMIT_MESSAGE =~ /^chore\(release\):/ && $CI_COMMIT_TAG + variables: + PARENT_PIPELINE_ID: $CI_PIPELINE_ID + only: + refs: + - develop + - main + - beta + - alpha + variables: + - $CI_PROJECT_NAMESPACE == "adaures" diff --git a/.gitlab/issue_templates/bug.md b/.gitlab/issue_templates/bug.md index c6041a61..7fec749a 100644 --- a/.gitlab/issue_templates/bug.md +++ b/.gitlab/issue_templates/bug.md @@ -6,7 +6,7 @@ 1. [First step] 2. [Second step] -3. [and so on…] +3. [and so on...] ### Expected behavior @@ -27,7 +27,7 @@ logs, and code as it's very hard to read otherwise. - OS: [e.g. Ubuntu server] - Browser: [e.g. chrome, safari] - Web server: [eg. Apache] -- [any other relevant context…] +- [any other relevant context...] ### Possible fixes diff --git a/.gitlab/issue_templates/feature-request.md b/.gitlab/issue_templates/feature-request.md index 0886d392..644a8fd4 100644 --- a/.gitlab/issue_templates/feature-request.md +++ b/.gitlab/issue_templates/feature-request.md @@ -1,7 +1,7 @@ ### Is your feature request related to a problem? Please describe A clear and concise description of what the problem is. Ex. I'm always -frustrated when […] +frustrated when [...] ### Describe the solution you'd like diff --git a/.husky/commit-msg b/.husky/commit-msg index 062719b1..cdb7c8da 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1 +1,4 @@ -pnpm exec commitlint --verbose --edit "$1" +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no-install commitlint --verbose --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit index 12ee980f..39c89b16 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,8 +1,11 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + # CaptainHook 5.10.0 INTERACTIVE="--no-interaction" vendor/bin/captainhook $INTERACTIVE --configuration=captainhook.json --bootstrap=vendor/autoload.php hook:pre-commit "$@" <&0 -pnpm run typecheck -pnpm exec lint-staged +npm run typecheck +npx lint-staged diff --git a/.husky/pre-push b/.husky/pre-push index a3617f04..9b4d0f80 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,3 +1,6 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + # CaptainHook 5.10.0 INTERACTIVE="--no-interaction" diff --git a/.prettierrc.json b/.prettierrc.json index cae76d94..d567a64c 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -2,7 +2,7 @@ "trailingComma": "es5", "overrides": [ { - "files": ["*.md", "*.mdx"], + "files": "*.md", "options": { "proseWrap": "always" } diff --git a/.releaserc.json b/.releaserc.json index 7a8b6584..a9deb773 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -8,79 +8,16 @@ { "name": "beta", "prerelease": true - }, - { - "name": "next", - "prerelease": true } ], "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "type": "docs", - "scope": "README", - "release": "patch" - }, - { - "type": "refactor", - "scope": "core-*", - "release": "minor" - }, - { - "type": "refactor", - "release": "patch" - } - ], - "parserOpts": { - "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"] - } - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "parserOpts": { - "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"] - }, - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Internal", - "hidden": false - }, - { - "type": "refactor", - "section": "Internal", - "hidden": false - }, - { - "type": "perf", - "section": "Internal", - "hidden": false - } - ] - } - } - ], + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", "@semantic-release/changelog", [ "@semantic-release/exec", { - "prepareCmd": "./scripts/bundle.sh ${nextRelease.version} && ./scripts/package.sh ${nextRelease.version} && pnpm exec prettier --write CHANGELOG.md" + "prepareCmd": "./scripts/bundle.sh ${nextRelease.version} && ./scripts/package.sh ${nextRelease.version} && npx prettier --write CHANGELOG.md" } ], "@semantic-release/npm", @@ -93,8 +30,7 @@ "package.json", "package-lock.json", "CHANGELOG.md" - ], - "message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}" + ] } ], [ diff --git a/.rsync-filter b/.rsync-filter index 0fcb79ec..674896fa 100644 --- a/.rsync-filter +++ b/.rsync-filter @@ -1,10 +1,8 @@ # rsync filter rules to copy required files for Castopod's bundle -+ resources/icons/*** -+ resources/ +- app/Resources/ + app/*** + modules/*** -+ plugins/*** + public/*** + themes/*** + vendor/*** @@ -13,5 +11,4 @@ + LICENSE.md + README.md + spark -+ php-icons.php - ** diff --git a/.stylelintrc.json b/.stylelintrc.json index 8ea025c1..2cd0132c 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,5 +1,5 @@ { - "extends": "stylelint-config-standard", + "extends": "stylelint-config-recommended", "rules": { "at-rule-no-unknown": [ true, @@ -10,24 +10,10 @@ "responsive", "variants", "screen", - "layer", - "config" + "layer" ] } ], - "at-rule-no-deprecated": [ - true, - { - "ignoreAtRules": ["apply"] - } - ], - "function-no-unknown": [ - true, - { - "ignoreFunctions": ["theme"] - } - ], - "no-descending-specificity": null, - "selector-class-pattern": null + "no-descending-specificity": null } } diff --git a/.svgo.icons.cjs b/.svgo.icons.js similarity index 100% rename from .svgo.icons.cjs rename to .svgo.icons.js diff --git a/.svgo.cjs b/.svgo.js similarity index 100% rename from .svgo.cjs rename to .svgo.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 29f4a170..b6d4cebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,1860 +1,3 @@ -## [2.0.0-next.3](https://code.castopod.org/adaures/castopod/compare/v2.0.0-next.2...v2.0.0-next.3) (2024-12-30) - -### Features - -- **api:** add Episode create and publish endpoints - ([a90cdfd](https://code.castopod.org/adaures/castopod/commit/a90cdfdcdbde7a8fb520c6815d7b757947aea055)) -- **image:** add image size's width and height - ([f50098e](https://code.castopod.org/adaures/castopod/commit/f50098ec8926c8ae40718f5f128b6de7fe721b46)) -- **plugins:** add defaultValue for all field types - ([d3a98db](https://code.castopod.org/adaures/castopod/commit/d3a98db6d0112b5f59daddd2708c09dd2e595332)) -- **plugins:** add group field type + multiple option to render field arrays - ([11ccd0e](https://code.castopod.org/adaures/castopod/commit/11ccd0ebe71d476d8c0dbfe28edcf01f7f362b83)) -- **plugins:** add html field type + CodeEditor component + rework html head - generation - ([8cf9c6d](https://code.castopod.org/adaures/castopod/commit/8cf9c6dc833aedcccbc4cdb309b111f84d97d629)) -- **rss:** add option for 301 redirect to new feed url - ([8402cc2](https://code.castopod.org/adaures/castopod/commit/8402cc29d2d0c61b014a7e03e5ccce7d3c11782a)) - -### Bug Fixes - -- add downloads_count to episodes table, computed every hour - ([f981937](https://code.castopod.org/adaures/castopod/commit/f9819376455c371eb5bd3c84ad938698335a3d67)) -- allow passing json to app.proxyIPs config to set it - ([cbf739e](https://code.castopod.org/adaures/castopod/commit/cbf739e95cc0ad6e83a21353b8f4678e68d74f63)) -- **api:** cast integers when creating episode - ([775b302](https://code.castopod.org/adaures/castopod/commit/775b302f7c886e30e133c8a8c68764301b6c663b)) -- **docker-image:** clear cache to account for new assets and data structure - changes - ([63c763f](https://code.castopod.org/adaures/castopod/commit/63c763f941195b3758c4b91acd8c350a5e7bb9c2)), - closes [#510](https://code.castopod.org/adaures/castopod/issues/510) -- edit remap functions to get episode in episode admin controllers - ([9f74cca](https://code.castopod.org/adaures/castopod/commit/9f74cca342fedd896977efd2e89d0143959f3c4f)) -- **episode:** do not change slug when editing episode title - ([a83afb0](https://code.castopod.org/adaures/castopod/commit/a83afb0004511db80337806577fbc36f8d777116)), - closes [#513](https://code.castopod.org/adaures/castopod/issues/513) -- **fediverse:** add "processing" and "failed" statuses to better manage - broadcast load - ([1d7583d](https://code.castopod.org/adaures/castopod/commit/1d7583d738219574ae3d45d294dc94e7e406472b)), - closes [#511](https://code.castopod.org/adaures/castopod/issues/511) -- **icons:** set correct names for lock and lock-unlock icons in premium banner - ([37ee6d3](https://code.castopod.org/adaures/castopod/commit/37ee6d35b4bb66ce23dc271fb846200d1be0e7f6)) -- **plugins:** clear cache after activating or deactivating plugin - ([08c7df2](https://code.castopod.org/adaures/castopod/commit/08c7df2a5d5be340490c78deeef823167eb1b2fc)) -- **plugins:** delete relevant cache when submitting settings - ([00bd4c0](https://code.castopod.org/adaures/castopod/commit/00bd4c02ee23b181d74e7731626bfec3b1ff4916)) -- **podcast-model:** always query podcast from database when clearing cache - ([d30c49c](https://code.castopod.org/adaures/castopod/commit/d30c49cdff380c15db4f1851631a255a5baffcbe)) -- **premium-podcasts:** update query to validate subscription - ([2b1bbf3](https://code.castopod.org/adaures/castopod/commit/2b1bbf34303ead927f433b5c7d5d888ca3799954)) -- **preview:** delete episode preview cache after editing episode - ([732d429](https://code.castopod.org/adaures/castopod/commit/732d42923d0d7a66ff1ebd5841458e4205060560)), - closes [#514](https://code.castopod.org/adaures/castopod/issues/514) -- **release:** add conventional-changelog-conventionalcommits for CHANGELOG - generation - ([6934c8a](https://code.castopod.org/adaures/castopod/commit/6934c8aa8f0b7f9eea7c3f6f4089c56b2391d9a6)) -- **rss:** add subscription id to cache name to prevent premium feeds from - overlapping - ([74f9325](https://code.castopod.org/adaures/castopod/commit/74f9325946d03a0d4efce57045e41cc9454ff97c)) -- set user as www-data when running cron jobs in docker's supervisord config - ([65d74f1](https://code.castopod.org/adaures/castopod/commit/65d74f14e612be3757c9304518eee112705f5ff9)) -- typo in EpisodeController remap function to get episode - ([f288a75](https://code.castopod.org/adaures/castopod/commit/f288a750f580ab19b04a170cc76bf8769084e19d)) -- update select and multi-select options to value/label arrays - ([63f93f5](https://code.castopod.org/adaures/castopod/commit/63f93f585bec4a11022cc8c75deb34968cba2348)) - -### Internal - -- **plugins:** create Field objects per field type in settings forms + handle - rendering in class - ([34be5bc](https://code.castopod.org/adaures/castopod/commit/34be5bccabb7531afdcc6ebaf1dd39e4dfbe0677)) -- remove fields from podcast and episode entities to be replaced with plugins - ([b869acb](https://code.castopod.org/adaures/castopod/commit/b869acb3a988a3616d883a41c25d9c8409bd5518)) -- rename controller methods for views and actions to be more consistent - ([85704bf](https://code.castopod.org/adaures/castopod/commit/85704bfbe03fe5e38ff5e76a0e1cf0e5f1275f57)) -- update CodeIgniter to v4.5.6 - ([f295e9a](https://code.castopod.org/adaures/castopod/commit/f295e9aa4ca3129df24a22779f7c19bba7fac370)) -- update codigniter-icons to v1.0.1 - ([fa6967e](https://code.castopod.org/adaures/castopod/commit/fa6967e65cef1705b19cbb205132c4c751507d53)) -- update js dependencies to latest - ([70c9797](https://code.castopod.org/adaures/castopod/commit/70c97971fcf5bbeee826578057ae0e3afbbbd8a8)) - -# [2.0.0-next.2](https://code.castopod.org/adaures/castopod/compare/v2.0.0-next.1...v2.0.0-next.2) (2024-07-08) - -### Bug Fixes - -- **audio-player:** set player icons to default instead of missing Castopod's - ([0ba0a25](https://code.castopod.org/adaures/castopod/commit/0ba0a25b11bd67aeeb47a8179b72152dfd4a36da)) -- broken icon call in frontend default pages template - ([3228362](https://code.castopod.org/adaures/castopod/commit/322836254e86be7878e21438177ee8f73f03a2fa)) -- **manifest:** set repository url as required in docstring typings - ([a8c81b3](https://code.castopod.org/adaures/castopod/commit/a8c81b3fa19a28dbd608027c231dcac31eafb38f)) -- set correct icons parameters in map and funding links views - ([5d35524](https://code.castopod.org/adaures/castopod/commit/5d355248753be24e3cf324144ff076f2fc23be88)), - closes [#500](https://code.castopod.org/adaures/castopod/issues/500) - -### Features - -- **plugins:** add `minCastopodVersion` to denote incompatibility with previous - Castopod versions - ([fc9ea75](https://code.castopod.org/adaures/castopod/commit/fc9ea7597e454e5c7c7af043d29af7bbe119e342)) -- **plugins:** load and display LICENSE.md file if found in plugin's directory - ([fee7905](https://code.castopod.org/adaures/castopod/commit/fee7905935a9adf963b4485b437fe4d972c14b5f)) - -# [2.0.0-next.1](https://code.castopod.org/adaures/castopod/compare/v1.11.0...v2.0.0-next.1) (6/19/2024) - -### Bug Fixes - -- add missing php-icons config file to bundle - ([56612f0](https://code.castopod.org/adaures/castopod/commit/56612f0c762aa2d98e3c8c77fba88ffdf6f46a44)) -- **docs:** add base to og image using env variable - ([fe67659](https://code.castopod.org/adaures/castopod/commit/fe676590f23a33bdbe8905d234760923c029e350)) -- **import:** rewrite download_file helper to output curl response directly to - file - ([eb7ad2f](https://code.castopod.org/adaures/castopod/commit/eb7ad2f7e1c0137f222f47e47062887de42c4824)) -- include app/Resources/icons folder to bundle - ([3fd5efc](https://code.castopod.org/adaures/castopod/commit/3fd5efc7956977acc19e53182f25b12813964a7d)) -- **platforms:** add platforms service + reduce memory consumption when - rendering platform cards - ([fe73e9f](https://code.castopod.org/adaures/castopod/commit/fe73e9fae9ea5d5ce946680aec194308bb2e620c)) -- set owner email visibility when editing podcast - ([fc4f982](https://code.castopod.org/adaures/castopod/commit/fc4f9825568cd4384c5b3cfe972accd146548807)), - closes [#473](https://code.castopod.org/adaures/castopod/issues/473) - -### Build System - -- release next major version as prerelease - ([8275226](https://code.castopod.org/adaures/castopod/commit/827522643e9f8a5ea9be05b4847dc637f0f43a13)) - -### Features - -- add Plugins module with base files for plugins architecture - ([7253e13](https://code.castopod.org/adaures/castopod/commit/7253e13ac2118f6f165f54ea0cbcd63d51ab9205)) -- **plugins:** abstract settings form for general, podcast and episode types - ([b62b483](https://code.castopod.org/adaures/castopod/commit/b62b483ad9ff114a22a9ee52e1a1a2c9fa444d42)) -- **plugins:** activate / deactivate plugin using settings table - ([27d2a1b](https://code.castopod.org/adaures/castopod/commit/27d2a1b0ffba9454dd54cbb4251a2d179b09762a)) -- **plugins:** add aside with plugin metadata next to plugin's readme - ([dfb7888](https://code.castopod.org/adaures/castopod/commit/dfb7888aeb689b4066abc37084e08cd7f1d0f15d)) -- **plugins:** add before channel/item hooks to allow podcast/episode data edit - when generating rss - ([80d2c48](https://code.castopod.org/adaures/castopod/commit/80d2c48ee265cb32ed0d710c488292fcbc120044)) -- **plugins:** add json schema definition for plugin manifest - ([b5eddf3](https://code.castopod.org/adaures/castopod/commit/b5eddf351f6f6fa1c299fbac31cbd056ef232330)) -- **plugins:** add methods to easily retrieve general, podcast and episode - settings in hooks methods - ([3a900bb](https://code.castopod.org/adaures/castopod/commit/3a900bbab68b819cedf8943540d2ee0aeb6e8539)) -- **plugins:** add new field types + validate & cast user data before storing - settings - ([6f833fc](https://code.castopod.org/adaures/castopod/commit/6f833fc76a3aa6c6b87c27ad18a2fb90e537e21e)) -- **plugins:** add options to manifest for building forms and storing plugin - settings - ([3d8aedf](https://code.castopod.org/adaures/castopod/commit/3d8aedf9c34e6927b6d3b11445d5f0e669b347d7)) -- **plugins:** add settings page for podcast and episode if defined in the - plugin's manifest - ([89ac92f](https://code.castopod.org/adaures/castopod/commit/89ac92fb412a04231ce52fd6480c9ab893b19ef5)) -- **plugins:** add siteHead hook to add custom meta tags to public pages - ([e80a33b](https://code.castopod.org/adaures/castopod/commit/e80a33bf2ad4fe1b47037add7470a6c2770f4036)) -- **plugins:** display errors when plugin is invalid instead of crashing - ([8ec7909](https://code.castopod.org/adaures/castopod/commit/8ec79097bbdbcbce622518ef61c068f20e0ef74e)) -- **plugins:** handle empty states and long strings in UI - ([45ac2a4](https://code.castopod.org/adaures/castopod/commit/45ac2a4be96532b9456e6af1d26ba4ada3649303)) -- **plugins:** load and validate plugin manifest.json - ([1510e36](https://code.castopod.org/adaures/castopod/commit/1510e36c0acd2b254622ec230acd1d2461ee9bf3)) -- **plugins:** load plugins using file locator service - ([587938d](https://code.castopod.org/adaures/castopod/commit/587938d2bf307b823af143586b9ec9e9b44e8dc1)) -- **plugins:** load README.md file to view plugin's instructions in UI - ([e6bfdfc](https://code.castopod.org/adaures/castopod/commit/e6bfdfc3902705285701c13c8067fe0f538425c6)) -- **plugins:** register plugins using Plugin.php file instead of namespace + - simplify i18n structure - ([2035c39](https://code.castopod.org/adaures/castopod/commit/2035c39fd138a1fd408516bd1972ab6a02544c10)) -- **plugins:** uninstall plugins via CLI and admin UI - ([9a80de4](https://code.castopod.org/adaures/castopod/commit/9a80de40686bbf4288da21cc2a6dde8036580e47)) -- set owner email to hidden by default in podcast create form - ([7a6d9df](https://code.castopod.org/adaures/castopod/commit/7a6d9df6db8a6184b8250ced0475f3e741dde7f4)) -- support podcast:txt tag with verify use case - ([57e459e](https://code.castopod.org/adaures/castopod/commit/57e459e187ed048430f4137172e22396cd02bf81)), - closes [#468](https://code.castopod.org/adaures/castopod/issues/468) - -### BREAKING CHANGES - -- next major release including plugins architecture - -# [1.11.0](https://code.castopod.org/adaures/castopod/compare/v1.10.5...v1.11.0) (4/17/2024) - -### Bug Fixes - -- **premium:** set itunes:block on premium feeds to prevent indexing - ([88851b0](https://code.castopod.org/adaures/castopod/commit/88851b022663d575a816f0e2f33f0353767dd52d)) -- **rss:** generate podcast guid if empty - ([a5aef2a](https://code.castopod.org/adaures/castopod/commit/a5aef2a63e464632f3941649d455672835989e6c)), - closes [#450](https://code.castopod.org/adaures/castopod/issues/450) - -### Features - -- add trailer tags to rss if trailer episodes are present - ([80fdd9c](https://code.castopod.org/adaures/castopod/commit/80fdd9cfb4a95feac6ed0000435a013fc83e6892)) -- add transcript display to episode page - ([4d141fc](https://code.castopod.org/adaures/castopod/commit/4d141fceae56fa9e666b42c32a830ff9c68989db)), - closes [#411](https://code.castopod.org/adaures/castopod/issues/411) -- **platforms:** add telegram to socials - ([004f804](https://code.castopod.org/adaures/castopod/commit/004f804045cd8e884361bb4318109fbdd7afc9a8)) -- **platforms:** add truefans.fm and episodes.fm - ([d046ecc](https://code.castopod.org/adaures/castopod/commit/d046ecc52f6ccd41d09f6de48e00d2c61d25d7f0)), - closes [#458](https://code.castopod.org/adaures/castopod/issues/458) - [#459](https://code.castopod.org/adaures/castopod/issues/459) - -## [1.10.5](https://code.castopod.org/adaures/castopod/compare/v1.10.4...v1.10.5) (3/12/2024) - -### Bug Fixes - -- **file-uploads:** validate chapters json content + remove permit_empty rule to - uploaded files - ([6289c42](https://code.castopod.org/adaures/castopod/commit/6289c42b1189f074c7e4e4cd9fbfd73bf26625c9)), - closes [#445](https://code.castopod.org/adaures/castopod/issues/445) - -## [1.10.4](https://code.castopod.org/adaures/castopod/compare/v1.10.3...v1.10.4) (2/26/2024) - -### Bug Fixes - -- display chapters in episode preview page - ([797516a](https://code.castopod.org/adaures/castopod/commit/797516a2ec7d88704412a5cca50421e8eef38eec)), - closes [#445](https://code.castopod.org/adaures/castopod/issues/445) - -## [1.10.3](https://code.castopod.org/adaures/castopod/compare/v1.10.2...v1.10.3) (2/21/2024) - -### Bug Fixes - -- **chapters:** use episode cover when chapter img is an empty string - ([a343de4](https://code.castopod.org/adaures/castopod/commit/a343de4cf6ba38561b8fe675fa9c38d9f0ecfec7)), - closes [#444](https://code.castopod.org/adaures/castopod/issues/444) -- **import:** set episodes as premium if podcast is set as premium by default - ([dfd66be](https://code.castopod.org/adaures/castopod/commit/dfd66beebfcca1670b0a9d389e8e3f8d2d08d2f2)) - -## [1.10.2](https://code.castopod.org/adaures/castopod/compare/v1.10.1...v1.10.2) (2/20/2024) - -### Bug Fixes - -- **podcast-import:** move closing parenthasis when checking for owner name and - email existence - ([cec7815](https://code.castopod.org/adaures/castopod/commit/cec78155f94a222edcf7964c0a2f3a3e0f46a98d)) - -## [1.10.1](https://code.castopod.org/adaures/castopod/compare/v1.10.0...v1.10.1) (2/20/2024) - -### Bug Fixes - -- **fediverse:** use config name to get Fediverse config properties instead of - hardcoded class string - ([5fd0980](https://code.castopod.org/adaures/castopod/commit/5fd0980ff7101d45051a2daa3f635694f85609d7)) - -# [1.10.0](https://code.castopod.org/adaures/castopod/compare/v1.9.0...v1.10.0) (2/19/2024) - -### Bug Fixes - -- **op3:** move op3 prefix to enclosure url instead of audio proxy - ([d580369](https://code.castopod.org/adaures/castopod/commit/d5803692357952d82d54efd8d3aa71de3a1c9571)) -- **podcast-import:** rollback transaction before exception is thrown - ([419bb04](https://code.castopod.org/adaures/castopod/commit/419bb04716088586b87b2c8f24a954ca8cfd6c76)), - closes [#429](https://code.castopod.org/adaures/castopod/issues/429) - [#319](https://code.castopod.org/adaures/castopod/issues/319) - [#443](https://code.castopod.org/adaures/castopod/issues/443) - [#438](https://code.castopod.org/adaures/castopod/issues/438) - -### Features - -- add podcast:season and podcast:episode tags to rss feed - ([98c6658](https://code.castopod.org/adaures/castopod/commit/98c6658840eedd55bd6d8042f8a69c342b87cd71)) -- add support for podcasting 2.0 "medium" tag with podcast, music and audiobook - ([630e788](https://code.castopod.org/adaures/castopod/commit/630e788f0e1ddfe5de229bd415a8e15361efa746)), - closes [#439](https://code.castopod.org/adaures/castopod/issues/439) -- display chapters in episode's public page - ([87cc437](https://code.castopod.org/adaures/castopod/commit/87cc437e1ead5486ed46ca37e2055aaf5c9445c1)), - closes [#423](https://code.castopod.org/adaures/castopod/issues/423) -- support VTT transcript file format in addition to SRT - ([7071b4b](https://code.castopod.org/adaures/castopod/commit/7071b4b6f48cb9a2f766064f3a5c23f92b293718)), - closes [#433](https://code.castopod.org/adaures/castopod/issues/433) - -# [1.9.0](https://code.castopod.org/adaures/castopod/compare/v1.8.2...v1.9.0) (1/31/2024) - -### Bug Fixes - -- **i18n:** escape language strings in form fields to prevent them from - disappearing - ([3cb5ffd](https://code.castopod.org/adaures/castopod/commit/3cb5ffd25b9604a83cd12935e641dab7c88fba47)), - closes [#412](https://code.castopod.org/adaures/castopod/issues/412) -- **podcast-about:** update stats query to discard scheduled episodes from - episodes number - ([67c037c](https://code.castopod.org/adaures/castopod/commit/67c037c9eb1e15c6945eaf74ec0ff30b33f4b704)) -- **premium-subs:** clear subscription list cache after insert - ([2accb0f](https://code.castopod.org/adaures/castopod/commit/2accb0f7652330b29c3adb85a2e1b0d5d83f1389)), - closes [#430](https://code.castopod.org/adaures/castopod/issues/430) -- **s3:** remove proxy, set objects acl to public-read, and serve files using - their public urls - ([6a77a9d](https://code.castopod.org/adaures/castopod/commit/6a77a9d2f29c849775a3d1bcbd819f73f21d9aa6)) - -### Features - -- add actor domain to handle in follow page - ([de099ac](https://code.castopod.org/adaures/castopod/commit/de099ac64300b8edb86e387fde89c0a3e9472f46)) -- **admin:** add podcast's OP3 analytics dashboard link - ([5f3752b](https://code.castopod.org/adaures/castopod/commit/5f3752b4430f6f2d5f9e5f6a7a003bc4d2f9d487)) - -## [1.8.2](https://code.castopod.org/adaures/castopod/compare/v1.8.1...v1.8.2) (1/17/2024) - -### Bug Fixes - -- **transcript:** add condition when concatenating sub text to prevent second - line duplication - ([6cbfec0](https://code.castopod.org/adaures/castopod/commit/6cbfec0d7d9bf85c8014d379026648857ea13373)) - -## [1.8.1](https://code.castopod.org/adaures/castopod/compare/v1.8.0...v1.8.1) (1/16/2024) - -### Bug Fixes - -- **models:** set updatedField as empty string when not used - ([164f4d3](https://code.castopod.org/adaures/castopod/commit/164f4d3be74ec8d371fb40d7fe730f7b2940ca05)) - -# [1.8.0](https://code.castopod.org/adaures/castopod/compare/v1.7.4...v1.8.0) (1/15/2024) - -### Bug Fixes - -- **episode-form:** add required validation rules for title and slug - ([30a3473](https://code.castopod.org/adaures/castopod/commit/30a34738635bf4f4a4c6b2a7174f7e439f0dfc6e)), - closes [#420](https://code.castopod.org/adaures/castopod/issues/420) -- **import:** check for empty string when generating podcast guid for feeds not - including one - ([ac5336f](https://code.castopod.org/adaures/castopod/commit/ac5336fbc5fb8038de541dd06938a8beb2e8d733)) -- **install:** add created superadmin to most powerful group in instance, ie. - superadmin - ([2ed511f](https://code.castopod.org/adaures/castopod/commit/2ed511f8a0005dc06eda5afd6b1d13beee1eb9dd)) -- **persons:** delete person avatar when deleting a person - ([c1ec98c](https://code.castopod.org/adaures/castopod/commit/c1ec98c95656844712011ff30b84c397b78da311)), - closes [#419](https://code.castopod.org/adaures/castopod/issues/419) -- **platforms:** add matrix.org as a social platform - ([9178c3f](https://code.castopod.org/adaures/castopod/commit/9178c3f3afa16e104d25ae159728e90a3bbd57c3)), - closes [#421](https://code.castopod.org/adaures/castopod/issues/421) - -### Features - -- **admin:** add tooltip for not authorized routes - ([f7f9baf](https://code.castopod.org/adaures/castopod/commit/f7f9bafc3e56621fab2569d9d76baafe0a2e940d)) -- **admin:** emphasize unprivileged items in sidebar with "prohibited" icon - ([0bd7dde](https://code.castopod.org/adaures/castopod/commit/0bd7ddea58adf502121b83e5c09317e20912fb4e)) -- allow hiding owner's email in public RSS feed - ([222e02a](https://code.castopod.org/adaures/castopod/commit/222e02a2af9ecb8b8768a63d3054f4c3ef54e991)) -- **persons:** order persons by full_name ASC for easier list scanning - ([68a599f](https://code.castopod.org/adaures/castopod/commit/68a599fee08c71763b9336e14b1c0d9e28c4449b)), - closes [#418](https://code.castopod.org/adaures/castopod/issues/418) - -## [1.7.4](https://code.castopod.org/adaures/castopod/compare/v1.7.3...v1.7.4) (1/3/2024) - -### Bug Fixes - -- **media:** add missing HEAD route for static assets served with S3 - ([b61a32c](https://code.castopod.org/adaures/castopod/commit/b61a32c8a9b10e129666804d533487430ce7432c)) - -## [1.7.3](https://code.castopod.org/adaures/castopod/compare/v1.7.2...v1.7.3) (12/21/2023) - -### Bug Fixes - -- **analytics:** upgrade opawg's user-agents-php to user-agents-v2-php - ([8cd7886](https://code.castopod.org/adaures/castopod/commit/8cd78866762e26aa63c224dace6c247e0e9dc068)) -- **platforms:** add Threads and YouTube Music - ([9264a2d](https://code.castopod.org/adaures/castopod/commit/9264a2d74cc95278c9d84c99ef914fdbcaf8a97f)) - -## [1.7.2](https://code.castopod.org/adaures/castopod/compare/v1.7.1...v1.7.2) (12/12/2023) - -### Bug Fixes - -- **episode-form:** render episode number optional when episode type is trailer - or bonus - ([694328f](https://code.castopod.org/adaures/castopod/commit/694328f10865b2fcd6436122de46866dae81f945)) - -## [1.7.1](https://code.castopod.org/adaures/castopod/compare/v1.7.0...v1.7.1) (12/1/2023) - -### Bug Fixes - -- **housekeeping:** add where clause to check episode_id is not null on reset - comments count - ([119742c](https://code.castopod.org/adaures/castopod/commit/119742cdbb2c2f7f847692fb76f6ff1dbb2e25b6)) - -# [1.7.0](https://code.castopod.org/adaures/castopod/compare/v1.6.5...v1.7.0) (11/29/2023) - -### Bug Fixes - -- **admin-ux:** hide navigation submenus in details panel for easier scanning - ([b047a3c](https://code.castopod.org/adaures/castopod/commit/b047a3c6707114d04c276758f2e543eef90d72f5)) -- **admin:** remove episode title truncation + display description in two lines - in episode list - ([f4ffa30](https://code.castopod.org/adaures/castopod/commit/f4ffa30ec4341f43e22b1f983781ad04c956aa25)), - closes [#386](https://code.castopod.org/adaures/castopod/issues/386) -- **auth:** display error messages from validator - ([5a834c0](https://code.castopod.org/adaures/castopod/commit/5a834c0f8957fc016e73325a3c3ff05e524d0755)) -- **housekeeping:** remove unnecessary $tablePrefix variable when resetting post - count - ([97d793f](https://code.castopod.org/adaures/castopod/commit/97d793f55e7eb3b049980e5081950baa2bb1b881)), - closes [#383](https://code.castopod.org/adaures/castopod/issues/383) -- **import:** handle bad values for location attributes - ([642981f](https://code.castopod.org/adaures/castopod/commit/642981fd358ccf118d3d7a957fb6be7933c016ac)) -- **import:** use cocur/slugify library to handle non latin text - ([4ca7f9c](https://code.castopod.org/adaures/castopod/commit/4ca7f9ccae1e352bf26a3b6db4de73bac7b84382)) -- move monetization outside of podcast form + add broadcast section to podcast - menu - ([dff8516](https://code.castopod.org/adaures/castopod/commit/dff85168b32a6df77425ef51865588ebcd8b8ba9)) -- **nodeinfo2:** import database config + use dynamic table prefix for active - local actors query - ([6a7ef01](https://code.castopod.org/adaures/castopod/commit/6a7ef0109a6e52144ca687b979ffe56fba66165b)) -- **persons:** set roles field as optional + set `Cast > Host` as default value - ([02132dc](https://code.castopod.org/adaures/castopod/commit/02132dc46640807e2bc4cfc406c911fa097f36fe)), - closes [#347](https://code.castopod.org/adaures/castopod/issues/347) -- **platforms:** make platforms' websites and submit urls more prominent - ([61cf8fa](https://code.castopod.org/adaures/castopod/commit/61cf8fa3e2435ee2a9bdd8e711b8d69d4ca4ec4c)) -- **podcast-form:** move fediverse section below author section - ([1861d67](https://code.castopod.org/adaures/castopod/commit/1861d67971e2cc0c20ace091f037f6436437a50d)) -- reorder podcast form fields + extract sync feeds to its own form - ([2d52fa1](https://code.castopod.org/adaures/castopod/commit/2d52fa1046faf1b8d81304e35fc24a7874315e6e)) - -### Features - -- **admin:** add rss feed link to podcast side navigation - ([18e2633](https://code.castopod.org/adaures/castopod/commit/18e2633a49dbbeb57a685f129a2ab158397de61e)) -- **icons:** update new Deezer logo - ([f2d5b27](https://code.castopod.org/adaures/castopod/commit/f2d5b272ac385a978d7e173121faafe03d7a7200)) -- **install:** init database and create superadmin using CLI - ([02d4ba6](https://code.castopod.org/adaures/castopod/commit/02d4ba69ac007ebd1eccab428a98b54051aaf70c)), - closes [#380](https://code.castopod.org/adaures/castopod/issues/380) -- **ux:** add episode description to episode cards - ([5f8d413](https://code.castopod.org/adaures/castopod/commit/5f8d413b84b236077a75934da9409f37d34cb4a5)) - -## [1.6.5](https://code.castopod.org/adaures/castopod/compare/v1.6.4...v1.6.5) (2023-09-26) - -### Bug Fixes - -- **fediverse:** use NoteObject including episode link in content (hotfix) - ([ffa530e](https://code.castopod.org/adaures/castopod/commit/ffa530e187ff6488648a7cf749ca0173765a5d87)) - -## [1.6.4](https://code.castopod.org/adaures/castopod/compare/v1.6.3...v1.6.4) (2023-09-17) - -### Bug Fixes - -- **fediverse:** do not cache remote action form + fix typo on post routes for - passing post uuid - ([4ecb42f](https://code.castopod.org/adaures/castopod/commit/4ecb42f7c82eb8d41d27c7b9705b3278ea04ab79)) -- **fediverse:** update post controller namespace in routes - ([3189f12](https://code.castopod.org/adaures/castopod/commit/3189f122067dc47d6de93c3185aca66d7df95e1a)) - -## [1.6.3](https://code.castopod.org/adaures/castopod/compare/v1.6.2...v1.6.3) (2023-09-14) - -### Bug Fixes - -- **fediverse:** add `index` to post controller-method to access post's jsonld - contents - ([35142d8](https://code.castopod.org/adaures/castopod/commit/35142d8e565e828a977ba2b4de77c1b47a633beb)) - -## [1.6.2](https://code.castopod.org/adaures/castopod/compare/v1.6.1...v1.6.2) (2023-09-11) - -### Bug Fixes - -- **migrations:** remove if exists modifier for drop index - ([82013c9](https://code.castopod.org/adaures/castopod/commit/82013c9cde901c54fdb3a833890aa693e8542627)), - closes [#382](https://code.castopod.org/adaures/castopod/issues/382) - -## [1.6.1](https://code.castopod.org/adaures/castopod/compare/v1.6.0...v1.6.1) (2023-09-09) - -### Bug Fixes - -- **admin:** redirect root fediverse route to fediverse-blocked-actors - ([ba5324e](https://code.castopod.org/adaures/castopod/commit/ba5324ea1942a3939f186e974d29fb393c54b253)) -- **analytics:** show full referrer domain in web pages visits reports - ([6be38e9](https://code.castopod.org/adaures/castopod/commit/6be38e9fda3d1436d81686e1a3a5e5b173e390a0)), - closes [#367](https://code.castopod.org/adaures/castopod/issues/367) -- **auth:** overwrite Shield's PermissionFilter - ([c6e8000](https://code.castopod.org/adaures/castopod/commit/c6e8000bab54f4a32068578f750f4cf9d91bad89)) -- **auth:** update shield from v1.0.0-beta.3 to v1.0.0-beta.6 - ([23842df](https://code.castopod.org/adaures/castopod/commit/23842df03ae28e416390e2436442b8e7c8340333)) -- **platforms:** add missing tiktok to social platforms seed - ([8dfdaf3](https://code.castopod.org/adaures/castopod/commit/8dfdaf321566050e9c53683e70864871eb55d618)) -- remove fediverse prefix to prevent migration error + load routes during - podcast import - ([7ff1dbe](https://code.castopod.org/adaures/castopod/commit/7ff1dbe9030768074b2fe7c7f570bfb9e7336f62)) -- **routes:** overwrite RouteCollection to include all routes + update js and - php dependencies - ([b4f1b91](https://code.castopod.org/adaures/castopod/commit/b4f1b916bfec53f071e8d0d900081c6d74486e53)) -- update Router to include latest CI changes with alternate-content logic - ([ae57601](https://code.castopod.org/adaures/castopod/commit/ae57601c838a7aa9469bae8038ac1c30d8c9a51e)) -- use podcast-activity named route instead of not existing actor route - ([3c35718](https://code.castopod.org/adaures/castopod/commit/3c357183ca51545787fcfc801b4a5829d9cd8ad6)) - -# [1.6.0](https://code.castopod.org/adaures/castopod/compare/v1.5.2...v1.6.0) (2023-08-28) - -### Bug Fixes - -- **home:** update where clause when getting all podcasts to prevent draft - podcasts from showing up - ([7a1eea5](https://code.castopod.org/adaures/castopod/commit/7a1eea58d3cbc1982baaec21d87a36e218e1910a)) -- **media:** copy and delete temp file when saving instead of moving it for FS - FileManager - ([9346e78](https://code.castopod.org/adaures/castopod/commit/9346e787bd2a2c815533092279f96ae1fe0d9aae)), - closes [#338](https://code.castopod.org/adaures/castopod/issues/338) -- **media:** get path using media_path_absolute when saving media file - ([754e7a6](https://code.castopod.org/adaures/castopod/commit/754e7a6b4b2c12cf50c1c8b166732dc3255f36fb)) -- **media:** init file properties in setAttributes' Model method + set defaults - to pathinfo data - ([0775add](https://code.castopod.org/adaures/castopod/commit/0775add67860b94a35b68c01b133ec8ec969f539)) -- **premium-podcasts:** show premium flag only when podcast has published - premium episodes - ([d10c4fd](https://code.castopod.org/adaures/castopod/commit/d10c4fd7538e6af8a5b0eb232a06522fe8c4bf8e)) -- **s3:** add a flag to serve media files by redirecting to a presigned url - instead of default proxy - ([11aa358](https://code.castopod.org/adaures/castopod/commit/11aa3586a04c166404954600235634cee77219df)) - -### Features - -- **episode:** add preview link in admin to view and share episode before - publication - ([7d21b35](https://code.castopod.org/adaures/castopod/commit/7d21b3509ec5d1aa65420efa038f44bcd235e64f)) - -## [1.5.2](https://code.castopod.org/adaures/castopod/compare/v1.5.1...v1.5.2) (2023-07-31) - -### Bug Fixes - -- **credits:** remove undefined $podcast variable from page layout - ([73a5b68](https://code.castopod.org/adaures/castopod/commit/73a5b680875cc520fd15c529c01d44df728f9be2)), - closes [#359](https://code.castopod.org/adaures/castopod/issues/359) -- **platforms:** change twitter to X + add buymeacoffee and kofi as funding - ([d69b4e4](https://code.castopod.org/adaures/castopod/commit/d69b4e4857fcb1ac1c05ac59c78d130788f00400)), - closes [#353](https://code.castopod.org/adaures/castopod/issues/353) - [#361](https://code.castopod.org/adaures/castopod/issues/361) - -## [1.5.1](https://code.castopod.org/adaures/castopod/compare/v1.5.0...v1.5.1) (2023-07-29) - -### Bug Fixes - -- **admin-ui:** remove button labels on smaller screens in podcast view - ([9cc5ffd](https://code.castopod.org/adaures/castopod/commit/9cc5ffd1439fdc86f46a03f4319cae32db95f84e)) -- **rss:** set srt transcripts' mimetype to application/x-subrip with - rel="captions" attribute - ([16a3fdb](https://code.castopod.org/adaures/castopod/commit/16a3fdb56e3f07185e75d106216f29519ccb25f7)), - closes [#360](https://code.castopod.org/adaures/castopod/issues/360) -- **rss:** update podcast extension namespace - ([6833dd0](https://code.castopod.org/adaures/castopod/commit/6833dd05ab51bc530d34fd4174ad732f623226c0)), - closes [#360](https://code.castopod.org/adaures/castopod/issues/360) - -# [1.5.0](https://code.castopod.org/adaures/castopod/compare/v1.4.7...v1.5.0) (2023-07-27) - -### Bug Fixes - -- **admin-ui:** truncate header title + remove sticky podcast banner card on - mobile - ([63c20da](https://code.castopod.org/adaures/castopod/commit/63c20da5ffd500265f06fa38f2b2c963e14602af)) - -### Features - -- add podcast links page including social, podcasting and funding links - ([8ae2929](https://code.castopod.org/adaures/castopod/commit/8ae292933af15fa99856582ac24e985bfef37d5b)) - -## [1.4.7](https://code.castopod.org/adaures/castopod/compare/v1.4.6...v1.4.7) (2023-07-19) - -### Bug Fixes - -- **s3:** allow CORS for served static files - ([9b955c9](https://code.castopod.org/adaures/castopod/commit/9b955c9ce25a06a9102b67ebe77375dc45d28f0f)) - -## [1.4.6](https://code.castopod.org/adaures/castopod/compare/v1.4.5...v1.4.6) (2023-07-11) - -### Bug Fixes - -- **fediverse:** expand object before sending accept follow request - ([082cdc9](https://code.castopod.org/adaures/castopod/commit/082cdc9ee79d004c2ed748e3b8046e9141bf0242)), - closes [#350](https://code.castopod.org/adaures/castopod/issues/350) -- **podcast-import:** remove error log when no import in queue, exit with - success instead - ([5e719f3](https://code.castopod.org/adaures/castopod/commit/5e719f3e9eb6cf48c3fd8ac97181638b24d03fc9)) - -## [1.4.5](https://code.castopod.org/adaures/castopod/compare/v1.4.4...v1.4.5) (2023-07-04) - -### Bug Fixes - -- **s3:** handle range requests to serve media files - ([41a5932](https://code.castopod.org/adaures/castopod/commit/41a59322332c835808a32987aaf8ec6cafbf5fca)) - -## [1.4.4](https://code.castopod.org/adaures/castopod/compare/v1.4.3...v1.4.4) (2023-07-02) - -### Bug Fixes - -- **audio-clipper:** init segment position on firstUpdate + improve UX by adding - ghost handle - ([aa68386](https://code.castopod.org/adaures/castopod/commit/aa683866671d14c0b9a11b09c74eb132673e5547)), - closes [#351](https://code.castopod.org/adaures/castopod/issues/351) -- set resized images to 72dpi for compatibility with Apple Podcasts - ([0b327cb](https://code.castopod.org/adaures/castopod/commit/0b327cb4d9c92d0ae227a0f08ede3b29390df172)), - closes [#282](https://code.castopod.org/adaures/castopod/issues/282) - -## [1.4.3](https://code.castopod.org/adaures/castopod/compare/v1.4.2...v1.4.3) (2023-06-29) - -### Bug Fixes - -- **video-clipper:** add -t option to ffmpeg command to stop generation after - duration - ([60814b8](https://code.castopod.org/adaures/castopod/commit/60814b8d202419c2bdbf6abb7c2bde447537b7e9)), - closes [#341](https://code.castopod.org/adaures/castopod/issues/341) - -## [1.4.2](https://code.castopod.org/adaures/castopod/compare/v1.4.1...v1.4.2) (2023-06-27) - -### Bug Fixes - -- **fediverse:** check that actor's images mimetype is present or guess it - otherwise - ([06c4f15](https://code.castopod.org/adaures/castopod/commit/06c4f15477a568407a3d3c1e5e489bc0241bc1e9)), - closes [#348](https://code.castopod.org/adaures/castopod/issues/348) -- **podcast-import:** show cancel or retry action depending on task status - ([e42258d](https://code.castopod.org/adaures/castopod/commit/e42258de1f331aac0cbb380b80cd8fc7f9d7dc18)) - -## [1.4.1](https://code.castopod.org/adaures/castopod/compare/v1.4.0...v1.4.1) (2023-06-22) - -### Bug Fixes - -- **podcast-import:** set default values for person group and role if not found - in taxonomy - ([aa46dca](https://code.castopod.org/adaures/castopod/commit/aa46dca4e399bf2e544d62dcb4a9a0328e4e6c41)) - -# [1.4.0](https://code.castopod.org/adaures/castopod/compare/v1.3.5...v1.4.0) (2023-06-21) - -### Bug Fixes - -- **charts:** set duration charts label to HHhMM for listening time analytics - ([3fc1d8e](https://code.castopod.org/adaures/castopod/commit/3fc1d8e18dc8119251c72dcaa7e5121246c2b194)) -- **embed:** set height of player iframe from config - ([4665741](https://code.castopod.org/adaures/castopod/commit/4665741425532f253a46a42ba05602047798dba2)) -- **s3:** serve files without cache if dummy cache handler + add http referer - header to redirect - ([30db9f0](https://code.castopod.org/adaures/castopod/commit/30db9f0667bf7f7a5f186ea667a524d1e3b502db)) -- **s3:** use presigned request uri to serve static files - ([cb92dc7](https://code.castopod.org/adaures/castopod/commit/cb92dc73f17543d32d1cdc24db72403a5c561a74)) -- **webmanifest:** import misc helper to get site_icon_url - ([548a11d](https://code.castopod.org/adaures/castopod/commit/548a11d501749fa61ef894fd8818abae5668554f)) - -### Features - -- **import:** run podcast imports' processes asynchronously using tasks - ([d8e1d40](https://code.castopod.org/adaures/castopod/commit/d8e1d4031d86de9a3889b74ae2a6d9c90af8a1da)) -- **rest-api:** add endpoints for episodes and full text search for podcasts and - episodes - ([85505d4](https://code.castopod.org/adaures/castopod/commit/85505d4b3181c96bc91619e3ab9b0601f8e1c120)), - closes [#296](https://code.castopod.org/adaures/castopod/issues/296) - -## [1.3.5](https://code.castopod.org/adaures/castopod/compare/v1.3.4...v1.3.5) (2023-05-09) - -### Bug Fixes - -- replace essence with embera to create preview cards - ([c682f03](https://code.castopod.org/adaures/castopod/commit/c682f03a67c6c0ebbcc6ff45d9a037f6f9823bde)) - -## [1.3.4](https://code.castopod.org/adaures/castopod/compare/v1.3.3...v1.3.4) (2023-05-05) - -### Bug Fixes - -- **import-update:** insert episodes incrementally into database - ([108fdf8](https://code.castopod.org/adaures/castopod/commit/108fdf84b8dd458fc71a06a77d14069287ab8e42)) - -## [1.3.3](https://code.castopod.org/adaures/castopod/compare/v1.3.2...v1.3.3) (2023-04-17) - -### Bug Fixes - -- unnescape podcast title special characters in "find us on" section - ([f727276](https://code.castopod.org/adaures/castopod/commit/f727276f820a8ef2c47947f40a37a4a157b509ef)), - closes [#323](https://code.castopod.org/adaures/castopod/issues/323) -- **websub:** add missing misc helper import - ([855aacc](https://code.castopod.org/adaures/castopod/commit/855aacce0bf3841a876cd593e668e116149080aa)) - -## [1.3.2](https://code.castopod.org/adaures/castopod/compare/v1.3.1...v1.3.2) (2023-04-14) - -### Bug Fixes - -- remove path key when getting default avatar path - ([c5a1359](https://code.castopod.org/adaures/castopod/commit/c5a1359218d61c0f78006f2bd5785e317f32bade)) -- **s3:** serve files using media base url to allow for CDN setup - ([502f53c](https://code.castopod.org/adaures/castopod/commit/502f53c9701da3b8da2caef1eb54df25b7d2d86a)) - -## [1.3.1](https://code.castopod.org/adaures/castopod/compare/v1.3.0...v1.3.1) (2023-04-13) - -### Bug Fixes - -- **s3:** add proxy to serve images from s3 to client - ([a76724a](https://code.castopod.org/adaures/castopod/commit/a76724a8cfee700f6874f86b35616d61facc664e)), - closes [#321](https://code.castopod.org/adaures/castopod/issues/321) - -# [1.3.0](https://code.castopod.org/adaures/castopod/compare/v1.2.4...v1.3.0) (2023-04-03) - -### Bug Fixes - -- delete files using file_manager when deleting episode and podcast - ([41d8efe](https://code.castopod.org/adaures/castopod/commit/41d8efe6e71566eba44bfdfd00d1708ac4338366)) - -### Features - -- **media:** set media storage directory as configurable - ([7e1a470](https://code.castopod.org/adaures/castopod/commit/7e1a470ba42172eb4c3864ab3652e9f8b55d1ba8)) - -## [1.2.4](https://code.castopod.org/adaures/castopod/compare/v1.2.3...v1.2.4) (2023-03-23) - -### Bug Fixes - -- allow images to have .jpeg extension consistently - ([ae5e12b](https://code.castopod.org/adaures/castopod/commit/ae5e12be3b15fe50cb2311abcbbc19ac23b592f6)) -- **s3:** delete persons image sizes from bucket + add keyPrefix to config - ([208c271](https://code.castopod.org/adaures/castopod/commit/208c2715f900371987c3b75a749fe937a3db1991)) -- **s3:** do not create bucket if not exists, check if healthy instead - ([da7076f](https://code.castopod.org/adaures/castopod/commit/da7076fc2d49d07708d5adaa99733487b7f52e20)) - -### Reverts - -- **homepage:** remove redirect to install if database is not setup - ([d4954e0](https://code.castopod.org/adaures/castopod/commit/d4954e026d5e0d48c5f15ed69d1ce71abb34d1a1)) - -## [1.2.3](https://code.castopod.org/adaures/castopod/compare/v1.2.2...v1.2.3) (2023-03-18) - -### Bug Fixes - -- **notifications:** set mark-all-as-read parameter to be podcast_id instead of - actor_id - ([2748f23](https://code.castopod.org/adaures/castopod/commit/2748f2313797e50d8a2a7b87df09c0bc6e64360a)) - -## [1.2.2](https://code.castopod.org/adaures/castopod/compare/v1.2.1...v1.2.2) (2023-03-18) - -### Bug Fixes - -- **migration:** change old media file_key to file_path - ([a414142](https://code.castopod.org/adaures/castopod/commit/a4141421aa1d6e89742b390b042382f729f965a9)), - closes [#314](https://code.castopod.org/adaures/castopod/issues/314) - -## [1.2.1](https://code.castopod.org/adaures/castopod/compare/v1.2.0...v1.2.1) (2023-03-17) - -### Bug Fixes - -- change app.mediaBaseURL to media.baseURL in install, docker entrypoints and - docs - ([b3c6e05](https://code.castopod.org/adaures/castopod/commit/b3c6e05e6fcd8a518eeedeefde28b61f879ba71d)) - -# [1.2.0](https://code.castopod.org/adaures/castopod/compare/v1.1.2...v1.2.0) (2023-03-17) - -### Bug Fixes - -- **analytics:** check the x_forwarded_for client header - ([1111177](https://code.castopod.org/adaures/castopod/commit/1111177eb7fea4eba6d119b17acdf3bf416492ef)) -- **auth:** update podcast editors' permissions - ([a9b6308](https://code.castopod.org/adaures/castopod/commit/a9b630884bc318499ea7f03862d5752dd5f178e1)) -- **contributors:** add dash to prevent deleting permissions from other podcast - ([5d2a2d4](https://code.castopod.org/adaures/castopod/commit/5d2a2d49c489cd98f9c9ecbca35fd5d21a9cadfb)), - closes [#310](https://code.castopod.org/adaures/castopod/issues/310) -- display bandwidth limit on dashboard when set in .env - ([a2a87ab](https://code.castopod.org/adaures/castopod/commit/a2a87abf7caea3c87bcf2d0988610cc07782de9e)) -- **docker:** update nginx configuration - ([8884598](https://code.castopod.org/adaures/castopod/commit/8884598a56d0e2550776ef4cee5e53558c20e009)) -- **platforms:** update 'submit_url' for Antennapod - ([9fc49a7](https://code.castopod.org/adaures/castopod/commit/9fc49a7430406f50e68318c5fd7c577ae1ebd9df)) - -### Features - -- add downloads count to episode list - ([b63c1dc](https://code.castopod.org/adaures/castopod/commit/b63c1dc9b1ed41626b99ba852a9a00ed417059ba)) -- add health route to check if db, cache and file manager are ok - ([1dde11f](https://code.castopod.org/adaures/castopod/commit/1dde11f8e42b66684a956068f5347e9289f4918b)) -- **media:** add s3 to manage media files - ([d93fc98](https://code.castopod.org/adaures/castopod/commit/d93fc98469ffe93913b65e539dec396891708c70)) - -### Reverts - -- **install:** reset condition to look for instance owner before continuing - install - ([fc009f3](https://code.castopod.org/adaures/castopod/commit/fc009f3d0058028bbbb6418603cf820c0f7cea80)) - -## [1.1.2](https://code.castopod.org/adaures/castopod/compare/v1.1.1...v1.1.2) (2022-12-14) - -### Bug Fixes - -- **analytics:** set EpisodeAudioController to init user session data - ([77ccb30](https://code.castopod.org/adaures/castopod/commit/77ccb306009eb093147c56789535e754f3d85570)) - -## [1.1.1](https://code.castopod.org/adaures/castopod/compare/v1.1.0...v1.1.1) (2022-12-13) - -### Bug Fixes - -- **op3:** remove scheme when wraping audio URI - ([0ad22e4](https://code.castopod.org/adaures/castopod/commit/0ad22e49bc488e96df5a41495f5b242559b64a45)) -- **rss:** add file extension to enclosure url - ([964cbba](https://code.castopod.org/adaures/castopod/commit/964cbba54f16556408bf8280c544a52e6be5c9fc)) - -# [1.1.0](https://code.castopod.org/adaures/castopod/compare/v1.0.5...v1.1.0) (2022-12-09) - -### Bug Fixes - -- **notifications:** remove cache inconsistencies when marking notification as - read - ([46d7054](https://code.castopod.org/adaures/castopod/commit/46d70541d313c836ab0c078ba6121fe5fe956e62)) -- **notifications:** retrieve activity from database instead of getting cache - ([7fbbd08](https://code.castopod.org/adaures/castopod/commit/7fbbd08da6a37d08608900ad318e72815fe4b0c4)) -- **podcast:soundbite:** rename start time attribute to follow spec - ([689831c](https://code.castopod.org/adaures/castopod/commit/689831c26c756d454de432900d23bc09a37f890b)) - -### Features - -- **analytics:** add OP3 analytics service option + update episode audio url - ([16527ed](https://code.castopod.org/adaures/castopod/commit/16527ed529265f2925e205856c684e34175a8933)) - -## [1.0.5](https://code.castopod.org/adaures/castopod/compare/v1.0.4...v1.0.5) (2022-11-25) - -### Bug Fixes - -- **router:** revert to CI4 v4.2.7 to include all routes - ([c13cfa0](https://code.castopod.org/adaures/castopod/commit/c13cfa0ea0679751521ca4157b953043ecc7974a)) - -## [1.0.4](https://code.castopod.org/adaures/castopod/compare/v1.0.3...v1.0.4) (2022-11-21) - -### Bug Fixes - -- update actorUsername regex to get url_to actor - ([1d6b177](https://code.castopod.org/adaures/castopod/commit/1d6b177a55111ede01fba1c08499036d474533bc)) - -## [1.0.3](https://code.castopod.org/adaures/castopod/compare/v1.0.2...v1.0.3) (2022-11-17) - -### Bug Fixes - -- **dashboard-ui:** fill the blank gaps between cards on smaller screen sizes - ([00836cc](https://code.castopod.org/adaures/castopod/commit/00836cc368c75ae2e23fa5dc4a53a5bb6eb2ce24)) - -## [1.0.2](https://code.castopod.org/adaures/castopod/compare/v1.0.1...v1.0.2) (2022-11-04) - -### Bug Fixes - -- **auth:** disallow registration by default - ([379b9be](https://code.castopod.org/adaures/castopod/commit/379b9be2b99574fe4af4009b01128dba2c75f037)) -- **contributors:** add prefix to podcast group to delete contributor - ([9f785db](https://code.castopod.org/adaures/castopod/commit/9f785db7ba674638a6f456aa3626f3f8100911f1)) -- extract podcast ids from user groups using a regex - ([e26215a](https://code.castopod.org/adaures/castopod/commit/e26215a11fc23aa0ad5ccff8ee97d6c6e8a09c1a)) -- **notifications:** add manage-notifications permission to podcast - ([ed7c247](https://code.castopod.org/adaures/castopod/commit/ed7c247bcbbb450e5ff96418930d3b37ce912cc4)) -- **platforms:** convert special characters to htmlentities to validate url - ([82310a2](https://code.castopod.org/adaures/castopod/commit/82310a2e0b426e84501090bdd9c0cf592d1c0d53)) - -## [1.0.1](https://code.castopod.org/adaures/castopod/compare/v1.0.0...v1.0.1) (2022-11-01) - -### Bug Fixes - -- **platforms:** trim platform url before validation and storage - ([259fe5f](https://code.castopod.org/adaures/castopod/commit/259fe5f697a833e268cde88e959bc19bd662edf6)) - -# 1.0.0 (2022-10-20) - -### Bug Fixes - -- **a11y:** replace active tab color to contrast with background on podcast and - episode pages - ([f3785e1](https://code.castopod.org/adaures/castopod/commit/f3785e140147d085a2fb6a62ded87cdfe360f442)) -- **activity-pub:** cache issues when navigating to activity stream urls - ([7bcbfb3](https://code.castopod.org/adaures/castopod/commit/7bcbfb32f7cca08d111be46c7f1640e372d4a4b0)) -- **activity-pub:** get database records using new model instances - ([92536dd](https://code.castopod.org/adaures/castopod/commit/92536ddb3812214a9c5682b92e547e5c1998a5d7)) -- **activitypub:** add conditions for possibly missing actor properties + add - user-agent to requests - ([8fbf948](https://code.castopod.org/adaures/castopod/commit/8fbf948fbba22ffd33966a1b2ccd42e8f7c1f8a2)) -- **activitypub:** add target actor id to like / announce activities to send - directly to note's actor - ([962dd30](https://code.castopod.org/adaures/castopod/commit/962dd305f5d3f6eadc68f400e0e8f953827fe20d)) -- **activitypub:** add target_actor_id for create activity to broadcast post - reply - ([0128a21](https://code.castopod.org/adaures/castopod/commit/0128a21ec55dcc0a2fbf4081dadb4c4737735ba1)) -- **activitypub:** allow cors on get requests for routes exposing acitivitypub - objects - ([2f24809](https://code.castopod.org/adaures/castopod/commit/2f2480998f9abb34f02ab186c65d462a74b4e640)) -- **activitypub:** set created_by to null for reblog if no user + update episode - oembed data - ([209dfbd](https://code.castopod.org/adaures/castopod/commit/209dfbd134e1a2cc02e7c24c158d786fa4dda61d)) -- add admin-audio-player to vite config to have admin player show up - ([93cb9b2](https://code.castopod.org/adaures/castopod/commit/93cb9b24701c09b92820204a67c1fc1b3c044708)) -- add application/octet-stream mimetype to mp3 and m4a extensions to prevent - ext_in error - ([339bef8](https://code.castopod.org/adaures/castopod/commit/339bef878e54983d86e91e6ff7a931a843d321b3)), - closes [#145](https://code.castopod.org/adaures/castopod/issues/145) -- add category_label component to include parent category in about podcast page - ([74e7d68](https://code.castopod.org/adaures/castopod/commit/74e7d68ac834885c4b89ee6e7d60db2157165799)) -- add explicit int conversion when formatting episode duration - ([1253096](https://code.castopod.org/adaures/castopod/commit/1253096197a0d30692bdafa7152f250cd9a71acf)) -- add head request to analytics_hit route - ([f0a2f0b](https://code.castopod.org/adaures/castopod/commit/f0a2f0bea491ca91976b351bb79837e95c9d094b)) -- add href to castopod website on login page - ([cc54257](https://code.castopod.org/adaures/castopod/commit/cc5425735184ad738aa0f38540f18e8971f8f56e)) -- add missing explicit badge for podcasts and episodes - ([cdf9f9d](https://code.castopod.org/adaures/castopod/commit/cdf9f9d53f2597f19455cb65c51da4677bb99327)) -- add open graph size for podcast images to replace the inadequate large format - ([33aae1f](https://code.castopod.org/adaures/castopod/commit/33aae1f7934e4962116e94e477dbf48e24971f5f)) -- add public/media folder to castopod bundle - ([8053d35](https://code.castopod.org/adaures/castopod/commit/8053d3521b481872711dabaaf265d08b9bfbaa87)), - closes [#52](https://code.castopod.org/adaures/castopod/issues/52) -- add translation key for audio-clipper trim labels - ([db191ac](https://code.castopod.org/adaures/castopod/commit/db191ac31bd16bad2a72afdb8b25c685adf86a6e)) -- add underline and semibold font weight for prose links to have them stand out - ([d4d8671](https://code.castopod.org/adaures/castopod/commit/d4d867121c50bded4176a53d7154cf1bb347e306)) -- add where condition to get episode count without deleted episodes - ([7661734](https://code.castopod.org/adaures/castopod/commit/7661734ed296654630f3668132671117519145dd)), - closes [#67](https://code.castopod.org/adaures/castopod/issues/67) -- **admin:** save block and lock switches - ([b66c0af](https://code.castopod.org/adaures/castopod/commit/b66c0afc8fab2e338402a9a4f8105e5f5459e208)) -- **analytics:** redirect to mp3 file even when referer was not set - ([9fc388d](https://code.castopod.org/adaures/castopod/commit/9fc388d154f29c335dedcd624abe8c1751762c07)) -- **analytics:** remove charts empty values + remove useless language cache - ([1678794](https://code.castopod.org/adaures/castopod/commit/16787941539ba4014281a366789ea896a9cd2afc)) -- **analytics:** set duration field to precise decimal as episode's audio file - duration - ([d772685](https://code.castopod.org/adaures/castopod/commit/d77268540569b2be9d91d5e09aefb3ff5ac2b071)) -- **analytics:** set initial value for duration and bandwidth - ([ee50539](https://code.castopod.org/adaures/castopod/commit/ee5053959154b1a2e5fbe4b43162968425206a26)) -- **analytics:** update migrations to set decimal precision for latitude and - longitude - ([714d6b5](https://code.castopod.org/adaures/castopod/commit/714d6b5d4950e52cf1c3170bb59954f98ffd48bd)) -- **analytics:** update service management so that it works with new OPAWG slug - values - ([7fe9d42](https://code.castopod.org/adaures/castopod/commit/7fe9d42500ade2c6fa3ff4365b4affc475af0e51)) -- **audio-clipper:** add mouse position offset when stretching clip to prevent - content from jumping - ([602654b](https://code.castopod.org/adaures/castopod/commit/602654b99b33ee8c29da080058a0aaea976cd484)) -- **audio-clipper:** show audio playing progress + put waveform behind audio - clipper - ([01a09dc](https://code.castopod.org/adaures/castopod/commit/01a09dc447b81c5412ceb45d6706a867939fd4dd)) -- **avatar:** use default avatar when no avatar url has been set - ([9d23c7e](https://code.castopod.org/adaures/castopod/commit/9d23c7e7e142c6cf1a1418e37e41d711064593c4)), - closes [#111](https://code.castopod.org/adaures/castopod/issues/111) -- **bundle:** include modules and themes when copying files with rsync - ([cd5bb88](https://code.castopod.org/adaures/castopod/commit/cd5bb8835c6e259408a8c13a2196a347e161da83)) -- **bundle:** update vite input files path + add `set -e` in bash scripts to - fail if command fails - ([0ee53c7](https://code.castopod.org/adaures/castopod/commit/0ee53c71ffadb8a6ddb1febd9f912bc99f5f7a0b)) -- **cache:** add locale for podcast and episode pages + clear some persisting - cache in models - ([9cec8a8](https://code.castopod.org/adaures/castopod/commit/9cec8a81ccbb7239402fe6633dbc31979272302a)), - closes [#42](https://code.castopod.org/adaures/castopod/issues/42) - [#61](https://code.castopod.org/adaures/castopod/issues/61) -- **cache:** delete posts and comments pages cache when updating platform links - ([f7c3e5b](https://code.castopod.org/adaures/castopod/commit/f7c3e5bf4ad43389bf8d58d2c4aaf16b81cbce00)), - closes [#169](https://code.castopod.org/adaures/castopod/issues/169) -- **cache:** return a non cached view when connected - ([e2e7358](https://code.castopod.org/adaures/castopod/commit/e2e735815d805a48eed2ea3288d060d0ddb253a3)) -- **cache:** suffix cache names with authenticated for credits, map and pages - ([418a70b](https://code.castopod.org/adaures/castopod/commit/418a70b2a670d8ba0ab6c15fa5faa41f6be55e53)) -- cast actor_id to pass as int to set_interact_as_actor() function - ([56a8e5d](https://code.castopod.org/adaures/castopod/commit/56a8e5d7dd615322aeb007e730801c65d0b02e5c)) -- **category:** remove uncategorized option to enforce users in choosing a - category - ([8c64f25](https://code.castopod.org/adaures/castopod/commit/8c64f25a0e72fec03d25544797d32623b2276fce)) -- change image size requirement hints - ([ea20206](https://code.castopod.org/adaures/castopod/commit/ea20206ee674eb54dd3ea188d2a2e2d41425df65)) -- change message upon cancellation of episode publication - ([9859c74](https://code.castopod.org/adaures/castopod/commit/9859c7434c2a3478ce035f7a4de20f594d63f5b0)) -- check for database connection and podcasts table existence before redirecting - to install - ([eb74e81](https://code.castopod.org/adaures/castopod/commit/eb74e81c3d93581e310b391cd029e62a0d690a8a)) -- check that additional files are valid when creating episode - ([eac5bc8](https://code.castopod.org/adaures/castopod/commit/eac5bc876de125e1fe08d1b89f767a04fc0fbfb6)) -- check that note has a preview_card_id before displaying it - ([acb8b3a](https://code.castopod.org/adaures/castopod/commit/acb8b3a40172ccb184ffe544760601d756692e6c)), - closes [#114](https://code.castopod.org/adaures/castopod/issues/114) -- clear cache when deleting podcast banner - ([99bb40b](https://code.castopod.org/adaures/castopod/commit/99bb40b8bc17b8ee2cd8468a82e46ea280c92cb6)) -- comment all cache clean after page update to prevent analytics cache deletion - ([e6197a4](https://code.castopod.org/adaures/castopod/commit/e6197a4972a3cce3d67dd7972bb54f8720b8e5b7)) -- **comments:** add comment view partials for public pages - ([fcecbe1](https://code.castopod.org/adaures/castopod/commit/fcecbe1c68b0d28d19454fba65caf3ab769fbc75)) -- correct chart data - ([4d3e9c8](https://code.castopod.org/adaures/castopod/commit/4d3e9c8c02cdc882e9fe1c29625695b6f83c820a)) -- correct percona compatibility issue - ([e53f819](https://code.castopod.org/adaures/castopod/commit/e53f819264b2d6902996f11ffcbb7c99295a90ef)) -- correct php-fpm issues - ([1ef55d7](https://code.castopod.org/adaures/castopod/commit/1ef55d7315bb44abe05f02ec8a84b6b6a557a9a0)) -- correct referrer bug - ([ed69b2f](https://code.castopod.org/adaures/castopod/commit/ed69b2f5004ed1cd18bac824c08a0df01f5d2637)) -- correction for servers with low int precision - ([31b7828](https://code.castopod.org/adaures/castopod/commit/31b7828e77519ef43e9bcfcbdf6c21712f97a571)) -- **cors:** add preflight option routes for episode, podcast and status objects - ([a281abf](https://code.castopod.org/adaures/castopod/commit/a281abfda475388a07943c169dab460cc2d4f944)) -- declare typed properties in PHPDoc for php<7.4 - ([14dd44d](https://code.castopod.org/adaures/castopod/commit/14dd44d03d6db0d9ae4198db8e65c92a0e45cb31)), - closes [#23](https://code.castopod.org/adaures/castopod/issues/23) -- define podcast_id and platform_slug as foreign keys in podcasts_plaforms table - ([6e9451a](https://code.castopod.org/adaures/castopod/commit/6e9451a1103b43750fa70ad576de36af25ca29cb)) -- define podcastNamespaceLink value - ([0d744d2](https://code.castopod.org/adaures/castopod/commit/0d744d212df0d070ceea185068eaf2746e1ccd48)) -- **email:** set the correct url in the activation and forgot emails - ([10fc6f1](https://code.castopod.org/adaures/castopod/commit/10fc6f17c6838a58348f32ccfd0cf05f9d3e172c)), - closes [#204](https://code.castopod.org/adaures/castopod/issues/204) -- **embeddable-player:** enable any ancestor when X-Frame-Options is set on - server - ([44a4962](https://code.castopod.org/adaures/castopod/commit/44a4962e0b7e3ed87e9914b4e7792a0d52330ff8)) -- **embed:** open embedded player's links in new tab - ([4aa73d7](https://code.castopod.org/adaures/castopod/commit/4aa73d71e3b8c0a6c3f75f4d1d45c4d693aba64c)) -- **episode-form:** show warning to set `memory_limit`, `upload_max_filesize` & - `post_max_size` - ([3b3c218](https://code.castopod.org/adaures/castopod/commit/3b3c218b9c868e9f12c54d7670e69d84c9ee79c0)), - closes [#5](https://code.castopod.org/adaures/castopod/issues/5) - [#86](https://code.castopod.org/adaures/castopod/issues/86) -- **episode-unpublish:** set consistent posts_counts' increments/decrements for - actors and episodes - ([8acdafd](https://code.castopod.org/adaures/castopod/commit/8acdafd26044e50a4d6ee451bf24ad66003c5bb3)), - closes [#233](https://code.castopod.org/adaures/castopod/issues/233) -- **episodeCount:** add missing brackets to French language file - ([c1b4112](https://code.castopod.org/adaures/castopod/commit/c1b411265ad9b06e95a8b097ecf73445b88dcb45)) -- **episode:** replace guid's empty string value to null - ([441052a](https://code.castopod.org/adaures/castopod/commit/441052af8d99e6e317edefd1e58ad71799357088)) -- **episodes-page:** handle defaultQuery being null when no podcast episodes - ([15183b7](https://code.castopod.org/adaures/castopod/commit/15183b7eab57dac007bcdfa8c3651239de1ae05a)), - closes [#100](https://code.castopod.org/adaures/castopod/issues/100) -- **episodes-table:** set descriptions to be not null - ([6774ec1](https://code.castopod.org/adaures/castopod/commit/6774ec10fa78527be6b7548ca1dc34ad0ada090c)) -- **episodes:** add publication status + set publication date to null when none - has been set - ([d882981](https://code.castopod.org/adaures/castopod/commit/d882981b3a86c81921ce6b07d4cf61fc13983689)), - closes [#70](https://code.castopod.org/adaures/castopod/issues/70) -- escape characters for `min` in format_duration_symbol - ([3b6722a](https://code.castopod.org/adaures/castopod/commit/3b6722a42b9e4330e5235d4ceed41c777159f4dc)) -- escape generated feed tag values and remove new lines from public pages meta - description - ([6238a43](https://code.castopod.org/adaures/castopod/commit/6238a43863210afe8988ad7cf251e6bfc6c8557c)), - closes [#57](https://code.castopod.org/adaures/castopod/issues/57) - [#46](https://code.castopod.org/adaures/castopod/issues/46) -- expire default query cache upon scheduled episode publication - ([b72e7c8](https://code.castopod.org/adaures/castopod/commit/b72e7c8691c887e41107baea0a4d50a39eaf8c8b)), - closes [#81](https://code.castopod.org/adaures/castopod/issues/81) -- explicitly cast seconds to int in iso8601_duration helper function - ([779653f](https://code.castopod.org/adaures/castopod/commit/779653f75b140942f731cbb238bc0667cc461307)) -- **fediverse:** set default castopod avatar url when actor avatar is not - present - ([460f52f](https://code.castopod.org/adaures/castopod/commit/460f52f70e493d619c28632db6c698e88f0ebb5f)) -- **fediverse:** set model instances as non shared to prevent overlapping - ([91128fa](https://code.castopod.org/adaures/castopod/commit/91128fad7a68e1f4e5acacba90b6899288699e61)) -- fix layout bugs in admin and update translation files - ([a834171](https://code.castopod.org/adaures/castopod/commit/a83417180cf61cdfadc5509b0aaa2fdb66592be3)), - closes [#40](https://code.castopod.org/adaures/castopod/issues/40) -- **follow:** add missing helpers to Actor controller - ([ee53a73](https://code.castopod.org/adaures/castopod/commit/ee53a732dc12ebbf5706e14969749a12cfd9d559)) -- **get_browser_language:** return defaultLocale if browser doesn't send user - preferred language - ([9cc2996](https://code.castopod.org/adaures/castopod/commit/9cc299626181048b85b629bbe7f5806a1f5d21ff)) -- handle HEAD requests on podcast_feed route - ([74b2640](https://code.castopod.org/adaures/castopod/commit/74b2640f2a25c4cd6fd8835fc492c2a6893d4950)), - closes [#79](https://code.castopod.org/adaures/castopod/issues/79) -- **home:** remove hardcoded prefix in getAllPodcasts query - ([92d5cc5](https://code.castopod.org/adaures/castopod/commit/92d5cc50a3e533875cd894dccc417918102d4b7f)) -- **housekeeping:** replace the use of GLOB_BRACE with looping over file - extensions - ([42d92d0](https://code.castopod.org/adaures/castopod/commit/42d92d0c8dfe0c567c28f5bfdda129890fa4c2ec)), - closes [#154](https://code.castopod.org/adaures/castopod/issues/154) -- **housekeeping:** set default sizes value + ignore illegal IFD size error to - proceed with script - ([f21ca57](https://code.castopod.org/adaures/castopod/commit/f21ca57603cfa503699b7e09a155e18d876d65fe)) -- **housekeeping:** use EpisodeModel's builder to reset comments count - ([65e9c0b](https://code.castopod.org/adaures/castopod/commit/65e9c0b05ea4992884149cb4a4b071bf31a20a1a)) -- **htaccess:** add ? after index.php in RewriteRule - ([d9d139e](https://code.castopod.org/adaures/castopod/commit/d9d139eefa03c28d1a064b3b32c9036193497e57)), - closes [#152](https://code.castopod.org/adaures/castopod/issues/152) -- **http-signature:** update SIGNATURE_PATTERN allowing signature keys to be - sent in any order - ([b7f285e](https://code.castopod.org/adaures/castopod/commit/b7f285e4e24247fedb94f030356fa6f291f525cc)) -- **images:** set default mimetype if none is specified when getting size info - ([6e4acc6](https://code.castopod.org/adaures/castopod/commit/6e4acc64ad256178cee7905402b48bafcd49f84c)) -- **import-with-escaped-characters:** remove \CodeIgniter\HTTP\URI in - download_file, closes - [#103](https://code.castopod.org/adaures/castopod/issues/103) - ([35b5be0](https://code.castopod.org/adaures/castopod/commit/35b5be095ff54d27acec1610a846ec0cdbdf1d65)) -- **import:** add extension when downloading file without + truncate slug if too - long - ([c5f18bb](https://code.castopod.org/adaures/castopod/commit/c5f18bb6dc08a758ff735454bbe9cfa45a68c09b)) -- **import:** add validation for handle field to prevent - Router.invalidParameterType error - ([5bf7200](https://code.castopod.org/adaures/castopod/commit/5bf7200fb390f2447b29f24b495f24483cf7b205)), - closes [#119](https://code.castopod.org/adaures/castopod/issues/119) -- **import:** cast description's SimpleXMLElement to string - ([02d17be](https://code.castopod.org/adaures/castopod/commit/02d17be4ffe229fc6657207d31eba0543b5f1a4c)) -- **import:** remove query string from files url - ([109c4aa](https://code.castopod.org/adaures/castopod/commit/109c4aa1afb72dd8b99c0302d74a7fef5a38638e)) -- **import:** save media files during podcast import + set missing media fields - ([a9989d8](https://code.castopod.org/adaures/castopod/commit/a9989d841a634f8cf6c04df25f40bb1e7d4fcdcc)) -- **import:** set default episode type if not set - ([d7250ab](https://code.castopod.org/adaures/castopod/commit/d7250ab03f9b032830c575ad58b51c8d60b7a49a)) -- **import:** set episode and season numbers to null when not present in item - tag - ([3211398](https://code.castopod.org/adaures/castopod/commit/3211398c78b1b28b76a46427ee07874bbf84a85d)) -- **import:** use tag when no is present - ([20e607a](https://code.castopod.org/adaures/castopod/commit/20e607afb755bc75056041738fa7cbf6723d754c)) -- include missing variables on public ui's episode page and remote_actions - ([193b373](https://code.castopod.org/adaures/castopod/commit/193b373bc94a5270acae99b637aa84b6cb2dedfe)) -- **input-component:** unset required attribute to prevent rendering it when - false - ([db9ac13](https://code.castopod.org/adaures/castopod/commit/db9ac13860bce58235a5da275910bea605a00626)) -- **install:** add password validation when creating super admin - ([5a2ca0c](https://code.castopod.org/adaures/castopod/commit/5a2ca0cc4ae85cc15960201c86f131cb822f714f)) -- **install:** redirect manually to install wizard on first visit - ([2ceaaca](https://code.castopod.org/adaures/castopod/commit/2ceaaca44f1b82fc64d961e2fb4f4aaeade7e736)) -- **install:** redirect to host_url install route on instanceConfig validation - error - ([99250b1](https://code.castopod.org/adaures/castopod/commit/99250b1868657c249a447399c7ebc69e00d43d1a)) -- **install:** redirect to input baseUrl after instance config - ([2426af7](https://code.castopod.org/adaures/castopod/commit/2426af7de8c9d426aaf534ff17b67f71c2e9f374)), - closes [#53](https://code.castopod.org/adaures/castopod/issues/53) -- **install:** set message block on forms to show error messages - ([3a0a20d](https://code.castopod.org/adaures/castopod/commit/3a0a20d59cdae7f166325efb750eaa6e9800ba6e)), - closes [#157](https://code.castopod.org/adaures/castopod/issues/157) -- **interact-as:** set actor_id instead of podcast id upon login event - ([5dfade7](https://code.castopod.org/adaures/castopod/commit/5dfade7cf37f339c56d2e577c679b88a1b1d9336)), - closes [#104](https://code.castopod.org/adaures/castopod/issues/104) -- **json-ld:** add missing properties to PodcastSeries object - ([e97266c](https://code.castopod.org/adaures/castopod/commit/e97266c5d4883a10f68b3685ecc0d1942f54d658)) -- keep subtitle line breaks when parsing srt file to json - ([cfb3da6](https://code.castopod.org/adaures/castopod/commit/cfb3da6592f2de23cb1a7ac420f19fc77fa338aa)) -- **layouts:** replace holy-grail layout with tailwind config + widen public - podcast layout - ([be5a287](https://code.castopod.org/adaures/castopod/commit/be5a28787fdb180b64d9bf570120eff7072ab9aa)) -- **map:** update episode markers query to discard unpublished episodes - ([b3caac4](https://code.castopod.org/adaures/castopod/commit/b3caac45b12a23e4289d00133d2ad7915d084c44)) -- **markdown-editor:** remove unnecessary buttons for podcast and episode - editors + add extensions - ([9c4f60e](https://code.castopod.org/adaures/castopod/commit/9c4f60e00bcbd4f784f12d2a6fed357ad402ee2e)) -- **md-editor:** build new markdown editor with lit + - github/markdown-toolbar-element - ([9ec1cb9](https://code.castopod.org/adaures/castopod/commit/9ec1cb93da6f41124c48b8cf14ee6942e865bede)), - closes [#93](https://code.castopod.org/adaures/castopod/issues/93) - [#94](https://code.castopod.org/adaures/castopod/issues/94) - [#120](https://code.castopod.org/adaures/castopod/issues/120) -- **migrations:** ignore invalid utf8 chars for media files metadata + update - transcript parser - ([45e8f99](https://code.castopod.org/adaures/castopod/commit/45e8f99e753cc02ec105e6f4d7fe026a205724f8)) -- minor corrections - ([13be386](https://code.castopod.org/adaures/castopod/commit/13be386842e94d9def1f7de4720931d8f6935171)) -- move analytics to helper - ([d311917](https://code.castopod.org/adaures/castopod/commit/d31191732e41aa106234b5ebe6e54ee02f0ce603)) -- move html escaping on credits page - ([fbffdbd](https://code.castopod.org/adaures/castopod/commit/fbffdbde78544c83138ee6234c62d43056f407b6)) -- **multiselect:** add missing class names in choices options for purge to work - properly - ([719538d](https://code.castopod.org/adaures/castopod/commit/719538d0ccb28af3c3c5e1a4b6468d4b772fe819)) -- **notifications:** add trigger after activities update + update insert trigger - ([e5d16e8](https://code.castopod.org/adaures/castopod/commit/e5d16e87119021fa5a43470d67ddfe5128e57f74)) -- **notifications:** notify actors after activities insert / update using model - callback methods - ([e08555a](https://code.castopod.org/adaures/castopod/commit/e08555a4e9a6c15eeba18273c63403f82eddae35)) -- **open-graph:** replace non existant episode description to podcast - description in podcast page - ([b02584e](https://code.castopod.org/adaures/castopod/commit/b02584ee609af1ad1b5680cc28208d113eb0410b)) -- overwrite common lang function to escape returned string - ([4c490c1](https://code.castopod.org/adaures/castopod/commit/4c490c15bb6642ad0b2aaddf08d8af25de99b4b0)), - closes [#196](https://code.castopod.org/adaures/castopod/issues/196) - [#198](https://code.castopod.org/adaures/castopod/issues/198) -- overwrite getActorById to return app's Actor entity - ([f2bc2f7](https://code.castopod.org/adaures/castopod/commit/f2bc2f7e01aa166faa627df6fe4d5ed4887c16e5)) -- **package.json:** update destination of postcss generation scripts - ([21413f8](https://code.castopod.org/adaures/castopod/commit/21413f8af3b8a0ac01d8c6f15bcd7a63e524e964)) -- **pages:** add locale to page cache - ([8f999ce](https://code.castopod.org/adaures/castopod/commit/8f999ce2f7ee1416c30cf58c84f67b3d11b3f142)) -- **partner:** set correct image URL - ([61554be](https://code.castopod.org/adaures/castopod/commit/61554be12a64d59ab99fab810b1b05632b408f3a)) -- pass timezone to relative time component to show the localized time in the UI - ([b9db936](https://code.castopod.org/adaures/castopod/commit/b9db936461d4cb914958bb3256bb910bbd7ba815)) -- **persons:** prevent overflow of persons list by adding horizontal scroll - ([9e8995d](https://code.castopod.org/adaures/castopod/commit/9e8995dc6e039032cc65f87895cf770f99e8b244)) -- **persons:** set person picture as optional for better ux - ([7fdea63](https://code.castopod.org/adaures/castopod/commit/7fdea63de7e572810082c84fff3013af580df58b)), - closes [#125](https://code.castopod.org/adaures/castopod/issues/125) -- **platforms:** display platform link only when visible is toggled on - ([6e503c8](https://code.castopod.org/adaures/castopod/commit/6e503c8d6182987e48892370623183f871bbd1c1)), - closes [#39](https://code.castopod.org/adaures/castopod/issues/39) -- **player-styling:** revert vite to 2.8 to reference the player css - ([e07d3af](https://code.castopod.org/adaures/castopod/commit/e07d3afea9af85b8361227e000fb64b502781668)) -- **podcast-activity:** check if transcript and chapters are set before - including them in audio - ([5855a25](https://code.castopod.org/adaures/castopod/commit/5855a250936f91641efef77650890a18d8e9917f)) -- **podcast-import:** move guid attribute declaration for Episode entity to - include slug data - ([5d02ae3](https://code.castopod.org/adaures/castopod/commit/5d02ae39908a9d743627135b372bf981134c4328)) -- **podcast:** use markdown description value for editor + set prose class to - about description - ([f304d97](https://code.castopod.org/adaures/castopod/commit/f304d97b14e0ef383509cb3bba50beb55bf701ba)), - closes [#156](https://code.castopod.org/adaures/castopod/issues/156) -- prefill description footer input when creating a new episode - ([9ea5ca3](https://code.castopod.org/adaures/castopod/commit/9ea5ca31697c70d176294f8aea37bd57d471fcf7)) -- **premium-podcasts:** display unlock button in embed when premium episode - ([ca109ba](https://code.castopod.org/adaures/castopod/commit/ca109ba3a8a08e661fd2484454b1983c3418f15d)) -- **premium-podcasts:** remove cache in unlock form + redirect to podcast if - podcast is not premium - ([242352c](https://code.castopod.org/adaures/castopod/commit/242352c4d9cd936de14e8e8a5d78ebf1287b1f95)) -- **premium-podcasts:** return different cached page when podcast is unlocked - ([b1303c5](https://code.castopod.org/adaures/castopod/commit/b1303c525517498b0edfb9885ff36e08c72628b5)) -- **pwa:** add scope to webmanifests to allow installing an app per podcast - ([74c683e](https://code.castopod.org/adaures/castopod/commit/74c683eb44398a84443ec17903c3e002bb5ea9b9)) -- **pwa:** set app display as standalone in the webmanifests - ([7aa37d2](https://code.castopod.org/adaures/castopod/commit/7aa37d24ac13a1ee160c01a56b43621d7efcfbbc)) -- re-order graph values - ([35f633b](https://code.castopod.org/adaures/castopod/commit/35f633b4c71c087d1ddc9bba9e9bbe18de09204f)) -- redirect to non cached views when authenticated in public views - ([482b47b](https://code.castopod.org/adaures/castopod/commit/482b47ba6bdab7f27fc5704a559567228e07cd14)) -- **release:** add missing version number to castopod-host package - ([8f3e9d9](https://code.castopod.org/adaures/castopod/commit/8f3e9d90c14545d3f84d4469b26a53db4554b4dc)) -- remove cache from remote follow form to display error messages - ([90e4443](https://code.castopod.org/adaures/castopod/commit/90e44437bdf37d8024ef609b2f7336dbdfc3b974)) -- remove defer from js script declaration as it is a module - ([18ae557](https://code.castopod.org/adaures/castopod/commit/18ae557e97f1cef775cd1e75fb1fedee7f1c0cc9)) -- remove fixed size from podcast sidebar + rearrange account info + space out - import radio inputs - ([776eec6](https://code.castopod.org/adaures/castopod/commit/776eec6f0d533d6c92ebec16f7a9dbfcde1f41f4)) -- remove heavy image cover data from audio file metadata - ([f74403b](https://code.castopod.org/adaures/castopod/commit/f74403bd7a5089b760603abe36264e7615be0e78)) -- remove required for other_categories field and add podcast_id to latest - podcasts query - ([5417be0](https://code.castopod.org/adaures/castopod/commit/5417be0049288489a19c7b575aa77bd1e2bc0243)) -- remove required property to persons picture - ([c546be3](https://code.castopod.org/adaures/castopod/commit/c546be385b243014243ae93356006cd126d2f00d)), - closes [#125](https://code.castopod.org/adaures/castopod/issues/125) -- remove value escaping for form inputs and textareas - ([bc6dea2](https://code.castopod.org/adaures/castopod/commit/bc6dea2f8ad1cf0aee0eaa93151332fbac7fb771)) -- rename field status to task_status to get scheduled activities - ([4ff82a5](https://code.castopod.org/adaures/castopod/commit/4ff82a5f0a38dbbc9e272fca7df70ea5a190e334)) -- rename issue_templates labels - ([9f00305](https://code.castopod.org/adaures/castopod/commit/9f00305844e5a168e89d727fe29892b4ad5e48d6)) -- rename MyAccount controller file - ([e109df3](https://code.castopod.org/adaures/castopod/commit/e109df3004a3a98d72de39532e062fff9917f50f)), - closes [#60](https://code.castopod.org/adaures/castopod/issues/60) -- rename podcast name to podcast handle to clarify field usage - ([9dd4c77](https://code.castopod.org/adaures/castopod/commit/9dd4c7741eb1b7cb5fc214ff674697f3aa986df0)), - closes [#126](https://code.castopod.org/adaures/castopod/issues/126) -- reorder fields as composite primary keys for analytics tables - ([9660aa9](https://code.castopod.org/adaures/castopod/commit/9660aa97c8ffd4fe61f3a388d52b9ac5dd8e1d63)) -- replace deletedField with published_at for episodes - ([14d7d07](https://code.castopod.org/adaures/castopod/commit/14d7d078225cdc8980759273a5dc4163d9f84b06)) -- replace getWebEnclosureUrl with getEnclosureWebUrl - ([8122cea](https://code.castopod.org/adaures/castopod/commit/8122ceaf8a70050f14b3078f28b024e7d7cdb9ac)) -- replace hardcoded style links with vite service + set default value for remote - transcript url - ([3f2e056](https://code.castopod.org/adaures/castopod/commit/3f2e05608e43d47bbb518a9acfaf56ec3eefafb4)), - closes [#149](https://code.castopod.org/adaures/castopod/issues/149) - [#150](https://code.castopod.org/adaures/castopod/issues/150) -- replace website key for webpages in breadcrumb translate file - ([50e32ff](https://code.castopod.org/adaures/castopod/commit/50e32ff75636c1d4c5d945a267e884cb26ad7191)) -- restore default podcast icon on public website - ([342778b](https://code.castopod.org/adaures/castopod/commit/342778bac3c684328d72633961df1a2ebdc1330e)) -- revert to beta.1's codeigniter4 version - ([e831411](https://code.castopod.org/adaures/castopod/commit/e83141127080ccde44987195db46ba97fd6cc2ca)) -- rewrite regenerate image function to use saveSizes method from Image entity - ([3889912](https://code.castopod.org/adaures/castopod/commit/38899124ec27e94a8c798bc2db528f9f785eec20)) -- **router:** check if Accept header is set before getting value - ([10a2ae0](https://code.castopod.org/adaures/castopod/commit/10a2ae02484672d6a0fbc6e7b943519c5ec16cb6)), - closes [#228](https://code.castopod.org/adaures/castopod/issues/228) -- **router:** trim URI slash to match same routes for URIs with and without - trailing slash - ([9e9375f](https://code.castopod.org/adaures/castopod/commit/9e9375f9a2cd6102f827b36ec521f4c86a557c00)) -- **rss-import:** add Castopod user-agent, handle redirects for downloaded - files, add Content namespace - ([214243b](https://code.castopod.org/adaures/castopod/commit/214243b3fec4937e45ef1ceaba1149004cdf3b44)) -- **rss:** cast number type values to string in rss_helper - ([7180ae9](https://code.castopod.org/adaures/castopod/commit/7180ae9ec700930b69c04ed91f8eceea16ad77ce)), - closes [#148](https://code.castopod.org/adaures/castopod/issues/148) -- **rss:** do not escape podcast and episode titles in the xml - ([0dd3b7e](https://code.castopod.org/adaures/castopod/commit/0dd3b7e0bf00d5a9eb80c93cba1efcada59ec3c1)), - closes [#138](https://code.castopod.org/adaures/castopod/issues/138) - [#71](https://code.castopod.org/adaures/castopod/issues/71) -- **rss:** remove escaping for publisher and owner name - ([6fc6347](https://code.castopod.org/adaures/castopod/commit/6fc6347846c126618cb7ff50164181650308d0c0)) -- **rss:** round episode durations and soundbites - ([c9fb987](https://code.castopod.org/adaures/castopod/commit/c9fb987fcfbe17069ec68fdbc823777079ce574b)), - closes [#214](https://code.castopod.org/adaures/castopod/issues/214) -- **rss:** set ❬itunes:author❭ tag to owner_name if publisher not specified - ([2271c14](https://code.castopod.org/adaures/castopod/commit/2271c1445b1ded12bc53b5d23b5e59d12b17c71a)), - closes [#96](https://code.castopod.org/adaures/castopod/issues/96) -- **rss:** use originalPath instead of originalMediaPath in Image library - ([b4012b7](https://code.castopod.org/adaures/castopod/commit/b4012b7d2ed6b34b69ad767570dd33f0dc7db920)) -- save transcript and chapters files to podcasts folder - ([63f49c7](https://code.castopod.org/adaures/castopod/commit/63f49c719f672b615c5a8893d3868dffcd332e47)) -- **search-episodes:** add fallback sql query using LIKE for search query with - less than 4 characters - ([e66bf44](https://code.castopod.org/adaures/castopod/commit/e66bf44341175bc5a10fbf7dfa00b351e76136c2)), - closes [#236](https://code.castopod.org/adaures/castopod/issues/236) -- **security:** add csrf filter + prevent xss attacks by escaping user input - ([cd2e1e1](https://code.castopod.org/adaures/castopod/commit/cd2e1e1dc37c53d32d00971c451c4800b8fd6107)) -- set cache expiration to next note publish to show note on publication date - ([0a66de3](https://code.castopod.org/adaures/castopod/commit/0a66de3e6c17d4ac94ee8e13bd00ceaf64b1303e)) -- set episode description footer to null when empty value - ([3a7d97d](https://code.castopod.org/adaures/castopod/commit/3a7d97d660046d80698611311ff3708110d2af82)) -- set episode duration translation to hardcoded english - ([c39efc9](https://code.castopod.org/adaures/castopod/commit/c39efc9489180662edcebd142d4476c0617ea97f)), - closes [#64](https://code.castopod.org/adaures/castopod/issues/64) -- set episode guid upon episode creation - ([ad8b153](https://code.castopod.org/adaures/castopod/commit/ad8b153f2a3b1a3b1751bf63785c4950e1516e6b)), - closes [#48](https://code.castopod.org/adaures/castopod/issues/48) -- set episode numbers during import + remove all custom form_helpers + minor ui - issues - ([99a3b8d](https://code.castopod.org/adaures/castopod/commit/99a3b8d33e00482da50dd62bdaa9215a351a56e4)) -- set interact_as_actor for user upon password reset - ([ad8f5f5](https://code.castopod.org/adaures/castopod/commit/ad8f5f5a0fac7b0b9cc10a0b86200f014aca7553)), - closes [#178](https://code.castopod.org/adaures/castopod/issues/178) -- set localized slug_field key as string in french language - ([17fb29b](https://code.castopod.org/adaures/castopod/commit/17fb29b20993b7deee4e252e0e3a4a2459ee0d98)) -- set location to null when getting empty string - ([71b1b5f](https://code.castopod.org/adaures/castopod/commit/71b1b5f775af475b1dc78328330e277f565e41b6)) -- set storage limit as disk_total_space instead of free space - ([7512e2e](https://code.castopod.org/adaures/castopod/commit/7512e2ed1ff5656cd63a4fc2524296dbb8b4164a)) -- **settings:** add .jpg extension to site-icon file input to display all jpeg - images - ([f611a16](https://code.castopod.org/adaures/castopod/commit/f611a16cd0c1a389e1c5a287eaec9d2a927a4bb6)) -- **socialinteract:** move social interact uri into uri attribute + update - social data upon import - ([12b2200](https://code.castopod.org/adaures/castopod/commit/12b22008a237185cb736fc29352fab22421dad16)) -- sort episodes by published_at with unpublished episodes at the begining - ([1686f84](https://code.castopod.org/adaures/castopod/commit/1686f840d16f2bd3d71d7f222a59b8e6a838fd6e)), - closes [#249](https://code.castopod.org/adaures/castopod/issues/249) -- sort episodic podcasts by season - ([d7b6794](https://code.castopod.org/adaures/castopod/commit/d7b6794f68f9a01fd606a407c6eb4c12d15dee74)) -- **themes:** update themes stylesheet route and remove css extension - ([e4e7e00](https://code.castopod.org/adaures/castopod/commit/e4e7e0005e931967dd6162588f1c5913dbf4603e)) -- **types:** update fake seeders types + fix bugs - ([76a4bf3](https://code.castopod.org/adaures/castopod/commit/76a4bf344160df679db29e236e7df7822970fb60)) -- **ui:** remove empty tooltip when hovering on sponsor button - ([40aa661](https://code.castopod.org/adaures/castopod/commit/40aa661289e1d1517fffcea5d257183bc9c458e4)) -- unpublish episode before deleting it + add validation step before deletion - ([f75bd76](https://code.castopod.org/adaures/castopod/commit/f75bd76458eeb01a2d37912695e33f77d03b7a69)), - closes [#112](https://code.castopod.org/adaures/castopod/issues/112) - [#55](https://code.castopod.org/adaures/castopod/issues/55) -- update .htaccess for shared hosting config - ([2379826](https://code.castopod.org/adaures/castopod/commit/2379826352e2f4b5060910bf9f29268610102f2e)) -- update broken contributor dropdown fields - ([e5b7515](https://code.castopod.org/adaures/castopod/commit/e5b75150234bd7f19e01def93425d3bda7379dd3)) -- update condition in AnalyticsTrait - ([fbc0967](https://code.castopod.org/adaures/castopod/commit/fbc0967caa81630d514ddb1b93b0834ebb4d913b)) -- update condition in home controller to redirect to install page - ([33f1b91](https://code.castopod.org/adaures/castopod/commit/33f1b91d55dd0652c979d50fc85879dbf88a4a42)) -- update conditions when checking for empty max_episodes and season_number - ([fbad0b5](https://code.castopod.org/adaures/castopod/commit/fbad0b59f68c65eba2fdcd5a8d3b312b622e9a45)) -- update form_textarea to prevent escaping value - ([78548b5](https://code.castopod.org/adaures/castopod/commit/78548b5cd75ea7d6688d1945ff5449ea4f6bec68)) -- update iso-369 language table seeder - ([0c90db4](https://code.castopod.org/adaures/castopod/commit/0c90db44c40de5af5b0b32b54489bda9424d9ef6)) -- update ivoox podcasting icon - ([f2b69a4](https://code.castopod.org/adaures/castopod/commit/f2b69a47339c887f57883ec612f3d200e512ac1c)) -- update MarkdownEditor component + restyle Button and other components - ([b05d177](https://code.castopod.org/adaures/castopod/commit/b05d177f1b7f44fef043ac5eb41f07133a2cf52d)) -- update purgecss content path for php helper files - ([eb70bb4](https://code.castopod.org/adaures/castopod/commit/eb70bb4f7078ff347aeb8f5dcc7896311d289466)), - closes [#59](https://code.castopod.org/adaures/castopod/issues/59) -- update translations for settings' tasks to include what they should be used - for - ([06b1a8b](https://code.castopod.org/adaures/castopod/commit/06b1a8b29b6ce5d81c5570d250bdac4e0c9ee5ca)) -- use slash instead of backslash to call layout - ([a80adb2](https://code.castopod.org/adaures/castopod/commit/a80adb22958fc0a38374cbce2d950a0042e699eb)) -- use UTC_TIMESTAMP() to get current utc date instead of NOW() in sql queries - ([4e22a0d](https://code.castopod.org/adaures/castopod/commit/4e22a0d5e4b60941d41071f059aac80cbaf38fbf)) -- **users:** remove required roles input when editing user + prevent owner's - roles from being edited - ([1c8af75](https://code.castopod.org/adaures/castopod/commit/1c8af7550ba27d8c8473ae96acd21ad7731fd863)), - closes [#239](https://code.castopod.org/adaures/castopod/issues/239) -- **ux:** allow for empty message upon episode publication and warn user on - submit - ([33d01b8](https://code.castopod.org/adaures/castopod/commit/33d01b8d4fd6ebf24e9f011aa705c456c846956c)), - closes [#129](https://code.castopod.org/adaures/castopod/issues/129) -- **ux:** have podcast dashboard card link to podcast dashboard if only one - podcast in instance - ([7dabee5](https://code.castopod.org/adaures/castopod/commit/7dabee58a187abe92358d962da506a836e29cda3)) -- **ux:** redirect user to install page on database error in home page - ([9017e30](https://code.castopod.org/adaures/castopod/commit/9017e30bf41bed8c2be65091bbc5fb1e63aef87a)) -- validate slug length when submitting episode form + clean permalink edit - prefix - ([b07ac09](https://code.castopod.org/adaures/castopod/commit/b07ac093b2cae646f9a897bc9dfeeaef6eda6561)) -- **video-clips:** check if created video exists before recreating it and - failing - ([dff1208](https://code.castopod.org/adaures/castopod/commit/dff12087251b2b89e195604202094b5ddd9a0936)) -- **video-clips:** clear video clip cache after process has finished - ([3ae6232](https://code.castopod.org/adaures/castopod/commit/3ae62325856f6ff331a5d9ed901b9fa097ca7055)) -- **video-clips:** create unique temporary files for resources to be deleted - after generation - ([7f7c878](https://code.castopod.org/adaures/castopod/commit/7f7c878cb6ecf7b4a967b2af87da82bc6593081e)) -- **video-clips:** set audio codec to aac, fixing audio issue on twitter - ([3c22c68](https://code.castopod.org/adaures/castopod/commit/3c22c68ee81f77bd7fcf7e2739ee6af016407843)) -- **video-clips:** set longer podcast and episode lengths for squared format - ([c030113](https://code.castopod.org/adaures/castopod/commit/c0301134c2048dc29eb2b995e4d5c22c49444100)) -- **video-clips:** tweak portrait parameters to have subtitles display without - overflowing - ([2385b1a](https://code.castopod.org/adaures/castopod/commit/2385b1a2926d1344569836e18cb30adb4c604664)) -- **video-clips:** update condition to check if ffmpeg is installed - ([b57f0b6](https://code.castopod.org/adaures/castopod/commit/b57f0b6eb65dccf22cb4d55f93d18ca36857d7fc)), - closes [#163](https://code.castopod.org/adaures/castopod/issues/163) -- **xml-editor:** escape xml editor's content + restyle form sections to prevent - overflowing - ([588590b](https://code.castopod.org/adaures/castopod/commit/588590bd2c0346e2465ff8f1930580d76a3bf068)) -- **xml-editor:** prettify xml even without root node - ([ca55c24](https://code.castopod.org/adaures/castopod/commit/ca55c248d0562a8529071c1f10be12f40ef50dda)) - -### Features - -- **activitypub:** add Podcast actor and PodcastEpisode object with comments - ([9e1e5d2](https://code.castopod.org/adaures/castopod/commit/9e1e5d2e862d6a3345d11ca7f96b955c76bfa013)) -- add about page in admin with instance info + database update button - ([d0836f3](https://code.castopod.org/adaures/castopod/commit/d0836f3ee360a836f815c59ea755f288501dc517)) -- add alternate rss feed link tag to podcast page head - ([a973c09](https://code.castopod.org/adaures/castopod/commit/a973c097d54a3d0186c4079b9d4d3e81aae38505)), - closes [#35](https://code.castopod.org/adaures/castopod/issues/35) -- add analytics and unknown useragents - ([ec92e65](https://code.castopod.org/adaures/castopod/commit/ec92e65aa42e09b1df04600b52a0c679dfc494bb)) -- add audio-clipper toolbar + add video-clip-previewer - ([0255753](https://code.castopod.org/adaures/castopod/commit/02557539e6eb48fc23ee2ee3b0c75aee3310965b)) -- add audio-clipper webcomponent (wip) - ([21d4251](https://code.castopod.org/adaures/castopod/commit/21d4251b9bcd5acb0f8a1761bc4edc34a3dbc228)) -- add autofocus to input field "Email or username" on login page - ([19caed4](https://code.castopod.org/adaures/castopod/commit/19caed4bce0daab9ccf6ab9645f44b60eb87de88)) -- add basic stats on podcast about page - ([1670558](https://code.castopod.org/adaures/castopod/commit/1670558473dba47219d470ff21d6224db6ab42ba)) -- add breadcrumb in admin area - ([7fb1de2](https://code.castopod.org/adaures/castopod/commit/7fb1de2cf3c97c4cd7afe3bd71bbe66041786ecd)), - closes [#17](https://code.castopod.org/adaures/castopod/issues/17) -- add cache to ActivityPub sql queries + cache activity and note pages - ([2d297f4](https://code.castopod.org/adaures/castopod/commit/2d297f45b3d7ef6e8711875a0b9b908e878115fa)) -- add CDN url - ([972bcbf](https://code.castopod.org/adaures/castopod/commit/972bcbf65ee119b8641ca3c4e5c0e8cf9ca8dd4f)), - closes [#37](https://code.castopod.org/adaures/castopod/issues/37) -- add codemirror to display xml editor for custom rss field - ([f15f262](https://code.castopod.org/adaures/castopod/commit/f15f26240cd5311fa9d07779f364b6639a501dec)) -- add cumulative listening time charts - ([588b4d2](https://code.castopod.org/adaures/castopod/commit/588b4d28da00bc12d02126e23181690f54d81716)) -- add default icons to Alert component - ([0d98001](https://code.castopod.org/adaures/castopod/commit/0d9800123b135e4fa1a2acd14a5e039c12174333)) -- add DropdownMenu component + remove global audio player in admin - ([abb7fba](https://code.castopod.org/adaures/castopod/commit/abb7fbac276d77b7d31a0aeba75d464f3ba3ad46)) -- add episode_numbering() component helper to display episode and season numbers - ([3f4a6bd](https://code.castopod.org/adaures/castopod/commit/3f4a6bd0b9f870f16107a41b102b6bf734868198)) -- add french translation - ([196920d](https://code.castopod.org/adaures/castopod/commit/196920d62f1810b4c35f800d17d7f93627319091)) -- add heading component + update ecs rules to fix views - ([23bdc6f](https://code.castopod.org/adaures/castopod/commit/23bdc6f8e36b7e8dfbe32755a54dea59ad913432)) -- add housekeeping task to run after migrations - ([89dee41](https://code.castopod.org/adaures/castopod/commit/89dee41d583e57251ea9315402a757f03571d7ad)) -- add install wizard form to bootstrap database and create the first superadmin - user - ([cba871c](https://code.castopod.org/adaures/castopod/commit/cba871c5df9f7120c44d9952456ebbd0d220669e)), - closes [#2](https://code.castopod.org/adaures/castopod/issues/2) -- add instructions on production error page to ease Castopod debugging process - ([9eab54e](https://code.castopod.org/adaures/castopod/commit/9eab54e0853ccb8300d9f9b743cd84aefbf06549)), - closes [#224](https://code.castopod.org/adaures/castopod/issues/224) -- add ISO 3166 country codes - ([97cd94b](https://code.castopod.org/adaures/castopod/commit/97cd94b47494b66faf43fbbe0748872da80020a4)) -- add js audio player on podcast, admin and embeddable player pages + fix admon - episodes ux - ([0e14eb4](https://code.castopod.org/adaures/castopod/commit/0e14eb4d3f526b0fd256a6144f3fbfc3fe52a357)), - closes [#131](https://code.castopod.org/adaures/castopod/issues/131) -- add label to sponsor button on podcast page - ([c29c018](https://code.castopod.org/adaures/castopod/commit/c29c018c7a543fc9398b5d7d11f086123e2b33f2)), - closes [#162](https://code.castopod.org/adaures/castopod/issues/162) -- add legalNoticeURL to app config for setting an external url to legal notice - ([711843a](https://code.castopod.org/adaures/castopod/commit/711843a0c81e1e2ec7a015431786df4ef32d5092)) -- add lock podcast according to the Podcastindex podcast-namespace to prevent - unauthozized import - ([72b3012](https://code.castopod.org/adaures/castopod/commit/72b301272e0b70ded3e2b237391909e3f152ad0b)) -- add map analytics, add episodes analytics, clean analytics page layout, - translate countries - ([07eae83](https://code.castopod.org/adaures/castopod/commit/07eae83a00d860e149359fae67d549488403d88b)) -- add media entity and link documents, images and audio files to it - ([6ecf286](https://code.castopod.org/adaures/castopod/commit/6ecf2866cfcde31a0840f15c3340808ce14b44cf)) -- add notifications inbox for actors - ([999999e](https://code.castopod.org/adaures/castopod/commit/999999e3efab7b1aad7568e4fd114dc7bac04f38)), - closes [#215](https://code.castopod.org/adaures/castopod/issues/215) -- add Noto Sans Mono font to use for durations + button to access new video clip - form in list - ([7609bb6](https://code.castopod.org/adaures/castopod/commit/7609bb60330539aa91bfdafbb35c2d585624218a)) -- add npm for js dependencies + move src/ files to root folder - ([cbb83a6](https://code.castopod.org/adaures/castopod/commit/cbb83a6f308ac9357e9fb0cca5edae9d3fee5b48)) -- add Open Graph and Twitter meta tags - ([af970b8](https://code.castopod.org/adaures/castopod/commit/af970b8bac949e4c63047e04aca1b7403a4e8deb)), - closes [#41](https://code.castopod.org/adaures/castopod/issues/41) -- add pages table to store custom instance pages (eg. legal-notice, cookie - policy, etc.) - ([9c224a8](https://code.castopod.org/adaures/castopod/commit/9c224a8ac6dd95f3c6c087a300fc8bac48e8090f)), - closes [#24](https://code.castopod.org/adaures/castopod/issues/24) -- add permanent delete feature for podcasts 🎉 - ([dbb4030](https://code.castopod.org/adaures/castopod/commit/dbb4030da49f9ea1f61759fb7c66d71fc29ea4a1)), - closes [#89](https://code.castopod.org/adaures/castopod/issues/89) -- add platform models - ([a333d29](https://code.castopod.org/adaures/castopod/commit/a333d291966229a909c0851fd8b890ed97c48ceb)) -- add platforms form in podcast settings - ([043f49c](https://code.castopod.org/adaures/castopod/commit/043f49c784bc007ca0fa756ca4ed2d3b08843ad9)) -- add platforms tables - ([ce59344](https://code.castopod.org/adaures/castopod/commit/ce5934419a516c9926dd3fd0ace3c11a95b60722)) -- add podcast banner field for each podcast + refactor images configuration - ([4a8147b](https://code.castopod.org/adaures/castopod/commit/4a8147bfbbd98d9badfc57a0f2a18bdd5812e802)) -- add premium podcasts to manage subscriptions for premium episodes - ([3234500](https://code.castopod.org/adaures/castopod/commit/3234500e2d967438ad140f65da801a543f43775d)), - closes [#193](https://code.castopod.org/adaures/castopod/issues/193) -- add publish feature for podcasts and set draft by default - ([3d363f2](https://code.castopod.org/adaures/castopod/commit/3d363f2efe99836ac05c305a2fa683e342f06561)), - closes [#128](https://code.castopod.org/adaures/castopod/issues/128) - [#220](https://code.castopod.org/adaures/castopod/issues/220) -- add remote_url alternative for transcript and chapters files - ([3143c9a](https://code.castopod.org/adaures/castopod/commit/3143c9ad36e4cf1364205cf2be39c0c96f80fdd2)) -- add replied to post or comment to reply element - ([d0f9c60](https://code.castopod.org/adaures/castopod/commit/d0f9c6018f1af527099f3e26b5d824710fa11caf)) -- add schema.org json-ld objects to podcasts, episodes, posts and comments pages - ([902f959](https://code.castopod.org/adaures/castopod/commit/902f959b30a10839684f093eb86edebc5d826a0b)) -- add task to housekeeping setting for resetting all instance counts - ([9303e51](https://code.castopod.org/adaures/castopod/commit/9303e51bc50d730a8026f58984e83b840360ee88)) -- add unique listeners analytics - ([3a49258](https://code.castopod.org/adaures/castopod/commit/3a4925816f3268230640525ad7af507aab8eecb9)) -- add update rss feed feature for podcasts to import their latest episodes - ([5eb9dc1](https://code.castopod.org/adaures/castopod/commit/5eb9dc168eb9af04767829b76242c9120f55d46d)), - closes [#183](https://code.castopod.org/adaures/castopod/issues/183) -- add user permissions and basic groups to handle authorizations - ([d58e518](https://code.castopod.org/adaures/castopod/commit/d58e51874a4722921b75b0049117015c2380406e)), - closes [#3](https://code.castopod.org/adaures/castopod/issues/3) - [#18](https://code.castopod.org/adaures/castopod/issues/18) -- add WebSub module for pushing feed updates to open hubs - ([10d3f73](https://code.castopod.org/adaures/castopod/commit/10d3f73786ba141e27a822b2585c4a244ee92c14)) -- **admin:** add instance wide dashboard with storage and bandwidth usage - ([b1a6c02](https://code.castopod.org/adaures/castopod/commit/b1a6c02e56fdc01a7ff69fa7e7dd8ea71380b7ba)), - closes [#216](https://code.castopod.org/adaures/castopod/issues/216) -- **admin:** add search form in podcast episodes list - ([6be5d12](https://code.castopod.org/adaures/castopod/commit/6be5d12877342a7c56e25ea8dd15a975c6ce45ac)), - closes [#26](https://code.castopod.org/adaures/castopod/issues/26) -- **admin:** make header stick on scroll and show title + action buttons using - css only - ([d60498c](https://code.castopod.org/adaures/castopod/commit/d60498c1beb970a14eeb3bbe02d1b1d8116624b0)) -- **admin:** update admin layout for better ux + update brand pine colors - ([d86142e](https://code.castopod.org/adaures/castopod/commit/d86142ebe7cd7582835f180b79fbeaaaba703528)) -- allow cross origin requests on episode comments - ([e12f95a](https://code.castopod.org/adaures/castopod/commit/e12f95aca13c6d54489a9cfd99d4cd2490fe83ab)) -- **analytics-gdpr:** update cached personal data to expire at midnight - ([0188b67](https://code.castopod.org/adaures/castopod/commit/0188b67354a756f0c926edd7b46623ab5b20c12b)) -- **analytics:** add 'other' group to pie charts in order to display more - accurate data - ([73acef9](https://code.castopod.org/adaures/castopod/commit/73acef933ff3485987afc5157de022910876fc12)) -- **analytics:** add charts and data export - ([78625c4](https://code.castopod.org/adaures/castopod/commit/78625c471b4f03a09bd42f72b82217e1f2d01cef)) -- **analytics:** add current date and secret salt to analytics hash for improved - privacy - ([6f2e7c0](https://code.castopod.org/adaures/castopod/commit/6f2e7c009c24830d4f08633bfbde3b75f40bf215)) -- **analytics:** add service name from rss user-agent - ([7202b98](https://code.castopod.org/adaures/castopod/commit/7202b9867bd59aafa8c338a4230fb5e5c55b24c6)) -- **analytics:** add weekday and hour bar charts - ([8ab3132](https://code.castopod.org/adaures/castopod/commit/8ab313296bb4a254ab05e90b17d896039839b784)) -- **api:** add rest api with podcasts read endpoints - ([e64001d](https://code.castopod.org/adaures/castopod/commit/e64001d00604bcf587ec5e9a631282f212df450d)), - closes [#210](https://code.castopod.org/adaures/castopod/issues/210) -- apply colour theme to embed player - ([9548337](https://code.castopod.org/adaures/castopod/commit/9548337a7c49879e8b58c2dfece46e3cfc9517eb)), - closes [#201](https://code.castopod.org/adaures/castopod/issues/201) -- **auth:** add auth.enable2FA config to enable two-factor authentication - ([7213ed2](https://code.castopod.org/adaures/castopod/commit/7213ed290c977ce8723f6d92addadc03913576ee)) -- build hashed static files to renew browser cache - ([37c54d2](https://code.castopod.org/adaures/castopod/commit/37c54d247749bdf8f528babd4a78f24d48051063)), - closes [#107](https://code.castopod.org/adaures/castopod/issues/107) -- **cache:** add podcast and episode pages to cache + clear them after insert or - update - ([da0f047](https://code.castopod.org/adaures/castopod/commit/da0f0472819007e02e5da37399f2377772c618b9)) -- **categories:** create model, entity, migrations and seeds - ([f73b042](https://code.castopod.org/adaures/castopod/commit/f73b042cc091be82abdbbca8992080875d526972)) -- **clips:** setup clip entities and model + save video clip to have it - generated in the background - ([2f6fdf9](https://code.castopod.org/adaures/castopod/commit/2f6fdf9091d52ca49709fc82621ba1c6dd0e817d)) -- **comments:** add comments to episodes + update naming of status to post - ([bb4752c](https://code.castopod.org/adaures/castopod/commit/bb4752c35e086664f5fd75fdc0d56546a1e356f6)) -- **comments:** add like / undo like to comment + add comment page - ([0c187ef](https://code.castopod.org/adaures/castopod/commit/0c187ef7a9278a60bcc6e5ee4d69d948b51e5c54)) -- **components:** add custom view renderer with ComponentRenderer adapted from - bonfire2 - ([a95de8b](https://code.castopod.org/adaures/castopod/commit/a95de8bab010f6b01c598da72191abe97e473687)) -- create optimized & resized images upon upload - ([02e4441](https://code.castopod.org/adaures/castopod/commit/02e4441f98f27e9534e5b9b63279153d14632ccd)), - closes [#6](https://code.castopod.org/adaures/castopod/issues/6) -- **custom-rss:** add custom xml tag injection in rss feed for ❬channel❭ and - ❬item❭ - ([6ecdaad](https://code.castopod.org/adaures/castopod/commit/6ecdaad911d06b7f7a2b7d24710968c7eb9118f6)) -- **datetime-picker:** set material_green theme to flatpickr - ([3ce6541](https://code.castopod.org/adaures/castopod/commit/3ce6541003260677e722a916ad6bc83ef47c4371)) -- **devcontainer:** add devcontainer settings for dev environment - ([69e7266](https://code.castopod.org/adaures/castopod/commit/69e72667365247b63430dee88194e8f0d7c28edc)) -- display castopod version in admin footer - ([9f2574e](https://code.castopod.org/adaures/castopod/commit/9f2574e6fbb61dac4e1a4252dff30017685da5f0)), - closes [#68](https://code.castopod.org/adaures/castopod/issues/68) -- display legal disclaimer and warning on podcast import page - ([2f07992](https://code.castopod.org/adaures/castopod/commit/2f07992e5508b34b91f194eebfac80c51e80e90a)), - closes [#34](https://code.castopod.org/adaures/castopod/issues/34) -- edit + delete podcast and episode - ([ac5f0c7](https://code.castopod.org/adaures/castopod/commit/ac5f0c732806e955c01e05b7867801bc938c6bd5)) -- **embeddable-player:** add embeddable player widget - ([141788f](https://code.castopod.org/adaures/castopod/commit/141788fa089f9dedc8956c64ca515a4a4625f904)) -- enhance admin ui with responsive design and ux improvements - ([2d44b45](https://code.castopod.org/adaures/castopod/commit/2d44b457a02205d2e7da258d7029b8bc5da39533)), - closes [#31](https://code.castopod.org/adaures/castopod/issues/31) - [#9](https://code.castopod.org/adaures/castopod/issues/9) -- enhance ui using javascript in admin area - ([c0e66d5](https://code.castopod.org/adaures/castopod/commit/c0e66d5f7012026e145d106f4d6bd3ba792a1b77)) -- **episode-unpublish:** remove episode comments upon unpublish - ([78acd7f](https://code.castopod.org/adaures/castopod/commit/78acd7f5c057c82507d801c424040296dbaba586)) -- **episode:** add form to allow editing episode's publication date to a past - date - ([d783d16](https://code.castopod.org/adaures/castopod/commit/d783d16eb73d3f896a3dea39a766b4e963e53abf)), - closes [#97](https://code.castopod.org/adaures/castopod/issues/97) -- **episodes:** add create form and view pages for episode - ([f3b2c8b](https://code.castopod.org/adaures/castopod/commit/f3b2c8b84f3d93bef734e34dbe8ed729535e45e9)), - closes [#1](https://code.castopod.org/adaures/castopod/issues/1) -- **episodes:** add migrations, model and entity for episodes table - ([0444821](https://code.castopod.org/adaures/castopod/commit/044482174ede555ce19a2d8c6f48771cc8e7d27b)) -- **episodes:** replace all audio file URL parameters with base64 encoded data - ([e1f65cd](https://code.castopod.org/adaures/castopod/commit/e1f65cd3b53353a30d4ab6eb5312393cf04a1676)) -- **episodes:** replace soft delete with permanent delete - ([eb9ff52](https://code.castopod.org/adaures/castopod/commit/eb9ff522c25af8ceb2ed08614b581757ee791d42)) -- **episodes:** schedule episode with future publication_date by using cache - expiration time - ([4f1e773](https://code.castopod.org/adaures/castopod/commit/4f1e773c0f9e4c2597f6c1b0a4773dfb34b2f203)), - closes [#47](https://code.castopod.org/adaures/castopod/issues/47) -- **fediverse:** implement activitypub protocols + update user interface - ([2f525c0](https://code.castopod.org/adaures/castopod/commit/2f525c0f6e44d320bff16e22c223481923ba683e)), - closes [#69](https://code.castopod.org/adaures/castopod/issues/69) - [#65](https://code.castopod.org/adaures/castopod/issues/65) - [#85](https://code.castopod.org/adaures/castopod/issues/85) - [#51](https://code.castopod.org/adaures/castopod/issues/51) - [#91](https://code.castopod.org/adaures/castopod/issues/91) - [#92](https://code.castopod.org/adaures/castopod/issues/92) - [#88](https://code.castopod.org/adaures/castopod/issues/88) -- **fonts:** replace Montserrat with Inter for better readablity - ([bfa11d0](https://code.castopod.org/adaures/castopod/commit/bfa11d007d04b8ac714c8cf3b8050a6aaf177a26)) -- **GDPR:** add GDPR.yml file to public/.well-known/ - ([86bccc3](https://code.castopod.org/adaures/castopod/commit/86bccc3d5cc9562b89196f1766ac91cdc8ad786d)) -- **gdpr:** add purpose for granting access to premium content - ([47d6d81](https://code.castopod.org/adaures/castopod/commit/47d6d81b798ec3ed467e0f4339c98c8a6b80cecd)) -- **home:** sort podcasts by recent activity + add dropdown menu to choose - between sorting options - ([7b89da6](https://code.castopod.org/adaures/castopod/commit/7b89da6106c150708782d39ed2742fe416c41e89)), - closes [#164](https://code.castopod.org/adaures/castopod/issues/164) -- **housekeeping:** add clear_cache option to flush redis or files cache - ([99bfac0](https://code.castopod.org/adaures/castopod/commit/99bfac0b428a4bc6fe8bfd10a355dfd93f42ba5c)) -- **i18n:** add 7 new languages + update german translations - ([d021abb](https://code.castopod.org/adaures/castopod/commit/d021abb52f5525d93810e25df2b453c918d7bc8b)) -- **i18n:** add german language as supported locale + create Language files from - english source - ([c220b31](https://code.castopod.org/adaures/castopod/commit/c220b310ed59cad188af044b1fed0c39efc7da5b)) -- **i18n:** add Norwegian Nynorsk to supported locales - ([ced61fc](https://code.castopod.org/adaures/castopod/commit/ced61fc2364f954c1f6e0208b572faf5741498a8)) -- **i18n:** add Polish translation - ([2d83b44](https://code.castopod.org/adaures/castopod/commit/2d83b44add9e4e00766a1f326377ed892f48ad73)) -- **i18n:** add Spanish to supported locales - ([e340b54](https://code.castopod.org/adaures/castopod/commit/e340b54a84d7dcdf9ba910fe7ff39c453fac0968)) -- **i18n:** add support for German and Brazilian Portuguese languages - ([c9b9fe4](https://code.castopod.org/adaures/castopod/commit/c9b9fe4ee893de9a1df7f8269c39d08a90d205d6)) -- **i18n:** add support for Simplified Chinese (zh-Hans) and Catalan (ca) - locales - ([48d1443](https://code.castopod.org/adaures/castopod/commit/48d14434727c3310a391160c7af02c56b7e20425)) -- **icons:** add default icons for podcasting, social and funding platforms + - remove complex icons - ([5bcdfeb](https://code.castopod.org/adaures/castopod/commit/5bcdfebe6489b5d6b90f3c828b014ec4e9a7e7e1)), - closes [#166](https://code.castopod.org/adaures/castopod/issues/166) - [#167](https://code.castopod.org/adaures/castopod/issues/167) - [#170](https://code.castopod.org/adaures/castopod/issues/170) -- **icons:** add podnews icon to podcasting platforms - ([5f42355](https://code.castopod.org/adaures/castopod/commit/5f423557c2b78fd7c38c5e0caab6c6c80d21e36e)), - closes [#190](https://code.castopod.org/adaures/castopod/issues/190) -- import podcast from an rss feed url - ([9a5d5a1](https://code.castopod.org/adaures/castopod/commit/9a5d5a15b4945eb319da9e999c4ca60a0a4f6d2d)), - closes [#21](https://code.castopod.org/adaures/castopod/issues/21) -- integrate stylized form components and update podcast edit page - ([6536729](https://code.castopod.org/adaures/castopod/commit/653672954606a23796e8a7bda3c34fd6b92f84e0)) -- make displayed publication time as relative time using @github/time-elements - ([230e139](https://code.castopod.org/adaures/castopod/commit/230e139e43324b9ebef06ca8f6e13b3d9a7bdc70)) -- make episode description more visible on episode pages - ([90533be](https://code.castopod.org/adaures/castopod/commit/90533be0298249e5527870c01329fce5f94ec2dc)), - closes [#171](https://code.castopod.org/adaures/castopod/issues/171) -- **map:** display geolocated episodes on a map page - ([4357cc2](https://code.castopod.org/adaures/castopod/commit/4357cc25ccc585ce398035c1c25d566b6a9df775)) -- **media:** clean media api + create an entity per media type - ([fafaa7e](https://code.castopod.org/adaures/castopod/commit/fafaa7e689b17f09a2b056081fa1f4fc53bf716b)) -- **media:** save audio, images, transcripts and chapters to media for episode - and persons - ([58e2a00](https://code.castopod.org/adaures/castopod/commit/58e2a00a87fa7d5b188e13cc521d94f0cfddba50)) -- **meta-tags:** add activitypub alternate links to podcast, episode, comment - and post pages - ([bd61752](https://code.castopod.org/adaures/castopod/commit/bd61752be2f574323b05d1d0aee0df55adf9a74e)) -- minor corrections to some tables - ([3bf9420](https://code.castopod.org/adaures/castopod/commit/3bf9420b5956a501b3b24405d243a71a928d6086)) -- **monetization:** add Web Monetization support - ([96a6026](https://code.castopod.org/adaures/castopod/commit/96a6026f1db452085360f5fe248de82a2ec06468)) -- **nodeinfo2:** add .well-known route for nodeinfo2 containing metadata about - the castopod instance - ([88fddc8](https://code.castopod.org/adaures/castopod/commit/88fddc81d730978f2a4d8a671936b54041e3fe45)) -- **partner:** add link and image in episode description - ([ad07bb9](https://code.castopod.org/adaures/castopod/commit/ad07bb9330dc9493813368e969e1f3a3def44614)) -- **person:** add podcastindex.org namespace person tag - ([8acd011](https://code.castopod.org/adaures/castopod/commit/8acd011f13e99492ef4b44b327685bb006fe5f8f)) -- **platforms:** add AntennaPod - ([53e9cfd](https://code.castopod.org/adaures/castopod/commit/53e9cfd61c794b1539e9d4691d3c4e73c4b7aaa7)) -- **platforms:** add Fediverse and some funding platforms, add link on logo - ([afc3d50](https://code.castopod.org/adaures/castopod/commit/afc3d50289bb4173e0697d109ffe72f6814b93d1)) -- **platforms:** add helloasso - ([16cb993](https://code.castopod.org/adaures/castopod/commit/16cb993ee6e28987a840fc27a9c2c73794c67697)) -- **platforms:** add missing newpodcastapps.com's platforms - ([92dd370](https://code.castopod.org/adaures/castopod/commit/92dd370e2f9a464edd26cddcde96d0e16f91548d)) -- **platforms:** add pod.link - ([3d7a232](https://code.castopod.org/adaures/castopod/commit/3d7a2320ddd116e4a311605421126aff57243219)) -- **platforms:** add Podcast Index - ([ad52b1c](https://code.castopod.org/adaures/castopod/commit/ad52b1cc2b7d0bc844970214d205961a7196b4a9)) -- **platforms:** add podfriend - ([9fdc8d3](https://code.castopod.org/adaures/castopod/commit/9fdc8d32930234c7ffd2be6892be57febcef1086)) -- **podcast-form:** add new_feed_url field to set an url when changing domain or - host - ([e7eec48](https://code.castopod.org/adaures/castopod/commit/e7eec48e7bc06a9aa907db01ed3e5b536e7dd8be)) -- **podcast-form:** update routes and redirect to podcast page - ([12ce905](https://code.castopod.org/adaures/castopod/commit/12ce905799002dc9c07e6de092342d30ba9fd7d8)) -- **podcast:** create a podcast using form - ([1202ba3](https://code.castopod.org/adaures/castopod/commit/1202ba3545f521097c60a6a2af95e70527cd1d34)) -- **podcasting 2.0:** update podcast:social tag to adhere to latest spec - ([a597cf4](https://code.castopod.org/adaures/castopod/commit/a597cf4ecfa6807a3413177d99c816056a7e7c45)) -- prefill season and episode numbers + set episode number as mandatory for - serial podcasts - ([07d740b](https://code.castopod.org/adaures/castopod/commit/07d740b79f9283e389e723954f680f909ce5de4a)), - closes [#134](https://code.castopod.org/adaures/castopod/issues/134) - [#136](https://code.castopod.org/adaures/castopod/issues/136) -- **public-ui:** adapt public podcast and episode pages to wireframes - ([40a0535](https://code.castopod.org/adaures/castopod/commit/40a0535fc1bc12a24994b651f5e00b35995cbdda)), - closes [#30](https://code.castopod.org/adaures/castopod/issues/30) - [#13](https://code.castopod.org/adaures/castopod/issues/13) -- **pwa:** add service-worker + webmanifest for each podcasts to have them - install on devices - ([fee2c1c](https://code.castopod.org/adaures/castopod/commit/fee2c1c0d0d03c4ff0a6a207b0a5e0c22bb7b13a)) -- redesign public podcast and episode pages + remove any information clutter for - better ux - ([9321400](https://code.castopod.org/adaures/castopod/commit/932140077c671f0486a2cd08ceb6126c7ecde87f)) -- replace form helper functions with components in admin template - ([e64548b](https://code.castopod.org/adaures/castopod/commit/e64548b982ba47ff35f2272e2e30dd85eeba950b)) -- replace slug field with interactive permalink component - ([578022b](https://code.castopod.org/adaures/castopod/commit/578022b8c5163ffaf8db5870ed5ec9d5d9536477)) -- restyle episode and person cards + add focus style to interactive elements for - a11y - ([a505a1d](https://code.castopod.org/adaures/castopod/commit/a505a1de56e8e3056379bd60d0595f432e294728)) -- **rss:** add ˂podcast:guid˃ tag for channel - ([1fab10e](https://code.castopod.org/adaures/castopod/commit/1fab10eb0d63bb7c3edf34ffe691e2aec2c2e43c)) -- **rss:** add podcast-namespace tags for platforms + previousUrl tag - ([dbba8dc](https://code.castopod.org/adaures/castopod/commit/dbba8dc58133967c778514268cbfed8098ed1dbc)), - closes [#73](https://code.castopod.org/adaures/castopod/issues/73) - [#75](https://code.castopod.org/adaures/castopod/issues/75) - [#76](https://code.castopod.org/adaures/castopod/issues/76) - [#80](https://code.castopod.org/adaures/castopod/issues/80) -- **rss:** add podcast:comments tag to link to episode comments - ([32e8c7c](https://code.castopod.org/adaures/castopod/commit/32e8c7c16a61ffe08e2f3bfbdeda556811a0358c)) -- **rss:** add podcast:location tag - ([c0a2282](https://code.castopod.org/adaures/castopod/commit/c0a22829bd87d48535a86e60c6cd7280e44683a2)) -- **rss:** add rss feed route without the `.xml` extension - ([94c0b7c](https://code.castopod.org/adaures/castopod/commit/94c0b7c15920dae9ade5cdc79c7996dbfe82ba05)), - closes [#247](https://code.castopod.org/adaures/castopod/issues/247) -- **rss:** add soundbites according to the podcastindex specs - ([6b34617](https://code.castopod.org/adaures/castopod/commit/6b34617d07c70522cb941e96d91d9987493413eb)), - closes [#83](https://code.castopod.org/adaures/castopod/issues/83) -- **rss:** add transcript and chapters support - ([e769d83](https://code.castopod.org/adaures/castopod/commit/e769d83a932c169e52a630a17cd4dd8ac5cebaf6)), - closes [#72](https://code.castopod.org/adaures/castopod/issues/72) - [#82](https://code.castopod.org/adaures/castopod/issues/82) -- **rss:** generate rss feed from podcast entity - ([c815ecd](https://code.castopod.org/adaures/castopod/commit/c815ecd6640931fee0895f80908a3ddfac482666)) -- **rss:** update monetization tag so that it meets PodcastIndex requirements - ([4c7ecbe](https://code.castopod.org/adaures/castopod/commit/4c7ecbee83950e5f9f2482cedaab18a1ac9bfc9e)) -- **select:** enhance select input with choices.js - ([910d457](https://code.castopod.org/adaures/castopod/commit/910d457cf843e0fc334b3505a4727d51633395ac)) -- set app parameter forceGlobalSecureRequests = true forcing requests to go - through https - ([d9dff1b](https://code.castopod.org/adaures/castopod/commit/d9dff1b8bf89c8b526ad6cb89f98a1f160d49117)) -- set podcast / episode description in the pages description meta tag - ([1c4a504](https://code.castopod.org/adaures/castopod/commit/1c4a50442bea2d3449efce9c5ff1c80743152f55)), - closes [#44](https://code.castopod.org/adaures/castopod/issues/44) -- **settings:** add general config for instance (site name, description and - icon) - ([5c56f3e](https://code.castopod.org/adaures/castopod/commit/5c56f3e6f00a61af2ccf50811c155c325f2b10fa)) -- **settings:** add theme settings to set an accent color for all public pages - ([5c529a8](https://code.castopod.org/adaures/castopod/commit/5c529a83aa6d6147d94e5aee996e6b0ab02f0ce4)) -- simplify podcast page's layout for better ux - ([2c0efc6](https://code.castopod.org/adaures/castopod/commit/2c0efc6563604dd067be88cfc9ddd88a01745e64)) -- **soundbites:** add soundbite list and creation forms with audio-clipper - component - ([de19317](https://code.castopod.org/adaures/castopod/commit/de19317138a2106deb825c1eed7dda036ed7dac3)) -- style file inputs using tailwind's file class - ([8208ab6](https://code.castopod.org/adaures/castopod/commit/8208ab6785aae8c49f78eb9ac8cd53d77ec8e5e5)) -- **themes:** add ViewThemes library to set views in root themes folder - ([7a27676](https://code.castopod.org/adaures/castopod/commit/7a276764e6a1ee3619d9d3488f6163215db75338)) -- **themes:** set different default banner per theme - ([11c916f](https://code.castopod.org/adaures/castopod/commit/11c916fe433eb749ac32230c48e256057564cbb0)) -- **themes:** set generic css variables for colors to enable instance themes - ([a746a78](https://code.castopod.org/adaures/castopod/commit/a746a781b4bfc78209cf8302c6d7bb3cb452e446)) -- toggle podcast sidebar on smaller screens - ([f0205ec](https://code.castopod.org/adaures/castopod/commit/f0205ec274414e881cba40d6776126f05eaee583)) -- **transcript:** parse srt subtitles into json file + add max file size info - below audio file input - ([0098761](https://code.castopod.org/adaures/castopod/commit/00987610a068c8d6cdd4421ea16585fa037eb61a)) -- **ui:** create ViewComponents library to enable building class and view files - components - ([94872f2](https://code.castopod.org/adaures/castopod/commit/94872f2338e6025c2f3770be256160838dae9003)) -- update analytics so to meet IABv2 requirements - ([03e23a2](https://code.castopod.org/adaures/castopod/commit/03e23a28bf9b1b73fba55352c36a8cd6cc8ae729)), - closes [#10](https://code.castopod.org/adaures/castopod/issues/10) -- update pine colors + create charts components - ([a50abc1](https://code.castopod.org/adaures/castopod/commit/a50abc138d4997b564e3065b37504cda5ce62da6)) -- **users:** add myth-auth to handle users crud + add admin gateway only - accessible by login - ([c63a077](https://code.castopod.org/adaures/castopod/commit/c63a077618c61b4cde7f25ffc650a4b0e1495f44)), - closes [#11](https://code.castopod.org/adaures/castopod/issues/11) -- **ux:** remove admin dashboard and redirect directly to podcast list - ([27c48b8](https://code.castopod.org/adaures/castopod/commit/27c48b8fa930b33e5e15f0c8685e468e857ca9cd)) -- **video-clip:** add video-clip page with video preview + logs - ([42538dd](https://code.castopod.org/adaures/castopod/commit/42538dd7577be0ffe59b4fdfadbd76cc89e5ef30)) -- **video-clip:** generate video clips in the bg using a cron job + add video - clip page + tidy up UI - ([db0e427](https://code.castopod.org/adaures/castopod/commit/db0e4272bd6d307c562e1f961d2747cb62de0f35)) -- **video-clips:** add dimensions for portrait and squared formats - ([3af404d](https://code.castopod.org/adaures/castopod/commit/3af404da3dd1901c78cc7e1778fc225f6716207d)) -- **video-clips:** add new themes + add castopod logo as a watermark - ([1d1490b](https://code.castopod.org/adaures/castopod/commit/1d1490b06a1f5ecb10b3b98a72efc55d09c10944)) -- **video-clips:** add route for scheduled video clips + list video clips with - status - ([2065ebb](https://code.castopod.org/adaures/castopod/commit/2065ebbee5e3d0f890ac90b55ca984f1d62a184c)) -- **video-clips:** allow episodeNumbering text to stand in the indent of - episodeTitle paragraph - ([71a063d](https://code.castopod.org/adaures/castopod/commit/71a063dac311cb21639801fbae6af7c5106c2699)) -- **video-clips:** generate a 16:9 video using ffmpeg - ([35aa7ea](https://code.castopod.org/adaures/castopod/commit/35aa7ea5d9a339b3e6f745137282268d69fe2231)) -- **video-clips:** generate subtitles clip using transcript json to have - subtitles accross video - ([3ce07e4](https://code.castopod.org/adaures/castopod/commit/3ce07e455d171e29be30d8ad45055510eb8d363c)) -- **video-clips:** replace hardcoded colors with config's theme colors - ([e462abf](https://code.castopod.org/adaures/castopod/commit/e462abf6d660e41d2170c52caf45704008de58e9)) -- **vite:** add vite config to decouple it from CI_ENVIRONMENT - ([8721719](https://code.castopod.org/adaures/castopod/commit/8721719cd7cf32e94823541eafaba1e9309355a8)) -- write id3v2 tags to episode's audio file - ([4651d01](https://code.castopod.org/adaures/castopod/commit/4651d01a84ff3ea8433a8ae26cfd750a1ec9e88d)) - -### Performance Improvements - -- **cache:** update CI4 to use cache's deleteMatching method - ([54b84f9](https://code.castopod.org/adaures/castopod/commit/54b84f96843af13f579fea49102c8c2ef81b0a54)) -- **cache:** use deleteMatching method to prevent forgetting cached elements in - models - ([76afc0c](https://code.castopod.org/adaures/castopod/commit/76afc0cfa2feb087697bae4bc138e4956873dd62)) -- defer javascript + lazy load images for faster page loads - ([f0685e4](https://code.castopod.org/adaures/castopod/commit/f0685e44799dfb494592ff97841c0ae035381db8)) -- **docker:** add redis caching service for development - ([05ace8c](https://code.castopod.org/adaures/castopod/commit/05ace8cff2ef02d19abd40097ac5546dca6a54ca)) - -### Reverts - -- **install:** redirect to install in homepage if no database was set - ([73f094d](https://code.castopod.org/adaures/castopod/commit/73f094daf26a8cf75e39ebff1eeb7f9039276312)) -- set deprecated config options back in App config - ([433745f](https://code.castopod.org/adaures/castopod/commit/433745f194c73407999b207090478563283876a5)) -- **soundbites:** remove soundbite table from episode's public page - ([5dc0f19](https://code.castopod.org/adaures/castopod/commit/5dc0f19656de0d764f627d6ae78a9e306c901835)) -- use basic input file for episodes audio files instead of button for better UX - ([d5f22fb](https://code.castopod.org/adaures/castopod/commit/d5f22fbb38c43d9b37df401eff655958a57cb40a)) - -### BREAKING CHANGES - -- **analytics:** analytics_podcasts_by_player table and analytics_podcasts - procedure were updated - # [1.0.0-beta.24](https://code.castopod.org/adaures/castopod/compare/v1.0.0-beta.23...v1.0.0-beta.24) (2022-10-14) ### Bug Fixes diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index b1291ae9..57da0daf 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,162 +1,128 @@ -# Contributor Covenant 3.0 Code of Conduct +# Contributor Covenant Code of Conduct ## Our Pledge -We pledge to make our community welcoming, safe, and equitable for all. +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity and +orientation. -We are committed to fostering an environment that respects and promotes the -dignity, rights, and contributions of all individuals, regardless of -characteristics including race, ethnicity, caste, color, age, physical -characteristics, neurodiversity, disability, sex or gender, gender identity or -expression, sexual orientation, language, philosophy or religion, national or -social origin, socio-economic position, level of education, or other status. The -same privileges of participation are extended to everyone who participates in -good faith and in accordance with this Covenant. +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. -## Encouraged Behaviors +## Our Standards -While acknowledging differences in social norms, we all strive to meet our -community's expectations for positive behavior. We also understand that our -words and actions may be interpreted differently than we intend based on -culture, background, or native language. +Examples of behavior that contributes to a positive environment for our +community include: -With these considerations in mind, we agree to behave mindfully toward each -other and act in ways that center our shared values, including: +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall + community -1. Respecting the **purpose of our community**, our activities, and our ways of - gathering. -2. Engaging **kindly and honestly** with others. -3. Respecting **different viewpoints** and experiences. -4. **Taking responsibility** for our actions and contributions. -5. Gracefully giving and accepting **constructive feedback**. -6. Committing to **repairing harm** when it occurs. -7. Behaving in other ways that promote and sustain the **well-being of our - community**. +Examples of unacceptable behavior include: -## Restricted Behaviors +- The use of sexualized language or imagery, and sexual attention or advances of + any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, + without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting -We agree to restrict the following behaviors in our community. Instances, -threats, and promotion of these behaviors are violations of this Code of -Conduct. +## Enforcement Responsibilities -1. **Harassment.** Violating explicitly expressed boundaries or engaging in - unnecessary personal attention after any clear request to stop. -2. **Character attacks.** Making insulting, demeaning, or pejorative comments - directed at a community member or group of people. -3. **Stereotyping or discrimination.** Characterizing anyone’s personality or - behavior on the basis of immutable identities or traits. -4. **Sexualization.** Behaving in a way that would generally be considered - inappropriately intimate in the context or purpose of the community. -5. **Violating confidentiality**. Sharing or acting on someone's personal or - private information without their permission. -6. **Endangerment.** Causing, encouraging, or threatening violence or other harm - toward any person or group. -7. Behaving in other ways that **threaten the well-being** of our community. +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. -### Other Restrictions - -1. **Misleading identity.** Impersonating someone else for any reason, or - pretending to be someone else to evade enforcement actions. -2. **Failing to credit sources.** Not properly crediting the sources of content - you contribute. -3. **Promotional materials**. Sharing marketing or other commercial content in a - way that is outside the norms of the community. -4. **Irresponsible communication.** Failing to responsibly present content which - includes, links or describes any other restricted behaviors. - -## Reporting an Issue - -Tensions can occur between community members even when they are trying their -best to collaborate. Not every conflict represents a code of conduct violation, -and this Code of Conduct reinforces encouraged behaviors and norms that can help -avoid conflicts and minimize harm. - -When an incident does occur, it is important to report it promptly. To report a -possible violation, email us at [abuse@castopod.org](mailto:abuse@castopod.org). - -Community Moderators take reports of violations seriously and will make every -effort to respond in a timely manner. They will investigate all reports of code -of conduct violations, reviewing messages, logs, and recordings, or interviewing -witnesses and other participants. Community Moderators will keep investigation -and enforcement actions as transparent as possible while prioritizing safety and -confidentiality. In order to honor these values, enforcement actions are carried -out in private with the involved parties, but communicating to the whole -community may be part of a mutually agreed upon resolution. - -## Addressing and Repairing Harm - -If an investigation by the Community Moderators finds that this Code of Conduct -has been violated, the following enforcement ladder may be used to determine how -best to repair harm, based on the incident's impact on the individuals involved -and the community as a whole. Depending on the severity of a violation, lower -rungs on the ladder may be skipped. - -1. Warning - 1. Event: A violation involving a single incident or series of incidents. - 2. Consequence: A private, written warning from the Community Moderators. - 3. Repair: Examples of repair include a private written apology, - acknowledgement of responsibility, and seeking clarification on - expectations. -2. Temporarily Limited Activities - 1. Event: A repeated incidence of a violation that previously resulted in a - warning, or the first incidence of a more serious violation. - 2. Consequence: A private, written warning with a time-limited cooldown - period designed to underscore the seriousness of the situation and give - the community members involved time to process the incident. The cooldown - period may be limited to particular communication channels or interactions - with particular community members. - 3. Repair: Examples of repair may include making an apology, using the - cooldown period to reflect on actions and impact, and being thoughtful - about re-entering community spaces after the period is over. -3. Temporary Suspension - 1. Event: A pattern of repeated violation which the Community Moderators have - tried to address with warnings, or a single serious violation. - 2. Consequence: A private written warning with conditions for return from - suspension. In general, temporary suspensions give the person being - suspended time to reflect upon their behavior and possible corrective - actions. - 3. Repair: Examples of repair include respecting the spirit of the - suspension, meeting the specified conditions for return, and being - thoughtful about how to reintegrate with the community when the suspension - is lifted. -4. Permanent Ban - 1. Event: A pattern of repeated code of conduct violations that other steps - on the ladder have failed to resolve, or a violation so serious that the - Community Moderators determine there is no way to keep the community safe - with this person as a member. - 2. Consequence: Access to all community spaces, tools, and communication - channels is removed. In general, permanent bans should be rarely used, - should have strong reasoning behind them, and should only be resorted to - if working through other remedies has failed to change the behavior. - 3. Repair: There is no possible repair in cases of this severity. - -This enforcement ladder is intended as a guideline. It does not limit the -ability of Community Managers to use their discretion and judgment, in keeping -with the best interests of our community. +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public or other -spaces. Examples of representing our community include using an official email -address, posting via an official social media account, or acting as an appointed +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed representative at an online or offline event. +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[abuse@castopod.org](mailto:abuse@castopod.org). All complaints will be reviewed +and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + ## Attribution -This Code of Conduct is adapted from the Contributor Covenant, version 3.0, -permanently available at -[https://www.contributor-covenant.org/version/3/0/](https://www.contributor-covenant.org/version/3/0/). +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. -Contributor Covenant is stewarded by the Organization for Ethical Source and -licensed under CC BY-SA 4.0. To view a copy of this license, visit -[https://creativecommons.org/licenses/by-sa/4.0/](https://creativecommons.org/licenses/by-sa/4.0/) +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). -For answers to common questions about Contributor Covenant, see the FAQ at -[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). -Translations are provided at -[https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations). -Additional enforcement and community guideline resources can be found at -[https://www.contributor-covenant.org/resources](https://www.contributor-covenant.org/resources). -The enforcement ladder was inspired by the work of -[Mozilla’s code of conduct team](https://github.com/mozilla/inclusion). +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3468537..21c69f78 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,167 +1,4 @@ -# Contributing to Castopod +# Contributing guidelines -Love Castopod and want to help? Thanks so much, there's something to do for -everybody! - -> [!NOTE] -> Castopod follows the [all contributors](https://allcontributors.org/) -> specification in an effort to **recognize any kind of contribution**, not just -> code! -> If you've made a contribution and do not appear in the -> [contributors](../index.md#contributors-✨) list, please -> [let us know](../index.md#contact) so we can correct our mistake! 🙂 - -Please take a moment to review this document in order to make the contribution -process easy and effective for everyone involved. - -Following these guidelines helps to communicate that you respect the time of the -developers managing and developing this open source project. In return, they -should reciprocate that respect in addressing your issue or assessing patches -and features. - -## Translating Castopod - -We use [Crowdin](https://translate.castopod.org/) to manage translation files -for [Castopod](https://code.castopod.org/), the -[documentation](https://docs.castopod.org/) and the -[landing](https://castopod.org/) websites. - -Whether you'd like to correct a translation error, validate new translations or -include your language to Castopod, head into the -[crowdin project](https://translate.castopod.org/) to get started. - -> [!NOTE] -> To prevent degrading user experience, new languages are included to Castopod -> when they reach a certain threshold (~90%). - -## Using the issue tracker - -The [issue tracker](https://code.castopod.org/adaures/castopod/-/issues) is the -preferred channel for [bug reports](#bug-reports), -[features requests](#feature-requests) and -[submitting pull requests](#pull-requests). - -## ⚠️ Security issues and vulnerabilities - -If you encounter any security issue or vulnerability in the Castopod source, -please contact us directly by email at -[security@castopod.org](mailto:security@castopod.org) - -## Bug reports - -A bug is a _demonstrable problem_ that is caused by the code in the repository. -Good bug reports are extremely helpful - thank you! - -Guidelines for bug reports: - -1. **Use the issue search** — check if the issue has already been - reported. - -2. **Check if the issue has been fixed** — try to reproduce it using the - latest `main` branch in the repository. - -3. **Isolate the problem** — ideally create a - [reduced test case](https://css-tricks.com/reduced-test-cases/) and a live - example. - -A good bug report shouldn't leave others needing to chase you up for more -information. Please try to be as detailed as possible in your report. What is -your environment? What steps will reproduce the issue? What browser(s) and OS -experience the problem? What would you expect to be the outcome? All these -details will help people to fix any potential bugs. - -> [!NOTE] -> [Issue templates](https://docs.gitlab.com/ee/user/project/description_templates.html#using-the-templates) have -> been created for this project. You may use them to help you follow those -> guidelines. - -## Feature requests - -Feature requests are welcome. But take a moment to find out whether your idea -fits with the scope and aims of the project. It's up to _you_ to make a strong -case to convince the project's developers of the merits of this feature. Please -provide as much detail and context as possible. - -## Pull requests - -Good pull requests - patches, improvements, new features - are a fantastic help. -They should remain focused in scope and avoid containing unrelated commits. - -**Please ask first** before embarking on any significant pull request (e.g. -implementing features, refactoring code, porting to a different language), -otherwise you risk spending a lot of time working on something that the -project's developers might not want to merge into the project. - -Please adhere to the coding conventions used throughout a project (indentation, -accurate comments, etc.) and any other requirements (such as test coverage). - -Adhering to the following process is the best way to get your work included in -the project: - -1. [Fork](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html) - the project, clone your fork, and configure the remotes: - - ```bash - # Clone your fork of the repo into the current directory - git clone https://code.castopod.org//castopod.git - - # Navigate to the newly cloned directory - cd castopod - - # Assign the original repo to a remote called "upstream" - git remote add upstream https://code.castopod.org/adaures/castopod.git - ``` - -2. If you cloned a while ago, get the latest changes from upstream: - - ```bash - git checkout main - git pull upstream main - ``` - -3. Create a new topic branch (off the `main` branch) to contain your feature, - change, or fix: - - ```bash - git checkout -b - ``` - -4. Commit your changes in logical chunks. Please adhere to these - [git commit message guidelines](https://conventionalcommits.org/) or your - code is unlikely be merged into the main project. Use Git's - [interactive rebase](https://help.github.com/articles/about-git-rebase/) - feature to tidy up your commits before making them public. - -5. Locally merge (or rebase) the upstream dev branch into your topic branch: - - ```bash - git pull [--rebase] upstream main - ``` - -6. Push your topic branch up to your fork: - - ```bash - git push origin - ``` - -7. [Open a Pull Request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html#new-merge-request-from-a-fork) - with a clear title and description. - -> [!IMPORTANT] -> By submitting a patch, you agree to allow the project owners to license your -> work under the terms of the -> [GNU AGPLv3](https://code.castopod.org/adaures/castopod/-/blob/develop/LICENSE.md). - -## Collaborating guidelines - -There are few basic rules to ensure high quality of the project: - -- Before merging, a PR requires at least two approvals from the collaborators - unless it's an architectural change, a large feature, etc. If it is, then at - least 50% of the core team have to agree to merge it, with every team member - having a full veto right. (i.e. every single one can block any PR) -- A PR should remain open for at least two days before merging (does not apply - for trivial contributions like fixing a typo). This way everyone has enough - time to look into it. - -You are always welcome to discuss and propose improvements to this guideline. +You may find the contributing guidelines in the +[Castopod documentation website](https://docs.castopod.org/contributing/guidelines.html). diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 97175ffd..b9c083c2 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -18,9 +18,9 @@ Javascript dependencies can be found in the [package.json](./package.json) file. ([Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL)) - [RemixIcon](https://remixicon.com/) ([Apache License 2.0](https://github.com/Remix-Design/RemixIcon/blob/master/License)) -- [OPAWG/User agent list](https://github.com/opawg/user-agents-v2) +- [OPAWG/User agent list](https://github.com/opawg/user-agents) ([by Open Podcast Analytics Working Group](https://github.com/opawg)) - ([MIT license](https://github.com/opawg/user-agents-v2/blob/master/LICENSE)) + ([MIT license](https://github.com/opawg/user-agents/blob/master/LICENSE)) - [OPAWG/podcast-rss-useragents](https://github.com/opawg/podcast-rss-useragents) ([by Open Podcast Analytics Working Group](https://github.com/opawg)) ([MIT license](https://github.com/opawg/podcast-rss-useragents/blob/master/LICENSE)) diff --git a/README.md b/README.md index 6460720c..89b6c508 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ @@ -15,11 +15,16 @@ Castopod is a free and open-source podcast hosting solution made for podcasters who want engage and interact with their audience. +> **Status** +> +> Castopod is currently in **beta** but already quite stable and used by +> podcasters around the world! + ## Getting started -Castopod comes pre-packaged with all the required static assets and -dependencies, you may download and install it by checking out the -[getting started page](https://castopod.org/getting-started/)! +To get started with Castopod, you may +[check out the documentation](https://docs.castopod.org/), everything should be +there! ## Security issues and vulnerabilities @@ -31,9 +36,12 @@ please contact us directly by email at Contributions are always welcome! -See the [contribution guidelines](./CONTRIBUTING.md) for ways to get started. +See the +[contribution guidelines](https://docs.castopod.org/contributing/guidelines) for +ways to get started. -> [!Important] +> **Note** +> > **Any** contribution made on a repository other than > [the original repository](https://code.castopod.org/adaures/castopod) will not > be accepted. @@ -47,76 +55,63 @@ Thanks goes to these wonderful people - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Yassine Doghri
Yassine Doghri

💻 🐛 📖 👀 🚧 🖋 🎨 ️️️️♿️ 🌍 💬 🧑‍🏫 🚇 🤔 📆 📝
Benjamin Bellamy
Benjamin Bellamy

💻 🐛 👀 🖋 🌍 💬 🚇 🤔 📝 📆 📢
Ola Hneini
Ola Hneini

💻 👀 📖 🚧 💬 🤔
Romain de Laage
Romain de Laage

💻 🚇 📖 🌍 🤔
Lyonel Bernard
Lyonel Bernard

🐛 💬 🔊 🤔
Christopher Lagonick-Weitzel
Christopher Lagonick-Weitzel

🐛 💬 🔊 🤔
Ernesto Acosta
Ernesto Acosta

🐛 🔊 🌍 💬 🤔
Ewen
Ewen

🌍 🤔 💻
Bastien Luneteau
Bastien Luneteau

💻 🐛
Cécile Ricordeau
Cécile Ricordeau

🎨
Patryk Miś
Patryk Miś

🌍
Marcin Lewandowski
Marcin Lewandowski

🐛 🤔
Sebastian Janik
Sebastian Janik

💻
Patryk Karczmarczyk
Patryk Karczmarczyk

💻
denis d
denis d

🐛 🤔
Douglas Kastle
Douglas Kastle

🐛 🤔
cExplorer
cExplorer

🐛 🌍
ImaCrea
ImaCrea

🐛 🤔
Jonas S
Jonas S

💻
LEFEBVRE Yann
LEFEBVRE Yann

🐛
Sebastian Späth
Sebastian Späth

🐛 🤔
rocky III
rocky III

🐛
Hermann Josef Eckl
Hermann Josef Eckl

🐛
Delhaye Cyrille
Delhaye Cyrille

🐛 🤔
João Leandro
João Leandro

🌍 🤔
Angelos Chouvardas
Angelos Chouvardas

🌍
Eivind
Eivind

🌍
forght
forght

🌍
glottis0q
glottis0q

🌍
ButterflyOfFire
ButterflyOfFire

🌍
Lucian I. Last
Lucian I. Last

🌍
LuuzViir
LuuzViir

🌍
CTHTC
CTHTC

🌍
Russian Retro
Russian Retro

🌍
Marek L'ach
Marek L'ach

🌍
GunChleoc
GunChleoc

🌍
GabiSnow
GabiSnow

🌍
bendaha
bendaha

🌍
Samuel Roland
Samuel Roland

🌍
Dimitri Regnier
Dimitri Regnier

🤔
irithys
irithys

🌍
Sergi
Sergi

🌍
Andreas Olsson
Andreas Olsson

🌍
leonfrom
leonfrom

🌍
agentcobra
agentcobra

🌍
Alessandro
Alessandro

🌍
liimee
liimee

🌍
Ahmed Sabouni
Ahmed Sabouni

🌍
KrzysztofDomanczyk
KrzysztofDomanczyk

💻
Guy Martin
Guy Martin

🐛 💻
Paul Cutler
Paul Cutler

📖 💬 🤔
Nate Ritter
Nate Ritter

💻

Yassine Doghri

💻 🐛 📖 👀 🚧 🖋 🎨 ️️️️♿️ 🌍 💬 🧑‍🏫 🚇 🤔 📆 📝

Benjamin Bellamy

💻 🐛 👀 🖋 🌍 💬 🚇 🤔 📝 📆 📢

Ola Hneini

💻 👀 📖 🚧 💬 🤔

Romain de Laage

💻 🚇 📖 🌍 🤔

Lyonel Bernard

🐛 💬 🔊 🤔

Christopher Lagonick-Weitzel

🐛 💬 🔊 🤔

Ernesto Acosta

🐛 🔊 🌍 💬 🤔

Bastien Luneteau

💻 🐛

Cécile Ricordeau

🎨

Patryk Miś

🌍

Marcin Lewandowski

🐛 🤔

Sebastian Janik

💻

Patryk Karczmarczyk

💻

denis d

🐛 🤔

Douglas Kastle

🐛 🤔

cExplorer

🐛 🌍

ImaCrea

🐛 🤔

Jonas S

💻

LEFEBVRE Yann

🐛

Sebastian Späth

🐛 🤔

rocky III

🐛

Hermann Josef Eckl

🐛

Delhaye Cyrille

🐛 🤔

João Leandro

🌍 🤔

Angelos Chouvardas

🌍

Eivind

🌍

Ewen

🌍 🤔

forght

🌍

glottis0q

🌍

ButterflyOfFire

🌍

Lucian I. Last

🌍

LuuzViir

🌍

CTHTC

🌍

Russian Retro

🌍

Marek L'ach

🌍

GunChleoc

🌍

GabiSnow

🌍

bendaha

🌍

Samuel Roland

🌍

Dimitri Regnier

🤔

irithys

🌍

Sergi

🌍

ghose (XoseM)

🌍
@@ -141,7 +136,7 @@ Alternatively, you can follow us on social media platforms to get news about Castopod: - [podlibre.social](https://podlibre.social/@Castopod) (Mastodon instance) -- [Bluesky](https://bsky.app/profile/castopod.org) +- [Twitter](https://twitter.com/castopod) - [LinkedIn](https://linkedin.com/company/castopod) - [Facebook](https://www.facebook.com/castopod) @@ -155,10 +150,10 @@ backers. If you'd like to help, please consider - Ad Aures + Netlify - NLnet Logo + NLnet Logo diff --git a/app/.htaccess b/app/.htaccess index e64d9494..f24db0ac 100644 --- a/app/.htaccess +++ b/app/.htaccess @@ -1,2 +1,6 @@ - Require all denied - Deny from all + + Require all denied + + + Deny from all + diff --git a/app/Commands/EpisodesComputeDownloads.php b/app/Commands/EpisodesComputeDownloads.php deleted file mode 100644 index 1bdc7b2d..00000000 --- a/app/Commands/EpisodesComputeDownloads.php +++ /dev/null @@ -1,50 +0,0 @@ -builder() - ->select('episodes.id as id, IFNULL(SUM(ape.hits),0) as downloads_count') - ->join('analytics_podcasts_by_episode ape', 'episodes.id=ape.episode_id', 'left') - ->groupBy('episodes.id'); - - $episodeModel2 = new EpisodeModel(); - $episodeModel2->builder() - ->setQueryAsData($query) - ->onConstraint('id') - ->updateBatch(); - } -} diff --git a/app/Common.php b/app/Common.php index 89981c0d..1f3b17c2 100644 --- a/app/Common.php +++ b/app/Common.php @@ -2,6 +2,8 @@ declare(strict_types=1); +use Config\Services; +use Config\View; use ViewThemes\Theme; /** @@ -12,7 +14,7 @@ use ViewThemes\Theme; * This can be looked at as a `master helper` file that is loaded early on, and may also contain additional functions * that you'd like to use throughout your entire application * - * @see: https://codeigniter.com/user_guide/extending/common.html + * @link: https://codeigniter4.github.io/CodeIgniter4/ */ if (! function_exists('view')) { @@ -27,17 +29,12 @@ if (! function_exists('view')) { */ function view(string $name, array $data = [], array $options = []): string { - if (array_key_exists('theme', $options)) { - Theme::setTheme($options['theme']); - } - $path = Theme::path(); /** @var CodeIgniter\View\View $renderer */ $renderer = single_service('renderer', $path); - $saveData = config('View') - ->saveData; + $saveData = config(View::class)->saveData; if (array_key_exists('saveData', $options)) { $saveData = (bool) $options['saveData']; @@ -48,3 +45,40 @@ if (! function_exists('view')) { ->render($name, $options, $saveData); } } + +if (! function_exists('lang')) { + /** + * A convenience method to translate a string or array of them and format the result with the intl extension's + * MessageFormatter. + * + * Overwritten to include an escape parameter (escaped by default). + * + * @param array $args + * + * @return string|string[] + */ + function lang(string $line, array $args = [], ?string $locale = null, bool $escape = true): string | array + { + $language = Services::language(); + + // Get active locale + $activeLocale = $language->getLocale(); + + if ($locale && $locale !== $activeLocale) { + $language->setLocale($locale); + } + + $line = $language->getLine($line, $args); + if (! $locale) { + return $escape ? esc($line) : $line; + } + + if ($locale === $activeLocale) { + return $escape ? esc($line) : $line; + } + + // Reset to active locale + $language->setLocale($activeLocale); + return $escape ? esc($line) : $line; + } +} diff --git a/app/Config/App.php b/app/Config/App.php index 404ff5a0..6aaeccae 100644 --- a/app/Config/App.php +++ b/app/Config/App.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace Config; use CodeIgniter\Config\BaseConfig; -use Override; +use CodeIgniter\Session\Handlers\FileHandler; class App extends BaseConfig { @@ -14,34 +14,38 @@ class App extends BaseConfig * Base Site URL * -------------------------------------------------------------------------- * - * URL to your CodeIgniter root. Typically, this will be your base URL, + * URL to your CodeIgniter root. Typically this will be your base URL, * WITH a trailing slash: * - * E.g., http://example.com/ + * http://example.com/ + * + * If this is not set then CodeIgniter will try guess the protocol, domain + * and path to your installation. However, you should always configure this + * explicitly and never rely on auto-guessing, especially in production + * environments. */ public string $baseURL = 'http://localhost:8080/'; /** - * Allowed Hostnames in the Site URL other than the hostname in the baseURL. - * If you want to accept multiple Hostnames, set this. + * -------------------------------------------------------------------------- + * Media Base URL + * -------------------------------------------------------------------------- * - * E.g., - * When your site URL ($baseURL) is 'http://example.com/', and your site - * also accepts 'http://media.example.com/' and 'http://accounts.example.com/': - * ['media.example.com', 'accounts.example.com'] + * URL to your media root. Typically this will be your base URL, + * WITH a trailing slash: * - * @var list + * http://cdn.example.com/ */ - public array $allowedHostnames = []; + public string $mediaBaseURL = 'http://localhost:8080/'; /** * -------------------------------------------------------------------------- * Index File * -------------------------------------------------------------------------- * - * Typically, this will be your `index.php` file, unless you've renamed it to - * something else. If you have configured your web server to remove this file - * from your site URIs, set this variable to an empty string. + * Typically this will be your index.php file, unless you've renamed it to + * something else. If you are using mod_rewrite to remove the page set this + * variable so that it is blank. */ public string $indexPage = ''; @@ -51,41 +55,17 @@ class App extends BaseConfig * -------------------------------------------------------------------------- * * This item determines which server global should be used to retrieve the - * URI string. The default setting of 'REQUEST_URI' works for most servers. + * URI string. The default setting of 'REQUEST_URI' works for most servers. * If your links do not seem to work, try one of the other delicious flavors: * - * 'REQUEST_URI': Uses $_SERVER['REQUEST_URI'] - * 'QUERY_STRING': Uses $_SERVER['QUERY_STRING'] - * 'PATH_INFO': Uses $_SERVER['PATH_INFO'] + * 'REQUEST_URI' Uses $_SERVER['REQUEST_URI'] + * 'QUERY_STRING' Uses $_SERVER['QUERY_STRING'] + * 'PATH_INFO' Uses $_SERVER['PATH_INFO'] * * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! */ public string $uriProtocol = 'REQUEST_URI'; - /* - *-------------------------------------------------------------------------- - * Allowed URL Characters - *-------------------------------------------------------------------------- - * - * This lets you specify which characters are permitted within your URLs. - * When someone tries to submit a URL with disallowed characters they will - * get a warning message. - * - * As a security measure you are STRONGLY encouraged to restrict URLs to - * as few characters as possible. - * - * By default, only these are allowed: `a-z 0-9~%.:_-` - * - * Set an empty string to allow all characters -- but only if you are insane. - * - * The configured value is actually a regular expression character group - * and it will be used as: '/\A[]+\z/iu' - * - * DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! - * - */ - public string $permittedURIChars = 'a-z 0-9~%.:_\-@'; - /** * -------------------------------------------------------------------------- * Default Locale @@ -119,23 +99,9 @@ class App extends BaseConfig * by the application in descending order of priority. If no match is * found, the first locale will be used. * - * IncomingRequest::setLocale() also uses this list. - * - * @var list + * @var string[] */ - public array $supportedLocales = [ - 'en', - 'fr', - 'pl', - 'de', - 'pt-br', - 'nn-no', - 'es', - 'zh-hans', - 'ca', - 'br', - 'sr-latn', - ]; + public array $supportedLocales = ['en', 'fr', 'pl', 'de', 'pt-BR', 'nn-NO', 'es', 'zh-Hans', 'ca']; /** * -------------------------------------------------------------------------- @@ -144,9 +110,6 @@ class App extends BaseConfig * * The default timezone that will be used in your application to display * dates with the date helper, and can be retrieved through app_timezone() - * - * @see https://www.php.net/manual/en/timezones.php for list of timezones - * supported by PHP. */ public string $appTimezone = 'UTC'; @@ -170,10 +133,170 @@ class App extends BaseConfig * If true, this will force every request made to this application to be * made via a secure connection (HTTPS). If the incoming request is not * secure, the user will be redirected to a secure version of the page - * and the HTTP Strict Transport Security (HSTS) header will be set. + * and the HTTP Strict Transport Security header will be set. */ public bool $forceGlobalSecureRequests = true; + /** + * -------------------------------------------------------------------------- + * Session Driver + * -------------------------------------------------------------------------- + * + * The session storage driver to use: + * - `CodeIgniter\Session\Handlers\FileHandler` + * - `CodeIgniter\Session\Handlers\DatabaseHandler` + * - `CodeIgniter\Session\Handlers\MemcachedHandler` + * - `CodeIgniter\Session\Handlers\RedisHandler` + */ + public string $sessionDriver = FileHandler::class; + + /** + * -------------------------------------------------------------------------- + * Session Cookie Name + * -------------------------------------------------------------------------- + * + * The session cookie name, must contain only [0-9a-z_-] characters + */ + public string $sessionCookieName = 'ci_session'; + + /** + * -------------------------------------------------------------------------- + * Session Expiration + * -------------------------------------------------------------------------- + * + * The number of SECONDS you want the session to last. + * Setting to 0 (zero) means expire when the browser is closed. + */ + public int $sessionExpiration = 7200; + + /** + * -------------------------------------------------------------------------- + * Session Save Path + * -------------------------------------------------------------------------- + * + * The location to save sessions to and is driver dependent. + * + * For the 'files' driver, it's a path to a writable directory. + * WARNING: Only absolute paths are supported! + * + * For the 'database' driver, it's a table name. + * Please read up the manual for the format with other session drivers. + * + * IMPORTANT: You are REQUIRED to set a valid save path! + */ + public string $sessionSavePath = WRITEPATH . 'session'; + + /** + * -------------------------------------------------------------------------- + * Session Match IP + * -------------------------------------------------------------------------- + * + * Whether to match the user's IP address when reading the session data. + * + * WARNING: If you're using the database driver, don't forget to update + * your session table's PRIMARY KEY when changing this setting. + */ + public bool $sessionMatchIP = false; + + /** + * -------------------------------------------------------------------------- + * Session Time to Update + * -------------------------------------------------------------------------- + * + * How many seconds between CI regenerating the session ID. + */ + public int $sessionTimeToUpdate = 300; + + /** + * -------------------------------------------------------------------------- + * Session Regenerate Destroy + * -------------------------------------------------------------------------- + * + * Whether to destroy session data associated with the old session ID + * when auto-regenerating the session ID. When set to FALSE, the data + * will be later deleted by the garbage collector. + */ + public bool $sessionRegenerateDestroy = false; + + /** + * -------------------------------------------------------------------------- + * Cookie Prefix + * -------------------------------------------------------------------------- + * + * Set a cookie name prefix if you need to avoid collisions. + * + * @deprecated use Config\Cookie::$prefix property instead. + */ + public string $cookiePrefix = ''; + + /** + * -------------------------------------------------------------------------- + * Cookie Domain + * -------------------------------------------------------------------------- + * + * Set to `.your-domain.com` for site-wide cookies. + * + * @deprecated use Config\Cookie::$domain property instead. + */ + public string $cookieDomain = ''; + + /** + * -------------------------------------------------------------------------- + * Cookie Path + * -------------------------------------------------------------------------- + * + * Typically will be a forward slash. + * + * @deprecated use Config\Cookie::$path property instead. + */ + public string $cookiePath = '/'; + + /** + * -------------------------------------------------------------------------- + * Cookie Secure + * -------------------------------------------------------------------------- + * + * Cookie will only be set if a secure HTTPS connection exists. + * + * @deprecated use Config\Cookie::$secure property instead. + */ + public bool $cookieSecure = false; + + /** + * -------------------------------------------------------------------------- + * Cookie HttpOnly + * -------------------------------------------------------------------------- + * + * Cookie will only be accessible via HTTP(S) (no JavaScript). + * + * @deprecated use Config\Cookie::$httponly property instead. + */ + public bool $cookieHTTPOnly = true; + + /** + * -------------------------------------------------------------------------- + * Cookie SameSite + * -------------------------------------------------------------------------- + * + * Configure cookie SameSite setting. Allowed values are: + * - None + * - Lax + * - Strict + * - '' + * + * Alternatively, you can use the constant names: + * - `Cookie::SAMESITE_NONE` + * - `Cookie::SAMESITE_LAX` + * - `Cookie::SAMESITE_STRICT` + * + * Defaults to `Lax` for compatibility with modern browsers. Setting `''` + * (empty string) means default SameSite attribute set by browsers (`Lax`) + * will be set on cookies. If set to `None`, `$cookieSecure` must also be set. + * + * @deprecated `Config\Cookie` $samesite property is used. + */ + public string $cookieSameSite = 'Lax'; + /** * -------------------------------------------------------------------------- * Reverse Proxy IPs @@ -181,21 +304,103 @@ class App extends BaseConfig * * If your server is behind a reverse proxy, you must whitelist the proxy * IP addresses from which CodeIgniter should trust headers such as - * X-Forwarded-For or Client-IP in order to properly identify + * HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify * the visitor's IP address. * - * You need to set a proxy IP address or IP address with subnets and - * the HTTP header for the client IP address. + * You can use both an array or a comma-separated list of proxy addresses, + * as well as specifying whole subnets. Here are a few examples: * - * Here are some examples: - * [ - * '10.0.1.200' => 'X-Forwarded-For', - * '192.168.5.0/24' => 'X-Real-IP', - * ] + * Comma-separated: '10.0.1.200,192.168.5.0/24' + * Array: ['10.0.1.200', '192.168.5.0/24'] * - * @var array|string + * @var string|string[] */ - public $proxyIPs = []; + public string | array $proxyIPs = ''; + + /** + * -------------------------------------------------------------------------- + * CSRF Token Name + * -------------------------------------------------------------------------- + * + * The token name. + * + * @deprecated Use `Config\Security` $tokenName property instead of using this property. + */ + public string $CSRFTokenName = 'csrf_test_name'; + + /** + * -------------------------------------------------------------------------- + * CSRF Header Name + * -------------------------------------------------------------------------- + * + * The header name. + * + * @deprecated Use `Config\Security` $headerName property instead of using this property. + */ + public string $CSRFHeaderName = 'X-CSRF-TOKEN'; + + /** + * -------------------------------------------------------------------------- + * CSRF Cookie Name + * -------------------------------------------------------------------------- + * + * The cookie name. + * + * @deprecated Use `Config\Security` $cookieName property instead of using this property. + */ + public string $CSRFCookieName = 'csrf_cookie_name'; + + /** + * -------------------------------------------------------------------------- + * CSRF Expire + * -------------------------------------------------------------------------- + * + * The number in seconds the token should expire. + * + * @deprecated Use `Config\Security` $expire property instead of using this property. + */ + public int $CSRFExpire = 7200; + + /** + * -------------------------------------------------------------------------- + * CSRF Regenerate + * -------------------------------------------------------------------------- + * + * Regenerate token on every submission? + * + * @deprecated Use `Config\Security` $regenerate property instead of using this property. + */ + public bool $CSRFRegenerate = true; + + /** + * -------------------------------------------------------------------------- + * CSRF Redirect + * -------------------------------------------------------------------------- + * + * Redirect to previous page with error on failure? + * + * @deprecated Use `Config\Security` $redirect property instead of using this property. + */ + public bool $CSRFRedirect = true; + + /** + * -------------------------------------------------------------------------- + * CSRF SameSite + * -------------------------------------------------------------------------- + * + * Setting for CSRF SameSite cookie token. Allowed values are: + * - None + * - Lax + * - Strict + * - '' + * + * Defaults to `Lax` as recommended in this link: + * + * @see https://portswigger.net/web-security/csrf/samesite-cookies + * + * @deprecated Use `Config\Security` $samesite property instead of using this property. + */ + public string $CSRFSameSite = 'Lax'; /** * -------------------------------------------------------------------------- @@ -215,6 +420,14 @@ class App extends BaseConfig */ public bool $CSPEnabled = false; + /** + * -------------------------------------------------------------------------- + * Media root folder + * -------------------------------------------------------------------------- + * Defines the root folder for media files storage + */ + public string $mediaRoot = 'media'; + /** * -------------------------------------------------------------------------- * Instance / Site Config @@ -231,7 +444,7 @@ class App extends BaseConfig */ public array $siteIcon = [ 'ico' => '/favicon.ico', - '64' => '/icon-64.png', + '64' => '/icon-64.png', '180' => '/icon-180.png', '192' => '/icon-192.png', '512' => '/icon-512.png', @@ -244,43 +457,5 @@ class App extends BaseConfig */ public ?int $storageLimit = null; - /** - * Bandwidth limit (per month) in Gigabytes - */ - public ?int $bandwidthLimit = null; - public ?string $legalNoticeURL = null; - - /** - * AuthToken Config Constructor - */ - public function __construct() - { - parent::__construct(); - - if (is_string($this->proxyIPs)) { - $array = json_decode($this->proxyIPs, true); - if (is_array($array)) { - $this->proxyIPs = $array; - } - } - } - - /** - * Override parent initEnvValue() to allow for direct setting to array properties values from ENV - * - * In order to set array properties via ENV vars we need to set the property to a string value first. - * - * @param mixed $property - */ - #[Override] - protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void - { - // if attempting to set property from ENV, first set to empty string - if ($name === 'proxyIPs' && $this->getEnvValue($name, $prefix, $shortPrefix) !== null) { - $property = ''; - } - - parent::initEnvValue($property, $name, $prefix, $shortPrefix); - } } diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php index 3fd8e175..f314d3d2 100644 --- a/app/Config/Autoload.php +++ b/app/Config/Autoload.php @@ -27,39 +27,42 @@ class Autoload extends AutoloadConfig * their location on the file system. These are used by the autoloader * to locate files the first time they have been instantiated. * - * The 'Config' (APPPATH . 'Config') and 'CodeIgniter' (SYSTEMPATH) are - * already mapped for you. - * - * You may change the name of the 'App' namespace if you wish, + * The '/app' and '/system' directories are already mapped for you. + * you may change the name of the 'App' namespace if you wish, * but this should be done prior to creating any namespaced classes, * else you will need to modify all of those classes for this to work. * - * @var array|string> + * Prototype: + * + * $psr4 = [ + * 'CodeIgniter' => SYSTEMPATH, + * 'App' => APPPATH + * ]; + * + * @var array */ public $psr4 = [ - APP_NAMESPACE => APPPATH, - 'Modules' => ROOTPATH . 'modules/', - 'Modules\Admin' => ROOTPATH . 'modules/Admin/', - 'Modules\Analytics' => ROOTPATH . 'modules/Analytics/', - 'Modules\Api\Rest\V1' => ROOTPATH . 'modules/Api/Rest/V1', - 'Modules\Auth' => ROOTPATH . 'modules/Auth/', - 'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse/', - 'Modules\Install' => ROOTPATH . 'modules/Install/', - 'Modules\Media' => ROOTPATH . 'modules/Media/', - 'Modules\MediaClipper' => ROOTPATH . 'modules/MediaClipper/', - 'Modules\Platforms' => ROOTPATH . 'modules/Platforms/', - 'Modules\Plugins' => ROOTPATH . 'modules/Plugins/', - 'Modules\PodcastImport' => ROOTPATH . 'modules/PodcastImport/', + APP_NAMESPACE => APPPATH, + 'Modules' => ROOTPATH . 'modules/', + 'Modules\Admin' => ROOTPATH . 'modules/Admin/', + 'Modules\Auth' => ROOTPATH . 'modules/Auth/', + 'Modules\Analytics' => ROOTPATH . 'modules/Analytics/', + 'Modules\Install' => ROOTPATH . 'modules/Install/', + 'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse/', + 'Modules\WebSub' => ROOTPATH . 'modules/WebSub/', + 'Modules\Api\Rest\V1' => ROOTPATH . 'modules/Api/Rest/V1', 'Modules\PremiumPodcasts' => ROOTPATH . 'modules/PremiumPodcasts/', - 'Modules\Update' => ROOTPATH . 'modules/Update/', - 'Modules\WebSub' => ROOTPATH . 'modules/WebSub/', - 'Themes' => ROOTPATH . 'themes', - 'ViewComponents' => APPPATH . 'Libraries/ViewComponents/', - 'ViewThemes' => APPPATH . 'Libraries/ViewThemes/', + 'Config' => APPPATH . 'Config/', + 'ViewComponents' => APPPATH . 'Libraries/ViewComponents/', + 'ViewThemes' => APPPATH . 'Libraries/ViewThemes/', + 'MediaClipper' => APPPATH . 'Libraries/MediaClipper/', + 'Vite' => APPPATH . 'Libraries/Vite/', + 'Themes' => ROOTPATH . 'themes', ]; /** * ------------------------------------------------------------------- + * Class Map * ------------------------------------------------------------------- * The class map provides a map of class names and their exact * location on the drive. Classes loaded in this manner will have @@ -86,25 +89,12 @@ class Autoload extends AutoloadConfig * or for loading functions. * * Prototype: - * + * ``` * $files = [ * '/path/to/my/file.php', * ]; - * - * @var list + * ``` + * @var array */ - public $files = []; - - /** - * ------------------------------------------------------------------- - * Helpers - * ------------------------------------------------------------------- - * Prototype: - * $helpers = [ - * 'form', - * ]; - * - * @var list - */ - public $helpers = ['auth', 'setting', 'plugins']; + public $files = [APPPATH . 'Libraries/ViewComponents/Helpers/view_components_helper.php']; } diff --git a/app/Config/Boot/development.php b/app/Config/Boot/development.php index e131d316..8193a56a 100644 --- a/app/Config/Boot/development.php +++ b/app/Config/Boot/development.php @@ -9,10 +9,8 @@ declare(strict_types=1); * In development, we want to show as many errors as possible to help * make sure they don't make it to production. And save us hours of * painful debugging. - * - * If you set 'display_errors' to '1', CI4's detailed error report will show. */ -error_reporting(E_ALL); +error_reporting(-1); ini_set('display_errors', '1'); /** diff --git a/app/Config/Boot/production.php b/app/Config/Boot/production.php index 9d22b60a..4cf210d8 100644 --- a/app/Config/Boot/production.php +++ b/app/Config/Boot/production.php @@ -8,13 +8,9 @@ declare(strict_types=1); * -------------------------------------------------------------------------- * Don't show ANY in production environments. Instead, let the system catch * it and display a generic error message. - * - * If you set 'display_errors' to '1', CI4's detailed error report will show. */ -error_reporting(E_ALL & ~E_DEPRECATED); -// If you want to suppress more types of errors. -// error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED); ini_set('display_errors', '0'); +error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED); /** * -------------------------------------------------------------------------- diff --git a/app/Config/Boot/testing.php b/app/Config/Boot/testing.php index 46e757da..56c22a9c 100644 --- a/app/Config/Boot/testing.php +++ b/app/Config/Boot/testing.php @@ -2,12 +2,6 @@ declare(strict_types=1); -/* - * The environment testing is reserved for PHPUnit testing. It has special - * conditions built into the framework at various places to assist with that. - * You can’t use it for your development. - */ - /** * -------------------------------------------------------------------------- * ERROR DISPLAY @@ -16,7 +10,7 @@ declare(strict_types=1); * make sure they don't make it to production. And save us hours of * painful debugging. */ -error_reporting(E_ALL); +error_reporting(-1); ini_set('display_errors', '1'); /** diff --git a/app/Config/CURLRequest.php b/app/Config/CURLRequest.php index 4dbb7afa..a0484ca7 100644 --- a/app/Config/CURLRequest.php +++ b/app/Config/CURLRequest.php @@ -8,19 +8,6 @@ use CodeIgniter\Config\BaseConfig; class CURLRequest extends BaseConfig { - /** - * -------------------------------------------------------------------------- - * CURLRequest Share Connection Options - * -------------------------------------------------------------------------- - * - * Share connection options between requests. - * - * @var list - * - * @see https://www.php.net/manual/en/curl.constants.php#constant.curl-lock-data-connect - */ - public array $shareConnectionOptions = [CURL_LOCK_DATA_CONNECT, CURL_LOCK_DATA_DNS]; - /** * -------------------------------------------------------------------------- * CURLRequest Share Options @@ -31,5 +18,5 @@ class CURLRequest extends BaseConfig * If true, all the options won't be reset between requests. * It may cause an error request with unnecessary headers. */ - public bool $shareOptions = false; + public bool $shareOptions = true; } diff --git a/app/Config/Cache.php b/app/Config/Cache.php index bbf812f9..4266fb6a 100644 --- a/app/Config/Cache.php +++ b/app/Config/Cache.php @@ -4,8 +4,6 @@ declare(strict_types=1); namespace Config; -use CodeIgniter\Cache\CacheInterface; -use CodeIgniter\Cache\Handlers\ApcuHandler; use CodeIgniter\Cache\Handlers\DummyHandler; use CodeIgniter\Cache\Handlers\FileHandler; use CodeIgniter\Cache\Handlers\MemcachedHandler; @@ -37,6 +35,37 @@ class Cache extends BaseConfig */ public string $backupHandler = 'dummy'; + /** + * -------------------------------------------------------------------------- + * Cache Directory Path + * -------------------------------------------------------------------------- + * + * The path to where cache files should be stored, if using a file-based + * system. + * + * @deprecated Use the driver-specific variant under $file + */ + public string $storePath = WRITEPATH . 'cache/'; + + /** + * -------------------------------------------------------------------------- + * Cache Include Query String + * -------------------------------------------------------------------------- + * + * Whether to take the URL query string into consideration when generating + * output cache files. Valid options are: + * + * false = Disabled + * true = Enabled, take all query parameters into account. + * Please be aware that this may result in numerous cache + * files generated for the same page over and over again. + * array('q') = Enabled, but only take into account the specified list + * of query parameters. + * + * @var boolean|string[] + */ + public bool | array $cacheQueryString = false; + /** * -------------------------------------------------------------------------- * Key Prefix @@ -68,7 +97,6 @@ class Cache extends BaseConfig * A string of reserved characters that will not be allowed in keys or tags. * Strings that violate this restriction will cause handlers to throw. * Default: {}()/\@: - * * Note: The default set is required for PSR-6 compliance. */ public string $reservedCharacters = '{}()/\@:'; @@ -77,34 +105,32 @@ class Cache extends BaseConfig * -------------------------------------------------------------------------- * File settings * -------------------------------------------------------------------------- - * * Your file storage preferences can be specified below, if you are using * the File driver. * - * @var array{storePath?: string, mode?: int} + * @var array */ public array $file = [ 'storePath' => WRITEPATH . 'cache/', - 'mode' => 0640, + 'mode' => 0640, ]; /** * ------------------------------------------------------------------------- * Memcached settings * ------------------------------------------------------------------------- - * * Your Memcached servers can be specified below, if you are using * the Memcached drivers. * * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached * - * @var array{host?: string, port?: int, weight?: int, raw?: bool} + * @var array */ public array $memcached = [ - 'host' => '127.0.0.1', - 'port' => 11211, + 'host' => '127.0.0.1', + 'port' => 11211, 'weight' => 1, - 'raw' => false, + 'raw' => false, ]; /** @@ -114,24 +140,14 @@ class Cache extends BaseConfig * Your Redis server can be specified below, if you are using * the Redis or Predis drivers. * - * @var array{ - * host?: string, - * password?: string|null, - * port?: int, - * timeout?: int, - * async?: bool, - * persistent?: bool, - * database?: int - * } + * @var array */ public array $redis = [ - 'host' => '127.0.0.1', - 'password' => null, - 'port' => 6379, - 'timeout' => 0, - 'async' => false, // specific to Predis and ignored by the native Redis extension - 'persistent' => false, - 'database' => 0, + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'timeout' => 0, + 'database' => 0, ]; /** @@ -142,58 +158,14 @@ class Cache extends BaseConfig * This is an array of cache engine alias' and class names. Only engines * that are listed here are allowed to be used. * - * @var array> + * @var array */ public array $validHandlers = [ - 'apcu' => ApcuHandler::class, - 'dummy' => DummyHandler::class, - 'file' => FileHandler::class, + 'dummy' => DummyHandler::class, + 'file' => FileHandler::class, 'memcached' => MemcachedHandler::class, - 'predis' => PredisHandler::class, - 'redis' => RedisHandler::class, - 'wincache' => WincacheHandler::class, + 'predis' => PredisHandler::class, + 'redis' => RedisHandler::class, + 'wincache' => WincacheHandler::class, ]; - - /** - * -------------------------------------------------------------------------- - * Web Page Caching: Cache Include Query String - * -------------------------------------------------------------------------- - * - * Whether to take the URL query string into consideration when generating - * output cache files. Valid options are: - * - * false = Disabled - * true = Enabled, take all query parameters into account. - * Please be aware that this may result in numerous cache - * files generated for the same page over and over again. - * ['q'] = Enabled, but only take into account the specified list - * of query parameters. - * - * @var bool|list - */ - public $cacheQueryString = false; - - /** - * -------------------------------------------------------------------------- - * Web Page Caching: Cache Status Codes - * -------------------------------------------------------------------------- - * - * HTTP status codes that are allowed to be cached. Only responses with - * these status codes will be cached by the PageCache filter. - * - * Default: [] - Cache all status codes (backward compatible) - * - * Recommended: [200] - Only cache successful responses - * - * You can also use status codes like: - * [200, 404, 410] - Cache successful responses and specific error codes - * [200, 201, 202, 203, 204] - All 2xx successful responses - * - * WARNING: Using [] may cache temporary error pages (404, 500, etc). - * Consider restricting to [200] for production applications to avoid - * caching errors that should be temporary. - * - * @var list - */ - public array $cacheStatusCodes = []; } diff --git a/app/Config/Colors.php b/app/Config/Colors.php index 49618892..83ac145e 100644 --- a/app/Config/Colors.php +++ b/app/Config/Colors.php @@ -14,136 +14,136 @@ class Colors extends BaseConfig public array $themes = [ /* Castopod's brand color */ 'pine' => [ - 'accent-base' => [174, 100, 29], - 'accent-hover' => [172, 100, 17], - 'accent-muted' => [131, 100, 12], + 'accent-base' => [174, 100, 29], + 'accent-hover' => [172, 100, 17], + 'accent-muted' => [131, 100, 12], 'accent-contrast' => [0, 0, 100], 'heading-foreground' => [172, 100, 17], 'heading-background' => [111, 64, 94], - 'background-elevated' => [0, 0, 100], - 'background-base' => [173, 44, 96], + 'background-elevated' => [0, 0, 100], + 'background-base' => [173, 44, 96], 'background-navigation' => [172, 100, 17], - 'background-header' => [172, 100, 17], - 'background-highlight' => [111, 64, 94], - 'background-backdrop' => [0, 0, 50], + 'background-header' => [172, 100, 17], + 'background-highlight' => [111, 64, 94], + 'background-backdrop' => [0, 0, 50], - 'border-subtle' => [111, 42, 86], - 'border-contrast' => [0, 0, 0], + 'border-subtle' => [111, 42, 86], + 'border-contrast' => [0, 0, 0], 'border-navigation' => [131, 100, 12], - 'text-base' => [158, 8, 3], + 'text-base' => [158, 8, 3], 'text-muted' => [172, 8, 38], ], /* Red / Rose color */ 'crimson' => [ - 'accent-base' => [350, 87, 61], - 'accent-hover' => [348, 75, 40], - 'accent-muted' => [348, 73, 32], + 'accent-base' => [350, 87, 61], + 'accent-hover' => [348, 75, 40], + 'accent-muted' => [348, 73, 32], 'accent-contrast' => [0, 0, 100], 'heading-foreground' => [348, 73, 32], 'heading-background' => [344, 79, 96], - 'background-elevated' => [0, 0, 100], - 'background-base' => [350, 44, 96], - 'background-header' => [348, 75, 40], + 'background-elevated' => [0, 0, 100], + 'background-base' => [350, 44, 96], + 'background-header' => [348, 75, 40], 'background-highlight' => [344, 79, 96], - 'background-backdrop' => [0, 0, 50], + 'background-backdrop' => [0, 0, 50], - 'border-subtle' => [348, 42, 86], + 'border-subtle' => [348, 42, 86], 'border-contrast' => [0, 0, 0], - 'text-base' => [340, 8, 3], + 'text-base' => [340, 8, 3], 'text-muted' => [345, 8, 38], ], /* Blue color */ 'lake' => [ - 'accent-base' => [194, 100, 44], - 'accent-hover' => [194, 100, 22], - 'accent-muted' => [195, 100, 11], + 'accent-base' => [194, 100, 44], + 'accent-hover' => [194, 100, 22], + 'accent-muted' => [195, 100, 11], 'accent-contrast' => [0, 0, 100], 'heading-foreground' => [194, 100, 22], 'heading-background' => [195, 100, 92], - 'background-elevated' => [0, 0, 100], - 'background-base' => [196, 44, 96], - 'background-header' => [194, 100, 22], + 'background-elevated' => [0, 0, 100], + 'background-base' => [196, 44, 96], + 'background-header' => [194, 100, 22], 'background-highlight' => [195, 100, 92], - 'background-backdrop' => [0, 0, 50], + 'background-backdrop' => [0, 0, 50], - 'border-subtle' => [195, 42, 86], + 'border-subtle' => [195, 42, 86], 'border-contrast' => [0, 0, 0], - 'text-base' => [194, 8, 3], + 'text-base' => [194, 8, 3], 'text-muted' => [195, 8, 38], ], /* Orange color */ 'amber' => [ - 'accent-base' => [17, 100, 57], - 'accent-hover' => [17, 100, 35], - 'accent-muted' => [17, 100, 24], + 'accent-base' => [17, 100, 57], + 'accent-hover' => [17, 100, 35], + 'accent-muted' => [17, 100, 24], 'accent-contrast' => [0, 0, 100], 'heading-foreground' => [17, 100, 35], 'heading-background' => [17, 100, 89], - 'background-elevated' => [0, 0, 100], - 'background-base' => [15, 44, 96], - 'background-header' => [17, 100, 35], + 'background-elevated' => [0, 0, 100], + 'background-base' => [15, 44, 96], + 'background-header' => [17, 100, 35], 'background-highlight' => [17, 100, 89], - 'background-backdrop' => [0, 0, 50], + 'background-backdrop' => [0, 0, 50], - 'border-subtle' => [17, 42, 86], + 'border-subtle' => [17, 42, 86], 'border-contrast' => [0, 0, 0], - 'text-base' => [15, 8, 3], + 'text-base' => [15, 8, 3], 'text-muted' => [17, 8, 38], ], /* Violet color */ 'jacaranda' => [ - 'accent-base' => [254, 72, 52], - 'accent-hover' => [254, 73, 30], - 'accent-muted' => [254, 71, 19], + 'accent-base' => [254, 72, 52], + 'accent-hover' => [254, 73, 30], + 'accent-muted' => [254, 71, 19], 'accent-contrast' => [0, 0, 100], 'heading-foreground' => [254, 73, 30], 'heading-background' => [254, 73, 84], - 'background-elevated' => [0, 0, 100], - 'background-base' => [253, 44, 96], - 'background-header' => [254, 73, 30], + 'background-elevated' => [0, 0, 100], + 'background-base' => [253, 44, 96], + 'background-header' => [254, 73, 30], 'background-highlight' => [254, 88, 91], - 'background-backdrop' => [0, 0, 50], + 'background-backdrop' => [0, 0, 50], - 'border-subtle' => [254, 42, 86], + 'border-subtle' => [254, 42, 86], 'border-contrast' => [0, 0, 0], - 'text-base' => [253, 8, 3], + 'text-base' => [253, 8, 3], 'text-muted' => [254, 8, 38], ], /* Black color */ 'onyx' => [ - 'accent-base' => [240, 17, 2], - 'accent-hover' => [240, 17, 17], - 'accent-muted' => [240, 17, 17], + 'accent-base' => [240, 17, 2], + 'accent-hover' => [240, 17, 17], + 'accent-muted' => [240, 17, 17], 'accent-contrast' => [0, 0, 100], 'heading-foreground' => [240, 17, 17], 'heading-background' => [240, 17, 94], - 'background-elevated' => [0, 0, 100], - 'background-base' => [240, 17, 96], - 'background-header' => [240, 12, 17], + 'background-elevated' => [0, 0, 100], + 'background-base' => [240, 17, 96], + 'background-header' => [240, 12, 17], 'background-highlight' => [240, 17, 94], - 'background-backdrop' => [0, 0, 50], + 'background-backdrop' => [0, 0, 50], - 'border-subtle' => [240, 17, 86], + 'border-subtle' => [240, 17, 86], 'border-contrast' => [0, 0, 0], - 'text-base' => [240, 8, 3], + 'text-base' => [240, 8, 3], 'text-muted' => [240, 8, 38], ], ]; diff --git a/app/Config/Constants.php b/app/Config/Constants.php index e23c0e0d..b52f7ea4 100644 --- a/app/Config/Constants.php +++ b/app/Config/Constants.php @@ -11,7 +11,7 @@ declare(strict_types=1); | | NOTE: this constant is updated upon release with Continuous Integration. */ -defined('CP_VERSION') || define('CP_VERSION', '2.0.0-next.3'); +defined('CP_VERSION') || define('CP_VERSION', '1.0.0-beta.24'); /* | -------------------------------------------------------------------- @@ -24,23 +24,10 @@ defined('CP_VERSION') || define('CP_VERSION', '2.0.0-next.3'); | classes should use. | | NOTE: changing this will require manually modifying the - | existing namespaces of App* namespaced-classes. + | existing namespaces of App\* namespaced-classes. */ defined('APP_NAMESPACE') || define('APP_NAMESPACE', 'App'); -/* - | -------------------------------------------------------------------- - | Plugins Path - | -------------------------------------------------------------------- - | - | This defines the folder in which plugins will live. - */ -defined('PLUGINS_PATH') || - define('PLUGINS_PATH', ROOTPATH . 'plugins' . DIRECTORY_SEPARATOR); - -defined('PLUGINS_KEY_PATTERN') || - define('PLUGINS_KEY_PATTERN', '[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9]([_.-]?[a-z0-9]+)*'); - /* | -------------------------------------------------------------------------- | Composer Path @@ -104,3 +91,18 @@ defined('EXIT_USER_INPUT') || define('EXIT_USER_INPUT', 7); // invalid user inpu defined('EXIT_DATABASE') || define('EXIT_DATABASE', 8); // database error defined('EXIT__AUTO_MIN') || define('EXIT__AUTO_MIN', 9); // lowest automatically-assigned error code defined('EXIT__AUTO_MAX') || define('EXIT__AUTO_MAX', 125); // highest automatically-assigned error code + +/** + * @deprecated Use \CodeIgniter\Events\Events::PRIORITY_LOW instead. + */ +define('EVENT_PRIORITY_LOW', 200); + +/** + * @deprecated Use \CodeIgniter\Events\Events::PRIORITY_NORMAL instead. + */ +define('EVENT_PRIORITY_NORMAL', 100); + +/** + * @deprecated Use \CodeIgniter\Events\Events::PRIORITY_HIGH instead. + */ +define('EVENT_PRIORITY_HIGH', 10); diff --git a/app/Config/ContentSecurityPolicy.php b/app/Config/ContentSecurityPolicy.php index 99fa0b0a..301f7731 100644 --- a/app/Config/ContentSecurityPolicy.php +++ b/app/Config/ContentSecurityPolicy.php @@ -26,77 +26,37 @@ class ContentSecurityPolicy extends BaseConfig */ public ?string $reportURI = null; - /** - * Specifies a reporting endpoint to which violation reports ought to be sent. - */ - public ?string $reportTo = null; - /** * Instructs user agents to rewrite URL schemes, changing HTTP to HTTPS. This directive is for websites with large * numbers of old URLs that need to be rewritten. */ public bool $upgradeInsecureRequests = false; - // ------------------------------------------------------------------------- - // CSP DIRECTIVES SETTINGS - // NOTE: once you set a policy to 'none', it cannot be further restricted - // ------------------------------------------------------------------------- - /** - * Will default to `'self'` if not overridden + * Will default to self if not overridden * - * @var list|string|null + * @var string|string[]|null */ public string | array | null $defaultSrc = null; /** * Lists allowed scripts' URLs. * - * @var list|string + * @var string|string[] */ public string | array $scriptSrc = 'self'; - /** - * Specifies valid sources for JavaScript - HTML); - - if ($this->title) { - $this->tag('title', esc($this->title)); - } - - if (url_is(route_to('admin') . '*') || url_is(base_url(config('Auth')->gateway) . '*')) { - // restricted admin and auth areas, do not index - $this->meta('robots', 'noindex'); - } else { - // public website, set siteHead hook only there - service('plugins') - ->siteHead($this); - } - - $head = ''; - foreach ($this->tags as $tag) { - if ($tag['value'] === null) { - $head .= <<stringify_attributes($tag['attributes'])}/> - HTML; - } else { - $head .= <<stringify_attributes($tag['attributes'])}>{$tag['value']} - HTML; - } - } - - $head .= $this->rawContent . ''; - - // reset head for next render - $this->title = null; - $this->tags = []; - $this->rawContent = ''; - - return $head; - } - - public function title(string $title): self - { - $this->title = $title; - return $this->meta('title', $title) - ->og('title', $title) - ->twitter('title', $title); - } - - public function description(string $desc): self - { - return $this->meta('description', $desc) - ->og('description', $desc) - ->twitter('description', $desc); - } - - public function image(string $url, string $card = 'summary_large_image'): self - { - return $this->og('image', $url) - ->twitter('card', $card) - ->twitter('image', $url); - } - - public function canonical(string $url): self - { - return $this->tag('link', null, [ - 'rel' => 'canonical', - 'href' => $url, - ]); - } - - public function twitter(string $name, string $value): self - { - $this->meta("twitter:{$name}", $value); - return $this; - } - - /** - * @param array $attributes - */ - public function tag(string $name, ?string $value = null, array $attributes = []): self - { - $this->tags[] = [ - 'name' => $name, - 'value' => $value, - 'attributes' => $attributes, - ]; - - return $this; - } - - public function meta(string $name, string $content): self - { - $this->tag('meta', null, [ - 'name' => $name, - 'content' => $content, - ]); - - return $this; - } - - public function og(string $name, string $content): self - { - $this->meta('og:' . $name, $content); - - return $this; - } - - public function appendRawContent(string $content): self - { - $this->rawContent .= $content; - - return $this; - } - - /** - * @param array $attributes - */ - private function stringify_attributes(array $attributes): string - { - return stringify_attributes($attributes); - } -} diff --git a/app/Libraries/MediaClipper/Config/MediaClipper.php b/app/Libraries/MediaClipper/Config/MediaClipper.php new file mode 100644 index 00000000..e0394165 --- /dev/null +++ b/app/Libraries/MediaClipper/Config/MediaClipper.php @@ -0,0 +1,346 @@ +>> + */ + public array $formats = [ + 'landscape' => [ + 'width' => 1920, + 'height' => 1080, + 'cover' => [ + 'width' => 480, + 'height' => 480, + 'radius' => 24, + 'x' => 150, + 'y' => 120, + ], + 'quotes' => [ + 'width' => 192, + 'height' => 192, + 'x' => 810, + 'y' => 210, + ], + 'podcastTitle' => [ + 'fontsize' => 20, + 'x' => 150, + 'y' => 620, + 'lineWidth' => 510, + ], + 'episodeTitle' => [ + 'fontsize' => 32, + 'x' => 150, + 'y' => 660, + 'lines' => 3, + 'lineWidth' => 510, + 'lineHeight' => 1.5, + ], + 'episodeNumbering' => [ + 'fontsize' => 18, + 'paddingX' => 10, + 'paddingY' => 5, + 'marginRight' => 10, + ], + 'timestamp' => [ + 'fontsize' => 32, + 'padding' => 10, + 'x' => 1620, + 'y' => 985, + ], + 'watermark' => [ + 'width' => 90, + 'height' => 72, + 'x' => 140, + 'y' => 960, + ], + 'progressbar' => [ + 'height' => 10, + ], + 'soundwaves' => [ + 'width' => 192, + 'height' => 108, + 'rescaleWidth' => 1920, + 'rescaleHeight' => 540, + 'x' => 0, + 'y' => 810, + 'mask' => APPPATH . 'Libraries/MediaClipper/soundwaves-mask-landscape.png', + ], + 'subtitles' => [ + 'fontsize' => 18, + 'marginL' => 180, + 'marginR' => 20, + 'marginV' => 85, + ], + ], + 'portrait' => [ + 'width' => 1080, + 'height' => 1920, + 'cover' => [ + 'width' => 280, + 'height' => 280, + 'radius' => 16, + 'x' => 50, + 'y' => 50, + ], + 'quotes' => [ + 'width' => 256, + 'height' => 256, + 'x' => 40, + 'y' => 520, + ], + 'podcastTitle' => [ + 'fontsize' => 32, + 'x' => 360, + 'y' => 55, + 'lineWidth' => 670, + ], + 'episodeTitle' => [ + 'fontsize' => 42, + 'x' => 360, + 'y' => 110, + 'lines' => 3, + 'lineWidth' => 670, + 'lineHeight' => 1.5, + ], + 'episodeNumbering' => [ + 'fontsize' => 28, + 'paddingX' => 10, + 'paddingY' => 10, + 'marginRight' => 10, + ], + 'timestamp' => [ + 'fontsize' => 48, + 'padding' => 14, + 'x' => 734, + 'y' => 1800, + ], + 'watermark' => [ + 'width' => 120, + 'height' => 96, + 'x' => 130, + 'y' => 1770, + ], + 'progressbar' => [ + 'height' => 10, + ], + 'soundwaves' => [ + 'width' => 54, + 'height' => 96, + 'rescaleWidth' => 1080, + 'rescaleHeight' => 1920, + 'x' => 0, + 'y' => 960, + 'mask' => APPPATH . 'Libraries/MediaClipper/soundwaves-mask-portrait.png', + ], + 'subtitles' => [ + 'fontsize' => 16, + 'marginL' => 40, + 'marginR' => 25, + 'marginV' => 97, + ], + ], + 'squared' => [ + 'width' => 1200, + 'height' => 1200, + 'cover' => [ + 'width' => 200, + 'height' => 200, + 'radius' => 16, + 'x' => 40, + 'y' => 40, + ], + 'quotes' => [ + 'width' => 200, + 'height' => 200, + 'x' => 85, + 'y' => 320, + ], + 'podcastTitle' => [ + 'fontsize' => 28, + 'x' => 260, + 'y' => 50, + 'lines' => 1, + 'lineWidth' => 800, + ], + 'episodeTitle' => [ + 'fontsize' => 36, + 'x' => 260, + 'y' => 90, + 'lines' => 2, + 'lineWidth' => 850, + 'lineHeight' => 1.5, + ], + 'episodeNumbering' => [ + 'fontsize' => 24, + 'paddingX' => 10, + 'paddingY' => 5, + 'marginRight' => 10, + ], + 'timestamp' => [ + 'fontsize' => 48, + 'padding' => 10, + 'x' => 855, + 'y' => 1070, + ], + 'watermark' => [ + 'width' => 120, + 'height' => 96, + 'x' => 130, + 'y' => 1040, + ], + 'progressbar' => [ + 'height' => 10, + ], + 'soundwaves' => [ + 'width' => 60, + 'height' => 60, + 'rescaleWidth' => 1200, + 'rescaleHeight' => 1200, + 'x' => 0, + 'y' => 600, + 'mask' => APPPATH . 'Libraries/MediaClipper/soundwaves-mask-squared.png', + ], + 'subtitles' => [ + 'fontsize' => 20, + 'marginL' => 60, + 'marginR' => 20, + 'marginV' => 98, + ], + ], + ]; + + /** + * @var array> + */ + public array $themes = [ + 'pine' => [ + // Previews must be a HSL colorscheme string + 'preview' => '174 100% 29%', + 'preview-background' => '172 100% 17%', + // arrays are rgb + 'background' => [0, 86, 74], + 'text' => [255, 255, 255], + // subtitle hex color is BGR (Blue, Green, Red), + 'subtitles' => 'FFFFFF', + // quotes image MUST BE black + 'quotes' => [0, 148, 134], + 'episodeNumberingBg' => [0, 61, 11], + 'episodeNumberingText' => [255, 255, 255], + 'progressbar' => '009486', + 'timestampBg' => '00564A', + 'timestampText' => 'FFFFFF', + 'watermarkBg' => '00564A', + 'soundwaves' => [231, 249, 228], + ], + 'crimson' => [ + // Preview must be a HSL colorscheme string + 'preview' => '350 87% 61%', + 'preview-background' => '348 75% 40%', + // arrays are rgb + 'background' => [179, 31, 57], + 'text' => [255, 255, 255], + // subtitle hex color is BGR (Blue, Green, Red), + 'subtitles' => 'FFFFFF', + // quotes image MUST BE black + 'quotes' => [242, 70, 100], + 'episodeNumberingBg' => [152, 16, 43], + 'episodeNumberingText' => [255, 255, 255], + 'progressbar' => 'F24664', + 'timestampBg' => 'B31F39', + 'timestampText' => 'FFFFFF', + 'watermarkBg' => 'B31F39', + 'soundwaves' => [253, 206, 215], + ], + 'lake' => [ + // Preview must be a HSL colorscheme string + 'preview' => '194 100% 44%', + 'preview-background' => '194 100% 22%', + // arrays are rgb + 'background' => [0, 86, 113], + 'text' => [255, 255, 255], + // subtitle hex color is BGR (Blue, Green, Red), + 'subtitles' => 'FFFFFF', + // quotes image MUST BE black + 'quotes' => [0, 171, 225], + 'episodeNumberingBg' => [0, 43, 57], + 'episodeNumberingText' => [255, 255, 255], + 'progressbar' => '00ABE1', + 'timestampBg' => '005671', + 'timestampText' => 'FFFFFF', + 'watermarkBg' => '005671', + 'soundwaves' => [214, 245, 255], + ], + 'amber' => [ + // Preview must be a HSL colorscheme string + 'preview' => '17 100% 57%', + 'preview-background' => '17 100% 35%', + // arrays are rgb + 'background' => [177, 50, 0], + 'text' => [255, 255, 255], + // subtitle hex color is BGR (Blue, Green, Red), + 'subtitles' => 'FFFFFF', + // quotes image MUST BE black + 'quotes' => [255, 96, 34], + 'episodeNumberingBg' => [121, 34, 0], + 'episodeNumberingText' => [255, 255, 255], + 'progressbar' => 'FF6022', + 'timestampBg' => 'B13200', + 'timestampText' => 'FFFFFF', + 'watermarkBg' => 'B13200', + 'soundwaves' => [255, 213, 197], + ], + 'jacaranda' => [ + // Preview must be a HSL colorscheme string + 'preview' => '254 72% 52%', + 'preview-background' => '254 73% 30%', + // arrays are rgb + 'background' => [47, 21, 132], + 'text' => [255, 255, 255], + // subtitle hex color is BGR (Blue, Green, Red), + 'subtitles' => 'FFFFFF', + // quotes image MUST BE black + 'quotes' => [86, 45, 221], + 'episodeNumberingBg' => [30, 14, 84], + 'episodeNumberingText' => [255, 255, 255], + 'progressbar' => '562DDD', + 'timestampBg' => '2F1584', + 'timestampText' => 'FFFFFF', + 'watermarkBg' => '2F1584', + 'soundwaves' => [199, 185, 244], + ], + 'onyx' => [ + // Preview must be a HSL colorscheme string + 'preview' => '240 17% 2%', + 'preview-background' => '240 17% 2%', + // arrays are rgb + 'background' => [5, 5, 7], + 'text' => [255, 255, 255], + // subtitle hex color is BGR (Blue, Green, Red), + 'subtitles' => 'FFFFFF', + // quotes image MUST BE black + 'quotes' => [38, 38, 49], + 'episodeNumberingBg' => [0, 0, 0], + 'episodeNumberingText' => [255, 255, 255], + 'progressbar' => 'D5D5E1', + 'timestampBg' => '050507', + 'timestampText' => 'FFFFFF', + 'watermarkBg' => '050507', + 'soundwaves' => [213, 213, 225], + ], + ]; +} diff --git a/modules/MediaClipper/VideoClipper.php b/app/Libraries/MediaClipper/VideoClipper.php similarity index 91% rename from modules/MediaClipper/VideoClipper.php rename to app/Libraries/MediaClipper/VideoClipper.php index 55e320fb..1c97f7cc 100644 --- a/modules/MediaClipper/VideoClipper.php +++ b/app/Libraries/MediaClipper/VideoClipper.php @@ -8,13 +8,11 @@ declare(strict_types=1); * @link https://castopod.org/ */ -namespace Modules\MediaClipper; +namespace MediaClipper; use App\Entities\Episode; use Exception; use GdImage; -use Modules\Media\Entities\Transcript; -use Modules\Media\FileManagers\FileManagerInterface; /** * TODO: refactor this by splitting process modules into different classes (image generation, subtitles clip, video @@ -25,21 +23,21 @@ class VideoClipper /** * @var array */ - final public const array FONTS = [ - 'episodeTitle' => 'Rubik-Bold.ttf', - 'podcastTitle' => 'Inter-Regular.otf', - 'subtitles' => 'Inter-SemiBold', + public const FONTS = [ + 'episodeTitle' => 'Rubik-Bold.ttf', + 'podcastTitle' => 'Inter-Regular.otf', + 'subtitles' => 'Inter-SemiBold', 'episodeNumbering' => 'Inter-SemiBold.otf', - 'timestamp' => 'NotoSansMono-Regular.ttf', + 'timestamp' => 'NotoSansMono-Regular.ttf', ]; public ?string $logs = null; public bool $error = false; - public string $videoClipFileKey; + public string $videoClipFilePath; - public string $videoClipOutput; + protected string $videoClipOutput; protected float $duration; @@ -85,25 +83,26 @@ class VideoClipper $this->colors = config('MediaClipper') ->themes[$theme]; - /** @var FileManagerInterface $fileManager */ - $fileManager = service('file_manager'); + helper(['media']); - $this->audioInput = $fileManager->getFileInput($this->episode->audio->file_key); - $this->episodeCoverPath = $fileManager->getFileInput($this->episode->cover->file_key); + $this->audioInput = media_path($this->episode->audio->file_path); + $this->episodeCoverPath = media_path($this->episode->cover->file_path); + + $podcastFolder = media_path("podcasts/{$this->episode->podcast->handle}"); + + $this->videoClipOutput = $podcastFolder . "/{$this->episode->slug}-clip-{$this->start}-to-{$this->end}-{$this->format}-{$this->theme}.mp4"; + $this->videoClipFilePath = "podcasts/{$this->episode->podcast->handle}/{$this->episode->slug}-clip-{$this->start}-to-{$this->end}-{$this->format}-{$this->theme}.mp4"; // Temporary files to generate clip $tempFile = tempnam(WRITEPATH . 'temp', "{$this->episode->slug}-{$this->start}-{$this->end}"); if (! $tempFile) { throw new Exception( - 'Could not create temporary files, check for permissions on your ' . WRITEPATH . 'temp folder.', + 'Could not create temporary files, check for permissions on your ' . WRITEPATH . 'temp folder.' ); } - $this->videoClipFileKey = "podcasts/{$this->episode->podcast->handle}/{$this->episode->slug}-clip-{$this->start}-to-{$this->end}-{$this->format}-{$this->theme}.mp4"; - $this->tempFileOutput = $tempFile; - $this->videoClipOutput = $tempFile . '-video-clip.mp4'; $this->soundbiteOutput = $tempFile . '-soundbite.mp3'; $this->subtitlesClipOutput = $tempFile . '-subtitle.srt'; $this->videoClipBgOutput = $tempFile . '-bg.png'; @@ -117,26 +116,23 @@ class VideoClipper public function subtitlesClip(): void { - if (! $this->episode->transcript instanceof Transcript) { + if ($this->episode->transcript === null) { throw new Exception('Episode does not have a transcript!'); } - if ($this->episode->transcript->json_url) { - $this->generateSubtitlesClipFromJson($this->episode->transcript->json_key); + if ($this->episode->transcript->json_path) { + $this->generateSubtitlesClipFromJson($this->episode->transcript->json_path); } else { - $subtitlesInput = $this->episode->transcript->file_url; + $subtitlesInput = media_path($this->episode->transcript->file_path); $subtitleClipCmd = "ffmpeg -y -i {$subtitlesInput} -ss {$this->start} -t {$this->duration} {$this->subtitlesClipOutput}"; exec($subtitleClipCmd); } } - public function generateSubtitlesClipFromJson(string $jsonFileKey): void + public function generateSubtitlesClipFromJson(string $jsonFileInput): void { - /** @var FileManagerInterface $fileManager */ - $fileManager = service('file_manager'); - - $jsonTranscriptString = (string) $fileManager->getFileContents($jsonFileKey); - if ($jsonTranscriptString === '') { + $jsonTranscriptString = file_get_contents($jsonFileInput); + if ($jsonTranscriptString === false) { throw new Exception('Cannot get transcript json contents.'); } @@ -223,6 +219,7 @@ class VideoClipper public function getCmd(): string { + // @phpstan-ignore $filters = [ "[0:a]aformat=channel_layouts=mono,showwaves=s={$this->dimensions['soundwaves']['width']}x{$this->dimensions['soundwaves']['height']}:mode=cline:rate=10:colors=white,format=rgb24[waves]", "[waves]scale={$this->dimensions['width']}:{$this->dimensions['height']}:flags=neighbor[resizedwaves]", @@ -233,11 +230,11 @@ class VideoClipper '[m][a]alphamerge[waves_t3]', "[waves_t3]scale={$this->dimensions['soundwaves']['rescaleWidth']}:{$this->dimensions['soundwaves']['rescaleHeight']},lutrgb=r='if(gt(val,100),{$this->colors['soundwaves'][0]},val)':g='if(gt(val,100),{$this->colors['soundwaves'][1]},val)':b='if(gt(val,100),{$this->colors['soundwaves'][2]},val)'[waves_final]", "[1:v][waves_final]overlay=x={$this->dimensions['soundwaves']['x']}:y={$this->dimensions['soundwaves']['y']}:shortest=1,drawtext=fontfile=" . $this->getFont( - 'timestamp', + 'timestamp' ) . ":text='%{pts\:gmtime\:{$this->start}\:%H\\\\\\\\\\:%M\\\\\\\\\\:%S\}':x={$this->dimensions['timestamp']['x']}:y={$this->dimensions['timestamp']['y']}:fontsize={$this->dimensions['timestamp']['fontsize']}:fontcolor=0x{$this->colors['timestampText']}:box=1:boxcolor=0x{$this->colors['timestampBg']}:boxborderw={$this->dimensions['timestamp']['padding']}[v3]", "color=c=0x{$this->colors['progressbar']}:s={$this->dimensions['width']}x{$this->dimensions['progressbar']['height']}[progressbar]", "[v3][progressbar]overlay=-w+(w/{$this->duration})*t:0:shortest=1:format=rgb,subtitles={$this->subtitlesClipOutput}:fontsdir=" . config( - 'MediaClipper', + 'MediaClipper' )->fontsFolder . ":force_style='Fontname=" . self::FONTS['subtitles'] . ",Alignment=5,Fontsize={$this->dimensions['subtitles']['fontsize']},PrimaryColour=&H{$this->colors['subtitles']}&,BorderStyle=1,Outline=0,Shadow=0,MarginL={$this->dimensions['subtitles']['marginL']},MarginR={$this->dimensions['subtitles']['marginR']},MarginV={$this->dimensions['subtitles']['marginV']}'[outv]", "[6:v]scale={$this->dimensions['watermark']['width']}:{$this->dimensions['watermark']['height']}[watermark]", "color=0x{$this->colors['watermarkBg']}:{$this->dimensions['watermark']['width']}x{$this->dimensions['watermark']['height']}[over]", @@ -259,7 +256,6 @@ class VideoClipper "-f lavfi -i color=white:{$this->dimensions['width']}x{$this->dimensions['height']}", "-loop 1 -framerate 1 -i {$watermark}", '-filter_complex "' . implode(';', $filters) . '"', - '-t ' . $this->duration, '-map "[outfinal]"', '-map 0:a', '-acodec aac', @@ -301,7 +297,7 @@ class VideoClipper { $background = $this->generateBackground($this->dimensions['width'], $this->dimensions['height']); - if (! $background instanceof GdImage) { + if (! $background instanceof \GdImage) { return false; } @@ -313,7 +309,7 @@ class VideoClipper $scaledEpisodeCover = $this->scaleImage( $episodeCover, $this->dimensions['cover']['width'], - $this->dimensions['cover']['height'], + $this->dimensions['cover']['height'] ); if (! $scaledEpisodeCover) { @@ -332,7 +328,7 @@ class VideoClipper $this->dimensions['cover']['x'], $this->dimensions['cover']['y'], $this->dimensions['cover']['width'], - $this->dimensions['cover']['height'], + $this->dimensions['cover']['height'] ); if (! $isOverlaid) { @@ -357,13 +353,13 @@ class VideoClipper $this->dimensions['episodeTitle']['fontsize'], 0, $this->getFont('episodeTitle'), - $this->episode->title, + $this->episode->title ); $episodeNumberingBox = $this->calculateTextBox( $this->dimensions['episodeNumbering']['fontsize'], 0, $this->getFont('episodeNumbering'), - $this->episodeNumbering, + $this->episodeNumbering ); if (! $episodeTitleBox || ! $episodeNumberingBox) { return false; @@ -419,7 +415,7 @@ class VideoClipper $scaledQuotes = $this->scaleImage( $cleanedQuotes, $this->dimensions['quotes']['width'], - $this->dimensions['quotes']['height'], + $this->dimensions['quotes']['height'] ); if (! $scaledQuotes) { @@ -433,7 +429,7 @@ class VideoClipper $this->dimensions['quotes']['x'], $this->dimensions['quotes']['y'], $this->dimensions['quotes']['width'], - $this->dimensions['quotes']['height'], + $this->dimensions['quotes']['height'] ); // Save Image @@ -505,8 +501,8 @@ class VideoClipper { return match ($this->episode->cover->file_mimetype) { 'image/jpeg' => imagecreatefromjpeg($this->episodeCoverPath), - 'image/png' => imagecreatefrompng($this->episodeCoverPath), - default => imagecreate(1400, 1400), + 'image/png' => imagecreatefrompng($this->episodeCoverPath), + default => imagecreate(1400, 1400), }; } @@ -541,9 +537,9 @@ class VideoClipper # find unique color do { - $r = random_int(0, 255); - $g = random_int(0, 255); - $b = random_int(0, 255); + $r = rand(0, 255); + $g = rand(0, 255); + $b = rand(0, 255); } while (imagecolorexact($src, $r, $g, $b) < 0); $ns = $s * $q; @@ -564,6 +560,7 @@ class VideoClipper imagefill($img, 0, 0, $alphacolor); imagecopyresampled($img, $src, 0, 0, 0, 0, $ns, $ns, $s, $s); + imagedestroy($src); imagearc($img, $radius - 1, $radius - 1, $radius * 2, $radius * 2, 180, 270, $alphacolor); imagefilltoborder($img, 0, 0, $alphacolor, $alphacolor); @@ -585,6 +582,7 @@ class VideoClipper imagealphablending($dest, false); imagefilledrectangle($dest, 0, 0, $s, $s, $alphacolor); imagecopyresampled($dest, $img, 0, 0, 0, 0, $s, $s, $ns, $ns); + imagedestroy($img); # output image imagealphablending($source, false); @@ -593,6 +591,7 @@ class VideoClipper imagecopy($source, $dest, $ws - $corner, $hs - $corner, $corner, $corner, $corner, $corner); imagecopy($source, $dest, 0, $hs - $corner, 0, $corner, $corner, $corner); imagealphablending($source, true); + imagedestroy($dest); return $source; } @@ -603,7 +602,7 @@ class VideoClipper int $x, int $y, int $width, - int $height, + int $height ): bool { return imagecopy($background, $foreground, $x, $y, 0, 0, $width, $height); } @@ -643,7 +642,7 @@ class VideoClipper $y + $fontsize + ($leading * $i), $textColor, $fontPath, - $line, + $line ); } @@ -674,11 +673,11 @@ class VideoClipper $maxY = max([$bbox[1], $bbox[3], $bbox[5], $bbox[7]]); return [ - 'left' => abs($minX) - 1, - 'top' => abs($minY), - 'width' => $maxX - $minX, + 'left' => abs($minX) - 1, + 'top' => abs($minY), + 'width' => $maxX - $minX, 'height' => $maxY - $minY, - 'box' => $bbox, + 'box' => $bbox, ]; } diff --git a/modules/MediaClipper/Resources/castopod-logo.png b/app/Libraries/MediaClipper/castopod-logo.png similarity index 100% rename from modules/MediaClipper/Resources/castopod-logo.png rename to app/Libraries/MediaClipper/castopod-logo.png diff --git a/modules/MediaClipper/Resources/fonts/Inter-Regular.otf b/app/Libraries/MediaClipper/fonts/Inter-Regular.otf similarity index 100% rename from modules/MediaClipper/Resources/fonts/Inter-Regular.otf rename to app/Libraries/MediaClipper/fonts/Inter-Regular.otf diff --git a/modules/MediaClipper/Resources/fonts/Inter-SemiBold.otf b/app/Libraries/MediaClipper/fonts/Inter-SemiBold.otf similarity index 100% rename from modules/MediaClipper/Resources/fonts/Inter-SemiBold.otf rename to app/Libraries/MediaClipper/fonts/Inter-SemiBold.otf diff --git a/modules/MediaClipper/Resources/fonts/NotoSansMono-Regular.ttf b/app/Libraries/MediaClipper/fonts/NotoSansMono-Regular.ttf similarity index 100% rename from modules/MediaClipper/Resources/fonts/NotoSansMono-Regular.ttf rename to app/Libraries/MediaClipper/fonts/NotoSansMono-Regular.ttf diff --git a/modules/MediaClipper/Resources/fonts/Rubik-Bold.ttf b/app/Libraries/MediaClipper/fonts/Rubik-Bold.ttf similarity index 100% rename from modules/MediaClipper/Resources/fonts/Rubik-Bold.ttf rename to app/Libraries/MediaClipper/fonts/Rubik-Bold.ttf diff --git a/modules/MediaClipper/Resources/quotes.png b/app/Libraries/MediaClipper/quotes.png similarity index 100% rename from modules/MediaClipper/Resources/quotes.png rename to app/Libraries/MediaClipper/quotes.png diff --git a/modules/MediaClipper/Resources/soundwaves-mask-landscape.png b/app/Libraries/MediaClipper/soundwaves-mask-landscape.png similarity index 100% rename from modules/MediaClipper/Resources/soundwaves-mask-landscape.png rename to app/Libraries/MediaClipper/soundwaves-mask-landscape.png diff --git a/modules/MediaClipper/Resources/soundwaves-mask-portrait.png b/app/Libraries/MediaClipper/soundwaves-mask-portrait.png similarity index 100% rename from modules/MediaClipper/Resources/soundwaves-mask-portrait.png rename to app/Libraries/MediaClipper/soundwaves-mask-portrait.png diff --git a/modules/MediaClipper/Resources/soundwaves-mask-squared.png b/app/Libraries/MediaClipper/soundwaves-mask-squared.png similarity index 100% rename from modules/MediaClipper/Resources/soundwaves-mask-squared.png rename to app/Libraries/MediaClipper/soundwaves-mask-squared.png diff --git a/app/Libraries/PodcastEpisode.php b/app/Libraries/PodcastEpisode.php index cbd260b9..9b2bf169 100644 --- a/app/Libraries/PodcastEpisode.php +++ b/app/Libraries/PodcastEpisode.php @@ -10,12 +10,8 @@ declare(strict_types=1); namespace App\Libraries; -use App\Entities\Actor; use App\Entities\Episode; -use CodeIgniter\I18n\Time; use Modules\Fediverse\Core\ObjectType; -use Modules\Media\Entities\Chapters; -use Modules\Media\Entities\Transcript; class PodcastEpisode extends ObjectType { @@ -46,49 +42,49 @@ class PodcastEpisode extends ObjectType $this->id = $episode->link; $this->description = [ - 'type' => 'Note', - 'mediaType' => 'text/markdown', - 'content' => $episode->description_markdown, + 'type' => 'Note', + 'mediaType' => 'text/markdown', + 'content' => $episode->description_markdown, 'contentMap' => [ $episode->podcast->language_code => $episode->description_html, ], ]; $this->image = [ - 'type' => 'Image', + 'type' => 'Image', 'mediaType' => $episode->cover->file_mimetype, - 'url' => $episode->cover->feed_url, + 'url' => $episode->cover->feed_url, ]; // add audio file $this->audio = [ - 'id' => $episode->audio_url, - 'type' => 'Audio', - 'name' => esc($episode->title), - 'size' => $episode->audio->file_size, + 'id' => $episode->audio->file_url, + 'type' => 'Audio', + 'name' => esc($episode->title), + 'size' => $episode->audio->file_size, 'duration' => $episode->audio->duration, - 'url' => [ - 'href' => $episode->audio_url, - 'type' => 'Link', + 'url' => [ + 'href' => $episode->audio->file_url, + 'type' => 'Link', 'mediaType' => $episode->audio->file_mimetype, ], ]; - if ($episode->transcript instanceof Transcript) { + if ($episode->transcript !== null) { $this->audio['transcript'] = $episode->transcript->file_url; } - if ($episode->chapters instanceof Chapters) { + if ($episode->chapters !== null) { $this->audio['chapters'] = $episode->chapters->file_url; } $this->comments = url_to('episode-comments', $episode->podcast->handle, $episode->slug); - if ($episode->published_at instanceof Time) { + if ($episode->published_at !== null) { $this->published = $episode->published_at->format(DATE_W3C); } - if ($episode->podcast->actor instanceof Actor) { + if ($episode->podcast->actor !== null) { $this->attributedTo = $episode->podcast->actor->uri; if ($episode->podcast->actor->followers_url) { diff --git a/app/Libraries/Router.php b/app/Libraries/Router.php index 5ce2c227..dc760907 100644 --- a/app/Libraries/Router.php +++ b/app/Libraries/Router.php @@ -14,12 +14,9 @@ declare(strict_types=1); namespace App\Libraries; -use CodeIgniter\Exceptions\PageNotFoundException; -use CodeIgniter\HTTP\Exceptions\RedirectException; -use CodeIgniter\Router\Exceptions\RouterException; +use CodeIgniter\Router\Exceptions\RedirectException; use CodeIgniter\Router\Router as CodeIgniterRouter; -use Config\Routing; -use Override; +use Config\Services; class Router extends CodeIgniterRouter { @@ -31,9 +28,9 @@ class Router extends CodeIgniterRouter * * @return boolean Whether the route was matched or not. */ - #[Override] protected function checkRoutes(string $uri): bool { + /** @noRector RemoveExtraParametersRector */ $routes = $this->collection->getRoutes($this->collection->getHTTPVerb()); // Don't waste any time @@ -44,14 +41,26 @@ class Router extends CodeIgniterRouter $uri = $uri === '/' ? $uri : trim($uri, '/ '); // Loop through the route array looking for wildcards - foreach ($routes as $routeKey => $handler) { - $routeKey = $routeKey === '/' ? $routeKey : ltrim((string) $routeKey, '/ '); + foreach ($routes as $routeKey => $val) { + // Reset localeSegment + $localeSegment = null; + + $routeKey = $routeKey === '/' ? $routeKey : ltrim($routeKey, '/ '); $matchedKey = $routeKey; // Are we dealing with a locale? if (str_contains($routeKey, '{locale}')) { - $routeKey = str_replace('{locale}', '[^/]+', $routeKey); + $localeSegment = array_search( + '{locale}', + preg_split('~[\/]*((^[a-zA-Z0-9])|\(([^()]*)\))*[\/]+~m', $routeKey), + true, + ); + + // Replace it with a regex so it + // will actually match. + $routeKey = str_replace('/', '\/', $routeKey); + $routeKey = str_replace('{locale}', '[^\/]+', $routeKey); } // Does the RegEx match? @@ -60,51 +69,32 @@ class Router extends CodeIgniterRouter // Is this route supposed to redirect to another? if ($this->collection->isRedirect($routeKey)) { - // replacing matched route groups with references: post/([0-9]+) -> post/$1 - $redirectTo = preg_replace_callback('/(\([^\(]+\))/', static function (): string { - static $i = 1; - - return '$' . $i++; - }, (string) (is_array($handler) ? key($handler) : $handler)); - throw new RedirectException( - preg_replace('#^' . $routeKey . '$#u', (string) $redirectTo, $uri), + is_array($val) ? key($val) : $val, $this->collection->getRedirectCode($routeKey), ); } // Store our locale so CodeIgniter object can // assign it to the Request. - if (str_contains($matchedKey, '{locale}')) { - preg_match( - '#^' . str_replace('{locale}', '(?[^/]+)', $matchedKey) . '$#u', - $uri, - $matched, - ); - - if ($this->collection->shouldUseSupportedLocalesOnly() - && ! in_array($matched['locale'], config('App')->supportedLocales, true)) { - // Throw exception to prevent the autorouter, if enabled, - // from trying to find a route - throw PageNotFoundException::forLocaleNotSupported($matched['locale']); - } - - $this->detectedLocale = $matched['locale']; - unset($matched); + if (isset($localeSegment)) { + // The following may be inefficient, but doesn't upset NetBeans :-/ + $temp = explode('/', $uri); + $this->detectedLocale = $temp[$localeSegment]; } // Are we using Closures? If so, then we need // to collect the params into an array // so it can be passed to the controller method later. - if (! is_string($handler) && is_callable($handler)) { - $this->controller = $handler; + if (! is_string($val) && is_callable($val)) { + $this->controller = $val; // Remove the original string from the matches array array_shift($matches); $this->params = $matches; - $this->setMatchedRoute($matchedKey, $handler); + $this->matchedRoute = [$matchedKey, $val]; return true; } @@ -117,8 +107,8 @@ class Router extends CodeIgniterRouter array_key_exists('alternate-content', $this->matchedRouteOptions) && is_array($this->matchedRouteOptions['alternate-content']) ) { - $request = service('request'); - $negotiate = service('negotiator'); + $request = Services::request(); + $negotiate = Services::negotiator(); // Accept header is mandatory if ($request->header('Accept') === null) { @@ -134,100 +124,62 @@ class Router extends CodeIgniterRouter $expectedContentType = $parsedHeader[0]; foreach ($supported as $available) { if ( - ! $negotiate->callMatch($expectedContentType, $available, true) + $negotiate->callMatch($expectedContentType, $available, true) ) { - continue; - } - - if ( - array_key_exists( - 'namespace', - $this->matchedRouteOptions[ - 'alternate-content' + if ( + array_key_exists( + 'namespace', + $this->matchedRouteOptions[ + 'alternate-content' ][$available], - ) - ) { - $this->collection->setDefaultNamespace( - $this->matchedRouteOptions[ - 'alternate-content' + ) + ) { + $this->collection->setDefaultNamespace( + $this->matchedRouteOptions[ + 'alternate-content' ][$available]['namespace'], - ); - } + ); + } - $handler = - $this->collection->getDefaultNamespace() . - $this->directory . - $this->matchedRouteOptions['alternate-content'][ - $available - ]['controller-method']; + $val = + $this->collection->getDefaultNamespace() . + $this->directory . + $this->matchedRouteOptions['alternate-content'][ + $available + ]['controller-method']; - // no need to continue loop as $handle has been overwritten - break; - } - } - - // Are we using Closures? If so, then we need - // to collect the params into an array - // so it can be passed to the controller method later. - if (! is_string($handler) && is_callable($handler)) { - $this->controller = $handler; - - // Remove the original string from the matches array - array_shift($matches); - - $this->params = $matches; - - $this->setMatchedRoute($matchedKey, $handler); - - return true; - } - - if (str_contains((string) $handler, '::')) { - [$controller, $methodAndParams] = explode('::', (string) $handler); - } else { - $controller = $handler; - $methodAndParams = ''; - } - - // Checks `/` in controller name - if (str_contains((string) $controller, '/')) { - throw RouterException::forInvalidControllerName($handler); - } - - if (str_contains((string) $handler, '$') && str_contains($routeKey, '(')) { - // Checks dynamic controller - if (str_contains((string) $controller, '$')) { - throw RouterException::forDynamicController($handler); - } - - if (config(Routing::class)->multipleSegmentsOneParam === false) { - // Using back-references - $segments = explode( - '/', - (string) preg_replace('#\A' . $routeKey . '\z#u', (string) $handler, $uri), - ); - } else { - if (str_contains($methodAndParams, '/')) { - [$method, $handlerParams] = explode('/', $methodAndParams, 2); - $params = explode('/', $handlerParams); - $handlerSegments = array_merge([$controller . '::' . $method], $params); - } else { - $handlerSegments = [$handler]; - } - - $segments = []; - - foreach ($handlerSegments as $segment) { - $segments[] = $this->replaceBackReferences($segment, $matches); + // no need to continue loop as $val has been overwritten + break; } } - } else { - $segments = explode('/', (string) $handler); } - $this->setRequest($segments); + // Are we using the default method for back-references? - $this->setMatchedRoute($matchedKey, $handler); + // Support resource route when function with subdirectory + // ex: $routes->resource('Admin/Admins'); + if ( + str_contains($val, '$') && + str_contains($routeKey, '(') && + str_contains($routeKey, '/') + ) { + $replacekey = str_replace('/(.*)', '', $routeKey); + $val = preg_replace('#^' . $routeKey . '$#u', $val, $uri); + $val = str_replace($replacekey, str_replace('/', '\\', $replacekey), $val); + } elseif (str_contains($val, '$') && str_contains($routeKey, '(')) { + $val = preg_replace('#^' . $routeKey . '$#u', $val, $uri); + } elseif (str_contains($val, '/')) { + [$controller, $method] = explode('::', $val); + + // Only replace slashes in the controller, not in the method. + $controller = str_replace('/', '\\', $controller); + + $val = $controller . '::' . $method; + } + + $this->setRequest(explode('/', $val)); + + $this->matchedRoute = [$matchedKey, $val]; return true; } diff --git a/app/Libraries/RssFeed.php b/app/Libraries/SimpleRSSElement.php similarity index 54% rename from app/Libraries/RssFeed.php rename to app/Libraries/SimpleRSSElement.php index 631c80f1..77fbb992 100644 --- a/app/Libraries/RssFeed.php +++ b/app/Libraries/SimpleRSSElement.php @@ -11,34 +11,10 @@ declare(strict_types=1); namespace App\Libraries; use DOMDocument; -use Override; use SimpleXMLElement; -class RssFeed extends SimpleXMLElement +class SimpleRSSElement extends SimpleXMLElement { - public const ATOM_NS = 'atom'; - - public const ATOM_NAMESPACE = 'http://www.w3.org/2005/Atom'; - - public const ITUNES_NS = 'itunes'; - - public const ITUNES_NAMESPACE = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; - - public const PODCAST_NS = 'podcast'; - - public const PODCAST_NAMESPACE = 'https://podcastindex.org/namespace/1.0'; - - public function __construct(string $contents = '') - { - parent::__construct(sprintf( - "%s", - $this::ATOM_NAMESPACE, - $this::ITUNES_NAMESPACE, - $this::PODCAST_NAMESPACE, - $contents, - )); - } - /** * Adds a child with $value inside CDATA * @@ -53,7 +29,7 @@ class RssFeed extends SimpleXMLElement $newChild = parent::addChild($name, null, $namespace); $node = dom_import_simplexml($newChild); $no = $node->ownerDocument; - if ($no instanceof DOMDocument) { + if ($no !== null) { $node->appendChild($no->createCDATASection($value)); } @@ -71,7 +47,6 @@ class RssFeed extends SimpleXMLElement * * @return static The addChild method returns a SimpleXMLElement object representing the child added to the XML node. */ - #[Override] public function addChild($name, $value = null, $namespace = null, $escape = true): static { $newChild = parent::addChild($name, null, $namespace); @@ -82,41 +57,12 @@ class RssFeed extends SimpleXMLElement return $newChild; } + if (is_array($value)) { + return $newChild; + } + $node->appendChild($no->createTextNode($value)); return $newChild; } - - /** - * Add RssFeed code into a RssFeed - * - * adapted from: https://stackoverflow.com/a/23527002 - * - * @param self|array $nodes - */ - public function appendNodes(self|array $nodes): void - { - if (! is_array($nodes)) { - $nodes = [$nodes]; - } - - foreach ($nodes as $element) { - $namespaces = $element->getNamespaces(); - $namespace = array_first($namespaces) ?? null; - - if (trim((string) $element) === '') { - $simpleRSS = $this->addChild($element->getName(), null, $namespace); - } else { - $simpleRSS = $this->addChild($element->getName(), (string) $element, $namespace); - } - - foreach ($element->children() as $child) { - $simpleRSS->appendNodes($child); - } - - foreach ($element->attributes() as $name => $value) { - $simpleRSS->addAttribute($name, (string) $value); - } - } - } } diff --git a/app/Libraries/TranscriptParser.php b/app/Libraries/TranscriptParser.php new file mode 100644 index 00000000..c54fec4e --- /dev/null +++ b/app/Libraries/TranscriptParser.php @@ -0,0 +1,110 @@ +transcriptContent = $content; + + return $this; + } + + /** + * Adapted from: https://stackoverflow.com/a/11659306 + */ + public function parseSrt(): string | false + { + if (! defined('SRT_STATE_SUBNUMBER')) { + define('SRT_STATE_SUBNUMBER', 0); + } + + if (! defined('SRT_STATE_TIME')) { + define('SRT_STATE_TIME', 1); + } + + if (! defined('SRT_STATE_TEXT')) { + define('SRT_STATE_TEXT', 2); + } + + if (! defined('SRT_STATE_BLANK')) { + define('SRT_STATE_BLANK', 3); + } + + $subs = []; + $state = SRT_STATE_SUBNUMBER; + $subNum = 0; + $subText = ''; + $subTime = ''; + + $lines = explode(PHP_EOL, $this->transcriptContent); + foreach ($lines as $line) { + switch ($state) { + case SRT_STATE_SUBNUMBER: + $subNum = trim($line); + $state = SRT_STATE_TIME; + break; + + case SRT_STATE_TIME: + $subTime = trim($line); + $state = SRT_STATE_TEXT; + break; + + case SRT_STATE_TEXT: + if (trim($line) === '') { + $sub = new stdClass(); + $sub->number = (int) $subNum; + [$startTime, $endTime] = explode(' --> ', $subTime); + $sub->startTime = $this->getSecondsFromTimeString($startTime); + $sub->endTime = $this->getSecondsFromTimeString($endTime); + $sub->text = trim($subText); + $subText = ''; + $state = SRT_STATE_SUBNUMBER; + + $subs[] = $sub; + } else { + if ($subText !== '') { + $subText .= PHP_EOL . $line; + } + + $subText .= $line; + } + + break; + + } + } + + if ($state === SRT_STATE_TEXT) { + // if file was missing the trailing newlines, we'll be in this + // state here. Append the last read text and add the last sub. + // @phpstan-ignore-next-line + $sub->text = $subText; + // @phpstan-ignore-next-line + $subs[] = $sub; + } + + return json_encode($subs, JSON_PRETTY_PRINT); + } + + private function getSecondsFromTimeString(string $timeString): float + { + $timeString = explode(',', $timeString); + return (strtotime($timeString[0]) - strtotime('TODAY')) + (float) "0.{$timeString[1]}"; + } +} diff --git a/app/Libraries/ViewComponents/Component.php b/app/Libraries/ViewComponents/Component.php index eaf9744a..47dc2625 100644 --- a/app/Libraries/ViewComponents/Component.php +++ b/app/Libraries/ViewComponents/Component.php @@ -4,34 +4,28 @@ declare(strict_types=1); namespace ViewComponents; -use Override; - -abstract class Component implements ComponentInterface +class Component implements ComponentInterface { - /** - * @var list - */ - protected array $props = []; + protected string $slot = ''; - /** - * @var array - */ - protected array $casts = []; - - protected ?string $slot = null; + protected string $class = ''; /** * @var array */ - protected array $attributes = []; + protected array $attributes = [ + 'class' => '', + ]; /** * @param array $attributes */ public function __construct(array $attributes) { + helper('viewcomponents'); + // overwrite default attributes if set - $this->attributes = [...$this->attributes, ...$attributes]; + $this->attributes = array_merge($this->attributes, $attributes); if ($attributes !== []) { $this->hydrate($attributes); @@ -48,42 +42,11 @@ abstract class Component implements ComponentInterface if (is_callable([$this, $method])) { $this->{$method}($value); } else { - if (array_key_exists($name, $this->casts)) { - $value = match ($this->casts[$name]) { - 'boolean' => $value === 'true', - 'number' => (int) $value, - 'array' => json_decode(htmlspecialchars_decode($value), true), - default => $value, - }; - } - $this->{$name} = $value; } - - // remove from attributes - if (in_array($name, $this->props, true)) { - unset($this->attributes[$name]); - } - } - - unset($this->attributes['slot']); - } - - public function mergeClass(string $class): void - { - if (! array_key_exists('class', $this->attributes)) { - $this->attributes['class'] = $class; - } else { - $this->attributes['class'] .= ' ' . $class; } } - public function getStringifiedAttributes(): string - { - return stringify_attributes($this->attributes); - } - - #[Override] public function render(): string { return static::class . ': RENDER METHOD NOT IMPLEMENTED'; diff --git a/app/Libraries/ViewComponents/ComponentRenderer.php b/app/Libraries/ViewComponents/ComponentRenderer.php index e9a68172..09712615 100644 --- a/app/Libraries/ViewComponents/ComponentRenderer.php +++ b/app/Libraries/ViewComponents/ComponentRenderer.php @@ -43,38 +43,38 @@ class ComponentRenderer private function renderSelfClosingTags(string $output): string { // Pattern borrowed and adapted from Laravel's ComponentTagCompiler - // Should match any Component tags + // Should match any Component tags $pattern = "/ < - \\s* - x[-\\:](?[\\w\\-\\:\\.]*) - \\s* + \s* + (?[A-Z][A-Za-z0-9\.]*?) + \s* (? (?: - \\s+ + \s+ (?: (?: - \\{\\{\\s*\\\$attributes(?:[^}]+?)?\\s*\\}\\} + \{\{\s*\\\$attributes(?:[^}]+?)?\s*\}\} ) | (?: - [\\w\\-:.@]+ + [\w\-:.@]+ ( = (?: \\\"[^\\\"]*\\\" | - \\'[^\\']*\\' + \'[^\']*\' | - [^\\'\\\"=<>]+ + [^\'\\\"=<>]+ ) )? ) ) )* - \\s* + \s* ) - \\/> + \/> /x"; /* @@ -82,7 +82,7 @@ class ComponentRenderer $matches[name] = tag name $matches[attributes] = array of attribute string (class="foo") */ - return preg_replace_callback($pattern, function (array $match): string { + return preg_replace_callback($pattern, function ($match): string { $view = $this->locateView($match['name']); $attributes = $this->parseAttributes($match['attributes']); @@ -96,16 +96,15 @@ class ComponentRenderer private function renderPairedTags(string $output): string { - // ini_set('pcre.backtrack_limit', '-1'); - $pattern = '/<\s*x[-\:](?[\w\-\:\.]*?)(?(\s*[\w\-]+\s*=\s*(\'[^\']*\'|\"[^\"]*\"))+\s*)>(?.*)<\/\s*x-\1\s*>/uiUsm'; - + $pattern = '/<\s*(?[A-Z][A-Za-z0-9\.]*?)(?[\s\S\=\'\"]*)>(?.*)<\/\s*\1\s*>/uUsm'; + ini_set('pcre.backtrack_limit', '-1'); /* $matches[0] = full tags matched and all of its content $matches[name] = pascal cased tag name $matches[attributes] = string of tag attributes (class="foo") $matches[slot] = the content inside the tags */ - return preg_replace_callback($pattern, function (array $match): string { + return preg_replace_callback($pattern, function ($match): string { $view = $this->locateView($match['name']); $attributes = $this->parseAttributes($match['attributes']); $attributes['slot'] = $match['slot']; @@ -135,17 +134,17 @@ class ComponentRenderer foreach ($pathsToDiscover as $basePath) { // Look for a class component first - $fileKey = $basePath . $this->config->componentsDirectory . '/' . $namePath . '.php'; + $filePath = $basePath . $this->config->componentsDirectory . '/' . $namePath . '.php'; - if (is_file($fileKey)) { - return $fileKey; + if (is_file($filePath)) { + return $filePath; } $snakeCaseName = strtolower(preg_replace('~(?config->componentsDirectory . '/' . $snakeCaseName . '.php'; + $filePath = $basePath . $this->config->componentsDirectory . '/' . $snakeCaseName . '.php'; - if (is_file($fileKey)) { - return $fileKey; + if (is_file($filePath)) { + return $filePath; } } @@ -168,6 +167,8 @@ class ComponentRenderer ( \"[^\"]+\" | + \'[^\']+\' + | \\\'[^\\\']+\\\' | [^\s>]+ @@ -203,18 +204,18 @@ class ComponentRenderer { // Locate the class in the same folder as the view $class = $name . '.php'; - $fileKey = str_replace($name . '.php', $class, $view); + $filePath = str_replace($name . '.php', $class, $view); - if ($fileKey === '') { + if ($filePath === '') { return null; } - if (! file_exists($fileKey)) { + if (! file_exists($filePath)) { return null; } $className = service('locator') - ->getClassname($fileKey); + ->getClassname($filePath); if (! class_exists($className)) { return null; diff --git a/app/Libraries/ViewComponents/Config/Services.php b/app/Libraries/ViewComponents/Config/Services.php index b7a1c74d..bb9c1d21 100644 --- a/app/Libraries/ViewComponents/Config/Services.php +++ b/app/Libraries/ViewComponents/Config/Services.php @@ -22,7 +22,6 @@ class Services extends BaseService public static function components(bool $getShared = true): ComponentRenderer { if ($getShared) { - /** @phpstan-ignore return.type */ return self::getSharedInstance('components'); } diff --git a/app/Libraries/ViewComponents/Decorator.php b/app/Libraries/ViewComponents/Decorator.php index d8e7bfb6..9ca40085 100644 --- a/app/Libraries/ViewComponents/Decorator.php +++ b/app/Libraries/ViewComponents/Decorator.php @@ -5,9 +5,10 @@ declare(strict_types=1); namespace ViewComponents; use CodeIgniter\View\ViewDecoratorInterface; -use Override; /** + * Class Decorator + * * Enables rendering of View Components into the views. * * Borrowed and adapted from https://github.com/lonnieezell/Bonfire2/ @@ -16,7 +17,6 @@ class Decorator implements ViewDecoratorInterface { private static ?ComponentRenderer $components = null; - #[Override] public static function decorate(string $html): string { $components = self::factory(); @@ -29,7 +29,7 @@ class Decorator implements ViewDecoratorInterface */ private static function factory(): ComponentRenderer { - if (! self::$components instanceof ComponentRenderer) { + if (self::$components === null) { self::$components = new ComponentRenderer(); } diff --git a/app/Libraries/ViewComponents/Helpers/viewcomponents_helper.php b/app/Libraries/ViewComponents/Helpers/viewcomponents_helper.php new file mode 100644 index 00000000..9c7caf7d --- /dev/null +++ b/app/Libraries/ViewComponents/Helpers/viewcomponents_helper.php @@ -0,0 +1,33 @@ + $val) { + $atts .= ($js) ? $key . '=' . esc($val, 'js') . ',' : ' ' . $key . '="' . $val . '"'; + } + + return rtrim($atts, ','); + } +} diff --git a/app/Libraries/ViewThemes/Config/Themes.php b/app/Libraries/ViewThemes/Config/Themes.php index 61ab4c9f..c22ac27c 100644 --- a/app/Libraries/ViewThemes/Config/Themes.php +++ b/app/Libraries/ViewThemes/Config/Themes.php @@ -16,9 +16,9 @@ class Themes extends BaseConfig * @var array */ public array $themes = [ - 'app' => 'cp_app', - 'admin' => 'cp_admin', + 'app' => 'cp_app', + 'admin' => 'cp_admin', 'install' => 'cp_install', - 'auth' => 'cp_auth', + 'auth' => 'cp_auth', ]; } diff --git a/app/Libraries/ViewThemes/Theme.php b/app/Libraries/ViewThemes/Theme.php index b1b9b008..30020dcb 100644 --- a/app/Libraries/ViewThemes/Theme.php +++ b/app/Libraries/ViewThemes/Theme.php @@ -19,7 +19,7 @@ class Theme protected static $defaultTheme = 'app'; /** - * @var ?string + * @var string */ protected static $currentTheme; @@ -46,7 +46,7 @@ class Theme /** * Returns the path to the specified theme folder. If no theme is provided, will use the current theme. */ - public static function path(?string $theme = null): string + public static function path(string $theme = null): string { if ($theme === null) { $theme = static::current(); @@ -71,7 +71,9 @@ class Theme */ public static function current(): string { - return static::$currentTheme ?? static::$defaultTheme; + return static::$currentTheme !== null + ? static::$currentTheme + : static::$defaultTheme; } /** diff --git a/modules/Media/Config/Services.php b/app/Libraries/Vite/Config/Services.php similarity index 54% rename from modules/Media/Config/Services.php rename to app/Libraries/Vite/Config/Services.php index 8b5fd814..cd5adfde 100644 --- a/modules/Media/Config/Services.php +++ b/app/Libraries/Vite/Config/Services.php @@ -2,11 +2,10 @@ declare(strict_types=1); -namespace Modules\Media\Config; +namespace Vite\Config; use CodeIgniter\Config\BaseService; -use Exception; -use Modules\Media\FileManagers\FileManagerInterface; +use Vite\Vite; /** * Services Configuration file. @@ -20,21 +19,12 @@ use Modules\Media\FileManagers\FileManagerInterface; */ class Services extends BaseService { - public static function file_manager(bool $getShared = true): FileManagerInterface + public static function vite(bool $getShared = true): Vite { if ($getShared) { - return self::getSharedInstance('file_manager'); + return self::getSharedInstance('vite'); } - $config = config('Media'); - $fileManagerClass = $config->fileManagers[$config->fileManager]; - - $fileManager = new $fileManagerClass($config); - - if ($fileManager instanceof FileManagerInterface) { - return $fileManager; - } - - throw new Exception('File Manager service must extend FileManagerInterface'); + return new Vite(); } } diff --git a/app/Libraries/Vite/Config/Vite.php b/app/Libraries/Vite/Config/Vite.php new file mode 100644 index 00000000..88471e78 --- /dev/null +++ b/app/Libraries/Vite/Config/Vite.php @@ -0,0 +1,20 @@ +|null + */ + protected ?array $manifestData = null; + + /** + * @var array|null + */ + protected ?array $manifestCSSData = null; + + public function asset(string $path, string $type): string + { + if (config('Vite')->environment !== 'production') { + return $this->loadDev($path, $type); + } + + return $this->loadProd($path, $type); + } + + private function loadDev(string $path, string $type): string + { + return $this->getHtmlTag(config('Vite')->baseUrl . config('Vite')->assetsRoot . "/{$path}", $type); + } + + private function loadProd(string $path, string $type): string + { + if ($type === 'css') { + if ($this->manifestCSSData === null) { + $cacheName = 'vite-manifest-css'; + if (! ($cachedManifestCSS = cache($cacheName))) { + $manifestCSSPath = config('Vite') + ->assetsRoot . '/' . config('Vite') + ->manifestCSSFile; + try { + if (($manifestCSSContent = file_get_contents($manifestCSSPath)) !== false) { + $cachedManifestCSS = json_decode($manifestCSSContent, true); + cache() + ->save($cacheName, $cachedManifestCSS, DECADE); + } + } catch (ErrorException) { + // ERROR when getting the manifest-css file + die("Could not load css manifest: {$manifestCSSPath} file not found!"); + } + } + + $this->manifestCSSData = $cachedManifestCSS; + } + + if (array_key_exists($path, $this->manifestCSSData)) { + return $this->getHtmlTag( + '/' . config('Vite')->assetsRoot . '/' . $this->manifestCSSData[$path]['file'], + 'css' + ); + } + } + + if ($this->manifestData === null) { + $cacheName = 'vite-manifest'; + if (! ($cachedManifest = cache($cacheName))) { + $manifestPath = config('Vite') + ->assetsRoot . '/' . config('Vite') + ->manifestFile; + try { + if (($manifestContents = file_get_contents($manifestPath)) !== false) { + $cachedManifest = json_decode($manifestContents, true); + cache() + ->save($cacheName, $cachedManifest, DECADE); + } + } catch (ErrorException) { + // ERROR when retrieving the manifest file + die("Could not load manifest: {$manifestPath} file not found!"); + } + } + + $this->manifestData = $cachedManifest; + } + + $html = ''; + if (array_key_exists($path, $this->manifestData)) { + $manifestElement = $this->manifestData[$path]; + + // import css dependencies if any + if (array_key_exists('css', $manifestElement)) { + foreach ($manifestElement['css'] as $cssFile) { + $html .= $this->getHtmlTag('/' . config('Vite')->assetsRoot . '/' . $cssFile, 'css'); + } + } + + // import dependencies first for faster js loading + if (array_key_exists('imports', $manifestElement)) { + foreach ($manifestElement['imports'] as $importPath) { + if (array_key_exists($importPath, $this->manifestData)) { + $html .= $this->getHtmlTag( + '/' . config('Vite')->assetsRoot . '/' . $this->manifestData[$importPath]['file'], + 'js' + ); + } + } + } + + $html .= $this->getHtmlTag('/' . config('Vite')->assetsRoot . '/' . $manifestElement['file'], $type); + } + + return $html; + } + + private function getHtmlTag(string $assetUrl, string $type): string + { + return match ($type) { + 'css' => << + CODE_SAMPLE +, + 'js' => << + CODE_SAMPLE +, + default => '', + }; + } +} diff --git a/app/Models/ActorModel.php b/app/Models/ActorModel.php index 59369100..47b35485 100644 --- a/app/Models/ActorModel.php +++ b/app/Models/ActorModel.php @@ -12,18 +12,25 @@ namespace App\Models; use App\Entities\Actor; use Modules\Fediverse\Models\ActorModel as FediverseActorModel; -use Override; class ActorModel extends FediverseActorModel { /** - * @var class-string + * @var string */ protected $returnType = Actor::class; - #[Override] public function getActorById(int $id): ?Actor { - return $this->find($id); + $cacheName = config('Fediverse') + ->cachePrefix . "actor#{$id}"; + if (! ($found = cache($cacheName))) { + $found = $this->find($id); + + cache() + ->save($cacheName, $found, DECADE); + } + + return $found; } } diff --git a/app/Models/CategoryModel.php b/app/Models/CategoryModel.php index 2c67efeb..a3858e2a 100644 --- a/app/Models/CategoryModel.php +++ b/app/Models/CategoryModel.php @@ -26,12 +26,12 @@ class CategoryModel extends Model protected $primaryKey = 'id'; /** - * @var list + * @var string[] */ protected $allowedFields = ['parent_id', 'code', 'apple_category', 'google_category']; /** - * @var class-string + * @var string */ protected $returnType = Category::class; @@ -65,17 +65,17 @@ class CategoryModel extends Model $options = array_reduce( $categories, static function (array $result, Category $category): array { - $label = ''; - if ($category->parent instanceof Category) { - $label = lang('Podcast.category_options.' . $category->parent->code) . ' › '; + $result[$category->id] = ''; + if ($category->parent !== null) { + $result[$category->id] = lang( + 'Podcast.category_options.' . $category->parent->code, + [], + null, + false + ) . ' › '; } - $label .= lang('Podcast.category_options.' . $category->code); - - $result[] = [ - 'value' => $category->id, - 'label' => $label, - ]; + $result[$category->id] .= lang('Podcast.category_options.' . $category->code, [], null, false); return $result; }, [], @@ -116,7 +116,7 @@ class CategoryModel extends Model $categoriesIds, static function (array $result, int $categoryId) use ($podcastId): array { $result[] = [ - 'podcast_id' => $podcastId, + 'podcast_id' => $podcastId, 'category_id' => $categoryId, ]; return $result; diff --git a/app/Models/ClipModel.php b/app/Models/ClipModel.php index cc5209c9..d4e01dcf 100644 --- a/app/Models/ClipModel.php +++ b/app/Models/ClipModel.php @@ -33,7 +33,7 @@ class ClipModel extends Model protected $primaryKey = 'id'; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -53,6 +53,9 @@ class ClipModel extends Model 'job_ended_at', ]; + /** + * @noRector + */ protected $returnType = BaseClip::class; /** @@ -67,8 +70,8 @@ class ClipModel extends Model public function __construct( protected string $type = 'audio', - ?ConnectionInterface &$db = null, - ?ValidationInterface $validation = null, + ConnectionInterface &$db = null, + ValidationInterface $validation = null ) { switch ($type) { case 'audio': @@ -91,10 +94,11 @@ class ClipModel extends Model if (! ($found = cache($cacheName))) { $clip = $this->find($videoClipId); - if (! $clip instanceof BaseClip) { + if ($clip === null) { return null; } + // @phpstan-ignore-next-line $found = new VideoClip($clip->toArray()); cache() @@ -112,7 +116,7 @@ class ClipModel extends Model public function getScheduledVideoClips(): array { $found = $this->where([ - 'type' => 'video', + 'type' => 'video', 'status' => 'queued', ]) ->orderBy('created_at') @@ -130,7 +134,7 @@ class ClipModel extends Model $result = $this->builder() ->select('COUNT(*) as `running_count`') ->where([ - 'type' => 'video', + 'type' => 'video', 'status' => 'running', ]) ->get() @@ -147,7 +151,7 @@ class ClipModel extends Model 'podcast_id' => $videoClip->podcast_id, 'episode_id' => $videoClip->episode_id, 'start_time' => $videoClip->start_time, - 'duration' => $videoClip->duration, + 'duration' => $videoClip->duration, ]) ->where('JSON_EXTRACT(`metadata`, "$.format")', $videoClip->format) ->where('JSON_EXTRACT(`metadata`, "$.theme.name")', $videoClip->theme['name']) @@ -161,21 +165,15 @@ class ClipModel extends Model return (int) $result[0]['id']; } - public function deleteVideoClip(int $clipId): BaseResult | bool + public function deleteVideoClip(int $podcastId, int $episodeId, int $clipId): BaseResult | bool { $this->clearVideoClipCache($clipId); - return $this->delete($clipId); - } - - public function getClipCount(int $podcastId, int $episodeId): int - { - return $this - ->where([ - 'podcast_id' => $podcastId, - 'episode_id' => $episodeId, - ]) - ->countAllResults(); + return $this->delete([ + 'podcast_id' => $podcastId, + 'episode_id' => $episodeId, + 'id' => $clipId, + ]); } public function clearVideoClipCache(int $clipId): void @@ -190,10 +188,11 @@ class ClipModel extends Model if (! ($found = cache($cacheName))) { $clip = $this->find($soundbiteId); - if (! $clip instanceof BaseClip) { + if ($clip === null) { return null; } + // @phpstan-ignore-next-line $found = new Soundbite($clip->toArray()); cache() @@ -215,7 +214,7 @@ class ClipModel extends Model $found = $this->where([ 'episode_id' => $episodeId, 'podcast_id' => $podcastId, - 'type' => 'audio', + 'type' => 'audio', ]) ->orderBy('start_time') ->findAll(); @@ -235,7 +234,11 @@ class ClipModel extends Model { $this->clearSoundbiteCache($podcastId, $episodeId, $clipId); - return $this->delete($clipId); + return $this->delete([ + 'podcast_id' => $podcastId, + 'episode_id' => $episodeId, + 'id' => $clipId, + ]); } public function clearSoundbiteCache(int $podcastId, int $episodeId, int $clipId): void diff --git a/app/Models/CreditModel.php b/app/Models/CreditModel.php index 23342d4c..021b81d6 100644 --- a/app/Models/CreditModel.php +++ b/app/Models/CreditModel.php @@ -21,7 +21,7 @@ class CreditModel extends Model protected $table = 'credits'; /** - * @var class-string + * @var string */ protected $returnType = Credit::class; } diff --git a/app/Models/EpisodeCommentModel.php b/app/Models/EpisodeCommentModel.php index 60582586..af096172 100644 --- a/app/Models/EpisodeCommentModel.php +++ b/app/Models/EpisodeCommentModel.php @@ -10,8 +10,6 @@ declare(strict_types=1); namespace App\Models; -use App\Entities\Actor; -use App\Entities\Episode; use App\Entities\EpisodeComment; use App\Libraries\CommentObject; use CodeIgniter\Database\BaseBuilder; @@ -20,12 +18,13 @@ use CodeIgniter\I18n\Time; use Michalsn\Uuid\UuidModel; use Modules\Fediverse\Activities\CreateActivity; use Modules\Fediverse\Activities\DeleteActivity; +use Modules\Fediverse\Models\ActivityModel; use Modules\Fediverse\Objects\TombstoneObject; class EpisodeCommentModel extends UuidModel { /** - * @var class-string + * @var string */ protected $returnType = EpisodeComment::class; @@ -40,7 +39,7 @@ class EpisodeCommentModel extends UuidModel protected $uuidFields = ['id', 'in_reply_to_id']; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -57,7 +56,7 @@ class EpisodeCommentModel extends UuidModel ]; /** - * @var list + * @var string[] */ protected $beforeInsert = ['setCommentId']; @@ -74,7 +73,7 @@ class EpisodeCommentModel extends UuidModel return $found; } - public function addComment(EpisodeComment $comment, bool $registerActivity = true): bool|int|object|string + public function addComment(EpisodeComment $comment, bool $registerActivity = true): string | false { $this->db->transStart(); @@ -86,13 +85,11 @@ class EpisodeCommentModel extends UuidModel } if ($comment->in_reply_to_id === null) { - new EpisodeModel() - ->builder() + (new EpisodeModel())->builder() ->where('id', $comment->episode_id) ->increment('comments_count'); } else { - new self() - ->builder() + (new self())->builder() ->where('id', service('uuid')->fromString($comment->in_reply_to_id)->getBytes()) ->increment('replies_count'); } @@ -104,7 +101,7 @@ class EpisodeCommentModel extends UuidModel 'episode-comment', esc($comment->actor->username), $comment->episode->slug, - $comment->id, + $comment->id ); $createActivity = new CreateActivity(); @@ -112,7 +109,7 @@ class EpisodeCommentModel extends UuidModel ->set('actor', $comment->actor->uri) ->set('object', new CommentObject($comment)); - $activityId = model('ActivityModel', false) + $activityId = model(ActivityModel::class, false) ->newActivity( 'Create', $comment->actor_id, @@ -125,7 +122,7 @@ class EpisodeCommentModel extends UuidModel $createActivity->set('id', url_to('activity', esc($comment->actor->username), $activityId)); - model('ActivityModel', false) + model(ActivityModel::class, false) ->update($activityId, [ 'payload' => $createActivity->toJSON(), ]); @@ -155,7 +152,7 @@ class EpisodeCommentModel extends UuidModel ->set('actor', $comment->actor->uri) ->set('object', $tombstoneObject); - $activityId = model('ActivityModel', false) + $activityId = model(ActivityModel::class, false) ->newActivity( 'Delete', $comment->actor_id, @@ -168,7 +165,7 @@ class EpisodeCommentModel extends UuidModel $deleteActivity->set('id', url_to('activity', esc($comment->actor->username), $activityId)); - model('ActivityModel', false) + model(ActivityModel::class, false) ->update($activityId, [ 'payload' => $deleteActivity->toJSON(), ]); @@ -178,12 +175,11 @@ class EpisodeCommentModel extends UuidModel ->delete($comment->id); if ($comment->in_reply_to_id === null) { - model('EpisodeModel', false)->builder() + model(EpisodeModel::class, false)->builder() ->where('id', $comment->episode_id) ->decrement('comments_count'); } else { - new self() - ->builder() + (new self())->builder() ->where('id', service('uuid')->fromString($comment->in_reply_to_id)->getBytes()) ->decrement('replies_count'); } @@ -199,14 +195,16 @@ class EpisodeCommentModel extends UuidModel * Retrieves all published posts for a given episode ordered by publication date * * @return EpisodeComment[] + * + * @noRector ReturnTypeDeclarationRector */ public function getEpisodeComments(int $episodeId): array { // TODO: merge with replies from posts linked to episode linked $episodeCommentsBuilder = $this->builder(); - $episodeComments = $episodeCommentsBuilder->select('*, 0 as is_private, 0 as is_from_post') + $episodeComments = $episodeCommentsBuilder->select('*, 0 as is_from_post') ->where([ - 'episode_id' => $episodeId, + 'episode_id' => $episodeId, 'in_reply_to_id' => null, ]) ->getCompiledSelect(); @@ -214,33 +212,29 @@ class EpisodeCommentModel extends UuidModel $postModel = new PostModel(); $episodePostsRepliesBuilder = $postModel->builder(); $episodePostsReplies = $episodePostsRepliesBuilder->select( - 'id, uri, episode_id, actor_id, in_reply_to_id, message, message_html, favourites_count as likes_count, replies_count, published_at as created_at, created_by, is_private, 1 as is_from_post', + 'id, uri, episode_id, actor_id, in_reply_to_id, message, message_html, favourites_count as likes_count, replies_count, published_at as created_at, created_by, 1 as is_from_post' ) ->whereIn('in_reply_to_id', static function (BaseBuilder $builder) use (&$episodeId): BaseBuilder { return $builder->select('id') - ->from('fediverse_posts') + ->from(config('Fediverse')->tablesPrefix . 'posts') ->where([ - 'episode_id' => $episodeId, + 'episode_id' => $episodeId, 'in_reply_to_id' => null, ]); }) - ->where('`created_at` <= UTC_TIMESTAMP()', null, false); - - // do not get private replies if public - if (! can_user_interact()) { - $episodePostsRepliesBuilder->where('is_private', false); - } - - $episodePostsReplies = $episodePostsRepliesBuilder->getCompiledSelect(); + ->where('`created_at` <= UTC_TIMESTAMP()', null, false) + ->getCompiledSelect(); /** @var BaseResult $allEpisodeComments */ $allEpisodeComments = $this->db->query( - $episodeComments . ' UNION ' . $episodePostsReplies . ' ORDER BY created_at ASC', + $episodeComments . ' UNION ' . $episodePostsReplies . ' ORDER BY created_at ASC' ); + // FIXME:? + // @phpstan-ignore-next-line return $this->convertUuidFieldsToStrings( $allEpisodeComments->getCustomResultObject($this->tempReturnType), - $this->tempReturnType, + $this->tempReturnType ); } @@ -300,20 +294,12 @@ class EpisodeCommentModel extends UuidModel $data['data']['id'] = $uuid4->toString(); if (! isset($data['data']['uri'])) { - $actor = model('ActorModel', false) + $actor = model(ActorModel::class, false) ->getActorById((int) $data['data']['actor_id']); - $episode = model('EpisodeModel', false) + $episode = model(EpisodeModel::class, false) ->find((int) $data['data']['episode_id']); - if (! $episode instanceof Episode) { - return $data; - } - - if (! $actor instanceof Actor) { - return $data; - } - - $data['data']['uri'] = url_to('episode-comment', $actor->username, $episode->slug, $uuid4->toString()); + $data['data']['uri'] = url_to('episode-comment', esc($actor->username), $episode->slug, $uuid4->toString()); } return $data; diff --git a/app/Models/EpisodeModel.php b/app/Models/EpisodeModel.php index c1ec3a02..dcf40ba5 100644 --- a/app/Models/EpisodeModel.php +++ b/app/Models/EpisodeModel.php @@ -11,13 +11,11 @@ declare(strict_types=1); namespace App\Models; use App\Entities\Episode; -use CodeIgniter\Database\BaseBuilder; use CodeIgniter\Database\BaseResult; use CodeIgniter\I18n\Time; -use Michalsn\Uuid\UuidModel; -use Ramsey\Uuid\Lazy\LazyUuidFromString; +use CodeIgniter\Model; -class EpisodeModel extends UuidModel +class EpisodeModel extends Model { /** * TODO: remove, shouldn't be here @@ -26,48 +24,44 @@ class EpisodeModel extends UuidModel */ public static $themes = [ 'light-transparent' => [ - 'style' => 'background-color: #fff; background-image: linear-gradient(45deg, #ccc 12.5%, transparent 12.5%, transparent 50%, #ccc 50%, #ccc 62.5%, transparent 62.5%, transparent 100%); background-size: 5.66px 5.66px;', + 'style' => + 'background-color: #fff; background-image: linear-gradient(45deg, #ccc 12.5%, transparent 12.5%, transparent 50%, #ccc 50%, #ccc 62.5%, transparent 62.5%, transparent 100%); background-size: 5.66px 5.66px;', 'background' => 'transparent', - 'text' => '#000', - 'inverted' => '#fff', + 'text' => '#000', + 'inverted' => '#fff', ], 'light' => [ - 'style' => 'background-color: #fff;', + 'style' => 'background-color: #fff;', 'background' => '#fff', - 'text' => '#000', - 'inverted' => '#fff', + 'text' => '#000', + 'inverted' => '#fff', ], 'dark-transparent' => [ - 'style' => 'background-color: #001f1a; background-image: linear-gradient(45deg, #888 12.5%, transparent 12.5%, transparent 50%, #888 50%, #888 62.5%, transparent 62.5%, transparent 100%); background-size: 5.66px 5.66px;', + 'style' => + 'background-color: #001f1a; background-image: linear-gradient(45deg, #888 12.5%, transparent 12.5%, transparent 50%, #888 50%, #888 62.5%, transparent 62.5%, transparent 100%); background-size: 5.66px 5.66px;', 'background' => 'transparent', - 'text' => '#fff', - 'inverted' => '#000', + 'text' => '#fff', + 'inverted' => '#000', ], 'dark' => [ - 'style' => 'background-color: #001f1a;', + 'style' => 'background-color: #001f1a;', 'background' => '#313131', - 'text' => '#fff', - 'inverted' => '#000', + 'text' => '#fff', + 'inverted' => '#000', ], ]; - /** - * @var string[] - */ - protected $uuidFields = ['preview_id']; - /** * @var string */ protected $table = 'episodes'; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', 'podcast_id', - 'preview_id', 'guid', 'title', 'slug', @@ -87,8 +81,8 @@ class EpisodeModel extends UuidModel 'location_name', 'location_geo', 'location_osm', + 'custom_rss', 'is_published_on_hubs', - 'downloads_count', 'posts_count', 'comments_count', 'is_premium', @@ -98,7 +92,7 @@ class EpisodeModel extends UuidModel ]; /** - * @var class-string + * @var string */ protected $returnType = Episode::class; @@ -111,33 +105,33 @@ class EpisodeModel extends UuidModel * @var array */ protected $validationRules = [ - 'podcast_id' => 'required', - 'title' => 'required', - 'slug' => 'required|regex_match[/^[a-zA-Z0-9\-]{1,128}$/]', - 'audio_id' => 'required', - 'description_markdown' => 'required', - 'number' => 'is_natural_no_zero|permit_empty', - 'season_number' => 'is_natural_no_zero|permit_empty', - 'type' => 'required', + 'podcast_id' => 'required', + 'title' => 'required', + 'slug' => 'required|regex_match[/^[a-zA-Z0-9\-]{1,128}$/]', + 'audio_id' => 'required', + 'description_markdown' => 'required', + 'number' => 'is_natural_no_zero|permit_empty', + 'season_number' => 'is_natural_no_zero|permit_empty', + 'type' => 'required', 'transcript_remote_url' => 'valid_url_strict|permit_empty', - 'chapters_remote_url' => 'valid_url_strict|permit_empty', - 'published_at' => 'valid_date|permit_empty', - 'created_by' => 'required', - 'updated_by' => 'required', + 'chapters_remote_url' => 'valid_url_strict|permit_empty', + 'published_at' => 'valid_date|permit_empty', + 'created_by' => 'required', + 'updated_by' => 'required', ]; /** - * @var list + * @var string[] */ protected $afterInsert = ['writeEnclosureMetadata', 'clearCache']; /** - * @var list + * @var string[] */ protected $afterUpdate = ['clearCache', 'writeEnclosureMetadata']; /** - * @var list + * @var string[] */ protected $beforeDelete = ['clearCache']; @@ -195,38 +189,6 @@ class EpisodeModel extends UuidModel return $found; } - public function getEpisodeByPreviewId(string $previewId): ?Episode - { - $cacheName = "podcast_episode-preview#{$previewId}"; - if (! ($found = cache($cacheName))) { - $builder = $this->where([ - 'preview_id' => $this->uuid->fromString($previewId) - ->getBytes(), - ]); - - $found = $builder->first(); - - cache() - ->save($cacheName, $found, DECADE); - } - - return $found; - } - - public function setEpisodePreviewId(int $episodeId): string|false - { - /** @var LazyUuidFromString $uuid */ - $uuid = $this->uuid->{$this->uuidVersion}(); - - if (! $this->update($episodeId, [ - 'preview_id' => $uuid, - ])) { - return false; - } - - return (string) $uuid; - } - /** * Gets all episodes for a podcast ordered according to podcast type Filtered depending on year or season * @@ -235,8 +197,8 @@ class EpisodeModel extends UuidModel public function getPodcastEpisodes( int $podcastId, string $podcastType, - ?string $year = null, - ?string $season = null, + string $year = null, + string $season = null ): array { $cacheName = implode( '_', @@ -272,7 +234,13 @@ class EpisodeModel extends UuidModel $secondsToNextUnpublishedEpisode = $this->getSecondsToNextUnpublishedEpisode($podcastId); cache() - ->save($cacheName, $found, $secondsToNextUnpublishedEpisode ?: DECADE); + ->save( + $cacheName, + $found, + $secondsToNextUnpublishedEpisode + ? $secondsToNextUnpublishedEpisode + : DECADE, + ); } return $found; @@ -316,9 +284,11 @@ class EpisodeModel extends UuidModel public function getCurrentSeasonNumber(int $podcastId): ?int { $result = $this->builder() - ->selectMax('season_number', 'current_season_number') - ->where('podcast_id', $podcastId) - ->where('`published_at` <= UTC_TIMESTAMP()', null, false) + ->select('MAX(season_number) as current_season_number') + ->where([ + 'podcast_id' => $podcastId, + 'published_at IS NOT' => null, + ]) ->get() ->getResultArray(); @@ -328,13 +298,12 @@ class EpisodeModel extends UuidModel public function getNextEpisodeNumber(int $podcastId, ?int $seasonNumber): int { $result = $this->builder() - ->selectMax('number', 'next_episode_number') + ->select('MAX(number) as next_episode_number') ->where([ - 'podcast_id' => $podcastId, + 'podcast_id' => $podcastId, 'season_number' => $seasonNumber, - ]) - ->where('`published_at` <= UTC_TIMESTAMP()', null, false) - ->get() + 'published_at IS NOT' => null, + ])->get() ->getResultArray(); return (int) $result[0]['next_episode_number'] + 1; @@ -347,15 +316,16 @@ class EpisodeModel extends UuidModel { $result = $this->builder() ->select( - 'COUNT(DISTINCT season_number) as number_of_seasons, COUNT(*) as number_of_episodes, MIN(published_at) as first_published_at', + 'COUNT(DISTINCT season_number) as number_of_seasons, COUNT(*) as number_of_episodes, MIN(published_at) as first_published_at' ) - ->where('podcast_id', $podcastId) - ->where('`published_at` <= UTC_TIMESTAMP()', null, false) - ->get() + ->where([ + 'podcast_id' => $podcastId, + 'published_at IS NOT' => null, + ])->get() ->getResultArray(); $stats = [ - 'number_of_seasons' => (int) $result[0]['number_of_seasons'], + 'number_of_seasons' => (int) $result[0]['number_of_seasons'], 'number_of_episodes' => (int) $result[0]['number_of_episodes'], ]; @@ -368,32 +338,30 @@ class EpisodeModel extends UuidModel public function resetCommentsCount(): int | false { - $episodeCommentsCount = new EpisodeCommentModel() - ->builder() + $episodeCommentsCount = (new EpisodeCommentModel())->builder() ->select('episode_id, COUNT(*) as `comments_count`') - ->where('in_reply_to_id') + ->where('in_reply_to_id', null) ->groupBy('episode_id') ->getCompiledSelect(); - $episodePostsRepliesCount = new PostModel() - ->builder() - ->select('fediverse_posts.episode_id as episode_id, COUNT(*) as `comments_count`') - ->join('fediverse_posts as fp', 'fediverse_posts.id = fp.in_reply_to_id') - ->where('fediverse_posts.in_reply_to_id') - ->where('fediverse_posts.episode_id IS NOT') - ->groupBy('fediverse_posts.episode_id') + $postsTable = config('Fediverse') + ->tablesPrefix . 'posts'; + $episodePostsRepliesCount = (new PostModel())->builder() + ->select($postsTable . '.episode_id as episode_id, COUNT(*) as `comments_count`') + ->join($postsTable . ' as fp', $postsTable . '.id = fp.in_reply_to_id') + ->where($postsTable . '.in_reply_to_id', null) + ->groupBy($postsTable . '.episode_id') ->getCompiledSelect(); /** @var BaseResult $query */ $query = $this->db->query( - 'SELECT `episode_id` as `id`, SUM(`comments_count`) as `comments_count` FROM (' . $episodeCommentsCount . ' UNION ALL ' . $episodePostsRepliesCount . ') x GROUP BY `episode_id`', + 'SELECT `episode_id` as `id`, SUM(`comments_count`) as `comments_count` FROM (' . $episodeCommentsCount . ' UNION ALL ' . $episodePostsRepliesCount . ') x GROUP BY `episode_id`' ); $countsPerEpisodeId = $query->getResultArray(); if ($countsPerEpisodeId !== []) { - return new self() - ->updateBatch($countsPerEpisodeId, 'id'); + return (new self())->updateBatch($countsPerEpisodeId, 'id'); } return 0; @@ -403,8 +371,12 @@ class EpisodeModel extends UuidModel { $episodePostsCount = $this->builder() ->select('episodes.id, COUNT(*) as `posts_count`') - ->join('fediverse_posts', 'episodes.id = fediverse_posts.episode_id') - ->where('in_reply_to_id') + ->join( + config('Fediverse') + ->tablesPrefix . 'posts', + 'episodes.id = ' . config('Fediverse')->tablesPrefix . 'posts.episode_id' + ) + ->where('in_reply_to_id', null) ->groupBy('episodes.id') ->get() ->getResultArray(); @@ -423,21 +395,7 @@ class EpisodeModel extends UuidModel */ public function clearCache(array $data): array { - /** @var int|null $episodeId */ - $episodeId = is_array($data['id']) ? $data['id'][0] : $data['id']; - - if ($episodeId === null) { - // Multiple episodes have been updated, do nothing - return $data; - } - - /** @var ?Episode $episode */ - $episode = new self() - ->find($episodeId); - - if (! $episode instanceof Episode) { - return $data; - } + $episode = (new self())->find(is_array($data['id']) ? $data['id'][0] : $data['id']); // delete podcast cache cache() @@ -445,7 +403,7 @@ class EpisodeModel extends UuidModel cache() ->deleteMatching("podcast-{$episode->podcast->handle}*"); cache() - ->deleteMatching('podcast_episode*'); + ->delete("podcast_episode#{$episode->id}"); cache() ->deleteMatching("page_podcast#{$episode->podcast_id}*"); cache() @@ -462,53 +420,7 @@ class EpisodeModel extends UuidModel ->where([ 'podcast_id' => $podcastId, 'is_premium' => true, - ]) - ->where('`published_at` <= UTC_TIMESTAMP()', null, false) - ->countAllResults() > 0; - } - - public function fullTextSearch(string $query): ?BaseBuilder - { - $prefix = $this->db->getPrefix(); - $episodeTable = $prefix . $this->builder()->getTable(); - - $podcastModel = (new PodcastModel()); - - $podcastTable = $podcastModel->db->getPrefix() . $podcastModel->builder()->getTable(); - - $this->builder() - ->select('' . $episodeTable . '.*') - ->select(' - ' . $this->getFullTextMatchClauseForEpisodes($episodeTable, $query) . ' as episodes_score, - ' . $podcastModel->getFullTextMatchClauseForPodcasts($podcastTable, $query) . ' as podcasts_score, - ') - ->select("{$podcastTable}.created_at AS podcast_created_at") - ->select( - "{$podcastTable}.title as podcast_title, {$podcastTable}.handle as podcast_handle, {$podcastTable}.description_markdown as podcast_description_markdown", - ) - ->join($podcastTable, "{$podcastTable} on {$podcastTable}.id = {$episodeTable}.podcast_id") - ->where(' - (' . - $this->getFullTextMatchClauseForEpisodes($episodeTable, $query) - . 'OR' . - $podcastModel->getFullTextMatchClauseForPodcasts($podcastTable, $query) - . ') - ', ); - - return $this->builder; - } - - public function getFullTextMatchClauseForEpisodes(string $table, string $value): string - { - return ' - MATCH ( - ' . $table . '.title, - ' . $table . '.description_markdown, - ' . $table . '.slug, - ' . $table . '.location_name - ) - AGAINST(' . $this->db->escape($value) . ') - '; + ])->countAllResults() > 0; } /** @@ -518,24 +430,10 @@ class EpisodeModel extends UuidModel */ protected function writeEnclosureMetadata(array $data): array { - /** @var int|null $episodeId */ - $episodeId = is_array($data['id']) ? $data['id'][0] : $data['id']; - - if ($episodeId === null) { - // Multiple episodes have been updated, do nothing - return $data; - } - - /** @var ?Episode $episode */ - $episode = new self() - ->find($episodeId); - - if (! $episode instanceof Episode) { - return $data; - } - helper('id3'); + $episode = (new self())->find(is_array($data['id']) ? $data['id'][0] : $data['id']); + write_audio_file_tags($episode); return $data; diff --git a/app/Models/LanguageModel.php b/app/Models/LanguageModel.php index b68a9197..20380200 100644 --- a/app/Models/LanguageModel.php +++ b/app/Models/LanguageModel.php @@ -26,12 +26,12 @@ class LanguageModel extends Model protected $primaryKey = 'id'; /** - * @var list + * @var string[] */ protected $allowedFields = ['code', 'native_name']; /** - * @var class-string + * @var string */ protected $returnType = Language::class; @@ -56,10 +56,7 @@ class LanguageModel extends Model $options = array_reduce( $languages, static function (array $result, Language $language): array { - $result[] = [ - 'value' => $language->code, - 'label' => $language->native_name, - ]; + $result[$language->code] = $language->native_name; return $result; }, [], diff --git a/app/Models/LikeModel.php b/app/Models/LikeModel.php index f3f382de..f4eebe36 100644 --- a/app/Models/LikeModel.php +++ b/app/Models/LikeModel.php @@ -15,8 +15,8 @@ use App\Entities\Like; use Michalsn\Uuid\UuidModel; use Modules\Fediverse\Activities\LikeActivity; use Modules\Fediverse\Activities\UndoActivity; -use Modules\Fediverse\Entities\Activity; use Modules\Fediverse\Entities\Actor; +use Modules\Fediverse\Models\ActivityModel; class LikeModel extends UuidModel { @@ -31,12 +31,12 @@ class LikeModel extends UuidModel protected $uuidFields = ['comment_id']; /** - * @var list + * @var string[] */ protected $allowedFields = ['actor_id', 'comment_id']; /** - * @var class-string + * @var string */ protected $returnType = Like::class; @@ -45,19 +45,18 @@ class LikeModel extends UuidModel */ protected $useTimestamps = true; - protected $updatedField = ''; + protected $updatedField; public function addLike(Actor $actor, EpisodeComment $comment, bool $registerActivity = true): void { $this->db->transStart(); $this->insert([ - 'actor_id' => $actor->id, + 'actor_id' => $actor->id, 'comment_id' => $comment->id, ]); - new EpisodeCommentModel() - ->builder() + (new EpisodeCommentModel())->builder() ->where('id', service('uuid')->fromString($comment->id)->getBytes()) ->increment('likes_count'); @@ -66,7 +65,7 @@ class LikeModel extends UuidModel $likeActivity->set('actor', $actor->uri) ->set('object', $comment->uri); - $activityId = model('ActivityModel') + $activityId = model(ActivityModel::class) ->newActivity( 'Like', $actor->id, @@ -79,7 +78,7 @@ class LikeModel extends UuidModel $likeActivity->set('id', url_to('activity', esc($actor->username), $activityId)); - model('ActivityModel') + model(ActivityModel::class) ->update($activityId, [ 'payload' => $likeActivity->toJSON(), ]); @@ -92,13 +91,12 @@ class LikeModel extends UuidModel { $this->db->transStart(); - new EpisodeCommentModel() - ->builder() + (new EpisodeCommentModel())->builder() ->where('id', service('uuid') ->fromString($comment->id) ->getBytes()) ->decrement('likes_count'); $this->where([ - 'actor_id' => $actor->id, + 'actor_id' => $actor->id, 'comment_id' => service('uuid') ->fromString($comment->id) ->getBytes(), @@ -108,18 +106,13 @@ class LikeModel extends UuidModel if ($registerActivity) { $undoActivity = new UndoActivity(); // FIXME: get like activity associated with the deleted like - $activity = model('ActivityModel') + $activity = model(ActivityModel::class) ->where([ - 'type' => 'Like', + 'type' => 'Like', 'actor_id' => $actor->id, ]) ->first(); - if (! $activity instanceof Activity) { - // no like activity found, do nothing - return; - } - $likeActivity = new LikeActivity(); $likeActivity ->set('id', url_to('activity', esc($actor->username), $activity->id)) @@ -130,7 +123,7 @@ class LikeModel extends UuidModel ->set('actor', $actor->uri) ->set('object', $likeActivity); - $activityId = model('ActivityModel') + $activityId = model(ActivityModel::class) ->newActivity( 'Undo', $actor->id, @@ -143,7 +136,7 @@ class LikeModel extends UuidModel $undoActivity->set('id', url_to('activity', esc($actor->username), $activityId)); - model('ActivityModel') + model(ActivityModel::class) ->update($activityId, [ 'payload' => $undoActivity->toJSON(), ]); @@ -159,11 +152,11 @@ class LikeModel extends UuidModel { if ( $this->where([ - 'actor_id' => $actor->id, + 'actor_id' => $actor->id, 'comment_id' => service('uuid') ->fromString($comment->id) ->getBytes(), - ])->first() instanceof Like + ])->first() ) { $this->removeLike($actor, $comment); } else { diff --git a/modules/Media/Models/MediaModel.php b/app/Models/MediaModel.php similarity index 65% rename from modules/Media/Models/MediaModel.php rename to app/Models/MediaModel.php index d6b948a6..7acb9608 100644 --- a/modules/Media/Models/MediaModel.php +++ b/app/Models/MediaModel.php @@ -8,18 +8,18 @@ declare(strict_types=1); * @link https://castopod.org/ */ -namespace Modules\Media\Models; +namespace App\Models; +use App\Entities\Media\Audio; +use App\Entities\Media\Chapters; +use App\Entities\Media\Document; +use App\Entities\Media\Image; +use App\Entities\Media\Transcript; +use App\Entities\Media\Video; use CodeIgniter\Database\BaseResult; use CodeIgniter\Database\ConnectionInterface; use CodeIgniter\Model; use CodeIgniter\Validation\ValidationInterface; -use Modules\Media\Entities\Audio; -use Modules\Media\Entities\Chapters; -use Modules\Media\Entities\Document; -use Modules\Media\Entities\Image; -use Modules\Media\Entities\Transcript; -use Modules\Media\Entities\Video; class MediaModel extends Model { @@ -28,6 +28,9 @@ class MediaModel extends Model */ protected $table = 'media'; + /** + * @noRector + */ protected $returnType = Document::class; /** @@ -48,11 +51,11 @@ class MediaModel extends Model protected $createdField = 'uploaded_at'; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', - 'file_key', + 'file_path', 'file_size', 'file_mimetype', 'file_metadata', @@ -66,32 +69,46 @@ class MediaModel extends Model /** * clear cache before update if by any chance, the podcast name changes, so will the podcast link * - * @var list + * @var string[] */ protected $beforeUpdate = ['clearCache']; /** - * @var list + * @var string[] */ protected $beforeDelete = ['clearCache']; /** + * Model constructor. + * * @param ConnectionInterface|null $db DB Connection * @param ValidationInterface|null $validation Validation */ public function __construct( protected string $fileType = 'document', - ?ConnectionInterface &$db = null, - ?ValidationInterface $validation = null, + ConnectionInterface &$db = null, + ValidationInterface $validation = null ) { - $this->returnType = match ($fileType) { - 'audio' => Audio::class, - 'video' => Video::class, - 'image' => Image::class, - 'transcript' => Transcript::class, - 'chapters' => Chapters::class, - default => Document::class, - }; + switch ($fileType) { + case 'audio': + $this->returnType = Audio::class; + break; + case 'video': + $this->returnType = Video::class; + break; + case 'image': + $this->returnType = Image::class; + break; + case 'transcript': + $this->returnType = Transcript::class; + break; + case 'chapters': + $this->returnType = Chapters::class; + break; + default: + // do nothing, keep Document class as default + break; + } parent::__construct($db, $validation); } @@ -100,7 +117,14 @@ class MediaModel extends Model { $cacheName = "media#{$mediaId}"; if (! ($found = cache($cacheName))) { - $found = $this->find($mediaId); + $builder = $this->where([ + 'id' => $mediaId, + ]); + + /** @var object $result */ + $result = $builder->first(); + $mediaClass = $this->returnType; + $found = new $mediaClass($result->toArray(false, true)); cache() ->save($cacheName, $found, DECADE); @@ -111,19 +135,13 @@ class MediaModel extends Model /** * @param Document|Audio|Video|Image|Transcript|Chapters $media + * + * @noRector ReturnTypeDeclarationRector */ public function saveMedia(object $media): int | false { - // save file first - $media->saveFile(); - // insert record in database - /** @var int|false $mediaId */ - $mediaId = $this->insert($media, true); - - if (! $mediaId) { - $this->db->transRollback(); - + if (! $mediaId = $this->insert($media, true)) { return false; } @@ -132,14 +150,11 @@ class MediaModel extends Model /** * @param Document|Audio|Video|Image|Transcript|Chapters $media + * + * @noRector ReturnTypeDeclarationRector */ public function updateMedia(object $media): bool { - // save file first - // FIXME: what if file is not set? - $media->saveFile(); - - // update record in database return $this->update($media->id, $media); } @@ -158,14 +173,9 @@ class MediaModel extends Model return $result; } - /** - * @param Document|Audio|Video|Image|Transcript|Chapters $media - */ - public function deleteMedia($media): bool|BaseResult + public function deleteMedia(object $media): bool|BaseResult { - if (! $media->deleteFile()) { - return false; - } + $media->deleteFile(); return $this->delete($media->id); } diff --git a/app/Models/PageModel.php b/app/Models/PageModel.php index f9a9eb5a..62772b59 100644 --- a/app/Models/PageModel.php +++ b/app/Models/PageModel.php @@ -26,12 +26,12 @@ class PageModel extends Model protected $primaryKey = 'id'; /** - * @var list + * @var string[] */ protected $allowedFields = ['id', 'title', 'slug', 'content_markdown', 'content_html']; /** - * @var class-string + * @var string */ protected $returnType = Page::class; @@ -49,25 +49,26 @@ class PageModel extends Model * @var array */ protected $validationRules = [ - 'title' => 'required', - 'slug' => 'required|regex_match[/^[a-zA-Z0-9\-]{1,128}$/]|is_unique[pages.slug,id,{id}]', + 'title' => 'required', + 'slug' => + 'required|regex_match[/^[a-zA-Z0-9\-]{1,128}$/]|is_unique[pages.slug,id,{id}]', 'content_markdown' => 'required', ]; /** - * @var list + * @var string[] */ protected $afterInsert = ['clearCache']; /** * Before update because slug or title might change * - * @var list + * @var string[] */ protected $beforeUpdate = ['clearCache']; /** - * @var list + * @var string[] */ protected $beforeDelete = ['clearCache']; diff --git a/app/Models/PersonModel.php b/app/Models/PersonModel.php index 705ad50a..9948393c 100644 --- a/app/Models/PersonModel.php +++ b/app/Models/PersonModel.php @@ -26,7 +26,7 @@ class PersonModel extends Model protected $primaryKey = 'id'; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -39,7 +39,7 @@ class PersonModel extends Model ]; /** - * @var class-string + * @var string */ protected $returnType = Person::class; @@ -57,26 +57,27 @@ class PersonModel extends Model * @var array */ protected $validationRules = [ - 'full_name' => 'required', - 'unique_name' => 'required|regex_match[/^[a-z0-9\-]{1,32}$/]|is_unique[persons.unique_name,id,{id}]', - 'created_by' => 'required', - 'updated_by' => 'required', + 'full_name' => 'required', + 'unique_name' => + 'required|regex_match[/^[a-z0-9\-]{1,32}$/]|is_unique[persons.unique_name,id,{id}]', + 'created_by' => 'required', + 'updated_by' => 'required', ]; /** - * @var list + * @var string[] */ protected $afterInsert = ['clearCache']; /** * clear cache before update if by any chance, the person name changes, so will the person link * - * @var list + * @var string[] */ protected $beforeUpdate = ['clearCache']; /** - * @var list + * @var string[] */ protected $beforeDelete = ['clearCache']; @@ -145,11 +146,8 @@ class PersonModel extends Model $this->select('`id`, `full_name`') ->orderBy('`full_name`', 'ASC') ->findAll(), - static function (array $result, Person $person): array { - $result[] = [ - 'value' => $person->id, - 'label' => $person->full_name, - ]; + static function ($result, $person) { + $result[$person->id] = $person->full_name; return $result; }, [], @@ -177,10 +175,9 @@ class PersonModel extends Model if (! ($options = cache($cacheName))) { foreach ($personsTaxonomy as $group_key => $group) { foreach ($group['roles'] as $role_key => $role) { - $options[] = [ - 'value' => sprintf('%s,%s', $group_key, $role_key), - 'label' => sprintf('%s › %s', $group['label'], $role['label']), - ]; + $options[ + "{$group_key},{$role_key}" + ] = "{$group['label']} › {$role['label']}"; } } @@ -194,13 +191,12 @@ class PersonModel extends Model public function addPerson(string $fullName, ?string $informationUrl, string $image): int | bool { $person = new Person([ - 'created_by' => user_id(), - 'updated_by' => user_id(), - 'full_name' => $fullName, - 'unique_name' => slugify($fullName), + 'full_name' => $fullName, + 'unique_name' => slugify($fullName), 'information_url' => $informationUrl, - 'image' => download_file($image), - + 'image' => download_file($image), + 'created_by' => user_id(), + 'updated_by' => user_id(), ]); return $this->insert($person); @@ -215,7 +211,7 @@ class PersonModel extends Model if (! ($found = cache($cacheName))) { $this->builder() ->select( - 'persons.*, episodes_persons.podcast_id as podcast_id, episodes_persons.episode_id as episode_id', + 'persons.*, episodes_persons.podcast_id as podcast_id, episodes_persons.episode_id as episode_id' ) ->distinct() ->join('episodes_persons', 'persons.id = episodes_persons.person_id') @@ -257,35 +253,34 @@ class PersonModel extends Model int $episodeId, int $personId, string $groupSlug, - string $roleSlug, + string $roleSlug ): bool { return $this->db->table('episodes_persons') ->insert([ - 'podcast_id' => $podcastId, - 'episode_id' => $episodeId, - 'person_id' => $personId, + 'podcast_id' => $podcastId, + 'episode_id' => $episodeId, + 'person_id' => $personId, 'person_group' => $groupSlug, - 'person_role' => $roleSlug, + 'person_role' => $roleSlug, ]); } public function addPodcastPerson(int $podcastId, int $personId, string $groupSlug, string $roleSlug): bool { return $this->db->table('podcasts_persons') - ->ignore(true) ->insert([ - 'podcast_id' => $podcastId, - 'person_id' => $personId, + 'podcast_id' => $podcastId, + 'person_id' => $personId, 'person_group' => $groupSlug, - 'person_role' => $roleSlug, + 'person_role' => $roleSlug, ]); } /** * Add persons to podcast * - * @param int[] $personIds - * @param string[] $roles + * @param array $personIds + * @param array $roles * * @return bool|int Number of rows inserted or FALSE on failure */ @@ -297,30 +292,26 @@ class PersonModel extends Model cache() ->delete("podcast#{$podcastId}_persons"); - new PodcastModel() - ->clearCache([ - 'id' => $podcastId, - ]); + (new PodcastModel())->clearCache([ + 'id' => $podcastId, + ]); $data = []; foreach ($personIds as $personId) { if ($roles === []) { - // add to default group (cast) and role (host), see https://podcastindex.org/namespace/1.0#person $data[] = [ - 'podcast_id' => $podcastId, - 'person_id' => $personId, - 'person_group' => 'cast', - 'person_role' => 'host', + 'podcast_id' => $podcastId, + 'person_id' => $personId, ]; } foreach ($roles as $role) { $groupRole = explode(',', $role); $data[] = [ - 'podcast_id' => $podcastId, - 'person_id' => $personId, + 'podcast_id' => $podcastId, + 'person_id' => $personId, 'person_group' => $groupRole[0], - 'person_role' => $groupRole[1], + 'person_role' => $groupRole[1], ]; } } @@ -340,15 +331,14 @@ class PersonModel extends Model cache()->deleteMatching("podcast#{$podcastId}_person#{$personId}*"); cache() ->delete("podcast#{$podcastId}_persons"); - new PodcastModel() - ->clearCache([ - 'id' => $podcastId, - ]); + (new PodcastModel())->clearCache([ + 'id' => $podcastId, + ]); return $this->db->table('podcasts_persons') ->delete([ 'podcast_id' => $podcastId, - 'person_id' => $personId, + 'person_id' => $personId, ]); } @@ -356,40 +346,41 @@ class PersonModel extends Model * Add persons to episode * * @param int[] $personIds - * @param string[] $roles + * @param string[] $groupsRoles * * @return bool|int Number of rows inserted or FALSE on failure */ - public function addEpisodePersons(int $podcastId, int $episodeId, array $personIds, array $roles): bool | int - { + public function addEpisodePersons( + int $podcastId, + int $episodeId, + array $personIds, + array $groupsRoles + ): bool | int { if ($personIds !== []) { cache() ->delete("podcast#{$podcastId}_episode#{$episodeId}_persons"); - new EpisodeModel() - ->clearCache([ - 'id' => $episodeId, - ]); + (new EpisodeModel())->clearCache([ + 'id' => $episodeId, + ]); $data = []; foreach ($personIds as $personId) { - if ($roles === []) { + if ($groupsRoles !== []) { + foreach ($groupsRoles as $groupRole) { + $groupRole = explode(',', $groupRole); + $data[] = [ + 'podcast_id' => $podcastId, + 'episode_id' => $episodeId, + 'person_id' => $personId, + 'person_group' => $groupRole[0], + 'person_role' => $groupRole[1], + ]; + } + } else { $data[] = [ - 'podcast_id' => $podcastId, - 'episode_id' => $episodeId, - 'person_id' => $personId, - 'person_group' => 'cast', - 'person_role' => 'host', - ]; - } - - foreach ($roles as $role) { - $groupRole = explode(',', $role); - $data[] = [ - 'podcast_id' => $podcastId, - 'episode_id' => $episodeId, - 'person_id' => $personId, - 'person_group' => $groupRole[0], - 'person_role' => $groupRole[1], + 'podcast_id' => $podcastId, + 'episode_id' => $episodeId, + 'person_id' => $personId, ]; } } @@ -407,16 +398,15 @@ class PersonModel extends Model cache()->deleteMatching("podcast#{$podcastId}_episode#{$episodeId}_person#{$personId}*"); cache() ->delete("podcast#{$podcastId}_episode#{$episodeId}_persons"); - new EpisodeModel() - ->clearCache([ - 'id' => $episodeId, - ]); + (new EpisodeModel())->clearCache([ + 'id' => $episodeId, + ]); return $this->db->table('episodes_persons') ->delete([ 'podcast_id' => $podcastId, 'episode_id' => $episodeId, - 'person_id' => $personId, + 'person_id' => $personId, ]); } diff --git a/app/Models/PlatformModel.php b/app/Models/PlatformModel.php new file mode 100644 index 00000000..990f4f59 --- /dev/null +++ b/app/Models/PlatformModel.php @@ -0,0 +1,209 @@ +baseURL, '/'); + $found = $this->select( + "*, CONCAT('{$baseUrl}/assets/images/platforms/',`type`,'/',`slug`,'.svg') as icon", + )->findAll(); + cache() + ->save('platforms', $found, DECADE); + } + + return $found; + } + + public function getPlatform(string $slug): ?Platform + { + $cacheName = "platform-{$slug}"; + if (! ($found = cache($cacheName))) { + $found = $this->where('slug', $slug) + ->first(); + cache() + ->save($cacheName, $found, DECADE); + } + + return $found; + } + + public function createPlatform( + string $slug, + string $type, + string $label, + string $homeUrl, + string $submitUrl = null + ): int | false { + $data = [ + 'slug' => $slug, + 'type' => $type, + 'label' => $label, + 'home_url' => $homeUrl, + 'submit_url' => $submitUrl, + ]; + + return $this->insert($data, false); + } + + /** + * @return Platform[] + */ + public function getPlatformsWithLinks(int $podcastId, string $platformType): array + { + if ( + ! ($found = cache("podcast#{$podcastId}_platforms_{$platformType}_withLinks")) + ) { + $found = $this->select( + 'platforms.*, podcasts_platforms.link_url, podcasts_platforms.account_id, podcasts_platforms.is_visible, podcasts_platforms.is_on_embed', + ) + ->join( + 'podcasts_platforms', + "podcasts_platforms.platform_slug = platforms.slug AND podcasts_platforms.podcast_id = {$podcastId}", + 'left', + ) + ->where('platforms.type', $platformType) + ->findAll(); + + cache() + ->save("podcast#{$podcastId}_platforms_{$platformType}_withLinks", $found, DECADE); + } + + return $found; + } + + /** + * @return Platform[] + */ + public function getPodcastPlatforms(int $podcastId, string $platformType): array + { + $cacheName = "podcast#{$podcastId}_platforms_{$platformType}"; + if (! ($found = cache($cacheName))) { + $found = $this->select( + 'platforms.*, podcasts_platforms.link_url, podcasts_platforms.account_id, podcasts_platforms.is_visible, podcasts_platforms.is_on_embed', + ) + ->join('podcasts_platforms', 'podcasts_platforms.platform_slug = platforms.slug') + ->where('podcasts_platforms.podcast_id', $podcastId) + ->where('platforms.type', $platformType) + ->findAll(); + + cache() + ->save($cacheName, $found, DECADE); + } + + return $found; + } + + /** + * @param mixed[] $podcastsPlatformsData + */ + public function savePodcastPlatforms( + int $podcastId, + string $platformType, + array $podcastsPlatformsData + ): int | false { + $this->clearCache($podcastId); + + $podcastsPlatformsTable = $this->db->prefixTable('podcasts_platforms'); + $platformsTable = $this->db->prefixTable('platforms'); + + $deleteJoinQuery = <<db->query($deleteJoinQuery, [$podcastId, $platformType]); + + return $this->db + ->table('podcasts_platforms') + ->insertBatch($podcastsPlatformsData); + } + + /** + * @param mixed[] $podcastsPlatformsData + */ + public function createPodcastPlatforms(int $podcastId, array $podcastsPlatformsData): int | false + { + $this->clearCache($podcastId); + + return $this->db + ->table('podcasts_platforms') + ->insertBatch($podcastsPlatformsData); + } + + public function removePodcastPlatform(int $podcastId, string $platformSlug): bool | string + { + $this->clearCache($podcastId); + + return $this->db->table('podcasts_platforms') + ->delete([ + 'podcast_id' => $podcastId, + 'platform_slug' => $platformSlug, + ]); + } + + public function clearCache(int $podcastId): void + { + cache()->deleteMatching("podcast#{$podcastId}_platforms_*"); + + // delete localized podcast page cache + cache() + ->deleteMatching("page_podcast#{$podcastId}*"); + // delete post and episode comments pages cache + cache() + ->deleteMatching('page_post*'); + cache() + ->deleteMatching('page_episode#*'); + } +} diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php index c64516f1..78d52672 100644 --- a/app/Models/PodcastModel.php +++ b/app/Models/PodcastModel.php @@ -10,8 +10,8 @@ declare(strict_types=1); namespace App\Models; -use App\Entities\Actor; use App\Entities\Podcast; +use CodeIgniter\Database\Query; use CodeIgniter\HTTP\URI; use CodeIgniter\Model; use phpseclib\Crypt\RSA; @@ -29,7 +29,7 @@ class PodcastModel extends Model protected $primaryKey = 'id'; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -38,6 +38,8 @@ class PodcastModel extends Model 'handle', 'description_markdown', 'description_html', + 'episode_description_footer_markdown', + 'episode_description_footer_html', 'cover_id', 'banner_id', 'language_code', @@ -56,7 +58,12 @@ class PodcastModel extends Model 'location_name', 'location_geo', 'location_osm', + 'payment_pointer', + 'custom_rss', 'is_published_on_hubs', + 'partner_id', + 'partner_link_url', + 'partner_image_url', 'is_premium_by_default', 'published_at', 'created_by', @@ -64,7 +71,7 @@ class PodcastModel extends Model ]; /** - * @var class-string + * @var string */ protected $returnType = Podcast::class; @@ -77,45 +84,45 @@ class PodcastModel extends Model * @var array */ protected $validationRules = [ - 'id' => 'permit_empty|is_natural_no_zero', - 'title' => 'required', - 'handle' => 'required|regex_match[/^[a-zA-Z0-9\_]{1,32}$/]|is_unique[podcasts.handle,id,{id}]', + 'title' => 'required', + 'handle' => + 'required|regex_match[/^[a-zA-Z0-9\_]{1,32}$/]|is_unique[podcasts.handle,id,{id}]', 'description_markdown' => 'required', - 'cover_id' => 'required', - 'language_code' => 'required', - 'category_id' => 'required', - 'owner_email' => 'required|valid_email', - 'new_feed_url' => 'valid_url_strict|permit_empty', - 'type' => 'required', - 'published_at' => 'valid_date|permit_empty', - 'created_by' => 'required', - 'updated_by' => 'required', + 'cover_id' => 'required', + 'language_code' => 'required', + 'category_id' => 'required', + 'owner_email' => 'required|valid_email', + 'new_feed_url' => 'valid_url_strict|permit_empty', + 'type' => 'required', + 'published_at' => 'valid_date|permit_empty', + 'created_by' => 'required', + 'updated_by' => 'required', ]; /** - * @var list + * @var string[] */ protected $beforeInsert = ['setPodcastGUID', 'createPodcastActor']; /** - * @var list + * @var string[] */ protected $afterInsert = ['setActorAvatar']; /** - * @var list + * @var string[] */ protected $afterUpdate = ['updatePodcastActor']; /** * clear cache before update if by any chance, the podcast name changes, so will the podcast link * - * @var list + * @var string[] */ protected $beforeUpdate = ['clearCache']; /** - * @var list + * @var string[] */ protected $beforeDelete = ['clearCache']; @@ -163,21 +170,27 @@ class PodcastModel extends Model /** * @return Podcast[] */ - public function getAllPodcasts(?string $orderBy = null): array + public function getAllPodcasts(string $orderBy = null): array { $prefix = $this->db->getPrefix(); if ($orderBy === 'activity') { + $fediverseTablePrefix = $prefix . config('Fediverse') + ->tablesPrefix; $this->builder() - ->select('podcasts.*, MAX(`' . $prefix . 'fediverse_posts`.`published_at`) as max_published_at') - ->join('fediverse_posts', 'fediverse_posts.actor_id = podcasts.actor_id', 'left') - ->groupStart() + ->select( + 'podcasts.*, MAX(' . $fediverseTablePrefix . 'posts.published_at' . ') as max_published_at' + ) + ->join( + $fediverseTablePrefix . 'posts', + $fediverseTablePrefix . 'posts.actor_id = podcasts.actor_id', + 'left' + ) ->where( - '`' . $prefix . 'fediverse_posts`.`published_at` <= UTC_TIMESTAMP()', + '`' . $fediverseTablePrefix . 'posts`.`published_at` <= UTC_TIMESTAMP()', null, - false, - )->orWhere('fediverse_posts.published_at') - ->groupEnd() + false + )->orWhere($fediverseTablePrefix . 'posts.published_at', null) ->groupBy('podcasts.actor_id') ->orderBy('max_published_at', 'DESC'); } elseif ($orderBy === 'created_desc') { @@ -192,14 +205,15 @@ class PodcastModel extends Model /** * Gets all the podcasts a given user is contributing to * - * @param string[] $userPodcastIds * @return Podcast[] podcasts */ - public function getUserPodcasts(int $userId, array $userPodcastIds): array + public function getUserPodcasts(int $userId): array { $cacheName = "user{$userId}_podcasts"; if (! ($found = cache($cacheName))) { - $found = $userPodcastIds === [] ? [] : $this->whereIn('id', $userPodcastIds) + $found = $this->select('podcasts.*') + ->join('podcasts_users', 'podcasts_users.podcast_id = podcasts.id') + ->where('podcasts_users.user_id', $userId) ->findAll(); cache() @@ -209,18 +223,76 @@ class PodcastModel extends Model return $found; } - public function getContributorGroup(int $userId, int $podcastId): int | false + public function addPodcastContributor(int $userId, int $podcastId, int $groupId): Query | bool { - $userPodcast = $this->db - ->table('auth_groups_users') - ->select('user_id, group') - ->where('user_id', $userId) - ->like('group', "podcast#{$podcastId}") - ->get() - ->getResultObject(); + cache()->delete("podcast#{$podcastId}_contributors"); + + $data = [ + 'user_id' => $userId, + 'podcast_id' => $podcastId, + 'group_id' => $groupId, + ]; + + return $this->db->table('podcasts_users') + ->insert($data); + } + + public function updatePodcastContributor(int $userId, int $podcastId, int $groupId): bool + { + cache()->delete("podcast#{$podcastId}_contributors"); + + return $this->db + ->table('podcasts_users') + ->where([ + 'user_id' => $userId, + 'podcast_id' => $podcastId, + ]) + ->update([ + 'group_id' => $groupId, + ]); + } + + public function removePodcastContributor(int $userId, int $podcastId): string | bool + { + cache()->delete("podcast#{$podcastId}_contributors"); + + return $this->db + ->table('podcasts_users') + ->where([ + 'user_id' => $userId, + 'podcast_id' => $podcastId, + ]) + ->delete(); + } + + public function getContributorGroupId(int $userId, int | string $podcastId): int | false + { + if (! is_numeric($podcastId)) { + // identifier is the podcast name, request must be a join + $userPodcast = $this->db + ->table('podcasts_users') + ->select('group_id, user_id') + ->join('podcasts', 'podcasts.id = podcasts_users.podcast_id') + ->where([ + 'user_id' => $userId, + 'handle' => $podcastId, + ]) + ->get() + ->getResultObject(); + } else { + $userPodcast = $this->db + ->table('podcasts_users') + ->select('group_id') + ->where([ + 'user_id' => $userId, + 'podcast_id' => $podcastId, + ]) + ->get() + ->getResultObject(); + } return $userPodcast !== [] - ? (int) $userPodcast[0]->group + ? (int) $userPodcast[0]->group_id : false; } @@ -236,8 +308,9 @@ class PodcastModel extends Model ->builder() ->select('YEAR(published_at) as year, count(*) as number_of_episodes') ->where([ - 'podcast_id' => $podcastId, + 'podcast_id' => $podcastId, 'season_number' => null, + 'published_at IS NOT' => null, ]) ->where('`published_at` <= UTC_TIMESTAMP()', null, false) ->groupBy('year') @@ -248,7 +321,13 @@ class PodcastModel extends Model $secondsToNextUnpublishedEpisode = $episodeModel->getSecondsToNextUnpublishedEpisode($podcastId); cache() - ->save($cacheName, $found, $secondsToNextUnpublishedEpisode ?: DECADE); + ->save( + $cacheName, + $found, + $secondsToNextUnpublishedEpisode + ? $secondsToNextUnpublishedEpisode + : DECADE, + ); } return $found; @@ -266,8 +345,9 @@ class PodcastModel extends Model ->builder() ->select('season_number, count(*) as number_of_episodes') ->where([ - 'podcast_id' => $podcastId, + 'podcast_id' => $podcastId, 'season_number is not' => null, + 'published_at IS NOT' => null, ]) ->where('`published_at` <= UTC_TIMESTAMP()', null, false) ->groupBy('season_number') @@ -278,7 +358,13 @@ class PodcastModel extends Model $secondsToNextUnpublishedEpisode = $episodeModel->getSecondsToNextUnpublishedEpisode($podcastId); cache() - ->save($cacheName, $found, $secondsToNextUnpublishedEpisode ?: DECADE); + ->save( + $cacheName, + $found, + $secondsToNextUnpublishedEpisode + ? $secondsToNextUnpublishedEpisode + : DECADE, + ); } return $found; @@ -309,11 +395,14 @@ class PodcastModel extends Model ]; } - $secondsToNextUnpublishedEpisode = new EpisodeModel() - ->getSecondsToNextUnpublishedEpisode($podcastId); + $secondsToNextUnpublishedEpisode = (new EpisodeModel())->getSecondsToNextUnpublishedEpisode($podcastId); cache() - ->save($cacheName, $defaultQuery, $secondsToNextUnpublishedEpisode ?: DECADE); + ->save( + $cacheName, + $defaultQuery, + $secondsToNextUnpublishedEpisode ? $secondsToNextUnpublishedEpisode : DECADE + ); } return $defaultQuery; @@ -326,14 +415,13 @@ class PodcastModel extends Model */ public function clearCache(array $data): array { - $podcast = new self() - ->find((int) (is_array($data['id']) ? $data['id'][0] : $data['id'])); + $podcast = (new self())->getPodcastById(is_array($data['id']) ? $data['id'][0] : $data['id']); // delete cache for users' podcasts cache() ->deleteMatching('user*podcasts'); - if ($podcast instanceof Podcast) { + if ($podcast !== null) { // delete cache all podcast pages cache() ->deleteMatching("page_podcast#{$podcast->id}*"); @@ -356,19 +444,6 @@ class PodcastModel extends Model return $data; } - public function getFullTextMatchClauseForPodcasts(string $table, string $value): string - { - return ' - MATCH ( - ' . $table . '.title , - ' . $table . '.description_markdown, - ' . $table . '.handle, - ' . $table . '.location_name - ) - AGAINST(' . $this->db->escape($value) . ') - '; - } - /** * Creates an actor linked to the podcast (Triggered before insert) * @@ -391,22 +466,21 @@ class PodcastModel extends Model $domain = $url->getHost() . ($url->getPort() ? ':' . $url->getPort() : ''); - $actorId = new ActorModel() - ->insert( - [ - 'uri' => url_to('podcast-activity', $username), - 'username' => $username, - 'domain' => $domain, - 'private_key' => $privatekey, - 'public_key' => $publickey, - 'display_name' => $data['data']['title'], - 'summary' => $data['data']['description_html'], - 'inbox_url' => url_to('inbox', $username), - 'outbox_url' => url_to('outbox', $username), - 'followers_url' => url_to('followers', $username), - ], - true, - ); + $actorId = (new ActorModel())->insert( + [ + 'uri' => url_to('actor', $username), + 'username' => $username, + 'domain' => $domain, + 'private_key' => $privatekey, + 'public_key' => $publickey, + 'display_name' => $data['data']['title'], + 'summary' => $data['data']['description_html'], + 'inbox_url' => url_to('inbox', $username), + 'outbox_url' => url_to('outbox', $username), + 'followers_url' => url_to('followers', $username), + ], + true, + ); $data['data']['actor_id'] = $actorId; @@ -420,22 +494,17 @@ class PodcastModel extends Model */ protected function setActorAvatar(array $data): array { - $podcast = new self() - ->find((int) (is_array($data['id']) ? $data['id'][0] : $data['id'])); + $podcast = (new self())->getPodcastById(is_array($data['id']) ? $data['id'][0] : $data['id']); - if ($podcast instanceof Podcast) { - $podcastActor = new ActorModel() - ->find($podcast->actor_id); + if ($podcast !== null) { + $podcastActor = (new ActorModel())->find($podcast->actor_id); - if (! $podcastActor instanceof Actor) { - return $data; + if ($podcastActor) { + $podcastActor->avatar_image_url = $podcast->cover->thumbnail_url; + $podcastActor->avatar_image_mimetype = $podcast->cover->thumbnail_mimetype; + + (new ActorModel())->update($podcast->actor_id, $podcastActor); } - - $podcastActor->avatar_image_url = $podcast->cover->federation_url; - $podcastActor->avatar_image_mimetype = $podcast->cover->federation_mimetype; - - new ActorModel() - ->update($podcast->actor_id, $podcastActor); } return $data; @@ -448,21 +517,20 @@ class PodcastModel extends Model */ protected function updatePodcastActor(array $data): array { - $podcast = new self() - ->find((int) (is_array($data['id']) ? $data['id'][0] : $data['id'])); + $podcast = (new self())->getPodcastById(is_array($data['id']) ? $data['id'][0] : $data['id']); - if ($podcast instanceof Podcast) { + if ($podcast !== null) { $actorModel = new ActorModel(); $actor = $actorModel->getActorById($podcast->actor_id); - if ($actor instanceof Actor) { + if ($actor !== null) { // update values $actor->display_name = $podcast->title; $actor->summary = $podcast->description_html; $actor->avatar_image_url = $podcast->cover->federation_url; - $actor->avatar_image_mimetype = $podcast->cover->federation_mimetype; - $actor->cover_image_url = get_podcast_banner_url($podcast, 'federation'); - $actor->cover_image_mimetype = get_podcast_banner_mimetype($podcast, 'federation'); + $actor->avatar_image_mimetype = $podcast->cover->file_mimetype; + $actor->cover_image_url = $podcast->banner->federation_url; + $actor->cover_image_mimetype = $podcast->banner->file_mimetype; if ($actor->hasChanged()) { $actorModel->update($actor->id, $actor); @@ -476,21 +544,13 @@ class PodcastModel extends Model /** * @param mixed[] $data * - * Sets the UUIDv5 for a podcast. For more information, see - * https://podcastindex.org/namespace/1.0#guid - * * @return mixed[] */ protected function setPodcastGUID(array $data): array { - if (! array_key_exists( - 'guid', - $data['data'], - ) || $data['data']['guid'] === null || $data['data']['guid'] === '') { - $uuid = service('uuid'); - $feedUrl = url_to('podcast-rss-feed', $data['data']['handle']); - // 'ead4c236-bf58-58c6-a2c6-a6b28d128cb6' is the uuid of the podcast namespace - $data['data']['guid'] = $uuid->uuid5('ead4c236-bf58-58c6-a2c6-a6b28d128cb6', $feedUrl)->toString(); + if (! array_key_exists('guid', $data['data']) || $data['data']['guid'] === null) { + helper('misc'); + $data['data']['guid'] = podcast_uuid(url_to('podcast-rss-feed', $data['data']['handle'])); } return $data; diff --git a/app/Models/PostModel.php b/app/Models/PostModel.php index 06b0b00a..6f8df615 100644 --- a/app/Models/PostModel.php +++ b/app/Models/PostModel.php @@ -16,12 +16,12 @@ use Modules\Fediverse\Models\PostModel as FediversePostModel; class PostModel extends FediversePostModel { /** - * @var class-string + * @var string */ protected $returnType = Post::class; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -32,7 +32,6 @@ class PostModel extends FediversePostModel 'episode_id', 'message', 'message_html', - 'is_private', 'favourites_count', 'reblogs_count', 'replies_count', @@ -50,7 +49,7 @@ class PostModel extends FediversePostModel return $this->where([ 'episode_id' => $episodeId, ]) - ->where('in_reply_to_id') + ->where('in_reply_to_id', null) ->where('`published_at` <= UTC_TIMESTAMP()', null, false) ->orderBy('published_at', 'DESC') ->findAll(); @@ -59,13 +58,13 @@ class PostModel extends FediversePostModel public function setEpisodeIdForRepliesOfEpisodePosts(): int | false { // make sure that posts in reply to episode activities have an episode id - $postsToUpdate = $this->db->table('fediverse_posts as p1') - ->join('fediverse_posts as p2', 'p1.id = p2.in_reply_to_id') + $postsToUpdate = $this->db->table(config('Fediverse')->tablesPrefix . 'posts as p1') + ->join(config('Fediverse')->tablesPrefix . 'posts as p2', 'p1.id = p2.in_reply_to_id') ->select('p2.id, p1.episode_id') ->where([ 'p2.in_reply_to_id IS NOT' => null, - 'p2.episode_id' => null, - 'p1.episode_id IS NOT' => null, + 'p2.episode_id' => null, + 'p1.episode_id IS NOT' => null, ]) ->get() ->getResultArray(); diff --git a/app/Models/UserModel.php b/app/Models/UserModel.php new file mode 100644 index 00000000..13685b89 --- /dev/null +++ b/app/Models/UserModel.php @@ -0,0 +1,55 @@ +select('users.*, auth_groups.name as podcast_role') + ->join('podcasts_users', 'podcasts_users.user_id = users.id') + ->join('auth_groups', 'auth_groups.id = podcasts_users.group_id') + ->where('podcasts_users.podcast_id', $podcastId) + ->findAll(); + + cache() + ->save($cacheName, $found, DECADE); + } + + return $found; + } + + public function getPodcastContributor(int $userId, int $podcastId): ?User + { + // @phpstan-ignore-next-line + return $this->select('users.*, podcasts_users.podcast_id as podcast_id, auth_groups.name as podcast_role') + ->join('podcasts_users', 'podcasts_users.user_id = users.id') + ->join('auth_groups', 'auth_groups.id = podcasts_users.group_id') + ->where([ + 'users.id' => $userId, + 'podcast_id' => $podcastId, + ]) + ->first(); + } +} diff --git a/resources/static/fonts/inter-600.woff2 b/app/Resources/fonts/inter-600.woff2 similarity index 100% rename from resources/static/fonts/inter-600.woff2 rename to app/Resources/fonts/inter-600.woff2 diff --git a/resources/static/fonts/inter-regular.woff2 b/app/Resources/fonts/inter-regular.woff2 similarity index 100% rename from resources/static/fonts/inter-regular.woff2 rename to app/Resources/fonts/inter-regular.woff2 diff --git a/resources/static/fonts/kumbh-sans-700.woff2 b/app/Resources/fonts/kumbh-sans-700.woff2 similarity index 100% rename from resources/static/fonts/kumbh-sans-700.woff2 rename to app/Resources/fonts/kumbh-sans-700.woff2 diff --git a/resources/static/fonts/kumbh-sans-regular.woff2 b/app/Resources/fonts/kumbh-sans-regular.woff2 similarity index 100% rename from resources/static/fonts/kumbh-sans-regular.woff2 rename to app/Resources/fonts/kumbh-sans-regular.woff2 diff --git a/resources/static/fonts/noto-sans-mono-regular.woff2 b/app/Resources/fonts/noto-sans-mono-regular.woff2 similarity index 100% rename from resources/static/fonts/noto-sans-mono-regular.woff2 rename to app/Resources/fonts/noto-sans-mono-regular.woff2 diff --git a/app/Resources/icons/account-circle.svg b/app/Resources/icons/account-circle.svg new file mode 100644 index 00000000..c825dc5a --- /dev/null +++ b/app/Resources/icons/account-circle.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/add-box.svg b/app/Resources/icons/add-box.svg new file mode 100755 index 00000000..5a6fd80c --- /dev/null +++ b/app/Resources/icons/add-box.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/add.svg b/app/Resources/icons/add.svg new file mode 100755 index 00000000..8f3f5a20 --- /dev/null +++ b/app/Resources/icons/add.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/alert.svg b/app/Resources/icons/alert.svg new file mode 100755 index 00000000..7dd74af7 --- /dev/null +++ b/app/Resources/icons/alert.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/arrow-left.svg b/app/Resources/icons/arrow-left.svg new file mode 100644 index 00000000..d10d02b5 --- /dev/null +++ b/app/Resources/icons/arrow-left.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/arrow-right.svg b/app/Resources/icons/arrow-right.svg new file mode 100644 index 00000000..f46779f7 --- /dev/null +++ b/app/Resources/icons/arrow-right.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/at.svg b/app/Resources/icons/at.svg new file mode 100644 index 00000000..80191b5f --- /dev/null +++ b/app/Resources/icons/at.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/bold.svg b/app/Resources/icons/bold.svg new file mode 100644 index 00000000..b5fb5947 --- /dev/null +++ b/app/Resources/icons/bold.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/bookmark.svg b/app/Resources/icons/bookmark.svg new file mode 100755 index 00000000..d3bde5f3 --- /dev/null +++ b/app/Resources/icons/bookmark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/calendar.svg b/app/Resources/icons/calendar.svg new file mode 100644 index 00000000..fe9bf8d9 --- /dev/null +++ b/app/Resources/icons/calendar.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/caret-down.svg b/app/Resources/icons/caret-down.svg new file mode 100644 index 00000000..e2138c8d --- /dev/null +++ b/app/Resources/icons/caret-down.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/caret-right.svg b/app/Resources/icons/caret-right.svg new file mode 100644 index 00000000..346cb156 --- /dev/null +++ b/app/Resources/icons/caret-right.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/chat.svg b/app/Resources/icons/chat.svg new file mode 100755 index 00000000..594b1503 --- /dev/null +++ b/app/Resources/icons/chat.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/check.svg b/app/Resources/icons/check.svg new file mode 100644 index 00000000..a28368fc --- /dev/null +++ b/app/Resources/icons/check.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/chevron-left.svg b/app/Resources/icons/chevron-left.svg new file mode 100644 index 00000000..6d82f7ba --- /dev/null +++ b/app/Resources/icons/chevron-left.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/chevron-right.svg b/app/Resources/icons/chevron-right.svg new file mode 100644 index 00000000..f33dff5e --- /dev/null +++ b/app/Resources/icons/chevron-right.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/clapperboard.svg b/app/Resources/icons/clapperboard.svg new file mode 100644 index 00000000..c5d7d121 --- /dev/null +++ b/app/Resources/icons/clapperboard.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/clipboard.svg b/app/Resources/icons/clipboard.svg new file mode 100644 index 00000000..4e4214b2 --- /dev/null +++ b/app/Resources/icons/clipboard.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/close.svg b/app/Resources/icons/close.svg new file mode 100644 index 00000000..0ef4f305 --- /dev/null +++ b/app/Resources/icons/close.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/cloud-off.svg b/app/Resources/icons/cloud-off.svg new file mode 100755 index 00000000..7177145a --- /dev/null +++ b/app/Resources/icons/cloud-off.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/dashboard.svg b/app/Resources/icons/dashboard.svg new file mode 100644 index 00000000..a25c9e47 --- /dev/null +++ b/app/Resources/icons/dashboard.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/database.svg b/app/Resources/icons/database.svg new file mode 100644 index 00000000..6dc449b4 --- /dev/null +++ b/app/Resources/icons/database.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/Resources/icons/delete-bin.svg b/app/Resources/icons/delete-bin.svg new file mode 100755 index 00000000..bd1f9b30 --- /dev/null +++ b/app/Resources/icons/delete-bin.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/disc.svg b/app/Resources/icons/disc.svg new file mode 100644 index 00000000..095d2cda --- /dev/null +++ b/app/Resources/icons/disc.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/download.svg b/app/Resources/icons/download.svg new file mode 100755 index 00000000..b3ea2a9f --- /dev/null +++ b/app/Resources/icons/download.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/edit.svg b/app/Resources/icons/edit.svg new file mode 100755 index 00000000..d9efb56c --- /dev/null +++ b/app/Resources/icons/edit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/exchange-dollar.svg b/app/Resources/icons/exchange-dollar.svg new file mode 100644 index 00000000..85cc6af0 --- /dev/null +++ b/app/Resources/icons/exchange-dollar.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/Resources/icons/external-link.svg b/app/Resources/icons/external-link.svg new file mode 100755 index 00000000..2efc6259 --- /dev/null +++ b/app/Resources/icons/external-link.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/eye.svg b/app/Resources/icons/eye.svg new file mode 100755 index 00000000..f14a8b7d --- /dev/null +++ b/app/Resources/icons/eye.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/file-copy.svg b/app/Resources/icons/file-copy.svg new file mode 100755 index 00000000..0b907436 --- /dev/null +++ b/app/Resources/icons/file-copy.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/file-download.svg b/app/Resources/icons/file-download.svg new file mode 100644 index 00000000..0202c99a --- /dev/null +++ b/app/Resources/icons/file-download.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/folder-user.svg b/app/Resources/icons/folder-user.svg new file mode 100755 index 00000000..6dcd37c4 --- /dev/null +++ b/app/Resources/icons/folder-user.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/forbid.svg b/app/Resources/icons/forbid.svg new file mode 100644 index 00000000..dbc2632c --- /dev/null +++ b/app/Resources/icons/forbid.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/funding/default.svg b/app/Resources/icons/funding/default.svg new file mode 100644 index 00000000..0c7876ae --- /dev/null +++ b/app/Resources/icons/funding/default.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/gofundme.svg b/app/Resources/icons/funding/gofundme.svg new file mode 100755 index 00000000..976e231a --- /dev/null +++ b/app/Resources/icons/funding/gofundme.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/helloasso.svg b/app/Resources/icons/funding/helloasso.svg new file mode 100755 index 00000000..e32d9a3f --- /dev/null +++ b/app/Resources/icons/funding/helloasso.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/indiegogo.svg b/app/Resources/icons/funding/indiegogo.svg new file mode 100755 index 00000000..beb3ca26 --- /dev/null +++ b/app/Resources/icons/funding/indiegogo.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/kickstarter.svg b/app/Resources/icons/funding/kickstarter.svg new file mode 100755 index 00000000..a300d7be --- /dev/null +++ b/app/Resources/icons/funding/kickstarter.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/kisskissbankbank.svg b/app/Resources/icons/funding/kisskissbankbank.svg new file mode 100755 index 00000000..4755a204 --- /dev/null +++ b/app/Resources/icons/funding/kisskissbankbank.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/liberapay.svg b/app/Resources/icons/funding/liberapay.svg new file mode 100755 index 00000000..827862fc --- /dev/null +++ b/app/Resources/icons/funding/liberapay.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/patreon.svg b/app/Resources/icons/funding/patreon.svg new file mode 100755 index 00000000..39e20c5a --- /dev/null +++ b/app/Resources/icons/funding/patreon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/paypal.svg b/app/Resources/icons/funding/paypal.svg new file mode 100755 index 00000000..2b525b0c --- /dev/null +++ b/app/Resources/icons/funding/paypal.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/tipeee.svg b/app/Resources/icons/funding/tipeee.svg new file mode 100755 index 00000000..e3797fee --- /dev/null +++ b/app/Resources/icons/funding/tipeee.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/funding/ulule.svg b/app/Resources/icons/funding/ulule.svg new file mode 100755 index 00000000..c5002f2d --- /dev/null +++ b/app/Resources/icons/funding/ulule.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/group.svg b/app/Resources/icons/group.svg new file mode 100755 index 00000000..5c2f10ee --- /dev/null +++ b/app/Resources/icons/group.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/heading.svg b/app/Resources/icons/heading.svg new file mode 100644 index 00000000..0ae177f1 --- /dev/null +++ b/app/Resources/icons/heading.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/heart.svg b/app/Resources/icons/heart.svg new file mode 100755 index 00000000..f10aafa4 --- /dev/null +++ b/app/Resources/icons/heart.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/history.svg b/app/Resources/icons/history.svg new file mode 100644 index 00000000..684091df --- /dev/null +++ b/app/Resources/icons/history.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/Resources/icons/home-gear.svg b/app/Resources/icons/home-gear.svg new file mode 100644 index 00000000..2504da6d --- /dev/null +++ b/app/Resources/icons/home-gear.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/image-add.svg b/app/Resources/icons/image-add.svg new file mode 100644 index 00000000..dca9aa8b --- /dev/null +++ b/app/Resources/icons/image-add.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/italic.svg b/app/Resources/icons/italic.svg new file mode 100644 index 00000000..4203e07e --- /dev/null +++ b/app/Resources/icons/italic.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/line-chart.svg b/app/Resources/icons/line-chart.svg new file mode 100755 index 00000000..dc43cd7d --- /dev/null +++ b/app/Resources/icons/line-chart.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/link.svg b/app/Resources/icons/link.svg new file mode 100755 index 00000000..3b7c8e06 --- /dev/null +++ b/app/Resources/icons/link.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/list-ordered.svg b/app/Resources/icons/list-ordered.svg new file mode 100644 index 00000000..be282082 --- /dev/null +++ b/app/Resources/icons/list-ordered.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/list-unordered.svg b/app/Resources/icons/list-unordered.svg new file mode 100644 index 00000000..41809a3a --- /dev/null +++ b/app/Resources/icons/list-unordered.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/loader.svg b/app/Resources/icons/loader.svg new file mode 100644 index 00000000..55da7bdb --- /dev/null +++ b/app/Resources/icons/loader.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/lock-unlock.svg b/app/Resources/icons/lock-unlock.svg new file mode 100644 index 00000000..0ea4517c --- /dev/null +++ b/app/Resources/icons/lock-unlock.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/lock.svg b/app/Resources/icons/lock.svg new file mode 100644 index 00000000..a54f3e42 --- /dev/null +++ b/app/Resources/icons/lock.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/map-pin.svg b/app/Resources/icons/map-pin.svg new file mode 100644 index 00000000..5950f056 --- /dev/null +++ b/app/Resources/icons/map-pin.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/markdown.svg b/app/Resources/icons/markdown.svg new file mode 100644 index 00000000..ab3edd2b --- /dev/null +++ b/app/Resources/icons/markdown.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/menu.svg b/app/Resources/icons/menu.svg new file mode 100755 index 00000000..666764dc --- /dev/null +++ b/app/Resources/icons/menu.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/mic.svg b/app/Resources/icons/mic.svg new file mode 100755 index 00000000..becff50c --- /dev/null +++ b/app/Resources/icons/mic.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/more.svg b/app/Resources/icons/more.svg new file mode 100755 index 00000000..5f6b5dba --- /dev/null +++ b/app/Resources/icons/more.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/movie.svg b/app/Resources/icons/movie.svg new file mode 100755 index 00000000..f92dd60f --- /dev/null +++ b/app/Resources/icons/movie.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/notification-bell.svg b/app/Resources/icons/notification-bell.svg new file mode 100644 index 00000000..ea792a4d --- /dev/null +++ b/app/Resources/icons/notification-bell.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/Resources/icons/pages.svg b/app/Resources/icons/pages.svg new file mode 100755 index 00000000..3d28c400 --- /dev/null +++ b/app/Resources/icons/pages.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/pause.svg b/app/Resources/icons/pause.svg new file mode 100644 index 00000000..81cffce1 --- /dev/null +++ b/app/Resources/icons/pause.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/play-circle.svg b/app/Resources/icons/play-circle.svg new file mode 100644 index 00000000..5d5f7039 --- /dev/null +++ b/app/Resources/icons/play-circle.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/Resources/icons/play.svg b/app/Resources/icons/play.svg new file mode 100644 index 00000000..4978d3d5 --- /dev/null +++ b/app/Resources/icons/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/amazon.svg b/app/Resources/icons/podcasting/amazon.svg new file mode 100755 index 00000000..38341ba6 --- /dev/null +++ b/app/Resources/icons/podcasting/amazon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/antennapod.svg b/app/Resources/icons/podcasting/antennapod.svg new file mode 100755 index 00000000..0e0b9006 --- /dev/null +++ b/app/Resources/icons/podcasting/antennapod.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/anytime.svg b/app/Resources/icons/podcasting/anytime.svg new file mode 100644 index 00000000..d7e778a7 --- /dev/null +++ b/app/Resources/icons/podcasting/anytime.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/apple.svg b/app/Resources/icons/podcasting/apple.svg new file mode 100755 index 00000000..31e26446 --- /dev/null +++ b/app/Resources/icons/podcasting/apple.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/blubrry.svg b/app/Resources/icons/podcasting/blubrry.svg new file mode 100755 index 00000000..a556a5d8 --- /dev/null +++ b/app/Resources/icons/podcasting/blubrry.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/breaker.svg b/app/Resources/icons/podcasting/breaker.svg new file mode 100755 index 00000000..8de3e6e6 --- /dev/null +++ b/app/Resources/icons/podcasting/breaker.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/breez.svg b/app/Resources/icons/podcasting/breez.svg new file mode 100644 index 00000000..d0901c86 --- /dev/null +++ b/app/Resources/icons/podcasting/breez.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/castamatic.svg b/app/Resources/icons/podcasting/castamatic.svg new file mode 100644 index 00000000..6c97e493 --- /dev/null +++ b/app/Resources/icons/podcasting/castamatic.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/castbox.svg b/app/Resources/icons/podcasting/castbox.svg new file mode 100755 index 00000000..701e3721 --- /dev/null +++ b/app/Resources/icons/podcasting/castbox.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/castopod.svg b/app/Resources/icons/podcasting/castopod.svg new file mode 100755 index 00000000..784f7818 --- /dev/null +++ b/app/Resources/icons/podcasting/castopod.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/castro.svg b/app/Resources/icons/podcasting/castro.svg new file mode 100755 index 00000000..189e7d5a --- /dev/null +++ b/app/Resources/icons/podcasting/castro.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/chartable.svg b/app/Resources/icons/podcasting/chartable.svg new file mode 100755 index 00000000..46c49805 --- /dev/null +++ b/app/Resources/icons/podcasting/chartable.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/deezer.svg b/app/Resources/icons/podcasting/deezer.svg new file mode 100755 index 00000000..a22f53bf --- /dev/null +++ b/app/Resources/icons/podcasting/deezer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/default.svg b/app/Resources/icons/podcasting/default.svg new file mode 100644 index 00000000..09670128 --- /dev/null +++ b/app/Resources/icons/podcasting/default.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/fountain.svg b/app/Resources/icons/podcasting/fountain.svg new file mode 100644 index 00000000..558aea45 --- /dev/null +++ b/app/Resources/icons/podcasting/fountain.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/fyyd.svg b/app/Resources/icons/podcasting/fyyd.svg new file mode 100755 index 00000000..8f93cda4 --- /dev/null +++ b/app/Resources/icons/podcasting/fyyd.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/google.svg b/app/Resources/icons/podcasting/google.svg new file mode 100755 index 00000000..e580789c --- /dev/null +++ b/app/Resources/icons/podcasting/google.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/gpodder.svg b/app/Resources/icons/podcasting/gpodder.svg new file mode 100644 index 00000000..a8e02542 --- /dev/null +++ b/app/Resources/icons/podcasting/gpodder.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/ivoox.svg b/app/Resources/icons/podcasting/ivoox.svg new file mode 100755 index 00000000..f6c76f4a --- /dev/null +++ b/app/Resources/icons/podcasting/ivoox.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/listennotes.svg b/app/Resources/icons/podcasting/listennotes.svg new file mode 100755 index 00000000..3f7826f1 --- /dev/null +++ b/app/Resources/icons/podcasting/listennotes.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/overcast.svg b/app/Resources/icons/podcasting/overcast.svg new file mode 100755 index 00000000..3c30ae4a --- /dev/null +++ b/app/Resources/icons/podcasting/overcast.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/playerfm.svg b/app/Resources/icons/podcasting/playerfm.svg new file mode 100755 index 00000000..4e0adb91 --- /dev/null +++ b/app/Resources/icons/podcasting/playerfm.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/plink.svg b/app/Resources/icons/podcasting/plink.svg new file mode 100644 index 00000000..4f31d3e9 --- /dev/null +++ b/app/Resources/icons/podcasting/plink.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/pocketcasts.svg b/app/Resources/icons/podcasting/pocketcasts.svg new file mode 100755 index 00000000..62b2b533 --- /dev/null +++ b/app/Resources/icons/podcasting/pocketcasts.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podbean.svg b/app/Resources/icons/podcasting/podbean.svg new file mode 100755 index 00000000..71d160bd --- /dev/null +++ b/app/Resources/icons/podcasting/podbean.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podcastaddict.svg b/app/Resources/icons/podcasting/podcastaddict.svg new file mode 100755 index 00000000..83e02432 --- /dev/null +++ b/app/Resources/icons/podcasting/podcastaddict.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podcastguru.svg b/app/Resources/icons/podcasting/podcastguru.svg new file mode 100644 index 00000000..3d3909fa --- /dev/null +++ b/app/Resources/icons/podcasting/podcastguru.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podcastindex.svg b/app/Resources/icons/podcasting/podcastindex.svg new file mode 100755 index 00000000..9c46acc6 --- /dev/null +++ b/app/Resources/icons/podcasting/podcastindex.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podchaser.svg b/app/Resources/icons/podcasting/podchaser.svg new file mode 100755 index 00000000..5996f9d4 --- /dev/null +++ b/app/Resources/icons/podcasting/podchaser.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podcloud.svg b/app/Resources/icons/podcasting/podcloud.svg new file mode 100755 index 00000000..eee11508 --- /dev/null +++ b/app/Resources/icons/podcasting/podcloud.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podfriend.svg b/app/Resources/icons/podcasting/podfriend.svg new file mode 100755 index 00000000..7b84e85d --- /dev/null +++ b/app/Resources/icons/podcasting/podfriend.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podinstall.svg b/app/Resources/icons/podcasting/podinstall.svg new file mode 100755 index 00000000..ccc7c5be --- /dev/null +++ b/app/Resources/icons/podcasting/podinstall.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podlink.svg b/app/Resources/icons/podcasting/podlink.svg new file mode 100755 index 00000000..e0ad3e83 --- /dev/null +++ b/app/Resources/icons/podcasting/podlink.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podlp.svg b/app/Resources/icons/podcasting/podlp.svg new file mode 100644 index 00000000..f4a9a5c7 --- /dev/null +++ b/app/Resources/icons/podcasting/podlp.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podnews.svg b/app/Resources/icons/podcasting/podnews.svg new file mode 100644 index 00000000..95f890cc --- /dev/null +++ b/app/Resources/icons/podcasting/podnews.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podtail.svg b/app/Resources/icons/podcasting/podtail.svg new file mode 100755 index 00000000..b0b10dd9 --- /dev/null +++ b/app/Resources/icons/podcasting/podtail.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/podverse.svg b/app/Resources/icons/podcasting/podverse.svg new file mode 100755 index 00000000..4a710f64 --- /dev/null +++ b/app/Resources/icons/podcasting/podverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/radiopublic.svg b/app/Resources/icons/podcasting/radiopublic.svg new file mode 100755 index 00000000..de3ff737 --- /dev/null +++ b/app/Resources/icons/podcasting/radiopublic.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/sphinxchat.svg b/app/Resources/icons/podcasting/sphinxchat.svg new file mode 100644 index 00000000..95c2c4c4 --- /dev/null +++ b/app/Resources/icons/podcasting/sphinxchat.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/spotify.svg b/app/Resources/icons/podcasting/spotify.svg new file mode 100755 index 00000000..43d56a18 --- /dev/null +++ b/app/Resources/icons/podcasting/spotify.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/spreaker.svg b/app/Resources/icons/podcasting/spreaker.svg new file mode 100755 index 00000000..30cc454c --- /dev/null +++ b/app/Resources/icons/podcasting/spreaker.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/stitcher.svg b/app/Resources/icons/podcasting/stitcher.svg new file mode 100755 index 00000000..0d59cba8 --- /dev/null +++ b/app/Resources/icons/podcasting/stitcher.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/tsacdop.svg b/app/Resources/icons/podcasting/tsacdop.svg new file mode 100644 index 00000000..0d3e288f --- /dev/null +++ b/app/Resources/icons/podcasting/tsacdop.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/tunein.svg b/app/Resources/icons/podcasting/tunein.svg new file mode 100755 index 00000000..da721274 --- /dev/null +++ b/app/Resources/icons/podcasting/tunein.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/podcasting/zion.svg b/app/Resources/icons/podcasting/zion.svg new file mode 100644 index 00000000..20c2f2f7 --- /dev/null +++ b/app/Resources/icons/podcasting/zion.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/question.svg b/app/Resources/icons/question.svg new file mode 100755 index 00000000..b7fd91ed --- /dev/null +++ b/app/Resources/icons/question.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/quote.svg b/app/Resources/icons/quote.svg new file mode 100644 index 00000000..a83df6c4 --- /dev/null +++ b/app/Resources/icons/quote.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/refresh.svg b/app/Resources/icons/refresh.svg new file mode 100644 index 00000000..08b0dba0 --- /dev/null +++ b/app/Resources/icons/refresh.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/repeat.svg b/app/Resources/icons/repeat.svg new file mode 100644 index 00000000..c5a26047 --- /dev/null +++ b/app/Resources/icons/repeat.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/rss.svg b/app/Resources/icons/rss.svg new file mode 100755 index 00000000..723552d9 --- /dev/null +++ b/app/Resources/icons/rss.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/scales.svg b/app/Resources/icons/scales.svg new file mode 100755 index 00000000..7383e06a --- /dev/null +++ b/app/Resources/icons/scales.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/search.svg b/app/Resources/icons/search.svg new file mode 100644 index 00000000..4d61f480 --- /dev/null +++ b/app/Resources/icons/search.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/Resources/icons/send-plane.svg b/app/Resources/icons/send-plane.svg new file mode 100644 index 00000000..74ffbcf9 --- /dev/null +++ b/app/Resources/icons/send-plane.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/settings.svg b/app/Resources/icons/settings.svg new file mode 100755 index 00000000..893c92d2 --- /dev/null +++ b/app/Resources/icons/settings.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/social/castopod.svg b/app/Resources/icons/social/castopod.svg new file mode 100755 index 00000000..784f7818 --- /dev/null +++ b/app/Resources/icons/social/castopod.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/default.svg b/app/Resources/icons/social/default.svg new file mode 100644 index 00000000..3e1b678a --- /dev/null +++ b/app/Resources/icons/social/default.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/discord.svg b/app/Resources/icons/social/discord.svg new file mode 100644 index 00000000..9a63df1f --- /dev/null +++ b/app/Resources/icons/social/discord.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/facebook.svg b/app/Resources/icons/social/facebook.svg new file mode 100755 index 00000000..c6ddd7e9 --- /dev/null +++ b/app/Resources/icons/social/facebook.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/funkwhale.svg b/app/Resources/icons/social/funkwhale.svg new file mode 100755 index 00000000..95b5abf6 --- /dev/null +++ b/app/Resources/icons/social/funkwhale.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/instagram.svg b/app/Resources/icons/social/instagram.svg new file mode 100755 index 00000000..7726b140 --- /dev/null +++ b/app/Resources/icons/social/instagram.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/linkedin.svg b/app/Resources/icons/social/linkedin.svg new file mode 100755 index 00000000..9042d1ee --- /dev/null +++ b/app/Resources/icons/social/linkedin.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/mastodon.svg b/app/Resources/icons/social/mastodon.svg new file mode 100755 index 00000000..7bab6080 --- /dev/null +++ b/app/Resources/icons/social/mastodon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/misskey.svg b/app/Resources/icons/social/misskey.svg new file mode 100644 index 00000000..2b8b3850 --- /dev/null +++ b/app/Resources/icons/social/misskey.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/mobilizon.svg b/app/Resources/icons/social/mobilizon.svg new file mode 100755 index 00000000..564f3ca6 --- /dev/null +++ b/app/Resources/icons/social/mobilizon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/peertube.svg b/app/Resources/icons/social/peertube.svg new file mode 100755 index 00000000..4cf8e7f8 --- /dev/null +++ b/app/Resources/icons/social/peertube.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/pixelfed.svg b/app/Resources/icons/social/pixelfed.svg new file mode 100755 index 00000000..cb3e4d66 --- /dev/null +++ b/app/Resources/icons/social/pixelfed.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/pleroma.svg b/app/Resources/icons/social/pleroma.svg new file mode 100644 index 00000000..657fe8ac --- /dev/null +++ b/app/Resources/icons/social/pleroma.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/plume.svg b/app/Resources/icons/social/plume.svg new file mode 100755 index 00000000..841b3c0e --- /dev/null +++ b/app/Resources/icons/social/plume.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/reddit.svg b/app/Resources/icons/social/reddit.svg new file mode 100755 index 00000000..8a0d2f72 --- /dev/null +++ b/app/Resources/icons/social/reddit.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/slack.svg b/app/Resources/icons/social/slack.svg new file mode 100755 index 00000000..3737d5a2 --- /dev/null +++ b/app/Resources/icons/social/slack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/tiktok.svg b/app/Resources/icons/social/tiktok.svg new file mode 100755 index 00000000..d6a380d2 --- /dev/null +++ b/app/Resources/icons/social/tiktok.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/twitch.svg b/app/Resources/icons/social/twitch.svg new file mode 100755 index 00000000..79f77875 --- /dev/null +++ b/app/Resources/icons/social/twitch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/twitter.svg b/app/Resources/icons/social/twitter.svg new file mode 100755 index 00000000..1b07620c --- /dev/null +++ b/app/Resources/icons/social/twitter.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/writefreely.svg b/app/Resources/icons/social/writefreely.svg new file mode 100755 index 00000000..21bc015a --- /dev/null +++ b/app/Resources/icons/social/writefreely.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/social/youtube.svg b/app/Resources/icons/social/youtube.svg new file mode 100755 index 00000000..3d875054 --- /dev/null +++ b/app/Resources/icons/social/youtube.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/Resources/icons/sort.svg b/app/Resources/icons/sort.svg new file mode 100644 index 00000000..51df3545 --- /dev/null +++ b/app/Resources/icons/sort.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/star-smile.svg b/app/Resources/icons/star-smile.svg new file mode 100755 index 00000000..05014c31 --- /dev/null +++ b/app/Resources/icons/star-smile.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/timer.svg b/app/Resources/icons/timer.svg new file mode 100755 index 00000000..21ab4767 --- /dev/null +++ b/app/Resources/icons/timer.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/upload-cloud.svg b/app/Resources/icons/upload-cloud.svg new file mode 100755 index 00000000..b87c7581 --- /dev/null +++ b/app/Resources/icons/upload-cloud.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/user-add.svg b/app/Resources/icons/user-add.svg new file mode 100755 index 00000000..2d56227f --- /dev/null +++ b/app/Resources/icons/user-add.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/user-follow.svg b/app/Resources/icons/user-follow.svg new file mode 100644 index 00000000..e8892f28 --- /dev/null +++ b/app/Resources/icons/user-follow.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/Resources/icons/volume-high.svg b/app/Resources/icons/volume-high.svg new file mode 100644 index 00000000..0aa5be36 --- /dev/null +++ b/app/Resources/icons/volume-high.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/volume-low.svg b/app/Resources/icons/volume-low.svg new file mode 100644 index 00000000..6acfade5 --- /dev/null +++ b/app/Resources/icons/volume-low.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/volume-mute.svg b/app/Resources/icons/volume-mute.svg new file mode 100644 index 00000000..79bd55ac --- /dev/null +++ b/app/Resources/icons/volume-mute.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/icons/warning.svg b/app/Resources/icons/warning.svg new file mode 100644 index 00000000..e01de7fb --- /dev/null +++ b/app/Resources/icons/warning.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/Resources/images/castopod-logo-base.svg b/app/Resources/images/castopod-logo-base.svg new file mode 100644 index 00000000..482eebfe --- /dev/null +++ b/app/Resources/images/castopod-logo-base.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/Resources/images/castopod-logo.svg b/app/Resources/images/castopod-logo.svg new file mode 100644 index 00000000..039deb74 --- /dev/null +++ b/app/Resources/images/castopod-logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/Resources/images/castopod-mascot_confused.svg b/app/Resources/images/castopod-mascot_confused.svg new file mode 100644 index 00000000..ab32c445 --- /dev/null +++ b/app/Resources/images/castopod-mascot_confused.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/static/images/marker/marker-icon-2x.png b/app/Resources/images/marker/marker-icon-2x.png similarity index 100% rename from resources/static/images/marker/marker-icon-2x.png rename to app/Resources/images/marker/marker-icon-2x.png diff --git a/resources/static/images/marker/marker-icon.png b/app/Resources/images/marker/marker-icon.png similarity index 100% rename from resources/static/images/marker/marker-icon.png rename to app/Resources/images/marker/marker-icon.png diff --git a/resources/static/images/marker/marker-shadow.png b/app/Resources/images/marker/marker-shadow.png similarity index 100% rename from resources/static/images/marker/marker-shadow.png rename to app/Resources/images/marker/marker-shadow.png diff --git a/resources/js/admin-audio-player.ts b/app/Resources/js/admin-audio-player.ts similarity index 91% rename from resources/js/admin-audio-player.ts rename to app/Resources/js/admin-audio-player.ts index 7fa61b86..28460b89 100644 --- a/resources/js/admin-audio-player.ts +++ b/app/Resources/js/admin-audio-player.ts @@ -34,14 +34,14 @@ import { } from "@vime/core"; import "@vime/core/themes/default.css"; import "@vime/core/themes/light.css"; -import "./_modules/play-episode-button"; +import "./modules/play-episode-button"; -// Register Castopod's vm player icons library +// Register Castopod's icons library const library: HTMLVmIconLibraryElement | null = document.querySelector( - 'vm-icon-library[name="castopod-vm-player-icons"]' + 'vm-icon-library[name="castopod-icons"]' ); if (library) { - library.resolver = (iconName) => `/assets/vm-player-icons/${iconName}.svg`; + library.resolver = (iconName) => `/assets/icons/${iconName}.svg`; } // Vime elements for audio player diff --git a/app/Resources/js/admin.ts b/app/Resources/js/admin.ts new file mode 100644 index 00000000..078e919f --- /dev/null +++ b/app/Resources/js/admin.ts @@ -0,0 +1,40 @@ +import "@github/markdown-toolbar-element"; +import "@github/time-elements"; +import "./modules/audio-clipper"; +import ClientTimezone from "./modules/ClientTimezone"; +import Clipboard from "./modules/Clipboard"; +import DateTimePicker from "./modules/DateTimePicker"; +import Dropdown from "./modules/Dropdown"; +import HotKeys from "./modules/HotKeys"; +import "./modules/markdown-preview"; +import "./modules/markdown-write-preview"; +import MultiSelect from "./modules/MultiSelect"; +import "./modules/permalink-edit"; +import "./modules/play-soundbite"; +import PublishMessageWarning from "./modules/PublishMessageWarning"; +import Select from "./modules/Select"; +import SidebarToggler from "./modules/SidebarToggler"; +import Slugify from "./modules/Slugify"; +import ThemePicker from "./modules/ThemePicker"; +import Time from "./modules/Time"; +import Tooltip from "./modules/Tooltip"; +import ValidateFileSize from "./modules/ValidateFileSize"; +import "./modules/video-clip-previewer"; +import VideoClipBuilder from "./modules/VideoClipBuilder"; +import "./modules/xml-editor"; + +Dropdown(); +Tooltip(); +Select(); +MultiSelect(); +Slugify(); +SidebarToggler(); +ClientTimezone(); +DateTimePicker(); +Time(); +Clipboard(); +ThemePicker(); +PublishMessageWarning(); +HotKeys(); +ValidateFileSize(); +VideoClipBuilder(); diff --git a/app/Resources/js/app.ts b/app/Resources/js/app.ts new file mode 100644 index 00000000..7b944f47 --- /dev/null +++ b/app/Resources/js/app.ts @@ -0,0 +1,5 @@ +import Dropdown from "./modules/Dropdown"; +import Tooltip from "./modules/Tooltip"; + +Dropdown(); +Tooltip(); diff --git a/resources/js/audio-player.ts b/app/Resources/js/audio-player.ts similarity index 92% rename from resources/js/audio-player.ts rename to app/Resources/js/audio-player.ts index 7c15480f..74cebcc2 100644 --- a/resources/js/audio-player.ts +++ b/app/Resources/js/audio-player.ts @@ -35,7 +35,7 @@ import { import "@vime/core/themes/default.css"; import "@vime/core/themes/light.css"; import { html, render } from "lit"; -import "./_modules/play-episode-button"; +import "./modules/play-episode-button"; const player = html`
- + @@ -86,12 +86,12 @@ const player = html`
`/assets/vm-player-icons/${iconName}.svg`; + library.resolver = (iconName) => `/assets/icons/${iconName}.svg`; } // Vime elements for audio player diff --git a/app/Resources/js/charts.ts b/app/Resources/js/charts.ts new file mode 100644 index 00000000..de52bd13 --- /dev/null +++ b/app/Resources/js/charts.ts @@ -0,0 +1,4 @@ +import "core-js"; +import DrawCharts from "./modules/Charts"; + +DrawCharts(); diff --git a/resources/js/embed.ts b/app/Resources/js/embed.ts similarity index 93% rename from resources/js/embed.ts rename to app/Resources/js/embed.ts index d587cb7b..9bad2538 100644 --- a/resources/js/embed.ts +++ b/app/Resources/js/embed.ts @@ -35,12 +35,12 @@ import { import "@vime/core/themes/default.css"; import "@vime/core/themes/light.css"; -// Register Castopod's vm player icons library +// Register Castopod's icons library const library: HTMLVmIconLibraryElement | null = document.querySelector( - 'vm-icon-library[name="castopod-vm-player-icons"]' + 'vm-icon-library[name="castopod-icons"]' ); if (library) { - library.resolver = (iconName) => `/assets/vm-player-icons/${iconName}.svg`; + library.resolver = (iconName) => `/assets/icons/${iconName}.svg`; } // Vime elements for audio player diff --git a/resources/js/error.ts b/app/Resources/js/error.ts similarity index 100% rename from resources/js/error.ts rename to app/Resources/js/error.ts diff --git a/app/Resources/js/install.ts b/app/Resources/js/install.ts new file mode 100644 index 00000000..e3bb9d53 --- /dev/null +++ b/app/Resources/js/install.ts @@ -0,0 +1,3 @@ +import Tooltip from "./modules/Tooltip"; + +Tooltip(); diff --git a/app/Resources/js/map.ts b/app/Resources/js/map.ts new file mode 100644 index 00000000..66afdef9 --- /dev/null +++ b/app/Resources/js/map.ts @@ -0,0 +1,4 @@ +import "core-js"; +import DrawEpisodesMaps from "./modules/EpisodesMap"; + +DrawEpisodesMaps(); diff --git a/resources/js/_modules/Charts.ts b/app/Resources/js/modules/Charts.ts similarity index 99% rename from resources/js/_modules/Charts.ts rename to app/Resources/js/modules/Charts.ts index c949599b..bac6f232 100644 --- a/resources/js/_modules/Charts.ts +++ b/app/Resources/js/modules/Charts.ts @@ -149,7 +149,7 @@ const drawXYDurationChart = ( const yAxis = chart.yAxes.push(new am4charts.DurationAxis()); yAxis.baseUnit = "second"; - chart.durationFormatter.durationFormat = "hh'h'mm"; + chart.durationFormatter.durationFormat = "hh'h,' mm'mn'"; // Add data chart.dataSource.url = dataUrl || ""; diff --git a/resources/js/_modules/ClientTimezone.ts b/app/Resources/js/modules/ClientTimezone.ts similarity index 100% rename from resources/js/_modules/ClientTimezone.ts rename to app/Resources/js/modules/ClientTimezone.ts diff --git a/resources/js/_modules/Clipboard.ts b/app/Resources/js/modules/Clipboard.ts similarity index 95% rename from resources/js/_modules/Clipboard.ts rename to app/Resources/js/modules/Clipboard.ts index defb176a..7a344a86 100644 --- a/resources/js/_modules/Clipboard.ts +++ b/app/Resources/js/modules/Clipboard.ts @@ -10,6 +10,7 @@ const Clipboard = (): void => { ); if (element) { button.addEventListener("click", () => { + console.log(element); element.select(); element.setSelectionRange(0, element.value.length); document.execCommand("copy"); diff --git a/resources/js/_modules/DateTimePicker.ts b/app/Resources/js/modules/DateTimePicker.ts similarity index 100% rename from resources/js/_modules/DateTimePicker.ts rename to app/Resources/js/modules/DateTimePicker.ts diff --git a/resources/js/_modules/Dropdown.ts b/app/Resources/js/modules/Dropdown.ts similarity index 100% rename from resources/js/_modules/Dropdown.ts rename to app/Resources/js/modules/Dropdown.ts diff --git a/resources/js/_modules/EpisodesMap.ts b/app/Resources/js/modules/EpisodesMap.ts similarity index 91% rename from resources/js/_modules/EpisodesMap.ts rename to app/Resources/js/modules/EpisodesMap.ts index bc0b2ed5..390564f9 100644 --- a/resources/js/_modules/EpisodesMap.ts +++ b/app/Resources/js/modules/EpisodesMap.ts @@ -11,11 +11,14 @@ import { MarkerClusterGroup } from "leaflet.markercluster"; import "leaflet.markercluster/dist/MarkerCluster.css"; import "leaflet.markercluster/dist/MarkerCluster.Default.css"; import "leaflet/dist/leaflet.css"; +import markerIconRetina from "../../images/marker/marker-icon-2x.png"; +import markerIcon from "../../images/marker/marker-icon.png"; +import markerShadow from "../../images/marker/marker-shadow.png"; Marker.prototype.options.icon = icon({ - iconRetinaUrl: "/assets/images/marker/marker-icon-2x.png", - iconUrl: "/assets/images/marker/marker-icon.png", - shadowUrl: "/assets/images/marker/marker-shadow.png", + iconRetinaUrl: markerIconRetina, + iconUrl: markerIcon, + shadowUrl: markerShadow, iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], diff --git a/resources/js/_modules/HotKeys.ts b/app/Resources/js/modules/HotKeys.ts similarity index 100% rename from resources/js/_modules/HotKeys.ts rename to app/Resources/js/modules/HotKeys.ts diff --git a/resources/js/_modules/Modal.ts b/app/Resources/js/modules/Modal.ts similarity index 100% rename from resources/js/_modules/Modal.ts rename to app/Resources/js/modules/Modal.ts diff --git a/resources/js/_modules/SelectMulti.ts b/app/Resources/js/modules/MultiSelect.ts similarity index 88% rename from resources/js/_modules/SelectMulti.ts rename to app/Resources/js/modules/MultiSelect.ts index 064bc78a..34a12592 100644 --- a/resources/js/_modules/SelectMulti.ts +++ b/app/Resources/js/modules/MultiSelect.ts @@ -1,6 +1,6 @@ import Choices from "choices.js"; -const SelectMulti = (): void => { +const MultiSelect = (): void => { // Pass single element const multiSelects: NodeListOf = document.querySelectorAll("select[multiple]"); @@ -9,7 +9,6 @@ const SelectMulti = (): void => { const multiSelect = multiSelects[i]; new Choices(multiSelect, { - allowHTML: false, maxItemCount: parseInt(multiSelect.dataset.maxItemCount || "-1"), loadingText: multiSelect.dataset.loadingText, itemSelectText: multiSelect.dataset.selectText, @@ -18,38 +17,35 @@ const SelectMulti = (): void => { noResultsText: multiSelect.dataset.noResultsText, removeItemButton: true, classNames: { - activeState: "is-active", - addChoice: ["choices__item--selectable", "add-choice"], - button: "choices__button", - containerInner: "choices__inner", containerOuter: "choices", - description: "choices__description", - disabledState: "is-disabled", - flippedState: "is-flipped", - focusState: "is-focused", - group: "choices__group", - groupHeading: "choices__heading", - highlightedState: "is-highlighted", + containerInner: "choices__inner", input: "choices__input", inputCloned: "choices__input--cloned", - item: "choices__item", - itemChoice: "choices__item--choice", - itemDisabled: "choices__item--disabled", - itemSelectable: "choices__item--selectable", list: "choices__list", - listDropdown: "choices__list--dropdown", listItems: "choices__list--multiple", listSingle: "choices__list--single", - loadingState: "is-loading", - noChoices: "has-no-choices", - noResults: "has-no-results", - notice: "choices__notice", - openState: "is-open", + listDropdown: "choices__list--dropdown", + item: "choices__item", + itemSelectable: "choices__item--selectable", + itemDisabled: "choices__item--disabled", + itemChoice: "choices__item--choice", placeholder: "choices__placeholder", + group: "choices__group", + groupHeading: "choices__heading", + button: "choices__button", + activeState: "is-active", + focusState: "is-focused", + openState: "is-open", + disabledState: "is-disabled", + highlightedState: "is-highlighted", selectedState: "is-selected", + flippedState: "is-flipped", + loadingState: "is-loading", + noResults: "has-no-results", + noChoices: "has-no-choices", }, }); } }; -export default SelectMulti; +export default MultiSelect; diff --git a/resources/js/_modules/PublishMessageWarning.ts b/app/Resources/js/modules/PublishMessageWarning.ts similarity index 100% rename from resources/js/_modules/PublishMessageWarning.ts rename to app/Resources/js/modules/PublishMessageWarning.ts diff --git a/resources/js/_modules/Select.ts b/app/Resources/js/modules/Select.ts similarity index 90% rename from resources/js/_modules/Select.ts rename to app/Resources/js/modules/Select.ts index 840dfed8..d3c5dce4 100644 --- a/resources/js/_modules/Select.ts +++ b/app/Resources/js/modules/Select.ts @@ -10,42 +10,38 @@ const Select = (): void => { const select = selects[i]; new Choices(select, { - allowHTML: false, loadingText: select.dataset.loadingText, itemSelectText: select.dataset.selectText, maxItemText: select.dataset.maxItemText, noChoicesText: select.dataset.noChoicesText, noResultsText: select.dataset.noResultsText, classNames: { - activeState: "is-active", - addChoice: ["choices__item--selectable", "add-choice"], - button: "choices__button", - containerInner: "choices__inner", containerOuter: "choices", - description: "choices__description", - disabledState: "is-disabled", - flippedState: "is-flipped", - focusState: "is-focused", - group: "choices__group", - groupHeading: "choices__heading", - highlightedState: "is-highlighted", + containerInner: "choices__inner", input: "choices__input", inputCloned: "choices__input--cloned", - item: "choices__item", - itemChoice: "choices__item--choice", - itemDisabled: "choices__item--disabled", - itemSelectable: "choices__item--selectable", list: "choices__list", - listDropdown: "choices__list--dropdown", listItems: "choices__list--multiple", listSingle: "choices__list--single", - loadingState: "is-loading", - noChoices: "has-no-choices", - noResults: "has-no-results", - notice: "choices__notice", - openState: "is-open", + listDropdown: "choices__list--dropdown", + item: "choices__item", + itemSelectable: "choices__item--selectable", + itemDisabled: "choices__item--disabled", + itemChoice: "choices__item--choice", placeholder: "choices__placeholder", + group: "choices__group", + groupHeading: "choices__heading", + button: "choices__button", + activeState: "is-active", + focusState: "is-focused", + openState: "is-open", + disabledState: "is-disabled", + highlightedState: "is-highlighted", selectedState: "is-selected", + flippedState: "is-flipped", + loadingState: "is-loading", + noResults: "has-no-results", + noChoices: "has-no-choices", }, }); } diff --git a/resources/js/_modules/SidebarToggler.ts b/app/Resources/js/modules/SidebarToggler.ts similarity index 100% rename from resources/js/_modules/SidebarToggler.ts rename to app/Resources/js/modules/SidebarToggler.ts diff --git a/resources/js/_modules/Slugify.ts b/app/Resources/js/modules/Slugify.ts similarity index 100% rename from resources/js/_modules/Slugify.ts rename to app/Resources/js/modules/Slugify.ts diff --git a/resources/js/_modules/ThemePicker.ts b/app/Resources/js/modules/ThemePicker.ts similarity index 82% rename from resources/js/_modules/ThemePicker.ts rename to app/Resources/js/modules/ThemePicker.ts index 850fb0a6..d302e463 100644 --- a/resources/js/_modules/ThemePicker.ts +++ b/app/Resources/js/modules/ThemePicker.ts @@ -14,7 +14,7 @@ const ThemePicker = (): void => { const url: string | undefined = button.dataset.url; if (url) { button.addEventListener("click", () => { - iframeTextArea.value = ``; + iframeTextArea.value = ``; urlTextArea.value = url; iframe.src = url; }); diff --git a/resources/js/_modules/Time.ts b/app/Resources/js/modules/Time.ts similarity index 100% rename from resources/js/_modules/Time.ts rename to app/Resources/js/modules/Time.ts diff --git a/resources/js/_modules/Toggler.ts b/app/Resources/js/modules/Toggler.ts similarity index 100% rename from resources/js/_modules/Toggler.ts rename to app/Resources/js/modules/Toggler.ts diff --git a/resources/js/_modules/Tooltip.ts b/app/Resources/js/modules/Tooltip.ts similarity index 98% rename from resources/js/_modules/Tooltip.ts rename to app/Resources/js/modules/Tooltip.ts index 5ea75754..0d0d2733 100644 --- a/resources/js/_modules/Tooltip.ts +++ b/app/Resources/js/modules/Tooltip.ts @@ -1,7 +1,7 @@ +import { Coords } from "@floating-ui/core"; import { arrow, computePosition, - Coords, flip, offset, Placement, diff --git a/resources/js/_modules/ValidateFileSize.ts b/app/Resources/js/modules/ValidateFileSize.ts similarity index 100% rename from resources/js/_modules/ValidateFileSize.ts rename to app/Resources/js/modules/ValidateFileSize.ts diff --git a/resources/js/_modules/VideoClipBuilder.ts b/app/Resources/js/modules/VideoClipBuilder.ts similarity index 100% rename from resources/js/_modules/VideoClipBuilder.ts rename to app/Resources/js/modules/VideoClipBuilder.ts diff --git a/resources/js/_modules/audio-clipper.ts b/app/Resources/js/modules/audio-clipper.ts similarity index 81% rename from resources/js/_modules/audio-clipper.ts rename to app/Resources/js/modules/audio-clipper.ts index a5521273..18df16e0 100644 --- a/resources/js/_modules/audio-clipper.ts +++ b/app/Resources/js/modules/audio-clipper.ts @@ -4,10 +4,10 @@ import { property, query, queryAll, - queryAssignedElements, + queryAssignedNodes, state, } from "lit/decorators.js"; -import WaveSurfer, { WaveSurferOptions } from "wavesurfer.js"; +import WaveSurfer from "wavesurfer.js"; enum ActionType { StretchLeft, @@ -17,9 +17,7 @@ enum ActionType { interface Action { type: ActionType; - payload?: { - offset: number; - }; + payload?: any; } interface EventElement { @@ -29,14 +27,14 @@ interface EventElement { @customElement("audio-clipper") export class AudioClipper extends LitElement { - @queryAssignedElements({ slot: "audio", flatten: true }) - _audio!: Array; + @queryAssignedNodes("audio", true) + _audio!: NodeListOf; - @queryAssignedElements({ slot: "start_time", flatten: true }) - _startTimeInput!: Array; + @queryAssignedNodes("start_time", true) + _startTimeInput!: NodeListOf; - @queryAssignedElements({ slot: "duration", flatten: true }) - _durationInput!: Array; + @queryAssignedNodes("duration", true) + _durationInput!: NodeListOf; @query(".slider") _sliderNode!: HTMLDivElement; @@ -47,12 +45,9 @@ export class AudioClipper extends LitElement { @query(".slider__segment-content") _segmentContentNode!: HTMLDivElement; - @query(".slider__segment-progress-handle--main") + @query(".slider__segment-progress-handle") _progressNode!: HTMLDivElement; - @query(".slider__segment-progress-handle--ghost") - _progressGhostNode!: HTMLDivElement; - @query(".slider__seeking-placeholder") _seekingNode!: HTMLDivElement; @@ -65,9 +60,6 @@ export class AudioClipper extends LitElement { @queryAll(".slider__segment-handle") _segmentHandleNodes!: NodeListOf; - @property({ type: Number, attribute: "audio-duration" }) - audioDuration = 0; - @property({ type: Number, attribute: "start-time" }) initStartTime = 0; @@ -89,9 +81,6 @@ export class AudioClipper extends LitElement { @property({ attribute: "trim-end-label" }) trimEndLabel = "Trim end"; - @state() - _canInteract = false; - @state() _isPlaying = false; @@ -104,6 +93,9 @@ export class AudioClipper extends LitElement { @state() _action: Action | null = null; + @state() + _audioDuration = 0; + @state() _sliderWidth = 0; @@ -124,15 +116,7 @@ export class AudioClipper extends LitElement { _windowEvents: EventElement[] = [ { - events: ["load"], - onEvent: () => { - this._canInteract = true; - this._sliderWidth = this._sliderNode.clientWidth; - this.setSegmentPosition(); - }, - }, - { - events: ["resize"], + events: ["load", "resize"], onEvent: () => { this._sliderWidth = this._sliderNode.clientWidth; this.setSegmentPosition(); @@ -146,12 +130,9 @@ export class AudioClipper extends LitElement { onEvent: () => { if (this._action !== null) { document.body.style.cursor = ""; - if ( - this._action.type === ActionType.Seek && - this._seekingTime !== null - ) { + if (this._action.type === ActionType.Seek && this._seekingTime) { this._audio[0].currentTime = this._seekingTime; - this._seekingTime = null; + this._seekingTime = 0; } this._action = null; } @@ -160,24 +141,14 @@ export class AudioClipper extends LitElement { { events: ["mousemove"], onEvent: (event: Event) => { - this.updatePosition(event as MouseEvent); + if (this._action !== null) { + this.updatePosition(event as MouseEvent); + } }, }, ]; _audioEvents: EventElement[] = [ - { - events: ["loadedmetadata"], - onEvent: () => { - this.audioDuration = this._audio[0].duration; - }, - }, - { - events: ["waiting"], - onEvent: () => { - this._isBuffering = true; - }, - }, { events: ["play"], onEvent: () => { @@ -205,7 +176,7 @@ export class AudioClipper extends LitElement { ); context.fillStyle = "#04AC64"; - const inc = this._bufferingBarNode.width / this.audioDuration; + const inc = this._bufferingBarNode.width / this._audio[0].duration; for (let i = 0; i < this._audio[0].buffered.length; i++) { const startX = this._audio[0].buffered.start(i) * inc; @@ -221,11 +192,13 @@ export class AudioClipper extends LitElement { { events: ["timeupdate"], onEvent: () => { - this._currentTime = this._audio[0].currentTime; + // TODO: change this? + this._currentTime = parseFloat(this._audio[0].currentTime.toFixed(3)); if (this._currentTime > this._clip.endTime) { this.pause(); this._audio[0].currentTime = this._clip.endTime; } else if (this._currentTime < this._clip.startTime) { + this._isBuffering = true; this._audio[0].currentTime = this._clip.startTime; } else { this._isBuffering = false; @@ -260,21 +233,6 @@ export class AudioClipper extends LitElement { }, ]; - _sliderSegmentEvents: EventElement[] = [ - { - events: ["hover"], - onEvent: (event: Event) => { - const ghostHandle = (event.target as HTMLDivElement).querySelector( - ".segment" - ) as HTMLDivElement; - if (ghostHandle) { - ghostHandle.style.opacity = "1"; - ghostHandle.style.transform = "translateX(50)"; - } - }, - }, - ]; - connectedCallback(): void { super.connectedCallback(); @@ -286,9 +244,7 @@ export class AudioClipper extends LitElement { } protected firstUpdated(): void { - this._sliderWidth = this._sliderNode.clientWidth; - this.setSegmentPosition(); - + this._audioDuration = this._audio[0].duration; this._audio[0].volume = this._volume; this._startTimeInput[0].hidden = true; this._durationInput[0].hidden = true; @@ -299,10 +255,11 @@ export class AudioClipper extends LitElement { interact: false, barWidth: 2, barHeight: 1, + // barGap: 4, responsive: true, waveColor: "hsl(0 5% 85%)", cursorColor: "transparent", - } as WaveSurferOptions); + }); this._wavesurfer.load(this._audio[0].src); this.addEventListeners(); @@ -381,11 +338,11 @@ export class AudioClipper extends LitElement { } private getPositionFromSeconds(seconds: number) { - return (seconds * this._sliderWidth) / this.audioDuration; + return (seconds * this._sliderWidth) / this._audioDuration; } private getSecondsFromPosition(position: number) { - return (this.audioDuration * position) / this._sliderWidth; + return (this._audioDuration * position) / this._sliderWidth; } protected updated( @@ -448,14 +405,14 @@ export class AudioClipper extends LitElement { } case ActionType.StretchRight: { let endTime; - if (seconds < this.audioDuration) { + if (seconds < this._audioDuration) { if (seconds < this._clip.startTime + this.minDuration) { endTime = this._clip.startTime + this.minDuration; } else { endTime = seconds; } } else { - endTime = this.audioDuration; + endTime = this._audioDuration; } this._clip = { @@ -502,7 +459,6 @@ export class AudioClipper extends LitElement { const seekingTimePercentage = (seekingTimeSegmentPosition / this._segmentContentNode.clientWidth) * this._segmentContentNode.clientWidth; - this._progressNode.style.transform = `translateX(${seekingTimeSegmentPosition}px)`; this._seekingNode.style.transform = `scaleX(${seekingTimePercentage})`; } @@ -630,10 +586,6 @@ export class AudioClipper extends LitElement { border-top: 10px solid #3b82f6; } - .slider__segment-progress-handle--ghost { - opacity: 0.5; - } - .slider__segment .slider__segment-handle { position: absolute; width: 1rem; @@ -685,9 +637,7 @@ export class AudioClipper extends LitElement { padding: 0.5rem 0.5rem 0.25rem 0.5rem; justify-content: space-between; background-color: hsl(var(--color-background-elevated)); - box-shadow: - 0 1px 3px 0 rgb(0 0 0 / 0.1), - 0 1px 2px -1px rgb(0 0 0 / 0.1); + box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); border-radius: 0 0 0.75rem 0.75rem; flex-wrap: wrap; gap: 0.5rem; @@ -720,9 +670,7 @@ export class AudioClipper extends LitElement { border-radius: 9999px; border: none; padding: 0.25rem 0.5rem; - box-shadow: - 0 1px 3px 0 rgb(0 0 0 / 0.1), - 0 1px 2px -1px rgb(0 0 0 / 0.1); + box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); } .toolbar button:hover { @@ -736,16 +684,11 @@ export class AudioClipper extends LitElement { var(--tw-ring-offset-width) var(--tw-ring-offset-color); --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: - var(--tw-ring-offset-shadow), - var(--tw-ring-shadow), + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), 0 0 rgba(0, 0, 0, 0); - box-shadow: - var(--tw-ring-offset-shadow), - var(--tw-ring-shadow), + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), 0 0 rgba(0, 0, 0, 0); - box-shadow: - var(--tw-ring-offset-shadow), var(--tw-ring-shadow), + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 rgba(0, 0, 0, 0)); --tw-ring-offset-width: 2px; --tw-ring-opacity: 1; @@ -755,27 +698,10 @@ export class AudioClipper extends LitElement { .toolbar__trim-controls button { font-weight: 600; - font-family: - Inter, - ui-sans-serif, - system-ui, - -apple-system, - Segoe UI, - Roboto, - Ubuntu, - Cantarell, - Noto Sans, - sans-serif, - BlinkMacSystemFont, - "Segoe UI", - Roboto, - "Helvetica Neue", - Arial, - "Noto Sans", - sans-serif, - "Apple Color Emoji", - "Segoe UI Emoji", - "Segoe UI Symbol", + font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, + Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, + "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } @@ -816,19 +742,14 @@ export class AudioClipper extends LitElement { -
+
-
- ${this._isBuffering || !this._canInteract + ${this._isBuffering ? html` ` : this._isPlaying - ? html` - - - - - ` - : html` + ? html` + - - `} + + + ` + : html` + + + `}
; + @queryAssignedNodes("write", true) + _write!: NodeListOf; - @queryAssignedElements({ slot: "preview", flatten: true }) - _preview!: Array; + @queryAssignedNodes("preview", true) + _preview!: NodeListOf; connectedCallback(): void { super.connectedCallback(); diff --git a/resources/js/_modules/permalink-edit.ts b/app/Resources/js/modules/permalink-edit.ts similarity index 90% rename from resources/js/_modules/permalink-edit.ts rename to app/Resources/js/modules/permalink-edit.ts index c0ea0224..fdda43cf 100644 --- a/resources/js/_modules/permalink-edit.ts +++ b/app/Resources/js/modules/permalink-edit.ts @@ -1,24 +1,23 @@ import "@github/clipboard-copy-element"; -import ClipboardCopyElement from "@github/clipboard-copy-element"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, query, - queryAssignedElements, + queryAssignedNodes, state, } from "lit/decorators.js"; @customElement("permalink-edit") export class PermalinkEdit extends LitElement { - @queryAssignedElements({ slot: "domain", flatten: true }) + @queryAssignedNodes("domain", true) _domain!: NodeListOf; - @queryAssignedElements({ slot: "slug-input", flatten: true }) + @queryAssignedNodes("slug-input", true) _slugInput!: NodeListOf; @query("clipboard-copy") - _clipboardCopy!: ClipboardCopyElement; + _clipboardCopy!: any; @property({ attribute: "edit-label" }) editLabel = "Edit"; @@ -26,9 +25,6 @@ export class PermalinkEdit extends LitElement { @property({ attribute: "copy-label" }) copyLabel = "Copy"; - @property({ attribute: "permalink-base" }) - permalinkBase = ""; - @state() isEditable = false; @@ -72,10 +68,6 @@ export class PermalinkEdit extends LitElement { } firstUpdated(): void { - console.log(this._slugInput); - - this.permalinkBase += this.permalinkBase.endsWith("/") ? "" : "/"; - // set permalink value this.setPermalink(); @@ -138,7 +130,7 @@ export class PermalinkEdit extends LitElement { } setPermalink(): void { - this.permalink = this.permalinkBase + this._slugInput[0].value; + this.permalink = this._domain[0].innerHTML + this._slugInput[0].value; } static styles = css` @@ -147,7 +139,7 @@ export class PermalinkEdit extends LitElement { border-color: transparent !important; padding-left: 0 !important; margin-left: -0.25rem !important; - font-weight: 600 !important; + font-weight: 600; } ::slotted([slot="domain"]) { diff --git a/resources/js/_modules/play-episode-button.ts b/app/Resources/js/modules/play-episode-button.ts similarity index 97% rename from resources/js/_modules/play-episode-button.ts rename to app/Resources/js/modules/play-episode-button.ts index 101868ad..3eee7af5 100644 --- a/resources/js/_modules/play-episode-button.ts +++ b/app/Resources/js/modules/play-episode-button.ts @@ -27,15 +27,15 @@ export class PlayEpisodeButton extends LitElement { @property() playingLabel!: string; - @property({ attribute: false }) + @property() + isPlaying!: boolean; + + @property() _castopodAudioPlayer!: HTMLDivElement; - @property({ attribute: false }) + @property() _audio!: HTMLAudioElement; - @state() - isPlaying!: boolean; - @state() _playbackSpeed = 1; @@ -206,8 +206,7 @@ export class PlayEpisodeButton extends LitElement { button:focus { outline: none; - box-shadow: - 0 0 0 2px hsl(var(--color-background-base)), + box-shadow: 0 0 0 2px hsl(var(--color-background-base)), 0 0 0 4px hsl(var(--color-accent-base)); } diff --git a/resources/js/_modules/play-soundbite.ts b/app/Resources/js/modules/play-soundbite.ts similarity index 80% rename from resources/js/_modules/play-soundbite.ts rename to app/Resources/js/modules/play-soundbite.ts index 098a73a9..26f24086 100644 --- a/resources/js/_modules/play-soundbite.ts +++ b/app/Resources/js/modules/play-soundbite.ts @@ -44,6 +44,11 @@ export class PlaySoundbite extends LitElement { name: "timeupdate", onEvent: () => { if (this._audio) { + console.log( + this._audio.currentTime, + this.startTime, + this.startTime + this.duration + ); if (this._audio.currentTime < this.startTime) { this._isLoading = true; this._audio.currentTime = this.startTime; @@ -104,8 +109,7 @@ export class PlaySoundbite extends LitElement { button:focus { outline: none; - box-shadow: - 0 0 0 2px hsl(var(--color-background-base)), + box-shadow: 0 0 0 2px hsl(var(--color-background-base)), 0 0 0 4px hsl(var(--color-accent-base)); } @@ -164,31 +168,31 @@ export class PlaySoundbite extends LitElement { > ` : this._isPlaying - ? html` - - - - - ` - : html` + ? html` + - `} + + ` + : html` + + + `} `; } } diff --git a/resources/js/_modules/video-clip-previewer.ts b/app/Resources/js/modules/video-clip-previewer.ts similarity index 94% rename from resources/js/_modules/video-clip-previewer.ts rename to app/Resources/js/modules/video-clip-previewer.ts index 34e68335..a28c2f2a 100644 --- a/resources/js/_modules/video-clip-previewer.ts +++ b/app/Resources/js/modules/video-clip-previewer.ts @@ -2,7 +2,8 @@ import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, - queryAssignedElements, + queryAssignedNodes, + state, } from "lit/decorators.js"; import { styleMap } from "lit/directives/style-map.js"; @@ -20,7 +21,7 @@ const formatMap = { @customElement("video-clip-previewer") export class VideoClipPreviewer extends LitElement { - @queryAssignedElements({ slot: "preview_image", flatten: true }) + @queryAssignedNodes("preview_image", true) _image!: NodeListOf; @property() @@ -35,7 +36,7 @@ export class VideoClipPreviewer extends LitElement { @property({ type: Number }) duration!: number; - @property({ attribute: false }) + @state() _previewImage!: HTMLImageElement; protected firstUpdated(): void { @@ -110,8 +111,7 @@ export class VideoClipPreviewer extends LitElement { ::slotted(img) { border-radius: 0.5rem; - box-shadow: - 0 4px 6px -1px rgb(0 0 0 / 0.1), + box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); } `; diff --git a/app/Resources/js/modules/xml-editor.ts b/app/Resources/js/modules/xml-editor.ts new file mode 100644 index 00000000..e32288e3 --- /dev/null +++ b/app/Resources/js/modules/xml-editor.ts @@ -0,0 +1,127 @@ +import { indentWithTab } from "@codemirror/commands"; +import { xml } from "@codemirror/lang-xml"; +import { + defaultHighlightStyle, + syntaxHighlighting, +} from "@codemirror/language"; +import { Compartment, EditorState } from "@codemirror/state"; +import { keymap } from "@codemirror/view"; +import { basicSetup, EditorView } from "codemirror"; +import { css, html, LitElement, TemplateResult } from "lit"; +import { customElement, queryAssignedNodes, state } from "lit/decorators.js"; +import prettifyXML from "xml-formatter"; + +const language = new Compartment(); + +@customElement("xml-editor") +export class XMLEditor extends LitElement { + @queryAssignedNodes({ slot: "textarea" }) + _textarea!: NodeListOf; + + @state() + editorState!: EditorState; + + @state() + editorView!: EditorView; + + firstUpdated(): void { + const minHeightEditor = EditorView.theme({ + ".cm-content, .cm-gutter": { + minHeight: this._textarea[0].clientHeight + "px", + }, + }); + + let editorContents = ""; + if (this._textarea[0].value) { + try { + editorContents = prettifyXML(this._textarea[0].value, { + indentation: " ", + }); + } catch (e) { + // xml doesn't have a root node + editorContents = prettifyXML( + "" + this._textarea[0].value + "", + { + indentation: " ", + } + ); + // remove root, unnecessary lines and indents + editorContents = editorContents + .replace(/^/, "") + .replace(/<\/root>$/, "") + .replace(/^\s*[\r\n]/gm, "") + .replace(/[\r\n] {2}/gm, "\r\n") + .trim(); + } + } + + this.editorState = EditorState.create({ + doc: editorContents, + extensions: [ + basicSetup, + keymap.of([indentWithTab]), + language.of(xml()), + minHeightEditor, + syntaxHighlighting(defaultHighlightStyle), + ], + }); + + this.editorView = new EditorView({ + state: this.editorState, + root: this.shadowRoot as ShadowRoot, + parent: this.shadowRoot as ShadowRoot, + }); + + this._textarea[0].hidden = true; + if (this._textarea[0].form) { + this._textarea[0].form.addEventListener("submit", () => { + this._textarea[0].value = this.editorView.state.doc.toString(); + }); + } + } + + disconnectedCallback(): void { + if (this._textarea[0].form) { + this._textarea[0].form.removeEventListener("submit", () => { + this._textarea[0].value = this.editorView.state.doc.toString(); + }); + } + } + + static styles = css` + .cm-editor { + border-radius: 0.5rem; + overflow: hidden; + border: 3px solid hsl(var(--color-border-contrast)); + background-color: hsl(var(--color-background-elevated)); + } + .cm-editor.cm-focused { + outline: 2px solid transparent; + box-shadow: 0 0 0 2px hsl(var(--color-background-elevated)), + 0 0 0 calc(4px) hsl(var(--color-accent-base)); + } + .cm-gutters { + background-color: hsl(var(--color-background-elevated)) !important; + } + + .cm-activeLine { + background-color: hsl(var(--color-background-highlight)) !important; + } + + .cm-activeLineGutter { + background-color: hsl(var(--color-background-highlight)) !important; + } + + .ͼ4 .cm-line { + caret-color: hsl(var(--color-text-base)) !important; + } + + .ͼ1 .cm-cursor { + border: none; + } + `; + + render(): TemplateResult<1> { + return html``; + } +} diff --git a/app/Resources/js/podcast.ts b/app/Resources/js/podcast.ts new file mode 100644 index 00000000..e7b0df73 --- /dev/null +++ b/app/Resources/js/podcast.ts @@ -0,0 +1,10 @@ +import "@github/time-elements"; +import SidebarToggler from "./modules/SidebarToggler"; +import Time from "./modules/Time"; +import Toggler from "./modules/Toggler"; +import Tooltip from "./modules/Tooltip"; + +Time(); +Toggler(); +Tooltip(); +SidebarToggler(); diff --git a/resources/js/typings.d.ts b/app/Resources/js/typings.d.ts similarity index 100% rename from resources/js/typings.d.ts rename to app/Resources/js/typings.d.ts diff --git a/resources/js/vite-env.d.ts b/app/Resources/js/vite-env.d.ts similarity index 100% rename from resources/js/vite-env.d.ts rename to app/Resources/js/vite-env.d.ts diff --git a/resources/styles/_modules/breadcrumb.css b/app/Resources/styles/breadcrumb.css similarity index 89% rename from resources/styles/_modules/breadcrumb.css rename to app/Resources/styles/breadcrumb.css index b1ef8a30..f0c31905 100644 --- a/resources/styles/_modules/breadcrumb.css +++ b/app/Resources/styles/breadcrumb.css @@ -4,7 +4,6 @@ .breadcrumb-item + .breadcrumb-item::before { @apply inline-block px-1; - color: hsl(var(--color-text-muted)); content: "/"; } @@ -15,6 +14,10 @@ &:hover { @apply underline; } + + &:focus { + @apply ring-accent; + } } .breadcrumb-item.active { diff --git a/resources/styles/_modules/choices.css b/app/Resources/styles/choices.css similarity index 83% rename from resources/styles/_modules/choices.css rename to app/Resources/styles/choices.css index a83a52f1..9e50896b 100644 --- a/resources/styles/_modules/choices.css +++ b/app/Resources/styles/choices.css @@ -1,6 +1,6 @@ -/* =============================== +/*=============================== = Choices = -=============================== */ +===============================*/ @layer components { .choices { @@ -9,6 +9,10 @@ font-size: 16px; } + .choices:focus { + outline: none; + } + .choices:last-child { margin-bottom: 0; } @@ -17,6 +21,8 @@ .choices.is-disabled .choices__input { opacity: 0.5; cursor: not-allowed; + -webkit-user-select: none; + -ms-user-select: none; user-select: none; } @@ -25,16 +31,17 @@ } .choices [hidden] { - position: absolute; - opacity: 0; - z-index: -9999; - pointer-events: none; + display: none !important; } .choices[data-type*="select-one"] { cursor: pointer; } + .choices[data-type*="select-one"] .choices__inner { + padding-bottom: 7.5px; + } + .choices[data-type*="select-one"] .choices__input { display: block; width: 100%; @@ -64,7 +71,7 @@ } .choices[data-type*="select-one"] .choices__button:focus { - box-shadow: 0 0 0 2px #00bcd4; + box-shadow: 0px 0px 0px 2px #00bcd4; } .choices[data-type*="select-one"] @@ -73,12 +80,13 @@ display: none; } - .choices[data-type*="select-one"]::after { + .choices[data-type*="select-one"]:after { content: ""; height: 0; width: 0; border-style: solid; - border-color: hsl(var(--color-text-muted)) transparent transparent; + border-color: hsl(var(--color-text-muted)) transparent transparent + transparent; border-width: 5px; position: absolute; right: 11.5px; @@ -87,12 +95,13 @@ pointer-events: none; } - .choices[data-type*="select-one"].is-open::after { - border-color: transparent transparent hsl(var(--color-text-muted)); + .choices[data-type*="select-one"].is-open:after { + border-color: transparent transparent hsl(var(--color-text-muted)) + transparent; margin-top: -7.5px; } - .choices[data-type*="select-one"][dir="rtl"]::after { + .choices[data-type*="select-one"][dir="rtl"]:after { left: 11.5px; right: auto; } @@ -115,7 +124,7 @@ display: inline-block; margin-left: 8px; padding-left: 16px; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%2300574B'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z'/%3E%3C/svg%3E"); background-size: 16px; width: 8px; line-height: 1; @@ -131,7 +140,7 @@ } .choices__inner { - @apply px-3 py-2 rounded-lg border-contrast bg-elevated border-3 transition; + @apply p-2 rounded-lg border-contrast bg-elevated border-3; box-shadow: 2px 2px 0 hsl(var(--color-border-contrast)); display: inline-block; @@ -142,9 +151,13 @@ overflow: hidden; } + .choices[data-type*="select-multiple"] .choices__inner { + @apply pb-1; + } + .is-focused .choices__inner, .is-open .choices__inner { - @apply ring-accent; + @apply ring-accent ring-inset; } .is-open .choices__inner { @@ -175,11 +188,11 @@ } .choices__list--multiple { - @apply inline-flex gap-2 mr-2 items-center; + display: inline; } .choices__list--multiple .choices__item { - @apply inline-block font-semibold px-1 py-0.5 text-sm align-middle rounded text-accent-hover bg-base border-accent-base ring-2 ring-accent-base; + @apply inline-block px-2 py-1 mb-1 mr-1 text-sm align-middle rounded text-accent-contrast bg-accent-base; word-break: break-all; box-sizing: border-box; @@ -195,18 +208,17 @@ } .choices__list--multiple .choices__item.is-highlighted { - @apply bg-subtle; + @apply bg-accent-base; } .is-disabled .choices__list--multiple .choices__item { - background-color: #aaa; + background-color: #aaaaaa; border: 1px solid #919191; } .choices__list--dropdown { @apply z-50 border-2 shadow-lg border-contrast; - - display: none; + visibility: hidden; position: absolute; width: 100%; background-color: hsl(var(--color-background-elevated)); @@ -214,10 +226,11 @@ margin-top: -1px; overflow: hidden; word-break: break-all; + will-change: visibility; } .choices__list--dropdown.is-active { - display: block; + visibility: visible; } .is-open .choices__list--dropdown { @@ -226,7 +239,6 @@ .is-flipped .choices__list--dropdown { @apply border-b-0 rounded-t-lg rounded-b-none border-t-3; - top: auto; bottom: 100%; margin-top: 0; @@ -242,8 +254,6 @@ } .choices__list--dropdown .choices__item { - @apply break-normal; - position: relative; padding: 10px; font-size: 14px; @@ -253,12 +263,11 @@ text-align: right; } - @media (width >= 640px) { + @media (min-width: 640px) { .choices__list--dropdown .choices__item--selectable { padding-right: 100px; } - - .choices__list--dropdown .choices__item--selectable::after { + .choices__list--dropdown .choices__item--selectable:after { content: attr(data-select-text); font-size: 12px; opacity: 0; @@ -267,14 +276,12 @@ top: 50%; transform: translateY(-50%); } - [dir="rtl"] .choices__list--dropdown .choices__item--selectable { text-align: right; padding-left: 100px; padding-right: 10px; } - - [dir="rtl"] .choices__list--dropdown .choices__item--selectable::after { + [dir="rtl"] .choices__list--dropdown .choices__item--selectable:after { right: auto; left: 10px; } @@ -284,7 +291,7 @@ background-color: hsl(var(--color-background-highlight)); } - .choices__list--dropdown .choices__item--selectable.is-highlighted::after { + .choices__list--dropdown .choices__item--selectable.is-highlighted:after { opacity: 0.5; } @@ -298,6 +305,8 @@ .choices__item--disabled { cursor: not-allowed; + -webkit-user-select: none; + -ms-user-select: none; user-select: none; opacity: 0.5; } @@ -312,6 +321,8 @@ .choices__button { text-indent: -9999px; + -webkit-appearance: none; + -moz-appearance: none; appearance: none; border: 0; background-color: transparent; @@ -320,8 +331,12 @@ cursor: pointer; } + .choices__button:focus { + outline: none; + } + .choices__input { - @apply align-middle bg-elevated; + @apply mb-1 align-middle bg-elevated; display: inline-block; font-size: 14px; @@ -334,7 +349,6 @@ .choices__input:focus { @apply outline-none; - box-shadow: none; } @@ -346,10 +360,6 @@ .choices__placeholder { opacity: 0.5; } - - .choices__description { - @apply text-xs block text-skin-muted break-normal; - } } -/* ===== End of Choices ====== */ +/*===== End of Choices ======*/ diff --git a/resources/styles/_modules/colorRadioBtn.css b/app/Resources/styles/colorRadioBtn.css similarity index 99% rename from resources/styles/_modules/colorRadioBtn.css rename to app/Resources/styles/colorRadioBtn.css index a6581249..73a39d5a 100644 --- a/resources/styles/_modules/colorRadioBtn.css +++ b/app/Resources/styles/colorRadioBtn.css @@ -20,7 +20,6 @@ & + label { @apply inline-block w-16 h-16 text-sm font-semibold rounded-full cursor-pointer border-contrast bg-accent-base text-accent-contrast border-3; - color: hsl(var(--color-text-muted)); } } diff --git a/resources/styles/_modules/colors.css b/app/Resources/styles/colors.css similarity index 93% rename from resources/styles/_modules/colors.css rename to app/Resources/styles/colors.css index d59e79ba..27b5a5b4 100644 --- a/resources/styles/_modules/colors.css +++ b/app/Resources/styles/colors.css @@ -4,18 +4,21 @@ --color-accent-hover: 172 100% 17%; --color-accent-muted: 131 100% 12%; --color-accent-contrast: 0 0% 100%; + --color-heading-foreground: 172 100% 17%; --color-heading-background: 111 64% 94%; + --color-background-elevated: 0 0% 100%; --color-background-base: 173 44% 96%; --color-background-navigation: 172 100% 17%; - --color-background-navigation-active: 131 100% 12%; --color-background-header: 172 100% 17%; --color-background-highlight: 111 64% 94%; --color-background-backdrop: 0 0% 50%; + --color-border-subtle: 111 42% 86%; --color-border-contrast: 0 0% 0%; --color-border-navigation: 131 100% 12%; + --color-text-base: 158 8% 3%; --color-text-muted: 172 8% 38%; } diff --git a/app/Resources/styles/custom.css b/app/Resources/styles/custom.css new file mode 100644 index 00000000..8cfb46bc --- /dev/null +++ b/app/Resources/styles/custom.css @@ -0,0 +1,59 @@ +@layer components { + .post-content { + & a { + @apply text-sm font-semibold text-accent-base hover:text-accent-hover; + } + } + + .ring-accent { + @apply outline-none ring-2 ring-offset-2; + /* FIXME: why doesn't ring-accent-base work? */ + --tw-ring-opacity: 1; + --tw-ring-color: hsl(var(--color-accent-base) / var(--tw-ring-opacity)); + --tw-ring-offset-color: hsl(var(--color-background-base)); + } + + .rounded-conditional-b-xl { + border-bottom-right-radius: max( + 0px, + min(0.75rem, calc((100vw - 0.75rem - 100%) * 9999)) + ); + border-bottom-left-radius: max( + 0px, + min(0.75rem, calc((100vw - 0.75rem - 100%) * 9999)) + ); + } + + .rounded-conditional-2xl { + border-radius: max(0px, min(1rem, calc((100vw - 1rem - 100%) * 9999))); + } + + .rounded-conditional-full { + border-radius: max(0px, min(9999px, calc((100vw - 1rem - 100%) * 9999))); + } + + .backdrop-gradient { + background-image: linear-gradient( + 180deg, + hsla(0 0% 35.29% / 0) 0%, + hsla(0 0% 34.53% / 0.034375) 16.36%, + hsla(0 0% 32.42% / 0.125) 33.34%, + hsla(0 0% 29.18% / 0.253125) 50.1%, + hsla(0 0% 24.96% / 0.4) 65.75%, + hsla(0 0% 19.85% / 0.546875) 79.43%, + hsla(0 0% 13.95% / 0.675) 90.28%, + hsla(0 0% 7.32% / 0.765625) 97.43%, + hsla(0 0% 0% / 0.8) 100% + ); + } + + .bg-stripes-gray { + background-image: repeating-linear-gradient( + -45deg, + #f3f4f6, + #f3f4f6 10px, + #e5e7eb 10px, + #e5e7eb 20px + ); + } +} diff --git a/resources/styles/_modules/dropdown.css b/app/Resources/styles/dropdown.css similarity index 99% rename from resources/styles/_modules/dropdown.css rename to app/Resources/styles/dropdown.css index e501d4e4..850f8d35 100644 --- a/resources/styles/_modules/dropdown.css +++ b/app/Resources/styles/dropdown.css @@ -2,7 +2,6 @@ [data-dropdown="menu"] { @apply absolute z-50; } - [data-dropdown="menu"]:not([data-show]) { @apply hidden; } diff --git a/resources/styles/_modules/fonts.css b/app/Resources/styles/fonts.css similarity index 63% rename from resources/styles/_modules/fonts.css rename to app/Resources/styles/fonts.css index f2d9aa00..cee3974e 100644 --- a/resources/styles/_modules/fonts.css +++ b/app/Resources/styles/fonts.css @@ -5,7 +5,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url("/assets/fonts/kumbh-sans-regular.woff2") format("woff2"); + src: url("/fonts/kumbh-sans-regular.woff2") format("woff2"); } /* kumbh-sans-700 */ @@ -14,25 +14,25 @@ font-style: normal; font-weight: 700; font-display: swap; - src: url("/assets/fonts/kumbh-sans-700.woff2") format("woff2"); + src: url("/fonts/kumbh-sans-700.woff2") format("woff2"); } /* inter-regular */ @font-face { - font-family: Inter; + font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap; - src: url("/assets/fonts/inter-regular.woff2") format("woff2"); + src: url("/fonts/inter-regular.woff2") format("woff2"); } /* inter-600 */ @font-face { - font-family: Inter; + font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap; - src: url("/assets/fonts/inter-600.woff2") format("woff2"); + src: url("/fonts/inter-600.woff2") format("woff2"); } /* noto-sans-mono-regular */ @@ -41,6 +41,6 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url("/assets/fonts/noto-sans-mono-regular.woff2") format("woff2"); + src: url("/fonts/noto-sans-mono-regular.woff2") format("woff2"); } } diff --git a/resources/styles/_modules/formInputTabs.css b/app/Resources/styles/formInputTabs.css similarity index 99% rename from resources/styles/_modules/formInputTabs.css rename to app/Resources/styles/formInputTabs.css index 4c5f21e5..4e71aa16 100644 --- a/resources/styles/_modules/formInputTabs.css +++ b/app/Resources/styles/formInputTabs.css @@ -30,7 +30,6 @@ .form-input-tabs > input:checked + label::after { @apply absolute inset-x-0 bottom-0 w-full mx-auto bg-accent-base; - content: ""; height: 0.2rem; } diff --git a/app/Resources/styles/index.css b/app/Resources/styles/index.css new file mode 100644 index 00000000..3af00d80 --- /dev/null +++ b/app/Resources/styles/index.css @@ -0,0 +1,15 @@ +@import "./tailwind.css"; +@import "./custom.css"; +@import "./fonts.css"; +@import "./colors.css"; +@import "./breadcrumb.css"; +@import "./dropdown.css"; +@import "./choices.css"; +@import "./radioBtn.css"; +@import "./colorRadioBtn.css"; +@import "./switch.css"; +@import "./radioToggler.css"; +@import "./formInputTabs.css"; +@import "./stickyHeader.css"; +@import "./readMore.css"; +@import "./seeMore.css"; diff --git a/resources/styles/_modules/inputRange.css b/app/Resources/styles/inputRange.css similarity index 95% rename from resources/styles/_modules/inputRange.css rename to app/Resources/styles/inputRange.css index b474963a..053df137 100644 --- a/resources/styles/_modules/inputRange.css +++ b/app/Resources/styles/inputRange.css @@ -4,11 +4,8 @@ position: relative; width: 12.5em; height: 5.25em; - font: - 1em/1 arial, - sans-serif; + font: 1em/1 arial, sans-serif; } - [type="range"] { flex: 1; margin: 0; @@ -17,12 +14,10 @@ background: transparent; font: inherit; } - [type="range"], [type="range"]::-webkit-slider-thumb { - appearance: none; + -webkit-appearance: none; } - [type="range"]::-webkit-slider-runnable-track { box-sizing: border-box; border: none; @@ -30,7 +25,6 @@ height: 0.25em; background: #ccc; } - [type="range"]::-moz-range-track { box-sizing: border-box; border: none; @@ -38,7 +32,6 @@ height: 0.25em; background: #ccc; } - [type="range"]::-ms-track { box-sizing: border-box; border: none; @@ -46,7 +39,6 @@ height: 0.25em; background: #ccc; } - [type="range"]::-webkit-slider-thumb { margin-top: -0.625em; box-sizing: border-box; @@ -56,7 +48,6 @@ border-radius: 50%; background: #f90; } - [type="range"]::-moz-range-thumb { box-sizing: border-box; border: none; @@ -65,7 +56,6 @@ border-radius: 50%; background: #f90; } - [type="range"]::-ms-thumb { margin-top: 0; box-sizing: border-box; @@ -75,15 +65,12 @@ border-radius: 50%; background: #f90; } - [type="range"]::-ms-tooltip { display: none; } - [type="range"] ~ output { display: none; } - .js [type="range"] ~ output { display: block; position: absolute; diff --git a/app/Resources/styles/radioBtn.css b/app/Resources/styles/radioBtn.css new file mode 100644 index 00000000..5a044cd9 --- /dev/null +++ b/app/Resources/styles/radioBtn.css @@ -0,0 +1,22 @@ +@layer components { + .form-radio-btn { + @apply absolute mt-3 ml-3 border-contrast border-3 text-accent-base; + + &:focus { + @apply ring-accent; + } + + &:checked { + @apply ring-2 ring-contrast; + + & + label { + @apply text-accent-contrast bg-accent-base; + } + } + + & + label { + @apply inline-flex items-center py-2 pl-8 pr-2 text-sm font-semibold rounded-lg cursor-pointer border-contrast bg-elevated border-3; + color: hsl(var(--color-text-muted)); + } + } +} diff --git a/resources/styles/_modules/radioToggler.css b/app/Resources/styles/radioToggler.css similarity index 100% rename from resources/styles/_modules/radioToggler.css rename to app/Resources/styles/radioToggler.css diff --git a/resources/styles/_modules/readMore.css b/app/Resources/styles/readMore.css similarity index 94% rename from resources/styles/_modules/readMore.css rename to app/Resources/styles/readMore.css index 38f40e02..d83e0bee 100644 --- a/resources/styles/_modules/readMore.css +++ b/app/Resources/styles/readMore.css @@ -6,14 +6,12 @@ Read more component (basic unstyled component) @layer components { .read-more { @apply flex flex-col items-start; - /* You can update this variable directly in the html with the style attribute: style="--line-clamp: 3" */ --line-clamp: 3; } .read-more__text { @apply overflow-hidden; - display: -webkit-box; -webkit-line-clamp: var(--line-clamp); -webkit-box-orient: vertical; @@ -21,8 +19,8 @@ Read more component (basic unstyled component) .read-more__checkbox { @apply absolute overflow-hidden whitespace-nowrap; - - clip-path: inset(50%); + clip: rect(0 0 0 0); + clip-path: inset(100%); height: 1px; width: 1px; } @@ -33,7 +31,7 @@ Read more component (basic unstyled component) /* Don't forget focus and hover styles for accessibility! */ .read-more__checkbox:focus ~ .read-more__label { - @apply ring-accent; + @apply ring; } .read-more__checkbox:hover ~ .read-more__label { @@ -50,7 +48,6 @@ Read more component (basic unstyled component) .read-more__checkbox:checked ~ .read-more__text { --line-clamp: none; - -webkit-line-clamp: var(--line-clamp); } } diff --git a/resources/styles/_modules/seeMore.css b/app/Resources/styles/seeMore.css similarity index 95% rename from resources/styles/_modules/seeMore.css rename to app/Resources/styles/seeMore.css index 6a191f57..4166b147 100644 --- a/resources/styles/_modules/seeMore.css +++ b/app/Resources/styles/seeMore.css @@ -5,13 +5,11 @@ .see-more__content { @apply relative overflow-hidden; - height: var(--content-height); } .see-more_content-fade { @apply absolute bottom-0 left-0 w-full h-full pointer-events-none; - background-image: linear-gradient( to bottom, transparent 70%, @@ -21,8 +19,8 @@ .see-more__checkbox { @apply absolute overflow-hidden whitespace-nowrap; - - clip-path: inset(50%); + clip: rect(0 0 0 0); + clip-path: inset(100%); height: 1px; width: 1px; } diff --git a/resources/styles/_modules/stickyHeader.css b/app/Resources/styles/stickyHeader.css similarity index 100% rename from resources/styles/_modules/stickyHeader.css rename to app/Resources/styles/stickyHeader.css diff --git a/resources/styles/_modules/switch.css b/app/Resources/styles/switch.css similarity index 64% rename from resources/styles/_modules/switch.css rename to app/Resources/styles/switch.css index 3065dc40..e12f3bca 100644 --- a/resources/styles/_modules/switch.css +++ b/app/Resources/styles/switch.css @@ -11,13 +11,12 @@ } &:checked + .form-switch-slider::before { - @apply transform translate-x-6; + @apply transform translate-x-8; } &:checked + .form-switch-slider::after { - @apply transform translate-x-0 left-1.5; - - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='m10 15.172 9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z'/%3E%3C/svg%3E%0A"); + @apply transform translate-x-0 left-2; + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='m10 15.172 9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z'/%3E%3C/svg%3E%0A"); } &:checked + .form-switch-slider.form-switch-slider--small::before { @@ -30,7 +29,7 @@ } .form-switch-slider { - @apply relative inset-0 flex-shrink-0 h-8 transition duration-200 rounded-full cursor-pointer w-14 bg-highlight border-contrast border-3; + @apply relative inset-0 flex-shrink-0 w-16 h-8 transition duration-200 rounded-full cursor-pointer bg-highlight border-contrast border-3; &.form-switch-slider--small { @apply w-12 h-6; @@ -41,7 +40,6 @@ &::after { @apply translate-x-5; - left: 0; top: -1px; } @@ -49,18 +47,16 @@ &::before { @apply absolute z-10 w-6 h-6 transition duration-200 rounded-full shadow bg-elevated ring-1 ring-black ring-opacity-5; - content: ""; left: 1px; bottom: 1px; } &::after { - @apply absolute w-4 h-4 transition duration-150 transform top-1; + @apply absolute w-5 h-5 transition duration-150 transform translate-x-5; - --tw-translate-x: 1.125rem; - - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='m12 10.586 4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z'/%3E%3C/svg%3E%0A"); + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='m12 10.586 4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z'/%3E%3C/svg%3E%0A"); + top: 3px; left: 10px; } } diff --git a/resources/styles/_modules/tailwind.css b/app/Resources/styles/tailwind.css similarity index 100% rename from resources/styles/_modules/tailwind.css rename to app/Resources/styles/tailwind.css diff --git a/app/Validation/FileRules.php b/app/Validation/FileRules.php index 2a149d46..49f5fb38 100644 --- a/app/Validation/FileRules.php +++ b/app/Validation/FileRules.php @@ -11,15 +11,13 @@ declare(strict_types=1); namespace App\Validation; use CodeIgniter\Validation\FileRules as ValidationFileRules; -use Override; class FileRules extends ValidationFileRules { /** * Checks an uploaded file to verify that the dimensions are within a specified allowable dimension. */ - #[Override] - public function min_dims(?string $blank = null, string $params = ''): bool + public function min_dims(string $blank = null, string $params = ''): bool { // Grab the file name off the top of the $params // after we split it. @@ -61,7 +59,7 @@ class FileRules extends ValidationFileRules /** * Checks an uploaded image to verify that the ratio corresponds to the params */ - public function is_image_ratio(?string $blank = null, string $params = ''): bool + public function is_image_ratio(string $blank = null, string $params = ''): bool { // Grab the file name off the top of the $params // after we split it. @@ -97,43 +95,4 @@ class FileRules extends ValidationFileRules } //-------------------------------------------------------------------- - - /** - * Checks that an uploaded json file's content is valid - */ - public function is_json(?string $blank = null, string $params = ''): bool - { - // Grab the file name off the top of the $params - // after we split it. - $params = explode(',', $params); - $name = array_shift($params); - - if (! ($files = $this->request->getFileMultiple($name))) { - $files = [$this->request->getFile($name)]; - } - - foreach ($files as $file) { - if ($file === null) { - return false; - } - - if ($file->getError() === UPLOAD_ERR_NO_FILE) { - return true; - } - - $content = file_get_contents($file->getTempName()); - - if ($content === false) { - return false; - } - - json_decode($content); - - if (json_last_error() !== JSON_ERROR_NONE) { - return false; - } - } - - return true; - } } diff --git a/app/Validation/OtherRules.php b/app/Validation/OtherRules.php deleted file mode 100644 index 74782809..00000000 --- a/app/Validation/OtherRules.php +++ /dev/null @@ -1,29 +0,0 @@ - 'alert', - ]; + protected ?string $title = null; /** * @var 'default'|'success'|'danger'|'warning' */ protected string $variant = 'default'; - #[Override] public function render(): string { - $variantData = match ($this->variant) { + $variants = [ 'success' => [ 'class' => 'text-pine-900 bg-pine-100 border-pine-300', - 'glyph' => 'check-fill', // @icon("check-fill") + 'glyph' => 'check', ], 'danger' => [ 'class' => 'text-red-900 bg-red-100 border-red-300', - 'glyph' => 'close-fill', // @icon("close-fill") + 'glyph' => 'close', ], 'warning' => [ 'class' => 'text-yellow-900 bg-yellow-100 border-yellow-300', - 'glyph' => 'alert-fill', // @icon("alert-fill") + 'glyph' => 'alert', ], - default => [ - 'class' => 'text-blue-900 bg-blue-100 border-blue-300', - 'glyph' => 'error-warning-fill', // @icon("error-warning-fill") - ], - }; + ]; - $glyph = icon(($this->glyph === '' ? $variantData['glyph'] : $this->glyph), [ - 'class' => 'flex-shrink-0 mr-2 text-lg', - ]); - $title = $this->title === '' ? '' : '
' . $this->title . '
'; - $this->mergeClass('inline-flex w-full p-2 text-sm border rounded '); - $this->mergeClass($variantData['class']); + $glyph = ''; + $title = $this->title === null ? '' : '
' . $this->title . '
'; + $class = 'inline-flex w-full p-2 text-sm border rounded ' . $variants[$this->variant]['class'] . ' ' . $this->class; + + unset($this->attributes['slot']); + unset($this->attributes['variant']); + $attributes = stringify_attributes($this->attributes); return <<getStringifiedAttributes()}>{$glyph}
{$title}

{$this->slot}

+ HTML; } } diff --git a/app/Views/Components/Button.php b/app/Views/Components/Button.php index 90d2ca63..292adf48 100644 --- a/app/Views/Components/Button.php +++ b/app/Views/Components/Button.php @@ -4,25 +4,14 @@ declare(strict_types=1); namespace App\Views\Components; -use Override; use ViewComponents\Component; class Button extends Component { - protected array $props = ['uri', 'variant', 'size', 'iconLeft', 'iconRight', 'isSquared', 'isExternal']; - - protected array $casts = [ - 'isSquared' => 'boolean', - 'isExternal' => 'boolean', - ]; - protected string $uri = ''; protected string $variant = 'default'; - /** - * @var 'small'|'base'|'large' - */ protected string $size = 'base'; protected string $iconLeft = ''; @@ -31,86 +20,106 @@ class Button extends Component protected bool $isSquared = false; - protected bool $isExternal = false; + public function setIsSquared(string $value): void + { + $this->isSquared = $value === 'true'; + } - #[Override] public function render(): string { - $this->mergeClass('shadow gap-x-2 flex-shrink-0 inline-flex items-center justify-center font-semibold rounded-full'); + $baseClass = + 'gap-x-2 flex-shrink-0 inline-flex items-center justify-center font-semibold shadow-xs rounded-full focus:ring-accent'; - $variantClass = match ($this->variant) { - 'primary' => 'text-accent-contrast bg-accent-base hover:bg-accent-hover', - 'secondary' => 'ring-2 ring-accent-base ring-inset text-accent-base bg-white hover:border-accent-hover hover:text-accent-hover hover:ring-accent-hover', - 'danger' => 'bg-red-50 ring-2 ring-red-700 ring-inset text-red-700 hover:ring-red-800 hover:text-red-800', - 'warning' => 'bg-yellow-50 ring-2 ring-yellow-700 ring-inset text-yellow-700 hover:ring-yellow-800 hover:text-yellow-800', - 'info' => 'bg-blue-50 ring-2 ring-blue-700 ring-inset text-blue-700 hover:ring-blue-800 hover:text-blue-800', - 'disabled' => 'text-black bg-gray-300 cursor-not-allowed', - default => 'text-black bg-gray-50 hover:bg-gray-200', - }; + $variantClass = [ + 'default' => 'text-black bg-gray-300 hover:bg-gray-400', + 'primary' => 'text-accent-contrast bg-accent-base hover:bg-accent-hover', + 'secondary' => 'border-2 border-accent-base text-accent-base bg-white hover:border-accent-hover hover:text-accent-hover', + 'success' => 'text-white bg-pine-500 hover:bg-pine-800', + 'danger' => 'text-white bg-red-600 hover:bg-red-700', + 'warning' => 'text-black bg-yellow-500 hover:bg-yellow-600', + 'info' => 'text-white bg-blue-500 hover:bg-blue-600', + 'disabled' => 'text-black bg-gray-300 cursor-not-allowed', + ]; - $sizeClass = match ($this->size) { + $sizeClass = [ 'small' => 'text-xs leading-6', + 'base' => 'text-sm leading-5', 'large' => 'text-base leading-6', - default => 'text-sm leading-5', - }; + ]; - $iconSizeClass = match ($this->size) { + $iconSize = [ 'small' => 'text-sm', + 'base' => 'text-lg', 'large' => 'text-2xl', - default => 'text-lg', - }; + ]; - $basePaddings = match ($this->size) { + $basePaddings = [ 'small' => 'px-3 py-1', + 'base' => 'px-3 py-2', 'large' => 'px-4 py-2', - default => 'px-3 py-2', - }; + ]; - $squaredPaddings = match ($this->size) { + $squaredPaddings = [ 'small' => 'p-1', + 'base' => 'p-2', 'large' => 'p-3', - default => 'p-2', - }; + ]; - $this->mergeClass($variantClass); - $this->mergeClass($sizeClass); + $buttonClass = + $baseClass . + ' ' . + ($this->isSquared + ? $squaredPaddings[$this->size] + : $basePaddings[$this->size]) . + ' ' . + $sizeClass[$this->size] . + ' ' . + $variantClass[$this->variant]; - if ($this->isSquared) { - $this->mergeClass($squaredPaddings); - } else { - $this->mergeClass($basePaddings); - } - - if ($this->iconLeft !== '' || $this->iconRight !== '') { - $this->slot = '' . $this->slot . ''; + if (array_key_exists('class', $this->attributes)) { + $buttonClass .= ' ' . $this->attributes['class']; + unset($this->attributes['class']); } if ($this->iconLeft !== '') { - $this->slot = icon($this->iconLeft, [ - 'class' => 'opacity-75 ' . $iconSizeClass, - ]) . $this->slot; + $this->slot = (new Icon([ + 'glyph' => $this->iconLeft, + 'class' => 'opacity-75' . ' ' . $iconSize[$this->size], + ]))->render() . $this->slot; } if ($this->iconRight !== '') { - $this->slot .= icon($this->iconRight, [ - 'class' => 'opacity-75 ' . $iconSizeClass, - ]); + $this->slot .= (new Icon([ + 'glyph' => $this->iconRight, + 'class' => 'opacity-75' . ' ' . $iconSize[$this->size], + ]))->render(); } + unset($this->attributes['slot']); + unset($this->attributes['variant']); + unset($this->attributes['size']); + unset($this->attributes['iconLeft']); + unset($this->attributes['iconRight']); + unset($this->attributes['isSquared']); + unset($this->attributes['uri']); + unset($this->attributes['label']); + if ($this->uri !== '') { $tagName = 'a'; - $this->attributes['href'] = $this->uri; - if ($this->isExternal) { - $this->attributes['target'] = '_blank'; - $this->attributes['rel'] = 'noopener noreferrer'; - } + $defaultButtonAttributes = [ + 'href' => $this->uri, + ]; } else { $tagName = 'button'; - $this->attributes['type'] ??= 'button'; + $defaultButtonAttributes = [ + 'type' => 'button', + ]; } + $attributes = stringify_attributes(array_merge($defaultButtonAttributes, $this->attributes)); + return <<getStringifiedAttributes()}>{$this->slot} + <{$tagName} class="{$buttonClass}" {$attributes}>{$this->slot} HTML; } } diff --git a/app/Views/Components/Charts/ChartsComponent.php b/app/Views/Components/Charts/ChartsComponent.php index 7d680f5a..8dbd5bfc 100644 --- a/app/Views/Components/Charts/ChartsComponent.php +++ b/app/Views/Components/Charts/ChartsComponent.php @@ -4,35 +4,21 @@ declare(strict_types=1); namespace App\Views\Components\Charts; -use Override; use ViewComponents\Component; class ChartsComponent extends Component { - protected array $props = ['title', 'subtitle', 'dataUrl', 'type']; + protected string $title = ''; - protected string $title; + protected string $dataUrl = ''; - protected string $subtitle = ''; + protected string $type = ''; - protected string $dataUrl; - - protected string $type; - - #[Override] public function render(): string { - $subtitleBlock = ''; - if ($this->subtitle !== '') { - $subtitleBlock = '

' . $this->subtitle . '

'; - } - - $this->mergeClass('bg-elevated border-3 rounded-xl border-subtle'); - return <<getStringifiedAttributes()}> +

{$this->title}

- {$subtitleBlock}
HTML; diff --git a/app/Views/Components/Charts/XYDuration.php b/app/Views/Components/Charts/XYDuration.php deleted file mode 100644 index bd881c56..00000000 --- a/app/Views/Components/Charts/XYDuration.php +++ /dev/null @@ -1,10 +0,0 @@ -subtitle = html_entity_decode($value); } - #[Override] public function render(): string { - $glyph = (string) icon($this->glyph, [ - 'class' => 'flex-shrink-0 bg-base rounded-full w-8 h-8 p-2 text-accent-base', - ]); + $glyph = icon($this->glyph, 'flex-shrink-0 bg-base rounded-full w-8 h-8 p-2 text-accent-base'); - if ($this->href !== '') { - $chevronRight = icon('arrow-right-s-fill'); + if ($this->href !== null && $this->href !== '') { + $chevronRight = icon('chevron-right'); $viewLang = lang('Common.view'); return << +
{$glyph}
{$this->title}
{$viewLang}{$chevronRight}

{$this->subtitle}

-
{$this->slot}
+
{$this->slot}
HTML; } return << +
{$glyph}
{$this->title}

{$this->subtitle}

-
{$this->slot}
+
{$this->slot}
HTML; } diff --git a/app/Views/Components/DropdownMenu.php b/app/Views/Components/DropdownMenu.php index 992ef22e..bed2220f 100644 --- a/app/Views/Components/DropdownMenu.php +++ b/app/Views/Components/DropdownMenu.php @@ -5,37 +5,27 @@ declare(strict_types=1); namespace App\Views\Components; use Exception; -use Override; use ViewComponents\Component; class DropdownMenu extends Component { - protected array $props = ['id', 'labelledby', 'placement', 'offsetX', 'offsetY', 'items']; + public string $id = ''; - protected array $casts = [ - 'offsetX' => 'number', - 'offsetY' => 'number', - 'items' => 'array', - ]; + public string $labelledby; - protected string $id; + public string $placement = 'bottom-end'; - protected string $labelledby; + public string $offsetX = '0'; - protected string $placement = 'bottom-end'; + public string $offsetY = '0'; - protected int $offsetX = 0; - - protected int $offsetY = 0; - - protected array $items = []; + public array $items = []; public function setItems(string $value): void { $this->items = json_decode(htmlspecialchars_decode($value), true); } - #[Override] public function render(): string { if ($this->items === []) { @@ -47,11 +37,11 @@ class DropdownMenu extends Component switch ($item['type']) { case 'link': $menuItems .= anchor($item['uri'], $item['title'], [ - 'class' => 'inline-flex gap-x-1 items-center px-4 py-1 hover:bg-highlight' . (array_key_exists('class', $item) ? ' ' . $item['class'] : ''), + 'class' => 'px-4 py-1 hover:bg-highlight focus:ring-accent focus:ring-inset' . (array_key_exists('class', $item) ? ' ' . $item['class'] : ''), ]); break; case 'html': - $menuItems .= htmlspecialchars_decode((string) $item['content']); + $menuItems .= htmlspecialchars_decode($item['content']); break; case 'separator': $menuItems .= '
'; @@ -61,16 +51,14 @@ class DropdownMenu extends Component } } - $this->mergeClass('absolute flex flex-col py-2 rounded-lg z-60 whitespace-nowrap text-skin-base border-contrast bg-elevated border-3'); - $this->attributes['id'] = $this->id; - $this->attributes['aria-labelledby'] = $this->labelledby; - $this->attributes['data-dropdown'] = 'menu'; - $this->attributes['data-dropdown-placement'] = $this->placement; - $this->attributes['data-dropdown-offset-x'] = $this->offsetX; - $this->attributes['data-dropdown-offset-y'] = $this->offsetY; - return <<getStringifiedAttributes()}>{$menuItems} + HTML; } } diff --git a/app/Views/Components/Forms/Checkbox.php b/app/Views/Components/Forms/Checkbox.php index 08c94bc5..63f033f7 100644 --- a/app/Views/Components/Forms/Checkbox.php +++ b/app/Views/Components/Forms/Checkbox.php @@ -4,59 +4,37 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use App\Views\Components\Hint; -use Override; - class Checkbox extends FormComponent { - protected array $props = ['hint', 'helper']; + protected ?string $hint = null; - protected array $casts = [ - 'isChecked' => 'boolean', - ]; + protected bool $isChecked = false; - protected string $hint = ''; + public function setIsChecked(string $value): void + { + $this->isChecked = $value === 'true'; + } - protected string $helper = ''; - - #[Override] public function render(): string { + $attributes = [ + 'id' => $this->value, + 'name' => $this->name, + 'class' => 'form-checkbox bg-elevated text-accent-base border-contrast border-3 focus:ring-accent w-6 h-6', + ]; + if ($this->required) { + $attributes['required'] = 'required'; + } $checkboxInput = form_checkbox( - [ - 'id' => $this->id, - 'name' => $this->name, - 'class' => 'form-checkbox bg-elevated text-accent-base border-contrast border-3 focus:ring-accent w-6 h-6 transition', - ], + $attributes, 'yes', - in_array($this->getValue(), ['yes', 'true', 'on', '1'], true), + old($this->name) ? old($this->name) === $this->value : $this->isChecked, ); - $hint = $this->hint === '' ? '' : new Hint([ - 'class' => 'ml-1', - 'slot' => $this->hint, - ])->render(); - - $this->mergeClass('inline-flex items-start gap-x-2'); - - $helperText = ''; - if ($this->helper !== '') { - $helperId = $this->name . 'Help'; - $helperText = new Helper([ - 'id' => $helperId, - 'slot' => $this->helper, - 'class' => '-mt-1', - ])->render(); - $this->attributes['aria-describedby'] = $helperId; - } + $hint = $this->hint === null ? '' : hint_tooltip($this->hint, 'ml-1'); return <<getStringifiedAttributes()}>{$checkboxInput} -
- {$this->slot}{$hint} - {$helperText} -
- + HTML; } } diff --git a/app/Views/Components/Forms/CodeEditor.php b/app/Views/Components/Forms/CodeEditor.php deleted file mode 100644 index ab20988f..00000000 --- a/app/Views/Components/Forms/CodeEditor.php +++ /dev/null @@ -1,35 +0,0 @@ - '6', - 'class' => 'bg-elevated w-full rounded-lg border-3 border-contrast focus:border-contrast focus-within:ring-accent transition', - ]; - - protected string $lang = ''; - - public function setValue(string $value): void - { - $this->value = htmlspecialchars_decode($value); - } - - #[Override] - public function render(): string - { - $this->attributes['slot'] = 'textarea'; - $textarea = form_textarea($this->attributes, $this->getValue()); - - return <<{$textarea} - HTML; - } -} diff --git a/app/Views/Components/Forms/ColorRadioButton.php b/app/Views/Components/Forms/ColorRadioButton.php index f1ff3fde..470200ef 100644 --- a/app/Views/Components/Forms/ColorRadioButton.php +++ b/app/Views/Components/Forms/ColorRadioButton.php @@ -4,39 +4,37 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; - class ColorRadioButton extends FormComponent { - protected array $props = ['isSelected']; + protected bool $isChecked = false; - protected array $casts = [ - 'isSelected' => 'boolean', - ]; + protected string $style = ''; - protected bool $isSelected = false; + public function setIsChecked(string $value): void + { + $this->isChecked = $value === 'true'; + } - #[Override] public function render(): string { $data = [ - 'id' => $this->value, - 'name' => $this->name, + 'id' => $this->value, + 'name' => $this->name, 'class' => 'color-radio-btn', ]; - if ($this->isRequired) { + if ($this->required) { $data['required'] = 'required'; } $radioInput = form_radio( $data, $this->value, - old($this->name) ? old($this->name) === $this->value : $this->isSelected, + old($this->name) ? old($this->name) === $this->value : $this->isChecked, ); return <<getStringifiedAttributes()}> +
{$radioInput}
diff --git a/app/Views/Components/Forms/DatetimePicker.php b/app/Views/Components/Forms/DatetimePicker.php index 1267ffef..1e3de877 100644 --- a/app/Views/Components/Forms/DatetimePicker.php +++ b/app/Views/Components/Forms/DatetimePicker.php @@ -4,34 +4,23 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; - class DatetimePicker extends FormComponent { - protected array $attributes = [ - 'data-picker' => 'datetime', - ]; - - #[Override] public function render(): string { - $dateInput = form_input([ - 'name' => $this->name, - 'class' => 'rounded-l-lg border-0 border-rounded-r-none flex-1 focus:ring-0', - 'data-input' => '', - ], $this->getValue()); + $this->attributes['class'] = 'rounded-l-lg border-0 border-rounded-r-none flex-1 focus:ring-0'; + $this->attributes['data-input'] = ''; + $dateInput = form_input($this->attributes, old($this->name, $this->value)); $clearLabel = lang( 'Episode.publish_form.scheduled_publication_date_clear', ); - $closeIcon = icon('close-fill'); - - $this->mergeClass('flex border-3 rounded-lg border-contrast focus-within:ring-accent transition'); + $closeIcon = icon('close'); return <<getStringifiedAttributes()}> +
{$dateInput} -
diff --git a/app/Views/Components/Forms/Field.php b/app/Views/Components/Forms/Field.php index 0efc0d09..8467df64 100644 --- a/app/Views/Components/Forms/Field.php +++ b/app/Views/Components/Forms/Field.php @@ -4,82 +4,52 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; -use ViewComponents\Component; - -class Field extends Component +class Field extends FormComponent { - protected array $props = [ - 'name', - 'label', - 'isRequired', - 'isReadonly', - 'as', - 'hint', - 'helper', - ]; - - protected array $casts = [ - 'isRequired' => 'boolean', - 'isReadonly' => 'boolean', - ]; - - protected string $name; - - protected string $label; - - protected bool $isRequired = false; - - protected bool $isReadonly = false; - protected string $as = 'Input'; - protected string $hint = ''; + protected string $label = ''; - protected string $helper = ''; + protected ?string $helper = null; + + protected ?string $hint = null; - #[Override] public function render(): string { $helperText = ''; - if ($this->helper !== '') { - $helperId = $this->name . 'Help'; - $helperText = new Helper([ - 'id' => $helperId, - 'slot' => $this->helper, - ])->render(); + if ($this->helper !== null) { + $helperId = $this->id . 'Help'; + $helperText = '' . $this->helper . ''; $this->attributes['aria-describedby'] = $helperId; } $labelAttributes = [ - 'for' => $this->name, - 'isOptional' => $this->isRequired ? 'false' : 'true', - 'class' => '-mb-1', - 'slot' => $this->label, + 'for' => $this->id, + 'isOptional' => $this->required ? 'false' : 'true', ]; - if ($this->hint !== '') { + if ($this->hint) { $labelAttributes['hint'] = $this->hint; } - $label = new Label($labelAttributes); + $labelAttributes = stringify_attributes($labelAttributes); - $this->mergeClass('flex flex-col'); - $fieldClass = $this->attributes['class']; + // remove field specific attributes to inject the rest to Form Component + $fieldComponentAttributes = $this->attributes; + unset($fieldComponentAttributes['as']); + unset($fieldComponentAttributes['label']); + unset($fieldComponentAttributes['class']); + unset($fieldComponentAttributes['helper']); + unset($fieldComponentAttributes['hint']); - unset($this->attributes['class']); + $fieldComponentAttributes['class'] = 'mb-1'; - $this->attributes['name'] = $this->name; - $this->attributes['isRequired'] = var_export($this->isRequired, true); - $this->attributes['isReadonly'] = var_export($this->isReadonly, true); $element = __NAMESPACE__ . '\\' . $this->as; - $fieldElement = new $element($this->attributes); + $fieldElement = new $element($fieldComponentAttributes); return << - {$label->render()} +
+ {$this->label} + {$fieldElement->render()} {$helperText} -
- {$fieldElement->render()} -
HTML; } diff --git a/app/Views/Components/Forms/FormComponent.php b/app/Views/Components/Forms/FormComponent.php index bcc46b26..d8883e04 100644 --- a/app/Views/Components/Forms/FormComponent.php +++ b/app/Views/Components/Forms/FormComponent.php @@ -6,77 +6,48 @@ namespace App\Views\Components\Forms; use ViewComponents\Component; -abstract class FormComponent extends Component +class FormComponent extends Component { - protected array $props = [ - 'id', - 'name', - 'value', - 'defaultValue', - 'isRequired', - 'isReadonly', - ]; + protected ?string $id = null; - protected array $casts = [ - 'isRequired' => 'boolean', - 'isReadonly' => 'boolean', - ]; + protected string $name = ''; - protected string $id; + protected string $value = ''; - protected string $name; + protected bool $required = false; - /** - * @var string|string[]|null - */ - protected string|array|null $value = null; - - /** - * @var string|string[]|null - */ - protected string|array|null $defaultValue = null; - - protected bool $isRequired = false; - - protected bool $isReadonly = false; + protected bool $readonly = false; /** * @param array $attributes */ public function __construct(array $attributes) { - $parentVars = get_class_vars(self::class); - $this->casts = [...$parentVars['casts'], ...$this->casts]; - $this->props = [...$parentVars['props'], $this->props]; - parent::__construct($attributes); - if (! isset($this->id)) { + if ($this->id === null) { $this->id = $this->name; - } - - $this->attributes['id'] = $this->id; - $this->attributes['name'] = $this->name; - - if ($this->isRequired) { - $this->attributes['required'] = 'required'; - } - - if ($this->isReadonly) { - $this->attributes['readonly'] = 'readonly'; + $this->attributes['id'] = $this->id; } } - protected function getValue(): string|array + public function setValue(string $value): void { - $valueCast = $this->casts['value'] ?? ''; - if ($valueCast === 'array') { - return old($this->name, in_array($this->value, [[], null], true) ? $this->defaultValue : $this->value) ?? []; - } + $this->value = htmlspecialchars_decode($value, ENT_QUOTES); + } - return old( - $this->name, - in_array($this->value, ['', null], true) ? $this->defaultValue : $this->value, - ) ?? ''; + public function setRequired(string $value): void + { + $this->required = $value === 'true'; + } + + public function setReadonly(string $value): void + { + $this->readonly = $value === 'true'; + if ($this->readonly) { + $this->attributes['readonly'] = 'readonly'; + } else { + unset($this->attributes['readonly']); + } } } diff --git a/app/Views/Components/Forms/Helper.php b/app/Views/Components/Forms/Helper.php index fbc895d1..f1702573 100644 --- a/app/Views/Components/Forms/Helper.php +++ b/app/Views/Components/Forms/Helper.php @@ -4,20 +4,19 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; -use ViewComponents\Component; - -class Helper extends Component +class Helper extends FormComponent { - // TODO: add type with error and show errors inline + /** + * @var 'default'|'error' + */ + protected string $type = 'default'; - #[Override] public function render(): string { - $this->mergeClass('form-helper'); + $class = 'text-skin-muted'; return <<getStringifiedAttributes()}>{$this->slot} + {$this->slot} HTML; } } diff --git a/app/Views/Components/Forms/Input.php b/app/Views/Components/Forms/Input.php index a45d3224..4a705ed2 100644 --- a/app/Views/Components/Forms/Input.php +++ b/app/Views/Components/Forms/Input.php @@ -4,33 +4,28 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; - class Input extends FormComponent { - protected array $props = ['type']; - protected string $type = 'text'; - #[Override] public function render(): string { - $this->mergeClass('w-full border-contrast rounded-lg focus:border-contrast border-3 focus-within:ring-accent transition'); + $baseClass = 'w-full bg-elevated border-contrast rounded-lg focus:border-contrast border-3 focus:ring-accent focus-within:ring-accent ' . $this->class; + + $this->attributes['class'] = $baseClass; if ($this->type === 'file') { - $this->mergeClass('file:px-3 file:py-2 file:h-[40px] file:font-semibold file:text-accent-hover file:text-sm file:rounded-none file:border-none file:bg-base file:cursor-pointer'); + $this->attributes['class'] .= ' file:px-3 file:py-2 file:h-[40px] file:font-semibold file:text-skin-muted file:text-sm file:rounded-none file:border-none file:bg-highlight file:cursor-pointer'; } else { - $this->mergeClass('px-3 py-2'); + $this->attributes['class'] .= ' px-3 py-2'; } - if ($this->isReadonly) { - $this->mergeClass('bg-base'); - } else { - $this->mergeClass('bg-elevated'); + unset($this->attributes['required']); + + if ($this->required) { + $this->attributes['required'] = 'required'; } - $this->attributes['type'] = $this->type; - - return form_input($this->attributes, $this->getValue()); + return form_input($this->attributes, old($this->name, $this->value)); } } diff --git a/app/Views/Components/Forms/Label.php b/app/Views/Components/Forms/Label.php index 3f8af6f6..49bbac3e 100644 --- a/app/Views/Components/Forms/Label.php +++ b/app/Views/Components/Forms/Label.php @@ -4,42 +4,39 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use App\Views\Components\Hint; -use Override; use ViewComponents\Component; class Label extends Component { - protected array $props = ['for', 'hint', 'isOptional']; + protected ?string $for = null; - protected array $casts = [ - 'isOptional' => 'boolean', - ]; - - protected string $for; - - protected string $hint = ''; + protected ?string $hint = null; protected bool $isOptional = false; - #[Override] + public function setIsOptional(string $value): void + { + $this->isOptional = $value === 'true'; + } + public function render(): string { - $this->mergeClass('text-sm font-semibold'); + $labelClass = 'text-sm ' . $this->attributes['class']; + unset($this->attributes['class']); - $optionalText = $this->isOptional ? '(' . + $optionalText = $this->isOptional ? '(' . lang('Common.optional') . ')' : ''; + $hint = $this->hint === null ? '' : hint_tooltip($this->hint, 'ml-1'); - $hint = $this->hint === '' ? '' : new Hint([ - 'class' => 'ml-1', - 'slot' => $this->hint, - ])->render(); + unset($this->attributes['isOptional']); + unset($this->attributes['hint']); + unset($this->attributes['slot']); - $this->attributes['for'] = $this->for; + $attributes = stringify_attributes($this->attributes); return <<getStringifiedAttributes()}>{$this->slot}{$optionalText}{$hint} + HTML; } } diff --git a/app/Views/Components/Forms/MarkdownEditor.php b/app/Views/Components/Forms/MarkdownEditor.php index 0549fd05..6625050d 100644 --- a/app/Views/Components/Forms/MarkdownEditor.php +++ b/app/Views/Components/Forms/MarkdownEditor.php @@ -4,12 +4,8 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; - class MarkdownEditor extends FormComponent { - protected array $props = ['disallowList']; - /** * @var string[] */ @@ -20,69 +16,69 @@ class MarkdownEditor extends FormComponent $this->disallowList = explode(',', $value); } - #[Override] public function render(): string { - $this->mergeClass('w-full flex flex-col bg-elevated border-3 border-contrast rounded-lg overflow-hidden focus-within:ring-accent transition'); - $wrapperClass = $this->attributes['class']; + $editorClass = 'w-full flex flex-col bg-elevated border-3 border-contrast rounded-lg overflow-hidden focus-within:ring-accent ' . $this->class; $this->attributes['class'] = 'bg-elevated border-none focus:border-none focus:outline-none focus:ring-0 w-full h-full'; $this->attributes['rows'] = 6; - $textarea = form_textarea( - $this->attributes, - $this->getValue(), + $textarea = form_textarea($this->attributes, old($this->name, $this->value)); + $markdownIcon = icon( + 'markdown', + 'mr-1 text-lg opacity-40' ); - $markdownIcon = (string) icon('markdown-fill', [ - 'class' => 'mr-1 text-lg opacity-40', - ]); - $translations = [ - 'write' => lang('Common.forms.editor.write'), + 'write' => lang('Common.forms.editor.write'), 'preview' => lang('Common.forms.editor.preview'), - 'help' => lang('Common.forms.editor.help'), + 'help' => lang('Common.forms.editor.help'), ]; $toolbarGroups = [ [ [ 'name' => 'header', - 'tag' => 'md-header', - 'icon' => (string) icon('heading'), + 'tag' => 'md-header', + 'icon' => icon('heading'), ], [ 'name' => 'bold', - 'tag' => 'md-bold', - 'icon' => (string) icon('bold'), + 'tag' => 'md-bold', + 'icon' => icon('bold'), ], [ 'name' => 'italic', - 'tag' => 'md-italic', - 'icon' => (string) icon('italic'), + 'tag' => 'md-italic', + 'icon' => icon('italic'), ], ], [ [ 'name' => 'unordered-list', - 'tag' => 'md-unordered-list', - 'icon' => (string) icon('list-unordered'), + 'tag' => 'md-unordered-list', + 'icon' => icon('list-unordered'), ], [ 'name' => 'ordered-list', - 'tag' => 'md-ordered-list ', - 'icon' => (string) icon('list-ordered-2'), + 'tag' => 'md-ordered-list ', + 'icon' => icon('list-ordered'), ], ], [ + [ + 'name' => 'quote', + 'tag' => 'md-quote', + 'icon' => icon('quote'), + ], [ 'name' => 'link', - 'tag' => 'md-link', - 'icon' => (string) icon('link'), + 'tag' => 'md-link', + 'icon' => icon('link'), ], [ 'name' => 'image', - 'tag' => 'md-image', - 'icon' => (string) icon('image-add-fill'), + 'tag' => 'md-image', + 'icon' => icon('image-add'), ], ], ]; @@ -92,19 +88,19 @@ class MarkdownEditor extends FormComponent $toolbarContent .= '
'; foreach ($buttonsGroup as $button) { if (! in_array($button['name'], $this->disallowList, true)) { - $toolbarContent .= '<' . $button['tag'] . ' class="opacity-50 hover:opacity-100 focus:opacity-100">' . $button['icon'] . ''; + $toolbarContent .= '<' . $button['tag'] . ' class="opacity-50 hover:opacity-100 focus:ring-accent focus:opacity-100">' . $button['icon'] . ''; } } $toolbarContent .= '
'; } return << +
- - + + {$toolbarContent}
diff --git a/app/Views/Components/Forms/MultiSelect.php b/app/Views/Components/Forms/MultiSelect.php new file mode 100644 index 00000000..67d0efd2 --- /dev/null +++ b/app/Views/Components/Forms/MultiSelect.php @@ -0,0 +1,45 @@ + + */ + protected array $options = []; + + /** + * @var string[] + */ + protected array $selected = []; + + public function setOptions(string $value): void + { + $this->options = json_decode(htmlspecialchars_decode($value), true); + } + + public function setSelected(string $selected): void + { + $this->selected = json_decode(htmlspecialchars_decode($selected), true); + } + + public function render(): string + { + $defaultAttributes = [ + 'data-class' => $this->attributes['class'], + 'multiple' => 'multiple', + 'data-select-text' => lang('Common.forms.multiSelect.selectText'), + 'data-loading-text' => lang('Common.forms.multiSelect.loadingText'), + 'data-no-results-text' => lang('Common.forms.multiSelect.noResultsText'), + 'data-no-choices-text' => lang('Common.forms.multiSelect.noChoicesText'), + 'data-max-item-text' => lang('Common.forms.multiSelect.maxItemText'), + ]; + $this->attributes['class'] .= ' bg-elevated border-3 border-contrast rounded-lg'; + $extra = array_merge($defaultAttributes, $this->attributes); + + return form_dropdown($this->name, $this->options, $this->selected, $extra); + } +} diff --git a/app/Views/Components/Forms/PermalinkEditor.php b/app/Views/Components/Forms/PermalinkEditor.php deleted file mode 100644 index 26cf31c9..00000000 --- a/app/Views/Components/Forms/PermalinkEditor.php +++ /dev/null @@ -1,41 +0,0 @@ -mergeClass('flex-1 text-xs border-contrast rounded-lg focus:border-contrast border-3 focus-within:ring-accent transition'); - - $this->attributes['slot'] = 'slug-input'; - $input = form_input($this->attributes, $this->getValue()); - - $editLabel = lang('Common.edit'); - $copyLabel = lang('Common.copy'); - $copiedLabel = lang('Common.copied'); - - return << - {$this->label} - - {$this->prefix} - {$input} - -
- HTML; - } -} diff --git a/app/Views/Components/Forms/Radio.php b/app/Views/Components/Forms/Radio.php index beac8525..9a67dd2e 100644 --- a/app/Views/Components/Forms/Radio.php +++ b/app/Views/Components/Forms/Radio.php @@ -4,35 +4,29 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; - class Radio extends FormComponent { - protected array $props = ['isChecked']; - - protected array $casts = [ - 'isChecked' => 'boolean', - ]; - protected bool $isChecked = false; - #[Override] + public function setIsChecked(string $value): void + { + $this->isChecked = $value === 'true'; + } + public function render(): string { $radioInput = form_radio( [ - 'id' => $this->value, - 'name' => $this->name, - 'class' => 'text-accent-base bg-elevated border-contrast border-3 focus:ring-accent w-6 h-6 transition', + 'id' => $this->value, + 'name' => $this->name, + 'class' => 'text-accent-base bg-elevated border-contrast border-3 focus:ring-accent w-6 h-6', ], - $this->getValue(), + $this->value, old($this->name) ? old($this->name) === $this->value : $this->isChecked, ); - $this->mergeClass('inline-flex items-center'); - return <<getStringifiedAttributes()}>{$radioInput}{$this->slot} + HTML; } } diff --git a/app/Views/Components/Forms/RadioButton.php b/app/Views/Components/Forms/RadioButton.php index 9f470b33..1772c3d4 100644 --- a/app/Views/Components/Forms/RadioButton.php +++ b/app/Views/Components/Forms/RadioButton.php @@ -4,57 +4,41 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; - class RadioButton extends FormComponent { - protected array $props = ['isSelected', 'description']; + protected bool $isChecked = false; - protected array $casts = [ - 'isSelected' => 'boolean', - ]; + protected ?string $hint = null; - protected bool $isSelected = false; + public function setIsChecked(string $value): void + { + $this->isChecked = $value === 'true'; + } - protected string $description = ''; - - #[Override] public function render(): string { $data = [ - 'id' => $this->value, - 'name' => $this->name, + 'id' => $this->value, + 'name' => $this->name, 'class' => 'form-radio-btn bg-elevated', ]; - if ($this->isRequired) { + if ($this->required) { $data['required'] = 'required'; } - $this->mergeClass('relative w-full'); - - $descriptionText = ''; - if ($this->description !== '') { - $describerId = $this->name . 'Help'; - $descriptionText = <<{$this->description} - HTML; - $data['aria-describedby'] = $describerId; - } - $radioInput = form_radio( $data, - $this->getValue(), - old($this->name) ? old($this->name) === $this->value : $this->isSelected, + $this->value, + old($this->name) ? old($this->name) === $this->value : $this->isChecked, ); + $hint = $this->hint ? hint_tooltip($this->hint, 'ml-1 text-base') : ''; + return <<getStringifiedAttributes()}"> +
{$radioInput} - +
HTML; } diff --git a/app/Views/Components/Forms/RadioGroup.php b/app/Views/Components/Forms/RadioGroup.php deleted file mode 100644 index 776ff8f2..00000000 --- a/app/Views/Components/Forms/RadioGroup.php +++ /dev/null @@ -1,70 +0,0 @@ - 'array', - ]; - - protected string $label; - - /** - * @var array{value:string,label:string,hint?:string} - */ - protected array $options = []; - - protected string $hint = ''; - - protected string $helper = ''; - - #[Override] - public function render(): string - { - $this->mergeClass('flex flex-col'); - $options = ''; - foreach ($this->options as $option) { - $radioButtonData = [ - 'value' => $option['value'], - 'name' => $this->name, - 'slot' => $option['label'], - 'description' => $option['description'] ?? '', - 'isSelected' => var_export($this->getValue() === '' ? $option['value'] === $this->options[0]['value'] : $option['value'] === $this->getValue(), true), - 'isRequired' => var_export($this->isRequired, true), - ]; - - $options .= new RadioButton($radioButtonData)->render(); - } - - $helperText = ''; - if ($this->helper !== '') { - $helperId = $this->name . 'Help'; - $helperText = new Helper([ - 'id' => $helperId, - 'slot' => $this->helper, - ])->render(); - $this->attributes['aria-describedby'] = $helperId; - } - - $hint = $this->hint === '' ? '' : new Hint([ - 'class' => 'ml-1', - 'slot' => $this->hint, - ])->render(); - - return <<getStringifiedAttributes()}> - {$this->label}{$hint} - {$helperText} -
{$options}
- - HTML; - } -} diff --git a/app/Views/Components/Forms/Section.php b/app/Views/Components/Forms/Section.php index d50baaed..eedd05a5 100644 --- a/app/Views/Components/Forms/Section.php +++ b/app/Views/Components/Forms/Section.php @@ -4,27 +4,23 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; use ViewComponents\Component; class Section extends Component { - protected array $props = ['title', 'subtitle']; + protected string $title = ''; - protected string $title; + protected ?string $subtitle = null; - protected string $subtitle = ''; + protected string $subtitleClass = ''; - #[Override] public function render(): string { - $subtitle = $this->subtitle === '' ? '' : '

' . $this->subtitle . '

'; - - $this->mergeClass('w-full p-4 sm:p-6 md:p-8 bg-elevated border-3 flex flex-col items-start border-subtle rounded-xl'); + $subtitle = $this->subtitle === null ? '' : '

' . $this->subtitle . '

'; return <<getStringifiedAttributes()}> - {$this->title} +
+ {$this->title} {$subtitle}
{$this->slot}
diff --git a/app/Views/Components/Forms/Select.php b/app/Views/Components/Forms/Select.php index b62c6942..1dce3393 100644 --- a/app/Views/Components/Forms/Select.php +++ b/app/Views/Components/Forms/Select.php @@ -4,44 +4,33 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; - class Select extends FormComponent { - protected array $props = ['options']; - - protected array $casts = [ - 'options' => 'array', - ]; - /** - * @var array> + * @var array */ protected array $options = []; - #[Override] + protected string $selected = ''; + + public function setOptions(string $value): void + { + $this->options = json_decode(htmlspecialchars_decode($value), true); + } + public function render(): string { - $this->mergeClass('w-full focus:border-contrast border-3 rounded-lg bg-elevated border-contrast'); $defaultAttributes = [ - 'data-select-text' => lang('Common.forms.multiSelect.selectText'), - 'data-loading-text' => lang('Common.forms.multiSelect.loadingText'), + 'class' => 'focus:border-contrast focus:ring-accent border-3 rounded-lg bg-elevated border-contrast ' . $this->class, + 'data-class' => $this->class, + 'data-select-text' => lang('Common.forms.multiSelect.selectText'), + 'data-loading-text' => lang('Common.forms.multiSelect.loadingText'), 'data-no-results-text' => lang('Common.forms.multiSelect.noResultsText'), 'data-no-choices-text' => lang('Common.forms.multiSelect.noChoicesText'), - 'data-max-item-text' => lang('Common.forms.multiSelect.maxItemText'), + 'data-max-item-text' => lang('Common.forms.multiSelect.maxItemText'), ]; - $this->attributes = [...$defaultAttributes, ...$this->attributes]; + $extra = array_merge($this->attributes, $defaultAttributes); - $options = ''; - $selected = $this->getValue(); - foreach ($this->options as $option) { - $options .= ''; - } - - $this->attributes['name'] = $this->name; - - return <<getStringifiedAttributes()}>{$options} - HTML; + return form_dropdown($this->name, $this->options, old($this->name, $this->selected !== '' ? [$this->selected] : []), $extra); } } diff --git a/app/Views/Components/Forms/SelectMulti.php b/app/Views/Components/Forms/SelectMulti.php deleted file mode 100644 index 6c09619b..00000000 --- a/app/Views/Components/Forms/SelectMulti.php +++ /dev/null @@ -1,52 +0,0 @@ - 'array', - 'defaultValue' => 'array', - 'options' => 'array', - ]; - - /** - * @var array> - */ - protected array $options = []; - - #[Override] - public function render(): string - { - $this->mergeClass('w-full bg-elevated border-3 border-contrast rounded-lg relative'); - - $defaultAttributes = [ - 'multiple' => 'multiple', - 'data-select-text' => lang('Common.forms.multiSelect.selectText'), - 'data-loading-text' => lang('Common.forms.multiSelect.loadingText'), - 'data-no-results-text' => lang('Common.forms.multiSelect.noResultsText'), - 'data-no-choices-text' => lang('Common.forms.multiSelect.noChoicesText'), - 'data-max-item-text' => lang('Common.forms.multiSelect.maxItemText'), - ]; - - $this->attributes = [...$defaultAttributes, ...$this->attributes]; - - $options = ''; - $selected = $this->getValue(); - foreach ($this->options as $option) { - $options .= ''; - } - - $this->attributes['name'] = $this->name . '[]'; - - return <<getStringifiedAttributes()}>{$options} - HTML; - } -} diff --git a/app/Views/Components/Forms/Textarea.php b/app/Views/Components/Forms/Textarea.php index f58e3b98..705ec0f3 100644 --- a/app/Views/Components/Forms/Textarea.php +++ b/app/Views/Components/Forms/Textarea.php @@ -4,27 +4,25 @@ declare(strict_types=1); namespace App\Views\Components\Forms; -use Override; - class Textarea extends FormComponent { - protected array $attributes = [ - 'rows' => '6', - ]; - - public function setValue(string $value): void + public function setValue(?string $value): void { - $this->value = htmlspecialchars_decode($value); + if ($value) { + $this->value = htmlspecialchars_decode($value); + } } - #[Override] public function render(): string { - $this->mergeClass('bg-elevated w-full rounded-lg border-3 border-contrast focus:border-contrast focus-within:ring-accent transition'); + unset($this->attributes['value']); - $this->attributes['id'] = $this->id; + $this->attributes['class'] = 'bg-elevated w-full focus:border-contrast focus:ring-accent rounded-lg border-3 border-contrast ' . $this->class; - $textarea = form_textarea($this->attributes, $this->getValue()); + $textarea = form_textarea( + $this->attributes, + old($this->name, $this->value ?? '', false) + ); return << 'boolean', - ]; + protected string $label = ''; protected string $hint = ''; - protected string $helper = ''; + protected bool $checked = false; - protected bool $isChecked = false; + public function setChecked(string $value): void + { + $this->checked = $value === 'true'; + } - #[Override] public function render(): string { - $this->mergeClass('relative justify-between inline-flex items-start gap-x-2'); + unset($this->attributes['checked']); - $checkbox = form_checkbox( - [ - 'id' => $this->id, - 'name' => $this->name, - 'class' => 'form-switch', - ], - 'yes', - in_array($this->getValue(), ['yes', 'true', 'on', '1'], true), - ); + $wrapperClass = $this->class; + unset($this->attributes['class']); - $hint = $this->hint === '' ? '' : new Hint([ - 'class' => 'ml-1', - 'slot' => $this->hint, - ])->render(); + $sizeClass = [ + 'base' => 'form-switch-slider', + 'small' => 'form-switch-slider form-switch-slider--small', + ]; - $helperText = ''; - if ($this->helper !== '') { - $helperId = $this->name . 'Help'; - $helperText = new Helper([ - 'id' => $helperId, - 'slot' => $this->helper, - 'class' => '-mt-1', - ])->render(); - $this->attributes['aria-describedby'] = $helperId; - } + $this->attributes['class'] = 'form-switch'; + $checkbox = form_checkbox($this->attributes, $this->value, old($this->name) === 'yes' ? true : $this->checked); + $hint = $this->hint === '' ? '' : hint_tooltip($this->hint, 'ml-1'); return <<getStringifiedAttributes()}> -
- {$this->slot}{$hint} - {$helperText} -
+ HTML; } diff --git a/app/Views/Components/Forms/XMLEditor.php b/app/Views/Components/Forms/XMLEditor.php new file mode 100644 index 00000000..fded2001 --- /dev/null +++ b/app/Views/Components/Forms/XMLEditor.php @@ -0,0 +1,33 @@ + + */ + protected array $attributes = [ + 'rows' => '5', + 'class' => 'textarea', + ]; + + protected string $content = ''; + + public function setContent(string $value): void + { + $this->content = htmlspecialchars_decode($value); + } + + public function render(): string + { + $this->attributes['slot'] = 'textarea'; + $textarea = form_textarea($this->attributes, $this->content); + + return <<{$textarea} + HTML; + } +} diff --git a/app/Views/Components/Heading.php b/app/Views/Components/Heading.php index 87d2de6e..5530c50b 100644 --- a/app/Views/Components/Heading.php +++ b/app/Views/Components/Heading.php @@ -4,13 +4,10 @@ declare(strict_types=1); namespace App\Views\Components; -use Override; use ViewComponents\Component; class Heading extends Component { - protected array $props = ['tagName', 'size']; - protected string $tagName = 'div'; /** @@ -18,20 +15,18 @@ class Heading extends Component */ protected string $size = 'base'; - #[Override] public function render(): string { - $sizeClass = match ($this->size) { + $sizeClasses = [ 'small' => 'tracking-wide text-base', + 'base' => 'text-xl', 'large' => 'text-3xl', - default => 'text-xl', - }; + ]; - $this->mergeClass('relative z-10 font-bold text-heading-foreground font-display before:w-full before:absolute before:h-1/2 before:left-0 before:bottom-0 before:rounded-full before:bg-heading-background before:z-[-10]'); - $this->mergeClass($sizeClass); + $class = $this->class . ' relative z-10 font-bold text-heading-foreground font-display before:w-full before:absolute before:h-1/2 before:left-0 before:bottom-0 before:rounded-full before:bg-heading-background before:z-[-10] ' . $sizeClasses[$this->size]; return <<tagName} {$this->getStringifiedAttributes()}>{$this->slot}tagName}> + <{$this->tagName} class="{$class}">{$this->slot}tagName}> HTML; } } diff --git a/app/Views/Components/Hint.php b/app/Views/Components/Hint.php deleted file mode 100644 index c329296f..00000000 --- a/app/Views/Components/Hint.php +++ /dev/null @@ -1,30 +0,0 @@ - 'bottom', - 'tabindex' => '0', - ]; - - #[Override] - public function render(): string - { - $this->attributes['title'] = $this->slot; - - $this->mergeClass('inline-block align-middle opacity-75'); - - $icon = icon('question-fill'); - - return <<getStringifiedAttributes()}>{$icon} - HTML; - } -} diff --git a/app/Views/Components/Icon.php b/app/Views/Components/Icon.php new file mode 100644 index 00000000..f926eb45 --- /dev/null +++ b/app/Views/Components/Icon.php @@ -0,0 +1,27 @@ +glyph . '.svg'); + } catch (Exception) { + return '□'; + } + + unset($this->attributes['glyph']); + $attributes = stringify_attributes($this->attributes); + + return str_replace(' 'true', - 'title' => $attributes['slot'], + 'isSquared' => 'true', + 'title' => $attributes['slot'], 'data-tooltip' => 'bottom', ]; - $allAttributes = [...$attributes, ...$iconButtonAttributes]; + $glyphSize = [ + 'small' => 'text-sm', + 'base' => 'text-lg', + 'large' => 'text-2xl', + ]; + + $allAttributes = array_merge($attributes, $iconButtonAttributes); parent::__construct($allAttributes); - $glyphSizeClass = match ($this->size) { - 'small' => 'text-sm', - 'large' => 'text-2xl', - default => 'text-lg', - }; - - $this->slot = (string) icon($this->glyph, [ - 'class' => $glyphSizeClass, - ]); + $this->slot = icon($this->glyph, $glyphSize[$this->size]); } } diff --git a/app/Views/Components/Pill.php b/app/Views/Components/Pill.php index 9d76cc5e..a6ff6ffa 100644 --- a/app/Views/Components/Pill.php +++ b/app/Views/Components/Pill.php @@ -4,57 +4,38 @@ declare(strict_types=1); namespace App\Views\Components; -use Override; use ViewComponents\Component; class Pill extends Component { - protected array $props = ['size', 'variant', 'icon', 'iconClass', 'hint']; - /** * @var 'small'|'base' */ - protected string $size = 'base'; + public string $size = 'base'; - protected string $variant = 'default'; + public string $variant = 'default'; - protected string $icon = ''; + public ?string $icon = null; - protected string $iconClass = ''; + public ?string $iconClass = ''; - protected string $hint = ''; + protected ?string $hint = null; - #[Override] public function render(): string { - $variantClass = match ($this->variant) { + $variantClasses = [ + 'default' => 'text-gray-800 bg-gray-100 border-gray-300', 'primary' => 'text-accent-contrast bg-accent-base border-accent-base', 'success' => 'text-pine-900 bg-pine-100 border-pine-300', - 'danger' => 'text-red-900 bg-red-100 border-red-300', + 'danger' => 'text-red-900 bg-red-100 border-red-300', 'warning' => 'text-yellow-900 bg-yellow-100 border-yellow-300', - default => 'text-gray-800 bg-gray-100 border-gray-300', - }; + ]; - $sizeClass = match ($this->size) { - 'small' => 'text-xs tracking-wide', - default => 'text-sm', - }; - - $icon = $this->icon !== '' ? icon($this->icon, [ - 'class' => $this->iconClass, - ]) : ''; - - if ($this->hint !== '') { - $this->attributes['data-tooltip'] = 'bottom'; - $this->attributes['title'] = $this->hint; - } - - $this->mergeClass('inline-flex lowercase items-center gap-x-1 px-1 font-semibold border rounded'); - $this->mergeClass($variantClass); - $this->mergeClass($sizeClass); + $icon = $this->icon ? icon($this->icon, $this->iconClass) : ''; + $hint = $this->hint ? 'data-tooltip="bottom" title="' . $this->hint . '"' : ''; return <<getStringifiedAttributes()}>{$icon}{$this->slot} + {$icon}{$this->slot} HTML; } } diff --git a/app/Views/Components/ReadMore.php b/app/Views/Components/ReadMore.php index d55e48d9..016a60b3 100644 --- a/app/Views/Components/ReadMore.php +++ b/app/Views/Components/ReadMore.php @@ -4,29 +4,21 @@ declare(strict_types=1); namespace App\Views\Components; -use Override; use ViewComponents\Component; class ReadMore extends Component { - protected array $props = ['id']; + public string $id; - protected string $id; - - #[Override] public function render(): string { $readMoreLabel = lang('Common.read_more'); $readLessLabel = lang('Common.read_less'); - - $this->mergeClass('read-more'); - $this->attributes['style'] = '--line-clamp: 3'; - return <<getStringifiedAttributes()}> +
-
{$this->slot}
- +
{$this->slot}
+
HTML; } diff --git a/app/Views/Components/SeeMore.php b/app/Views/Components/SeeMore.php index e8e42deb..19f247f2 100644 --- a/app/Views/Components/SeeMore.php +++ b/app/Views/Components/SeeMore.php @@ -4,25 +4,19 @@ declare(strict_types=1); namespace App\Views\Components; -use Override; use ViewComponents\Component; class SeeMore extends Component { - #[Override] public function render(): string { $seeMoreLabel = lang('Common.see_more'); $seeLessLabel = lang('Common.see_less'); - - $this->mergeClass('see-more'); - $this->attributes['styles'] = '--content-height: 10rem'; - return <<getStringifiedAttributes()}> +
-
{$this->slot}
- +
{$this->slot}
+
HTML; } diff --git a/app/Views/_message_block.php b/app/Views/_message_block.php index 4f40c4e5..1504aa37 100644 --- a/app/Views/_message_block.php +++ b/app/Views/_message_block.php @@ -1,18 +1,18 @@ has('message')): ?> - + has('error')): ?> - + has('errors')): ?>
    -
  • +
diff --git a/app/Views/errors/cli/error_exception.php b/app/Views/errors/cli/error_exception.php index 7a7247fc..b9c4941c 100644 --- a/app/Views/errors/cli/error_exception.php +++ b/app/Views/errors/cli/error_exception.php @@ -5,26 +5,17 @@ declare(strict_types=1); use CodeIgniter\CLI\CLI; // The main Exception -CLI::write('[' . $exception::class . ']', 'light_gray', 'red'); +CLI::newLine(); +CLI::write('[' . get_class($exception) . ']', 'light_gray', 'red'); +CLI::newLine(); CLI::write($message); +CLI::newLine(); CLI::write('at ' . CLI::color(clean_path($exception->getFile()) . ':' . $exception->getLine(), 'green')); CLI::newLine(); -$last = $exception; - -while ($prevException = $last->getPrevious()) { - $last = $prevException; - - CLI::write(' Caused by:'); - CLI::write(' [' . $prevException::class . ']', 'red'); - CLI::write(' ' . $prevException->getMessage()); - CLI::write(' at ' . CLI::color(clean_path($prevException->getFile()) . ':' . $prevException->getLine(), 'green')); - CLI::newLine(); -} - // The backtrace if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE) { - $backtraces = $last->getTrace(); + $backtraces = $exception->getTrace(); if ($backtraces) { CLI::write('Backtrace:', 'green'); @@ -36,9 +27,9 @@ if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE) { $c = str_pad((string) ($i + 1), 3, ' ', STR_PAD_LEFT); if (isset($error['file'])) { - $fileKey = clean_path($error['file']) . ':' . $error['line']; + $filepath = clean_path($error['file']) . ':' . $error['line']; - CLI::write($c . $padFile . CLI::color($fileKey, 'yellow')); + CLI::write($c . $padFile . CLI::color($filepath, 'yellow')); } else { CLI::write($c . $padFile . CLI::color('[internal function]', 'yellow')); } @@ -52,11 +43,20 @@ if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE) { $function .= $padClass . $error['function']; } - $args = implode(', ', array_map(static fn ($value) => match (true) { - is_object($value) => 'Object(' . $value::class . ')', - is_array($value) => $value !== [] ? '[...]' : '[]', - $value === null => 'null', // return the lowercased version - default => var_export($value, true), + $args = implode(', ', array_map(static function ($value) { + switch (true) { + case is_object($value): + return 'Object(' . get_class($value) . ')'; + + case is_array($value): + return count($value) ? '[...]' : '[]'; + + case $value === null: + return 'null'; // return the lowercased version + + default: + return var_export($value, true); + } }, array_values($error['args'] ?? []))); $function .= '(' . $args . ')'; diff --git a/app/Views/errors/html/debug.css b/app/Views/errors/html/debug.css index 3b6de5b6..2ef43583 100644 --- a/app/Views/errors/html/debug.css +++ b/app/Views/errors/html/debug.css @@ -3,7 +3,7 @@ --main-text-color: #555; --dark-text-color: #222; --light-text-color: #c7c7c7; - --brand-primary-color: #dc4814; + --brand-primary-color: #e06e3f; --light-bg-color: #ededee; --dark-bg-color: #404040; } @@ -11,81 +11,69 @@ body { height: 100%; background: var(--main-bg-color); - font-family: - -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, - "Apple Color Emoji", "Segoe UI Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, + sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; color: var(--main-text-color); font-weight: 300; margin: 0; padding: 0; } - h1 { font-weight: lighter; + letter-spacing: 0.8; font-size: 3rem; color: var(--dark-text-color); margin: 0; } - h1.headline { margin-top: 20%; font-size: 5rem; } - .text-center { text-align: center; } - p.lead { font-size: 1.6rem; } - .container { max-width: 75rem; margin: 0 auto; padding: 1rem; } - .header { background: var(--light-bg-color); color: var(--dark-text-color); - margin-top: 2.17rem; } - .header .container { - padding: 1rem; + padding: 1rem 1.75rem 1.75rem 1.75rem; } - .header h1 { font-size: 2.5rem; font-weight: 500; } - .header p { font-size: 1.2rem; margin: 0; line-height: 2.5; } - .header a { color: var(--brand-primary-color); margin-left: 2rem; display: none; text-decoration: none; } - .header:hover a { display: inline; } -.environment { - background: var(--brand-primary-color); - color: var(--main-bg-color); +.footer { + background: var(--dark-bg-color); + color: var(--light-text-color); +} +.footer .container { + border-top: 1px solid #e7e7e7; + margin-top: 1rem; text-align: center; - padding: calc(4px + 0.2083vw); - width: 100%; - top: 0; - position: fixed; } .source { @@ -98,21 +86,17 @@ p.lead { margin: 0; overflow-x: scroll; } - .source span.line { line-height: 1.4; } - .source span.line .number { color: #666; } - .source .line .highlight { display: block; background: var(--dark-text-color); color: var(--light-text-color); } - .source span.highlight .number { color: #fff; } @@ -124,44 +108,37 @@ p.lead { padding: 0; margin-bottom: -1px; } - .tabs li { display: inline; } - .tabs a:link, .tabs a:visited { - padding: 0 1rem; + padding: 0rem 1rem; line-height: 2.7; text-decoration: none; color: var(--dark-text-color); background: var(--light-bg-color); - border: 1px solid rgb(0 0 0 / 15%); + border: 1px solid rgba(0, 0, 0, 0.15); border-bottom: 0; border-top-left-radius: 5px; border-top-right-radius: 5px; display: inline-block; } - .tabs a:hover { background: var(--light-bg-color); - border-color: rgb(0 0 0 / 15%); + border-color: rgba(0, 0, 0, 0.15); } - .tabs a.active { background: var(--main-bg-color); color: var(--main-text-color); } - .tab-content { background: var(--main-bg-color); - border: 1px solid rgb(0 0 0 / 15%); + border: 1px solid rgba(0, 0, 0, 0.15); } - .content { padding: 1rem; } - .hide { display: none; } @@ -176,26 +153,26 @@ p.lead { border-radius: 5px; color: #31708f; } +ul, +ol { + line-height: 1.8; +} table { width: 100%; overflow: hidden; } - th { text-align: left; border-bottom: 1px solid #e7e7e7; padding-bottom: 0.5rem; } - td { padding: 0.2rem 0.5rem 0.2rem 0; } - tr:hover td { background: #f1f1f1; } - td pre { white-space: pre-wrap; } @@ -203,25 +180,20 @@ td pre { .trace a { color: inherit; } - .trace table { width: auto; } - .trace tr td:first-child { min-width: 5em; font-weight: bold; } - .trace td { background: var(--light-bg-color); padding: 0 1rem; } - .trace td pre { margin: 0; } - .args { display: none; } diff --git a/app/Views/errors/html/debug.js b/app/Views/errors/html/debug.js index 65254785..3428750f 100644 --- a/app/Views/errors/html/debug.js +++ b/app/Views/errors/html/debug.js @@ -5,7 +5,6 @@ var tabLinks = []; var contentDivs = []; -// eslint-disable-next-line @typescript-eslint/no-unused-vars function init() { // Grab the tab links and content divs from the page var tabListItems = document.getElementById("tabs").childNodes; @@ -86,7 +85,6 @@ function getHash(url) { //-------------------------------------------------------------------- -// eslint-disable-next-line @typescript-eslint/no-unused-vars function toggle(elem) { elem = document.getElementById(elem); diff --git a/app/Views/errors/html/error_400.php b/app/Views/errors/html/error_400.php deleted file mode 100644 index 555da042..00000000 --- a/app/Views/errors/html/error_400.php +++ /dev/null @@ -1,84 +0,0 @@ - - - - - <?= lang('Errors.badRequest') ?> - - - - -
-

400

- -

- - - - - -

-
- - diff --git a/app/Views/errors/html/error_403.php b/app/Views/errors/html/error_403.php deleted file mode 100644 index a5d4d040..00000000 --- a/app/Views/errors/html/error_403.php +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - 403 Forbidden - ' /> - asset('styles/index.css', 'css') ?> - - - - -

403 - Forbidden

- -

- - - - You do not have sufficient permissions to access that page. - -

- - - - diff --git a/app/Views/errors/html/error_404.php b/app/Views/errors/html/error_404.php index 4d74a150..ed288ac1 100644 --- a/app/Views/errors/html/error_404.php +++ b/app/Views/errors/html/error_404.php @@ -1,13 +1,12 @@ - + - <?= lang('Errors.pageNotFound') ?> + 404 Page Not Found ' /> asset('styles/index.css', 'css') ?> @@ -15,16 +14,16 @@ -

404

+

404 - File Not Found

- + Sorry! Cannot seem to find the page you were looking for.

- + diff --git a/app/Views/errors/html/error_exception.php b/app/Views/errors/html/error_exception.php index 1931636f..e0723098 100644 --- a/app/Views/errors/html/error_exception.php +++ b/app/Views/errors/html/error_exception.php @@ -1,12 +1,6 @@ - +$error_id = uniqid('error', true); ?> @@ -14,11 +8,11 @@ $errorId = uniqid('error', true); <?= esc($title) ?> - - @@ -26,12 +20,6 @@ $errorId = uniqid('error', true);
-
- Displayed at — - PHP: — - CodeIgniter: -- - Environment: -

getCode() ? ' #' . $exception->getCode() : '') ?>

@@ -53,30 +41,6 @@ $errorId = uniqid('error', true);

-
- getPrevious()) { - $last = $prevException; - ?> - -
-    Caused by:
-    getCode() ? ' #' . $prevException->getCode() : '') ?>
-
-    getMessage())) ?>
-    getMessage())) ?>"
-       rel="noreferrer" target="_blank">search →
-    getFile()) . ':' . $prevException->getLine()) ?>
-    
- - -
- -
    @@ -99,14 +63,14 @@ while ($prevException = $last->getPrevious()) {
  • - + + if (isset($row['function']) && in_array($row['function'], ['include', 'include_once', 'require', 'require_once'], true)) { + echo esc($row['function'] . ' ' . clean_path($row['file'])); + } else { + echo esc(clean_path($row['file']) . ' : ' . $row['line']); + } + ?> {PHP internal code} @@ -115,20 +79,20 @@ while ($prevException = $last->getPrevious()) {   —   - - ( arguments ) -

    + + ( arguments ) +
    getParameters(); - } + $params = null; + // Reflection by name is not available for closure function + if (substr($row['function'], -1) !== '}') { + $mirror = isset($row['class']) ? new \ReflectionMethod($row['class'], $row['function']) : new \ReflectionFunction($row['function']); + $params = $mirror->getParameters(); + } - foreach ($row['args'] as $key => $value) : ?> + foreach ($row['args'] as $key => $value) : ?> @@ -227,7 +191,7 @@ while ($prevException = $last->getPrevious()) {
    - +
    name : "#{$key}") ?>
    @@ -237,7 +201,7 @@ while ($prevException = $last->getPrevious()) { - + @@ -321,22 +285,22 @@ while ($prevException = $last->getPrevious()) { - $value) : ?> - - - - - + + + + + + + + +
    HTTP MethodgetMethod()) ?>getMethod())) ?>
    IP Address
    - getValueLine(), 'html'); - } else { - foreach ($value as $i => $header) { - echo ' (' . $i + 1 . ') ' . esc($header->getValueLine(), 'html'); - } - } - ?> -
    getName(), 'html') ?>getValueLine(), 'html') ?>
    @@ -345,9 +309,9 @@ while ($prevException = $last->getPrevious()) { setStatusCode(http_response_code()); -?> + $response = \Config\Services::response(); + $response->setStatusCode(http_response_code()); + ?>
    @@ -358,6 +322,8 @@ $response->setStatusCode(http_response_code()); headers(); ?> + +

    Headers

    @@ -368,22 +334,12 @@ $response->setStatusCode(http_response_code()); - $value) : ?> - - - - - + $value) : ?> + + + + +
    - getHeaderLine($name), 'html'); - } else { - foreach ($value as $i => $header) { - echo ' (' . $i + 1 . ') ' . esc($header->getValueLine(), 'html'); - } - } - ?> -
    getHeaderLine($name), 'html') ?>
    @@ -426,7 +382,18 @@ $response->setStatusCode(http_response_code());
    - + + diff --git a/app/Views/errors/html/production.php b/app/Views/errors/html/production.php index 77445e16..1ddf8306 100644 --- a/app/Views/errors/html/production.php +++ b/app/Views/errors/html/production.php @@ -7,45 +7,41 @@ - <?= lang('Errors.whoops') ?> + Whoops! ' /> asset('styles/index.css', 'css') ?> - loggedIn()): ?> + isLoggedIn()): ?> asset('js/error.ts', 'js') ?> - loggedIn()): ?> + isLoggedIn()): ?>
    -

    -

    +

    Whoops!

    +

    We seem to have hit a snag. Please try again later...

    getCode() ? ' #' . $exception->getCode() : '') ?>

    getMessage())) ?>
    at getFile())) ?>:getLine()) ?>

    - - 'mr-2', - ]) ?>Copy stack trace - + + Copy stack trace +

    Found a bug?

    -

    You can help get it fixed by creating an issue on the Castopod issue tracker. Please check that the issue does not already exist beforehand.

    +

    You can help get it fixed by creating an issue on the Castopod issue tracker. Please check that the issue does not already exist beforehand.

    Not sure what's happening?

    -

    You can ask for help in the Castopod community chat!

    +

    You can ask for help in the Castopod community chat!

    diff --git a/app/Views/pager/default_full.php b/app/Views/pager/default_full.php index e82fefa8..7d942e38 100644 --- a/app/Views/pager/default_full.php +++ b/app/Views/pager/default_full.php @@ -11,18 +11,18 @@ $pager->setSurroundCount(2); hasPreviousPage()): ?>
  • + 'Pager.first', +) ?>" class="block px-3 py-2 text-skin-muted hover:bg-highlight">
  • + 'Pager.previous', +) ?>" class="block px-3 py-2 text-skin-muted hover:bg-highlight"> + 'Pager.previous', +) ?>
  • @@ -34,7 +34,9 @@ $pager->setSurroundCount(2); - + @@ -44,15 +46,15 @@ $pager->setSurroundCount(2); hasNextPage()): ?>
  • + 'Pager.next', + ) ?>" class="block px-3 py-2 text-skin-muted hover:bg-highlight">
  • + 'Pager.last', + ) ?>" class="block px-3 py-2 text-skin-muted hover:bg-highlight">
  • diff --git a/app/index.html b/app/index.html index 242d70c1..5caba05a 100644 --- a/app/index.html +++ b/app/index.html @@ -1,4 +1,4 @@ - + 403 Forbidden diff --git a/builds b/builds index e7884e0b..cc2ca085 100644 --- a/builds +++ b/builds @@ -1,8 +1,6 @@ #!/usr/bin/env php vendor/opawg/user-agents-v2-php/src/UserAgents.php", - "@php vendor/opawg/user-agents-v2-php/src/UserAgentsRSSGenerate.php > vendor/opawg/user-agents-v2-php/src/UserAgentsRSS.php", + "@php vendor/opawg/user-agents-php/src/UserAgentsGenerate.php > vendor/opawg/user-agents-php/src/UserAgents.php", + "@php vendor/opawg/user-agents-php/src/UserAgentsRSSGenerate.php > vendor/opawg/user-agents-php/src/UserAgentsRSS.php", "@php vendor/adaures/ipcat-php/src/IpDbGenerate.php > vendor/adaures/ipcat-php/src/IpDb.php", "@php vendor/adaures/podcast-persons-taxonomy/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json > modules/Admin/Language/en/PersonsTaxonomy.php", "@php vendor/adaures/podcast-persons-taxonomy/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-fr.json > modules/Admin/Language/fr/PersonsTaxonomy.php", - "@php vendor/adaures/podcast-persons-taxonomy/src/ReversedTaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json > vendor/adaures/podcast-persons-taxonomy/src/ReversedTaxonomy.php", - "vendor/bin/php-icons init && vendor/bin/php-icons scan" + "@php vendor/adaures/podcast-persons-taxonomy/src/ReversedTaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json > vendor/adaures/podcast-persons-taxonomy/src/ReversedTaxonomy.php" ], "post-update-cmd": [ "@composer dump-autoload", - "@php vendor/opawg/user-agents-v2-php/src/UserAgentsGenerate.php > vendor/opawg/user-agents-v2-php/src/UserAgents.php", - "@php vendor/opawg/user-agents-v2-php/src/UserAgentsRSSGenerate.php > vendor/opawg/user-agents-v2-php/src/UserAgentsRSS.php", + "@php vendor/opawg/user-agents-php/src/UserAgentsGenerate.php > vendor/opawg/user-agents-php/src/UserAgents.php", + "@php vendor/opawg/user-agents-php/src/UserAgentsRSSGenerate.php > vendor/opawg/user-agents-php/src/UserAgentsRSS.php", "@php vendor/adaures/ipcat-php/src/IpDbGenerate.php > vendor/adaures/ipcat-php/src/IpDb.php", "@php vendor/adaures/podcast-persons-taxonomy/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json > modules/Admin/Language/en/PersonsTaxonomy.php", "@php vendor/adaures/podcast-persons-taxonomy/src/TaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-fr.json > modules/Admin/Language/fr/PersonsTaxonomy.php", - "@php vendor/adaures/podcast-persons-taxonomy/src/ReversedTaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json > vendor/adaures/podcast-persons-taxonomy/src/ReversedTaxonomy.php", - "vendor/bin/php-icons init && vendor/bin/php-icons scan" + "@php vendor/adaures/podcast-persons-taxonomy/src/ReversedTaxonomyGenerate.php https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json > vendor/adaures/podcast-persons-taxonomy/src/ReversedTaxonomy.php" ] }, "support": { "source": "https://code.castopod.org/adaures/castopod.git", "discord": "https://castopod.org/discord" }, - "minimum-stability": "dev", "prefer-stable": true, "config": { - "optimize-autoloader": true, - "preferred-install": "dist", - "sort-packages": true, "allow-plugins": { "phpstan/extension-installer": true } - }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/codeigniter4/tasks.git" - } - ] + } } diff --git a/composer.lock b/composer.lock index 3e35a5dd..0eaf6f04 100644 --- a/composer.lock +++ b/composer.lock @@ -4,63 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "de1c665976cbb37fec3de326336d83f5", + "content-hash": "caa3b9ff10584fe03c7be1176713b427", "packages": [ - { - "name": "adaures/castopod-plugins-manager", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/ad-aures/castopod-plugins-manager.git", - "reference": "53430f9a57cd38eee3e3dfe5953764cc42c2a0c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ad-aures/castopod-plugins-manager/zipball/53430f9a57cd38eee3e3dfe5953764cc42c2a0c9", - "reference": "53430f9a57cd38eee3e3dfe5953764cc42c2a0c9", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "z4kn4fein/php-semver": "^3.0" - }, - "require-dev": { - "pestphp/pest": "^4.0.4", - "pestphp/pest-plugin-type-coverage": "^4.0.2", - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.1.22", - "rector/rector": "^2.1.4", - "symplify/coding-standard": "^12.4.3", - "symplify/easy-coding-standard": "^12.5.24" - }, - "default-branch": true, - "type": "library", - "autoload": { - "files": [ - "src/Constants.php", - "src/helpers.php" - ], - "psr-4": { - "Castopod\\PluginsManager\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "AGPL-3.0-only" - ], - "authors": [ - { - "name": "Yassine Doghri", - "homepage": "https://yassinedoghri.com/" - } - ], - "description": "A PHP library to install, update, and remove plugins on a Castopod instance.", - "support": { - "issues": "https://github.com/ad-aures/castopod-plugins-manager/issues", - "source": "https://github.com/ad-aures/castopod-plugins-manager/tree/main" - }, - "time": "2025-10-06T15:58:43+00:00" - }, { "name": "adaures/ipcat-php", "version": "v1.0.0", @@ -79,9 +24,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-3.0-only" - ], + "license": ["GPL-3.0-only"], "authors": [ { "name": "Benjamin Bellamy", @@ -100,11 +43,11 @@ }, { "name": "adaures/podcast-persons-taxonomy", - "version": "v1.0.1", + "version": "v1.0.0", "source": { "type": "git", "url": "https://code.castopod.org/adaures/podcast-persons-taxonomy", - "reference": "d2a6836e32ed013676fd969425e133e0ebb104fc" + "reference": "117b207e334f54cd1b00ee52b0c53d58cb1a5524" }, "type": "library", "autoload": { @@ -113,9 +56,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Benjamin Bellamy", @@ -130,253 +71,30 @@ ], "description": "Generate PHP translation files for CodeIgniter4 from the podcast-namespace's Persons Taxonomy json files.", "homepage": "https://code.castopod.org/adaures/podcast-persons-taxonomy", - "time": "2023-06-22T14:24:55+00:00" - }, - { - "name": "adhocore/cli", - "version": "v1.9.4", - "source": { - "type": "git", - "url": "https://github.com/adhocore/php-cli.git", - "reference": "474dc3d7ab139796be98b104d891476e3916b6f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/adhocore/php-cli/zipball/474dc3d7ab139796be98b104d891476e3916b6f4", - "reference": "474dc3d7ab139796be98b104d891476e3916b6f4", - "shasum": "" - }, - "require": { - "php": ">=8.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Ahc\\Cli\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jitendra Adhikari", - "email": "jiten.adhikary@gmail.com" - } - ], - "description": "Command line interface library for PHP", - "keywords": [ - "argument-parser", - "argv-parser", - "cli", - "cli-action", - "cli-app", - "cli-color", - "cli-option", - "cli-writer", - "command", - "console", - "console-app", - "php-cli", - "php8", - "stream-input", - "stream-output" - ], - "support": { - "issues": "https://github.com/adhocore/php-cli/issues", - "source": "https://github.com/adhocore/php-cli/tree/v1.9.4" - }, - "funding": [ - { - "url": "https://paypal.me/ji10", - "type": "custom" - }, - { - "url": "https://github.com/adhocore", - "type": "github" - } - ], - "time": "2025-05-11T13:23:54+00:00" - }, - { - "name": "aws/aws-crt-php", - "version": "v1.2.7", - "source": { - "type": "git", - "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e", - "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", - "yoast/phpunit-polyfills": "^1.0" - }, - "suggest": { - "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "AWS SDK Common Runtime Team", - "email": "aws-sdk-common-runtime@amazon.com" - } - ], - "description": "AWS Common Runtime for PHP", - "homepage": "https://github.com/awslabs/aws-crt-php", - "keywords": [ - "amazon", - "aws", - "crt", - "sdk" - ], - "support": { - "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7" - }, - "time": "2024-10-18T22:15:13+00:00" - }, - { - "name": "aws/aws-sdk-php", - "version": "3.369.37", - "source": { - "type": "git", - "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "bc599ce989b101ee630d5e1a1aeda387632df47b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/bc599ce989b101ee630d5e1a1aeda387632df47b", - "reference": "bc599ce989b101ee630d5e1a1aeda387632df47b", - "shasum": "" - }, - "require": { - "aws/aws-crt-php": "^1.2.3", - "ext-json": "*", - "ext-pcre": "*", - "ext-simplexml": "*", - "guzzlehttp/guzzle": "^7.4.5", - "guzzlehttp/promises": "^2.0", - "guzzlehttp/psr7": "^2.4.5", - "mtdowling/jmespath.php": "^2.8.0", - "php": ">=8.1", - "psr/http-message": "^1.0 || ^2.0", - "symfony/filesystem": "^v5.4.45 || ^v6.4.3 || ^v7.1.0 || ^v8.0.0" - }, - "require-dev": { - "andrewsville/php-token-reflection": "^1.4", - "aws/aws-php-sns-message-validator": "~1.0", - "behat/behat": "~3.0", - "composer/composer": "^2.7.8", - "dms/phpunit-arraysubset-asserts": "^0.4.0", - "doctrine/cache": "~1.4", - "ext-dom": "*", - "ext-openssl": "*", - "ext-sockets": "*", - "phpunit/phpunit": "^9.6", - "psr/cache": "^2.0 || ^3.0", - "psr/simple-cache": "^2.0 || ^3.0", - "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0", - "yoast/phpunit-polyfills": "^2.0" - }, - "suggest": { - "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", - "doctrine/cache": "To use the DoctrineCacheAdapter", - "ext-curl": "To send requests using cURL", - "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", - "ext-pcntl": "To use client-side monitoring", - "ext-sockets": "To use client-side monitoring" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Aws\\": "src/" - }, - "exclude-from-classmap": [ - "src/data/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Amazon Web Services", - "homepage": "http://aws.amazon.com" - } - ], - "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", - "homepage": "http://aws.amazon.com/sdkforphp", - "keywords": [ - "amazon", - "aws", - "cloud", - "dynamodb", - "ec2", - "glacier", - "s3", - "sdk" - ], - "support": { - "forum": "https://github.com/aws/aws-sdk-php/discussions", - "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.369.37" - }, - "time": "2026-02-18T19:16:34+00:00" + "time": "2022-02-20T14:09:25+00:00" }, { "name": "brick/math", - "version": "0.14.8", + "version": "0.10.2", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629" + "reference": "459f2781e1a08d52ee56b0b1444086e038561e3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/63422359a44b7f06cae63c3b429b59e8efcc0629", - "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629", + "url": "https://api.github.com/repos/brick/math/zipball/459f2781e1a08d52ee56b0b1444086e038561e3f", + "reference": "459f2781e1a08d52ee56b0b1444086e038561e3f", "shasum": "" }, "require": { - "php": "^8.2" + "ext-json": "*", + "php": "^7.4 || ^8.0" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpstan/phpstan": "2.1.22", - "phpunit/phpunit": "^11.5" + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "4.25.0" }, "type": "library", "autoload": { @@ -385,9 +103,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Arbitrary-precision arithmetic library", "keywords": [ "Arbitrary-precision", @@ -396,17 +112,12 @@ "arithmetic", "bigdecimal", "bignum", - "bignumber", "brick", - "decimal", - "integer", - "math", - "mathematics", - "rational" + "math" ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.8" + "source": "https://github.com/brick/math/tree/0.10.2" }, "funding": [ { @@ -414,7 +125,7 @@ "type": "github" } ], - "time": "2026-02-10T14:33:43+00:00" + "time": "2022-08-10T22:54:19+00:00" }, { "name": "chrisjean/php-ico", @@ -436,14 +147,10 @@ }, "type": "library", "autoload": { - "classmap": [ - "class-php-ico.php" - ] + "classmap": ["class-php-ico.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0+" - ], + "license": ["GPL-2.0+"], "authors": [ { "name": "Chris Jean", @@ -453,268 +160,116 @@ ], "description": "An easy-to-use library to generate valid ICO files.", "homepage": "https://github.com/chrisbliss18/php-ico", - "keywords": [ - "favicon", - "ico" - ], + "keywords": ["favicon", "ico"], "support": { "issues": "https://github.com/chrisbliss18/php-ico/issues", "source": "https://github.com/chrisbliss18/php-ico" }, "time": "2016-09-27T22:00:56+00:00" }, - { - "name": "cocur/slugify", - "version": "v4.7.1", - "source": { - "type": "git", - "url": "https://github.com/cocur/slugify.git", - "reference": "a860dab2b9f5f37775fc6414d4f049434848165f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cocur/slugify/zipball/a860dab2b9f5f37775fc6414d4f049434848165f", - "reference": "a860dab2b9f5f37775fc6414d4f049434848165f", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" - }, - "conflict": { - "symfony/config": "<3.4 || >=4,<4.3", - "symfony/dependency-injection": "<3.4 || >=4,<4.3", - "symfony/http-kernel": "<3.4 || >=4,<4.3", - "twig/twig": "<2.12.1" - }, - "require-dev": { - "laravel/framework": "^5.0|^6.0|^7.0|^8.0", - "latte/latte": "~2.2", - "league/container": "^2.2.0", - "mikey179/vfsstream": "~1.6.8", - "mockery/mockery": "^1.3", - "nette/di": "~2.4", - "pimple/pimple": "~1.1", - "plumphp/plum": "~0.1", - "symfony/config": "^3.4 || ^4.3 || ^5.0 || ^6.0", - "symfony/dependency-injection": "^3.4 || ^4.3 || ^5.0 || ^6.0", - "symfony/http-kernel": "^3.4 || ^4.3 || ^5.0 || ^6.0", - "symfony/phpunit-bridge": "^5.4 || ^6.0", - "twig/twig": "^2.12.1 || ~3.0", - "zendframework/zend-modulemanager": "~2.2", - "zendframework/zend-servicemanager": "~2.2", - "zendframework/zend-view": "~2.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Cocur\\Slugify\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Florian Eckerstorfer", - "email": "florian@eckerstorfer.co", - "homepage": "https://florian.ec" - }, - { - "name": "Ivo Bathke", - "email": "ivo.bathke@gmail.com" - } - ], - "description": "Converts a string into a slug.", - "keywords": [ - "slug", - "slugify" - ], - "support": { - "issues": "https://github.com/cocur/slugify/issues", - "source": "https://github.com/cocur/slugify/tree/v4.7.1" - }, - "time": "2025-11-27T18:57:36+00:00" - }, { "name": "codeigniter4/framework", - "version": "v4.7.0", + "version": "v4.2.7", "source": { "type": "git", "url": "https://github.com/codeigniter4/framework.git", - "reference": "e7753bc03f8b74af428f46b5e2bb74925487c930" + "reference": "011ce3bbda6f85930075a9b8fecbee01c4b23ab9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/codeigniter4/framework/zipball/e7753bc03f8b74af428f46b5e2bb74925487c930", - "reference": "e7753bc03f8b74af428f46b5e2bb74925487c930", + "url": "https://api.github.com/repos/codeigniter4/framework/zipball/011ce3bbda6f85930075a9b8fecbee01c4b23ab9", + "reference": "011ce3bbda6f85930075a9b8fecbee01c4b23ab9", "shasum": "" }, "require": { + "ext-curl": "*", "ext-intl": "*", + "ext-json": "*", "ext-mbstring": "*", - "laminas/laminas-escaper": "^2.18", - "php": "^8.2", - "psr/log": "^3.0" + "kint-php/kint": "^4.2", + "laminas/laminas-escaper": "^2.9", + "php": "^7.4 || ^8.0", + "psr/log": "^1.1" }, "require-dev": { - "codeigniter/coding-standard": "^1.7", - "fakerphp/faker": "^1.24", - "friendsofphp/php-cs-fixer": "^3.47.1", - "kint-php/kint": "^6.1", - "mikey179/vfsstream": "^1.6.12", + "codeigniter/coding-standard": "^1.5", + "fakerphp/faker": "^1.9", + "friendsofphp/php-cs-fixer": "~3.11.0", + "mikey179/vfsstream": "^1.6", "nexusphp/cs-config": "^3.6", - "phpunit/phpunit": "^10.5.16 || ^11.2", - "predis/predis": "^3.0" + "phpunit/phpunit": "^9.1", + "predis/predis": "^1.1 || ^2.0" }, "suggest": { - "ext-apcu": "If you use Cache class ApcuHandler", - "ext-curl": "If you use CURLRequest class", - "ext-dom": "If you use TestResponse", - "ext-exif": "If you run Image class tests", "ext-fileinfo": "Improves mime type detection for files", - "ext-gd": "If you use Image class GDHandler", "ext-imagick": "If you use Image class ImageMagickHandler", - "ext-libxml": "If you use TestResponse", "ext-memcache": "If you use Cache class MemcachedHandler with Memcache", "ext-memcached": "If you use Cache class MemcachedHandler with Memcached", "ext-mysqli": "If you use MySQL", "ext-oci8": "If you use Oracle Database", - "ext-pcntl": "If you use Signals", "ext-pgsql": "If you use PostgreSQL", - "ext-posix": "If you use Signals", "ext-readline": "Improves CLI::input() usability", "ext-redis": "If you use Cache class RedisHandler", "ext-simplexml": "If you format XML", - "ext-sodium": "If you use Encryption SodiumHandler", "ext-sqlite3": "If you use SQLite3", - "ext-sqlsrv": "If you use SQL Server", - "ext-xdebug": "If you use CIUnitTestCase::assertHeaderEmitted()" + "ext-sqlsrv": "If you use SQL Server" }, "type": "project", "autoload": { "psr-4": { "CodeIgniter\\": "system/" }, - "exclude-from-classmap": [ - "**/Database/Migrations/**" - ] + "exclude-from-classmap": ["**/Database/Migrations/**"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "The CodeIgniter framework v4", "homepage": "https://codeigniter.com", "support": { - "forum": "https://forum.codeigniter.com/", + "forum": "http://forum.codeigniter.com/", "slack": "https://codeigniterchat.slack.com", "source": "https://github.com/codeigniter4/CodeIgniter4" }, - "time": "2026-02-01T20:39:35+00:00" - }, - { - "name": "codeigniter4/queue", - "version": "dev-develop", - "source": { - "type": "git", - "url": "https://github.com/codeigniter4/queue.git", - "reference": "b44386ad29f0a2124e59582ef5ba170788b926ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/codeigniter4/queue/zipball/b44386ad29f0a2124e59582ef5ba170788b926ed", - "reference": "b44386ad29f0a2124e59582ef5ba170788b926ed", - "shasum": "" - }, - "require": { - "php": "^8.2" - }, - "require-dev": { - "codeigniter4/devkit": "^1.3", - "codeigniter4/framework": "^4.3", - "php-amqplib/php-amqplib": "^3.7", - "phpstan/phpstan-strict-rules": "^2.0", - "predis/predis": "^2.0" - }, - "suggest": { - "ext-redis": "If you want to use RedisHandler", - "php-amqplib/php-amqplib": "If you want to use RabbitMQHandler", - "predis/predis": "If you want to use PredisHandler" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "CodeIgniter\\Queue\\": "src" - }, - "exclude-from-classmap": [ - "**/Database/Migrations/**" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "michalsn", - "homepage": "https://github.com/michalsn", - "role": "Developer" - } - ], - "description": "Queues for CodeIgniter 4 framework", - "homepage": "https://github.com/codeigniter4/queue", - "keywords": [ - "codeigniter", - "codeigniter4", - "database", - "predis", - "queue", - "redis" - ], - "support": { - "issues": "https://github.com/codeigniter4/queue/issues", - "source": "https://github.com/codeigniter4/queue/tree/develop" - }, - "time": "2026-02-15T08:22:24+00:00" + "time": "2022-10-06T13:46:23+00:00" }, { "name": "codeigniter4/settings", - "version": "v2.2.0", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/codeigniter4/settings.git", - "reference": "2748f2b4572d44a940f98c31847d65272cac5666" + "reference": "0c3fbd5a474eeb592bef5550be2a6d2f73a8a09d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/codeigniter4/settings/zipball/2748f2b4572d44a940f98c31847d65272cac5666", - "reference": "2748f2b4572d44a940f98c31847d65272cac5666", + "url": "https://api.github.com/repos/codeigniter4/settings/zipball/0c3fbd5a474eeb592bef5550be2a6d2f73a8a09d", + "reference": "0c3fbd5a474eeb592bef5550be2a6d2f73a8a09d", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" + "php": "^7.3 || ^8.0" }, "require-dev": { - "codeigniter4/devkit": "^1.1.2", - "codeigniter4/framework": "^4.2.3", - "rector/rector": "0.18.13" + "codeigniter/coding-standard": "^1.1", + "codeigniter4/codeigniter4": "dev-develop", + "fakerphp/faker": "^1.9", + "mockery/mockery": "^1.0", + "nexusphp/cs-config": "^3.1", + "nexusphp/tachycardia": "^1.0", + "php-coveralls/php-coveralls": "^2.4", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^9.0", + "squizlabs/php_codesniffer": "^3.3" }, "type": "library", "autoload": { "psr-4": { "CodeIgniter\\Settings\\": "src" }, - "exclude-from-classmap": [ - "**/Database/Migrations/**" - ] + "exclude-from-classmap": ["**/Database/Migrations/**"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Lonnie Ezell", @@ -724,221 +279,37 @@ ], "description": "Settings library for CodeIgniter 4", "homepage": "https://github.com/codeigniter4/settings", - "keywords": [ - "Settings", - "codeigniter", - "codeigniter4" - ], + "keywords": ["Settings", "codeigniter", "codeigniter4"], "support": { "issues": "https://github.com/codeigniter4/settings/issues", - "source": "https://github.com/codeigniter4/settings/tree/v2.2.0" + "source": "https://github.com/codeigniter4/settings/tree/v2.1.0" }, - "time": "2024-01-06T07:10:58+00:00" - }, - { - "name": "codeigniter4/shield", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/codeigniter4/shield.git", - "reference": "2d1b2177a914dcd490f54a6706792eacabd9e3e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/codeigniter4/shield/zipball/2d1b2177a914dcd490f54a6706792eacabd9e3e8", - "reference": "2d1b2177a914dcd490f54a6706792eacabd9e3e8", - "shasum": "" - }, - "require": { - "codeigniter4/settings": "^2.1", - "php": "^8.1" - }, - "provide": { - "codeigniter4/authentication-implementation": "1.0" - }, - "require-dev": { - "codeigniter/phpstan-codeigniter": "^1.3", - "codeigniter4/devkit": "^1.3", - "codeigniter4/framework": ">=4.3.5 <4.5.0 || ^4.5.1", - "firebase/php-jwt": "^6.4", - "mikey179/vfsstream": "^1.6.7", - "mockery/mockery": "^1.0", - "phpstan/phpstan-strict-rules": "^2.0" - }, - "suggest": { - "ext-curl": "Required to use the password validation rule via PwnedValidator class.", - "ext-openssl": "Required to use the JWT Authenticator." - }, - "type": "library", - "autoload": { - "psr-4": { - "CodeIgniter\\Shield\\": "src" - }, - "exclude-from-classmap": [ - "**/Database/Migrations/**" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Lonnie Ezell", - "email": "lonnieje@gmail.com", - "role": "Developer" - } - ], - "description": "Authentication and Authorization for CodeIgniter 4", - "homepage": "https://github.com/codeigniter4/shield", - "keywords": [ - "Authentication", - "authorization", - "codeigniter", - "codeigniter4" - ], - "support": { - "docs": "https://codeigniter4.github.io/shield/", - "forum": "https://github.com/codeigniter4/shield/discussions", - "issues": "https://github.com/codeigniter4/shield/issues", - "slack": "https://codeigniterchat.slack.com", - "source": "https://github.com/codeigniter4/shield" - }, - "time": "2025-07-14T10:26:03+00:00" - }, - { - "name": "codeigniter4/tasks", - "version": "dev-develop", - "source": { - "type": "git", - "url": "https://github.com/codeigniter4/tasks.git", - "reference": "8d0c0f83d48dd1ac322d30a4c51ff309ab5368e0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/codeigniter4/tasks/zipball/8d0c0f83d48dd1ac322d30a4c51ff309ab5368e0", - "reference": "8d0c0f83d48dd1ac322d30a4c51ff309ab5368e0", - "shasum": "" - }, - "require": { - "codeigniter4/queue": "dev-develop", - "codeigniter4/settings": "^2.0", - "ext-json": "*", - "php": "^8.2" - }, - "require-dev": { - "codeigniter4/devkit": "^1.3", - "codeigniter4/framework": "^4.3" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "CodeIgniter\\Tasks\\": "src" - }, - "exclude-from-classmap": [ - "**/Database/Migrations/**" - ] - }, - "autoload-dev": { - "psr-4": { - "Tests\\Support\\": "tests/_support" - } - }, - "scripts": { - "post-update-cmd": [ - "bash admin/setup.sh" - ], - "analyze": [ - "Composer\\Config::disableProcessTimeout", - "phpstan analyze", - "psalm", - "rector process --dry-run" - ], - "sa": [ - "@analyze" - ], - "ci": [ - "Composer\\Config::disableProcessTimeout", - "@cs", - "@deduplicate", - "@inspect", - "@analyze", - "@test" - ], - "cs": [ - "php-cs-fixer fix --ansi --verbose --dry-run --diff" - ], - "cs-fix": [ - "php-cs-fixer fix --ansi --verbose --diff" - ], - "style": [ - "@cs-fix" - ], - "deduplicate": [ - "phpcpd src/ tests/" - ], - "inspect": [ - "deptrac analyze --cache-file=build/deptrac.cache" - ], - "mutate": [ - "infection --threads=2 --skip-initial-tests --coverage=build/phpunit" - ], - "retool": [ - "retool" - ], - "test": [ - "phpunit" - ] - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Lonnie Ezell", - "email": "lonnieje@gmail.com", - "role": "Developer" - } - ], - "description": "Task Scheduler for CodeIgniter 4", - "homepage": "https://github.com/codeigniter4/tasks", - "keywords": [ - "codeigniter", - "codeigniter4", - "cron", - "task scheduling" - ], - "support": { - "source": "https://github.com/codeigniter4/tasks/tree/develop", - "issues": "https://github.com/codeigniter4/tasks/issues" - }, - "time": "2026-02-15T08:22:03+00:00" + "time": "2021-11-22T17:30:18+00:00" }, { "name": "composer/ca-bundle", - "version": "1.5.10", + "version": "1.3.4", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63" + "reference": "69098eca243998b53eed7a48d82dedd28b447cd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/961a5e4056dd2e4a2eedcac7576075947c28bf63", - "reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/69098eca243998b53eed7a48d82dedd28b447cd5", + "reference": "69098eca243998b53eed7a48d82dedd28b447cd5", "shasum": "" }, "require": { "ext-openssl": "*", "ext-pcre": "*", - "php": "^7.2 || ^8.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8 || ^9", - "psr/log": "^1.0 || ^2.0 || ^3.0", - "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "phpstan/phpstan": "^0.12.55", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.2 || ^5", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" }, "type": "library", "extra": { @@ -952,9 +323,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jordi Boggiano", @@ -963,17 +332,11 @@ } ], "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], + "keywords": ["cabundle", "cacert", "certificate", "ssl", "tls"], "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.10" + "source": "https://github.com/composer/ca-bundle/tree/1.3.4" }, "funding": [ { @@ -983,22 +346,26 @@ { "url": "https://github.com/composer", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" } ], - "time": "2025-12-08T15:06:51+00:00" + "time": "2022-10-12T12:08:29+00:00" }, { "name": "dflydev/dot-access-data", - "version": "v3.0.3", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/dflydev/dflydev-dot-access-data.git", - "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + "reference": "0992cc19268b259a39e86f296da5f0677841f42c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", - "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/0992cc19268b259a39e86f296da5f0677841f42c", + "reference": "0992cc19268b259a39e86f296da5f0677841f42c", "shasum": "" }, "require": { @@ -1009,7 +376,7 @@ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", "scrutinizer/ocular": "1.6.0", "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.0.0" + "vimeo/psalm": "^3.14" }, "type": "library", "extra": { @@ -1023,9 +390,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Dragonfly Development Inc.", @@ -1050,43 +415,212 @@ ], "description": "Given a deep data structure, access data by dot notation.", "homepage": "https://github.com/dflydev/dflydev-dot-access-data", - "keywords": [ - "access", - "data", - "dot", - "notation" - ], + "keywords": ["access", "data", "dot", "notation"], "support": { "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", - "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.1" }, - "time": "2024-07-08T12:26:09+00:00" + "time": "2021-08-13T13:06:58+00:00" }, { - "name": "geoip2/geoip2", - "version": "v3.3.0", + "name": "essence/dom", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/maxmind/GeoIP2-php.git", - "reference": "49fceddd694295e76e970a32848e03bb19e56b42" + "url": "https://github.com/essence/dom.git", + "reference": "e5776d2286f4ccbd048d160c28ac77ccc6d68f3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/49fceddd694295e76e970a32848e03bb19e56b42", - "reference": "49fceddd694295e76e970a32848e03bb19e56b42", + "url": "https://api.github.com/repos/essence/dom/zipball/e5776d2286f4ccbd048d160c28ac77ccc6d68f3a", + "reference": "e5776d2286f4ccbd048d160c28ac77ccc6d68f3a", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Essence\\Dom\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Félix Girault", + "email": "felix.girault@gmail.com", + "homepage": "http://www.felix-girault.fr", + "role": "Developer" + } + ], + "description": "Essence's DOM parser.", + "homepage": "http://github.com/essence/dom", + "keywords": ["dom", "parser"], + "support": { + "issues": "https://github.com/essence/dom/issues", + "source": "https://github.com/essence/dom/tree/1.0.0" + }, + "time": "2015-07-23T20:33:17+00:00" + }, + { + "name": "essence/essence", + "version": "3.5.4", + "source": { + "type": "git", + "url": "https://github.com/essence/essence.git", + "reference": "81e889a87603840dadd04b317a51487df1d45933" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/essence/essence/zipball/81e889a87603840dadd04b317a51487df1d45933", + "reference": "81e889a87603840dadd04b317a51487df1d45933", + "shasum": "" + }, + "require": { + "essence/dom": "~1.0.0", + "essence/http": "~1.0.0", + "fg/parkour": "~1.1.0", + "php": ">=5.5.0" + }, + "suggest": { + "ext-curl": "*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Essence\\": "lib/Essence" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-2-Clause"], + "authors": [ + { + "name": "Félix Girault", + "email": "felix.girault@gmail.com", + "homepage": "http://www.felix-girault.fr", + "role": "Developer" + } + ], + "description": "Extracts information about medias on the web, like youtube videos, twitter statuses or blog articles.", + "homepage": "http://github.com/essence/essence", + "keywords": ["embed", "media", "oembed", "opengraph"], + "support": { + "issues": "https://github.com/essence/essence/issues", + "source": "https://github.com/essence/essence/tree/3.5.4" + }, + "time": "2021-01-21T09:58:10+00:00" + }, + { + "name": "essence/http", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/essence/http.git", + "reference": "ce0e52e0c0f2ed894ce2922ab2fd598dcaac91d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/essence/http/zipball/ce0e52e0c0f2ed894ce2922ab2fd598dcaac91d2", + "reference": "ce0e52e0c0f2ed894ce2922ab2fd598dcaac91d2", + "shasum": "" + }, + "suggest": { + "ext-curl": "*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Essence\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Félix Girault", + "email": "felix.girault@gmail.com", + "homepage": "http://www.felix-girault.fr", + "role": "Developer" + } + ], + "description": "Essence's HTTP client.", + "homepage": "http://github.com/essence/http", + "keywords": ["client", "http"], + "support": { + "issues": "https://github.com/essence/http/issues", + "source": "https://github.com/essence/http/tree/1.0.0" + }, + "time": "2015-07-23T20:33:50+00:00" + }, + { + "name": "fg/parkour", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/felixgirault/parkour.git", + "reference": "f837eb640fc4aac81b11fe50d2fa04fb4ec71496" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixgirault/parkour/zipball/f837eb640fc4aac81b11fe50d2fa04fb4ec71496", + "reference": "f837eb640fc4aac81b11fe50d2fa04fb4ec71496", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "4.3.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Parkour\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-2-Clause"], + "authors": [ + { + "name": "Félix Girault", + "email": "felix.girault@gmail.com", + "homepage": "http://www.felix-girault.fr", + "role": "Developer" + } + ], + "description": "A collection of utilities to manipulate arrays.", + "homepage": "http://github.com/felixgirault/parkour", + "keywords": ["array", "manipulation", "traversing"], + "support": { + "issues": "https://github.com/felixgirault/parkour/issues", + "source": "https://github.com/felixgirault/parkour/tree/1.1.1" + }, + "time": "2015-10-03T10:39:22+00:00" + }, + { + "name": "geoip2/geoip2", + "version": "v2.13.0", + "source": { + "type": "git", + "url": "git@github.com:maxmind/GeoIP2-php.git", + "reference": "6a41d8fbd6b90052bc34dff3b4252d0f88067b23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/6a41d8fbd6b90052bc34dff3b4252d0f88067b23", + "reference": "6a41d8fbd6b90052bc34dff3b4252d0f88067b23", "shasum": "" }, "require": { "ext-json": "*", - "maxmind-db/reader": "^1.13.0", - "maxmind/web-service-common": "~0.11", - "php": ">=8.1" + "maxmind-db/reader": "~1.8", + "maxmind/web-service-common": "~0.8", + "php": ">=7.2" }, "require-dev": { "friendsofphp/php-cs-fixer": "3.*", "phpstan/phpstan": "*", - "phpunit/phpunit": "^10.0", - "squizlabs/php_codesniffer": "4.*" + "phpunit/phpunit": "^8.0 || ^9.0", + "squizlabs/php_codesniffer": "3.*" }, "type": "library", "autoload": { @@ -1095,9 +629,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "Gregory J. Oschwald", @@ -1107,39 +639,29 @@ ], "description": "MaxMind GeoIP2 PHP API", "homepage": "https://github.com/maxmind/GeoIP2-php", - "keywords": [ - "IP", - "geoip", - "geoip2", - "geolocation", - "maxmind" - ], - "support": { - "issues": "https://github.com/maxmind/GeoIP2-php/issues", - "source": "https://github.com/maxmind/GeoIP2-php/tree/v3.3.0" - }, - "time": "2025-11-20T18:50:15+00:00" + "keywords": ["IP", "geoip", "geoip2", "geolocation", "maxmind"], + "time": "2022-08-05T20:32:58+00:00" }, { "name": "graham-campbell/result-type", - "version": "v1.1.4", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b" + "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b", - "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/a878d45c1914464426dc94da61c9e1d36ae262a8", + "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.5" + "phpoption/phpoption": "^1.9" }, "require-dev": { - "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7" + "phpunit/phpunit": "^8.5.28 || ^9.5.21" }, "type": "library", "autoload": { @@ -1148,9 +670,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Graham Campbell", @@ -1168,7 +688,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.0" }, "funding": [ { @@ -1180,345 +700,20 @@ "type": "tidelift" } ], - "time": "2025-12-27T19:43:20+00:00" - }, - { - "name": "guzzlehttp/guzzle", - "version": "7.10.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", - "shasum": "" - }, - "require": { - "ext-json": "*", - "guzzlehttp/promises": "^2.3", - "guzzlehttp/psr7": "^2.8", - "php": "^7.2.5 || ^8.0", - "psr/http-client": "^1.0", - "symfony/deprecation-contracts": "^2.2 || ^3.0" - }, - "provide": { - "psr/http-client-implementation": "1.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "ext-curl": "*", - "guzzle/client-integration-tests": "3.0.2", - "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.39 || ^9.6.20", - "psr/log": "^1.1 || ^2.0 || ^3.0" - }, - "suggest": { - "ext-curl": "Required for CURL handler support", - "ext-intl": "Required for Internationalized Domain Name (IDN) support", - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Jeremy Lindblom", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "psr-18", - "psr-7", - "rest", - "web service" - ], - "support": { - "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.10.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", - "type": "tidelift" - } - ], - "time": "2025-08-23T22:36:01+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "2.3.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "481557b130ef3790cf82b713667b43030dc9c957" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", - "reference": "481557b130ef3790cf82b713667b43030dc9c957", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "support": { - "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.3.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", - "type": "tidelift" - } - ], - "time": "2025-08-22T14:34:08+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "2.8.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0", - "ralouphie/getallheaders": "^3.0" - }, - "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" - }, - "suggest": { - "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://sagikazarmark.hu" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "support": { - "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.8.0" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", - "type": "tidelift" - } - ], - "time": "2025-08-23T21:21:41+00:00" + "time": "2022-07-30T15:56:11+00:00" }, { "name": "james-heinrich/getid3", - "version": "v2.0.0-beta6", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/JamesHeinrich/getID3.git", - "reference": "8bf46222ae008d870e6676b4bf455ed664d90d05" + "reference": "ee238d552571c6029898b087d5fc95df826418d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/8bf46222ae008d870e6676b4bf455ed664d90d05", - "reference": "8bf46222ae008d870e6676b4bf455ed664d90d05", + "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/ee238d552571c6029898b087d5fc95df826418d6", + "reference": "ee238d552571c6029898b087d5fc95df826418d6", "shasum": "" }, "require": { @@ -1557,11 +752,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-1.0-or-later", - "LGPL-3.0-only", - "MPL-2.0" - ], + "license": ["GPL-1.0-or-later", "LGPL-3.0-only", "MPL-2.0"], "authors": [ { "name": "James Heinrich", @@ -1578,48 +769,99 @@ ], "description": "Extract and write useful information to/from popular multimedia file formats", "homepage": "https://www.getid3.org/", - "keywords": [ - "audio", - "codecs", - "id3", - "metadata", - "tags", - "video" - ], + "keywords": ["audio", "codecs", "id3", "metadata", "tags", "video"], "support": { "issues": "https://github.com/JamesHeinrich/getID3/issues", - "source": "https://github.com/JamesHeinrich/getID3/tree/v2.0.0-beta6" + "source": "https://github.com/JamesHeinrich/getID3/tree/2.0" }, - "time": "2023-11-02T19:40:57+00:00" + "time": "2021-12-15T17:29:14+00:00" }, { - "name": "laminas/laminas-escaper", - "version": "2.18.0", + "name": "kint-php/kint", + "version": "4.2.3", "source": { "type": "git", - "url": "https://github.com/laminas/laminas-escaper.git", - "reference": "06f211dfffff18d91844c1f55250d5d13c007e18" + "url": "https://github.com/kint-php/kint.git", + "reference": "7601bfd95ccc50a1b903c2764b31d00919e8edd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/06f211dfffff18d91844c1f55250d5d13c007e18", - "reference": "06f211dfffff18d91844c1f55250d5d13c007e18", + "url": "https://api.github.com/repos/kint-php/kint/zipball/7601bfd95ccc50a1b903c2764b31d00919e8edd9", + "reference": "7601bfd95ccc50a1b903c2764b31d00919e8edd9", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.0", + "phpspec/prophecy-phpunit": "^2", + "phpunit/phpunit": "^9.0", + "seld/phar-utils": "^1.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "vimeo/psalm": "^4.0" + }, + "suggest": { + "kint-php/kint-helpers": "Provides extra helper functions", + "kint-php/kint-twig": "Provides d() and s() functions in twig templates" + }, + "type": "library", + "autoload": { + "files": ["init.php"], + "psr-4": { + "Kint\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Jonathan Vollebregt", + "homepage": "https://github.com/jnvsor" + }, + { + "name": "Contributors", + "homepage": "https://github.com/kint-php/kint/graphs/contributors" + } + ], + "description": "Kint - debugging tool for PHP developers", + "homepage": "https://kint-php.github.io/kint/", + "keywords": ["debug", "kint", "php"], + "support": { + "issues": "https://github.com/kint-php/kint/issues", + "source": "https://github.com/kint-php/kint/tree/4.2.3" + }, + "time": "2022-10-01T20:16:33+00:00" + }, + { + "name": "laminas/laminas-escaper", + "version": "2.12.0", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-escaper.git", + "reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490", + "reference": "ee7a4c37bf3d0e8c03635d5bddb5bb3184ead490", "shasum": "" }, "require": { "ext-ctype": "*", "ext-mbstring": "*", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0" }, "conflict": { "zendframework/zend-escaper": "*" }, "require-dev": { - "infection/infection": "^0.31.0", - "laminas/laminas-coding-standard": "~3.1.0", - "phpunit/phpunit": "^11.5.42", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13.1" + "infection/infection": "^0.26.6", + "laminas/laminas-coding-standard": "~2.4.0", + "maglnet/composer-require-checker": "^3.8.0", + "phpunit/phpunit": "^9.5.18", + "psalm/plugin-phpunit": "^0.17.0", + "vimeo/psalm": "^4.22.0" }, "type": "library", "autoload": { @@ -1628,15 +870,10 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", "homepage": "https://laminas.dev", - "keywords": [ - "escaper", - "laminas" - ], + "keywords": ["escaper", "laminas"], "support": { "chat": "https://laminas.dev/chat", "docs": "https://docs.laminas.dev/laminas-escaper/", @@ -1651,20 +888,20 @@ "type": "community_bridge" } ], - "time": "2025-10-14T18:31:13+00:00" + "time": "2022-10-10T10:11:09+00:00" }, { "name": "league/commonmark", - "version": "2.8.0", + "version": "2.3.5", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" + "reference": "84d74485fdb7074f4f9dd6f02ab957b1de513257" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/84d74485fdb7074f4f9dd6f02ab957b1de513257", + "reference": "84d74485fdb7074f4f9dd6f02ab957b1de513257", "shasum": "" }, "require": { @@ -1677,23 +914,22 @@ }, "require-dev": { "cebe/markdown": "^1.0", - "commonmark/cmark": "0.31.1", - "commonmark/commonmark.js": "0.31.1", + "commonmark/cmark": "0.30.0", + "commonmark/commonmark.js": "0.30.0", "composer/package-versions-deprecated": "^1.8", "embed/embed": "^4.4", "erusev/parsedown": "^1.0", "ext-json": "*", "github/gfm": "0.29.0", - "michelf/php-markdown": "^1.4 || ^2.0", + "michelf/php-markdown": "^1.4", "nyholm/psr7": "^1.5", "phpstan/phpstan": "^1.8.2", - "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "phpunit/phpunit": "^9.5.21", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 | ^7.0", - "symfony/process": "^5.4 | ^6.0 | ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "symfony/finder": "^5.3 | ^6.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0", "unleashedtech/php-coding-standard": "^3.1.1", - "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" + "vimeo/psalm": "^4.24.0" }, "suggest": { "symfony/yaml": "v2.3+ required if using the Front Matter extension" @@ -1701,7 +937,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.9-dev" + "dev-main": "2.4-dev" } }, "autoload": { @@ -1710,9 +946,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Colin O'Dell", @@ -1758,20 +992,20 @@ "type": "tidelift" } ], - "time": "2025-11-26T21:48:24+00:00" + "time": "2022-07-29T10:59:45+00:00" }, { "name": "league/config", - "version": "v1.2.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/thephpleague/config.git", - "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + "reference": "a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", - "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "url": "https://api.github.com/repos/thephpleague/config/zipball/a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e", + "reference": "a9d39eeeb6cc49d10a6e6c36f22c4c1f4a767f3e", "shasum": "" }, "require": { @@ -1780,7 +1014,7 @@ "php": "^7.4 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.8.2", + "phpstan/phpstan": "^0.12.90", "phpunit/phpunit": "^9.5.5", "scrutinizer/ocular": "^1.8.1", "unleashedtech/php-coding-standard": "^3.1", @@ -1798,9 +1032,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Colin O'Dell", @@ -1840,20 +1072,20 @@ "type": "github" } ], - "time": "2022-12-11T20:36:23+00:00" + "time": "2021-08-14T12:15:32+00:00" }, { "name": "league/html-to-markdown", - "version": "5.1.1", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/thephpleague/html-to-markdown.git", - "reference": "0b4066eede55c48f38bcee4fb8f0aa85654390fd" + "reference": "e0fc8cf07bdabbcd3765341ecb50c34c271d64e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/0b4066eede55c48f38bcee4fb8f0aa85654390fd", - "reference": "0b4066eede55c48f38bcee4fb8f0aa85654390fd", + "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/e0fc8cf07bdabbcd3765341ecb50c34c271d64e1", + "reference": "e0fc8cf07bdabbcd3765341ecb50c34c271d64e1", "shasum": "" }, "require": { @@ -1863,15 +1095,13 @@ }, "require-dev": { "mikehaertl/php-shellcommand": "^1.1.0", - "phpstan/phpstan": "^1.8.8", + "phpstan/phpstan": "^0.12.99", "phpunit/phpunit": "^8.5 || ^9.2", "scrutinizer/ocular": "^1.6", - "unleashedtech/php-coding-standard": "^2.7 || ^3.0", - "vimeo/psalm": "^4.22 || ^5.0" + "unleashedtech/php-coding-standard": "^2.7", + "vimeo/psalm": "^4.22" }, - "bin": [ - "bin/html-to-markdown" - ], + "bin": ["bin/html-to-markdown"], "type": "library", "extra": { "branch-alias": { @@ -1884,9 +1114,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Colin O'Dell", @@ -1903,13 +1131,10 @@ ], "description": "An HTML-to-markdown conversion helper for PHP", "homepage": "https://github.com/thephpleague/html-to-markdown", - "keywords": [ - "html", - "markdown" - ], + "keywords": ["html", "markdown"], "support": { "issues": "https://github.com/thephpleague/html-to-markdown/issues", - "source": "https://github.com/thephpleague/html-to-markdown/tree/5.1.1" + "source": "https://github.com/thephpleague/html-to-markdown/tree/5.1.0" }, "funding": [ { @@ -1929,39 +1154,40 @@ "type": "tidelift" } ], - "time": "2023-07-12T21:21:09+00:00" + "time": "2022-03-02T17:24:08+00:00" }, { "name": "maxmind-db/reader", - "version": "v1.13.1", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", - "reference": "2194f58d0f024ce923e685cdf92af3daf9951908" + "reference": "b1f3c0699525336d09cc5161a2861268d9f2ae5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/2194f58d0f024ce923e685cdf92af3daf9951908", - "reference": "2194f58d0f024ce923e685cdf92af3daf9951908", + "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/b1f3c0699525336d09cc5161a2861268d9f2ae5b", + "reference": "b1f3c0699525336d09cc5161a2861268d9f2ae5b", "shasum": "" }, "require": { "php": ">=7.2" }, "conflict": { - "ext-maxminddb": "<1.11.1 || >=2.0.0" + "ext-maxminddb": "<1.10.1,>=2.0.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "3.*", + "php-coveralls/php-coveralls": "^2.1", "phpstan/phpstan": "*", + "phpunit/phpcov": ">=6.0.0", "phpunit/phpunit": ">=8.0.0,<10.0.0", - "squizlabs/php_codesniffer": "4.*" + "squizlabs/php_codesniffer": "3.*" }, "suggest": { "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", - "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups", - "maxmind-db/reader-ext": "C extension for significantly faster IP lookups (install via PIE: pie install maxmind-db/reader-ext)" + "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups" }, "type": "library", "autoload": { @@ -1970,9 +1196,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "Gregory J. Oschwald", @@ -1982,44 +1206,38 @@ ], "description": "MaxMind DB Reader API", "homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php", - "keywords": [ - "database", - "geoip", - "geoip2", - "geolocation", - "maxmind" - ], + "keywords": ["database", "geoip", "geoip2", "geolocation", "maxmind"], "support": { "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", - "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.13.1" + "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.11.0" }, - "time": "2025-11-21T22:24:26+00:00" + "time": "2021-10-18T15:23:10+00:00" }, { "name": "maxmind/web-service-common", - "version": "v0.11.1", + "version": "v0.9.0", "source": { "type": "git", "url": "https://github.com/maxmind/web-service-common-php.git", - "reference": "c309236b5a5555b96cf560089ec3cead12d845d2" + "reference": "4dc5a3e8df38aea4ca3b1096cee3a038094e9b53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/c309236b5a5555b96cf560089ec3cead12d845d2", - "reference": "c309236b5a5555b96cf560089ec3cead12d845d2", + "url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/4dc5a3e8df38aea4ca3b1096cee3a038094e9b53", + "reference": "4dc5a3e8df38aea4ca3b1096cee3a038094e9b53", "shasum": "" }, "require": { "composer/ca-bundle": "^1.0.3", "ext-curl": "*", "ext-json": "*", - "php": ">=8.1" + "php": ">=7.2" }, "require-dev": { "friendsofphp/php-cs-fixer": "3.*", "phpstan/phpstan": "*", - "phpunit/phpunit": "^10.0", - "squizlabs/php_codesniffer": "4.*" + "phpunit/phpunit": "^8.0 || ^9.0", + "squizlabs/php_codesniffer": "3.*" }, "type": "library", "autoload": { @@ -2029,9 +1247,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "Gregory Oschwald", @@ -2042,32 +1258,32 @@ "homepage": "https://github.com/maxmind/web-service-common-php", "support": { "issues": "https://github.com/maxmind/web-service-common-php/issues", - "source": "https://github.com/maxmind/web-service-common-php/tree/v0.11.1" + "source": "https://github.com/maxmind/web-service-common-php/tree/v0.9.0" }, - "time": "2026-01-13T17:56:03+00:00" + "time": "2022-03-28T17:43:20+00:00" }, { "name": "melbahja/seo", - "version": "v3.0.2", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/melbahja/seo.git", - "reference": "e8d36b2c46e1b05af957c90beea19090f64d5bf9" + "reference": "22b0b3273bf9c8867cadf018e4daa3e426525929" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/melbahja/seo/zipball/e8d36b2c46e1b05af957c90beea19090f64d5bf9", - "reference": "e8d36b2c46e1b05af957c90beea19090f64d5bf9", + "url": "https://api.github.com/repos/melbahja/seo/zipball/22b0b3273bf9c8867cadf018e4daa3e426525929", + "reference": "22b0b3273bf9c8867cadf018e4daa3e426525929", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-xml": "*", - "php": ">=8.1" + "php": ">=7.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^8.5" }, "type": "library", "autoload": { @@ -2076,9 +1292,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Mohamed ELbahja", @@ -2087,53 +1301,48 @@ "role": "Developer" } ], - "description": "SEO library for PHP is a simple PHP library to help developers 🍻 do better on-page SEO optimizations.", + "description": "Simple PHP library to help developers 🍻 do better on-page SEO optimization", "keywords": [ - "images sitemaps", - "index sitemaps", + "PHP7", "meta tags", - "news sitemaps", "open graph", - "php8", - "rich results", "schema.org", "search engine optimization", "seo", "sitemap index", "sitemap.xml", "sitemaps", - "twitter tags", - "video sitemaps" + "twitter tags" ], "support": { "issues": "https://github.com/melbahja/seo/issues", - "source": "https://github.com/melbahja/seo/tree/v3.0.2" + "source": "https://github.com/melbahja/seo/tree/v2.1.1" }, - "time": "2026-02-08T12:48:54+00:00" + "time": "2022-09-11T11:16:07+00:00" }, { "name": "michalsn/codeigniter4-uuid", - "version": "v1.3.1", + "version": "dev-develop", "source": { "type": "git", "url": "https://github.com/michalsn/codeigniter4-uuid.git", - "reference": "31457ec91f54e3c981762d9f06e87e417869c380" + "reference": "b26512ac4f3f0c772fbfa2c3317346d3c17e2d44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/michalsn/codeigniter4-uuid/zipball/31457ec91f54e3c981762d9f06e87e417869c380", - "reference": "31457ec91f54e3c981762d9f06e87e417869c380", + "url": "https://api.github.com/repos/michalsn/codeigniter4-uuid/zipball/b26512ac4f3f0c772fbfa2c3317346d3c17e2d44", + "reference": "b26512ac4f3f0c772fbfa2c3317346d3c17e2d44", "shasum": "" }, "require": { - "ext-ctype": "*", - "php": ">=8.1", - "ramsey/uuid": "^4.7" + "php": ">=7.3", + "ramsey/uuid": "^4.0" }, "require-dev": { "codeigniter4/codeigniter4": "dev-develop", "phpunit/phpunit": "8.5.*" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -2141,9 +1350,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "michalsn", @@ -2153,198 +1360,114 @@ ], "description": "UUID package for CodeIgniter 4 with support for Model and Entity.", "homepage": "https://github.com/michalsn/codeigniter4-uuid", - "keywords": [ - "codeigniter4", - "entity", - "model", - "uuid" - ], + "keywords": ["codeigniter4", "entity", "model", "uuid"], "support": { "issues": "https://github.com/michalsn/codeigniter4-uuid/issues", - "source": "https://github.com/michalsn/codeigniter4-uuid/tree/v1.3.1" + "source": "https://github.com/michalsn/codeigniter4-uuid/tree/develop" }, - "time": "2025-10-16T10:20:23+00:00" + "time": "2021-05-10T16:28:01+00:00" }, { - "name": "mpratt/embera", - "version": "2.0.42", + "name": "myth/auth", + "version": "dev-develop", "source": { "type": "git", - "url": "https://github.com/mpratt/Embera.git", - "reference": "afa728339c6f078c803c9277a5054ca241b3c469" + "url": "https://github.com/lonnieezell/myth-auth.git", + "reference": "cc94231f5284e9578967aba4796f018809669c84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpratt/Embera/zipball/afa728339c6f078c803c9277a5054ca241b3c469", - "reference": "afa728339c6f078c803c9277a5054ca241b3c469", + "url": "https://api.github.com/repos/lonnieezell/myth-auth/zipball/cc94231f5284e9578967aba4796f018809669c84", + "reference": "cc94231f5284e9578967aba4796f018809669c84", "shasum": "" }, "require": { - "ext-json": "*", - "php": ">=5.6" + "php": "^7.4 || ^8.0" + }, + "provide": { + "codeigniter4/authentication-implementation": "1.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^9.0||^10.0", - "symfony/yaml": "^2.1" - }, - "suggest": { - "ext-curl": "Fetch data using curl instead of using file_get_contents" + "codeigniter4/codeigniter4-standard": "^1.0", + "codeigniter4/devkit": "^1.0", + "codeigniter4/framework": "^4.1", + "mockery/mockery": "^1.0" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { - "Embera\\": "src/Embera" - } + "Myth\\Auth\\": "src" + }, + "exclude-from-classmap": ["**/Database/Migrations/**"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { - "name": "Michael Pratt", - "email": "yo@michael-pratt.com", - "homepage": "http://www.michael-pratt.com", - "role": "Author/Developer" + "name": "Lonnie Ezell", + "email": "lonnieje@gmail.com", + "homepage": "http://newmythmedia.com", + "role": "Developer" } ], - "description": "Oembed consumer library. Converts urls into their html embed code. Supports 150+ sites, such as Youtube, Twitter, vimeo, Instagram etc.", - "homepage": "https://github.com/mpratt/Embera", - "keywords": [ - "Auto embed", - "Embed Text", - "Responsive Embeds", - "Url Embed", - "embed", - "instagram", - "oembed", - "twitter", - "vimeo", - "vine", - "youtube" - ], + "description": "Flexible authentication/authorization system for CodeIgniter 4.", + "homepage": "https://github.com/lonnieezell/myth-auth", + "keywords": ["Authentication", "authorization", "codeigniter"], "support": { - "issues": "https://github.com/mpratt/Embera/issues", - "source": "https://github.com/mpratt/Embera/tree/2.0.42" + "issues": "https://github.com/lonnieezell/myth-auth/issues", + "source": "https://github.com/lonnieezell/myth-auth/tree/develop" }, "funding": [ { - "url": "https://paypal.me/mtpratt", - "type": "paypal" - } - ], - "time": "2025-01-04T06:07:59+00:00" - }, - { - "name": "mtdowling/jmespath.php", - "version": "2.8.0", - "source": { - "type": "git", - "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", - "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0", - "symfony/polyfill-mbstring": "^1.17" - }, - "require-dev": { - "composer/xdebug-handler": "^3.0.3", - "phpunit/phpunit": "^8.5.33" - }, - "bin": [ - "bin/jp.php" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "files": [ - "src/JmesPath.php" - ], - "psr-4": { - "JmesPath\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" + "url": "https://github.com/lonnieezell", + "type": "github" }, { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "url": "https://github.com/mgatner", + "type": "github" + }, + { + "url": "https://www.patreon.com/lonnieezell", + "type": "patreon" } ], - "description": "Declaratively specify how to extract elements from a JSON document", - "keywords": [ - "json", - "jsonpath" - ], - "support": { - "issues": "https://github.com/jmespath/jmespath.php/issues", - "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" - }, - "time": "2024-09-04T18:46:31+00:00" + "time": "2022-08-01T17:23:52+00:00" }, { "name": "nette/schema", - "version": "v1.3.4", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "086497a2f34b82fede9b5a41cc8e131d087cd8f7" + "reference": "9a39cef03a5b34c7de64f551538cbba05c2be5df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/086497a2f34b82fede9b5a41cc8e131d087cd8f7", - "reference": "086497a2f34b82fede9b5a41cc8e131d087cd8f7", + "url": "https://api.github.com/repos/nette/schema/zipball/9a39cef03a5b34c7de64f551538cbba05c2be5df", + "reference": "9a39cef03a5b34c7de64f551538cbba05c2be5df", "shasum": "" }, "require": { - "nette/utils": "^4.0", - "php": "8.1 - 8.5" + "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", + "php": ">=7.1 <8.2" }, "require-dev": { - "nette/tester": "^2.6", - "phpstan/phpstan": "^2.0@stable", - "tracy/tracy": "^2.8" + "nette/tester": "^2.3 || ^2.4", + "phpstan/phpstan-nette": "^0.12", + "tracy/tracy": "^2.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.2-dev" } }, "autoload": { - "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], + "license": ["BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"], "authors": [ { "name": "David Grudl", @@ -2357,44 +1480,37 @@ ], "description": "📐 Nette Schema: validating data structures against a given Schema.", "homepage": "https://nette.org", - "keywords": [ - "config", - "nette" - ], + "keywords": ["config", "nette"], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.4" + "source": "https://github.com/nette/schema/tree/v1.2.2" }, - "time": "2026-02-08T02:54:00+00:00" + "time": "2021-10-15T11:40:02+00:00" }, { "name": "nette/utils", - "version": "v4.1.3", + "version": "v3.2.8", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "bb3ea637e3d131d72acc033cfc2746ee893349fe" + "reference": "02a54c4c872b99e4ec05c4aec54b5a06eb0f6368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/bb3ea637e3d131d72acc033cfc2746ee893349fe", - "reference": "bb3ea637e3d131d72acc033cfc2746ee893349fe", + "url": "https://api.github.com/repos/nette/utils/zipball/02a54c4c872b99e4ec05c4aec54b5a06eb0f6368", + "reference": "02a54c4c872b99e4ec05c4aec54b5a06eb0f6368", "shasum": "" }, "require": { - "php": "8.2 - 8.5" + "php": ">=7.2 <8.3" }, "conflict": { - "nette/finder": "<3", - "nette/schema": "<1.2.2" + "nette/di": "<3.0.6" }, "require-dev": { - "jetbrains/phpstorm-attributes": "^1.2", - "nette/phpstan-rules": "^1.0", - "nette/tester": "^2.5", - "phpstan/extension-installer": "^1.4@stable", - "phpstan/phpstan": "^2.1@stable", - "tracy/tracy": "^2.9" + "nette/tester": "~2.0", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.3" }, "suggest": { "ext-gd": "to use Image", @@ -2402,28 +1518,20 @@ "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", "ext-json": "to use Nette\\Utils\\Json", "ext-mbstring": "to use Strings::lower() etc...", - "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "psr-4": { - "Nette\\": "src" - }, - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], + "license": ["BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"], "authors": [ { "name": "David Grudl", @@ -2454,76 +1562,72 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.3" + "source": "https://github.com/nette/utils/tree/v3.2.8" }, - "time": "2026-02-13T03:05:33+00:00" + "time": "2022-09-12T23:36:20+00:00" }, { - "name": "opawg/user-agents-v2-php", - "version": "dev-main", + "name": "opawg/user-agents-php", + "version": "v1.0", "source": { "type": "git", - "url": "https://github.com/opawg/user-agents-v2-php.git", - "reference": "1b7646bc6e82501c99466fcdef23700604966b97" + "url": "https://github.com/opawg/user-agents-php.git", + "reference": "e22c7be05f475b44d0e6ecd76acf1617a2efef85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opawg/user-agents-v2-php/zipball/1b7646bc6e82501c99466fcdef23700604966b97", - "reference": "1b7646bc6e82501c99466fcdef23700604966b97", + "url": "https://api.github.com/repos/opawg/user-agents-php/zipball/e22c7be05f475b44d0e6ecd76acf1617a2efef85", + "reference": "e22c7be05f475b44d0e6ecd76acf1617a2efef85", "shasum": "" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { - "Opawg\\UserAgentsV2Php\\": "src/" + "Opawg\\UserAgentsPhp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Benjamin Bellamy", - "email": "benjamin@castopod.org", - "homepage": "https://castopod.org/" + "email": "ben@podlibre.org", + "homepage": "https://podlibre.org/" } ], - "description": "PHP implementation for opawg/user-agents-v2.", - "homepage": "https://github.com/opawg/user-agents-v2-php", + "description": "PHP implementation for opawg/user-agents.", + "homepage": "https://github.com/opawg/user-agents-php", "support": { - "issues": "https://github.com/opawg/user-agents-v2-php/issues", - "source": "https://github.com/opawg/user-agents-v2-php/tree/main" + "source": "https://github.com/opawg/user-agents-php/tree/v1.0" }, - "time": "2023-12-20T16:54:44+00:00" + "time": "2020-11-28T10:54:05+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.5", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "75365b91986c2405cf5e1e012c5595cd487a98be" + "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be", - "reference": "75365b91986c2405cf5e1e012c5595cd487a98be", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dc5ff11e274a90cc1c743f66c9ad700ce50db9ab", + "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" + "bamarni/composer-bin-plugin": "^1.8", + "phpunit/phpunit": "^8.5.28 || ^9.5.21" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": false + "forward-command": true }, "branch-alias": { "dev-master": "1.9-dev" @@ -2535,9 +1639,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], + "license": ["Apache-2.0"], "authors": [ { "name": "Johannes M. Schmitt", @@ -2551,15 +1653,10 @@ } ], "description": "Option Type for PHP", - "keywords": [ - "language", - "option", - "php", - "type" - ], + "keywords": ["language", "option", "php", "type"], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.5" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.0" }, "funding": [ { @@ -2571,20 +1668,20 @@ "type": "tidelift" } ], - "time": "2025-12-27T19:41:33+00:00" + "time": "2022-07-30T15:51:26+00:00" }, { "name": "phpseclib/phpseclib", - "version": "2.0.51", + "version": "2.0.38", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "ed661e7cdaeb8c419e609e2f3203551a13c2ed48" + "reference": "b03536539f43a4f9aa33c4f0b2f3a1c752088fcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/ed661e7cdaeb8c419e609e2f3203551a13c2ed48", - "reference": "ed661e7cdaeb8c419e609e2f3203551a13c2ed48", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/b03536539f43a4f9aa33c4f0b2f3a1c752088fcd", + "reference": "b03536539f43a4f9aa33c4f0b2f3a1c752088fcd", "shasum": "" }, "require": { @@ -2604,17 +1701,13 @@ }, "type": "library", "autoload": { - "files": [ - "phpseclib/bootstrap.php" - ], + "files": ["phpseclib/bootstrap.php"], "psr-4": { "phpseclib\\": "phpseclib/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jim Wigginton", @@ -2665,7 +1758,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/2.0.51" + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.38" }, "funding": [ { @@ -2681,7 +1774,7 @@ "type": "tidelift" } ], - "time": "2026-01-27T09:11:52+00:00" + "time": "2022-09-02T17:04:26+00:00" }, { "name": "psr/cache", @@ -2712,9 +1805,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -2722,11 +1813,7 @@ } ], "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], + "keywords": ["cache", "psr", "psr-6"], "support": { "source": "https://github.com/php-fig/cache/tree/3.0.0" }, @@ -2761,9 +1848,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -2771,209 +1856,43 @@ } ], "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], + "keywords": ["events", "psr", "psr-14"], "support": { "issues": "https://github.com/php-fig/event-dispatcher/issues", "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" }, "time": "2019-01-08T18:20:26+00:00" }, - { - "name": "psr/http-client", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Client\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", - "keywords": [ - "http", - "http-client", - "psr", - "psr-18" - ], - "support": { - "source": "https://github.com/php-fig/http-client" - }, - "time": "2023-09-23T14:17:50+00:00" - }, - { - "name": "psr/http-factory", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "psr/http-message": "^1.0 || ^2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-factory" - }, - "time": "2024-04-15T12:06:14+00:00" - }, - { - "name": "psr/http-message", - "version": "2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" - }, - "time": "2023-04-04T09:54:51+00:00" - }, { "name": "psr/log", - "version": "3.0.2", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "src" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -2982,114 +1901,57 @@ ], "description": "Common interface for logging libraries", "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], + "keywords": ["log", "psr", "psr-3"], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" + "source": "https://github.com/php-fig/log/tree/1.1.4" }, - "time": "2024-09-11T13:17:53+00:00" - }, - { - "name": "ralouphie/getallheaders", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" - }, - "time": "2019-03-08T08:55:37+00:00" + "time": "2021-05-03T11:20:27+00:00" }, { "name": "ramsey/collection", - "version": "2.1.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", - "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a", + "reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^7.3 || ^8", + "symfony/polyfill-php81": "^1.23" }, "require-dev": { - "captainhook/plugin-composer": "^5.3", - "ergebnis/composer-normalize": "^2.45", - "fakerphp/faker": "^1.24", - "hamcrest/hamcrest-php": "^2.0", - "jangregor/phpstan-prophecy": "^2.1", - "mockery/mockery": "^1.6", - "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.4", - "phpspec/prophecy-phpunit": "^2.3", - "phpstan/extension-installer": "^1.4", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-mockery": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^10.5", - "ramsey/coding-standard": "^2.3", - "ramsey/conventional-commits": "^1.6", - "roave/security-advisories": "dev-latest" + "captainhook/captainhook": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "ergebnis/composer-normalize": "^2.6", + "fakerphp/faker": "^1.5", + "hamcrest/hamcrest-php": "^2", + "jangregor/phpstan-prophecy": "^0.8", + "mockery/mockery": "^1.3", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^0.12.32", + "phpstan/phpstan-mockery": "^0.12.5", + "phpstan/phpstan-phpunit": "^0.12.11", + "phpunit/phpunit": "^8.5 || ^9", + "psy/psysh": "^0.10.4", + "slevomat/coding-standard": "^6.3", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.4" }, "type": "library", - "extra": { - "captainhook": { - "force-install": true - }, - "ramsey/conventional-commits": { - "configFile": "conventional-commits.json" - } - }, "autoload": { "psr-4": { "Ramsey\\Collection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ben Ramsey", @@ -3098,63 +1960,72 @@ } ], "description": "A PHP library for representing and manipulating collections.", - "keywords": [ - "array", - "collection", - "hash", - "map", - "queue", - "set" - ], + "keywords": ["array", "collection", "hash", "map", "queue", "set"], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/2.1.1" + "source": "https://github.com/ramsey/collection/tree/1.2.2" }, - "time": "2025-03-22T05:38:12+00:00" + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/collection", + "type": "tidelift" + } + ], + "time": "2021-10-10T03:01:02+00:00" }, { "name": "ramsey/uuid", - "version": "4.9.2", + "version": "4.5.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "8429c78ca35a09f27565311b98101e2826affde0" + "reference": "a161a26d917604dc6d3aa25100fddf2556e9f35d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/8429c78ca35a09f27565311b98101e2826affde0", - "reference": "8429c78ca35a09f27565311b98101e2826affde0", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/a161a26d917604dc6d3aa25100fddf2556e9f35d", + "reference": "a161a26d917604dc6d3aa25100fddf2556e9f35d", "shasum": "" }, "require": { - "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14", + "brick/math": "^0.8.8 || ^0.9 || ^0.10", + "ext-ctype": "*", + "ext-json": "*", "php": "^8.0", - "ramsey/collection": "^1.2 || ^2.0" + "ramsey/collection": "^1.0" }, "replace": { "rhumsaa/uuid": "self.version" }, "require-dev": { - "captainhook/captainhook": "^5.25", + "captainhook/captainhook": "^5.10", "captainhook/plugin-composer": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "ergebnis/composer-normalize": "^2.47", - "mockery/mockery": "^1.6", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", "paragonie/random-lib": "^2", - "php-mock/php-mock": "^2.6", - "php-mock/php-mock-mockery": "^1.5", - "php-parallel-lint/php-parallel-lint": "^1.4.0", - "phpbench/phpbench": "^1.2.14", - "phpstan/extension-installer": "^1.4", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-mockery": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^9.6", - "slevomat/coding-standard": "^8.18", - "squizlabs/php_codesniffer": "^3.13" + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-ctype": "Enables faster processing of character classification using ctype functions.", "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", @@ -3167,41 +2038,43 @@ } }, "autoload": { - "files": [ - "src/functions.php" - ], + "files": ["src/functions.php"], "psr-4": { "Ramsey\\Uuid\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", - "keywords": [ - "guid", - "identifier", - "uuid" - ], + "keywords": ["guid", "identifier", "uuid"], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.9.2" + "source": "https://github.com/ramsey/uuid/tree/4.5.1" }, - "time": "2025-12-14T04:43:48+00:00" + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2022-09-16T03:22:46+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.6.0", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", + "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", "shasum": "" }, "require": { @@ -3209,23 +2082,19 @@ }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "files": [ - "function.php" - ] + "files": ["function.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -3239,7 +2108,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1" }, "funding": [ { @@ -3255,94 +2124,24 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v8.0.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "d937d400b980523dc9ee946bb69972b5e619058d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/d937d400b980523dc9ee946bb69972b5e619058d", - "reference": "d937d400b980523dc9ee946bb69972b5e619058d", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^7.4|^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v8.0.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-12-01T09:13:36+00:00" + "time": "2022-02-25T11:15:52+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "provide": { "ext-ctype": "*" @@ -3352,23 +2151,22 @@ }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Gert de Pagter", @@ -3381,14 +2179,9 @@ ], "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], + "keywords": ["compatibility", "ctype", "polyfill", "portable"], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" }, "funding": [ { @@ -3399,34 +2192,29 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", "shasum": "" }, "require": { - "ext-iconv": "*", - "php": ">=7.2" + "php": ">=7.1" }, "provide": { "ext-mbstring": "*" @@ -3436,23 +2224,22 @@ }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -3465,15 +2252,9 @@ ], "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], + "keywords": ["compatibility", "mbstring", "polyfill", "portable", "shim"], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" }, "funding": [ { @@ -3484,56 +2265,49 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.33.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", + "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, - "classmap": [ - "Resources/stubs" - ] + "classmap": ["Resources/stubs"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Ion Bazan", @@ -3550,14 +2324,9 @@ ], "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], + "keywords": ["compatibility", "polyfill", "portable", "shim"], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" }, "funding": [ { @@ -3569,7 +2338,71 @@ "type": "github" }, { - "url": "https://github.com/nicolas-grekas", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-10T07:21:04+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1", + "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": ["bootstrap.php"], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": ["Resources/stubs"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": ["compatibility", "polyfill", "portable", "shim"], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" }, { @@ -3577,47 +2410,43 @@ "type": "tidelift" } ], - "time": "2025-01-02T08:10:11+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "vlucas/phpdotenv", - "version": "v5.6.3", + "version": "v5.4.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "955e7815d677a3eaa7075231212f2110983adecc" + "reference": "264dce589e7ce37a7ba99cb901eed8249fbec92f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc", - "reference": "955e7815d677a3eaa7075231212f2110983adecc", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/264dce589e7ce37a7ba99cb901eed8249fbec92f", + "reference": "264dce589e7ce37a7ba99cb901eed8249fbec92f", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.1.4", - "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9.5", - "symfony/polyfill-ctype": "^1.26", - "symfony/polyfill-mbstring": "^1.26", - "symfony/polyfill-php80": "^1.26" + "graham-campbell/result-type": "^1.0.2", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.8", + "symfony/polyfill-ctype": "^1.23", + "symfony/polyfill-mbstring": "^1.23.1", + "symfony/polyfill-php80": "^1.23.1" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", + "bamarni/composer-bin-plugin": "^1.4.1", "ext-filter": "*", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^7.5.20 || ^8.5.21 || ^9.5.10" }, "suggest": { "ext-filter": "Required to use the boolean validator." }, "type": "library", "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - }, "branch-alias": { - "dev-master": "5.6-dev" + "dev-master": "5.4-dev" } }, "autoload": { @@ -3626,9 +2455,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Graham Campbell", @@ -3642,14 +2469,10 @@ } ], "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", - "keywords": [ - "dotenv", - "env", - "environment" - ], + "keywords": ["dotenv", "env", "environment"], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.4.1" }, "funding": [ { @@ -3661,20 +2484,20 @@ "type": "tidelift" } ], - "time": "2025-12-27T19:49:13+00:00" + "time": "2021-12-12T23:22:04+00:00" }, { "name": "whichbrowser/parser", - "version": "v2.1.8", + "version": "v2.1.7", "source": { "type": "git", "url": "https://github.com/WhichBrowser/Parser-PHP.git", - "reference": "581d614d686bfbec3529ad60562a5213ac5d8d72" + "reference": "1044880bc792dbce5948fbff22ae731c43c280d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/581d614d686bfbec3529ad60562a5213ac5d8d72", - "reference": "581d614d686bfbec3529ad60562a5213ac5d8d72", + "url": "https://api.github.com/repos/WhichBrowser/Parser-PHP/zipball/1044880bc792dbce5948fbff22ae731c43c280d9", + "reference": "1044880bc792dbce5948fbff22ae731c43c280d9", "shasum": "" }, "require": { @@ -3696,15 +2519,11 @@ "type": "library", "autoload": { "psr-4": { - "WhichBrowser\\": [ - "src/" - ] + "WhichBrowser\\": ["src/", "tests/src/"] } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Niels Leenheer", @@ -3714,269 +2533,40 @@ ], "description": "Useragent sniffing library for PHP", "homepage": "http://whichbrowser.net", - "keywords": [ - "browser", - "sniffing", - "ua", - "useragent" - ], + "keywords": ["browser", "sniffing", "ua", "useragent"], "support": { "issues": "https://github.com/WhichBrowser/Parser-PHP/issues", - "source": "https://github.com/WhichBrowser/Parser-PHP/tree/v2.1.8" + "source": "https://github.com/WhichBrowser/Parser-PHP/tree/v2.1.7" }, - "time": "2024-04-17T12:47:41+00:00" - }, - { - "name": "yassinedoghri/codeigniter-vite", - "version": "v2.1.0", - "source": { - "type": "git", - "url": "https://github.com/yassinedoghri/codeigniter-vite.git", - "reference": "95c1dd30b716e3204ce981aa564202b299f9c8a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/yassinedoghri/codeigniter-vite/zipball/95c1dd30b716e3204ce981aa564202b299f9c8a5", - "reference": "95c1dd30b716e3204ce981aa564202b299f9c8a5", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "codeigniter/phpstan-codeigniter": "^1.5.4", - "codeigniter4/framework": "^v4.6.0", - "pestphp/pest": "^3.8.4", - "pestphp/pest-plugin-type-coverage": "^3.6.1", - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.1.22", - "rector/rector": "^2.1.4", - "symplify/coding-standard": "^12.4.3", - "symplify/easy-coding-standard": "^12.5.24" - }, - "type": "library", - "autoload": { - "psr-4": { - "CodeIgniterVite\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Yassine Doghri", - "homepage": "https://yassinedoghri.com/" - } - ], - "description": "An opinionated Vite integration for CodeIgniter4 projects.", - "keywords": [ - "codeigniter", - "codeigniter4", - "iconify", - "icons", - "php-icons" - ], - "support": { - "issues": "https://github.com/yassinedoghri/codeigniter-vite/issues", - "source": "https://github.com/yassinedoghri/codeigniter-vite/tree/v2.1.0" - }, - "time": "2025-09-09T18:36:45+00:00" - }, - { - "name": "yassinedoghri/php-icons", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/yassinedoghri/php-icons.git", - "reference": "ae5d7727431f6891a0660d2b20818795fae40b41" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/yassinedoghri/php-icons/zipball/ae5d7727431f6891a0660d2b20818795fae40b41", - "reference": "ae5d7727431f6891a0660d2b20818795fae40b41", - "shasum": "" - }, - "require": { - "adhocore/cli": "^v1.9.3", - "composer-runtime-api": "^2.2", - "php": ">=8.1" - }, - "require-dev": { - "kint-php/kint": "^6.0.1", - "pestphp/pest": "^3.7.4", - "pestphp/pest-plugin-type-coverage": "^3.4.0", - "phpstan/phpstan": "^2.1.10", - "rector/rector": "^2.0.10", - "symplify/coding-standard": "^12.2.3", - "symplify/easy-coding-standard": "^12.5.9" - }, - "bin": [ - "bin/php-icons" - ], - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Console/helpers.php" - ], - "psr-4": { - "PHPIcons\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Yassine Doghri", - "email": "yassine@doghri.fr", - "homepage": "https://yassinedoghri.com", - "role": "Maintainer" - } - ], - "description": "A PHP library based on iconify's API to download and render svg icons from popular open source icon sets.", - "support": { - "issues": "https://github.com/yassinedoghri/php-icons/issues", - "source": "https://github.com/yassinedoghri/php-icons/tree/v1.3.0" - }, - "time": "2025-03-23T16:46:25+00:00" - }, - { - "name": "yassinedoghri/podcast-feed", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/yassinedoghri/podcast-feed.git", - "reference": "d617e204fe85e0b7bd12b9d382cae4064af280c8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/yassinedoghri/podcast-feed/zipball/d617e204fe85e0b7bd12b9d382cae4064af280c8", - "reference": "d617e204fe85e0b7bd12b9d382cae4064af280c8", - "shasum": "" - }, - "require": { - "ext-intl": "*", - "php": ">=8.1" - }, - "require-dev": { - "kint-php/kint": "^5.0.5", - "phpstan/phpstan": "^1.10.18", - "rector/rector": "^0.17.0", - "symplify/coding-standard": "^11.3.0", - "symplify/easy-coding-standard": "^11.3.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "PodcastFeed\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "AGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Yassine Doghri", - "email": "yassine@doghri.fr", - "homepage": "https://yassinedoghri.com", - "role": "Maintainer" - } - ], - "description": "A robust podcast feed parser and validator written in PHP.", - "support": { - "issues": "https://github.com/yassinedoghri/podcast-feed/issues", - "source": "https://github.com/yassinedoghri/podcast-feed/tree/main" - }, - "time": "2024-04-28T16:17:41+00:00" - }, - { - "name": "z4kn4fein/php-semver", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/z4kn4fein/php-semver.git", - "reference": "049a1d81e92235c8b3c9ab30a96fcbaa929a266d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/z4kn4fein/php-semver/zipball/049a1d81e92235c8b3c9ab30a96fcbaa929a266d", - "reference": "049a1d81e92235c8b3c9ab30a96fcbaa929a266d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.0", - "phpstan/phpstan": "^1.0", - "phpunit/phpunit": "^10" - }, - "type": "library", - "autoload": { - "psr-4": { - "z4kn4fein\\SemVer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Peter Csajtai", - "email": "peter.csajtai@outlook.com" - } - ], - "description": "Semantic Versioning library for PHP. It implements the full semantic version 2.0.0 specification and provides ability to parse, compare, and increment semantic versions along with validation against constraints.", - "homepage": "https://github.com/z4kn4fein/php-semver", - "keywords": [ - "comparison", - "semantic", - "semver", - "validation", - "version", - "versioning" - ], - "support": { - "issues": "https://github.com/z4kn4fein/php-semver/issues", - "source": "https://github.com/z4kn4fein/php-semver/tree/v3.0.0" - }, - "time": "2024-04-01T16:17:27+00:00" + "time": "2022-04-19T20:14:54+00:00" } ], "packages-dev": [ { "name": "captainhook/captainhook", - "version": "5.28.3", + "version": "5.10.11", "source": { "type": "git", - "url": "https://github.com/captainhook-git/captainhook.git", - "reference": "5d35b249f3843ef36ead119f4347e649278ad6d8" + "url": "https://github.com/captainhookphp/captainhook.git", + "reference": "377ea566c5fb91e2fbec6ad0aadf21eb88e18cee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/captainhook-git/captainhook/zipball/5d35b249f3843ef36ead119f4347e649278ad6d8", - "reference": "5d35b249f3843ef36ead119f4347e649278ad6d8", + "url": "https://api.github.com/repos/captainhookphp/captainhook/zipball/377ea566c5fb91e2fbec6ad0aadf21eb88e18cee", + "reference": "377ea566c5fb91e2fbec6ad0aadf21eb88e18cee", "shasum": "" }, "require": { - "captainhook/secrets": "^0.9.4", "ext-json": "*", "ext-spl": "*", "ext-xml": "*", - "php": ">=8.0", + "php": ">=7.2", "sebastianfeldmann/camino": "^0.9.2", "sebastianfeldmann/cli": "^3.3", - "sebastianfeldmann/git": "^3.16.0", - "symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", - "symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", - "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0" + "sebastianfeldmann/git": "^3.8.1", + "symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0", + "symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0", + "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0" }, "replace": { "sebastianfeldmann/captainhook": "*" @@ -3985,16 +2575,14 @@ "composer/composer": "~1 || ^2.0", "mikey179/vfsstream": "~1" }, - "bin": [ - "bin/captainhook" - ], + "bin": ["bin/captainhook"], "type": "library", "extra": { - "captainhook": { - "config": "captainhook.json" - }, "branch-alias": { "dev-main": "6.0.x-dev" + }, + "captainhook": { + "config": "captainhook.json" } }, "autoload": { @@ -4003,9 +2591,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Sebastian Feldmann", @@ -4013,7 +2599,7 @@ } ], "description": "PHP git hook manager", - "homepage": "https://php.captainhook.info/", + "homepage": "https://github.com/captainhookphp/captainhook", "keywords": [ "commit-msg", "git", @@ -4024,8 +2610,8 @@ "prepare-commit-msg" ], "support": { - "issues": "https://github.com/captainhook-git/captainhook/issues", - "source": "https://github.com/captainhook-git/captainhook/tree/5.28.3" + "issues": "https://github.com/captainhookphp/captainhook/issues", + "source": "https://github.com/captainhookphp/captainhook/tree/5.10.11" }, "funding": [ { @@ -4033,232 +2619,32 @@ "type": "github" } ], - "time": "2026-02-16T14:08:58+00:00" - }, - { - "name": "captainhook/secrets", - "version": "0.9.7", - "source": { - "type": "git", - "url": "https://github.com/captainhook-git/secrets.git", - "reference": "d62c97f75f81ac98e22f1c282482bd35fa82f631" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/captainhook-git/secrets/zipball/d62c97f75f81ac98e22f1c282482bd35fa82f631", - "reference": "d62c97f75f81ac98e22f1c282482bd35fa82f631", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "CaptainHook\\Secrets\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Sebastian Feldmann", - "email": "sf@sebastian-feldmann.info" - } - ], - "description": "Utility classes to detect secrets", - "keywords": [ - "commit-msg", - "keys", - "passwords", - "post-merge", - "prepare-commit-msg", - "secrets", - "tokens" - ], - "support": { - "issues": "https://github.com/captainhook-git/secrets/issues", - "source": "https://github.com/captainhook-git/secrets/tree/0.9.7" - }, - "funding": [ - { - "url": "https://github.com/sponsors/sebastianfeldmann", - "type": "github" - } - ], - "time": "2025-04-08T07:10:48+00:00" - }, - { - "name": "clue/ndjson-react", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/clue/reactphp-ndjson.git", - "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", - "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", - "shasum": "" - }, - "require": { - "php": ">=5.3", - "react/stream": "^1.2" - }, - "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", - "react/event-loop": "^1.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "Clue\\React\\NDJson\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering" - } - ], - "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", - "homepage": "https://github.com/clue/reactphp-ndjson", - "keywords": [ - "NDJSON", - "json", - "jsonlines", - "newline", - "reactphp", - "streaming" - ], - "support": { - "issues": "https://github.com/clue/reactphp-ndjson/issues", - "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" - }, - "funding": [ - { - "url": "https://clue.engineering/support", - "type": "custom" - }, - { - "url": "https://github.com/clue", - "type": "github" - } - ], - "time": "2022-12-23T10:58:28+00:00" - }, - { - "name": "codeigniter/phpstan-codeigniter", - "version": "v1.5.4", - "source": { - "type": "git", - "url": "https://github.com/CodeIgniter/phpstan-codeigniter.git", - "reference": "e959fb0841c29a01870aa6570f3095f42e1057ad" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/CodeIgniter/phpstan-codeigniter/zipball/e959fb0841c29a01870aa6570f3095f42e1057ad", - "reference": "e959fb0841c29a01870aa6570f3095f42e1057ad", - "shasum": "" - }, - "require": { - "php": "^8.1", - "phpstan/phpstan": "^2.0" - }, - "conflict": { - "codeigniter/framework": "*" - }, - "require-dev": { - "codeigniter/coding-standard": "^1.7", - "codeigniter4/framework": "^4.5", - "codeigniter4/shield": "^1.0", - "friendsofphp/php-cs-fixer": "^3.49", - "nexusphp/cs-config": "^3.21", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan-deprecation-rules": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^10.5 || ^11.4" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon" - ] - } - }, - "autoload": { - "psr-4": { - "CodeIgniter\\PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Paul E. Balandan, CPA", - "email": "paulbalandan@gmail.com" - } - ], - "description": "CodeIgniter extensions and rules for PHPStan", - "keywords": [ - "PHPStan", - "codeigniter", - "codeigniter4", - "dev", - "static analysis" - ], - "support": { - "forum": "http://forum.codeigniter.com/", - "issues": "https://github.com/CodeIgniter/phpstan-codeigniter/issues", - "slack": "https://codeigniterchat.slack.com", - "source": "https://github.com/CodeIgniter/phpstan-codeigniter" - }, - "time": "2025-06-24T17:28:48+00:00" + "time": "2022-07-26T20:11:41+00:00" }, { "name": "composer/pcre", - "version": "3.3.2", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd", + "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, - "conflict": { - "phpstan/phpstan": "<1.11.10" - }, "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" }, "type": "library", "extra": { - "phpstan": { - "includes": [ - "extension.neon" - ] - }, "branch-alias": { "dev-main": "3.x-dev" } @@ -4269,9 +2655,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Jordi Boggiano", @@ -4280,15 +2664,10 @@ } ], "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], + "keywords": ["PCRE", "preg", "regex", "regular expression"], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" + "source": "https://github.com/composer/pcre/tree/3.0.0" }, "funding": [ { @@ -4304,28 +2683,28 @@ "type": "tidelift" } ], - "time": "2024-11-12T16:29:46+00:00" + "time": "2022-02-25T20:21:48+00:00" }, { "name": "composer/semver", - "version": "3.4.4", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.11", - "symfony/phpunit-bridge": "^3 || ^7" + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "extra": { @@ -4339,9 +2718,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nils Adermann", @@ -4360,78 +2737,11 @@ } ], "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], + "keywords": ["semantic", "semver", "validation", "versioning"], "support": { - "irc": "ircs://irc.libera.chat:6697/composer", + "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.4" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - } - ], - "time": "2025-08-20T19:15:30+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.5", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + "source": "https://github.com/composer/semver/tree/3.3.2" }, "funding": [ { @@ -4447,191 +2757,331 @@ "type": "tidelift" } ], - "time": "2024-05-06T16:37:16+00:00" + "time": "2022-04-01T19:23:25+00:00" }, { - "name": "evenement/evenement", - "version": "v3.0.2", + "name": "composer/xdebug-handler", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/igorw/evenement.git", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "ced299686f41dce890debac69273b47ffe98a40c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", "shasum": "" }, "require": { - "php": ">=7.0" + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" }, "require-dev": { - "phpunit/phpunit": "^9 || ^6" + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^6.0" }, "type": "library", "autoload": { "psr-4": { - "Evenement\\": "src/" + "Composer\\XdebugHandler\\": "src" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" } ], - "description": "Événement is a very simple event dispatching library for PHP", - "keywords": [ - "event-dispatcher", - "event-emitter" - ], + "description": "Restarts a process without Xdebug.", + "keywords": ["Xdebug", "performance"], "support": { - "issues": "https://github.com/igorw/evenement/issues", - "source": "https://github.com/igorw/evenement/tree/v3.0.2" - }, - "time": "2023-08-08T05:53:35+00:00" - }, - { - "name": "fidry/cpu-core-counter", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-deprecation-rules": "^2.0.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^8.5.31 || ^9.5.26", - "webmozarts/strict-phpunit": "^7.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Fidry\\CpuCoreCounter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com" - } - ], - "description": "Tiny utility to get the number of CPU cores.", - "keywords": [ - "CPU", - "core" - ], - "support": { - "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" }, "funding": [ { - "url": "https://github.com/theofidry", + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" } ], - "time": "2025-08-14T07:29:31+00:00" + "time": "2022-02-25T21:32:43+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.94.1", + "name": "doctrine/annotations", + "version": "1.13.3", "source": { "type": "git", - "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "d1a3634e29916367b885250e1fc4dfd5ffe3b091" + "url": "https://github.com/doctrine/annotations.git", + "reference": "648b0343343565c4a056bfc8392201385e8d89f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/d1a3634e29916367b885250e1fc4dfd5ffe3b091", - "reference": "d1a3634e29916367b885250e1fc4dfd5ffe3b091", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0", + "reference": "648b0343343565c4a056bfc8392201385e8d89f0", "shasum": "" }, "require": { - "clue/ndjson-react": "^1.3", - "composer/semver": "^3.4", - "composer/xdebug-handler": "^3.0.5", - "ext-filter": "*", - "ext-hash": "*", - "ext-json": "*", + "doctrine/lexer": "1.*", "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.3", - "php": "^7.4 || ^8.0", - "react/child-process": "^0.6.6", - "react/event-loop": "^1.5", - "react/socket": "^1.16", - "react/stream": "^1.4", - "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0", - "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", - "symfony/polyfill-mbstring": "^1.33", - "symfony/polyfill-php80": "^1.33", - "symfony/polyfill-php81": "^1.33", - "symfony/polyfill-php84": "^1.33", - "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", - "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.7.1", - "infection/infection": "^0.32.3", - "justinrainbow/json-schema": "^6.6.4", - "keradus/cli-executor": "^2.3", - "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.9.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7", - "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51", - "symfony/polyfill-php85": "^1.33", - "symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4", - "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1" + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^6.0 || ^8.1", + "phpstan/phpstan": "^1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", + "symfony/cache": "^4.4 || ^5.2", + "vimeo/psalm": "^4.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": ["annotations", "docblock", "parser"], + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.13.3" + }, + "time": "2022-07-02T10:48:51+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": ["constructor", "instantiate"], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-03-03T08:28:38+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": ["annotations", "docblock", "lexer", "parser", "php"], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-02-28T11:07:21+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.12.0", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "eae11d945e2885d86e1c080eec1bb30a2aa27998" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/eae11d945e2885d86e1c080eec1bb30a2aa27998", + "reference": "eae11d945e2885d86e1c080eec1bb30a2aa27998", + "shasum": "" + }, + "require": { + "composer/semver": "^3.2", + "composer/xdebug-handler": "^3.0.3", + "doctrine/annotations": "^1.13", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0", + "sebastian/diff": "^4.0", + "symfony/console": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/filesystem": "^5.4 || ^6.0", + "symfony/finder": "^5.4 || ^6.0", + "symfony/options-resolver": "^5.4 || ^6.0", + "symfony/polyfill-mbstring": "^1.23", + "symfony/polyfill-php80": "^1.25", + "symfony/polyfill-php81": "^1.25", + "symfony/process": "^5.4 || ^6.0", + "symfony/stopwatch": "^5.4 || ^6.0" + }, + "require-dev": { + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^1.5", + "mikey179/vfsstream": "^1.6.10", + "php-coveralls/php-coveralls": "^2.5.2", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "phpunitgoodpractices/polyfill": "^1.6", + "phpunitgoodpractices/traits": "^1.9.2", + "symfony/phpunit-bridge": "^6.0", + "symfony/yaml": "^5.4 || ^6.0" }, "suggest": { "ext-dom": "For handling output formats in XML", "ext-mbstring": "For handling non-UTF8 characters." }, - "bin": [ - "php-cs-fixer" - ], + "bin": ["php-cs-fixer"], "type": "application", "autoload": { "psr-4": { "PhpCsFixer\\": "src/" - }, - "exclude-from-classmap": [ - "src/**/Internal/" - ] + } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -4643,15 +3093,9 @@ } ], "description": "A tool to automatically fix PHP code style", - "keywords": [ - "Static code analysis", - "fixer", - "standards", - "static analysis" - ], "support": { - "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.1" + "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.12.0" }, "funding": [ { @@ -4659,28 +3103,27 @@ "type": "github" } ], - "time": "2026-02-18T12:24:42+00:00" + "time": "2022-10-12T14:20:51+00:00" }, { "name": "mikey179/vfsstream", - "version": "v1.6.12", + "version": "v1.6.11", "source": { "type": "git", "url": "https://github.com/bovigo/vfsStream.git", - "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0" + "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", - "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", + "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", "shasum": "" }, "require": { - "php": ">=7.1.0" + "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^7.5||^8.5||^9.6", - "yoast/phpunit-polyfills": "^2.0" + "phpunit/phpunit": "^4.5|^5.0" }, "type": "library", "extra": { @@ -4694,9 +3137,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Frank Kleine", @@ -4711,20 +3152,20 @@ "source": "https://github.com/bovigo/vfsStream/tree/master", "wiki": "https://github.com/bovigo/vfsStream/wiki" }, - "time": "2024-08-29T18:43:31+00:00" + "time": "2022-02-23T02:02:42+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.13.4", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", "shasum": "" }, "require": { @@ -4732,38 +3173,27 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], + "files": ["src/DeepCopy/deep_copy.php"], "psr-4": { "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], + "keywords": ["clone", "copy", "duplicate", "object", "object graph"], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" }, "funding": [ { @@ -4771,39 +3201,35 @@ "type": "tidelift" } ], - "time": "2025-08-01T08:46:24+00:00" + "time": "2022-03-03T13:19:32+00:00" }, { "name": "nikic/php-parser", - "version": "v5.7.0", + "version": "v4.15.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", "shasum": "" }, "require": { - "ext-ctype": "*", - "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.4" + "php": ">=7.0" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, - "bin": [ - "bin/php-parse" - ], + "bin": ["bin/php-parse"], "type": "library", "extra": { "branch-alias": { - "dev-master": "5.x-dev" + "dev-master": "4.9-dev" } }, "autoload": { @@ -4812,42 +3238,36 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], + "keywords": ["parser", "php"], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" }, - "time": "2025-12-06T11:56:16+00:00" + "time": "2022-09-04T07:30:47+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.4", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { "ext-dom": "*", - "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -4860,14 +3280,10 @@ } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Arne Blankerts", @@ -4888,15 +3304,9 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" + "source": "https://github.com/phar-io/manifest/tree/2.0.3" }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" + "time": "2021-07-20T11:28:43+00:00" }, { "name": "phar-io/version", @@ -4917,14 +3327,10 @@ }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Arne Blankerts", @@ -4950,93 +3356,37 @@ "time": "2022-02-21T01:04:05+00:00" }, { - "name": "phpstan/extension-installer", - "version": "1.4.3", + "name": "phpstan/phpstan", + "version": "1.8.9", "source": { "type": "git", - "url": "https://github.com/phpstan/extension-installer.git", - "reference": "85e90b3942d06b2326fba0403ec24fe912372936" + "url": "https://github.com/phpstan/phpstan.git", + "reference": "3a72d9d9f2528fbd50c2d8fcf155fd9f74ade3f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", - "reference": "85e90b3942d06b2326fba0403ec24fe912372936", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3a72d9d9f2528fbd50c2d8fcf155fd9f74ade3f2", + "reference": "3a72d9d9f2528fbd50c2d8fcf155fd9f74ade3f2", "shasum": "" }, "require": { - "composer-plugin-api": "^2.0", - "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.9.0 || ^2.0" - }, - "require-dev": { - "composer/composer": "^2.0", - "php-parallel-lint/php-parallel-lint": "^1.2.0", - "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PHPStan\\ExtensionInstaller\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPStan\\ExtensionInstaller\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Composer plugin for automatic installation of PHPStan extensions", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpstan/extension-installer/issues", - "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" - }, - "time": "2024-09-04T20:21:43+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "2.1.39", - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c6f73a2af4cbcd99c931d0fb8f08548cc0fa8224", - "reference": "c6f73a2af4cbcd99c931d0fb8f08548cc0fa8224", - "shasum": "" - }, - "require": { - "php": "^7.4|^8.0" + "php": "^7.2|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" }, - "bin": [ - "phpstan", - "phpstan.phar" - ], + "bin": ["phpstan", "phpstan.phar"], "type": "library", "autoload": { - "files": [ - "bootstrap.php" - ] + "files": ["bootstrap.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], + "keywords": ["dev", "static analysis"], "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" + "source": "https://github.com/phpstan/phpstan/tree/1.8.9" }, "funding": [ { @@ -5046,60 +3396,61 @@ { "url": "https://github.com/phpstan", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" } ], - "time": "2026-02-11T14:48:56+00:00" + "time": "2022-10-13T13:40:18+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "13.0.1", + "version": "9.2.17", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "a8b58fde2f4fbc69a064e1f80ff917607cf7737c" + "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a8b58fde2f4fbc69a064e1f80ff917607cf7737c", - "reference": "a8b58fde2f4fbc69a064e1f80ff917607cf7737c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8", + "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^5.7.0", - "php": ">=8.4", - "phpunit/php-file-iterator": "^7.0", - "phpunit/php-text-template": "^6.0", - "sebastian/complexity": "^6.0", - "sebastian/environment": "^9.0", - "sebastian/lines-of-code": "^5.0", - "sebastian/version": "^7.0", - "theseer/tokenizer": "^2.0.1" + "nikic/php-parser": "^4.14", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-pcov": "*", + "ext-xdebug": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "13.0.x-dev" + "dev-master": "9.2-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -5109,71 +3460,50 @@ ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], + "keywords": ["coverage", "testing", "xunit"], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/13.0.1" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", - "type": "tidelift" } ], - "time": "2026-02-06T06:05:15+00:00" + "time": "2022-08-30T12:24:04+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "7.0.0", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", - "reference": "6e5aa1fb0a95b1703d83e721299ee18bb4e2de50", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -5183,55 +3513,39 @@ ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], + "keywords": ["filesystem", "iterator"], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/7.0.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", - "type": "tidelift" } ], - "time": "2026-02-06T04:33:26+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { "name": "phpunit/php-invoker", - "version": "7.0.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88" + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", - "reference": "42e5c5cae0c65df12d1b1a3ab52bf3f50f244d88", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-pcntl": "*" @@ -5239,18 +3553,14 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -5260,69 +3570,50 @@ ], "description": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], + "keywords": ["process"], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/7.0.0" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-invoker", - "type": "tidelift" } ], - "time": "2026-02-06T04:34:47+00:00" + "time": "2020-09-28T05:58:55+00:00" }, { "name": "phpunit/php-text-template", - "version": "6.0.0", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4" + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/a47af19f93f76aa3368303d752aa5272ca3299f4", - "reference": "a47af19f93f76aa3368303d752aa5272ca3299f4", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -5332,69 +3623,50 @@ ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], + "keywords": ["template"], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-text-template", - "type": "tidelift" } ], - "time": "2026-02-06T04:36:37+00:00" + "time": "2020-10-26T05:33:50+00:00" }, { "name": "phpunit/php-timer", - "version": "9.0.0", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6" + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a0e12065831f6ab0d83120dc61513eb8d9a966f6", - "reference": "a0e12065831f6ab0d83120dc61513eb8d9a966f6", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "9.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -5404,97 +3676,79 @@ ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], + "keywords": ["timer"], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/9.0.0" + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-timer", - "type": "tidelift" } ], - "time": "2026-02-06T04:37:53+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", - "version": "13.0.5", + "version": "9.5.25", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d57826e8921a534680c613924bfd921ded8047f4" + "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d57826e8921a534680c613924bfd921ded8047f4", - "reference": "d57826e8921a534680c613924bfd921ded8047f4", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d", + "reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.3.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.4.1", - "phpunit/php-code-coverage": "^13.0.1", - "phpunit/php-file-iterator": "^7.0.0", - "phpunit/php-invoker": "^7.0.0", - "phpunit/php-text-template": "^6.0.0", - "phpunit/php-timer": "^9.0.0", - "sebastian/cli-parser": "^5.0.0", - "sebastian/comparator": "^8.0.0", - "sebastian/diff": "^8.0.0", - "sebastian/environment": "^9.0.0", - "sebastian/exporter": "^8.0.0", - "sebastian/global-state": "^9.0.0", - "sebastian/object-enumerator": "^8.0.0", - "sebastian/recursion-context": "^8.0.0", - "sebastian/type": "^7.0.0", - "sebastian/version": "^7.0.0", - "staabm/side-effects-detector": "^1.0.5" + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" }, - "bin": [ - "phpunit" - ], + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" + }, + "bin": ["phpunit"], "type": "library", "extra": { "branch-alias": { - "dev-main": "13.0-dev" + "dev-master": "9.5-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] + "files": ["src/Framework/Assert/Functions.php"], + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -5504,15 +3758,10 @@ ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], + "keywords": ["phpunit", "testing", "xunit"], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/13.0.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25" }, "funding": [ { @@ -5523,20 +3772,12 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2026-02-18T12:40:03+00:00" + "time": "2022-09-25T03:44:45+00:00" }, { "name": "psr/container", @@ -5567,9 +3808,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "PHP-FIG", @@ -5591,583 +3830,49 @@ }, "time": "2021-11-05T16:47:00+00:00" }, - { - "name": "react/cache", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/cache.git", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "react/promise": "^3.0 || ^2.0 || ^1.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async, Promise-based cache interface for ReactPHP", - "keywords": [ - "cache", - "caching", - "promise", - "reactphp" - ], - "support": { - "issues": "https://github.com/reactphp/cache/issues", - "source": "https://github.com/reactphp/cache/tree/v1.2.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2022-11-30T15:59:55+00:00" - }, - { - "name": "react/child-process", - "version": "v0.6.7", - "source": { - "type": "git", - "url": "https://github.com/reactphp/child-process.git", - "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", - "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.0", - "react/event-loop": "^1.2", - "react/stream": "^1.4" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/socket": "^1.16", - "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\ChildProcess\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Event-driven library for executing child processes with ReactPHP.", - "keywords": [ - "event-driven", - "process", - "reactphp" - ], - "support": { - "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.7" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-12-23T15:25:20+00:00" - }, - { - "name": "react/dns", - "version": "v1.14.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/dns.git", - "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", - "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "react/cache": "^1.0 || ^0.6 || ^0.5", - "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.7 || ^1.2.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3 || ^2", - "react/promise-timer": "^1.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Dns\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async DNS resolver for ReactPHP", - "keywords": [ - "async", - "dns", - "dns-resolver", - "reactphp" - ], - "support": { - "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.14.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-11-18T19:34:28+00:00" - }, - { - "name": "react/event-loop", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/event-loop.git", - "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", - "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" - }, - "suggest": { - "ext-pcntl": "For signal handling support when using the StreamSelectLoop" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\EventLoop\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", - "keywords": [ - "asynchronous", - "event-loop" - ], - "support": { - "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-11-17T20:46:25+00:00" - }, - { - "name": "react/promise", - "version": "v3.3.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", - "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", - "shasum": "" - }, - "require": { - "php": ">=7.1.0" - }, - "require-dev": { - "phpstan/phpstan": "1.12.28 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "React\\Promise\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "keywords": [ - "promise", - "promises" - ], - "support": { - "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.3.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-08-19T18:57:03+00:00" - }, - { - "name": "react/socket", - "version": "v1.17.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/socket.git", - "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", - "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.0", - "react/dns": "^1.13", - "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.6 || ^1.2.1", - "react/stream": "^1.4" - }, - "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3.3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Socket\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", - "keywords": [ - "Connection", - "Socket", - "async", - "reactphp", - "stream" - ], - "support": { - "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.17.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2025-11-19T20:47:34+00:00" - }, - { - "name": "react/stream", - "version": "v1.4.0", - "source": { - "type": "git", - "url": "https://github.com/reactphp/stream.git", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", - "shasum": "" - }, - "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.8", - "react/event-loop": "^1.2" - }, - "require-dev": { - "clue/stream-filter": "~1.2", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" - }, - "type": "library", - "autoload": { - "psr-4": { - "React\\Stream\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", - "keywords": [ - "event-driven", - "io", - "non-blocking", - "pipe", - "reactphp", - "readable", - "stream", - "writable" - ], - "support": { - "issues": "https://github.com/reactphp/stream/issues", - "source": "https://github.com/reactphp/stream/tree/v1.4.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2024-06-11T12:45:25+00:00" - }, { "name": "rector/rector", - "version": "2.3.6", + "version": "0.14.5", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "ca9ebb81d280cd362ea39474dabd42679e32ca6b" + "reference": "f7fd87b2435835f481e6a94ee28e09af412bd3cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/ca9ebb81d280cd362ea39474dabd42679e32ca6b", - "reference": "ca9ebb81d280cd362ea39474dabd42679e32ca6b", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/f7fd87b2435835f481e6a94ee28e09af412bd3cc", + "reference": "f7fd87b2435835f481e6a94ee28e09af412bd3cc", "shasum": "" }, "require": { - "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.38" + "php": "^7.2|^8.0", + "phpstan/phpstan": "^1.8.6" }, "conflict": { + "rector/rector-cakephp": "*", "rector/rector-doctrine": "*", - "rector/rector-downgrade-php": "*", + "rector/rector-laravel": "*", + "rector/rector-php-parser": "*", + "rector/rector-phpoffice": "*", "rector/rector-phpunit": "*", "rector/rector-symfony": "*" }, - "suggest": { - "ext-dom": "To manipulate phpunit.xml via the custom-rule command" - }, - "bin": [ - "bin/rector" - ], + "bin": ["bin/rector"], "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.14-dev" + } + }, "autoload": { - "files": [ - "bootstrap.php" - ] + "files": ["bootstrap.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Instant Upgrade and Automated Refactoring of any PHP code", - "homepage": "https://getrector.com/", - "keywords": [ - "automation", - "dev", - "migration", - "refactoring" - ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.3.6" + "source": "https://github.com/rectorphp/rector/tree/0.14.5" }, "funding": [ { @@ -6175,43 +3880,39 @@ "type": "github" } ], - "time": "2026-02-06T14:25:06+00:00" + "time": "2022-09-29T11:05:42+00:00" }, { "name": "sebastian/cli-parser", - "version": "5.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca" + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/48a4654fa5e48c1c81214e9930048a572d4b23ca", - "reference": "48a4654fa5e48c1c81214e9930048a572d4b23ca", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6223,71 +3924,152 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser", - "type": "tidelift" } ], - "time": "2026-02-06T04:39:44+00:00" + "time": "2020-09-28T06:08:49+00:00" }, { - "name": "sebastian/comparator", - "version": "8.0.0", + "name": "sebastian/code-unit", + "version": "1.0.8", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "29b232ddc29c2b114c0358c69b3084e7c3da0d58" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/29b232ddc29c2b114c0358c69b3084e7c3da0d58", - "reference": "29b232ddc29c2b114c0358c69b3084e7c3da0d58", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.4", - "sebastian/diff": "^8.0", - "sebastian/exporter": "^8.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" - }, - "suggest": { - "ext-bcmath": "For comparing BcMath\\Number objects" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6308,72 +4090,51 @@ ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], + "keywords": ["comparator", "compare", "equality"], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/8.0.0" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", - "type": "tidelift" } ], - "time": "2026-02-06T04:40:39+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", - "version": "6.0.0", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "c5651c795c98093480df79350cb050813fc7a2f3" + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c5651c795c98093480df79350cb050813fc7a2f3", - "reference": "c5651c795c98093480df79350cb050813fc7a2f3", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", "shasum": "" }, "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.4" + "nikic/php-parser": "^4.7", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6385,65 +4146,48 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/complexity", - "type": "tidelift" } ], - "time": "2026-02-06T04:41:32+00:00" + "time": "2020-10-26T15:52:27+00:00" }, { "name": "sebastian/diff", - "version": "8.0.0", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3" + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/a2b6d09d7729ee87d605a439469f9dcc39be5ea3", - "reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0", - "symfony/process": "^7.2" + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6456,56 +4200,38 @@ ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], + "keywords": ["diff", "udiff", "unidiff", "unified diff"], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/8.0.0" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/diff", - "type": "tidelift" } ], - "time": "2026-02-06T04:42:27+00:00" + "time": "2020-10-26T13:10:38+00:00" }, { "name": "sebastian/environment", - "version": "9.0.0", + "version": "5.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "bb64d08145b021b67d5f253308a498b73ab0461e" + "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/bb64d08145b021b67d5f253308a498b73ab0461e", - "reference": "bb64d08145b021b67d5f253308a498b73ab0461e", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-posix": "*" @@ -6513,18 +4239,14 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.0-dev" + "dev-master": "5.1-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6532,74 +4254,53 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": ["Xdebug", "environment", "hhvm"], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/9.0.0" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", - "type": "tidelift" } ], - "time": "2026-02-06T04:43:29+00:00" + "time": "2022-04-03T09:37:03+00:00" }, { "name": "sebastian/exporter", - "version": "8.0.0", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "dc31f1f8e0186c8f0bb3e48fd4d51421d8905fea" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/dc31f1f8e0186c8f0bb3e48fd4d51421d8905fea", - "reference": "dc31f1f8e0186c8f0bb3e48fd4d51421d8905fea", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=8.4", - "sebastian/recursion-context": "^8.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6624,73 +4325,56 @@ ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], + "keywords": ["export", "exporter"], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/8.0.0" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", - "type": "tidelift" } ], - "time": "2026-02-06T04:44:28+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", - "version": "9.0.0", + "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e52e3dc22441e6218c710afe72c3042f8fc41ea7" + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e52e3dc22441e6218c710afe72c3042f8fc41ea7", - "reference": "e52e3dc22441e6218c710afe72c3042f8fc41ea7", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", "shasum": "" }, "require": { - "php": ">=8.4", - "sebastian/object-reflector": "^6.0", - "sebastian/recursion-context": "^8.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "9.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6698,71 +4382,52 @@ } ], "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": ["global state"], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/9.0.0" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", - "type": "tidelift" } ], - "time": "2026-02-06T04:45:13+00:00" + "time": "2022-02-14T08:28:10+00:00" }, { "name": "sebastian/lines-of-code", - "version": "5.0.0", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "4f21bb7768e1c997722ccc7efb1d6b5c11bfd471" + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/4f21bb7768e1c997722ccc7efb1d6b5c11bfd471", - "reference": "4f21bb7768e1c997722ccc7efb1d6b5c11bfd471", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", "shasum": "" }, "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.4" + "nikic/php-parser": "^4.6", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6774,66 +4439,49 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/lines-of-code", - "type": "tidelift" } ], - "time": "2026-02-06T04:45:54+00:00" + "time": "2020-11-28T06:42:11+00:00" }, { "name": "sebastian/object-enumerator", - "version": "8.0.0", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5" + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", - "reference": "b39ab125fd9a7434b0ecbc4202eebce11a98cfc5", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", "shasum": "" }, "require": { - "php": ">=8.4", - "sebastian/object-reflector": "^6.0", - "sebastian/recursion-context": "^8.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6844,64 +4492,47 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/8.0.0" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/object-enumerator", - "type": "tidelift" } ], - "time": "2026-02-06T04:46:36+00:00" + "time": "2020-10-26T13:12:34+00:00" }, { "name": "sebastian/object-reflector", - "version": "6.0.0", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200" + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", - "reference": "3ca042c2c60b0eab094f8a1b6a7093f4d4c72200", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6912,64 +4543,47 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/object-reflector", - "type": "tidelift" } ], - "time": "2026-02-06T04:47:13+00:00" + "time": "2020-10-26T13:14:26+00:00" }, { "name": "sebastian/recursion-context", - "version": "8.0.0", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e" + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/74c5af21f6a5833e91767ca068c4d3dfec15317e", - "reference": "74c5af21f6a5833e91767ca068c4d3dfec15317e", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -6985,67 +4599,101 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/8.0.0" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", - "type": "tidelift" } ], - "time": "2026-02-06T04:51:28+00:00" + "time": "2020-10-26T13:17:30+00:00" }, { - "name": "sebastian/type", - "version": "7.0.0", + "name": "sebastian/resource-operations", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "42412224607bd3931241bbd17f38e0f972f5a916" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/42412224607bd3931241bbd17f38e0f972f5a916", - "reference": "42412224607bd3931241bbd17f38e0f972f5a916", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^13.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -7057,61 +4705,44 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/7.0.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/type", - "type": "tidelift" } ], - "time": "2026-02-06T04:52:09+00:00" + "time": "2022-09-12T14:47:03+00:00" }, { "name": "sebastian/version", - "version": "7.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b" + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ad37a5552c8e2b88572249fdc19b6da7792e021b", - "reference": "ad37a5552c8e2b88572249fdc19b6da7792e021b", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Sebastian Bergmann", @@ -7123,28 +4754,15 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/7.0.0" + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/sebastian/version", - "type": "tidelift" } ], - "time": "2026-02-06T04:52:52+00:00" + "time": "2020-09-28T06:39:44+00:00" }, { "name": "sebastianfeldmann/camino", @@ -7175,9 +4793,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Sebastian Feldmann", @@ -7186,10 +4802,7 @@ ], "description": "Path management the OO way", "homepage": "https://github.com/sebastianfeldmann/camino", - "keywords": [ - "file system", - "path" - ], + "keywords": ["file system", "path"], "support": { "issues": "https://github.com/sebastianfeldmann/camino/issues", "source": "https://github.com/sebastianfeldmann/camino/tree/0.9.5" @@ -7204,16 +4817,16 @@ }, { "name": "sebastianfeldmann/cli", - "version": "3.4.2", + "version": "3.4.1", "source": { "type": "git", "url": "https://github.com/sebastianfeldmann/cli.git", - "reference": "6fa122afd528dae7d7ec988a604aa6c600f5d9b5" + "reference": "8a932e99e9455981fb32fa6c085492462fe8f8cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianfeldmann/cli/zipball/6fa122afd528dae7d7ec988a604aa6c600f5d9b5", - "reference": "6fa122afd528dae7d7ec988a604aa6c600f5d9b5", + "url": "https://api.github.com/repos/sebastianfeldmann/cli/zipball/8a932e99e9455981fb32fa6c085492462fe8f8cf", + "reference": "8a932e99e9455981fb32fa6c085492462fe8f8cf", "shasum": "" }, "require": { @@ -7234,9 +4847,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Sebastian Feldmann", @@ -7245,12 +4856,10 @@ ], "description": "PHP cli helper classes", "homepage": "https://github.com/sebastianfeldmann/cli", - "keywords": [ - "cli" - ], + "keywords": ["cli"], "support": { "issues": "https://github.com/sebastianfeldmann/cli/issues", - "source": "https://github.com/sebastianfeldmann/cli/tree/3.4.2" + "source": "https://github.com/sebastianfeldmann/cli/tree/3.4.1" }, "funding": [ { @@ -7258,27 +4867,26 @@ "type": "github" } ], - "time": "2024-11-26T10:19:01+00:00" + "time": "2021-12-20T14:59:49+00:00" }, { "name": "sebastianfeldmann/git", - "version": "3.16.0", + "version": "3.8.4", "source": { "type": "git", "url": "https://github.com/sebastianfeldmann/git.git", - "reference": "40a5cc043f0957228767f639e370ec92590e940f" + "reference": "b324b6ba21871709812e34ad278a82c2e1c2965b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianfeldmann/git/zipball/40a5cc043f0957228767f639e370ec92590e940f", - "reference": "40a5cc043f0957228767f639e370ec92590e940f", + "url": "https://api.github.com/repos/sebastianfeldmann/git/zipball/b324b6ba21871709812e34ad278a82c2e1c2965b", + "reference": "b324b6ba21871709812e34ad278a82c2e1c2965b", "shasum": "" }, "require": { "ext-json": "*", - "ext-libxml": "*", - "ext-simplexml": "*", - "php": ">=8.0", + "ext-xml": "*", + "php": ">=7.2", "sebastianfeldmann/cli": "^3.0" }, "require-dev": { @@ -7296,9 +4904,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Sebastian Feldmann", @@ -7307,12 +4913,10 @@ ], "description": "PHP git wrapper", "homepage": "https://github.com/sebastianfeldmann/git", - "keywords": [ - "git" - ], + "keywords": ["git"], "support": { "issues": "https://github.com/sebastianfeldmann/git/issues", - "source": "https://github.com/sebastianfeldmann/git/tree/3.16.0" + "source": "https://github.com/sebastianfeldmann/git/tree/3.8.4" }, "funding": [ { @@ -7320,109 +4924,136 @@ "type": "github" } ], - "time": "2026-01-26T20:59:18+00:00" + "time": "2022-08-26T07:03:13+00:00" }, { - "name": "staabm/side-effects-detector", - "version": "1.0.5", + "name": "symfony/config", + "version": "v6.1.3", "source": { "type": "git", - "url": "https://github.com/staabm/side-effects-detector.git", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + "url": "https://github.com/symfony/config.git", + "reference": "a0645dc585d378b73c01115dd7ab9348f7d40c85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "url": "https://api.github.com/repos/symfony/config/zipball/a0645dc585d378b73c01115dd7ab9348f7d40c85", + "reference": "a0645dc585d378b73c01115dd7ab9348f7d40c85", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/filesystem": "^5.4|^6.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<5.4" }, "require-dev": { - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^1.12.6", - "phpunit/phpunit": "^9.6.21", - "symfony/var-dumper": "^5.4.43", - "tomasvotruba/type-coverage": "1.0.0", - "tomasvotruba/unused-public": "1.0.0" + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" }, "type": "library", "autoload": { - "classmap": [ - "lib/" - ] + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A static analysis tool to detect side effects in PHP code", - "keywords": [ - "static analysis" + "license": ["MIT"], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/staabm/side-effects-detector/issues", - "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + "source": "https://github.com/symfony/config/tree/v6.1.3" }, "funding": [ { - "url": "https://github.com/staabm", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-10-20T05:08:20+00:00" + "time": "2022-07-20T15:00:40+00:00" }, { "name": "symfony/console", - "version": "v8.0.4", + "version": "v6.1.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "ace03c4cf9805080ff40cbeec69fca180c339a3b" + "reference": "7fa3b9cf17363468795e539231a5c91b02b608fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/ace03c4cf9805080ff40cbeec69fca180c339a3b", - "reference": "ace03c4cf9805080ff40cbeec69fca180c339a3b", + "url": "https://api.github.com/repos/symfony/console/zipball/7fa3b9cf17363468795e539231a5c91b02b608fc", + "reference": "7fa3b9cf17363468795e539231a5c91b02b608fc", "shasum": "" }, "require": { - "php": ">=8.4", - "symfony/polyfill-mbstring": "^1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.4|^8.0" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/event-dispatcher": "^7.4|^8.0", - "symfony/http-foundation": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/lock": "^7.4|^8.0", - "symfony/messenger": "^7.4|^8.0", - "symfony/process": "^7.4|^8.0", - "symfony/stopwatch": "^7.4|^8.0", - "symfony/var-dumper": "^7.4|^8.0" + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -7435,14 +5066,9 @@ ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], + "keywords": ["cli", "command line", "console", "terminal"], "support": { - "source": "https://github.com/symfony/console/tree/v8.0.4" + "source": "https://github.com/symfony/console/tree/v6.1.6" }, "funding": [ { @@ -7454,7 +5080,86 @@ "type": "github" }, { - "url": "https://github.com/nicolas-grekas", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-10-07T08:04:03+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "b9c797c9d56afc290d4265854bafd01b4e379240" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b9c797c9d56afc290d4265854bafd01b4e379240", + "reference": "b9c797c9d56afc290d4265854bafd01b4e379240", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/service-contracts": "^1.1.6|^2.0|^3.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2", + "symfony/config": "<6.1", + "symfony/finder": "<5.4", + "symfony/proxy-manager-bridge": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "symfony/service-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "symfony/config": "^6.1", + "symfony/expression-language": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": ["/Tests/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows you to standardize and centralize the way objects are constructed in your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v6.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" }, { @@ -7462,29 +5167,28 @@ "type": "tidelift" } ], - "time": "2026-01-13T13:06:50+00:00" + "time": "2022-09-28T16:00:52+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v8.0.4", + "version": "v6.1.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "99301401da182b6cfaa4700dbe9987bb75474b47" + "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99301401da182b6cfaa4700dbe9987bb75474b47", - "reference": "99301401da182b6cfaa4700dbe9987bb75474b47", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a0449a7ad7daa0f7c0acd508259f80544ab5a347", + "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347", "shasum": "" }, "require": { - "php": ">=8.4", - "symfony/event-dispatcher-contracts": "^2.5|^3" + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2|^3" }, "conflict": { - "symfony/security-http": "<7.4", - "symfony/service-contracts": "<2.5" + "symfony/dependency-injection": "<5.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", @@ -7492,28 +5196,27 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/error-handler": "^7.4|^8.0", - "symfony/expression-language": "^7.4|^8.0", - "symfony/framework-bundle": "^7.4|^8.0", - "symfony/http-foundation": "^7.4|^8.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^7.4|^8.0" + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^5.4|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -7527,7 +5230,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.4" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.1.0" }, "funding": [ { @@ -7538,43 +5241,42 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2026-01-05T11:45:55+00:00" + "time": "2022-05-05T16:51:07+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.6.0", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + "reference": "02ff5eea2f453731cfbc6bc215e456b781480448" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/02ff5eea2f453731cfbc6bc215e456b781480448", + "reference": "02ff5eea2f453731cfbc6bc215e456b781480448", "shasum": "" }, "require": { "php": ">=8.1", "psr/event-dispatcher": "^1" }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -7583,9 +5285,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -7607,7 +5307,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.1.1" }, "funding": [ { @@ -7623,41 +5323,96 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2022-02-25T11:15:52+00:00" }, { - "name": "symfony/finder", - "version": "v8.0.5", + "name": "symfony/filesystem", + "version": "v6.1.5", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0" + "url": "https://github.com/symfony/filesystem.git", + "reference": "4d216a2beef096edf040a070117c39ca2abce307" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8bd576e97c67d45941365bf824e18dc8538e6eb0", - "reference": "8bd576e97c67d45941365bf824e18dc8538e6eb0", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4d216a2beef096edf040a070117c39ca2abce307", + "reference": "4d216a2beef096edf040a070117c39ca2abce307", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": ["/Tests/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v6.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-09-21T20:29:40+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709", + "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709", + "shasum": "" + }, + "require": { + "php": ">=8.1" }, "require-dev": { - "symfony/filesystem": "^7.4|^8.0" + "symfony/filesystem": "^6.0" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -7671,7 +5426,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v8.0.5" + "source": "https://github.com/symfony/finder/tree/v6.1.3" }, "funding": [ { @@ -7682,48 +5437,40 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2026-01-26T15:08:38+00:00" + "time": "2022-07-29T07:42:06+00:00" }, { "name": "symfony/options-resolver", - "version": "v8.0.0", + "version": "v6.1.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7" + "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7", - "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a3016f5442e28386ded73c43a32a5b68586dd1c4", + "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4", "shasum": "" }, "require": { - "php": ">=8.4", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -7736,13 +5483,9 @@ ], "description": "Provides an improved replacement for the array_replace PHP function", "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], + "keywords": ["config", "configuration", "options"], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v8.0.0" + "source": "https://github.com/symfony/options-resolver/tree/v6.1.0" }, "funding": [ { @@ -7753,56 +5496,51 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-11-12T15:55:31+00:00" + "time": "2022-02-25T11:15:52+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + "reference": "433d05519ce6990bf3530fba6957499d327395c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", + "reference": "433d05519ce6990bf3530fba6957499d327395c2", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -7824,7 +5562,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" }, "funding": [ { @@ -7835,59 +5573,52 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T09:58:17+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", + "version": "v1.26.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "reference": "219aa369ceff116e673852dce47c3a41794c14bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", + "reference": "219aa369ceff116e673852dce47c3a41794c14bd", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "files": [ - "bootstrap.php" - ], + "files": ["bootstrap.php"], "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, - "classmap": [ - "Resources/stubs" - ] + "classmap": ["Resources/stubs"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -7909,7 +5640,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" }, "funding": [ { @@ -7920,207 +5651,39 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-php84", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php84\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-06-24T13:30:11+00:00" + "time": "2022-05-24T11:49:31+00:00" }, { "name": "symfony/process", - "version": "v8.0.5", + "version": "v6.1.3", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674" + "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", - "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", + "url": "https://api.github.com/repos/symfony/process/zipball/a6506e99cfad7059b1ab5cab395854a0a0c21292", + "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292", "shasum": "" }, "require": { - "php": ">=8.4" + "php": ">=8.1" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -8134,7 +5697,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v8.0.5" + "source": "https://github.com/symfony/process/tree/v6.1.3" }, "funding": [ { @@ -8145,61 +5708,55 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2026-01-26T15:08:38+00:00" + "time": "2022-06-27T17:24:16+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.6.1", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239", + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, + "suggest": { + "symfony/service-implementation": "" + }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" }, - "exclude-from-classmap": [ - "/Test/" - ] + "exclude-from-classmap": ["/Test/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -8221,7 +5778,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.1.1" }, "funding": [ { @@ -8232,48 +5789,40 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-07-15T11:30:57+00:00" + "time": "2022-05-30T19:18:58+00:00" }, { "name": "symfony/stopwatch", - "version": "v8.0.0", + "version": "v6.1.5", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942" + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/67df1914c6ccd2d7b52f70d40cf2aea02159d942", - "reference": "67df1914c6ccd2d7b52f70d40cf2aea02159d942", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/266636bb8f3fbdccc302491df7b3a1b9a8c238a7", + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7", "shasum": "" }, "require": { - "php": ">=8.4", - "symfony/service-contracts": "^2.5|^3" + "php": ">=8.1", + "symfony/service-contracts": "^1|^2|^3" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Fabien Potencier", @@ -8287,7 +5836,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v8.0.0" + "source": "https://github.com/symfony/stopwatch/tree/v6.1.5" }, "funding": [ { @@ -8298,64 +5847,53 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-08-04T07:36:47+00:00" + "time": "2022-09-28T16:00:52+00:00" }, { "name": "symfony/string", - "version": "v8.0.4", + "version": "v6.1.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "758b372d6882506821ed666032e43020c4f57194" + "reference": "7e7e0ff180d4c5a6636eaad57b65092014b61864" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/758b372d6882506821ed666032e43020c4f57194", - "reference": "758b372d6882506821ed666032e43020c4f57194", + "url": "https://api.github.com/repos/symfony/string/zipball/7e7e0ff180d4c5a6636eaad57b65092014b61864", + "reference": "7e7e0ff180d4c5a6636eaad57b65092014b61864", "shasum": "" }, "require": { - "php": ">=8.4", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-intl-grapheme": "^1.33", - "symfony/polyfill-intl-normalizer": "^1.0", - "symfony/polyfill-mbstring": "^1.0" + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.5" + "symfony/translation-contracts": "<2.0" }, "require-dev": { - "symfony/emoji": "^7.4|^8.0", - "symfony/http-client": "^7.4|^8.0", - "symfony/intl": "^7.4|^8.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^7.4|^8.0" + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", "autoload": { - "files": [ - "Resources/functions.php" - ], + "files": ["Resources/functions.php"], "psr-4": { "Symfony\\Component\\String\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "exclude-from-classmap": ["/Tests/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "authors": [ { "name": "Nicolas Grekas", @@ -8368,16 +5906,9 @@ ], "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], + "keywords": ["grapheme", "i18n", "string", "unicode", "utf-8", "utf8"], "support": { - "source": "https://github.com/symfony/string/tree/v8.0.4" + "source": "https://github.com/symfony/string/tree/v6.1.6" }, "funding": [ { @@ -8388,62 +5919,163 @@ "url": "https://github.com/fabpot", "type": "github" }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2026-01-12T12:37:40+00:00" + "time": "2022-10-10T09:34:31+00:00" }, { - "name": "symplify/coding-standard", - "version": "13.0.0", + "name": "symplify/autowire-array-parameter", + "version": "10.3.3", "source": { "type": "git", - "url": "https://github.com/symplify/coding-standard.git", - "reference": "bd7c36af1e96eecd08cfcc0a772a19767aa02300" + "url": "https://github.com/symplify/autowire-array-parameter.git", + "reference": "e3ca795122712fab224a5c10339b1fb278505420" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symplify/coding-standard/zipball/bd7c36af1e96eecd08cfcc0a772a19767aa02300", - "reference": "bd7c36af1e96eecd08cfcc0a772a19767aa02300", + "url": "https://api.github.com/repos/symplify/autowire-array-parameter/zipball/e3ca795122712fab224a5c10339b1fb278505420", + "reference": "e3ca795122712fab224a5c10339b1fb278505420", "shasum": "" }, "require": { - "friendsofphp/php-cs-fixer": "^3.89", - "nette/utils": "^4.0", - "php": ">=8.2" + "nette/utils": "^3.2", + "php": ">=8.0", + "symfony/dependency-injection": "^6.0", + "symplify/package-builder": "^10.3.3" + }, + "conflict": { + "symplify/astral": "<10.3.3", + "symplify/coding-standard": "<10.3.3", + "symplify/composer-json-manipulator": "<10.3.3", + "symplify/config-transformer": "<10.3.3", + "symplify/easy-ci": "<10.3.3", + "symplify/easy-coding-standard": "<10.3.3", + "symplify/easy-parallel": "<10.3.3", + "symplify/easy-testing": "<10.3.3", + "symplify/monorepo-builder": "<10.3.3", + "symplify/neon-config-dumper": "<10.3.3", + "symplify/php-config-printer": "<10.3.3", + "symplify/phpstan-extensions": "<10.3.3", + "symplify/phpstan-rules": "<10.3.3", + "symplify/rule-doc-generator": "<10.3.3", + "symplify/rule-doc-generator-contracts": "<10.3.3", + "symplify/skipper": "<10.3.3", + "symplify/smart-file-system": "<10.3.3", + "symplify/symfony-static-dumper": "<10.3.3", + "symplify/symplify-kernel": "<10.3.3", + "symplify/vendor-patches": "<10.3.3" }, "require-dev": { - "phpstan/extension-installer": "^1.4", - "phpstan/phpstan": "^2.1", - "phpunit/phpunit": "^11.5|^12.0", - "rector/jack": "^0.2", - "rector/rector": "^2.2", - "squizlabs/php_codesniffer": "^4.0", - "symplify/easy-coding-standard": "^12.6", - "symplify/phpstan-extensions": "^12.0", - "tomasvotruba/class-leak": "^2.0", - "tracy/tracy": "^2.11" + "phpunit/phpunit": "^9.5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symplify\\AutowireArrayParameter\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "description": "Autowire array parameters for your Symfony applications", + "support": { + "source": "https://github.com/symplify/autowire-array-parameter/tree/10.3.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-06-13T14:05:31+00:00" + }, + { + "name": "symplify/coding-standard", + "version": "10.3.3", + "source": { + "type": "git", + "url": "https://github.com/symplify/coding-standard.git", + "reference": "07e8a9f67dd74ede6038dc70750654449e80e9ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/coding-standard/zipball/07e8a9f67dd74ede6038dc70750654449e80e9ab", + "reference": "07e8a9f67dd74ede6038dc70750654449e80e9ab", + "shasum": "" + }, + "require": { + "friendsofphp/php-cs-fixer": "^3.8", + "nette/utils": "^3.2", + "php": ">=8.0", + "symplify/autowire-array-parameter": "^10.3.3", + "symplify/package-builder": "^10.3.3", + "symplify/rule-doc-generator-contracts": "^10.3.3", + "symplify/symplify-kernel": "^10.3.3" + }, + "conflict": { + "symplify/astral": "<10.3.3", + "symplify/composer-json-manipulator": "<10.3.3", + "symplify/config-transformer": "<10.3.3", + "symplify/easy-ci": "<10.3.3", + "symplify/easy-coding-standard": "<10.3.3", + "symplify/easy-parallel": "<10.3.3", + "symplify/easy-testing": "<10.3.3", + "symplify/monorepo-builder": "<10.3.3", + "symplify/neon-config-dumper": "<10.3.3", + "symplify/php-config-printer": "<10.3.3", + "symplify/phpstan-extensions": "<10.3.3", + "symplify/phpstan-rules": "<10.3.3", + "symplify/rule-doc-generator": "<10.3.3", + "symplify/skipper": "<10.3.3", + "symplify/smart-file-system": "<10.3.3", + "symplify/symfony-static-dumper": "<10.3.3", + "symplify/vendor-patches": "<10.3.3" + }, + "require-dev": { + "cweagans/composer-patches": "^1.7", + "doctrine/orm": "^2.10", + "nette/application": "^3.1", + "nette/bootstrap": "^3.1", + "phpunit/phpunit": "^9.5", + "symfony/framework-bundle": "^6.0", + "symplify/easy-coding-standard": "^10.3.3", + "symplify/rule-doc-generator": "^10.3.3", + "symplify/smart-file-system": "^10.3.3", + "symplify/symplify-kernel": "^10.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.4-dev" + }, + "enable-patching": true, + "patches": { + "symfony/dependency-injection": [ + "https://raw.githubusercontent.com/symplify/vendor-patch-files/main/patches/generic-php-config-loader.patch" + ] + } + }, "autoload": { "psr-4": { "Symplify\\CodingStandard\\": "src" } }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], + "license": ["MIT"], "description": "Set of Symplify rules for PHP_CodeSniffer and PHP CS Fixer.", "support": { - "issues": "https://github.com/symplify/coding-standard/issues", - "source": "https://github.com/symplify/coding-standard/tree/13.0.0" + "source": "https://github.com/symplify/coding-standard/tree/10.3.3" }, "funding": [ { @@ -8455,56 +6087,121 @@ "type": "github" } ], - "time": "2025-10-30T21:46:47+00:00" + "time": "2022-06-13T14:05:35+00:00" }, { - "name": "symplify/easy-coding-standard", - "version": "13.0.4", + "name": "symplify/composer-json-manipulator", + "version": "10.3.3", "source": { "type": "git", - "url": "https://github.com/easy-coding-standard/easy-coding-standard.git", - "reference": "5c7e7a07e5d6a98b9dd2e6fc0a9155efb7c166c8" + "url": "https://github.com/symplify/composer-json-manipulator.git", + "reference": "84f716bd543d946921c4ef6d2197a9f2877c7691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/5c7e7a07e5d6a98b9dd2e6fc0a9155efb7c166c8", - "reference": "5c7e7a07e5d6a98b9dd2e6fc0a9155efb7c166c8", + "url": "https://api.github.com/repos/symplify/composer-json-manipulator/zipball/84f716bd543d946921c4ef6d2197a9f2877c7691", + "reference": "84f716bd543d946921c4ef6d2197a9f2877c7691", + "shasum": "" + }, + "require": { + "nette/utils": "^3.2", + "php": ">=8.0", + "symfony/config": "^6.0", + "symfony/dependency-injection": "^6.0", + "symfony/filesystem": "^6.0", + "symplify/package-builder": "^10.3.3", + "symplify/smart-file-system": "^10.3.3", + "symplify/symplify-kernel": "^10.3.3" + }, + "conflict": { + "symplify/astral": "<10.3.3", + "symplify/autowire-array-parameter": "<10.3.3", + "symplify/coding-standard": "<10.3.3", + "symplify/config-transformer": "<10.3.3", + "symplify/easy-ci": "<10.3.3", + "symplify/easy-coding-standard": "<10.3.3", + "symplify/easy-parallel": "<10.3.3", + "symplify/easy-testing": "<10.3.3", + "symplify/monorepo-builder": "<10.3.3", + "symplify/neon-config-dumper": "<10.3.3", + "symplify/php-config-printer": "<10.3.3", + "symplify/phpstan-extensions": "<10.3.3", + "symplify/phpstan-rules": "<10.3.3", + "symplify/rule-doc-generator": "<10.3.3", + "symplify/rule-doc-generator-contracts": "<10.3.3", + "symplify/skipper": "<10.3.3", + "symplify/symfony-static-dumper": "<10.3.3", + "symplify/symplify-kernel": "<9.4.70", + "symplify/vendor-patches": "<10.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-main": "10.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symplify\\ComposerJsonManipulator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "description": "Package to load, merge and save composer.json file(s)", + "support": { + "source": "https://github.com/symplify/composer-json-manipulator/tree/10.3.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-06-13T14:06:01+00:00" + }, + { + "name": "symplify/easy-coding-standard", + "version": "10.3.3", + "source": { + "type": "git", + "url": "https://github.com/symplify/easy-coding-standard.git", + "reference": "c93878b3c052321231519b6540e227380f90be17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/easy-coding-standard/zipball/c93878b3c052321231519b6540e227380f90be17", + "reference": "c93878b3c052321231519b6540e227380f90be17", "shasum": "" }, "require": { "php": ">=7.2" }, "conflict": { - "friendsofphp/php-cs-fixer": "<3.92.4", - "phpcsstandards/php_codesniffer": "<4.0.1", - "symplify/coding-standard": "<12.1" + "friendsofphp/php-cs-fixer": "<3.0", + "squizlabs/php_codesniffer": "<3.6" }, - "suggest": { - "ext-dom": "Needed to support checkstyle output format in class CheckstyleOutputFormatter" - }, - "bin": [ - "bin/ecs" - ], + "bin": ["bin/ecs"], "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.3-dev" + } + }, "autoload": { - "files": [ - "bootstrap.php" - ] + "files": ["bootstrap.php"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer", - "keywords": [ - "Code style", - "automation", - "fixer", - "static analysis" - ], + "license": ["MIT"], + "description": "Prefixed scoped version of ECS package", "support": { - "issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues", - "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/13.0.4" + "source": "https://github.com/symplify/easy-coding-standard/tree/10.3.3" }, "funding": [ { @@ -8516,38 +6213,400 @@ "type": "github" } ], - "time": "2026-01-05T09:10:04+00:00" + "time": "2022-06-13T14:03:37+00:00" }, { - "name": "theseer/tokenizer", - "version": "2.0.1", + "name": "symplify/easy-testing", + "version": "10.3.3", "source": { "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4" + "url": "https://github.com/symplify/easy-testing.git", + "reference": "d4a78c8d55282143754d9be0d9577865394c073c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/7989e43bf381af0eac72e4f0ca5bcbfa81658be4", - "reference": "7989e43bf381af0eac72e4f0ca5bcbfa81658be4", + "url": "https://api.github.com/repos/symplify/easy-testing/zipball/d4a78c8d55282143754d9be0d9577865394c073c", + "reference": "d4a78c8d55282143754d9be0d9577865394c073c", + "shasum": "" + }, + "require": { + "nette/utils": "^3.2", + "php": ">=8.0", + "symfony/console": "^6.0", + "symfony/dependency-injection": "^6.0", + "symfony/finder": "^6.0", + "symplify/package-builder": "^10.3.3", + "symplify/smart-file-system": "^10.3.3", + "symplify/symplify-kernel": "^10.3.3" + }, + "conflict": { + "symplify/astral": "<10.3.3", + "symplify/autowire-array-parameter": "<10.3.3", + "symplify/coding-standard": "<10.3.3", + "symplify/composer-json-manipulator": "<10.3.3", + "symplify/config-transformer": "<10.3.3", + "symplify/easy-ci": "<10.3.3", + "symplify/easy-coding-standard": "<10.3.3", + "symplify/easy-parallel": "<10.3.3", + "symplify/monorepo-builder": "<10.3.3", + "symplify/neon-config-dumper": "<10.3.3", + "symplify/php-config-printer": "<10.3.3", + "symplify/phpstan-extensions": "<10.3.3", + "symplify/phpstan-rules": "<10.3.3", + "symplify/rule-doc-generator": "<10.3.3", + "symplify/rule-doc-generator-contracts": "<10.3.3", + "symplify/skipper": "<10.3.3", + "symplify/symfony-static-dumper": "<10.3.3", + "symplify/vendor-patches": "<10.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "bin": ["bin/easy-testing"], + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-main": "10.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symplify\\EasyTesting\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "description": "Testing made easy", + "support": { + "source": "https://github.com/symplify/easy-testing/tree/10.3.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-06-13T14:05:39+00:00" + }, + { + "name": "symplify/package-builder", + "version": "10.3.3", + "source": { + "type": "git", + "url": "https://github.com/symplify/package-builder.git", + "reference": "bc785e064429f2341d035cc88cc954a56f220040" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/package-builder/zipball/bc785e064429f2341d035cc88cc954a56f220040", + "reference": "bc785e064429f2341d035cc88cc954a56f220040", + "shasum": "" + }, + "require": { + "nette/utils": "^3.2", + "php": ">=8.0", + "sebastian/diff": "^4.0", + "symfony/config": "^6.0", + "symfony/console": "^6.0", + "symfony/dependency-injection": "^6.0", + "symfony/finder": "^6.0", + "symplify/easy-testing": "^10.3.3", + "symplify/symplify-kernel": "^10.3.3" + }, + "conflict": { + "symplify/astral": "<10.3.3", + "symplify/autowire-array-parameter": "<10.3.3", + "symplify/coding-standard": "<10.3.3", + "symplify/composer-json-manipulator": "<10.3.3", + "symplify/config-transformer": "<10.3.3", + "symplify/easy-ci": "<10.3.3", + "symplify/easy-coding-standard": "<10.3.3", + "symplify/easy-parallel": "<10.3.3", + "symplify/monorepo-builder": "<10.3.3", + "symplify/neon-config-dumper": "<10.3.3", + "symplify/php-config-printer": "<10.3.3", + "symplify/phpstan-extensions": "<10.3.3", + "symplify/phpstan-rules": "<10.3.3", + "symplify/rule-doc-generator": "<10.3.3", + "symplify/rule-doc-generator-contracts": "<10.3.3", + "symplify/skipper": "<10.3.3", + "symplify/smart-file-system": "<10.3.3", + "symplify/symfony-static-dumper": "<10.3.3", + "symplify/vendor-patches": "<10.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symplify\\PackageBuilder\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "description": "Dependency Injection, Console and Kernel toolkit for Symplify packages.", + "support": { + "source": "https://github.com/symplify/package-builder/tree/10.3.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-06-13T14:05:45+00:00" + }, + { + "name": "symplify/rule-doc-generator-contracts", + "version": "10.3.3", + "source": { + "type": "git", + "url": "https://github.com/symplify/rule-doc-generator-contracts.git", + "reference": "6c5f2661fdd9a290d455b31aa3619c80702119cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/rule-doc-generator-contracts/zipball/6c5f2661fdd9a290d455b31aa3619c80702119cd", + "reference": "6c5f2661fdd9a290d455b31aa3619c80702119cd", + "shasum": "" + }, + "require": { + "nette/utils": "^3.2", + "php": ">=8.0" + }, + "conflict": { + "symplify/astral": "<10.3.3", + "symplify/autowire-array-parameter": "<10.3.3", + "symplify/coding-standard": "<10.3.3", + "symplify/composer-json-manipulator": "<10.3.3", + "symplify/config-transformer": "<10.3.3", + "symplify/easy-ci": "<10.3.3", + "symplify/easy-coding-standard": "<10.3.3", + "symplify/easy-parallel": "<10.3.3", + "symplify/easy-testing": "<10.3.3", + "symplify/monorepo-builder": "<10.3.3", + "symplify/neon-config-dumper": "<10.3.3", + "symplify/package-builder": "<10.3.3", + "symplify/php-config-printer": "<10.3.3", + "symplify/phpstan-extensions": "<10.3.3", + "symplify/phpstan-rules": "<10.3.3", + "symplify/rule-doc-generator": "<10.3.3", + "symplify/skipper": "<10.3.3", + "symplify/smart-file-system": "<10.3.3", + "symplify/symfony-static-dumper": "<10.3.3", + "symplify/symplify-kernel": "<10.3.3", + "symplify/vendor-patches": "<10.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symplify\\RuleDocGenerator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "description": "Contracts for production code of RuleDocGenerator", + "support": { + "source": "https://github.com/symplify/rule-doc-generator-contracts/tree/10.3.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-06-13T14:03:35+00:00" + }, + { + "name": "symplify/smart-file-system", + "version": "10.3.3", + "source": { + "type": "git", + "url": "https://github.com/symplify/smart-file-system.git", + "reference": "0b465fcf7490ac89708510551a044961b9124493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/smart-file-system/zipball/0b465fcf7490ac89708510551a044961b9124493", + "reference": "0b465fcf7490ac89708510551a044961b9124493", + "shasum": "" + }, + "require": { + "nette/utils": "^3.2", + "php": ">=8.0", + "symfony/filesystem": "^6.0", + "symfony/finder": "^6.0" + }, + "conflict": { + "symplify/astral": "<10.3.3", + "symplify/autowire-array-parameter": "<10.3.3", + "symplify/coding-standard": "<10.3.3", + "symplify/composer-json-manipulator": "<10.3.3", + "symplify/config-transformer": "<10.3.3", + "symplify/easy-ci": "<10.3.3", + "symplify/easy-coding-standard": "<10.3.3", + "symplify/easy-parallel": "<10.3.3", + "symplify/easy-testing": "<10.3.3", + "symplify/monorepo-builder": "<10.3.3", + "symplify/neon-config-dumper": "<10.3.3", + "symplify/package-builder": "<10.3.3", + "symplify/php-config-printer": "<10.3.3", + "symplify/phpstan-extensions": "<10.3.3", + "symplify/phpstan-rules": "<10.3.3", + "symplify/rule-doc-generator": "<10.3.3", + "symplify/rule-doc-generator-contracts": "<10.3.3", + "symplify/skipper": "<10.3.3", + "symplify/symfony-static-dumper": "<10.3.3", + "symplify/symplify-kernel": "<10.3.3", + "symplify/vendor-patches": "<10.3.3" + }, + "require-dev": { + "nette/finder": "^2.5", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symplify\\SmartFileSystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "description": "Sanitized FileInfo with safe getRealPath() and other handy methods", + "support": { + "source": "https://github.com/symplify/smart-file-system/tree/10.3.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2022-06-13T14:03:57+00:00" + }, + { + "name": "symplify/symplify-kernel", + "version": "10.3.3", + "source": { + "type": "git", + "url": "https://github.com/symplify/symplify-kernel.git", + "reference": "951838b8c4cee31c347a132755428c39437585c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/symplify-kernel/zipball/951838b8c4cee31c347a132755428c39437585c8", + "reference": "951838b8c4cee31c347a132755428c39437585c8", + "shasum": "" + }, + "require": { + "php": ">=8.0", + "symfony/console": "^6.0", + "symfony/dependency-injection": "^6.0", + "symplify/autowire-array-parameter": "^10.3.3", + "symplify/composer-json-manipulator": "^10.3.3", + "symplify/package-builder": "^10.3.3", + "symplify/smart-file-system": "^10.3.3", + "webmozart/assert": "^1.10" + }, + "conflict": { + "symplify/astral": "<10.3.3", + "symplify/coding-standard": "<10.3.3", + "symplify/config-transformer": "<10.3.3", + "symplify/easy-ci": "<10.3.3", + "symplify/easy-coding-standard": "<10.3.3", + "symplify/easy-parallel": "<10.3.3", + "symplify/easy-testing": "<10.3.3", + "symplify/monorepo-builder": "<10.3.3", + "symplify/neon-config-dumper": "<10.3.3", + "symplify/php-config-printer": "<10.3.3", + "symplify/phpstan-extensions": "<10.3.3", + "symplify/phpstan-rules": "<10.3.3", + "symplify/rule-doc-generator": "<10.3.3", + "symplify/rule-doc-generator-contracts": "<10.3.3", + "symplify/skipper": "<10.3.3", + "symplify/symfony-static-dumper": "<10.3.3", + "symplify/vendor-patches": "<10.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symplify\\SymplifyKernel\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "description": "Internal Kernel for Symplify packages", + "support": { + "source": "https://github.com/symplify/symplify-kernel/tree/10.3.3" + }, + "time": "2022-06-13T14:06:24+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": "^8.1" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "classmap": ["src/"] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], + "license": ["BSD-3-Clause"], "authors": [ { "name": "Arne Blankerts", @@ -8558,7 +6617,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/2.0.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" }, "funding": [ { @@ -8566,22 +6625,73 @@ "type": "github" } ], - "time": "2025-12-08T11:19:18+00:00" + "time": "2021-07-28T10:34:58+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": ["assert", "check", "validate"], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" } ], "aliases": [], - "minimum-stability": "dev", + "minimum-stability": "stable", "stability-flags": { - "adaures/castopod-plugins-manager": 20, - "codeigniter4/tasks": 20, - "opawg/user-agents-v2-php": 20, - "yassinedoghri/podcast-feed": 20 + "james-heinrich/getid3": 20, + "myth/auth": 20, + "michalsn/codeigniter4-uuid": 20 }, "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.4" + "php": "^8.0" }, - "platform-dev": {}, - "plugin-api-version": "2.9.0" + "platform-dev": [], + "plugin-api-version": "2.3.0" } diff --git a/crontab b/crontab new file mode 100644 index 00000000..3589b3e9 --- /dev/null +++ b/crontab @@ -0,0 +1,3 @@ +* * * * * /usr/local/bin/php /castopod/public/index.php scheduled-activities +* * * * * /usr/local/bin/php /castopod/public/index.php scheduled-video-clips +* * * * * /usr/local/bin/php /castopod/public/index.php scheduled-websub-publish diff --git a/crowdin.yml b/crowdin.yml index 944c6241..7f46417d 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -4,5 +4,7 @@ files: translation: /app/Language/%osx_locale%/%original_file_name% - source: /modules/**/Language/en/*.php translation: /modules/**/Language/%osx_locale%/%original_file_name% - - source: /docs/src/content/docs/en/**/*.mdx - translation: /docs/src/content/docs/%osx_locale%/**/%original_file_name% + - source: /docs/src/getting-started/*.md + translation: /docs/src/%osx_locale%/getting-started/%original_file_name% + - source: /docs/src/index.md + translation: /docs/src/%osx_locale%/index.md diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..52a712c7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,67 @@ +version: "3" + +networks: + castopod: + +services: + app: + build: + context: . + dockerfile: docker/development/Dockerfile + container_name: app + command: /bin/sh -c "crontab ./crontab && cron && service cron reload && php spark serve - 0.0.0.0" + ports: + - 8080:8080 + volumes: + - .:/castopod + depends_on: + - redis + - mariadb + networks: + - castopod + + redis: + image: redis:alpine + container_name: castopod_redis + ports: + - 6379:6379 + volumes: + - redis:/data + networks: + - castopod + + mariadb: + image: mariadb:10.2 + container_name: castopod_mariadb + ports: + - 3306:3306 + volumes: + - ./initdb:/docker-entrypoint-initdb.d + - mariadb:/var/lib/mysql + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: castopod + MYSQL_USER: castopod + MYSQL_PASSWORD: castopod + networks: + - castopod + + phpmyadmin: + image: phpmyadmin/phpmyadmin:latest + container_name: castopod_phpmyadmin + environment: + PMA_HOST: mariadb + PMA_PORT: 3306 + ports: + - 8888:80 + volumes: + - phpmyadmin:/sessions + depends_on: + - mariadb + networks: + - castopod + +volumes: + redis: + mariadb: + phpmyadmin: diff --git a/docker/ci/Dockerfile b/docker/ci/Dockerfile deleted file mode 100644 index bae95838..00000000 --- a/docker/ci/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -#################################################### -# Castopod CI/CD docker file -#################################################### -# ⚠️ NOT optimized for production -# should be used only for continuous integration -#--------------------------------------------------- -FROM php:8.5-fpm-alpine3.23 - -LABEL maintainer="Yassine Doghri " - -RUN \ - # install composer - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer \ - # install ci requirements - && apk add --no-cache \ - nodejs \ - # install npm for @semantic-release/npm - npm \ - git \ - unzip \ - wget \ - jq \ - zip \ - openssh-client \ - rsync \ - icu-libs \ - mysql \ - mysql-client \ - && apk add --no-cache --virtual .php-ext-build-dep icu-dev \ - && docker-php-ext-install \ - intl \ - mysqli \ - && apk del .php-ext-build-dep \ - # install pnpm - && npm install --global corepack@latest \ - && corepack enable pnpm \ - # set pnpm store directory - && pnpm config set store-dir .pnpm-store \ - # set composer cache directory - && composer config -g cache-dir .composer-cache diff --git a/.devcontainer/Dockerfile b/docker/development/Dockerfile similarity index 68% rename from .devcontainer/Dockerfile rename to docker/development/Dockerfile index cca42fb0..b99f9539 100644 --- a/.devcontainer/Dockerfile +++ b/docker/development/Dockerfile @@ -4,20 +4,31 @@ # ⚠️ NOT optimized for production # should be used only for development purposes #--------------------------------------------------- -FROM php:8.5-fpm +FROM php:8.1-fpm LABEL maintainer="Yassine Doghri " +COPY . /castopod +WORKDIR /castopod + # Install composer COPY --from=composer:2 /usr/bin/composer /usr/bin/composer # Install server requirements -RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ +RUN apt-get update \ + # gnupg to sign commits with gpg + && apt-get install --yes --no-install-recommends gnupg \ + # npm through the nodejs package + && curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \ && apt-get update \ && apt-get install --yes --no-install-recommends nodejs \ - # gnupg to sign commits with gpg - gnupg \ + # update npm + && npm install --global npm@8 \ + && apt-get update \ + && apt-get install --yes --no-install-recommends \ + git \ openssh-client \ + vim \ # cron for scheduled tasks cron \ # unzip used by composer @@ -27,7 +38,7 @@ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ libicu-dev \ libpng-dev \ libwebp-dev \ - libjpeg62-turbo-dev \ + libjpeg-dev \ libfreetype6-dev \ zlib1g-dev \ libzip-dev \ @@ -47,4 +58,11 @@ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ && docker-php-ext-enable redis \ # mysqli for database access && docker-php-ext-install mysqli \ - && docker-php-ext-enable mysqli + && docker-php-ext-enable mysqli \ + # configure php + && echo "file_uploads = On\n" \ + "memory_limit = 512M\n" \ + "upload_max_filesize = 500M\n" \ + "post_max_size = 512M\n" \ + "max_execution_time = 300\n" \ + > /usr/local/etc/php/conf.d/uploads.ini diff --git a/docker/production/.gitlab-ci.yml b/docker/production/.gitlab-ci.yml index 6256cc13..2a8c05e7 100644 --- a/docker/production/.gitlab-ci.yml +++ b/docker/production/.gitlab-ci.yml @@ -4,109 +4,54 @@ stages: docker-build-rolling: stage: build image: - name: docker.io/docker:29.2-dind - services: - - docker:29.2-dind + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] variables: TAG: $CI_COMMIT_BRANCH - DOCKER_BUILDKIT: 1 - DOCKER_HOST: tcp://docker:2376 - DOCKER_TLS_CERTDIR: "/certs" - before_script: - # ensure the Docker config directory exists - - mkdir -p /root/.docker - # copy credentials to authenticate against registry - - cp ${DOCKER_HUB_CONFIG} /root/.docker/config.json - - - docker context create tls-environment - - # Create and use builder with optimized settings - - docker buildx create - --name fast-multiplatform - --driver docker-container - --driver-opt network=host - --driver-opt image=moby/buildkit:v0.27.1 - --use - tls-environment - - # initialize and boot fast-multiplatform builder - # configure BuildKit features that aren't enabled by default - - docker buildx inspect --bootstrap script: - - docker buildx build - --target production - --secret id=maxmind-licence-key,env=MAXMIND_LICENCE_KEY - --platform linux/amd64 - --file docker/production/Dockerfile - --push - --tag ${DOCKER_IMAGE_CASTOPOD}:${TAG} - . - rules: - - if: $CI_COMMIT_BRANCH == 'develop' + - cp ${DOCKER_HUB_CONFIG} /kaniko/.docker/config.json + - /kaniko/executor --context . --dockerfile docker/production/web-server/Dockerfile --destination ${DOCKER_IMAGE_WEB_SERVER}:${TAG} + - /kaniko/executor --context . --dockerfile docker/production/app/Dockerfile --destination ${DOCKER_IMAGE_APP}:${TAG} + needs: + - pipeline: $PARENT_PIPELINE_ID + job: bundle + only: + refs: + - develop -docker-build-release: +docker-build-main-release: stage: build image: - name: docker.io/docker:29.2-dind - services: - - docker:29.2-dind - variables: - DOCKER_BUILDKIT: 1 - DOCKER_HOST: tcp://docker:2376 - DOCKER_TLS_CERTDIR: "/certs" - before_script: - # ensure the Docker config directory exists - - mkdir -p /root/.docker - # copy credentials to authenticate against registry - - cp ${DOCKER_HUB_CONFIG} /root/.docker/config.json - - ## Prepare Docker image tags from git tag - ## -------------------------------------- - # extract full SemVer from git tag (remove leading "v") - - export IMAGE_TAG_VERSION=$(echo "$CI_COMMIT_TAG" | sed 's/^v//') - # extract channel (prerelease like "alpha", "beta", "next"; "latest" for stable) - - export IMAGE_TAG_CHANNEL=$(echo "$IMAGE_TAG_VERSION" | sed 's/^[^-]*-\([^.]*\)\..*/\1/; t; s/.*/latest/') - # extract major version number (first SemVer component) - - export IMAGE_TAG_MAJOR=$(echo "$IMAGE_TAG_VERSION" | sed 's/\..*//') - # construct major-channel tag ("X" for stable, "X-channel" for prerelease) - - export IMAGE_TAG_MAJOR_CHANNEL=$([ "$IMAGE_TAG_CHANNEL" = "latest" ] && echo "$IMAGE_TAG_MAJOR" || echo "${IMAGE_TAG_MAJOR}-${IMAGE_TAG_CHANNEL}") - - - docker context create tls-environment - - # Create and use builder with optimized settings - - docker buildx create - --name fast-multiplatform - --driver docker-container - --driver-opt network=host - --driver-opt image=moby/buildkit:v0.27.1 - --use - tls-environment - - # initialize and boot fast-multiplatform builder - # configure BuildKit features that aren't enabled by default - - docker buildx inspect --bootstrap + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] script: - - docker buildx build - --target production - --secret id=maxmind-licence-key,env=MAXMIND_LICENCE_KEY - --platform linux/amd64 - --file docker/production/Dockerfile - --push - --tag ${DOCKER_IMAGE_CASTOPOD}:${IMAGE_TAG_VERSION} - --tag ${DOCKER_IMAGE_CASTOPOD}:${IMAGE_TAG_CHANNEL} - --tag ${DOCKER_IMAGE_CASTOPOD}:${IMAGE_TAG_MAJOR_CHANNEL} - . - # when --platform=linux/amd64,linux/arm64: amd64 image takes too long to be pushed as it needs to wait for arm64 to be built - # --> build and push amd64 image first, then overwrite manifest after building arm64 - - docker buildx build - --target production - --secret id=maxmind-licence-key,env=MAXMIND_LICENCE_KEY - --platform linux/amd64,linux/arm64 - --file docker/production/Dockerfile - --push - --tag ${DOCKER_IMAGE_CASTOPOD}:${IMAGE_TAG_VERSION} - --tag ${DOCKER_IMAGE_CASTOPOD}:${IMAGE_TAG_CHANNEL} - --tag ${DOCKER_IMAGE_CASTOPOD}:${IMAGE_TAG_MAJOR_CHANNEL} - . - rules: - - if: $CI_COMMIT_TAG + - cp ${DOCKER_HUB_CONFIG} /kaniko/.docker/config.json + - export CP_VERSION=$(cat CP_VERSION.env) + - /kaniko/executor --context . --dockerfile docker/production/web-server/Dockerfile --destination ${DOCKER_IMAGE_WEB_SERVER}:${CP_VERSION} --destination ${DOCKER_IMAGE_WEB_SERVER}:latest + - /kaniko/executor --context . --dockerfile docker/production/app/Dockerfile --destination ${DOCKER_IMAGE_APP}:${CP_VERSION} --destination ${DOCKER_IMAGE_APP}:latest + needs: + - pipeline: $PARENT_PIPELINE_ID + job: release + only: + refs: + - main + +docker-build-alpha-beta-release: + stage: build + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + variables: + TAG: $CI_COMMIT_BRANCH + script: + - cp ${DOCKER_HUB_CONFIG} /kaniko/.docker/config.json + - export CP_VERSION=$(cat CP_VERSION.env) + - /kaniko/executor --context . --dockerfile docker/production/web-server/Dockerfile --destination ${DOCKER_IMAGE_WEB_SERVER}:${CP_VERSION} --destination ${DOCKER_IMAGE_WEB_SERVER}:${TAG} + - /kaniko/executor --context . --dockerfile docker/production/app/Dockerfile --destination ${DOCKER_IMAGE_APP}:${CP_VERSION} --destination ${DOCKER_IMAGE_APP}:${TAG} + needs: + - pipeline: $PARENT_PIPELINE_ID + job: release + only: + refs: + - alpha + - beta diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile deleted file mode 100644 index f55d3cfc..00000000 --- a/docker/production/Dockerfile +++ /dev/null @@ -1,154 +0,0 @@ -#################################################### -# Castopod's Production Dockerfile -#################################################### -# An optimized Dockerfile for production using -# multi-stage builds: -# 1. BUNDLE castopod -# 2. BUILD the FrankenPHP/debian based prod image -#--------------------------------------------------- - -ARG PHP_VERSION="8.5" - -#################################################### -# BUNDLE STAGE -# ------------------------------------------------- -# Bundle castopod for production using -# a PHP / Alpine image -#--------------------------------------------------- -FROM php:${PHP_VERSION}-alpine3.23 AS bundle - -LABEL maintainer="Yassine Doghri " - -COPY . /castopod-src -WORKDIR /castopod-src - -COPY --from=composer:2.9 /usr/bin/composer /usr/local/bin/composer - -RUN \ - # download GeoLite2-City archive and extract it to writable/uploads - --mount=type=secret,id=maxmind-licence-key,env=MAXMIND_LICENCE_KEY \ - wget -c "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=$MAXMIND_LICENCE_KEY&suffix=tar.gz" -O - | tar -xz -C ./writable/uploads/ \ - # rename extracted archives' folders - && mv ./writable/uploads/GeoLite2-City* ./writable/uploads/GeoLite2-City - -RUN \ - # install composer globally - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \ - # install node and pnpm - && apk add --no-cache \ - nodejs \ - pnpm \ - git \ - rsync \ - # install production dependencies only using the --no-dev option - && composer install --no-dev --prefer-dist --no-ansi --no-interaction --no-progress --ignore-platform-reqs \ - # install js dependencies based on lockfile - && pnpm install --frozen-lockfile \ - # build all production static assets (css, js, images, icons, fonts, etc.) - && pnpm run build \ - # create castopod folder bundle: uses .rsync-filter (-F) file to copy only needed files - && rsync -aF . /castopod - - -#################################################### -# BUILD STAGE -# ------------------------------------------------- -# Define production image based on FrankenPHP / -# Debian with services managed by s6-overlay -#--------------------------------------------------- -FROM serversideup/php:${PHP_VERSION}-frankenphp-trixie AS production - -LABEL maintainer="Yassine Doghri " - -USER root - -ARG TARGETARCH - -# Latest releases available at https://github.com/aptible/supercronic/releases -# add supercronic to handle cron jobs -RUN if [ "$TARGETARCH" = "amd64" ]; then \ - SUPERCRONIC_URL="https://github.com/aptible/supercronic/releases/download/v0.2.43/supercronic-linux-amd64"; \ - SUPERCRONIC_SHA1SUM="f97b92132b61a8f827c3faf67106dc0e4467ccf2"; \ - SUPERCRONIC="supercronic-linux-amd64"; \ - elif [ "$TARGETARCH" = "arm64" ]; then \ - SUPERCRONIC_URL="https://github.com/aptible/supercronic/releases/download/v0.2.43/supercronic-linux-arm64"; \ - SUPERCRONIC_SHA1SUM="5c6266786c2813d6f8a99965d84452faae42b483"; \ - SUPERCRONIC="supercronic-linux-arm64"; \ - else \ - echo "Unsupported TARGETARCH: $TARGETARCH"; exit 1; \ - fi && \ - curl -fsSLO "$SUPERCRONIC_URL" \ - && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ - && chmod +x "$SUPERCRONIC" \ - && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \ - && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic - -ARG S6_OVERLAY_VERSION=3.2.2.0 - -# add s6-overlay process manager -ADD https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz /tmp -RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz - -# add Arch-specific tarball -RUN if [ "$TARGETARCH" = "amd64" ]; then \ - S6_ARCH="x86_64"; \ - elif [ "$TARGETARCH" = "arm64" ]; then \ - S6_ARCH="aarch64"; \ - else \ - echo "Unsupported TARGETARCH: $TARGETARCH"; exit 1; \ - fi && \ - curl -fsSL -o /tmp/s6-overlay-${S6_ARCH}.tar.xz \ - "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.xz" && \ - tar -C / -Jxpf /tmp/s6-overlay-${S6_ARCH}.tar.xz && \ - rm /tmp/s6-overlay-${S6_ARCH}.tar.xz - -# copy s6-overlay services -COPY --chown=www-data:www-data docker/production/s6-rc.d /etc/s6-overlay/s6-rc.d - -# make prepare-environment executable for bootstrapping the Castopod environment -RUN chmod +x /etc/s6-overlay/s6-rc.d/bootstrap/prepare-environment.sh - -RUN \ - apt-get update \ - && apt-get install -y \ - ffmpeg \ - libfreetype6-dev \ - libjpeg62-turbo-dev \ - libpng-dev \ - libwebp-dev \ - libicu-dev \ - && install-php-extensions \ - intl \ - mysqli \ - exif \ - gd \ - # As of PHP 7.4 we don't need to add --with-png - && docker-php-ext-configure gd --with-webp --with-jpeg --with-freetype - -# copy castopod bundle from bundle stage -COPY --from=bundle --chown=www-data:www-data /castopod /app - -RUN \ - chmod -R 550 /app/ \ - && chmod -R 770 /app/public/media/ \ - && chmod -R 770 /app/writable/ \ - && chmod 750 /app/ - -ARG \ - PHP_MEMORY_LIMIT=512M \ - PHP_MAX_EXECUTION_TIME=300 \ - PHP_UPLOAD_MAX_FILE_SIZE=512M \ - PHP_POST_MAX_SIZE=512M \ - PHP_OPCACHE_ENABLE=1 - -ENV \ - PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT} \ - PHP_MAX_EXECUTION_TIME=${PHP_MAX_EXECUTION_TIME} \ - PHP_UPLOAD_MAX_FILE_SIZE=${PHP_UPLOAD_MAX_FILE_SIZE} \ - PHP_POST_MAX_SIZE=${PHP_POST_MAX_SIZE} \ - PHP_OPCACHE_ENABLE=${PHP_OPCACHE_ENABLE} - -USER www-data - -ENTRYPOINT ["docker-php-serversideup-entrypoint"] -CMD ["/init"] diff --git a/docker/production/app/Dockerfile b/docker/production/app/Dockerfile new file mode 100644 index 00000000..6ac15b24 --- /dev/null +++ b/docker/production/app/Dockerfile @@ -0,0 +1,40 @@ +FROM docker.io/alpine:3.13 AS ffmpeg-downloader + +RUN apk add --no-cache curl && \ + curl https://johnvansickle.com/ffmpeg/releases/ffmpeg-5.1.1-amd64-static.tar.xz -o ffmpeg.tar.xz && \ + mkdir ffmpeg && \ + tar -xJf ffmpeg.tar.xz -C ffmpeg --strip-components 1 + +FROM docker.io/php:8.0-fpm-alpine3.13 + +COPY docker/production/app/entrypoint.sh /entrypoint.sh + +COPY docker/production/app/uploads.ini /usr/local/etc/php/conf.d/uploads.ini + +RUN echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-activities" > /crontab.txt && \ + echo "* * * * 10 /usr/local/bin/php /opt/castopod/public/index.php scheduled-video-clips" >> /crontab.txt && \ + echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-websub-publish" >> /crontab.txt + +RUN apk add --no-cache libpng icu-libs freetype libwebp libjpeg-turbo libxpm ffmpeg && \ + apk add --no-cache --virtual .php-ext-build-dep freetype-dev libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev libxpm-dev icu-dev && \ + docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm && \ + docker-php-ext-install gd intl mysqli exif && \ + docker-php-ext-enable mysqli gd intl exif && \ + apk del .php-ext-build-dep + +COPY castopod /opt/castopod +COPY --from=ffmpeg-downloader /ffmpeg/ffmpeg /ffmpeg/ffprobe /ffmpeg/qt-faststart /usr/local/bin/ + +RUN chmod 544 /entrypoint.sh && \ + chmod 444 /crontab.txt && \ + /usr/bin/crontab /crontab.txt + +WORKDIR /opt/castopod + +VOLUME /opt/castopod/public/media + +EXPOSE 9000 + +ENTRYPOINT [ "sh", "-c" ] + +CMD [ "/entrypoint.sh" ] diff --git a/docker/production/app/entrypoint.sh b/docker/production/app/entrypoint.sh new file mode 100644 index 00000000..7246b533 --- /dev/null +++ b/docker/production/app/entrypoint.sh @@ -0,0 +1,198 @@ +#!/bin/sh + +if [ -z "${CP_BASEURL}" ] +then + echo "CP_BASEURL must be set" + exit 1 +fi + +if [ -z "${CP_MEDIA_BASEURL}" ] +then + echo "CP_MEDIA_BASEURL is empty, leaving empty by default" +fi + +if [ -z "${CP_ADMIN_GATEWAY}" ] +then + echo "CP_ADMIN_GATEWAY is empty, using default" + CP_ADMIN_GATEWAY="cp-admin" +fi + +if [ -z "${CP_AUTH_GATEWAY}" ] +then + echo "CP_AUTH_GATEWAY is empty, using default" + CP_AUTH_GATEWAY="cp-auth" +fi + +if [ -z "${CP_ANALYTICS_SALT}" ] +then + echo "CP_ANALYTICS_SALT is empty, this is mandatory, generate a new one with tr -dc \\!\\#-\\&\\(-\\[\\]-\\_a-\\~ /opt/castopod/.env +app.baseURL="${CP_BASEURL}" +app.mediaBaseURL="${CP_MEDIA_BASEURL}" +EOF + +if [ "${CP_DISABLE_HTTPS}" == "1" ] +then + echo "HTTPS redirection is disabled for test purpose, please enable it in production mode" + echo "app.forceGlobalSecureRequests=false" >> /opt/castopod/.env +else + echo "HTTPS redirection is enabled by default (mandatory to federate with the fediverse), use CP_DISABLE_HTTPS=1 to disable it for testing purposes" +fi + +cat << EOF >> /opt/castopod/.env +admin.gateway="${CP_ADMIN_GATEWAY}" +auth.gateway="${CP_AUTH_GATEWAY}" + +analytics.salt="${CP_ANALYTICS_SALT}" + +database.default.hostname="${CP_DATABASE_HOSTNAME}" +database.default.database="${CP_DATABASE_NAME}" +database.default.username="${CP_DATABASE_USERNAME}" +database.default.password="${CP_DATABASE_PASSWORD}" +database.default.DBPrefix="${CP_DATABASE_PREFIX}" + +cache.handler="${CP_CACHE_HANDLER}" +EOF + +if [ "${CP_CACHE_HANDLER}" == "redis" ] +then + cat << EOF >> /opt/castopod/.env +cache.redis.host="${CP_REDIS_HOST}" +cache.redis.password=${CP_REDIS_PASSWORD} +cache.redis.port=${CP_REDIS_PORT} +cache.redis.database=${CP_REDIS_DATABASE} +EOF +fi + +if [ ! -z "${CP_EMAIL_SMTP_HOST}" ] +then + if [ -z "${CP_EMAIL_SMTP_USERNAME}" ] + then + echo "When CP_EMAIL_SMTP_HOST is provided, CP_EMAIL_SMTP_USERNAME must be set" + exit 1 + fi + + if [ -z "${CP_EMAIL_SMTP_PASSWORD}" ] + then + echo "When CP_EMAIL_SMTP_HOST is provided, CP_EMAIL_SMTP_PASSWORD must be set" + exit 1 + fi + + if [ -z "${CP_EMAIL_FROM}" ] + then + echo "When CP_EMAIL_SMTP_HOST is provided, CP_EMAIL_FROM must be set" + exit 1 + fi + + cat << EOF >> /opt/castopod/.env +email.protocol="smtp" +email.SMTPHost="${CP_EMAIL_SMTP_HOST}" +email.SMTPUser=${CP_EMAIL_SMTP_USERNAME} +email.SMTPPass=${CP_EMAIL_SMTP_PASSWORD} +email.fromEmail=${CP_EMAIL_FROM} +EOF + + if [ ! -z "${CP_EMAIL_SMTP_PORT}" ] + then + cat << EOF >> /opt/castopod/.env +email.SMTPPort=${CP_EMAIL_SMTP_PORT} +EOF + fi + + if [ ! -z "${CP_EMAIL_SMTP_CRYPTO}" ] + then + if [ "${CP_EMAIL_SMTP_CRYPTO}" != "ssl" ] && [ "${CP_EMAIL_SMTP_CRYPTO}" != "tls" ] + then + echo "CP_EMAIL_SMTP_CRYPTO must be ssl or tls" + exit 1 + fi + cat << EOF >> /opt/castopod/.env +email.SMTPCrypto=${CP_EMAIL_SMTP_CRYPTO} +EOF + fi +fi + +echo "Using config:" +cat /opt/castopod/.env + +/usr/sbin/crond -f /crontab.txt -L /dev/stdout & +/usr/local/sbin/php-fpm diff --git a/.devcontainer/uploads.ini b/docker/production/app/uploads.ini similarity index 100% rename from .devcontainer/uploads.ini rename to docker/production/app/uploads.ini diff --git a/docker/production/s6-rc.d/bootstrap/dependencies.d/frankenphp b/docker/production/s6-rc.d/bootstrap/dependencies.d/frankenphp deleted file mode 100644 index e69de29b..00000000 diff --git a/docker/production/s6-rc.d/bootstrap/prepare-environment.sh b/docker/production/s6-rc.d/bootstrap/prepare-environment.sh deleted file mode 100644 index bb5a9a36..00000000 --- a/docker/production/s6-rc.d/bootstrap/prepare-environment.sh +++ /dev/null @@ -1,277 +0,0 @@ -#!/command/with-contenv sh - -ENV_FILE_LOCATION=/app/.env - -log_error() { - printf "\033[0;31mERROR:\033[0m $1\n" - exit 1 -} - -log_warning() { - printf "\033[0;33mWARNING:\033[0m $1\n" -} - -log_info() { - printf "\033[0;34mINFO:\033[0m $1\n" -} - -# Remove .env file if exists to recreate it. -rm -f $ENV_FILE_LOCATION - -if [ -z "${CP_BASEURL}" ] -then - log_error "CP_BASEURL must be set" -fi - -if [ -z "${CP_MEDIA_BASEURL}" ] -then - log_info "CP_MEDIA_BASEURL is empty, using CP_BASEURL by default" - CP_MEDIA_BASEURL=$CP_BASEURL -fi - -if [ -z "${CP_ADMIN_GATEWAY}" ] -then - log_info "CP_ADMIN_GATEWAY is empty, using default \"cp-admin\"" - CP_ADMIN_GATEWAY="cp-admin" -fi - -if [ -z "${CP_AUTH_GATEWAY}" ] -then - log_info "CP_AUTH_GATEWAY is empty, using default \"cp-auth\"" - CP_AUTH_GATEWAY="cp-auth" -fi - -if [ -z "${CP_ANALYTICS_SALT}" ] -then - log_error "CP_ANALYTICS_SALT is empty, this is mandatory, generate a new one with tr -dc \\!\\#-\\&\\(-\\[\\]-\\_a-\\~ $ENV_FILE_LOCATION -app.baseURL="${CP_BASEURL}" -media.baseURL="${CP_MEDIA_BASEURL}" -EOF - -if [ "${CP_DISABLE_HTTPS}" = "1" ] -then - log_warning "HTTPS redirection is disabled for testing purposes, please enable it in production mode" - echo "app.forceGlobalSecureRequests=false" >> $ENV_FILE_LOCATION -else - echo "HTTPS redirection is enabled by default (mandatory to federate with the fediverse), use CP_DISABLE_HTTPS=1 to disable it for testing purposes" -fi - -cat << EOF >> $ENV_FILE_LOCATION -admin.gateway="${CP_ADMIN_GATEWAY}" -auth.gateway="${CP_AUTH_GATEWAY}" - -analytics.salt="${CP_ANALYTICS_SALT}" - -database.default.hostname="${CP_DATABASE_HOSTNAME}" -database.default.database="${CP_DATABASE_NAME}" -database.default.username="${CP_DATABASE_USERNAME}" -database.default.password="${CP_DATABASE_PASSWORD}" -database.default.DBPrefix="${CP_DATABASE_PREFIX}" - -cache.handler="${CP_CACHE_HANDLER}" -EOF - -if [ "${CP_CACHE_HANDLER}" = "redis" ] -then - cat << EOF >> $ENV_FILE_LOCATION -cache.redis.host="${CP_REDIS_HOST}" -cache.redis.password=${CP_REDIS_PASSWORD} -cache.redis.port=${CP_REDIS_PORT} -cache.redis.database=${CP_REDIS_DATABASE} -EOF -fi - -if [ "${CP_ENABLE_2FA}" = "true" ] -then - cat << EOF >> $ENV_FILE_LOCATION -auth.enable2FA=true -EOF -fi - -if [ "${CP_MEDIA_FILE_MANAGER}" = "s3" ] -then - cat << EOF >> $ENV_FILE_LOCATION -media.fileManager=s3 -media.s3.endpoint=${CP_MEDIA_S3_ENDPOINT} -media.s3.key=${CP_MEDIA_S3_KEY} -media.s3.secret=${CP_MEDIA_S3_SECRET} -media.s3.region=${CP_MEDIA_S3_REGION} -media.s3.bucket=${CP_MEDIA_S3_BUCKET} -EOF -fi - -if [ ! -z "${CP_MEDIA_S3_PROTOCOL}" ] -then - cat << EOF >> $ENV_FILE_LOCATION -media.s3.protocol=${CP_MEDIA_S3_PROTOCOL} -EOF -fi - -if [ ! -z "${CP_MEDIA_S3_PATH_STYLE_ENDPOINT}" ] -then - cat << EOF >> $ENV_FILE_LOCATION -media.s3.pathStyleEndpoint=${CP_MEDIA_S3_PATH_STYLE_ENDPOINT} -EOF -fi - -if [ ! -z "${CP_MEDIA_S3_KEY_PREFIX}" ] -then - cat << EOF >> $ENV_FILE_LOCATION -media.s3.keyPrefix=${CP_MEDIA_S3_KEY_PREFIX} -EOF -fi - -if [ ! -z "${CP_EMAIL_SMTP_HOST}" ] -then - if [ -z "${CP_EMAIL_SMTP_USERNAME}" ] - then - log_error "When CP_EMAIL_SMTP_HOST is provided, CP_EMAIL_SMTP_USERNAME must be set" - fi - - if [ -z "${CP_EMAIL_SMTP_PASSWORD}" ] - then - log_error "When CP_EMAIL_SMTP_HOST is provided, CP_EMAIL_SMTP_PASSWORD must be set" - fi - - if [ -z "${CP_EMAIL_FROM}" ] - then - log_error "When CP_EMAIL_SMTP_HOST is provided, CP_EMAIL_FROM must be set" - fi - - cat << EOF >> $ENV_FILE_LOCATION -email.protocol="smtp" -email.SMTPHost="${CP_EMAIL_SMTP_HOST}" -email.SMTPUser=${CP_EMAIL_SMTP_USERNAME} -email.SMTPPass=${CP_EMAIL_SMTP_PASSWORD} -email.fromEmail=${CP_EMAIL_FROM} -EOF - - if [ ! -z "${CP_EMAIL_SMTP_PORT}" ] - then - cat << EOF >> $ENV_FILE_LOCATION -email.SMTPPort=${CP_EMAIL_SMTP_PORT} -EOF - fi - - if [ ! -z "${CP_EMAIL_SMTP_CRYPTO}" ] - then - if [ "${CP_EMAIL_SMTP_CRYPTO}" != "ssl" ] && [ "${CP_EMAIL_SMTP_CRYPTO}" != "tls" ] - then - log_error "CP_EMAIL_SMTP_CRYPTO must be ssl or tls" - fi - cat << EOF >> $ENV_FILE_LOCATION -email.SMTPCrypto=${CP_EMAIL_SMTP_CRYPTO} -EOF - fi -fi - -log_info "Using config:" -cat $ENV_FILE_LOCATION - -# prevent .env from being writable -chmod -w $ENV_FILE_LOCATION - -#Run database migrations -/usr/local/bin/php /var/www/html/spark castopod:database-update - -# clear cache to account for new assets and any change in data structure -/usr/local/bin/php /var/www/html/spark cache:clear diff --git a/docker/production/s6-rc.d/bootstrap/type b/docker/production/s6-rc.d/bootstrap/type deleted file mode 100644 index bdd22a18..00000000 --- a/docker/production/s6-rc.d/bootstrap/type +++ /dev/null @@ -1 +0,0 @@ -oneshot diff --git a/docker/production/s6-rc.d/bootstrap/up b/docker/production/s6-rc.d/bootstrap/up deleted file mode 100644 index 4abab1a4..00000000 --- a/docker/production/s6-rc.d/bootstrap/up +++ /dev/null @@ -1,2 +0,0 @@ -#!/command/with-contenv sh -/etc/s6-overlay/s6-rc.d/bootstrap/prepare-environment.sh diff --git a/docker/production/s6-rc.d/frankenphp/dependencies.d/base b/docker/production/s6-rc.d/frankenphp/dependencies.d/base deleted file mode 100644 index e69de29b..00000000 diff --git a/docker/production/s6-rc.d/frankenphp/run b/docker/production/s6-rc.d/frankenphp/run deleted file mode 100644 index 1193fcc3..00000000 --- a/docker/production/s6-rc.d/frankenphp/run +++ /dev/null @@ -1,2 +0,0 @@ -#!/command/with-contenv sh -frankenphp run --config /etc/frankenphp/Caddyfile --adapter caddyfile diff --git a/docker/production/s6-rc.d/frankenphp/type b/docker/production/s6-rc.d/frankenphp/type deleted file mode 100644 index 5883cff0..00000000 --- a/docker/production/s6-rc.d/frankenphp/type +++ /dev/null @@ -1 +0,0 @@ -longrun diff --git a/docker/production/s6-rc.d/supercronic/crontab b/docker/production/s6-rc.d/supercronic/crontab deleted file mode 100644 index 8382f92f..00000000 --- a/docker/production/s6-rc.d/supercronic/crontab +++ /dev/null @@ -1 +0,0 @@ -* * * * * /usr/local/bin/php /var/www/html/spark tasks:run >> /dev/null 2>&1 diff --git a/docker/production/s6-rc.d/supercronic/dependencies.d/frankenphp b/docker/production/s6-rc.d/supercronic/dependencies.d/frankenphp deleted file mode 100644 index e69de29b..00000000 diff --git a/docker/production/s6-rc.d/supercronic/run b/docker/production/s6-rc.d/supercronic/run deleted file mode 100644 index 73b9b0cf..00000000 --- a/docker/production/s6-rc.d/supercronic/run +++ /dev/null @@ -1,2 +0,0 @@ -#!/command/with-contenv sh -supercronic /etc/s6-overlay/s6-rc.d/supercronic/crontab diff --git a/docker/production/s6-rc.d/supercronic/type b/docker/production/s6-rc.d/supercronic/type deleted file mode 100644 index 5883cff0..00000000 --- a/docker/production/s6-rc.d/supercronic/type +++ /dev/null @@ -1 +0,0 @@ -longrun diff --git a/docker/production/s6-rc.d/user/contents.d/bootstrap b/docker/production/s6-rc.d/user/contents.d/bootstrap deleted file mode 100644 index e69de29b..00000000 diff --git a/docker/production/s6-rc.d/user/contents.d/frankenphp b/docker/production/s6-rc.d/user/contents.d/frankenphp deleted file mode 100644 index e69de29b..00000000 diff --git a/docker/production/s6-rc.d/user/contents.d/supercronic b/docker/production/s6-rc.d/user/contents.d/supercronic deleted file mode 100644 index e69de29b..00000000 diff --git a/docker/production/web-server/Dockerfile b/docker/production/web-server/Dockerfile new file mode 100644 index 00000000..3b2320a2 --- /dev/null +++ b/docker/production/web-server/Dockerfile @@ -0,0 +1,20 @@ +FROM docker.io/nginx:1.21-alpine + +VOLUME /var/www/html/media + +EXPOSE 80 + +WORKDIR /var/www/html + +COPY docker/production/web-server/entrypoint.sh /entrypoint.sh + +RUN chmod +x /entrypoint.sh && \ + apk add --no-cache curl + +HEALTHCHECK --interval=30s --timeout=3s CMD curl --fail http://localhost || exit 1 + +COPY docker/production/web-server/nginx.conf /etc/nginx/nginx.conf + +COPY castopod/public /var/www/html + +CMD ["/entrypoint.sh"] diff --git a/docker/production/web-server/entrypoint.sh b/docker/production/web-server/entrypoint.sh new file mode 100644 index 00000000..4365e2cd --- /dev/null +++ b/docker/production/web-server/entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/sh +if [ -z "${CP_APP_HOSTNAME}" ] +then + echo "CP_APP_HOSTNAME is empty, using default" + CP_APP_HOSTNAME="app" +fi + +sed -i "s/CP_APP_HOSTNAME/${CP_APP_HOSTNAME}/" /etc/nginx/nginx.conf +nginx -g "daemon off;" diff --git a/docker/production/web-server/nginx.conf b/docker/production/web-server/nginx.conf new file mode 100644 index 00000000..425dcf24 --- /dev/null +++ b/docker/production/web-server/nginx.conf @@ -0,0 +1,76 @@ +worker_processes auto; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + + keepalive_timeout 65; + + set_real_ip_from 10.0.0.0/8; + set_real_ip_from 172.16.0.0/12; + set_real_ip_from 192.168.0.0/16; + real_ip_header X-Real-IP; + + upstream php-handler { + server CP_APP_HOSTNAME:9000; + } + + server { + listen 80; + + root /var/www/html; + + index index.php index.html index.htm; + + client_max_body_size 1G; + fastcgi_buffers 64 4K; + + gzip on; + gzip_vary on; + gzip_comp_level 4; + gzip_min_length 256; + gzip_types application/atom+xml application/javascript audio/mpeg application/rss+xml image/bmp image/png image/jpeg image/webp image/svg+xml image/x-icon video/mp4 text/css text/plain text/html; + + location ~ /.*\.(png|ico|txt|js|js\.map)$ { + try_files $uri =404; + } + + location ~ /(assets|media)/.*$ { + try_files $uri =404; + } + + location /.well-known/GDPR.yml { + try_files $uri =404; + } + + location / { + fastcgi_param SCRIPT_FILENAME /opt/castopod/public/index.php; + include fastcgi_params; + fastcgi_index index.php; + fastcgi_pass php-handler; + } + + location ~ \.php$ { + try_files $uri =404; + fastcgi_param SCRIPT_FILENAME /opt/castopod/public/$fastcgi_script_name; + include fastcgi_params; + fastcgi_index index.php; + fastcgi_pass php-handler; + } + } +} diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index 6240da8b..00000000 --- a/docs/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# build output -dist/ -# generated types -.astro/ - -# dependencies -node_modules/ - -# logs -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* - - -# environment variables -.env -.env.production - -# macOS-specific files -.DS_Store diff --git a/docs/.gitlab-ci.yml b/docs/.gitlab-ci.yml index d0f1bde5..d7f739a2 100644 --- a/docs/.gitlab-ci.yml +++ b/docs/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: node:22 +image: node:16 stages: - build @@ -6,32 +6,26 @@ stages: .documentation-setup: before_script: - - npm install --global corepack@latest - - corepack enable - - corepack prepare pnpm@latest-10 --activate - - pnpm config set store-dir .pnpm-store - cd docs - chmod +x ./scripts/i18n-filter.sh - - ./scripts/i18n-filter.sh src/content/docs - - pnpm install + - ./scripts/i18n-filter.sh src + - npm ci cache: - key: - files: - - docs/pnpm-lock.yaml paths: - - .pnpm-store + - docs/node_modules/ # This job only serves for validating that the docs builds correctly on all non deployment branches build: extends: .documentation-setup stage: build script: - - pnpm run build - rules: - - if: $CI_COMMIT_BRANCH =~ /^(develop|main|alpha|beta|next)$/ - when: never - - when: on_success + - npm run build + except: + - develop + - main + - beta + - alpha build-production: extends: .documentation-setup @@ -40,13 +34,16 @@ build-production: name: production url: https://docs.castopod.org/ script: - - BASE=/$CI_COMMIT_REF_SLUG pnpm run build --outDir=./dist/$CI_COMMIT_REF_SLUG --base=/$CI_COMMIT_REF_SLUG + - npm run build artifacts: paths: - - docs/dist/$CI_COMMIT_REF_SLUG + - docs/.vitepress/dist expire_in: 30 mins - rules: - - if: $CI_COMMIT_BRANCH =~ /^(develop|main|alpha|beta|next)$/ + only: + - develop + - main + - beta + - alpha deploy: stage: deploy @@ -56,13 +53,15 @@ deploy: variables: HOST: $DOCS_HOST USER: $DOCS_USER - TEMP_DIRECTORY: $DOCS_TEMP_DIRECTORY/$CI_COMMIT_REF_SLUG/ - DIRECTORY: $DOCS_DIRECTORY/$CI_COMMIT_REF_SLUG/ + TEMP_DIRECTORY: $DOCS_TEMP_DIRECTORY + DIRECTORY: $DOCS_DIRECTORY SSH_PORT: 3242 - SOURCE_FOLDER: "docs/dist/$CI_COMMIT_REF_SLUG/" + SOURCE_FOLDER: "docs/.vitepress/dist/" before_script: # install rsync for file transfers - apt-get update && apt-get install rsync -y + # ssh config + - "which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )" # Run ssh-agent (inside the build environment) - eval $(ssh-agent -s) # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store @@ -72,5 +71,8 @@ deploy: script: - rsync -avzuh -e "ssh -p $SSH_PORT" $SOURCE_FOLDER $USER@$HOST:$TEMP_DIRECTORY --progress - ssh $USER@$HOST -p $SSH_PORT "rsync -rtv $TEMP_DIRECTORY $DIRECTORY" - rules: - - if: $CI_COMMIT_BRANCH =~ /^(develop|main|alpha|beta|next)$/ + only: + - develop + - main + - beta + - alpha diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts new file mode 100644 index 00000000..c76d8335 --- /dev/null +++ b/docs/.vitepress/config.ts @@ -0,0 +1,276 @@ +import { defineConfig } from "vitepress"; + +export default defineConfig({ + srcDir: "src", + + head: [ + ["link", { rel: "icon", type: "image/x-icon", href: "/favicon.ico" }], + ["link", { rel: "canonical", href: "https://docs.castopod.org/" }], + ["meta", { name: "robots", content: "index, follow" }], + ["meta", { property: "og:type", content: "website" }], + [ + "meta", + { + property: "og:image", + content: "https://docs.castopod.org/images/open-graph.jpg", + }, + ], + ["meta", { property: "og:image:type", content: "image/jpeg" }], + ["meta", { property: "og:image:width", content: "1200" }], + ["meta", { property: "og:image:height", content: "630" }], + [ + "meta", + { + property: "og:image:alt", + content: + "Castopod mascot waving hello and holding a browser showcasing the Castopod documentation.", + }, + ], + ["meta", { property: "og:url", content: "https://docs.castopod.org/" }], + ["meta", { name: "twitter:site", content: "@castopod" }], + ["meta", { name: "twitter:card", content: "summary_large_image" }], + ["meta", { name: "twitter:creator", content: "@ad_aures" }], + [ + "script", + { + defer: "defer", + "data-domain": "docs.castopod.org", + src: "https://analytics.castopod.org/js/plausible.js", + }, + ], + ], + + locales: { + "/": { + lang: "en", + title: "Castopod documentation", + description: + "Check out the Castopod documentation! Install your own free & open-source podcast host, help make it better by contributing, or simply learn more about Castopod!", + }, + "/fr/": { + lang: "fr", + title: "Documentation Castopod", + description: + "Castopod est une plateforme d’hébergement gratuite & open-source conçue pour les podcasteurs qui veulent échanger et interagir avec leur public.", + }, + "/pt-BR/": { + lang: "pt-BR", + title: "Documentação Castopod", + description: + "Castopod é uma plataforma de hospedagem de código livre & aberto feita para podcasters que querem se envolver e interagir com seu público.", + }, + "/nn-NO/": { + lang: "nn-NO", + title: "Castopod dokumentasjon", + description: + "Castopod er ei open og gratis løysing for dei som vil køyra si eiga podkasting-plattform, og for podkastarar som vil engasjera og samhandla med publikum.", + }, + }, + + themeConfig: { + logo: "/images/castopod-icon.svg", + lastUpdated: "Last Updated", + repo: "https://code.castopod.org/adaures/castopod", + docsDir: "docs/src", + docsBranch: "develop", + editLinks: true, + locales: { + "/": { + label: "English", + selectText: "Languages", + repoLabel: "Source code", + nav: [ + { + text: "Home", + link: "https://castopod.org/", + }, + { + text: "Blog", + link: "https://blog.castopod.org/", + }, + { + text: "Github", + link: "https://github.com/ad-aures/castopod", + }, + ], + sidebar: { + "/": getGuideSidebarEn(), + }, + }, + "/fr/": { + label: "Français", + selectText: "Langues", + repoLabel: "Code source", + nav: [ + { + text: "Accueil", + link: "https://castopod.org/", + }, + { + text: "Blog", + link: "https://blog.castopod.org/", + }, + { + text: "Github", + link: "https://github.com/ad-aures/castopod", + }, + ], + sidebar: { + "/": getGuideSidebarFr(), + }, + }, + "/pt-BR/": { + label: "Português do Brasil", + selectText: "Línguas", + repoLabel: "Código fonte", + nav: [ + { + text: "Início", + link: "https://castopod.org/", + }, + { + text: "Blogue", + link: "https://blog.castopod.org/", + }, + { + text: "Github", + link: "https://github.com/ad-aures/castopod", + }, + ], + sidebar: { "/pt-BR/": getGuideSidebarPtBR() }, + }, + "/nn-NO/": { + label: "Norsk nynorsk", + selectText: "Språk", + repoLabel: "Kildekode", + nav: [ + { + text: "Heim", + link: "https://castopod.org/", + }, + { + text: "Blogg", + link: "https://blog.castopod.org/", + }, + { + text: "Github", + link: "https://github.com/ad-aures/castopod", + }, + ], + sidebar: { "/nn-NO/": getGuideSidebarNnNO() }, + }, + }, + }, +}); + +function getGuideSidebarEn() { + return [ + { + text: "Introduction", + link: "/", + }, + { + text: "Getting started", + children: [ + { text: "Install", link: "/getting-started/install" }, + { + text: "Docker", + link: "/getting-started/docker", + }, + { text: "Security", link: "/getting-started/security" }, + { text: "Update", link: "/getting-started/update" }, + ], + }, + { + text: "Contributing", + children: [ + { text: "Guide", link: "/contributing/guidelines" }, + { text: "Dev Setup", link: "/contributing/setup-development" }, + ], + }, + ]; +} + +function getGuideSidebarFr() { + return [ + { + text: "Introduction", + link: "/fr/", + }, + { + text: "Commencer", + children: [ + { text: "Installer", link: "/fr/getting-started/install" }, + { + text: "Docker", + link: "/fr/getting-started/docker", + }, + { text: "Sécurité", link: "/fr/getting-started/security" }, + { text: "Mise à jour", link: "/fr/getting-started/update" }, + ], + }, + { + text: "Contributing", + children: [ + { text: "Guide", link: "/fr/contributing/guidelines" }, + { text: "Dev Setup", link: "/fr/contributing/setup-development" }, + ], + }, + ]; +} + +function getGuideSidebarPtBR() { + return [ + { + text: "Introdução", + link: "/pt-BR/", + }, + { + text: "Começando", + children: [ + { text: "Instalar", link: "/pt-BR/getting-started/install" }, + { + text: "Docker", + link: "/pt-BR/getting-started/docker", + }, + { text: "Segurança", link: "/pt-BR/getting-started/security" }, + { text: "Atualizar", link: "/pt-BR/getting-started/update" }, + ], + }, + { + text: "Contributing", + children: [ + { text: "Guide", link: "/pt-BR/contributing/guidelines" }, + { text: "Dev Setup", link: "/pt-BR/contributing/setup-development" }, + ], + }, + ]; +} + +function getGuideSidebarNnNO() { + return [ + { + text: "Introduksjon", + link: "/nn-NO/", + }, + { + text: "Starter", + children: [ + { text: "Installer", link: "/nn-NO/getting-started/install" }, + { + text: "Docker", + link: "/nn-NO/getting-started/docker", + }, + { text: "Sikkerhet", link: "/nn-NO/getting-started/security" }, + { text: "Oppdaterer", link: "/nn-NO/getting-started/update" }, + ], + }, + { + text: "Contributing", + children: [ + { text: "Guide", link: "/nn-NO/contributing/guidelines" }, + { text: "Dev Setup", link: "/nn-NO/contributing/setup-development" }, + ], + }, + ]; +} diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts new file mode 100644 index 00000000..a60960f7 --- /dev/null +++ b/docs/.vitepress/theme/index.ts @@ -0,0 +1,6 @@ +import Theme from "vitepress/theme"; +import "./tailwind.css"; + +export default { + ...Theme, +}; diff --git a/docs/.vitepress/theme/tailwind.css b/docs/.vitepress/theme/tailwind.css new file mode 100644 index 00000000..7c05d4dd --- /dev/null +++ b/docs/.vitepress/theme/tailwind.css @@ -0,0 +1,2 @@ +@tailwind components; +@tailwind utilities; diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 34351f25..00000000 --- a/docs/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# Castopod Docs - -[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) - -```sh -pnpm create astro@latest -- --template starlight -``` - -> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! - -## 🚀 Project Structure - -Inside of your Astro + Starlight project, you'll see the following folders and -files: - -```sh -. -├── public/ -├── src/ -│ ├── assets/ -│ ├── content/ -│ │ └── docs/ -│ └── content.config.ts -├── astro.config.mjs -├── package.json -└── tsconfig.json -``` - -Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. -Each file is exposed as a route based on its file name. - -Images can be added to `src/assets/` and embedded in Markdown with a relative -link. - -Static assets, like favicons, can be placed in the `public/` directory. - -## 🧞 Commands - -All commands are run from the root of the project, from a terminal: - -| Command | Action | -| :--------------------- | :----------------------------------------------- | -| `pnpm install` | Installs dependencies | -| `pnpm dev` | Starts local dev server at `localhost:4321` | -| `pnpm build` | Build your production site to `./dist/` | -| `pnpm preview` | Preview your build locally, before deploying | -| `pnpm astro ...` | Run CLI commands like `astro add`, `astro check` | -| `pnpm astro -- --help` | Get help using the Astro CLI | - -## 👀 Want to learn more? - -Check out [Starlight’s docs](https://starlight.astro.build/), read -[the Astro documentation](https://docs.astro.build), or jump into the -[Astro Discord server](https://astro.build/chat). diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs deleted file mode 100644 index d641ec7f..00000000 --- a/docs/astro.config.mjs +++ /dev/null @@ -1,413 +0,0 @@ -// @ts-check -import { defineConfig } from "astro/config"; -import starlight from "@astrojs/starlight"; -import starlightOpenAPI from "starlight-openapi"; - -const site = "https://docs.castopod.org/"; -const base = process.env.BASE ?? "/docs"; - -// https://astro.build/config -export default defineConfig({ - server: { - host: true, - }, - site, - base, - integrations: [ - starlight({ - title: "Castopod Docs", - description: - "Check out the Castopod documentation! Install your own free & open-source podcast host, help make it better by contributing, or simply learn more about Castopod!", - components: { - ThemeSelect: "./src/components/ThemeSelect.astro", - }, - logo: { - src: "./src/assets/castopod-logo-inline.svg", - replacesTitle: true, - }, - favicon: "/favicon.ico", - customCss: [ - "@fontsource/inter/400.css", - "@fontsource/inter/600.css", - "@fontsource/rubik/700.css", - "./src/styles/custom.css", - ], - head: [ - { - tag: "meta", - attrs: { - property: "og:type", - content: "website", - }, - }, - { - tag: "meta", - attrs: { - property: "og:image", - content: base + "/open-graph.jpg?v=1", - }, - }, - { - tag: "meta", - attrs: { property: "og:image:type", content: "image/jpeg" }, - }, - { tag: "meta", attrs: { property: "og:image:width", content: "1200" } }, - { tag: "meta", attrs: { property: "og:image:height", content: "630" } }, - { - tag: "meta", - attrs: { - property: "og:image:alt", - content: - "Castopod mascot waving hello and holding a browser showcasing the Castopod documentation.", - }, - }, - { - tag: "meta", - attrs: { property: "og:url", content: "https://docs.castopod.org/" }, - }, - { tag: "meta", attrs: { name: "twitter:site", content: "@castopod" } }, - { - tag: "meta", - attrs: { name: "twitter:card", content: "summary_large_image" }, - }, - { - tag: "meta", - attrs: { name: "twitter:creator", content: "@ad_aures" }, - }, - { - tag: "script", - attrs: { - src: "https://analytics.castopod.org/js/plausible.js", - "data-domain": "docs.castopod.org", - defer: true, - }, - }, - ], - social: [ - { - icon: "discord", - label: "Discord", - href: "https://castopod.org/chat", - }, - { - icon: "blueSky", - label: "Bluesky", - href: "https://bsky.app/profile/castopod.org", - }, - { - icon: "mastodon", - label: "Mastodon", - href: "https://podlibre.social/@Castopod", - }, - { - icon: "gitlab", - label: "Source code", - href: "https://code.castopod.org/adaures/castopod", - }, - { - icon: "github", - label: "Github", - href: "https://github.com/ad-aures/castopod", - }, - ], - defaultLocale: "en", - locales: { - en: { - label: "English", - }, - ca: { - label: "Català", - }, - de: { - label: "Deutsch", - }, - es: { - label: "Español", - }, - fr: { - label: "Français", - }, - "nn-no": { - label: "Norsk nynorsk", - lang: "nn-NO", - }, - "pt-br": { - label: "Português do Brasil", - lang: "pt-BR", - }, - "sr-latn": { - label: "Srpski", - lang: "sr-Latn", - }, - "zh-hans": { - label: "中文", - lang: "zh-Hans", - }, - }, - plugins: [ - // Generate the OpenAPI documentation pages. - starlightOpenAPI([ - { - base: "en/api", - label: "API reference", - schema: "../modules/Api/Rest/V1/schema.yaml", - collapsed: true, - }, - ]), - ], - sidebar: [ - { - label: "Introduction", - link: "/", - translations: { - fr: "Installer", - "pt-br": "Instalar", - "nn-no": "Installer", - }, - }, - { - label: "Getting started", - translations: { - fr: "Commencer", - "pt-br": "Começando", - "nn-no": "Starter", - }, - items: [ - // Each item here is one entry in the navigation menu. - { - label: "Install", - link: "/getting-started/install/", - translations: { - fr: "Installer", - "pt-br": "Instalar", - "nn-no": "Installer", - }, - }, - { - label: "Docker", - link: "/getting-started/docker/", - }, - { - label: "Security", - link: "/getting-started/security/", - translations: { - fr: "Sécurité", - "pt-br": "Segurança", - "nn-no": "Sikkerhet", - }, - }, - { - label: "Update", - link: "/getting-started/update/", - translations: { - fr: "Mise à jour", - "pt-br": "Atualizar", - "nn-no": "Oppdaterer", - }, - }, - { - label: "Auth", - link: "/getting-started/auth/", - translations: { - fr: "Authentification", - "pt-br": "Autenticação", - "nn-no": "Autentisering", - }, - }, - { - label: "Create your first podcast", - link: "/getting-started/create-podcast/", - translations: {}, - }, - { - label: "Create your first episode", - link: "/getting-started/create-episode/", - translations: {}, - }, - ], - }, - { - label: "Plugins", - items: [ - { - label: "Introduction", - link: "/plugins/", - }, - { - label: "Install plugins", - link: "/plugins/install", - }, - { - label: "Create a plugin", - link: "/plugins/create", - }, - { - label: "Share your plugin", - link: "/plugins/share", - }, - { - label: "Reference", - items: [ - { - label: "plugins.json", - link: "/plugins/reference/plugins-json", - }, - { - label: "plugins-lock.json", - link: "/plugins/reference/plugins-lock-json", - }, - { - label: "manifest.json", - link: "/plugins/reference/manifest", - }, - { - label: "hooks", - link: "/plugins/reference/hooks", - }, - ], - }, - ], - }, - // TODO: openapi plugin does not handle i18n, manual sidebar workaround - // Add the generated sidebar group to the sidebar. - // ...openAPISidebarGroups, - { - label: "API reference", - translations: {}, - items: [ - { - label: "Overview", - link: "/api", - }, - { - label: "Operations", - items: [ - { - label: "Get all podcasts", - link: "/api/operations/get-all-podcasts", - }, - { - label: "Get podcast by ID", - link: "/api/operations/get-podcast-by-id", - }, - { - label: "Get all episodes", - link: "/api/operations/get-all-episodes", - }, - { - label: "Add a new episode", - link: "/api/operations/add-episode", - }, - { - label: "Get episode by ID", - link: "/api/operations/get-episode-by-id", - }, - { - label: "Publish an episode", - link: "/api/operations/publish-episode", - }, - ], - }, - ], - }, - { - label: "User guide", - translations: {}, - items: [ - { - label: "Introduction", - link: "/user-guide/", - }, - { - label: "Manage your instance", - translations: {}, - collapsed: true, - items: [ - { - label: "Introduction", - link: "/user-guide/instance/", - }, - { - label: "Add a podcast", - link: "/user-guide/instance/podcast", - translations: {}, - }, - { - label: "Persons", - link: "/user-guide/instance/persons", - translations: {}, - }, - - { - label: "Fediverse", - link: "/user-guide/instance/fediverse", - translations: {}, - }, - { - label: "Users", - link: "/user-guide/instance/users", - translations: {}, - }, - { - label: "Pages", - link: "/user-guide/instance/pages", - translations: {}, - }, - { - label: "Settings", - link: "/user-guide/instance/settings", - translations: {}, - }, - ], - }, - { - label: "Manage your podcasts", - translations: {}, - collapsed: true, - items: [ - { - label: "Introduction", - link: "/user-guide/podcast/", - }, - { - label: "Podcast dashboard", - link: "/user-guide/podcast/dashboard", - translations: {}, - }, - { - label: "Episodes", - link: "/user-guide/podcast/episodes", - translations: {}, - }, - - { - label: "Analytics", - link: "/user-guide/podcast/analytics", - translations: {}, - }, - { - label: "Broadcasting", - link: "/user-guide/podcast/broadcast", - translations: {}, - }, - { - label: "Contributors", - link: "/user-guide/podcast/contributors", - translations: {}, - }, - ], - }, - { - label: "Website overview", - link: "/user-guide/website/", - translations: {}, - }, - ], - }, - ], - editLink: { - baseUrl: "https://code.castopod.org/adaures/castopod/-/edit/main/docs/", - }, - }), - ], -}); diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 00000000..82e5454b --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,3577 @@ +{ + "name": "castopod-docs", + "version": "0.0.0-development", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "castopod-docs", + "version": "0.0.0-development", + "license": "AGPL-3.0-or-later", + "devDependencies": { + "tailwindcss": "^3.0.23", + "vitepress": "^0.22.3" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz", + "integrity": "sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.5.2" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz", + "integrity": "sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.5.2" + }, + "peerDependencies": { + "@algolia/client-search": "^4.9.1", + "algoliasearch": "^4.9.1" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz", + "integrity": "sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug==", + "dev": true + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.2.tgz", + "integrity": "sha512-z8LjFsQc0B6h6LEE3pkUGM4ErVktn6bkFbhnYbTccjmFVQ+wXFJd/D63e0WtaC+hwRB1xq8uKhkz9oojEKEsGA==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.12.2" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.12.2.tgz", + "integrity": "sha512-r//r7MF0Na0HxD2BHnjWsDKuI72Z5UEf/Rb/8MC08XKBsjCwBihGxWxycjRcNGjNEIxJBsvRMIEOipcd9qD54g==", + "dev": true + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.12.2.tgz", + "integrity": "sha512-opWpbBUloP1fcTG3wBDnAfcoyNXW5GFDgGtLXrSANdfnelPKkr3O8j01ZTkRlPIuBDR0izGZG8MVWMDlTf71Bw==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.12.2" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.12.2.tgz", + "integrity": "sha512-HZqEyeVVjzOlfoSUyc+7+ueEJmRgqSuC+hqQOGECYa5JVno4d8eRVuDAMOb87I2LOdg/WoFMcAtaaRq2gpfV/w==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.12.2", + "@algolia/client-search": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.12.2.tgz", + "integrity": "sha512-7ktimzesu+vk3l+eG9w/nQh6/9AoIieCKmoiRIguKh6okGsaSBrcTHvUwIQEIiliqPuAFBk2M8eXYFqOZzwCZw==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.12.2", + "@algolia/client-search": "4.12.2", + "@algolia/requester-common": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.12.2.tgz", + "integrity": "sha512-+dTicT1lklwOpeoiDspUoRSQYHhrr2IzllrX89/WuTPEBm2eww1xurqrSTQYC0MuVeX1s9/i4k34Q0ZnspypWg==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.12.2.tgz", + "integrity": "sha512-JBW3vYFGIm5sAAy3cLUdmUCpmSAdreo5S1fERg7xgF6KyxGrwyy5BViTNWrOKG+av2yusk1wKydOYJ1Fbpbaxw==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.12.2", + "@algolia/requester-common": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.12.2.tgz", + "integrity": "sha512-JIqi14TgfEqAooNbSPBC1ZCk3Pnviqlaz9KofAqWBxSRTpPUFnU/XQCU5ihR0PC68SFVDnU/Y9cak/XotXPUeg==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.12.2", + "@algolia/requester-common": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "node_modules/@algolia/logger-common": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.12.2.tgz", + "integrity": "sha512-iOiJAymLjq137G7+8EQuUEkrgta0cZGMg6scp8s4hJ+X6k+6By4nyptdkCWYwKLsW/Xy927QcIhGlkWV78vQIQ==", + "dev": true + }, + "node_modules/@algolia/logger-console": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.12.2.tgz", + "integrity": "sha512-veuQZyTSqHoHJtr9mLMnYeal9Mee6hCie4eqY+645VbeOrgT9p/kCMbKg5GLJGoLPlXGu7C0XpHyUj5k7/NQyw==", + "dev": true, + "dependencies": { + "@algolia/logger-common": "4.12.2" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.2.tgz", + "integrity": "sha512-FpFdHNd81tS3zj6Glqd+lt+RV0ljPExKtx+QB+gani6HWZ9YlSCM+Zl82T4ibxN+hmkrMeAyT+TMzS0jiGhGyQ==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.12.2" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.12.2.tgz", + "integrity": "sha512-4szj/lvDQf/u8EyyRBBRZD1ZkKDyLBbckLj7meQDlnbfwnW1UpLwpB2l3XJ9wDmDSftGxUCeTl5oMFe4z9OEvQ==", + "dev": true + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.12.2.tgz", + "integrity": "sha512-UXfJNZt2KMwjBjiOa3cJ/PyoXWZa/F1vy6rdyG4xQeZDcLbqKP3O2b+bOJcGPmFbmdwBhtAyMVLt+hvAvAVfOw==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.12.2" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.12.2.tgz", + "integrity": "sha512-PUq79if4CukXsm27ymTQ3eD3juSvMcyJmt6mxCkSFE0zQRL4ert61HBlNH6S9y/quUVe3g7oggfHq3d5pdpqZA==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.12.2", + "@algolia/logger-common": "4.12.2", + "@algolia/requester-common": "4.12.2" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", + "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0.tgz", + "integrity": "sha512-1kkV7tkAsiuEd0shunYRByKJe3xQDG2q7wYg24SOw1nV9/2lwEd4WrUYRJC/ukGTl2/kHeFxsaUvtiOy0y6fFA==", + "dev": true + }, + "node_modules/@docsearch/js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.0.0.tgz", + "integrity": "sha512-j3tUJWlgW3slYqzGB8fm7y05kh2qqrIK1dZOXHeMUm/5gdKE85fiz/ltfCPMDFb/MXF+bLZChJXSMzqY0Ck30Q==", + "dev": true, + "dependencies": { + "@docsearch/react": "3.0.0", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0.tgz", + "integrity": "sha512-yhMacqS6TVQYoBh/o603zszIb5Bl8MIXuOc6Vy617I74pirisDzzcNh0NEaYQt50fVVR3khUbeEhUEWEWipESg==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-core": "1.5.2", + "@algolia/autocomplete-preset-algolia": "1.5.2", + "@docsearch/css": "3.0.0", + "algoliasearch": "^4.0.0" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 18.0.0", + "react": ">= 16.8.0 < 18.0.0", + "react-dom": ">= 16.8.0 < 18.0.0" + } + }, + "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" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@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, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@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, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true, + "peer": true + }, + "node_modules/@types/react": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", + "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", + "dev": true, + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true, + "peer": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.2.4.tgz", + "integrity": "sha512-ev9AOlp0ljCaDkFZF3JwC/pD2N4Hh+r5srl5JHM6BKg5+99jiiK0rE/XaRs3pVm1wzyKkjUy/StBSoXX5fFzcw==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "vite": "^2.5.10", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.31.tgz", + "integrity": "sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz", + "integrity": "sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==", + "dev": true, + "dependencies": { + "@vue/compiler-core": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz", + "integrity": "sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.31", + "@vue/compiler-dom": "3.2.31", + "@vue/compiler-ssr": "3.2.31", + "@vue/reactivity-transform": "3.2.31", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz", + "integrity": "sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.31.tgz", + "integrity": "sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==", + "dev": true, + "dependencies": { + "@vue/shared": "3.2.31" + } + }, + "node_modules/@vue/reactivity-transform": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.31.tgz", + "integrity": "sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.31", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.31.tgz", + "integrity": "sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==", + "dev": true, + "dependencies": { + "@vue/reactivity": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.31.tgz", + "integrity": "sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==", + "dev": true, + "dependencies": { + "@vue/runtime-core": "3.2.31", + "@vue/shared": "3.2.31", + "csstype": "^2.6.8" + } + }, + "node_modules/@vue/runtime-dom/node_modules/csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==", + "dev": true + }, + "node_modules/@vue/server-renderer": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.31.tgz", + "integrity": "sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==", + "dev": true, + "dependencies": { + "@vue/compiler-ssr": "3.2.31", + "@vue/shared": "3.2.31" + }, + "peerDependencies": { + "vue": "3.2.31" + } + }, + "node_modules/@vue/shared": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.31.tgz", + "integrity": "sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/algoliasearch": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.12.2.tgz", + "integrity": "sha512-bn1P9+V415zeDQJtXn+1SwuwedEAv9/LJAxt8XwR6ygH/sMwaHSm2hpkz8wIbCBt/tKQ43TL672Kyxzv5PwGgQ==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.12.2", + "@algolia/cache-common": "4.12.2", + "@algolia/cache-in-memory": "4.12.2", + "@algolia/client-account": "4.12.2", + "@algolia/client-analytics": "4.12.2", + "@algolia/client-common": "4.12.2", + "@algolia/client-personalization": "4.12.2", + "@algolia/client-search": "4.12.2", + "@algolia/logger-common": "4.12.2", + "@algolia/logger-console": "4.12.2", + "@algolia/requester-browser-xhr": "4.12.2", + "@algolia/requester-common": "4.12.2", + "@algolia/requester-node-http": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", + "dev": true + }, + "node_modules/autoprefixer": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", + "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", + "dev": true, + "peer": true, + "dependencies": { + "browserslist": "^4.19.1", + "caniuse-lite": "^1.0.30001297", + "fraction.js": "^4.1.2", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "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/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", + "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", + "dev": true, + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001312", + "electron-to-chromium": "^1.4.71", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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-lite": { + "version": "1.0.30001313", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001313.tgz", + "integrity": "sha512-rI1UN0koZUiKINjysQDuRi2VeSCce3bYJNmDcj3PIKREiAmjakugBul1QSkg/fPrlULYl6oWfGg3PbgOSY9X4Q==", + "dev": true, + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "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/" + } + ], + "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" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "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==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "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/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", + "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", + "dev": true, + "peer": true + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "node_modules/detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "dependencies": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.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 + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.75", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz", + "integrity": "sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q==", + "dev": true, + "peer": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/esbuild": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.25.tgz", + "integrity": "sha512-4JHEIOMNFvK09ziiL+iVmldIhLbn49V4NAVo888tcGFKedEZY/Y8YapfStJ6zSE23tzYPKxqKwQBnQoIO0BI/Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-64": "0.14.25", + "esbuild-android-arm64": "0.14.25", + "esbuild-darwin-64": "0.14.25", + "esbuild-darwin-arm64": "0.14.25", + "esbuild-freebsd-64": "0.14.25", + "esbuild-freebsd-arm64": "0.14.25", + "esbuild-linux-32": "0.14.25", + "esbuild-linux-64": "0.14.25", + "esbuild-linux-arm": "0.14.25", + "esbuild-linux-arm64": "0.14.25", + "esbuild-linux-mips64le": "0.14.25", + "esbuild-linux-ppc64le": "0.14.25", + "esbuild-linux-riscv64": "0.14.25", + "esbuild-linux-s390x": "0.14.25", + "esbuild-netbsd-64": "0.14.25", + "esbuild-openbsd-64": "0.14.25", + "esbuild-sunos-64": "0.14.25", + "esbuild-windows-32": "0.14.25", + "esbuild-windows-64": "0.14.25", + "esbuild-windows-arm64": "0.14.25" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.25.tgz", + "integrity": "sha512-L5vCUk7TzFbBnoESNoXjU3x9+/+7TDIE/1mTfy/erAfvZAqC+S3sp/Qa9wkypFMcFvN9FzvESkTlpeQDolREtQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.25.tgz", + "integrity": "sha512-4jv5xPjM/qNm27T5j3ZEck0PvjgQtoMHnz4FzwF5zNP56PvY2CT0WStcAIl6jNlsuDdN63rk2HRBIsO6xFbcFw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.25.tgz", + "integrity": "sha512-TGp8tuudIxOyWd1+8aYPxQmC1ZQyvij/AfNBa35RubixD0zJ1vkKHVAzo0Zao1zcG6pNqiSyzfPto8vmg0s7oA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.25.tgz", + "integrity": "sha512-oTcDgdm0MDVEmw2DWu8BV68pYuImpFgvWREPErBZmNA4MYKGuBRaCiJqq6jZmBR1x+3y1DWCjez+5uLtuAm6mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.25.tgz", + "integrity": "sha512-ueAqbnMZ8arnuLH8tHwTCQYeptnHOUV7vA6px6j4zjjQwDx7TdP7kACPf3TLZLdJQ3CAD1XCvQ2sPhX+8tacvQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.25.tgz", + "integrity": "sha512-+ZVWud2HKh+Ob6k/qiJWjBtUg4KmJGGmbvEXXW1SNKS7hW7HU+Zq2ZCcE1akFxOPkVB+EhOty/sSek30tkCYug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.25.tgz", + "integrity": "sha512-3OP/lwV3kCzEz45tobH9nj+uE4ubhGsfx+tn0L26WAGtUbmmcRpqy7XRG/qK7h1mClZ+eguIANcQntYMdYklfw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.25.tgz", + "integrity": "sha512-+aKHdHZmX9qwVlQmu5xYXh7GsBFf4TWrePgeJTalhXHOG7NNuUwoHmketGiZEoNsWyyqwH9rE5BC+iwcLY30Ug==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.25.tgz", + "integrity": "sha512-aTLcE2VBoLydL943REcAcgnDi3bHtmULSXWLbjtBdtykRatJVSxKMjK9YlBXUZC4/YcNQfH7AxwVeQr9fNxPhw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.25.tgz", + "integrity": "sha512-UxfenPx/wSZx55gScCImPtXekvZQLI2GW3qe5dtlmU7luiqhp5GWPzGeQEbD3yN3xg/pHc671m5bma5Ns7lBHw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.25.tgz", + "integrity": "sha512-wLWYyqVfYx9Ur6eU5RT92yJVsaBGi5RdkoWqRHOqcJ38Kn60QMlcghsKeWfe9jcYut8LangYZ98xO1LxIoSXrQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.25.tgz", + "integrity": "sha512-0dR6Csl6Zas3g4p9ULckEl8Mo8IInJh33VCJ3eaV1hj9+MHGdmDOakYMN8MZP9/5nl+NU/0ygpd14cWgy8uqRw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.25.tgz", + "integrity": "sha512-J4d20HDmTrgvhR0bdkDhvvJGaikH3LzXQnNaseo8rcw9Yqby9A90gKUmWpfwqLVNRILvNnAmKLfBjCKU9ajg8w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.25.tgz", + "integrity": "sha512-YI2d5V6nTE73ZnhEKQD7MtsPs1EtUZJ3obS21oxQxGbbRw1G+PtJKjNyur+3t6nzHP9oTg6GHQ3S3hOLLmbDIQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.25.tgz", + "integrity": "sha512-TKIVgNWLUOkr+Exrye70XTEE1lJjdQXdM4tAXRzfHE9iBA7LXWcNtVIuSnphTqpanPzTDFarF0yqq4kpbC6miA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.25.tgz", + "integrity": "sha512-QgFJ37A15D7NIXBTYEqz29+uw3nNBOIyog+3kFidANn6kjw0GHZ0lEYQn+cwjyzu94WobR+fes7cTl/ZYlHb1A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.25.tgz", + "integrity": "sha512-rmWfjUItYIVlqr5EnTH1+GCxXiBOC42WBZ3w++qh7n2cS9Xo0lO5pGSG2N+huOU2fX5L+6YUuJ78/vOYvefeFw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.25.tgz", + "integrity": "sha512-HGAxVUofl3iUIz9W10Y9XKtD0bNsK9fBXv1D55N/ljNvkrAYcGB8YCm0v7DjlwtyS6ws3dkdQyXadbxkbzaKOA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.25.tgz", + "integrity": "sha512-TirEohRkfWU9hXLgoDxzhMQD1g8I2mOqvdQF2RS9E/wbkORTAqJHyh7wqGRCQAwNzdNXdg3JAyhQ9/177AadWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.25.tgz", + "integrity": "sha512-4ype9ERiI45rSh+R8qUoBtaj6kJvUOI7oVLhKqPEpcF4Pa5PpT3hm/mXAyotJHREkHpM87PAJcA442mLnbtlNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@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" + }, + "engines": { + "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==", + "dev": true, + "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, + "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, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fraction.js": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz", + "integrity": "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "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, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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/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/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/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/lilconfig": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", + "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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 + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "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" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true, + "peer": 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, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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 + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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 + }, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.7", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz", + "integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==", + "dev": true, + "dependencies": { + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.3.tgz", + "integrity": "sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.4", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.6" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", + "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "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/preact": { + "version": "10.6.6", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.6.6.tgz", + "integrity": "sha512-dgxpTFV2vs4vizwKohYKkk7g7rmp1wOOcfd4Tz3IB3Wi+ivZzsn/SpeKJhRENSE+n8sUfsAl4S3HiCVT923ABw==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prismjs": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", + "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, + "node_modules/readdirp": { + "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" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "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" + } + }, + "node_modules/rollup": { + "version": "2.69.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.69.1.tgz", + "integrity": "sha512-xaQKTomUVZBopk38EIshM/kOoPFkKWisgBV7Emy80coP9MOSLUDrba1jKZhqH0iS5DoGcRbbcuyl/BzblV8w5w==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/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, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.23.tgz", + "integrity": "sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==", + "dev": true, + "dependencies": { + "arg": "^5.0.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "cosmiconfig": "^7.0.1", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "normalize-path": "^3.0.0", + "object-hash": "^2.2.0", + "postcss": "^8.4.6", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.0", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "autoprefixer": "^10.0.2", + "postcss": "^8.0.9" + } + }, + "node_modules/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, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "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 + }, + "node_modules/vite": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.8.6.tgz", + "integrity": "sha512-e4H0QpludOVKkmOsRyqQ7LTcMUDF3mcgyNU4lmi0B5JUbe0ZxeBBl8VoZ8Y6Rfn9eFKYtdXNPcYK97ZwH+K2ug==", + "dev": true, + "dependencies": { + "esbuild": "^0.14.14", + "postcss": "^8.4.6", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": ">=12.2.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "0.22.3", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-0.22.3.tgz", + "integrity": "sha512-Yfvu/rent2vp/TXIDZMutS6ft2TJPn4xngS48PYFWDEbuFI2ccUAXM481lF1qVVnCKxfh4g8e/KPvevSJdg1Bw==", + "dev": true, + "dependencies": { + "@docsearch/css": "^3.0.0-alpha.41", + "@docsearch/js": "^3.0.0-alpha.41", + "@vitejs/plugin-vue": "^2.2.0", + "prismjs": "^1.25.0", + "vite": "^2.8.1", + "vue": "^3.2.31" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vue": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.31.tgz", + "integrity": "sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.2.31", + "@vue/compiler-sfc": "3.2.31", + "@vue/runtime-dom": "3.2.31", + "@vue/server-renderer": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + } + }, + "dependencies": { + "@algolia/autocomplete-core": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.5.2.tgz", + "integrity": "sha512-DY0bhyczFSS1b/CqJlTE/nQRtnTAHl6IemIkBy0nEWnhDzRDdtdx4p5Uuk3vwAFxwEEgi1WqKwgSSMx6DpNL4A==", + "dev": true, + "requires": { + "@algolia/autocomplete-shared": "1.5.2" + } + }, + "@algolia/autocomplete-preset-algolia": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.2.tgz", + "integrity": "sha512-3MRYnYQFJyovANzSX2CToS6/5cfVjbLLqFsZTKcvF3abhQzxbqwwaMBlJtt620uBUOeMzhdfasKhCc40+RHiZw==", + "dev": true, + "requires": { + "@algolia/autocomplete-shared": "1.5.2" + } + }, + "@algolia/autocomplete-shared": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.2.tgz", + "integrity": "sha512-ylQAYv5H0YKMfHgVWX0j0NmL8XBcAeeeVQUmppnnMtzDbDnca6CzhKj3Q8eF9cHCgcdTDdb5K+3aKyGWA0obug==", + "dev": true + }, + "@algolia/cache-browser-local-storage": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.2.tgz", + "integrity": "sha512-z8LjFsQc0B6h6LEE3pkUGM4ErVktn6bkFbhnYbTccjmFVQ+wXFJd/D63e0WtaC+hwRB1xq8uKhkz9oojEKEsGA==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.12.2" + } + }, + "@algolia/cache-common": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.12.2.tgz", + "integrity": "sha512-r//r7MF0Na0HxD2BHnjWsDKuI72Z5UEf/Rb/8MC08XKBsjCwBihGxWxycjRcNGjNEIxJBsvRMIEOipcd9qD54g==", + "dev": true + }, + "@algolia/cache-in-memory": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.12.2.tgz", + "integrity": "sha512-opWpbBUloP1fcTG3wBDnAfcoyNXW5GFDgGtLXrSANdfnelPKkr3O8j01ZTkRlPIuBDR0izGZG8MVWMDlTf71Bw==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.12.2" + } + }, + "@algolia/client-account": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.12.2.tgz", + "integrity": "sha512-HZqEyeVVjzOlfoSUyc+7+ueEJmRgqSuC+hqQOGECYa5JVno4d8eRVuDAMOb87I2LOdg/WoFMcAtaaRq2gpfV/w==", + "dev": true, + "requires": { + "@algolia/client-common": "4.12.2", + "@algolia/client-search": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "@algolia/client-analytics": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.12.2.tgz", + "integrity": "sha512-7ktimzesu+vk3l+eG9w/nQh6/9AoIieCKmoiRIguKh6okGsaSBrcTHvUwIQEIiliqPuAFBk2M8eXYFqOZzwCZw==", + "dev": true, + "requires": { + "@algolia/client-common": "4.12.2", + "@algolia/client-search": "4.12.2", + "@algolia/requester-common": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "@algolia/client-common": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.12.2.tgz", + "integrity": "sha512-+dTicT1lklwOpeoiDspUoRSQYHhrr2IzllrX89/WuTPEBm2eww1xurqrSTQYC0MuVeX1s9/i4k34Q0ZnspypWg==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "@algolia/client-personalization": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.12.2.tgz", + "integrity": "sha512-JBW3vYFGIm5sAAy3cLUdmUCpmSAdreo5S1fERg7xgF6KyxGrwyy5BViTNWrOKG+av2yusk1wKydOYJ1Fbpbaxw==", + "dev": true, + "requires": { + "@algolia/client-common": "4.12.2", + "@algolia/requester-common": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "@algolia/client-search": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.12.2.tgz", + "integrity": "sha512-JIqi14TgfEqAooNbSPBC1ZCk3Pnviqlaz9KofAqWBxSRTpPUFnU/XQCU5ihR0PC68SFVDnU/Y9cak/XotXPUeg==", + "dev": true, + "requires": { + "@algolia/client-common": "4.12.2", + "@algolia/requester-common": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "@algolia/logger-common": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.12.2.tgz", + "integrity": "sha512-iOiJAymLjq137G7+8EQuUEkrgta0cZGMg6scp8s4hJ+X6k+6By4nyptdkCWYwKLsW/Xy927QcIhGlkWV78vQIQ==", + "dev": true + }, + "@algolia/logger-console": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.12.2.tgz", + "integrity": "sha512-veuQZyTSqHoHJtr9mLMnYeal9Mee6hCie4eqY+645VbeOrgT9p/kCMbKg5GLJGoLPlXGu7C0XpHyUj5k7/NQyw==", + "dev": true, + "requires": { + "@algolia/logger-common": "4.12.2" + } + }, + "@algolia/requester-browser-xhr": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.2.tgz", + "integrity": "sha512-FpFdHNd81tS3zj6Glqd+lt+RV0ljPExKtx+QB+gani6HWZ9YlSCM+Zl82T4ibxN+hmkrMeAyT+TMzS0jiGhGyQ==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.12.2" + } + }, + "@algolia/requester-common": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.12.2.tgz", + "integrity": "sha512-4szj/lvDQf/u8EyyRBBRZD1ZkKDyLBbckLj7meQDlnbfwnW1UpLwpB2l3XJ9wDmDSftGxUCeTl5oMFe4z9OEvQ==", + "dev": true + }, + "@algolia/requester-node-http": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.12.2.tgz", + "integrity": "sha512-UXfJNZt2KMwjBjiOa3cJ/PyoXWZa/F1vy6rdyG4xQeZDcLbqKP3O2b+bOJcGPmFbmdwBhtAyMVLt+hvAvAVfOw==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.12.2" + } + }, + "@algolia/transporter": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.12.2.tgz", + "integrity": "sha512-PUq79if4CukXsm27ymTQ3eD3juSvMcyJmt6mxCkSFE0zQRL4ert61HBlNH6S9y/quUVe3g7oggfHq3d5pdpqZA==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.12.2", + "@algolia/logger-common": "4.12.2", + "@algolia/requester-common": "4.12.2" + } + }, + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", + "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", + "dev": true + }, + "@docsearch/css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.0.0.tgz", + "integrity": "sha512-1kkV7tkAsiuEd0shunYRByKJe3xQDG2q7wYg24SOw1nV9/2lwEd4WrUYRJC/ukGTl2/kHeFxsaUvtiOy0y6fFA==", + "dev": true + }, + "@docsearch/js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.0.0.tgz", + "integrity": "sha512-j3tUJWlgW3slYqzGB8fm7y05kh2qqrIK1dZOXHeMUm/5gdKE85fiz/ltfCPMDFb/MXF+bLZChJXSMzqY0Ck30Q==", + "dev": true, + "requires": { + "@docsearch/react": "3.0.0", + "preact": "^10.0.0" + } + }, + "@docsearch/react": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.0.0.tgz", + "integrity": "sha512-yhMacqS6TVQYoBh/o603zszIb5Bl8MIXuOc6Vy617I74pirisDzzcNh0NEaYQt50fVVR3khUbeEhUEWEWipESg==", + "dev": true, + "requires": { + "@algolia/autocomplete-core": "1.5.2", + "@algolia/autocomplete-preset-algolia": "1.5.2", + "@docsearch/css": "3.0.0", + "algoliasearch": "^4.0.0" + } + }, + "@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" + } + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true, + "peer": true + }, + "@types/react": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", + "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", + "dev": true, + "peer": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true, + "peer": true + }, + "@vitejs/plugin-vue": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.2.4.tgz", + "integrity": "sha512-ev9AOlp0ljCaDkFZF3JwC/pD2N4Hh+r5srl5JHM6BKg5+99jiiK0rE/XaRs3pVm1wzyKkjUy/StBSoXX5fFzcw==", + "dev": true, + "requires": {} + }, + "@vue/compiler-core": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.31.tgz", + "integrity": "sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-dom": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz", + "integrity": "sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==", + "dev": true, + "requires": { + "@vue/compiler-core": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "@vue/compiler-sfc": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz", + "integrity": "sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.31", + "@vue/compiler-dom": "3.2.31", + "@vue/compiler-ssr": "3.2.31", + "@vue/reactivity-transform": "3.2.31", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-ssr": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz", + "integrity": "sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==", + "dev": true, + "requires": { + "@vue/compiler-dom": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "@vue/reactivity": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.31.tgz", + "integrity": "sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==", + "dev": true, + "requires": { + "@vue/shared": "3.2.31" + } + }, + "@vue/reactivity-transform": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.31.tgz", + "integrity": "sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==", + "dev": true, + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.31", + "@vue/shared": "3.2.31", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "@vue/runtime-core": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.31.tgz", + "integrity": "sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==", + "dev": true, + "requires": { + "@vue/reactivity": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "@vue/runtime-dom": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.31.tgz", + "integrity": "sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==", + "dev": true, + "requires": { + "@vue/runtime-core": "3.2.31", + "@vue/shared": "3.2.31", + "csstype": "^2.6.8" + }, + "dependencies": { + "csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==", + "dev": true + } + } + }, + "@vue/server-renderer": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.31.tgz", + "integrity": "sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==", + "dev": true, + "requires": { + "@vue/compiler-ssr": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "@vue/shared": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.31.tgz", + "integrity": "sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==", + "dev": true + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "algoliasearch": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.12.2.tgz", + "integrity": "sha512-bn1P9+V415zeDQJtXn+1SwuwedEAv9/LJAxt8XwR6ygH/sMwaHSm2hpkz8wIbCBt/tKQ43TL672Kyxzv5PwGgQ==", + "dev": true, + "requires": { + "@algolia/cache-browser-local-storage": "4.12.2", + "@algolia/cache-common": "4.12.2", + "@algolia/cache-in-memory": "4.12.2", + "@algolia/client-account": "4.12.2", + "@algolia/client-analytics": "4.12.2", + "@algolia/client-common": "4.12.2", + "@algolia/client-personalization": "4.12.2", + "@algolia/client-search": "4.12.2", + "@algolia/logger-common": "4.12.2", + "@algolia/logger-console": "4.12.2", + "@algolia/requester-browser-xhr": "4.12.2", + "@algolia/requester-common": "4.12.2", + "@algolia/requester-node-http": "4.12.2", + "@algolia/transporter": "4.12.2" + } + }, + "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": { + "color-convert": "^2.0.1" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", + "dev": true + }, + "autoprefixer": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", + "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", + "dev": true, + "peer": true, + "requires": { + "browserslist": "^4.19.1", + "caniuse-lite": "^1.0.30001297", + "fraction.js": "^4.1.2", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "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 + }, + "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.19.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz", + "integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==", + "dev": true, + "peer": true, + "requires": { + "caniuse-lite": "^1.0.30001312", + "electron-to-chromium": "^1.4.71", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "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-lite": { + "version": "1.0.30001313", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001313.tgz", + "integrity": "sha512-rI1UN0koZUiKINjysQDuRi2VeSCce3bYJNmDcj3PIKREiAmjakugBul1QSkg/fPrlULYl6oWfGg3PbgOSY9X4Q==", + "dev": true, + "peer": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "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 + }, + "cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "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 + }, + "csstype": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", + "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", + "dev": true, + "peer": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "requires": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } + }, + "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 + }, + "electron-to-chromium": { + "version": "1.4.75", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz", + "integrity": "sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q==", + "dev": true, + "peer": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "esbuild": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.25.tgz", + "integrity": "sha512-4JHEIOMNFvK09ziiL+iVmldIhLbn49V4NAVo888tcGFKedEZY/Y8YapfStJ6zSE23tzYPKxqKwQBnQoIO0BI/Q==", + "dev": true, + "requires": { + "esbuild-android-64": "0.14.25", + "esbuild-android-arm64": "0.14.25", + "esbuild-darwin-64": "0.14.25", + "esbuild-darwin-arm64": "0.14.25", + "esbuild-freebsd-64": "0.14.25", + "esbuild-freebsd-arm64": "0.14.25", + "esbuild-linux-32": "0.14.25", + "esbuild-linux-64": "0.14.25", + "esbuild-linux-arm": "0.14.25", + "esbuild-linux-arm64": "0.14.25", + "esbuild-linux-mips64le": "0.14.25", + "esbuild-linux-ppc64le": "0.14.25", + "esbuild-linux-riscv64": "0.14.25", + "esbuild-linux-s390x": "0.14.25", + "esbuild-netbsd-64": "0.14.25", + "esbuild-openbsd-64": "0.14.25", + "esbuild-sunos-64": "0.14.25", + "esbuild-windows-32": "0.14.25", + "esbuild-windows-64": "0.14.25", + "esbuild-windows-arm64": "0.14.25" + } + }, + "esbuild-android-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.25.tgz", + "integrity": "sha512-L5vCUk7TzFbBnoESNoXjU3x9+/+7TDIE/1mTfy/erAfvZAqC+S3sp/Qa9wkypFMcFvN9FzvESkTlpeQDolREtQ==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.25.tgz", + "integrity": "sha512-4jv5xPjM/qNm27T5j3ZEck0PvjgQtoMHnz4FzwF5zNP56PvY2CT0WStcAIl6jNlsuDdN63rk2HRBIsO6xFbcFw==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.25.tgz", + "integrity": "sha512-TGp8tuudIxOyWd1+8aYPxQmC1ZQyvij/AfNBa35RubixD0zJ1vkKHVAzo0Zao1zcG6pNqiSyzfPto8vmg0s7oA==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.25.tgz", + "integrity": "sha512-oTcDgdm0MDVEmw2DWu8BV68pYuImpFgvWREPErBZmNA4MYKGuBRaCiJqq6jZmBR1x+3y1DWCjez+5uLtuAm6mw==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.25.tgz", + "integrity": "sha512-ueAqbnMZ8arnuLH8tHwTCQYeptnHOUV7vA6px6j4zjjQwDx7TdP7kACPf3TLZLdJQ3CAD1XCvQ2sPhX+8tacvQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.25.tgz", + "integrity": "sha512-+ZVWud2HKh+Ob6k/qiJWjBtUg4KmJGGmbvEXXW1SNKS7hW7HU+Zq2ZCcE1akFxOPkVB+EhOty/sSek30tkCYug==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.25.tgz", + "integrity": "sha512-3OP/lwV3kCzEz45tobH9nj+uE4ubhGsfx+tn0L26WAGtUbmmcRpqy7XRG/qK7h1mClZ+eguIANcQntYMdYklfw==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.25.tgz", + "integrity": "sha512-+aKHdHZmX9qwVlQmu5xYXh7GsBFf4TWrePgeJTalhXHOG7NNuUwoHmketGiZEoNsWyyqwH9rE5BC+iwcLY30Ug==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.25.tgz", + "integrity": "sha512-aTLcE2VBoLydL943REcAcgnDi3bHtmULSXWLbjtBdtykRatJVSxKMjK9YlBXUZC4/YcNQfH7AxwVeQr9fNxPhw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.25.tgz", + "integrity": "sha512-UxfenPx/wSZx55gScCImPtXekvZQLI2GW3qe5dtlmU7luiqhp5GWPzGeQEbD3yN3xg/pHc671m5bma5Ns7lBHw==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.25.tgz", + "integrity": "sha512-wLWYyqVfYx9Ur6eU5RT92yJVsaBGi5RdkoWqRHOqcJ38Kn60QMlcghsKeWfe9jcYut8LangYZ98xO1LxIoSXrQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.25.tgz", + "integrity": "sha512-0dR6Csl6Zas3g4p9ULckEl8Mo8IInJh33VCJ3eaV1hj9+MHGdmDOakYMN8MZP9/5nl+NU/0ygpd14cWgy8uqRw==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.25.tgz", + "integrity": "sha512-J4d20HDmTrgvhR0bdkDhvvJGaikH3LzXQnNaseo8rcw9Yqby9A90gKUmWpfwqLVNRILvNnAmKLfBjCKU9ajg8w==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.25.tgz", + "integrity": "sha512-YI2d5V6nTE73ZnhEKQD7MtsPs1EtUZJ3obS21oxQxGbbRw1G+PtJKjNyur+3t6nzHP9oTg6GHQ3S3hOLLmbDIQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.25.tgz", + "integrity": "sha512-TKIVgNWLUOkr+Exrye70XTEE1lJjdQXdM4tAXRzfHE9iBA7LXWcNtVIuSnphTqpanPzTDFarF0yqq4kpbC6miA==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.25.tgz", + "integrity": "sha512-QgFJ37A15D7NIXBTYEqz29+uw3nNBOIyog+3kFidANn6kjw0GHZ0lEYQn+cwjyzu94WobR+fes7cTl/ZYlHb1A==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.25.tgz", + "integrity": "sha512-rmWfjUItYIVlqr5EnTH1+GCxXiBOC42WBZ3w++qh7n2cS9Xo0lO5pGSG2N+huOU2fX5L+6YUuJ78/vOYvefeFw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.25.tgz", + "integrity": "sha512-HGAxVUofl3iUIz9W10Y9XKtD0bNsK9fBXv1D55N/ljNvkrAYcGB8YCm0v7DjlwtyS6ws3dkdQyXadbxkbzaKOA==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.25.tgz", + "integrity": "sha512-TirEohRkfWU9hXLgoDxzhMQD1g8I2mOqvdQF2RS9E/wbkORTAqJHyh7wqGRCQAwNzdNXdg3JAyhQ9/177AadWA==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.25", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.25.tgz", + "integrity": "sha512-4ype9ERiI45rSh+R8qUoBtaj6kJvUOI7oVLhKqPEpcF4Pa5PpT3hm/mXAyotJHREkHpM87PAJcA442mLnbtlNA==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "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" + } + }, + "fraction.js": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz", + "integrity": "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==", + "dev": true, + "peer": 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 + }, + "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" + } + }, + "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" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "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.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "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-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 + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "lilconfig": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", + "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", + "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 + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "peer": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "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.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true + }, + "node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true, + "peer": 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, + "peer": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "peer": true + }, + "object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "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": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "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 + }, + "postcss": { + "version": "8.4.7", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz", + "integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==", + "dev": true, + "requires": { + "nanoid": "^3.3.1", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-load-config": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.3.tgz", + "integrity": "sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==", + "dev": true, + "requires": { + "lilconfig": "^2.0.4", + "yaml": "^1.10.2" + } + }, + "postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.6" + } + }, + "postcss-selector-parser": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", + "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "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 + }, + "preact": { + "version": "10.6.6", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.6.6.tgz", + "integrity": "sha512-dgxpTFV2vs4vizwKohYKkk7g7rmp1wOOcfd4Tz3IB3Wi+ivZzsn/SpeKJhRENSE+n8sUfsAl4S3HiCVT923ABw==", + "dev": true + }, + "prismjs": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", + "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", + "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 + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + } + }, + "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" + } + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rollup": { + "version": "2.69.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.69.1.tgz", + "integrity": "sha512-xaQKTomUVZBopk38EIshM/kOoPFkKWisgBV7Emy80coP9MOSLUDrba1jKZhqH0iS5DoGcRbbcuyl/BzblV8w5w==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "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" + } + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "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 + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "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 + }, + "tailwindcss": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.23.tgz", + "integrity": "sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==", + "dev": true, + "requires": { + "arg": "^5.0.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "cosmiconfig": "^7.0.1", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "normalize-path": "^3.0.0", + "object-hash": "^2.2.0", + "postcss": "^8.4.6", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.0", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.0" + } + }, + "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" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vite": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.8.6.tgz", + "integrity": "sha512-e4H0QpludOVKkmOsRyqQ7LTcMUDF3mcgyNU4lmi0B5JUbe0ZxeBBl8VoZ8Y6Rfn9eFKYtdXNPcYK97ZwH+K2ug==", + "dev": true, + "requires": { + "esbuild": "^0.14.14", + "fsevents": "~2.3.2", + "postcss": "^8.4.6", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + } + }, + "vitepress": { + "version": "0.22.3", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-0.22.3.tgz", + "integrity": "sha512-Yfvu/rent2vp/TXIDZMutS6ft2TJPn4xngS48PYFWDEbuFI2ccUAXM481lF1qVVnCKxfh4g8e/KPvevSJdg1Bw==", + "dev": true, + "requires": { + "@docsearch/css": "^3.0.0-alpha.41", + "@docsearch/js": "^3.0.0-alpha.41", + "@vitejs/plugin-vue": "^2.2.0", + "prismjs": "^1.25.0", + "vite": "^2.8.1", + "vue": "^3.2.31" + } + }, + "vue": { + "version": "3.2.31", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.31.tgz", + "integrity": "sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==", + "dev": true, + "requires": { + "@vue/compiler-dom": "3.2.31", + "@vue/compiler-sfc": "3.2.31", + "@vue/runtime-dom": "3.2.31", + "@vue/server-renderer": "3.2.31", + "@vue/shared": "3.2.31" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + } + } +} diff --git a/docs/package.json b/docs/package.json index 9258fab6..da849551 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,21 +1,21 @@ { "name": "castopod-docs", - "type": "module", - "version": "0.0.1", + "version": "0.0.0-development", + "description": "Castopod documentation using vitepress", + "main": "index.js", "scripts": { - "dev": "astro dev", - "start": "astro dev", - "build": "astro build", - "preview": "astro preview", - "astro": "astro", - "prepare": "astro telemetry disable" + "dev": "vitepress --port=3050", + "build": "vitepress build", + "serve": "vitepress serve" }, - "dependencies": { - "@astrojs/starlight": "^0.37.6", - "@fontsource/inter": "^5.2.8", - "@fontsource/rubik": "^5.2.8", - "astro": "^5.17.2", - "sharp": "^0.34.5", - "starlight-openapi": "^0.22.0" + "author": { + "name": "Yassine Doghri", + "email": "yassine@doghri.fr", + "url": "https://code.castopod.org/yassine" + }, + "license": "AGPL-3.0-or-later", + "devDependencies": { + "tailwindcss": "^3.0.23", + "vitepress": "^0.22.3" } } diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml deleted file mode 100644 index 45dac61d..00000000 --- a/docs/pnpm-lock.yaml +++ /dev/null @@ -1,6029 +0,0 @@ -lockfileVersion: "9.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - .: - dependencies: - "@astrojs/starlight": - specifier: ^0.37.6 - version: 0.37.6(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3)) - "@fontsource/inter": - specifier: ^5.2.8 - version: 5.2.8 - "@fontsource/rubik": - specifier: ^5.2.8 - version: 5.2.8 - astro: - specifier: ^5.17.2 - version: 5.17.2(rollup@4.57.1)(typescript@5.9.3) - sharp: - specifier: ^0.34.5 - version: 0.34.5 - starlight-openapi: - specifier: ^0.22.0 - version: 0.22.0(@astrojs/markdown-remark@6.3.10)(@astrojs/starlight@0.37.6(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3)))(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3))(openapi-types@12.1.3) - -packages: - "@apidevtools/json-schema-ref-parser@13.0.5": - resolution: - { - integrity: sha512-xfh4xVJD62gG6spIc7lwxoWT+l16nZu1ELyU8FkjaP/oD2yP09EvLAU6KhtudN9aML2Khhs9pY6Slr7KGTES3w==, - } - engines: { node: ">= 16" } - - "@astrojs/compiler@2.13.1": - resolution: - { - integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==, - } - - "@astrojs/internal-helpers@0.7.5": - resolution: - { - integrity: sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA==, - } - - "@astrojs/markdown-remark@6.3.10": - resolution: - { - integrity: sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A==, - } - - "@astrojs/mdx@4.3.13": - resolution: - { - integrity: sha512-IHDHVKz0JfKBy3//52JSiyWv089b7GVSChIXLrlUOoTLWowG3wr2/8hkaEgEyd/vysvNQvGk+QhysXpJW5ve6Q==, - } - engines: { node: 18.20.8 || ^20.3.0 || >=22.0.0 } - peerDependencies: - astro: ^5.0.0 - - "@astrojs/prism@3.3.0": - resolution: - { - integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==, - } - engines: { node: 18.20.8 || ^20.3.0 || >=22.0.0 } - - "@astrojs/sitemap@3.7.0": - resolution: - { - integrity: sha512-+qxjUrz6Jcgh+D5VE1gKUJTA3pSthuPHe6Ao5JCxok794Lewx8hBFaWHtOnN0ntb2lfOf7gvOi9TefUswQ/ZVA==, - } - - "@astrojs/starlight@0.37.6": - resolution: - { - integrity: sha512-wQrKwH431q+8FsLBnNQeG+R36TMtEGxTQ2AuiVpcx9APcazvL3n7wVW8mMmYyxX0POjTnxlcWPkdMGR3Yj1L+w==, - } - peerDependencies: - astro: ^5.5.0 - - "@astrojs/telemetry@3.3.0": - resolution: - { - integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==, - } - engines: { node: 18.20.8 || ^20.3.0 || >=22.0.0 } - - "@babel/code-frame@7.29.0": - resolution: - { - integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-string-parser@7.27.1": - resolution: - { - integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-validator-identifier@7.28.5": - resolution: - { - integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==, - } - engines: { node: ">=6.9.0" } - - "@babel/parser@7.29.0": - resolution: - { - integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==, - } - engines: { node: ">=6.0.0" } - hasBin: true - - "@babel/runtime@7.28.6": - resolution: - { - integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==, - } - engines: { node: ">=6.9.0" } - - "@babel/types@7.29.0": - resolution: - { - integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==, - } - engines: { node: ">=6.9.0" } - - "@capsizecss/unpack@4.0.0": - resolution: - { - integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==, - } - engines: { node: ">=18" } - - "@ctrl/tinycolor@4.2.0": - resolution: - { - integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==, - } - engines: { node: ">=14" } - - "@emnapi/runtime@1.8.1": - resolution: - { - integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==, - } - - "@esbuild/aix-ppc64@0.25.12": - resolution: - { - integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==, - } - engines: { node: ">=18" } - cpu: [ppc64] - os: [aix] - - "@esbuild/aix-ppc64@0.27.3": - resolution: - { - integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==, - } - engines: { node: ">=18" } - cpu: [ppc64] - os: [aix] - - "@esbuild/android-arm64@0.25.12": - resolution: - { - integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [android] - - "@esbuild/android-arm64@0.27.3": - resolution: - { - integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [android] - - "@esbuild/android-arm@0.25.12": - resolution: - { - integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==, - } - engines: { node: ">=18" } - cpu: [arm] - os: [android] - - "@esbuild/android-arm@0.27.3": - resolution: - { - integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==, - } - engines: { node: ">=18" } - cpu: [arm] - os: [android] - - "@esbuild/android-x64@0.25.12": - resolution: - { - integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [android] - - "@esbuild/android-x64@0.27.3": - resolution: - { - integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [android] - - "@esbuild/darwin-arm64@0.25.12": - resolution: - { - integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [darwin] - - "@esbuild/darwin-arm64@0.27.3": - resolution: - { - integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [darwin] - - "@esbuild/darwin-x64@0.25.12": - resolution: - { - integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [darwin] - - "@esbuild/darwin-x64@0.27.3": - resolution: - { - integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [darwin] - - "@esbuild/freebsd-arm64@0.25.12": - resolution: - { - integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [freebsd] - - "@esbuild/freebsd-arm64@0.27.3": - resolution: - { - integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [freebsd] - - "@esbuild/freebsd-x64@0.25.12": - resolution: - { - integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [freebsd] - - "@esbuild/freebsd-x64@0.27.3": - resolution: - { - integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [freebsd] - - "@esbuild/linux-arm64@0.25.12": - resolution: - { - integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [linux] - - "@esbuild/linux-arm64@0.27.3": - resolution: - { - integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [linux] - - "@esbuild/linux-arm@0.25.12": - resolution: - { - integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==, - } - engines: { node: ">=18" } - cpu: [arm] - os: [linux] - - "@esbuild/linux-arm@0.27.3": - resolution: - { - integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==, - } - engines: { node: ">=18" } - cpu: [arm] - os: [linux] - - "@esbuild/linux-ia32@0.25.12": - resolution: - { - integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==, - } - engines: { node: ">=18" } - cpu: [ia32] - os: [linux] - - "@esbuild/linux-ia32@0.27.3": - resolution: - { - integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==, - } - engines: { node: ">=18" } - cpu: [ia32] - os: [linux] - - "@esbuild/linux-loong64@0.25.12": - resolution: - { - integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==, - } - engines: { node: ">=18" } - cpu: [loong64] - os: [linux] - - "@esbuild/linux-loong64@0.27.3": - resolution: - { - integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==, - } - engines: { node: ">=18" } - cpu: [loong64] - os: [linux] - - "@esbuild/linux-mips64el@0.25.12": - resolution: - { - integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==, - } - engines: { node: ">=18" } - cpu: [mips64el] - os: [linux] - - "@esbuild/linux-mips64el@0.27.3": - resolution: - { - integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==, - } - engines: { node: ">=18" } - cpu: [mips64el] - os: [linux] - - "@esbuild/linux-ppc64@0.25.12": - resolution: - { - integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==, - } - engines: { node: ">=18" } - cpu: [ppc64] - os: [linux] - - "@esbuild/linux-ppc64@0.27.3": - resolution: - { - integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==, - } - engines: { node: ">=18" } - cpu: [ppc64] - os: [linux] - - "@esbuild/linux-riscv64@0.25.12": - resolution: - { - integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==, - } - engines: { node: ">=18" } - cpu: [riscv64] - os: [linux] - - "@esbuild/linux-riscv64@0.27.3": - resolution: - { - integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==, - } - engines: { node: ">=18" } - cpu: [riscv64] - os: [linux] - - "@esbuild/linux-s390x@0.25.12": - resolution: - { - integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==, - } - engines: { node: ">=18" } - cpu: [s390x] - os: [linux] - - "@esbuild/linux-s390x@0.27.3": - resolution: - { - integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==, - } - engines: { node: ">=18" } - cpu: [s390x] - os: [linux] - - "@esbuild/linux-x64@0.25.12": - resolution: - { - integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [linux] - - "@esbuild/linux-x64@0.27.3": - resolution: - { - integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [linux] - - "@esbuild/netbsd-arm64@0.25.12": - resolution: - { - integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [netbsd] - - "@esbuild/netbsd-arm64@0.27.3": - resolution: - { - integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [netbsd] - - "@esbuild/netbsd-x64@0.25.12": - resolution: - { - integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [netbsd] - - "@esbuild/netbsd-x64@0.27.3": - resolution: - { - integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [netbsd] - - "@esbuild/openbsd-arm64@0.25.12": - resolution: - { - integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [openbsd] - - "@esbuild/openbsd-arm64@0.27.3": - resolution: - { - integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [openbsd] - - "@esbuild/openbsd-x64@0.25.12": - resolution: - { - integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [openbsd] - - "@esbuild/openbsd-x64@0.27.3": - resolution: - { - integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [openbsd] - - "@esbuild/openharmony-arm64@0.25.12": - resolution: - { - integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [openharmony] - - "@esbuild/openharmony-arm64@0.27.3": - resolution: - { - integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [openharmony] - - "@esbuild/sunos-x64@0.25.12": - resolution: - { - integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [sunos] - - "@esbuild/sunos-x64@0.27.3": - resolution: - { - integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [sunos] - - "@esbuild/win32-arm64@0.25.12": - resolution: - { - integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [win32] - - "@esbuild/win32-arm64@0.27.3": - resolution: - { - integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [win32] - - "@esbuild/win32-ia32@0.25.12": - resolution: - { - integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==, - } - engines: { node: ">=18" } - cpu: [ia32] - os: [win32] - - "@esbuild/win32-ia32@0.27.3": - resolution: - { - integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==, - } - engines: { node: ">=18" } - cpu: [ia32] - os: [win32] - - "@esbuild/win32-x64@0.25.12": - resolution: - { - integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [win32] - - "@esbuild/win32-x64@0.27.3": - resolution: - { - integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [win32] - - "@expressive-code/core@0.41.6": - resolution: - { - integrity: sha512-FvJQP+hG0jWi/FLBSmvHInDqWR7jNANp9PUDjdMqSshHb0y7sxx3vHuoOr6SgXjWw+MGLqorZyPQ0aAlHEok6g==, - } - - "@expressive-code/plugin-frames@0.41.6": - resolution: - { - integrity: sha512-d+hkSYXIQot6fmYnOmWAM+7TNWRv/dhfjMsNq+mIZz8Tb4mPHOcgcfZeEM5dV9TDL0ioQNvtcqQNuzA1sRPjxg==, - } - - "@expressive-code/plugin-shiki@0.41.6": - resolution: - { - integrity: sha512-Y6zmKBmsIUtWTzdefqlzm/h9Zz0Rc4gNdt2GTIH7fhHH2I9+lDYCa27BDwuBhjqcos6uK81Aca9dLUC4wzN+ng==, - } - - "@expressive-code/plugin-text-markers@0.41.6": - resolution: - { - integrity: sha512-PBFa1wGyYzRExMDzBmAWC6/kdfG1oLn4pLpBeTfIRrALPjcGA/59HP3e7q9J0Smk4pC7U+lWkA2LHR8FYV8U7Q==, - } - - "@fontsource/inter@5.2.8": - resolution: - { - integrity: sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==, - } - - "@fontsource/rubik@5.2.8": - resolution: - { - integrity: sha512-PIc8QR7FqWPcYhbdRiGff56vQlKqg/ytES1YqecSq1GkgxiH4TBshrFvDEOZ9JonUF9m1qQ+qXxJj7wD5zgXEw==, - } - - "@humanwhocodes/momoa@2.0.4": - resolution: - { - integrity: sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==, - } - engines: { node: ">=10.10.0" } - - "@img/colour@1.0.0": - resolution: - { - integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==, - } - engines: { node: ">=18" } - - "@img/sharp-darwin-arm64@0.34.5": - resolution: - { - integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [darwin] - - "@img/sharp-darwin-x64@0.34.5": - resolution: - { - integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [darwin] - - "@img/sharp-libvips-darwin-arm64@1.2.4": - resolution: - { - integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==, - } - cpu: [arm64] - os: [darwin] - - "@img/sharp-libvips-darwin-x64@1.2.4": - resolution: - { - integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==, - } - cpu: [x64] - os: [darwin] - - "@img/sharp-libvips-linux-arm64@1.2.4": - resolution: - { - integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==, - } - cpu: [arm64] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-arm@1.2.4": - resolution: - { - integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==, - } - cpu: [arm] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-ppc64@1.2.4": - resolution: - { - integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==, - } - cpu: [ppc64] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-riscv64@1.2.4": - resolution: - { - integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==, - } - cpu: [riscv64] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-s390x@1.2.4": - resolution: - { - integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==, - } - cpu: [s390x] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-x64@1.2.4": - resolution: - { - integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==, - } - cpu: [x64] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linuxmusl-arm64@1.2.4": - resolution: - { - integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==, - } - cpu: [arm64] - os: [linux] - libc: [musl] - - "@img/sharp-libvips-linuxmusl-x64@1.2.4": - resolution: - { - integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==, - } - cpu: [x64] - os: [linux] - libc: [musl] - - "@img/sharp-linux-arm64@0.34.5": - resolution: - { - integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-arm@0.34.5": - resolution: - { - integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-ppc64@0.34.5": - resolution: - { - integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [ppc64] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-riscv64@0.34.5": - resolution: - { - integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [riscv64] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-s390x@0.34.5": - resolution: - { - integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [s390x] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-x64@0.34.5": - resolution: - { - integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [linux] - libc: [glibc] - - "@img/sharp-linuxmusl-arm64@0.34.5": - resolution: - { - integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [linux] - libc: [musl] - - "@img/sharp-linuxmusl-x64@0.34.5": - resolution: - { - integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [linux] - libc: [musl] - - "@img/sharp-wasm32@0.34.5": - resolution: - { - integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [wasm32] - - "@img/sharp-win32-arm64@0.34.5": - resolution: - { - integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [win32] - - "@img/sharp-win32-ia32@0.34.5": - resolution: - { - integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [ia32] - os: [win32] - - "@img/sharp-win32-x64@0.34.5": - resolution: - { - integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [win32] - - "@jridgewell/sourcemap-codec@1.5.5": - resolution: - { - integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, - } - - "@mdx-js/mdx@3.1.1": - resolution: - { - integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==, - } - - "@oslojs/encoding@1.1.0": - resolution: - { - integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==, - } - - "@pagefind/darwin-arm64@1.4.0": - resolution: - { - integrity: sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==, - } - cpu: [arm64] - os: [darwin] - - "@pagefind/darwin-x64@1.4.0": - resolution: - { - integrity: sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==, - } - cpu: [x64] - os: [darwin] - - "@pagefind/default-ui@1.4.0": - resolution: - { - integrity: sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==, - } - - "@pagefind/freebsd-x64@1.4.0": - resolution: - { - integrity: sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==, - } - cpu: [x64] - os: [freebsd] - - "@pagefind/linux-arm64@1.4.0": - resolution: - { - integrity: sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==, - } - cpu: [arm64] - os: [linux] - - "@pagefind/linux-x64@1.4.0": - resolution: - { - integrity: sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==, - } - cpu: [x64] - os: [linux] - - "@pagefind/windows-x64@1.4.0": - resolution: - { - integrity: sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==, - } - cpu: [x64] - os: [win32] - - "@readme/better-ajv-errors@2.4.0": - resolution: - { - integrity: sha512-9WODaOAKSl/mU+MYNZ2aHCrkoRSvmQ+1YkLj589OEqqjOAhbn8j7Z+ilYoiTu/he6X63/clsxxAB4qny9/dDzg==, - } - engines: { node: ">=18" } - peerDependencies: - ajv: 4.11.8 - 8 - - "@readme/openapi-parser@4.1.2": - resolution: - { - integrity: sha512-lAFH88r/CHs5VZDUocEda0OSMSQsr6801sziIjOKyVA+0hSFN+BPuelPF5XvkMROHecnPd+XEJN1iNQqCgER/g==, - } - engines: { node: ">=20" } - peerDependencies: - openapi-types: ">=7" - - "@readme/openapi-schemas@3.1.0": - resolution: - { - integrity: sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw==, - } - engines: { node: ">=18" } - - "@rollup/pluginutils@5.3.0": - resolution: - { - integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==, - } - engines: { node: ">=14.0.0" } - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - "@rollup/rollup-android-arm-eabi@4.57.1": - resolution: - { - integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==, - } - cpu: [arm] - os: [android] - - "@rollup/rollup-android-arm64@4.57.1": - resolution: - { - integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==, - } - cpu: [arm64] - os: [android] - - "@rollup/rollup-darwin-arm64@4.57.1": - resolution: - { - integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==, - } - cpu: [arm64] - os: [darwin] - - "@rollup/rollup-darwin-x64@4.57.1": - resolution: - { - integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==, - } - cpu: [x64] - os: [darwin] - - "@rollup/rollup-freebsd-arm64@4.57.1": - resolution: - { - integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==, - } - cpu: [arm64] - os: [freebsd] - - "@rollup/rollup-freebsd-x64@4.57.1": - resolution: - { - integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==, - } - cpu: [x64] - os: [freebsd] - - "@rollup/rollup-linux-arm-gnueabihf@4.57.1": - resolution: - { - integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==, - } - cpu: [arm] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-arm-musleabihf@4.57.1": - resolution: - { - integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==, - } - cpu: [arm] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-arm64-gnu@4.57.1": - resolution: - { - integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==, - } - cpu: [arm64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-arm64-musl@4.57.1": - resolution: - { - integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==, - } - cpu: [arm64] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-loong64-gnu@4.57.1": - resolution: - { - integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==, - } - cpu: [loong64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-loong64-musl@4.57.1": - resolution: - { - integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==, - } - cpu: [loong64] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-ppc64-gnu@4.57.1": - resolution: - { - integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==, - } - cpu: [ppc64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-ppc64-musl@4.57.1": - resolution: - { - integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==, - } - cpu: [ppc64] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-riscv64-gnu@4.57.1": - resolution: - { - integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==, - } - cpu: [riscv64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-riscv64-musl@4.57.1": - resolution: - { - integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==, - } - cpu: [riscv64] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-s390x-gnu@4.57.1": - resolution: - { - integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==, - } - cpu: [s390x] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-x64-gnu@4.57.1": - resolution: - { - integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==, - } - cpu: [x64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-x64-musl@4.57.1": - resolution: - { - integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==, - } - cpu: [x64] - os: [linux] - libc: [musl] - - "@rollup/rollup-openbsd-x64@4.57.1": - resolution: - { - integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==, - } - cpu: [x64] - os: [openbsd] - - "@rollup/rollup-openharmony-arm64@4.57.1": - resolution: - { - integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==, - } - cpu: [arm64] - os: [openharmony] - - "@rollup/rollup-win32-arm64-msvc@4.57.1": - resolution: - { - integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==, - } - cpu: [arm64] - os: [win32] - - "@rollup/rollup-win32-ia32-msvc@4.57.1": - resolution: - { - integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==, - } - cpu: [ia32] - os: [win32] - - "@rollup/rollup-win32-x64-gnu@4.57.1": - resolution: - { - integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==, - } - cpu: [x64] - os: [win32] - - "@rollup/rollup-win32-x64-msvc@4.57.1": - resolution: - { - integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==, - } - cpu: [x64] - os: [win32] - - "@shikijs/core@3.22.0": - resolution: - { - integrity: sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==, - } - - "@shikijs/engine-javascript@3.22.0": - resolution: - { - integrity: sha512-jdKhfgW9CRtj3Tor0L7+yPwdG3CgP7W+ZEqSsojrMzCjD1e0IxIbwUMDDpYlVBlC08TACg4puwFGkZfLS+56Tw==, - } - - "@shikijs/engine-oniguruma@3.22.0": - resolution: - { - integrity: sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==, - } - - "@shikijs/langs@3.22.0": - resolution: - { - integrity: sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==, - } - - "@shikijs/themes@3.22.0": - resolution: - { - integrity: sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==, - } - - "@shikijs/types@3.22.0": - resolution: - { - integrity: sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==, - } - - "@shikijs/vscode-textmate@10.0.2": - resolution: - { - integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==, - } - - "@types/debug@4.1.12": - resolution: - { - integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==, - } - - "@types/estree-jsx@1.0.5": - resolution: - { - integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==, - } - - "@types/estree@1.0.8": - resolution: - { - integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, - } - - "@types/hast@3.0.4": - resolution: - { - integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==, - } - - "@types/js-yaml@4.0.9": - resolution: - { - integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==, - } - - "@types/json-schema@7.0.15": - resolution: - { - integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, - } - - "@types/mdast@4.0.4": - resolution: - { - integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==, - } - - "@types/mdx@2.0.13": - resolution: - { - integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==, - } - - "@types/ms@2.1.0": - resolution: - { - integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==, - } - - "@types/nlcst@2.0.3": - resolution: - { - integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==, - } - - "@types/node@17.0.45": - resolution: - { - integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==, - } - - "@types/sax@1.2.7": - resolution: - { - integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==, - } - - "@types/unist@2.0.11": - resolution: - { - integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==, - } - - "@types/unist@3.0.3": - resolution: - { - integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==, - } - - "@ungap/structured-clone@1.3.0": - resolution: - { - integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==, - } - - acorn-jsx@5.3.2: - resolution: - { - integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, - } - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.15.0: - resolution: - { - integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==, - } - engines: { node: ">=0.4.0" } - hasBin: true - - ajv-draft-04@1.0.0: - resolution: - { - integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==, - } - peerDependencies: - ajv: ^8.5.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv@8.18.0: - resolution: - { - integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==, - } - - ansi-align@3.0.1: - resolution: - { - integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==, - } - - ansi-regex@5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, - } - engines: { node: ">=8" } - - ansi-regex@6.2.2: - resolution: - { - integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, - } - engines: { node: ">=12" } - - ansi-styles@6.2.3: - resolution: - { - integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==, - } - engines: { node: ">=12" } - - anymatch@3.1.3: - resolution: - { - integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, - } - engines: { node: ">= 8" } - - arg@5.0.2: - resolution: - { - integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==, - } - - argparse@2.0.1: - resolution: - { - integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, - } - - aria-query@5.3.2: - resolution: - { - integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==, - } - engines: { node: ">= 0.4" } - - array-iterate@2.0.1: - resolution: - { - integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==, - } - - astring@1.9.0: - resolution: - { - integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==, - } - hasBin: true - - astro-expressive-code@0.41.6: - resolution: - { - integrity: sha512-l47tb1uhmVIebHUkw+HEPtU/av0G4O8Q34g2cbkPvC7/e9ZhANcjUUciKt9Hp6gSVDdIuXBBLwJQn2LkeGMOAw==, - } - peerDependencies: - astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta - - astro@5.17.2: - resolution: - { - integrity: sha512-7jnMqGo53hOQNwo1N/wqeOvUp8wwW/p+DeerSjSkHNx8L/1mhy6P7rVo7EhdmF8DpKqw0tl/B5Fx1WcIzg1ysA==, - } - engines: - { node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: ">=9.6.5", pnpm: ">=7.1.0" } - hasBin: true - - axobject-query@4.1.0: - resolution: - { - integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==, - } - engines: { node: ">= 0.4" } - - bail@2.0.2: - resolution: - { - integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==, - } - - base-64@1.0.0: - resolution: - { - integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==, - } - - bcp-47-match@2.0.3: - resolution: - { - integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==, - } - - bcp-47@2.1.0: - resolution: - { - integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==, - } - - boolbase@1.0.0: - resolution: - { - integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==, - } - - boxen@8.0.1: - resolution: - { - integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==, - } - engines: { node: ">=18" } - - camelcase@8.0.0: - resolution: - { - integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==, - } - engines: { node: ">=16" } - - ccount@2.0.1: - resolution: - { - integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==, - } - - chalk@5.6.2: - resolution: - { - integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==, - } - engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } - - character-entities-html4@2.1.0: - resolution: - { - integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==, - } - - character-entities-legacy@3.0.0: - resolution: - { - integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==, - } - - character-entities@2.0.2: - resolution: - { - integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==, - } - - character-reference-invalid@2.0.1: - resolution: - { - integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==, - } - - chokidar@5.0.0: - resolution: - { - integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==, - } - engines: { node: ">= 20.19.0" } - - ci-info@4.4.0: - resolution: - { - integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==, - } - engines: { node: ">=8" } - - cli-boxes@3.0.0: - resolution: - { - integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==, - } - engines: { node: ">=10" } - - clsx@2.1.1: - resolution: - { - integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==, - } - engines: { node: ">=6" } - - collapse-white-space@2.1.0: - resolution: - { - integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==, - } - - comma-separated-tokens@2.0.3: - resolution: - { - integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==, - } - - commander@11.1.0: - resolution: - { - integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==, - } - engines: { node: ">=16" } - - common-ancestor-path@1.0.1: - resolution: - { - integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==, - } - - cookie-es@1.2.2: - resolution: - { - integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==, - } - - cookie@1.1.1: - resolution: - { - integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==, - } - engines: { node: ">=18" } - - crossws@0.3.5: - resolution: - { - integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==, - } - - css-select@5.2.2: - resolution: - { - integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==, - } - - css-selector-parser@3.3.0: - resolution: - { - integrity: sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==, - } - - css-tree@2.2.1: - resolution: - { - integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==, - } - engines: { node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: ">=7.0.0" } - - css-tree@3.1.0: - resolution: - { - integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==, - } - engines: { node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0 } - - css-what@6.2.2: - resolution: - { - integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==, - } - engines: { node: ">= 6" } - - cssesc@3.0.0: - resolution: - { - integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==, - } - engines: { node: ">=4" } - hasBin: true - - csso@5.0.5: - resolution: - { - integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==, - } - engines: { node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: ">=7.0.0" } - - debug@4.4.3: - resolution: - { - integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, - } - engines: { node: ">=6.0" } - peerDependencies: - supports-color: "*" - peerDependenciesMeta: - supports-color: - optional: true - - decode-named-character-reference@1.3.0: - resolution: - { - integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==, - } - - defu@6.1.4: - resolution: - { - integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==, - } - - dequal@2.0.3: - resolution: - { - integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==, - } - engines: { node: ">=6" } - - destr@2.0.5: - resolution: - { - integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==, - } - - detect-libc@2.1.2: - resolution: - { - integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==, - } - engines: { node: ">=8" } - - deterministic-object-hash@2.0.2: - resolution: - { - integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==, - } - engines: { node: ">=18" } - - devalue@5.6.2: - resolution: - { - integrity: sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==, - } - - devlop@1.1.0: - resolution: - { - integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==, - } - - diff@8.0.3: - resolution: - { - integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==, - } - engines: { node: ">=0.3.1" } - - direction@2.0.1: - resolution: - { - integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==, - } - hasBin: true - - dlv@1.1.3: - resolution: - { - integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==, - } - - dom-serializer@2.0.0: - resolution: - { - integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==, - } - - domelementtype@2.3.0: - resolution: - { - integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==, - } - - domhandler@5.0.3: - resolution: - { - integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==, - } - engines: { node: ">= 4" } - - domutils@3.2.2: - resolution: - { - integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==, - } - - dset@3.1.4: - resolution: - { - integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==, - } - engines: { node: ">=4" } - - emoji-regex@10.6.0: - resolution: - { - integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==, - } - - emoji-regex@8.0.0: - resolution: - { - integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, - } - - entities@4.5.0: - resolution: - { - integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, - } - engines: { node: ">=0.12" } - - entities@6.0.1: - resolution: - { - integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==, - } - engines: { node: ">=0.12" } - - es-module-lexer@1.7.0: - resolution: - { - integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==, - } - - esast-util-from-estree@2.0.0: - resolution: - { - integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==, - } - - esast-util-from-js@2.0.1: - resolution: - { - integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==, - } - - esbuild@0.25.12: - resolution: - { - integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==, - } - engines: { node: ">=18" } - hasBin: true - - esbuild@0.27.3: - resolution: - { - integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==, - } - engines: { node: ">=18" } - hasBin: true - - escape-string-regexp@5.0.0: - resolution: - { - integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==, - } - engines: { node: ">=12" } - - estree-util-attach-comments@3.0.0: - resolution: - { - integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==, - } - - estree-util-build-jsx@3.0.1: - resolution: - { - integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==, - } - - estree-util-is-identifier-name@3.0.0: - resolution: - { - integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==, - } - - estree-util-scope@1.0.0: - resolution: - { - integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==, - } - - estree-util-to-js@2.0.0: - resolution: - { - integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==, - } - - estree-util-visit@2.0.0: - resolution: - { - integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==, - } - - estree-walker@2.0.2: - resolution: - { - integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==, - } - - estree-walker@3.0.3: - resolution: - { - integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, - } - - eventemitter3@5.0.4: - resolution: - { - integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==, - } - - expressive-code@0.41.6: - resolution: - { - integrity: sha512-W/5+IQbrpCIM5KGLjO35wlp1NCwDOOVQb+PAvzEoGkW1xjGM807ZGfBKptNWH6UECvt6qgmLyWolCMYKh7eQmA==, - } - - extend@3.0.2: - resolution: - { - integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==, - } - - fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } - - fast-uri@3.1.0: - resolution: - { - integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==, - } - - fdir@6.5.0: - resolution: - { - integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, - } - engines: { node: ">=12.0.0" } - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - flattie@1.1.1: - resolution: - { - integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==, - } - engines: { node: ">=8" } - - fontace@0.4.1: - resolution: - { - integrity: sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==, - } - - fontkitten@1.0.2: - resolution: - { - integrity: sha512-piJxbLnkD9Xcyi7dWJRnqszEURixe7CrF/efBfbffe2DPyabmuIuqraruY8cXTs19QoM8VJzx47BDRVNXETM7Q==, - } - engines: { node: ">=20" } - - fsevents@2.3.3: - resolution: - { - integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } - os: [darwin] - - get-east-asian-width@1.4.0: - resolution: - { - integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==, - } - engines: { node: ">=18" } - - github-slugger@2.0.0: - resolution: - { - integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==, - } - - h3@1.15.5: - resolution: - { - integrity: sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==, - } - - hast-util-embedded@3.0.0: - resolution: - { - integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==, - } - - hast-util-format@1.1.0: - resolution: - { - integrity: sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==, - } - - hast-util-from-html@2.0.3: - resolution: - { - integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==, - } - - hast-util-from-parse5@8.0.3: - resolution: - { - integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==, - } - - hast-util-has-property@3.0.0: - resolution: - { - integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==, - } - - hast-util-is-body-ok-link@3.0.1: - resolution: - { - integrity: sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==, - } - - hast-util-is-element@3.0.0: - resolution: - { - integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==, - } - - hast-util-minify-whitespace@1.0.1: - resolution: - { - integrity: sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==, - } - - hast-util-parse-selector@4.0.0: - resolution: - { - integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==, - } - - hast-util-phrasing@3.0.1: - resolution: - { - integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==, - } - - hast-util-raw@9.1.0: - resolution: - { - integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==, - } - - hast-util-select@6.0.4: - resolution: - { - integrity: sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==, - } - - hast-util-to-estree@3.1.3: - resolution: - { - integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==, - } - - hast-util-to-html@9.0.5: - resolution: - { - integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==, - } - - hast-util-to-jsx-runtime@2.3.6: - resolution: - { - integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==, - } - - hast-util-to-parse5@8.0.1: - resolution: - { - integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==, - } - - hast-util-to-string@3.0.1: - resolution: - { - integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==, - } - - hast-util-to-text@4.0.2: - resolution: - { - integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==, - } - - hast-util-whitespace@3.0.0: - resolution: - { - integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==, - } - - hastscript@9.0.1: - resolution: - { - integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==, - } - - html-escaper@3.0.3: - resolution: - { - integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==, - } - - html-void-elements@3.0.0: - resolution: - { - integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==, - } - - html-whitespace-sensitive-tag-names@3.0.1: - resolution: - { - integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==, - } - - http-cache-semantics@4.2.0: - resolution: - { - integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==, - } - - i18next@23.16.8: - resolution: - { - integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==, - } - - import-meta-resolve@4.2.0: - resolution: - { - integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==, - } - - inline-style-parser@0.2.7: - resolution: - { - integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==, - } - - iron-webcrypto@1.2.1: - resolution: - { - integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==, - } - - is-alphabetical@2.0.1: - resolution: - { - integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==, - } - - is-alphanumerical@2.0.1: - resolution: - { - integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==, - } - - is-decimal@2.0.1: - resolution: - { - integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==, - } - - is-docker@3.0.0: - resolution: - { - integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - hasBin: true - - is-fullwidth-code-point@3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: ">=8" } - - is-hexadecimal@2.0.1: - resolution: - { - integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==, - } - - is-inside-container@1.0.0: - resolution: - { - integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==, - } - engines: { node: ">=14.16" } - hasBin: true - - is-plain-obj@4.1.0: - resolution: - { - integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==, - } - engines: { node: ">=12" } - - is-wsl@3.1.1: - resolution: - { - integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==, - } - engines: { node: ">=16" } - - js-tokens@4.0.0: - resolution: - { - integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, - } - - js-yaml@4.1.1: - resolution: - { - integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==, - } - hasBin: true - - json-schema-traverse@1.0.0: - resolution: - { - integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, - } - - jsonpointer@5.0.1: - resolution: - { - integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==, - } - engines: { node: ">=0.10.0" } - - kleur@3.0.3: - resolution: - { - integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==, - } - engines: { node: ">=6" } - - klona@2.0.6: - resolution: - { - integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==, - } - engines: { node: ">= 8" } - - leven@3.1.0: - resolution: - { - integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==, - } - engines: { node: ">=6" } - - longest-streak@3.1.0: - resolution: - { - integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==, - } - - lru-cache@11.2.6: - resolution: - { - integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==, - } - engines: { node: 20 || >=22 } - - magic-string@0.30.21: - resolution: - { - integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, - } - - magicast@0.5.2: - resolution: - { - integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==, - } - - markdown-extensions@2.0.0: - resolution: - { - integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==, - } - engines: { node: ">=16" } - - markdown-table@3.0.4: - resolution: - { - integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==, - } - - mdast-util-definitions@6.0.0: - resolution: - { - integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==, - } - - mdast-util-directive@3.1.0: - resolution: - { - integrity: sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==, - } - - mdast-util-find-and-replace@3.0.2: - resolution: - { - integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==, - } - - mdast-util-from-markdown@2.0.2: - resolution: - { - integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==, - } - - mdast-util-gfm-autolink-literal@2.0.1: - resolution: - { - integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==, - } - - mdast-util-gfm-footnote@2.1.0: - resolution: - { - integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==, - } - - mdast-util-gfm-strikethrough@2.0.0: - resolution: - { - integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==, - } - - mdast-util-gfm-table@2.0.0: - resolution: - { - integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==, - } - - mdast-util-gfm-task-list-item@2.0.0: - resolution: - { - integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==, - } - - mdast-util-gfm@3.1.0: - resolution: - { - integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==, - } - - mdast-util-mdx-expression@2.0.1: - resolution: - { - integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==, - } - - mdast-util-mdx-jsx@3.2.0: - resolution: - { - integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==, - } - - mdast-util-mdx@3.0.0: - resolution: - { - integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==, - } - - mdast-util-mdxjs-esm@2.0.1: - resolution: - { - integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==, - } - - mdast-util-phrasing@4.1.0: - resolution: - { - integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==, - } - - mdast-util-to-hast@13.2.1: - resolution: - { - integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==, - } - - mdast-util-to-markdown@2.1.2: - resolution: - { - integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==, - } - - mdast-util-to-string@4.0.0: - resolution: - { - integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==, - } - - mdn-data@2.0.28: - resolution: - { - integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==, - } - - mdn-data@2.12.2: - resolution: - { - integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==, - } - - micromark-core-commonmark@2.0.3: - resolution: - { - integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==, - } - - micromark-extension-directive@3.0.2: - resolution: - { - integrity: sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==, - } - - micromark-extension-gfm-autolink-literal@2.1.0: - resolution: - { - integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==, - } - - micromark-extension-gfm-footnote@2.1.0: - resolution: - { - integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==, - } - - micromark-extension-gfm-strikethrough@2.1.0: - resolution: - { - integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==, - } - - micromark-extension-gfm-table@2.1.1: - resolution: - { - integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==, - } - - micromark-extension-gfm-tagfilter@2.0.0: - resolution: - { - integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==, - } - - micromark-extension-gfm-task-list-item@2.1.0: - resolution: - { - integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==, - } - - micromark-extension-gfm@3.0.0: - resolution: - { - integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==, - } - - micromark-extension-mdx-expression@3.0.1: - resolution: - { - integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==, - } - - micromark-extension-mdx-jsx@3.0.2: - resolution: - { - integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==, - } - - micromark-extension-mdx-md@2.0.0: - resolution: - { - integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==, - } - - micromark-extension-mdxjs-esm@3.0.0: - resolution: - { - integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==, - } - - micromark-extension-mdxjs@3.0.0: - resolution: - { - integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==, - } - - micromark-factory-destination@2.0.1: - resolution: - { - integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==, - } - - micromark-factory-label@2.0.1: - resolution: - { - integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==, - } - - micromark-factory-mdx-expression@2.0.3: - resolution: - { - integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==, - } - - micromark-factory-space@2.0.1: - resolution: - { - integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==, - } - - micromark-factory-title@2.0.1: - resolution: - { - integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==, - } - - micromark-factory-whitespace@2.0.1: - resolution: - { - integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==, - } - - micromark-util-character@2.1.1: - resolution: - { - integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==, - } - - micromark-util-chunked@2.0.1: - resolution: - { - integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==, - } - - micromark-util-classify-character@2.0.1: - resolution: - { - integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==, - } - - micromark-util-combine-extensions@2.0.1: - resolution: - { - integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==, - } - - micromark-util-decode-numeric-character-reference@2.0.2: - resolution: - { - integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==, - } - - micromark-util-decode-string@2.0.1: - resolution: - { - integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==, - } - - micromark-util-encode@2.0.1: - resolution: - { - integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==, - } - - micromark-util-events-to-acorn@2.0.3: - resolution: - { - integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==, - } - - micromark-util-html-tag-name@2.0.1: - resolution: - { - integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==, - } - - micromark-util-normalize-identifier@2.0.1: - resolution: - { - integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==, - } - - micromark-util-resolve-all@2.0.1: - resolution: - { - integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==, - } - - micromark-util-sanitize-uri@2.0.1: - resolution: - { - integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==, - } - - micromark-util-subtokenize@2.1.0: - resolution: - { - integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==, - } - - micromark-util-symbol@2.0.1: - resolution: - { - integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==, - } - - micromark-util-types@2.0.2: - resolution: - { - integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==, - } - - micromark@4.0.2: - resolution: - { - integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==, - } - - mrmime@2.0.1: - resolution: - { - integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==, - } - engines: { node: ">=10" } - - ms@2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } - - nanoid@3.3.11: - resolution: - { - integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==, - } - engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } - hasBin: true - - neotraverse@0.6.18: - resolution: - { - integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==, - } - engines: { node: ">= 10" } - - nlcst-to-string@4.0.0: - resolution: - { - integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==, - } - - node-fetch-native@1.6.7: - resolution: - { - integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==, - } - - node-mock-http@1.0.4: - resolution: - { - integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==, - } - - normalize-path@3.0.0: - resolution: - { - integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, - } - engines: { node: ">=0.10.0" } - - nth-check@2.1.1: - resolution: - { - integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==, - } - - ofetch@1.5.1: - resolution: - { - integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==, - } - - ohash@2.0.11: - resolution: - { - integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==, - } - - oniguruma-parser@0.12.1: - resolution: - { - integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==, - } - - oniguruma-to-es@4.3.4: - resolution: - { - integrity: sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==, - } - - openapi-types@12.1.3: - resolution: - { - integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==, - } - - p-limit@6.2.0: - resolution: - { - integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==, - } - engines: { node: ">=18" } - - p-queue@8.1.1: - resolution: - { - integrity: sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==, - } - engines: { node: ">=18" } - - p-timeout@6.1.4: - resolution: - { - integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==, - } - engines: { node: ">=14.16" } - - package-manager-detector@1.6.0: - resolution: - { - integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==, - } - - pagefind@1.4.0: - resolution: - { - integrity: sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==, - } - hasBin: true - - parse-entities@4.0.2: - resolution: - { - integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==, - } - - parse-latin@7.0.0: - resolution: - { - integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==, - } - - parse5@7.3.0: - resolution: - { - integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==, - } - - piccolore@0.1.3: - resolution: - { - integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==, - } - - picocolors@1.1.1: - resolution: - { - integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, - } - - picomatch@2.3.1: - resolution: - { - integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, - } - engines: { node: ">=8.6" } - - picomatch@4.0.3: - resolution: - { - integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==, - } - engines: { node: ">=12" } - - postcss-nested@6.2.0: - resolution: - { - integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==, - } - engines: { node: ">=12.0" } - peerDependencies: - postcss: ^8.2.14 - - postcss-selector-parser@6.1.2: - resolution: - { - integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==, - } - engines: { node: ">=4" } - - postcss@8.5.6: - resolution: - { - integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==, - } - engines: { node: ^10 || ^12 || >=14 } - - prismjs@1.30.0: - resolution: - { - integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==, - } - engines: { node: ">=6" } - - prompts@2.4.2: - resolution: - { - integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==, - } - engines: { node: ">= 6" } - - property-information@7.1.0: - resolution: - { - integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==, - } - - radix3@1.1.2: - resolution: - { - integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==, - } - - readdirp@5.0.0: - resolution: - { - integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==, - } - engines: { node: ">= 20.19.0" } - - recma-build-jsx@1.0.0: - resolution: - { - integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==, - } - - recma-jsx@1.0.1: - resolution: - { - integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==, - } - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - recma-parse@1.0.0: - resolution: - { - integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==, - } - - recma-stringify@1.0.0: - resolution: - { - integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==, - } - - regex-recursion@6.0.2: - resolution: - { - integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==, - } - - regex-utilities@2.3.0: - resolution: - { - integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==, - } - - regex@6.1.0: - resolution: - { - integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==, - } - - rehype-expressive-code@0.41.6: - resolution: - { - integrity: sha512-aBMX8kxPtjmDSFUdZlAWJkMvsQ4ZMASfee90JWIAV8tweltXLzkWC3q++43ToTelI8ac5iC0B3/S/Cl4Ql1y2g==, - } - - rehype-format@5.0.1: - resolution: - { - integrity: sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==, - } - - rehype-parse@9.0.1: - resolution: - { - integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==, - } - - rehype-raw@7.0.0: - resolution: - { - integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==, - } - - rehype-recma@1.0.0: - resolution: - { - integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==, - } - - rehype-stringify@10.0.1: - resolution: - { - integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==, - } - - rehype@13.0.2: - resolution: - { - integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==, - } - - remark-directive@3.0.1: - resolution: - { - integrity: sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==, - } - - remark-gfm@4.0.1: - resolution: - { - integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==, - } - - remark-mdx@3.1.1: - resolution: - { - integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==, - } - - remark-parse@11.0.0: - resolution: - { - integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==, - } - - remark-rehype@11.1.2: - resolution: - { - integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==, - } - - remark-smartypants@3.0.2: - resolution: - { - integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==, - } - engines: { node: ">=16.0.0" } - - remark-stringify@11.0.0: - resolution: - { - integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==, - } - - require-from-string@2.0.2: - resolution: - { - integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, - } - engines: { node: ">=0.10.0" } - - retext-latin@4.0.0: - resolution: - { - integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==, - } - - retext-smartypants@6.2.0: - resolution: - { - integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==, - } - - retext-stringify@4.0.0: - resolution: - { - integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==, - } - - retext@9.0.0: - resolution: - { - integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==, - } - - rollup@4.57.1: - resolution: - { - integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==, - } - engines: { node: ">=18.0.0", npm: ">=8.0.0" } - hasBin: true - - sax@1.4.4: - resolution: - { - integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==, - } - engines: { node: ">=11.0.0" } - - semver@7.7.4: - resolution: - { - integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==, - } - engines: { node: ">=10" } - hasBin: true - - sharp@0.34.5: - resolution: - { - integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - - shiki@3.22.0: - resolution: - { - integrity: sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g==, - } - - sisteransi@1.0.5: - resolution: - { - integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==, - } - - sitemap@8.0.2: - resolution: - { - integrity: sha512-LwktpJcyZDoa0IL6KT++lQ53pbSrx2c9ge41/SeLTyqy2XUNA6uR4+P9u5IVo5lPeL2arAcOKn1aZAxoYbCKlQ==, - } - engines: { node: ">=14.0.0", npm: ">=6.0.0" } - hasBin: true - - smol-toml@1.6.0: - resolution: - { - integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==, - } - engines: { node: ">= 18" } - - source-map-js@1.2.1: - resolution: - { - integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, - } - engines: { node: ">=0.10.0" } - - source-map@0.7.6: - resolution: - { - integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==, - } - engines: { node: ">= 12" } - - space-separated-tokens@2.0.2: - resolution: - { - integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==, - } - - starlight-openapi@0.22.0: - resolution: - { - integrity: sha512-4H/fywAoTcvKbcv+xBr9LdrjMc5geDOSnydvzpiOxjxkHvI6g+7uPhWNCejnJPyZUd/MC1MI23tvYug85d/WzA==, - } - engines: { node: ">=18.17.1" } - peerDependencies: - "@astrojs/markdown-remark": ">=6.0.1" - "@astrojs/starlight": ">=0.34.0" - astro: ">=5.5.0" - - stream-replace-string@2.0.0: - resolution: - { - integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==, - } - - string-width@4.2.3: - resolution: - { - integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, - } - engines: { node: ">=8" } - - string-width@7.2.0: - resolution: - { - integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==, - } - engines: { node: ">=18" } - - stringify-entities@4.0.4: - resolution: - { - integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==, - } - - strip-ansi@6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, - } - engines: { node: ">=8" } - - strip-ansi@7.1.2: - resolution: - { - integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==, - } - engines: { node: ">=12" } - - style-to-js@1.1.21: - resolution: - { - integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==, - } - - style-to-object@1.0.14: - resolution: - { - integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==, - } - - svgo@4.0.0: - resolution: - { - integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==, - } - engines: { node: ">=16" } - hasBin: true - - tiny-inflate@1.0.3: - resolution: - { - integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==, - } - - tinyexec@1.0.2: - resolution: - { - integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==, - } - engines: { node: ">=18" } - - tinyglobby@0.2.15: - resolution: - { - integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==, - } - engines: { node: ">=12.0.0" } - - trim-lines@3.0.1: - resolution: - { - integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==, - } - - trough@2.2.0: - resolution: - { - integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==, - } - - tsconfck@3.1.6: - resolution: - { - integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==, - } - engines: { node: ^18 || >=20 } - hasBin: true - peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true - - tslib@2.8.1: - resolution: - { - integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, - } - - type-fest@4.41.0: - resolution: - { - integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==, - } - engines: { node: ">=16" } - - typescript@5.9.3: - resolution: - { - integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, - } - engines: { node: ">=14.17" } - hasBin: true - - ufo@1.6.3: - resolution: - { - integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==, - } - - ultrahtml@1.6.0: - resolution: - { - integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==, - } - - uncrypto@0.1.3: - resolution: - { - integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==, - } - - unified@11.0.5: - resolution: - { - integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==, - } - - unifont@0.7.4: - resolution: - { - integrity: sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==, - } - - unist-util-find-after@5.0.0: - resolution: - { - integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==, - } - - unist-util-is@6.0.1: - resolution: - { - integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==, - } - - unist-util-modify-children@4.0.0: - resolution: - { - integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==, - } - - unist-util-position-from-estree@2.0.0: - resolution: - { - integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==, - } - - unist-util-position@5.0.0: - resolution: - { - integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==, - } - - unist-util-remove-position@5.0.0: - resolution: - { - integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==, - } - - unist-util-stringify-position@4.0.0: - resolution: - { - integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==, - } - - unist-util-visit-children@3.0.0: - resolution: - { - integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==, - } - - unist-util-visit-parents@6.0.2: - resolution: - { - integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==, - } - - unist-util-visit@5.1.0: - resolution: - { - integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==, - } - - unstorage@1.17.4: - resolution: - { - integrity: sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==, - } - peerDependencies: - "@azure/app-configuration": ^1.8.0 - "@azure/cosmos": ^4.2.0 - "@azure/data-tables": ^13.3.0 - "@azure/identity": ^4.6.0 - "@azure/keyvault-secrets": ^4.9.0 - "@azure/storage-blob": ^12.26.0 - "@capacitor/preferences": ^6 || ^7 || ^8 - "@deno/kv": ">=0.9.0" - "@netlify/blobs": ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 - "@planetscale/database": ^1.19.0 - "@upstash/redis": ^1.34.3 - "@vercel/blob": ">=0.27.1" - "@vercel/functions": ^2.2.12 || ^3.0.0 - "@vercel/kv": ^1 || ^2 || ^3 - aws4fetch: ^1.0.20 - db0: ">=0.2.1" - idb-keyval: ^6.2.1 - ioredis: ^5.4.2 - uploadthing: ^7.4.4 - peerDependenciesMeta: - "@azure/app-configuration": - optional: true - "@azure/cosmos": - optional: true - "@azure/data-tables": - optional: true - "@azure/identity": - optional: true - "@azure/keyvault-secrets": - optional: true - "@azure/storage-blob": - optional: true - "@capacitor/preferences": - optional: true - "@deno/kv": - optional: true - "@netlify/blobs": - optional: true - "@planetscale/database": - optional: true - "@upstash/redis": - optional: true - "@vercel/blob": - optional: true - "@vercel/functions": - optional: true - "@vercel/kv": - optional: true - aws4fetch: - optional: true - db0: - optional: true - idb-keyval: - optional: true - ioredis: - optional: true - uploadthing: - optional: true - - url-template@3.1.1: - resolution: - { - integrity: sha512-4oszoaEKE/mQOtAmdMWqIRHmkxWkUZMnXFnjQ5i01CuRSK3uluxcH1MRVVVWmhlnzT1SCDfKxxficm2G37qzCA==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - - util-deprecate@1.0.2: - resolution: - { - integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, - } - - vfile-location@5.0.3: - resolution: - { - integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==, - } - - vfile-message@4.0.3: - resolution: - { - integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==, - } - - vfile@6.0.3: - resolution: - { - integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==, - } - - vite@6.4.1: - resolution: - { - integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==, - } - engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } - hasBin: true - peerDependencies: - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: ">=1.21.0" - less: "*" - lightningcss: ^1.21.0 - sass: "*" - sass-embedded: "*" - stylus: "*" - sugarss: "*" - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - "@types/node": - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vitefu@1.1.1: - resolution: - { - integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==, - } - peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 - peerDependenciesMeta: - vite: - optional: true - - web-namespaces@2.0.1: - resolution: - { - integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==, - } - - which-pm-runs@1.1.0: - resolution: - { - integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==, - } - engines: { node: ">=4" } - - widest-line@5.0.0: - resolution: - { - integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==, - } - engines: { node: ">=18" } - - wrap-ansi@9.0.2: - resolution: - { - integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==, - } - engines: { node: ">=18" } - - xxhash-wasm@1.1.0: - resolution: - { - integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==, - } - - yargs-parser@21.1.1: - resolution: - { - integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, - } - engines: { node: ">=12" } - - yocto-queue@1.2.2: - resolution: - { - integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==, - } - engines: { node: ">=12.20" } - - yocto-spinner@0.2.3: - resolution: - { - integrity: sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==, - } - engines: { node: ">=18.19" } - - yoctocolors@2.1.2: - resolution: - { - integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==, - } - engines: { node: ">=18" } - - zod-to-json-schema@3.25.1: - resolution: - { - integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==, - } - peerDependencies: - zod: ^3.25 || ^4 - - zod-to-ts@1.2.0: - resolution: - { - integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==, - } - peerDependencies: - typescript: ^4.9.4 || ^5.0.2 - zod: ^3 - - zod@3.25.76: - resolution: - { - integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==, - } - - zwitch@2.0.4: - resolution: - { - integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==, - } - -snapshots: - "@apidevtools/json-schema-ref-parser@13.0.5": - dependencies: - "@types/json-schema": 7.0.15 - js-yaml: 4.1.1 - - "@astrojs/compiler@2.13.1": {} - - "@astrojs/internal-helpers@0.7.5": {} - - "@astrojs/markdown-remark@6.3.10": - dependencies: - "@astrojs/internal-helpers": 0.7.5 - "@astrojs/prism": 3.3.0 - github-slugger: 2.0.0 - hast-util-from-html: 2.0.3 - hast-util-to-text: 4.0.2 - import-meta-resolve: 4.2.0 - js-yaml: 4.1.1 - mdast-util-definitions: 6.0.0 - rehype-raw: 7.0.0 - rehype-stringify: 10.0.1 - remark-gfm: 4.0.1 - remark-parse: 11.0.0 - remark-rehype: 11.1.2 - remark-smartypants: 3.0.2 - shiki: 3.22.0 - smol-toml: 1.6.0 - unified: 11.0.5 - unist-util-remove-position: 5.0.0 - unist-util-visit: 5.1.0 - unist-util-visit-parents: 6.0.2 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - - "@astrojs/mdx@4.3.13(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3))": - dependencies: - "@astrojs/markdown-remark": 6.3.10 - "@mdx-js/mdx": 3.1.1 - acorn: 8.15.0 - astro: 5.17.2(rollup@4.57.1)(typescript@5.9.3) - es-module-lexer: 1.7.0 - estree-util-visit: 2.0.0 - hast-util-to-html: 9.0.5 - piccolore: 0.1.3 - rehype-raw: 7.0.0 - remark-gfm: 4.0.1 - remark-smartypants: 3.0.2 - source-map: 0.7.6 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - - "@astrojs/prism@3.3.0": - dependencies: - prismjs: 1.30.0 - - "@astrojs/sitemap@3.7.0": - dependencies: - sitemap: 8.0.2 - stream-replace-string: 2.0.0 - zod: 3.25.76 - - "@astrojs/starlight@0.37.6(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3))": - dependencies: - "@astrojs/markdown-remark": 6.3.10 - "@astrojs/mdx": 4.3.13(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3)) - "@astrojs/sitemap": 3.7.0 - "@pagefind/default-ui": 1.4.0 - "@types/hast": 3.0.4 - "@types/js-yaml": 4.0.9 - "@types/mdast": 4.0.4 - astro: 5.17.2(rollup@4.57.1)(typescript@5.9.3) - astro-expressive-code: 0.41.6(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3)) - bcp-47: 2.1.0 - hast-util-from-html: 2.0.3 - hast-util-select: 6.0.4 - hast-util-to-string: 3.0.1 - hastscript: 9.0.1 - i18next: 23.16.8 - js-yaml: 4.1.1 - klona: 2.0.6 - magic-string: 0.30.21 - mdast-util-directive: 3.1.0 - mdast-util-to-markdown: 2.1.2 - mdast-util-to-string: 4.0.0 - pagefind: 1.4.0 - rehype: 13.0.2 - rehype-format: 5.0.1 - remark-directive: 3.0.1 - ultrahtml: 1.6.0 - unified: 11.0.5 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - - "@astrojs/telemetry@3.3.0": - dependencies: - ci-info: 4.4.0 - debug: 4.4.3 - dlv: 1.1.3 - dset: 3.1.4 - is-docker: 3.0.0 - is-wsl: 3.1.1 - which-pm-runs: 1.1.0 - transitivePeerDependencies: - - supports-color - - "@babel/code-frame@7.29.0": - dependencies: - "@babel/helper-validator-identifier": 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - "@babel/helper-string-parser@7.27.1": {} - - "@babel/helper-validator-identifier@7.28.5": {} - - "@babel/parser@7.29.0": - dependencies: - "@babel/types": 7.29.0 - - "@babel/runtime@7.28.6": {} - - "@babel/types@7.29.0": - dependencies: - "@babel/helper-string-parser": 7.27.1 - "@babel/helper-validator-identifier": 7.28.5 - - "@capsizecss/unpack@4.0.0": - dependencies: - fontkitten: 1.0.2 - - "@ctrl/tinycolor@4.2.0": {} - - "@emnapi/runtime@1.8.1": - dependencies: - tslib: 2.8.1 - optional: true - - "@esbuild/aix-ppc64@0.25.12": - optional: true - - "@esbuild/aix-ppc64@0.27.3": - optional: true - - "@esbuild/android-arm64@0.25.12": - optional: true - - "@esbuild/android-arm64@0.27.3": - optional: true - - "@esbuild/android-arm@0.25.12": - optional: true - - "@esbuild/android-arm@0.27.3": - optional: true - - "@esbuild/android-x64@0.25.12": - optional: true - - "@esbuild/android-x64@0.27.3": - optional: true - - "@esbuild/darwin-arm64@0.25.12": - optional: true - - "@esbuild/darwin-arm64@0.27.3": - optional: true - - "@esbuild/darwin-x64@0.25.12": - optional: true - - "@esbuild/darwin-x64@0.27.3": - optional: true - - "@esbuild/freebsd-arm64@0.25.12": - optional: true - - "@esbuild/freebsd-arm64@0.27.3": - optional: true - - "@esbuild/freebsd-x64@0.25.12": - optional: true - - "@esbuild/freebsd-x64@0.27.3": - optional: true - - "@esbuild/linux-arm64@0.25.12": - optional: true - - "@esbuild/linux-arm64@0.27.3": - optional: true - - "@esbuild/linux-arm@0.25.12": - optional: true - - "@esbuild/linux-arm@0.27.3": - optional: true - - "@esbuild/linux-ia32@0.25.12": - optional: true - - "@esbuild/linux-ia32@0.27.3": - optional: true - - "@esbuild/linux-loong64@0.25.12": - optional: true - - "@esbuild/linux-loong64@0.27.3": - optional: true - - "@esbuild/linux-mips64el@0.25.12": - optional: true - - "@esbuild/linux-mips64el@0.27.3": - optional: true - - "@esbuild/linux-ppc64@0.25.12": - optional: true - - "@esbuild/linux-ppc64@0.27.3": - optional: true - - "@esbuild/linux-riscv64@0.25.12": - optional: true - - "@esbuild/linux-riscv64@0.27.3": - optional: true - - "@esbuild/linux-s390x@0.25.12": - optional: true - - "@esbuild/linux-s390x@0.27.3": - optional: true - - "@esbuild/linux-x64@0.25.12": - optional: true - - "@esbuild/linux-x64@0.27.3": - optional: true - - "@esbuild/netbsd-arm64@0.25.12": - optional: true - - "@esbuild/netbsd-arm64@0.27.3": - optional: true - - "@esbuild/netbsd-x64@0.25.12": - optional: true - - "@esbuild/netbsd-x64@0.27.3": - optional: true - - "@esbuild/openbsd-arm64@0.25.12": - optional: true - - "@esbuild/openbsd-arm64@0.27.3": - optional: true - - "@esbuild/openbsd-x64@0.25.12": - optional: true - - "@esbuild/openbsd-x64@0.27.3": - optional: true - - "@esbuild/openharmony-arm64@0.25.12": - optional: true - - "@esbuild/openharmony-arm64@0.27.3": - optional: true - - "@esbuild/sunos-x64@0.25.12": - optional: true - - "@esbuild/sunos-x64@0.27.3": - optional: true - - "@esbuild/win32-arm64@0.25.12": - optional: true - - "@esbuild/win32-arm64@0.27.3": - optional: true - - "@esbuild/win32-ia32@0.25.12": - optional: true - - "@esbuild/win32-ia32@0.27.3": - optional: true - - "@esbuild/win32-x64@0.25.12": - optional: true - - "@esbuild/win32-x64@0.27.3": - optional: true - - "@expressive-code/core@0.41.6": - dependencies: - "@ctrl/tinycolor": 4.2.0 - hast-util-select: 6.0.4 - hast-util-to-html: 9.0.5 - hast-util-to-text: 4.0.2 - hastscript: 9.0.1 - postcss: 8.5.6 - postcss-nested: 6.2.0(postcss@8.5.6) - unist-util-visit: 5.1.0 - unist-util-visit-parents: 6.0.2 - - "@expressive-code/plugin-frames@0.41.6": - dependencies: - "@expressive-code/core": 0.41.6 - - "@expressive-code/plugin-shiki@0.41.6": - dependencies: - "@expressive-code/core": 0.41.6 - shiki: 3.22.0 - - "@expressive-code/plugin-text-markers@0.41.6": - dependencies: - "@expressive-code/core": 0.41.6 - - "@fontsource/inter@5.2.8": {} - - "@fontsource/rubik@5.2.8": {} - - "@humanwhocodes/momoa@2.0.4": {} - - "@img/colour@1.0.0": {} - - "@img/sharp-darwin-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-darwin-arm64": 1.2.4 - optional: true - - "@img/sharp-darwin-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-darwin-x64": 1.2.4 - optional: true - - "@img/sharp-libvips-darwin-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-darwin-x64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-arm@1.2.4": - optional: true - - "@img/sharp-libvips-linux-ppc64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-riscv64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-s390x@1.2.4": - optional: true - - "@img/sharp-libvips-linux-x64@1.2.4": - optional: true - - "@img/sharp-libvips-linuxmusl-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-linuxmusl-x64@1.2.4": - optional: true - - "@img/sharp-linux-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-arm64": 1.2.4 - optional: true - - "@img/sharp-linux-arm@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-arm": 1.2.4 - optional: true - - "@img/sharp-linux-ppc64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-ppc64": 1.2.4 - optional: true - - "@img/sharp-linux-riscv64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-riscv64": 1.2.4 - optional: true - - "@img/sharp-linux-s390x@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-s390x": 1.2.4 - optional: true - - "@img/sharp-linux-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-x64": 1.2.4 - optional: true - - "@img/sharp-linuxmusl-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linuxmusl-arm64": 1.2.4 - optional: true - - "@img/sharp-linuxmusl-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linuxmusl-x64": 1.2.4 - optional: true - - "@img/sharp-wasm32@0.34.5": - dependencies: - "@emnapi/runtime": 1.8.1 - optional: true - - "@img/sharp-win32-arm64@0.34.5": - optional: true - - "@img/sharp-win32-ia32@0.34.5": - optional: true - - "@img/sharp-win32-x64@0.34.5": - optional: true - - "@jridgewell/sourcemap-codec@1.5.5": {} - - "@mdx-js/mdx@3.1.1": - dependencies: - "@types/estree": 1.0.8 - "@types/estree-jsx": 1.0.5 - "@types/hast": 3.0.4 - "@types/mdx": 2.0.13 - acorn: 8.15.0 - collapse-white-space: 2.1.0 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - estree-util-scope: 1.0.0 - estree-walker: 3.0.3 - hast-util-to-jsx-runtime: 2.3.6 - markdown-extensions: 2.0.0 - recma-build-jsx: 1.0.0 - recma-jsx: 1.0.1(acorn@8.15.0) - recma-stringify: 1.0.0 - rehype-recma: 1.0.0 - remark-mdx: 3.1.1 - remark-parse: 11.0.0 - remark-rehype: 11.1.2 - source-map: 0.7.6 - unified: 11.0.5 - unist-util-position-from-estree: 2.0.0 - unist-util-stringify-position: 4.0.0 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - - "@oslojs/encoding@1.1.0": {} - - "@pagefind/darwin-arm64@1.4.0": - optional: true - - "@pagefind/darwin-x64@1.4.0": - optional: true - - "@pagefind/default-ui@1.4.0": {} - - "@pagefind/freebsd-x64@1.4.0": - optional: true - - "@pagefind/linux-arm64@1.4.0": - optional: true - - "@pagefind/linux-x64@1.4.0": - optional: true - - "@pagefind/windows-x64@1.4.0": - optional: true - - "@readme/better-ajv-errors@2.4.0(ajv@8.18.0)": - dependencies: - "@babel/code-frame": 7.29.0 - "@babel/runtime": 7.28.6 - "@humanwhocodes/momoa": 2.0.4 - ajv: 8.18.0 - jsonpointer: 5.0.1 - leven: 3.1.0 - picocolors: 1.1.1 - - "@readme/openapi-parser@4.1.2(openapi-types@12.1.3)": - dependencies: - "@apidevtools/json-schema-ref-parser": 13.0.5 - "@readme/better-ajv-errors": 2.4.0(ajv@8.18.0) - "@readme/openapi-schemas": 3.1.0 - "@types/json-schema": 7.0.15 - ajv: 8.18.0 - ajv-draft-04: 1.0.0(ajv@8.18.0) - openapi-types: 12.1.3 - - "@readme/openapi-schemas@3.1.0": {} - - "@rollup/pluginutils@5.3.0(rollup@4.57.1)": - dependencies: - "@types/estree": 1.0.8 - estree-walker: 2.0.2 - picomatch: 4.0.3 - optionalDependencies: - rollup: 4.57.1 - - "@rollup/rollup-android-arm-eabi@4.57.1": - optional: true - - "@rollup/rollup-android-arm64@4.57.1": - optional: true - - "@rollup/rollup-darwin-arm64@4.57.1": - optional: true - - "@rollup/rollup-darwin-x64@4.57.1": - optional: true - - "@rollup/rollup-freebsd-arm64@4.57.1": - optional: true - - "@rollup/rollup-freebsd-x64@4.57.1": - optional: true - - "@rollup/rollup-linux-arm-gnueabihf@4.57.1": - optional: true - - "@rollup/rollup-linux-arm-musleabihf@4.57.1": - optional: true - - "@rollup/rollup-linux-arm64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-arm64-musl@4.57.1": - optional: true - - "@rollup/rollup-linux-loong64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-loong64-musl@4.57.1": - optional: true - - "@rollup/rollup-linux-ppc64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-ppc64-musl@4.57.1": - optional: true - - "@rollup/rollup-linux-riscv64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-riscv64-musl@4.57.1": - optional: true - - "@rollup/rollup-linux-s390x-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-x64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-x64-musl@4.57.1": - optional: true - - "@rollup/rollup-openbsd-x64@4.57.1": - optional: true - - "@rollup/rollup-openharmony-arm64@4.57.1": - optional: true - - "@rollup/rollup-win32-arm64-msvc@4.57.1": - optional: true - - "@rollup/rollup-win32-ia32-msvc@4.57.1": - optional: true - - "@rollup/rollup-win32-x64-gnu@4.57.1": - optional: true - - "@rollup/rollup-win32-x64-msvc@4.57.1": - optional: true - - "@shikijs/core@3.22.0": - dependencies: - "@shikijs/types": 3.22.0 - "@shikijs/vscode-textmate": 10.0.2 - "@types/hast": 3.0.4 - hast-util-to-html: 9.0.5 - - "@shikijs/engine-javascript@3.22.0": - dependencies: - "@shikijs/types": 3.22.0 - "@shikijs/vscode-textmate": 10.0.2 - oniguruma-to-es: 4.3.4 - - "@shikijs/engine-oniguruma@3.22.0": - dependencies: - "@shikijs/types": 3.22.0 - "@shikijs/vscode-textmate": 10.0.2 - - "@shikijs/langs@3.22.0": - dependencies: - "@shikijs/types": 3.22.0 - - "@shikijs/themes@3.22.0": - dependencies: - "@shikijs/types": 3.22.0 - - "@shikijs/types@3.22.0": - dependencies: - "@shikijs/vscode-textmate": 10.0.2 - "@types/hast": 3.0.4 - - "@shikijs/vscode-textmate@10.0.2": {} - - "@types/debug@4.1.12": - dependencies: - "@types/ms": 2.1.0 - - "@types/estree-jsx@1.0.5": - dependencies: - "@types/estree": 1.0.8 - - "@types/estree@1.0.8": {} - - "@types/hast@3.0.4": - dependencies: - "@types/unist": 3.0.3 - - "@types/js-yaml@4.0.9": {} - - "@types/json-schema@7.0.15": {} - - "@types/mdast@4.0.4": - dependencies: - "@types/unist": 3.0.3 - - "@types/mdx@2.0.13": {} - - "@types/ms@2.1.0": {} - - "@types/nlcst@2.0.3": - dependencies: - "@types/unist": 3.0.3 - - "@types/node@17.0.45": {} - - "@types/sax@1.2.7": - dependencies: - "@types/node": 17.0.45 - - "@types/unist@2.0.11": {} - - "@types/unist@3.0.3": {} - - "@ungap/structured-clone@1.3.0": {} - - acorn-jsx@5.3.2(acorn@8.15.0): - dependencies: - acorn: 8.15.0 - - acorn@8.15.0: {} - - ajv-draft-04@1.0.0(ajv@8.18.0): - optionalDependencies: - ajv: 8.18.0 - - ajv@8.18.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - ansi-align@3.0.1: - dependencies: - string-width: 4.2.3 - - ansi-regex@5.0.1: {} - - ansi-regex@6.2.2: {} - - ansi-styles@6.2.3: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - arg@5.0.2: {} - - argparse@2.0.1: {} - - aria-query@5.3.2: {} - - array-iterate@2.0.1: {} - - astring@1.9.0: {} - - astro-expressive-code@0.41.6(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3)): - dependencies: - astro: 5.17.2(rollup@4.57.1)(typescript@5.9.3) - rehype-expressive-code: 0.41.6 - - astro@5.17.2(rollup@4.57.1)(typescript@5.9.3): - dependencies: - "@astrojs/compiler": 2.13.1 - "@astrojs/internal-helpers": 0.7.5 - "@astrojs/markdown-remark": 6.3.10 - "@astrojs/telemetry": 3.3.0 - "@capsizecss/unpack": 4.0.0 - "@oslojs/encoding": 1.1.0 - "@rollup/pluginutils": 5.3.0(rollup@4.57.1) - acorn: 8.15.0 - aria-query: 5.3.2 - axobject-query: 4.1.0 - boxen: 8.0.1 - ci-info: 4.4.0 - clsx: 2.1.1 - common-ancestor-path: 1.0.1 - cookie: 1.1.1 - cssesc: 3.0.0 - debug: 4.4.3 - deterministic-object-hash: 2.0.2 - devalue: 5.6.2 - diff: 8.0.3 - dlv: 1.1.3 - dset: 3.1.4 - es-module-lexer: 1.7.0 - esbuild: 0.27.3 - estree-walker: 3.0.3 - flattie: 1.1.1 - fontace: 0.4.1 - github-slugger: 2.0.0 - html-escaper: 3.0.3 - http-cache-semantics: 4.2.0 - import-meta-resolve: 4.2.0 - js-yaml: 4.1.1 - magic-string: 0.30.21 - magicast: 0.5.2 - mrmime: 2.0.1 - neotraverse: 0.6.18 - p-limit: 6.2.0 - p-queue: 8.1.1 - package-manager-detector: 1.6.0 - piccolore: 0.1.3 - picomatch: 4.0.3 - prompts: 2.4.2 - rehype: 13.0.2 - semver: 7.7.4 - shiki: 3.22.0 - smol-toml: 1.6.0 - svgo: 4.0.0 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tsconfck: 3.1.6(typescript@5.9.3) - ultrahtml: 1.6.0 - unifont: 0.7.4 - unist-util-visit: 5.1.0 - unstorage: 1.17.4 - vfile: 6.0.3 - vite: 6.4.1 - vitefu: 1.1.1(vite@6.4.1) - xxhash-wasm: 1.1.0 - yargs-parser: 21.1.1 - yocto-spinner: 0.2.3 - zod: 3.25.76 - zod-to-json-schema: 3.25.1(zod@3.25.76) - zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76) - optionalDependencies: - sharp: 0.34.5 - transitivePeerDependencies: - - "@azure/app-configuration" - - "@azure/cosmos" - - "@azure/data-tables" - - "@azure/identity" - - "@azure/keyvault-secrets" - - "@azure/storage-blob" - - "@capacitor/preferences" - - "@deno/kv" - - "@netlify/blobs" - - "@planetscale/database" - - "@types/node" - - "@upstash/redis" - - "@vercel/blob" - - "@vercel/functions" - - "@vercel/kv" - - aws4fetch - - db0 - - idb-keyval - - ioredis - - jiti - - less - - lightningcss - - rollup - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - typescript - - uploadthing - - yaml - - axobject-query@4.1.0: {} - - bail@2.0.2: {} - - base-64@1.0.0: {} - - bcp-47-match@2.0.3: {} - - bcp-47@2.1.0: - dependencies: - is-alphabetical: 2.0.1 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - - boolbase@1.0.0: {} - - boxen@8.0.1: - dependencies: - ansi-align: 3.0.1 - camelcase: 8.0.0 - chalk: 5.6.2 - cli-boxes: 3.0.0 - string-width: 7.2.0 - type-fest: 4.41.0 - widest-line: 5.0.0 - wrap-ansi: 9.0.2 - - camelcase@8.0.0: {} - - ccount@2.0.1: {} - - chalk@5.6.2: {} - - character-entities-html4@2.1.0: {} - - character-entities-legacy@3.0.0: {} - - character-entities@2.0.2: {} - - character-reference-invalid@2.0.1: {} - - chokidar@5.0.0: - dependencies: - readdirp: 5.0.0 - - ci-info@4.4.0: {} - - cli-boxes@3.0.0: {} - - clsx@2.1.1: {} - - collapse-white-space@2.1.0: {} - - comma-separated-tokens@2.0.3: {} - - commander@11.1.0: {} - - common-ancestor-path@1.0.1: {} - - cookie-es@1.2.2: {} - - cookie@1.1.1: {} - - crossws@0.3.5: - dependencies: - uncrypto: 0.1.3 - - css-select@5.2.2: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 - - css-selector-parser@3.3.0: {} - - css-tree@2.2.1: - dependencies: - mdn-data: 2.0.28 - source-map-js: 1.2.1 - - css-tree@3.1.0: - dependencies: - mdn-data: 2.12.2 - source-map-js: 1.2.1 - - css-what@6.2.2: {} - - cssesc@3.0.0: {} - - csso@5.0.5: - dependencies: - css-tree: 2.2.1 - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - decode-named-character-reference@1.3.0: - dependencies: - character-entities: 2.0.2 - - defu@6.1.4: {} - - dequal@2.0.3: {} - - destr@2.0.5: {} - - detect-libc@2.1.2: {} - - deterministic-object-hash@2.0.2: - dependencies: - base-64: 1.0.0 - - devalue@5.6.2: {} - - devlop@1.1.0: - dependencies: - dequal: 2.0.3 - - diff@8.0.3: {} - - direction@2.0.1: {} - - dlv@1.1.3: {} - - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - - domelementtype@2.3.0: {} - - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - - dset@3.1.4: {} - - emoji-regex@10.6.0: {} - - emoji-regex@8.0.0: {} - - entities@4.5.0: {} - - entities@6.0.1: {} - - es-module-lexer@1.7.0: {} - - esast-util-from-estree@2.0.0: - dependencies: - "@types/estree-jsx": 1.0.5 - devlop: 1.1.0 - estree-util-visit: 2.0.0 - unist-util-position-from-estree: 2.0.0 - - esast-util-from-js@2.0.1: - dependencies: - "@types/estree-jsx": 1.0.5 - acorn: 8.15.0 - esast-util-from-estree: 2.0.0 - vfile-message: 4.0.3 - - esbuild@0.25.12: - optionalDependencies: - "@esbuild/aix-ppc64": 0.25.12 - "@esbuild/android-arm": 0.25.12 - "@esbuild/android-arm64": 0.25.12 - "@esbuild/android-x64": 0.25.12 - "@esbuild/darwin-arm64": 0.25.12 - "@esbuild/darwin-x64": 0.25.12 - "@esbuild/freebsd-arm64": 0.25.12 - "@esbuild/freebsd-x64": 0.25.12 - "@esbuild/linux-arm": 0.25.12 - "@esbuild/linux-arm64": 0.25.12 - "@esbuild/linux-ia32": 0.25.12 - "@esbuild/linux-loong64": 0.25.12 - "@esbuild/linux-mips64el": 0.25.12 - "@esbuild/linux-ppc64": 0.25.12 - "@esbuild/linux-riscv64": 0.25.12 - "@esbuild/linux-s390x": 0.25.12 - "@esbuild/linux-x64": 0.25.12 - "@esbuild/netbsd-arm64": 0.25.12 - "@esbuild/netbsd-x64": 0.25.12 - "@esbuild/openbsd-arm64": 0.25.12 - "@esbuild/openbsd-x64": 0.25.12 - "@esbuild/openharmony-arm64": 0.25.12 - "@esbuild/sunos-x64": 0.25.12 - "@esbuild/win32-arm64": 0.25.12 - "@esbuild/win32-ia32": 0.25.12 - "@esbuild/win32-x64": 0.25.12 - - esbuild@0.27.3: - optionalDependencies: - "@esbuild/aix-ppc64": 0.27.3 - "@esbuild/android-arm": 0.27.3 - "@esbuild/android-arm64": 0.27.3 - "@esbuild/android-x64": 0.27.3 - "@esbuild/darwin-arm64": 0.27.3 - "@esbuild/darwin-x64": 0.27.3 - "@esbuild/freebsd-arm64": 0.27.3 - "@esbuild/freebsd-x64": 0.27.3 - "@esbuild/linux-arm": 0.27.3 - "@esbuild/linux-arm64": 0.27.3 - "@esbuild/linux-ia32": 0.27.3 - "@esbuild/linux-loong64": 0.27.3 - "@esbuild/linux-mips64el": 0.27.3 - "@esbuild/linux-ppc64": 0.27.3 - "@esbuild/linux-riscv64": 0.27.3 - "@esbuild/linux-s390x": 0.27.3 - "@esbuild/linux-x64": 0.27.3 - "@esbuild/netbsd-arm64": 0.27.3 - "@esbuild/netbsd-x64": 0.27.3 - "@esbuild/openbsd-arm64": 0.27.3 - "@esbuild/openbsd-x64": 0.27.3 - "@esbuild/openharmony-arm64": 0.27.3 - "@esbuild/sunos-x64": 0.27.3 - "@esbuild/win32-arm64": 0.27.3 - "@esbuild/win32-ia32": 0.27.3 - "@esbuild/win32-x64": 0.27.3 - - escape-string-regexp@5.0.0: {} - - estree-util-attach-comments@3.0.0: - dependencies: - "@types/estree": 1.0.8 - - estree-util-build-jsx@3.0.1: - dependencies: - "@types/estree-jsx": 1.0.5 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - estree-walker: 3.0.3 - - estree-util-is-identifier-name@3.0.0: {} - - estree-util-scope@1.0.0: - dependencies: - "@types/estree": 1.0.8 - devlop: 1.1.0 - - estree-util-to-js@2.0.0: - dependencies: - "@types/estree-jsx": 1.0.5 - astring: 1.9.0 - source-map: 0.7.6 - - estree-util-visit@2.0.0: - dependencies: - "@types/estree-jsx": 1.0.5 - "@types/unist": 3.0.3 - - estree-walker@2.0.2: {} - - estree-walker@3.0.3: - dependencies: - "@types/estree": 1.0.8 - - eventemitter3@5.0.4: {} - - expressive-code@0.41.6: - dependencies: - "@expressive-code/core": 0.41.6 - "@expressive-code/plugin-frames": 0.41.6 - "@expressive-code/plugin-shiki": 0.41.6 - "@expressive-code/plugin-text-markers": 0.41.6 - - extend@3.0.2: {} - - fast-deep-equal@3.1.3: {} - - fast-uri@3.1.0: {} - - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - - flattie@1.1.1: {} - - fontace@0.4.1: - dependencies: - fontkitten: 1.0.2 - - fontkitten@1.0.2: - dependencies: - tiny-inflate: 1.0.3 - - fsevents@2.3.3: - optional: true - - get-east-asian-width@1.4.0: {} - - github-slugger@2.0.0: {} - - h3@1.15.5: - dependencies: - cookie-es: 1.2.2 - crossws: 0.3.5 - defu: 6.1.4 - destr: 2.0.5 - iron-webcrypto: 1.2.1 - node-mock-http: 1.0.4 - radix3: 1.1.2 - ufo: 1.6.3 - uncrypto: 0.1.3 - - hast-util-embedded@3.0.0: - dependencies: - "@types/hast": 3.0.4 - hast-util-is-element: 3.0.0 - - hast-util-format@1.1.0: - dependencies: - "@types/hast": 3.0.4 - hast-util-embedded: 3.0.0 - hast-util-minify-whitespace: 1.0.1 - hast-util-phrasing: 3.0.1 - hast-util-whitespace: 3.0.0 - html-whitespace-sensitive-tag-names: 3.0.1 - unist-util-visit-parents: 6.0.2 - - hast-util-from-html@2.0.3: - dependencies: - "@types/hast": 3.0.4 - devlop: 1.1.0 - hast-util-from-parse5: 8.0.3 - parse5: 7.3.0 - vfile: 6.0.3 - vfile-message: 4.0.3 - - hast-util-from-parse5@8.0.3: - dependencies: - "@types/hast": 3.0.4 - "@types/unist": 3.0.3 - devlop: 1.1.0 - hastscript: 9.0.1 - property-information: 7.1.0 - vfile: 6.0.3 - vfile-location: 5.0.3 - web-namespaces: 2.0.1 - - hast-util-has-property@3.0.0: - dependencies: - "@types/hast": 3.0.4 - - hast-util-is-body-ok-link@3.0.1: - dependencies: - "@types/hast": 3.0.4 - - hast-util-is-element@3.0.0: - dependencies: - "@types/hast": 3.0.4 - - hast-util-minify-whitespace@1.0.1: - dependencies: - "@types/hast": 3.0.4 - hast-util-embedded: 3.0.0 - hast-util-is-element: 3.0.0 - hast-util-whitespace: 3.0.0 - unist-util-is: 6.0.1 - - hast-util-parse-selector@4.0.0: - dependencies: - "@types/hast": 3.0.4 - - hast-util-phrasing@3.0.1: - dependencies: - "@types/hast": 3.0.4 - hast-util-embedded: 3.0.0 - hast-util-has-property: 3.0.0 - hast-util-is-body-ok-link: 3.0.1 - hast-util-is-element: 3.0.0 - - hast-util-raw@9.1.0: - dependencies: - "@types/hast": 3.0.4 - "@types/unist": 3.0.3 - "@ungap/structured-clone": 1.3.0 - hast-util-from-parse5: 8.0.3 - hast-util-to-parse5: 8.0.1 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.1 - parse5: 7.3.0 - unist-util-position: 5.0.0 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - - hast-util-select@6.0.4: - dependencies: - "@types/hast": 3.0.4 - "@types/unist": 3.0.3 - bcp-47-match: 2.0.3 - comma-separated-tokens: 2.0.3 - css-selector-parser: 3.3.0 - devlop: 1.1.0 - direction: 2.0.1 - hast-util-has-property: 3.0.0 - hast-util-to-string: 3.0.1 - hast-util-whitespace: 3.0.0 - nth-check: 2.1.1 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - unist-util-visit: 5.1.0 - zwitch: 2.0.4 - - hast-util-to-estree@3.1.3: - dependencies: - "@types/estree": 1.0.8 - "@types/estree-jsx": 1.0.5 - "@types/hast": 3.0.4 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - estree-util-attach-comments: 3.0.0 - estree-util-is-identifier-name: 3.0.0 - hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.2.0 - mdast-util-mdxjs-esm: 2.0.1 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - style-to-js: 1.1.21 - unist-util-position: 5.0.0 - zwitch: 2.0.4 - transitivePeerDependencies: - - supports-color - - hast-util-to-html@9.0.5: - dependencies: - "@types/hast": 3.0.4 - "@types/unist": 3.0.3 - ccount: 2.0.1 - comma-separated-tokens: 2.0.3 - hast-util-whitespace: 3.0.0 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.1 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - stringify-entities: 4.0.4 - zwitch: 2.0.4 - - hast-util-to-jsx-runtime@2.3.6: - dependencies: - "@types/estree": 1.0.8 - "@types/hast": 3.0.4 - "@types/unist": 3.0.3 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.2.0 - mdast-util-mdxjs-esm: 2.0.1 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - style-to-js: 1.1.21 - unist-util-position: 5.0.0 - vfile-message: 4.0.3 - transitivePeerDependencies: - - supports-color - - hast-util-to-parse5@8.0.1: - dependencies: - "@types/hast": 3.0.4 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - - hast-util-to-string@3.0.1: - dependencies: - "@types/hast": 3.0.4 - - hast-util-to-text@4.0.2: - dependencies: - "@types/hast": 3.0.4 - "@types/unist": 3.0.3 - hast-util-is-element: 3.0.0 - unist-util-find-after: 5.0.0 - - hast-util-whitespace@3.0.0: - dependencies: - "@types/hast": 3.0.4 - - hastscript@9.0.1: - dependencies: - "@types/hast": 3.0.4 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 4.0.0 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - - html-escaper@3.0.3: {} - - html-void-elements@3.0.0: {} - - html-whitespace-sensitive-tag-names@3.0.1: {} - - http-cache-semantics@4.2.0: {} - - i18next@23.16.8: - dependencies: - "@babel/runtime": 7.28.6 - - import-meta-resolve@4.2.0: {} - - inline-style-parser@0.2.7: {} - - iron-webcrypto@1.2.1: {} - - is-alphabetical@2.0.1: {} - - is-alphanumerical@2.0.1: - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - - is-decimal@2.0.1: {} - - is-docker@3.0.0: {} - - is-fullwidth-code-point@3.0.0: {} - - is-hexadecimal@2.0.1: {} - - is-inside-container@1.0.0: - dependencies: - is-docker: 3.0.0 - - is-plain-obj@4.1.0: {} - - is-wsl@3.1.1: - dependencies: - is-inside-container: 1.0.0 - - js-tokens@4.0.0: {} - - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 - - json-schema-traverse@1.0.0: {} - - jsonpointer@5.0.1: {} - - kleur@3.0.3: {} - - klona@2.0.6: {} - - leven@3.1.0: {} - - longest-streak@3.1.0: {} - - lru-cache@11.2.6: {} - - magic-string@0.30.21: - dependencies: - "@jridgewell/sourcemap-codec": 1.5.5 - - magicast@0.5.2: - dependencies: - "@babel/parser": 7.29.0 - "@babel/types": 7.29.0 - source-map-js: 1.2.1 - - markdown-extensions@2.0.0: {} - - markdown-table@3.0.4: {} - - mdast-util-definitions@6.0.0: - dependencies: - "@types/mdast": 4.0.4 - "@types/unist": 3.0.3 - unist-util-visit: 5.1.0 - - mdast-util-directive@3.1.0: - dependencies: - "@types/mdast": 4.0.4 - "@types/unist": 3.0.3 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - parse-entities: 4.0.2 - stringify-entities: 4.0.4 - unist-util-visit-parents: 6.0.2 - transitivePeerDependencies: - - supports-color - - mdast-util-find-and-replace@3.0.2: - dependencies: - "@types/mdast": 4.0.4 - escape-string-regexp: 5.0.0 - unist-util-is: 6.0.1 - unist-util-visit-parents: 6.0.2 - - mdast-util-from-markdown@2.0.2: - dependencies: - "@types/mdast": 4.0.4 - "@types/unist": 3.0.3 - decode-named-character-reference: 1.3.0 - devlop: 1.1.0 - mdast-util-to-string: 4.0.0 - micromark: 4.0.2 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-decode-string: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - unist-util-stringify-position: 4.0.0 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-autolink-literal@2.0.1: - dependencies: - "@types/mdast": 4.0.4 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-find-and-replace: 3.0.2 - micromark-util-character: 2.1.1 - - mdast-util-gfm-footnote@2.1.0: - dependencies: - "@types/mdast": 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - micromark-util-normalize-identifier: 2.0.1 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-strikethrough@2.0.0: - dependencies: - "@types/mdast": 4.0.4 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-table@2.0.0: - dependencies: - "@types/mdast": 4.0.4 - devlop: 1.1.0 - markdown-table: 3.0.4 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-task-list-item@2.0.0: - dependencies: - "@types/mdast": 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm@3.1.0: - dependencies: - mdast-util-from-markdown: 2.0.2 - mdast-util-gfm-autolink-literal: 2.0.1 - mdast-util-gfm-footnote: 2.1.0 - mdast-util-gfm-strikethrough: 2.0.0 - mdast-util-gfm-table: 2.0.0 - mdast-util-gfm-task-list-item: 2.0.0 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-mdx-expression@2.0.1: - dependencies: - "@types/estree-jsx": 1.0.5 - "@types/hast": 3.0.4 - "@types/mdast": 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-mdx-jsx@3.2.0: - dependencies: - "@types/estree-jsx": 1.0.5 - "@types/hast": 3.0.4 - "@types/mdast": 4.0.4 - "@types/unist": 3.0.3 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - parse-entities: 4.0.2 - stringify-entities: 4.0.4 - unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.3 - transitivePeerDependencies: - - supports-color - - mdast-util-mdx@3.0.0: - dependencies: - mdast-util-from-markdown: 2.0.2 - mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.2.0 - mdast-util-mdxjs-esm: 2.0.1 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-mdxjs-esm@2.0.1: - dependencies: - "@types/estree-jsx": 1.0.5 - "@types/hast": 3.0.4 - "@types/mdast": 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-phrasing@4.1.0: - dependencies: - "@types/mdast": 4.0.4 - unist-util-is: 6.0.1 - - mdast-util-to-hast@13.2.1: - dependencies: - "@types/hast": 3.0.4 - "@types/mdast": 4.0.4 - "@ungap/structured-clone": 1.3.0 - devlop: 1.1.0 - micromark-util-sanitize-uri: 2.0.1 - trim-lines: 3.0.1 - unist-util-position: 5.0.0 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - - mdast-util-to-markdown@2.1.2: - dependencies: - "@types/mdast": 4.0.4 - "@types/unist": 3.0.3 - longest-streak: 3.1.0 - mdast-util-phrasing: 4.1.0 - mdast-util-to-string: 4.0.0 - micromark-util-classify-character: 2.0.1 - micromark-util-decode-string: 2.0.1 - unist-util-visit: 5.1.0 - zwitch: 2.0.4 - - mdast-util-to-string@4.0.0: - dependencies: - "@types/mdast": 4.0.4 - - mdn-data@2.0.28: {} - - mdn-data@2.12.2: {} - - micromark-core-commonmark@2.0.3: - dependencies: - decode-named-character-reference: 1.3.0 - devlop: 1.1.0 - micromark-factory-destination: 2.0.1 - micromark-factory-label: 2.0.1 - micromark-factory-space: 2.0.1 - micromark-factory-title: 2.0.1 - micromark-factory-whitespace: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-chunked: 2.0.1 - micromark-util-classify-character: 2.0.1 - micromark-util-html-tag-name: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-subtokenize: 2.1.0 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-directive@3.0.2: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-factory-whitespace: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - parse-entities: 4.0.2 - - micromark-extension-gfm-autolink-literal@2.1.0: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-footnote@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-strikethrough@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.1 - micromark-util-classify-character: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-table@2.1.1: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-tagfilter@2.0.0: - dependencies: - micromark-util-types: 2.0.2 - - micromark-extension-gfm-task-list-item@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm@3.0.0: - dependencies: - micromark-extension-gfm-autolink-literal: 2.1.0 - micromark-extension-gfm-footnote: 2.1.0 - micromark-extension-gfm-strikethrough: 2.1.0 - micromark-extension-gfm-table: 2.1.1 - micromark-extension-gfm-tagfilter: 2.0.0 - micromark-extension-gfm-task-list-item: 2.1.0 - micromark-util-combine-extensions: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-mdx-expression@3.0.1: - dependencies: - "@types/estree": 1.0.8 - devlop: 1.1.0 - micromark-factory-mdx-expression: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-events-to-acorn: 2.0.3 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-mdx-jsx@3.0.2: - dependencies: - "@types/estree": 1.0.8 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - micromark-factory-mdx-expression: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-events-to-acorn: 2.0.3 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - vfile-message: 4.0.3 - - micromark-extension-mdx-md@2.0.0: - dependencies: - micromark-util-types: 2.0.2 - - micromark-extension-mdxjs-esm@3.0.0: - dependencies: - "@types/estree": 1.0.8 - devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-util-character: 2.1.1 - micromark-util-events-to-acorn: 2.0.3 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - unist-util-position-from-estree: 2.0.0 - vfile-message: 4.0.3 - - micromark-extension-mdxjs@3.0.0: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - micromark-extension-mdx-expression: 3.0.1 - micromark-extension-mdx-jsx: 3.0.2 - micromark-extension-mdx-md: 2.0.0 - micromark-extension-mdxjs-esm: 3.0.0 - micromark-util-combine-extensions: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-destination@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-label@2.0.1: - dependencies: - devlop: 1.1.0 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-mdx-expression@2.0.3: - dependencies: - "@types/estree": 1.0.8 - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-events-to-acorn: 2.0.3 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - unist-util-position-from-estree: 2.0.0 - vfile-message: 4.0.3 - - micromark-factory-space@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-types: 2.0.2 - - micromark-factory-title@2.0.1: - dependencies: - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-whitespace@2.0.1: - dependencies: - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-character@2.1.1: - dependencies: - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-chunked@2.0.1: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-classify-character@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-combine-extensions@2.0.1: - dependencies: - micromark-util-chunked: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-decode-numeric-character-reference@2.0.2: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-decode-string@2.0.1: - dependencies: - decode-named-character-reference: 1.3.0 - micromark-util-character: 2.1.1 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-symbol: 2.0.1 - - micromark-util-encode@2.0.1: {} - - micromark-util-events-to-acorn@2.0.3: - dependencies: - "@types/estree": 1.0.8 - "@types/unist": 3.0.3 - devlop: 1.1.0 - estree-util-visit: 2.0.0 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - vfile-message: 4.0.3 - - micromark-util-html-tag-name@2.0.1: {} - - micromark-util-normalize-identifier@2.0.1: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-resolve-all@2.0.1: - dependencies: - micromark-util-types: 2.0.2 - - micromark-util-sanitize-uri@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-encode: 2.0.1 - micromark-util-symbol: 2.0.1 - - micromark-util-subtokenize@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-symbol@2.0.1: {} - - micromark-util-types@2.0.2: {} - - micromark@4.0.2: - dependencies: - "@types/debug": 4.1.12 - debug: 4.4.3 - decode-named-character-reference: 1.3.0 - devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-chunked: 2.0.1 - micromark-util-combine-extensions: 2.0.1 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-encode: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-subtokenize: 2.1.0 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - transitivePeerDependencies: - - supports-color - - mrmime@2.0.1: {} - - ms@2.1.3: {} - - nanoid@3.3.11: {} - - neotraverse@0.6.18: {} - - nlcst-to-string@4.0.0: - dependencies: - "@types/nlcst": 2.0.3 - - node-fetch-native@1.6.7: {} - - node-mock-http@1.0.4: {} - - normalize-path@3.0.0: {} - - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 - - ofetch@1.5.1: - dependencies: - destr: 2.0.5 - node-fetch-native: 1.6.7 - ufo: 1.6.3 - - ohash@2.0.11: {} - - oniguruma-parser@0.12.1: {} - - oniguruma-to-es@4.3.4: - dependencies: - oniguruma-parser: 0.12.1 - regex: 6.1.0 - regex-recursion: 6.0.2 - - openapi-types@12.1.3: {} - - p-limit@6.2.0: - dependencies: - yocto-queue: 1.2.2 - - p-queue@8.1.1: - dependencies: - eventemitter3: 5.0.4 - p-timeout: 6.1.4 - - p-timeout@6.1.4: {} - - package-manager-detector@1.6.0: {} - - pagefind@1.4.0: - optionalDependencies: - "@pagefind/darwin-arm64": 1.4.0 - "@pagefind/darwin-x64": 1.4.0 - "@pagefind/freebsd-x64": 1.4.0 - "@pagefind/linux-arm64": 1.4.0 - "@pagefind/linux-x64": 1.4.0 - "@pagefind/windows-x64": 1.4.0 - - parse-entities@4.0.2: - dependencies: - "@types/unist": 2.0.11 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.3.0 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - - parse-latin@7.0.0: - dependencies: - "@types/nlcst": 2.0.3 - "@types/unist": 3.0.3 - nlcst-to-string: 4.0.0 - unist-util-modify-children: 4.0.0 - unist-util-visit-children: 3.0.0 - vfile: 6.0.3 - - parse5@7.3.0: - dependencies: - entities: 6.0.1 - - piccolore@0.1.3: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - picomatch@4.0.3: {} - - postcss-nested@6.2.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - postcss-selector-parser@6.1.2: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prismjs@1.30.0: {} - - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - - property-information@7.1.0: {} - - radix3@1.1.2: {} - - readdirp@5.0.0: {} - - recma-build-jsx@1.0.0: - dependencies: - "@types/estree": 1.0.8 - estree-util-build-jsx: 3.0.1 - vfile: 6.0.3 - - recma-jsx@1.0.1(acorn@8.15.0): - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - estree-util-to-js: 2.0.0 - recma-parse: 1.0.0 - recma-stringify: 1.0.0 - unified: 11.0.5 - - recma-parse@1.0.0: - dependencies: - "@types/estree": 1.0.8 - esast-util-from-js: 2.0.1 - unified: 11.0.5 - vfile: 6.0.3 - - recma-stringify@1.0.0: - dependencies: - "@types/estree": 1.0.8 - estree-util-to-js: 2.0.0 - unified: 11.0.5 - vfile: 6.0.3 - - regex-recursion@6.0.2: - dependencies: - regex-utilities: 2.3.0 - - regex-utilities@2.3.0: {} - - regex@6.1.0: - dependencies: - regex-utilities: 2.3.0 - - rehype-expressive-code@0.41.6: - dependencies: - expressive-code: 0.41.6 - - rehype-format@5.0.1: - dependencies: - "@types/hast": 3.0.4 - hast-util-format: 1.1.0 - - rehype-parse@9.0.1: - dependencies: - "@types/hast": 3.0.4 - hast-util-from-html: 2.0.3 - unified: 11.0.5 - - rehype-raw@7.0.0: - dependencies: - "@types/hast": 3.0.4 - hast-util-raw: 9.1.0 - vfile: 6.0.3 - - rehype-recma@1.0.0: - dependencies: - "@types/estree": 1.0.8 - "@types/hast": 3.0.4 - hast-util-to-estree: 3.1.3 - transitivePeerDependencies: - - supports-color - - rehype-stringify@10.0.1: - dependencies: - "@types/hast": 3.0.4 - hast-util-to-html: 9.0.5 - unified: 11.0.5 - - rehype@13.0.2: - dependencies: - "@types/hast": 3.0.4 - rehype-parse: 9.0.1 - rehype-stringify: 10.0.1 - unified: 11.0.5 - - remark-directive@3.0.1: - dependencies: - "@types/mdast": 4.0.4 - mdast-util-directive: 3.1.0 - micromark-extension-directive: 3.0.2 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - - remark-gfm@4.0.1: - dependencies: - "@types/mdast": 4.0.4 - mdast-util-gfm: 3.1.0 - micromark-extension-gfm: 3.0.0 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - - remark-mdx@3.1.1: - dependencies: - mdast-util-mdx: 3.0.0 - micromark-extension-mdxjs: 3.0.0 - transitivePeerDependencies: - - supports-color - - remark-parse@11.0.0: - dependencies: - "@types/mdast": 4.0.4 - mdast-util-from-markdown: 2.0.2 - micromark-util-types: 2.0.2 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - - remark-rehype@11.1.2: - dependencies: - "@types/hast": 3.0.4 - "@types/mdast": 4.0.4 - mdast-util-to-hast: 13.2.1 - unified: 11.0.5 - vfile: 6.0.3 - - remark-smartypants@3.0.2: - dependencies: - retext: 9.0.0 - retext-smartypants: 6.2.0 - unified: 11.0.5 - unist-util-visit: 5.1.0 - - remark-stringify@11.0.0: - dependencies: - "@types/mdast": 4.0.4 - mdast-util-to-markdown: 2.1.2 - unified: 11.0.5 - - require-from-string@2.0.2: {} - - retext-latin@4.0.0: - dependencies: - "@types/nlcst": 2.0.3 - parse-latin: 7.0.0 - unified: 11.0.5 - - retext-smartypants@6.2.0: - dependencies: - "@types/nlcst": 2.0.3 - nlcst-to-string: 4.0.0 - unist-util-visit: 5.1.0 - - retext-stringify@4.0.0: - dependencies: - "@types/nlcst": 2.0.3 - nlcst-to-string: 4.0.0 - unified: 11.0.5 - - retext@9.0.0: - dependencies: - "@types/nlcst": 2.0.3 - retext-latin: 4.0.0 - retext-stringify: 4.0.0 - unified: 11.0.5 - - rollup@4.57.1: - dependencies: - "@types/estree": 1.0.8 - optionalDependencies: - "@rollup/rollup-android-arm-eabi": 4.57.1 - "@rollup/rollup-android-arm64": 4.57.1 - "@rollup/rollup-darwin-arm64": 4.57.1 - "@rollup/rollup-darwin-x64": 4.57.1 - "@rollup/rollup-freebsd-arm64": 4.57.1 - "@rollup/rollup-freebsd-x64": 4.57.1 - "@rollup/rollup-linux-arm-gnueabihf": 4.57.1 - "@rollup/rollup-linux-arm-musleabihf": 4.57.1 - "@rollup/rollup-linux-arm64-gnu": 4.57.1 - "@rollup/rollup-linux-arm64-musl": 4.57.1 - "@rollup/rollup-linux-loong64-gnu": 4.57.1 - "@rollup/rollup-linux-loong64-musl": 4.57.1 - "@rollup/rollup-linux-ppc64-gnu": 4.57.1 - "@rollup/rollup-linux-ppc64-musl": 4.57.1 - "@rollup/rollup-linux-riscv64-gnu": 4.57.1 - "@rollup/rollup-linux-riscv64-musl": 4.57.1 - "@rollup/rollup-linux-s390x-gnu": 4.57.1 - "@rollup/rollup-linux-x64-gnu": 4.57.1 - "@rollup/rollup-linux-x64-musl": 4.57.1 - "@rollup/rollup-openbsd-x64": 4.57.1 - "@rollup/rollup-openharmony-arm64": 4.57.1 - "@rollup/rollup-win32-arm64-msvc": 4.57.1 - "@rollup/rollup-win32-ia32-msvc": 4.57.1 - "@rollup/rollup-win32-x64-gnu": 4.57.1 - "@rollup/rollup-win32-x64-msvc": 4.57.1 - fsevents: 2.3.3 - - sax@1.4.4: {} - - semver@7.7.4: {} - - sharp@0.34.5: - dependencies: - "@img/colour": 1.0.0 - detect-libc: 2.1.2 - semver: 7.7.4 - optionalDependencies: - "@img/sharp-darwin-arm64": 0.34.5 - "@img/sharp-darwin-x64": 0.34.5 - "@img/sharp-libvips-darwin-arm64": 1.2.4 - "@img/sharp-libvips-darwin-x64": 1.2.4 - "@img/sharp-libvips-linux-arm": 1.2.4 - "@img/sharp-libvips-linux-arm64": 1.2.4 - "@img/sharp-libvips-linux-ppc64": 1.2.4 - "@img/sharp-libvips-linux-riscv64": 1.2.4 - "@img/sharp-libvips-linux-s390x": 1.2.4 - "@img/sharp-libvips-linux-x64": 1.2.4 - "@img/sharp-libvips-linuxmusl-arm64": 1.2.4 - "@img/sharp-libvips-linuxmusl-x64": 1.2.4 - "@img/sharp-linux-arm": 0.34.5 - "@img/sharp-linux-arm64": 0.34.5 - "@img/sharp-linux-ppc64": 0.34.5 - "@img/sharp-linux-riscv64": 0.34.5 - "@img/sharp-linux-s390x": 0.34.5 - "@img/sharp-linux-x64": 0.34.5 - "@img/sharp-linuxmusl-arm64": 0.34.5 - "@img/sharp-linuxmusl-x64": 0.34.5 - "@img/sharp-wasm32": 0.34.5 - "@img/sharp-win32-arm64": 0.34.5 - "@img/sharp-win32-ia32": 0.34.5 - "@img/sharp-win32-x64": 0.34.5 - - shiki@3.22.0: - dependencies: - "@shikijs/core": 3.22.0 - "@shikijs/engine-javascript": 3.22.0 - "@shikijs/engine-oniguruma": 3.22.0 - "@shikijs/langs": 3.22.0 - "@shikijs/themes": 3.22.0 - "@shikijs/types": 3.22.0 - "@shikijs/vscode-textmate": 10.0.2 - "@types/hast": 3.0.4 - - sisteransi@1.0.5: {} - - sitemap@8.0.2: - dependencies: - "@types/node": 17.0.45 - "@types/sax": 1.2.7 - arg: 5.0.2 - sax: 1.4.4 - - smol-toml@1.6.0: {} - - source-map-js@1.2.1: {} - - source-map@0.7.6: {} - - space-separated-tokens@2.0.2: {} - - starlight-openapi@0.22.0(@astrojs/markdown-remark@6.3.10)(@astrojs/starlight@0.37.6(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3)))(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3))(openapi-types@12.1.3): - dependencies: - "@astrojs/markdown-remark": 6.3.10 - "@astrojs/starlight": 0.37.6(astro@5.17.2(rollup@4.57.1)(typescript@5.9.3)) - "@readme/openapi-parser": 4.1.2(openapi-types@12.1.3) - astro: 5.17.2(rollup@4.57.1)(typescript@5.9.3) - github-slugger: 2.0.0 - url-template: 3.1.1 - transitivePeerDependencies: - - openapi-types - - stream-replace-string@2.0.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 - - stringify-entities@4.0.4: - dependencies: - character-entities-html4: 2.1.0 - character-entities-legacy: 3.0.0 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.2: - dependencies: - ansi-regex: 6.2.2 - - style-to-js@1.1.21: - dependencies: - style-to-object: 1.0.14 - - style-to-object@1.0.14: - dependencies: - inline-style-parser: 0.2.7 - - svgo@4.0.0: - dependencies: - commander: 11.1.0 - css-select: 5.2.2 - css-tree: 3.1.0 - css-what: 6.2.2 - csso: 5.0.5 - picocolors: 1.1.1 - sax: 1.4.4 - - tiny-inflate@1.0.3: {} - - tinyexec@1.0.2: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - trim-lines@3.0.1: {} - - trough@2.2.0: {} - - tsconfck@3.1.6(typescript@5.9.3): - optionalDependencies: - typescript: 5.9.3 - - tslib@2.8.1: - optional: true - - type-fest@4.41.0: {} - - typescript@5.9.3: {} - - ufo@1.6.3: {} - - ultrahtml@1.6.0: {} - - uncrypto@0.1.3: {} - - unified@11.0.5: - dependencies: - "@types/unist": 3.0.3 - bail: 2.0.2 - devlop: 1.1.0 - extend: 3.0.2 - is-plain-obj: 4.1.0 - trough: 2.2.0 - vfile: 6.0.3 - - unifont@0.7.4: - dependencies: - css-tree: 3.1.0 - ofetch: 1.5.1 - ohash: 2.0.11 - - unist-util-find-after@5.0.0: - dependencies: - "@types/unist": 3.0.3 - unist-util-is: 6.0.1 - - unist-util-is@6.0.1: - dependencies: - "@types/unist": 3.0.3 - - unist-util-modify-children@4.0.0: - dependencies: - "@types/unist": 3.0.3 - array-iterate: 2.0.1 - - unist-util-position-from-estree@2.0.0: - dependencies: - "@types/unist": 3.0.3 - - unist-util-position@5.0.0: - dependencies: - "@types/unist": 3.0.3 - - unist-util-remove-position@5.0.0: - dependencies: - "@types/unist": 3.0.3 - unist-util-visit: 5.1.0 - - unist-util-stringify-position@4.0.0: - dependencies: - "@types/unist": 3.0.3 - - unist-util-visit-children@3.0.0: - dependencies: - "@types/unist": 3.0.3 - - unist-util-visit-parents@6.0.2: - dependencies: - "@types/unist": 3.0.3 - unist-util-is: 6.0.1 - - unist-util-visit@5.1.0: - dependencies: - "@types/unist": 3.0.3 - unist-util-is: 6.0.1 - unist-util-visit-parents: 6.0.2 - - unstorage@1.17.4: - dependencies: - anymatch: 3.1.3 - chokidar: 5.0.0 - destr: 2.0.5 - h3: 1.15.5 - lru-cache: 11.2.6 - node-fetch-native: 1.6.7 - ofetch: 1.5.1 - ufo: 1.6.3 - - url-template@3.1.1: {} - - util-deprecate@1.0.2: {} - - vfile-location@5.0.3: - dependencies: - "@types/unist": 3.0.3 - vfile: 6.0.3 - - vfile-message@4.0.3: - dependencies: - "@types/unist": 3.0.3 - unist-util-stringify-position: 4.0.0 - - vfile@6.0.3: - dependencies: - "@types/unist": 3.0.3 - vfile-message: 4.0.3 - - vite@6.4.1: - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.57.1 - tinyglobby: 0.2.15 - optionalDependencies: - fsevents: 2.3.3 - - vitefu@1.1.1(vite@6.4.1): - optionalDependencies: - vite: 6.4.1 - - web-namespaces@2.0.1: {} - - which-pm-runs@1.1.0: {} - - widest-line@5.0.0: - dependencies: - string-width: 7.2.0 - - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.1.2 - - xxhash-wasm@1.1.0: {} - - yargs-parser@21.1.1: {} - - yocto-queue@1.2.2: {} - - yocto-spinner@0.2.3: - dependencies: - yoctocolors: 2.1.2 - - yoctocolors@2.1.2: {} - - zod-to-json-schema@3.25.1(zod@3.25.76): - dependencies: - zod: 3.25.76 - - zod-to-ts@1.2.0(typescript@5.9.3)(zod@3.25.76): - dependencies: - typescript: 5.9.3 - zod: 3.25.76 - - zod@3.25.76: {} - - zwitch@2.0.4: {} diff --git a/docs/postcss.config.js b/docs/postcss.config.js new file mode 100644 index 00000000..b9f6f4b1 --- /dev/null +++ b/docs/postcss.config.js @@ -0,0 +1,5 @@ +/* eslint-disable */ + +module.exports = { + plugins: [require("tailwindcss")], +}; diff --git a/docs/src/.i18n-filter b/docs/src/.i18n-filter index 9871cee8..6e3dfc30 100644 --- a/docs/src/.i18n-filter +++ b/docs/src/.i18n-filter @@ -1,9 +1,7 @@ -en -ca -de -es +public +contributing +getting-started +index.md fr -nn-no -pt-br -sr-latn -zh-hans +pt-BR +nn-NO diff --git a/docs/src/ar/contributing/_category_.json b/docs/src/ar/contributing/_category_.json new file mode 100644 index 00000000..e12f1ce5 --- /dev/null +++ b/docs/src/ar/contributing/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Contributing", + "position": 3 +} diff --git a/docs/src/ar/contributing/guidelines.md b/docs/src/ar/contributing/guidelines.md new file mode 100644 index 00000000..1a53c89e --- /dev/null +++ b/docs/src/ar/contributing/guidelines.md @@ -0,0 +1,154 @@ +--- +title: Guidelines +--- + +# Contributing to Castopod + +Love Castopod and want to help? Thanks so much, there's something to do for +everybody! + +Please take a moment to review this document in order to make the contribution +process easy and effective for everyone involved. + +Following these guidelines helps to communicate that you respect the time of the +developers managing and developing this open source project. In return, they +should reciprocate that respect in addressing your issue or assessing patches +and features. + +::: info Note + +**Any** contribution made on a repository other than +[the original repository](https://code.castopod.org/adaures/castopod) will not +be accepted. + +::: + +## Using the issue tracker + +The [issue tracker](https://code.castopod.org/adaures/castopod/-/issues) is the +preferred channel for [bug reports](#bug-reports), +[features requests](#feature-requests) and +[submitting pull requests](#pull-requests). + +## ⚠️ Security issues and vulnerabilities + +If you encounter any security issue or vulnerability in the Castopod source, +please contact us directly by email at +[security@castopod.org](mailto:security@castopod.org) + +## Bug reports + +A bug is a _demonstrable problem_ that is caused by the code in the repository. +Good bug reports are extremely helpful - thank you! + +Guidelines for bug reports: + +1. **Use the issue search** — check if the issue has already been + reported. + +2. **Check if the issue has been fixed** — try to reproduce it using the + latest `main` branch in the repository. + +3. **Isolate the problem** — ideally create a + [reduced test case](https://css-tricks.com/reduced-test-cases/) and a live + example. + +A good bug report shouldn't leave others needing to chase you up for more +information. Please try to be as detailed as possible in your report. What is +your environment? What steps will reproduce the issue? What browser(s) and OS +experience the problem? What would you expect to be the outcome? All these +details will help people to fix any potential bugs. + +> [Issue templates](https://docs.gitlab.com/ee/user/project/description_templates.html#using-the-templates) +> have been created for this project. You may use them to help you follow those +> guidelines. + +## Feature requests + +Feature requests are welcome. But take a moment to find out whether your idea +fits with the scope and aims of the project. It's up to _you_ to make a strong +case to convince the project's developers of the merits of this feature. Please +provide as much detail and context as possible. + +## Pull requests + +Good pull requests - patches, improvements, new features - are a fantastic help. +They should remain focused in scope and avoid containing unrelated commits. + +**Please ask first** before embarking on any significant pull request (e.g. +implementing features, refactoring code, porting to a different language), +otherwise you risk spending a lot of time working on something that the +project's developers might not want to merge into the project. + +Please adhere to the coding conventions used throughout a project (indentation, +accurate comments, etc.) and any other requirements (such as test coverage). + +Adhering to the following process is the best way to get your work included in +the project: + +1. [Fork](https://docs.gitlab.com/ee/gitlab-basics/fork-project.html) the + project, clone your fork, and configure the remotes: + +```bash +# Clone your fork of the repo into the current directory +git clone https://code.castopod.org//castopod.git + +# Navigate to the newly cloned directory +cd castopod + +# Assign the original repo to a remote called "upstream" +git remote add upstream https://code.castopod.org/adaures/castopod.git +``` + +2. If you cloned a while ago, get the latest changes from upstream: + +```bash +git checkout main +git pull upstream main +``` + +3. Create a new topic branch (off the `main` branch) to contain your feature, + change, or fix: + +```bash +git checkout -b +``` + +4. Commit your changes in logical chunks. Please adhere to these + [git commit message guidelines](https://conventionalcommits.org/) or your + code is unlikely be merged into the main project. Use Git's + [interactive rebase](https://help.github.com/articles/about-git-rebase/) + feature to tidy up your commits before making them public. + +5. Locally merge (or rebase) the upstream dev branch into your topic branch: + +```bash +git pull [--rebase] upstream main +``` + +6. Push your topic branch up to your fork: + +```bash +git push origin +``` + +7. [Open a Pull Request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html#new-merge-request-from-a-fork) + with a clear title and description. + +**IMPORTANT**: By submitting a patch, you agree to allow the project owners to +license your work under the terms of the +[GNU AGPLv3](https://code.castopod.org/adaures/castopod/-/blob/main/LICENSE). + +## Collaborating guidelines + +There are few basic rules to ensure high quality of the project: + +- Before merging, a PR requires at least two approvals from the collaborators + unless it's an architectural change, a large feature, etc. If it is, then at + least 50% of the core team have to agree to merge it, with every team member + having a full veto right. (i.e. every single one can block any PR) +- A PR should remain open for at least two days before merging (does not apply + for trivial contributions like fixing a typo). This way everyone has enough + time to look into it. + +You are always welcome to discuss and propose improvements to this guideline. diff --git a/CONTRIBUTING-DEV.md b/docs/src/ar/contributing/setup-development.md similarity index 63% rename from CONTRIBUTING-DEV.md rename to docs/src/ar/contributing/setup-development.md index 907d3ce1..6aafb50b 100644 --- a/CONTRIBUTING-DEV.md +++ b/docs/src/ar/contributing/setup-development.md @@ -1,3 +1,8 @@ +--- +title: Development setup +sidebarDepth: 3 +--- + # Setup your development environment ## Introduction @@ -5,7 +10,7 @@ Castopod is a web app based on the `php` framework [CodeIgniter 4](https://codeigniter.com). -We use [Docker](https://www.docker.com/) to quickly setup a dev environment. A +We use [Docker](https://www.docker.com/) quickly setup a dev environment. A `docker-compose.yml` and `Dockerfile` are included in the project's root folder to help you kickstart your contribution. @@ -16,9 +21,9 @@ to help you kickstart your contribution. ### 1. Pre-requisites -0. Install [Docker](https://docs.docker.com/get-docker). +0. Install [docker](https://docs.docker.com/get-docker). -1. Clone the Castopod repository by running: +1. Clone Castopod project by running: ```bash git clone https://code.castopod.org/adaures/castopod.git @@ -29,7 +34,7 @@ to help you kickstart your contribution. ```ini CI_ENVIRONMENT="development" - # If set to development, you must run `pnpm run dev` to start the static assets server + # If set to development, you must run `npm run dev` to start the static assets server vite.environment="development" # By default, this is set to true in the app config. @@ -38,6 +43,7 @@ to help you kickstart your contribution. app.forceGlobalSecureRequests=false app.baseURL="http://localhost:8080/" + app.mediaBaseURL="http://localhost:8080/" admin.gateway="cp-admin" auth.gateway="cp-auth" @@ -46,43 +52,25 @@ to help you kickstart your contribution. database.default.database="castopod" database.default.username="castopod" database.default.password="castopod" - database.default.DBPrefix="dev_" - - analytics.salt="DEV_ANALYTICS_SALT" cache.handler="redis" - cache.redis.host="redis" + cache.redis.host = "redis" # You may not want to use redis as your cache handler # Comment/remove the two lines above and uncomment # the next line for file caching. - # ----------------------- #cache.handler="file" - - ###################################### - # Media config - ###################################### - media.baseURL="http://localhost:8080/" - - # S3 - # Uncomment to store s3 objects using adobe/s3mock service - # ----------------------- - #media.fileManager="s3" - #media.s3.bucket="castopod" - #media.s3.endpoint="http://172.31.0.6:9090/" - #media.s3.pathStyleEndpoint=true ``` - > [!NOTE] - > You can tweak your environment by setting more environment variables in - > your custom `.env` file. See the `env` for examples or the + > _NB._ You can tweak your environment by setting more environment variables + > in your custom `.env` file. See the `env` for examples or the > [CodeIgniter4 User Guide](https://codeigniter.com/user_guide/index.html) > for more info. -3. (for Docker desktop) Add the repository you've cloned to Docker desktop's +3. (for docker desktop) Add the repository you've cloned to docker desktop's `Settings` > `Resources` > `File Sharing` -### 2. (recommended) Develop inside the app container with VSCode +### 2. (recommended) Develop inside the app Container with VSCode If you're working in VSCode, you can take advantage of the `.devcontainer/` folder. It defines a development environment (dev container) with preinstalled @@ -96,16 +84,16 @@ required services will be loaded automagically! 🪄 > The VSCode window will reload inside the dev container. Expect several > minutes during first load as it is building all necessary services. - **Note**: The dev container will start by running Castopod's PHP server. + **Note**: The dev container will start by running Castopod's php server. During development, you will have to start [Vite](https://vitejs.dev)'s dev server for compiling the typescript code and styles: ```bash # run Vite dev server - pnpm run dev + npm run dev ``` - If there is any issue with the PHP server not running, you can restart them + If there is any issue with the php server not running, you can restart them using the following commands: ```bash @@ -125,15 +113,15 @@ required services will be loaded automagically! 🪄 # Composer is installed composer -V - # pnpm is installed - pnpm -v + # npm is installed + npm -v # git is installed git version ``` For more info, see -[Developing inside a Container](https://code.visualstudio.com/docs/devcontainers/containers) +[VSCode Remote Containers](https://code.visualstudio.com/docs/remote/containers) ### 3. Start hacking @@ -144,12 +132,9 @@ more insights. To see your changes, go to: -- `http://localhost:8080/` for the Castopod website -- `http://localhost:8080/cp-admin` for the Castopod admin: - - email: **admin@castopod.local** - - password: **castopod** - +- `http://localhost:8080/` for the Castopod app - `http://localhost:8888/` for the phpmyadmin interface: + - username: **castopod** - password: **castopod** @@ -157,9 +142,9 @@ To see your changes, go to: You do not wish to use the VSCode devcontainer? No problem! -1. Start the Docker containers manually: +1. Start docker containers manually: - Go to the project's root folder and run: + Go to project's root folder and run: ```bash # starts all services declared in docker-compose.yml file @@ -174,7 +159,7 @@ You do not wish to use the VSCode devcontainer? No problem! ``` - > The `docker-compose up -d` command will boot 5 containers in the + > The `docker-compose up -d` command will boot 4 containers in the > background: > > - `castopod_app`: a php based container with Castopod requirements @@ -185,7 +170,6 @@ You do not wish to use the VSCode devcontainer? No problem! > persistent data > - `castopod_phpmyadmin`: a phpmyadmin server to visualize the mariadb > database. - > - `castopod_s3`: a mock s3 server to work on the s3 fileManager 2. Run any command inside the containers by prefixing them with `docker-compose run --rm app`: @@ -197,8 +181,8 @@ You do not wish to use the VSCode devcontainer? No problem! # use Composer docker-compose run --rm app composer -V - # use pnpm - docker-compose run --rm app pnpm -v + # use npm + docker-compose run --rm app npm -v # use git docker-compose run --rm app git version @@ -216,46 +200,57 @@ You do not wish to use the VSCode devcontainer? No problem! composer install ``` - > [!NOTE] - > The php dependencies aren't included in the repository. Composer will check - > the `composer.json` and `composer.lock` files to download the packages with - > the right versions. The dependencies will live under the `vendor/` folder. - > For more info, check out the - > [Composer documentation](https://getcomposer.org/doc/). + ::: info Note -2. Install JavaScript dependencies with [pnpm](https://pnpm.io/) + The php dependencies aren't included in the repository. Composer will check + the `composer.json` and `composer.lock` files to download the packages with + the right versions. The dependencies will live under the `vendor/` folder. + For more info, check out the + [Composer documentation](https://getcomposer.org/doc/). + + ::: + +2. Install javascript dependencies with [npm](https://www.npmjs.com/) ```bash - pnpm install + npm install ``` - > [!NOTE] - > The JavaScript dependencies aren't included in the repository. Pnpm will - > check the `package.json` and `pnpm-lock.yaml` files to download the - > packages with the right versions. The dependencies will live under the - > `node_module` folder. For more info, check out the - > [PNPM documentation](https://pnpm.io/motivation). + ::: info Note + + The javascript dependencies aren't included in the repository. Npm will check + the `package.json` and `package.lock` files to download the packages with the + right versions. The dependencies will live under the `node_module` folder. + For more info, check out the [NPM documentation](https://docs.npmjs.com/). + + ::: 3. Generate static assets: ```bash # build all static assets at once - pnpm run build:static + npm run build:static # build specific assets - pnpm run build:icons - pnpm run build:svg + npm run build:icons + npm run build:svg ``` - > [!NOTE] - > The static assets generated live under the `public/assets` folder, it - > includes JavaScript, styles, images, fonts, icons and svg files. + ::: info Note + + The static assets generated live under the `public/assets` folder, it + includes javascript, styles, images, fonts, icons and svg files. + + ::: ### Initialize and populate database -> [!TIP] -> You may skip this section if you go through the install wizard (go to -> `/cp-install`). +::: tip Tip + +You may skip this section if you go through the install wizard (go to +`/cp-install`). + +::: 1. Build the database with the migrate command: @@ -275,7 +270,7 @@ You do not wish to use the VSCode devcontainer? No problem! ```bash # Populates all required data - php spark db:seed DevSeeder + php spark db:seed AppSeeder ``` You may choose to add data separately: @@ -287,11 +282,21 @@ You do not wish to use the VSCode devcontainer? No problem! # Populates all Languages php spark db:seed LanguageSeeder - # Adds a superadmin with [admin@castopod.local / castopod] credentials - php spark db:seed DevSuperadminSeeder + # Populates all podcasts platforms + php spark db:seed PlatformSeeder + + # Populates all Authentication data (roles definition…) + php spark db:seed AuthSeeder + ``` + +3. (optionnal) Populate the database with test data: + + - Populate test data (login: admin / password: AGUehL3P) + + ```bash + php spark db:seed TestSeeder ``` -3. (optional) Populate the database with test data: - Populate with fake podcast analytics: ```bash @@ -304,6 +309,11 @@ You do not wish to use the VSCode devcontainer? No problem! php spark db:seed FakeWebsiteAnalyticsSeeder ``` + TestSeeder will add an active superadmin user with the following credentials: + + - username: **admin** + - password: **AGUehL3P** + ### Useful docker / docker-compose commands - Monitor the app container: @@ -312,13 +322,13 @@ You do not wish to use the VSCode devcontainer? No problem! docker-compose logs --tail 50 --follow --timestamps app ``` -- Interact with the Redis server using included redis-cli command: +- Interact with redis server using included redis-cli command: ```bash docker exec -it castopod_redis redis-cli ``` -- Monitor the Redis container: +- Monitor the redis container: ```bash docker-compose logs --tail 50 --follow --timestamps redis @@ -354,52 +364,28 @@ docker-compose down docker-compose build app ``` -Check [Docker](https://docs.docker.com/engine/reference/commandline/docker/) and +Check [docker](https://docs.docker.com/engine/reference/commandline/docker/) and [docker-compose](https://docs.docker.com/compose/reference/) documentations for more insights. -### Updating Documentation - -Castopod's documentation is written in Markdown and uses the Astro Starlight -framework. To update Castopod's documentation, including the Getting Started -guide and User Guide: - -1. Change directories to the `docs` directory and install the dependencies: - - ```bash - cd docs/ - pnpm i - ``` - -2. Start the documentation development server: - - ```bash - pnpm run dev --host - ``` - -3. The documentation development server runs on port 4321. In your browser visit - `http://localhost:4321/docs`. If the page displays a 404 Not Found error, - click on the Castopod logo in the upper left hand corner of the page and the - documentation should load. - -4. Edit the Markdown files with your documentation updates. The Astro Starlight - development server will automatically update each time you save a change. - ## Known issues ### Allocation failed - JavaScript heap out of memory -This happens when running `pnpm install`. +This happens when running `npm install`. 👉 By default, docker might not have access to enough RAM. Allocate more memory -and run `pnpm install` again. +and run `npm install` again. ### (Linux) Files created inside container are attributed to root locally You may use Linux user namespaces to fix this on your machine: -> [!NOTE] -> Replace "username" with your local username +::: info Note + +Replace "username" with your local username + +::: 1. Go to `/etc/docker/daemon.json` and add: @@ -423,7 +409,7 @@ You may use Linux user namespaces to fix this on your machine: username:100000:65536 ``` -3. Restart Docker: +3. Restart docker: ```bash sudo systemctl restart docker diff --git a/docs/src/ar/getting-started/_category_.json b/docs/src/ar/getting-started/_category_.json new file mode 100644 index 00000000..877a378f --- /dev/null +++ b/docs/src/ar/getting-started/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Getting Started", + "position": 2 +} diff --git a/docs/src/ar/getting-started/docker.md b/docs/src/ar/getting-started/docker.md new file mode 100644 index 00000000..ededc582 --- /dev/null +++ b/docs/src/ar/getting-started/docker.md @@ -0,0 +1,148 @@ +--- +title: Official Docker images +sidebarDepth: 3 +--- + +# Official Docker images + +Castopod pushes 2 Docker images to the Docker Hub during its automated build +process: + +- [**`castopod/app`**](https://hub.docker.com/r/castopod/app): the app bundle + with all of Castopod dependencies +- [**`castopod/web-server`**](https://hub.docker.com/r/castopod/web-server): an + Nginx configuration for Castopod + +Additionally, Castopod requires a MySQL-compatible database. A Redis database +can be added as a cache handler. + +## Supported tags + +- `develop` [unstable], latest development branch build +- `beta` [stable], latest beta version build +- `1.0.0-beta.x` [stable], specific beta version build (since `1.0.0-beta.22`) + +## Example usage + +1. Install [docker](https://docs.docker.com/get-docker/) and + [docker-compose](https://docs.docker.com/compose/install/) +2. Create a `docker-compose.yml` file with the following: + + ```yml + version: "3.7" + + services: + app: + image: castopod/app:beta + container_name: "castopod-app" + volumes: + - castopod-media:/opt/castopod/public/media + environment: + MYSQL_DATABASE: castopod + MYSQL_USER: castopod + MYSQL_PASSWORD: changeme + CP_BASEURL: "http://castopod.example.com" + CP_ANALYTICS_SALT: changeme + CP_CACHE_HANDLER: redis + CP_REDIS_HOST: redis + networks: + - castopod-app + - castopod-db + restart: unless-stopped + + web-server: + image: castopod/web-server:beta + container_name: "castopod-web-server" + volumes: + - castopod-media:/var/www/html/media + networks: + - castopod-app + ports: + - 8080:80 + restart: unless-stopped + + mariadb: + image: mariadb:10.5 + container_name: "castopod-mariadb" + networks: + - castopod-db + volumes: + - castopod-db:/var/lib/mysql + environment: + MYSQL_ROOT_PASSWORD: changeme + MYSQL_DATABASE: castopod + MYSQL_USER: castopod + MYSQL_PASSWORD: changeme + restart: unless-stopped + + redis: + image: redis:7.0-alpine + container_name: "castopod-redis" + volumes: + - castopod-cache:/data + networks: + - castopod-app + + volumes: + castopod-media: + castopod-db: + castopod-cache: + + networks: + castopod-app: + castopod-db: + ``` + + You have to adapt some variables to your needs (e.g. `CP_BASEURL`, + `MYSQL_ROOT_PASSWORD`, `MYSQL_PASSWORD` and `CP_ANALYTICS_SALT`). + +3. Setup a reverse proxy for TLS (SSL/HTTPS) + + TLS is mandatory for ActivityPub to work. This job can easily be handled by + a reverse proxy, for example with [Caddy](https://caddyserver.com/): + + ``` + #castopod + castopod.example.com { + reverse_proxy localhost:8080 + } + ``` + +4. Run `docker-compose up -d`, wait for it to initialize and head on to + `https://castopod.example.com/cp-install` to finish setting up Castopod! + +5. You're all set, start podcasting! 🎙️🚀 + +## Environment Variables + +- **castopod/app** + + | Variable name | Type (`default`) | Default | + | ---------------------------- | ----------------------- | ---------------- | + | **`CP_BASEURL`** | string | `undefined` | + | **`CP_MEDIA_BASEURL`** | ?string | `CP_BASEURL` | + | **`CP_ADMIN_GATEWAY`** | ?string | `"cp-admin"` | + | **`CP_AUTH_GATEWAY`** | ?string | `"cp-auth"` | + | **`CP_ANALYTICS_SALT`** | string | `undefined` | + | **`CP_DATABASE_HOSTNAME`** | ?string | `"mariadb"` | + | **`CP_DATABASE_NAME`** | ?string | `MYSQL_DATABASE` | + | **`CP_DATABASE_USERNAME`** | ?string | `MYSQL_USER` | + | **`CP_DATABASE_PASSWORD`** | ?string | `MYSQL_PASSWORD` | + | **`CP_DATABASE_PREFIX`** | ?string | `"cp_"` | + | **`CP_CACHE_HANDLER`** | [`"file"` or `"redis"`] | `"file"` | + | **`CP_REDIS_HOST`** | ?string | `"localhost"` | + | **`CP_REDIS_PASSWORD`** | ?string | `null` | + | **`CP_REDIS_PORT`** | ?number | `6379` | + | **`CP_REDIS_DATABASE`** | ?number | `0` | + | **`CP_EMAIL_SMTP_HOST`** | ?string | `undefined` | + | **`CP_EMAIL_FROM`** | ?string | `undefined` | + | **`CP_EMAIL_SMTP_USERNAME`** | ?string | `"localhost"` | + | **`CP_EMAIL_SMTP_PASSWORD`** | ?string | `null` | + | **`CP_EMAIL_SMTP_PORT`** | ?number | `25` | + | **`CP_EMAIL_SMTP_CRYPTO`** | [`"tls"` or `"ssl"`] | `"tls"` | + +- **castopod/web-server** + + | Variable name | Type | Default | + | --------------------- | ------- | ------- | + | **`CP_APP_HOSTNAME`** | ?string | `"app"` | diff --git a/docs/src/content/docs/en/getting-started/install.mdx b/docs/src/ar/getting-started/install.md similarity index 60% rename from docs/src/content/docs/en/getting-started/install.mdx rename to docs/src/ar/getting-started/install.md index f30943b8..3d73187d 100644 --- a/docs/src/content/docs/en/getting-started/install.mdx +++ b/docs/src/ar/getting-started/install.md @@ -1,23 +1,31 @@ --- -title: How to install Castopod? +title: Installation +sidebarDepth: 3 --- -import { Aside, LinkButton } from "@astrojs/starlight/components"; +# How to install Castopod? Castopod was thought-out to be easy to install. Whether using dedicated or shared hosting, you can install it on most PHP-MySQL compatible web servers. +::: tip Note + +We've released official Docker images for Castopod! + +If you prefer using Docker, you may skip this and go straight to the +[docker documentation](./docker.md) for Castopod. + +::: + ## Requirements -- PHP v8.5 or higher -- MySQL version 8.4 or higher or MariaDB version 11.4 or higher +- PHP v8.0 or higher +- MySQL version 5.7 or higher or MariaDB version 10.2 or higher - HTTPS support -- An [ntp-synced clock](https://wiki.debian.org/NTP) to validate federation's - incoming requests -### PHP v8.5 or higher +### PHP v8.0 or higher -PHP version 8.5 or higher is required, with the following extensions installed: +PHP version 8.0 or higher is required, with the following extensions installed: - [intl](https://php.net/manual/en/intl.requirements.php) - [libcurl](https://php.net/manual/en/curl.requirements.php) @@ -36,6 +44,14 @@ Additionally, make sure that the following extensions are enabled in your PHP: > We recommend using [MariaDB](https://mariadb.org). +::: warning Warning + +Castopod only works with supported MySQL 5.7 or higher compatible databases. It +will break with the previous MySQL v5.6 for example as its end of life was on +February 5, 2021. + +::: + You will need the server hostname, database name, username and password to complete the installation process. If you do not have these, please contact your server administrator. @@ -76,18 +92,29 @@ want to generate Video Clips. The following extensions must be installed: 4. Add **cron tasks** on your web server for various background processes (replace the paths accordingly): + - For social features to work properly, this task is used to broadcast social + activities to your followers on the fediverse: + ```bash - * * * * * /path/to/php /path/to/castopod/spark tasks:run >> /dev/null 2>&1 + * * * * * /path/to/php /path/to/castopod/public/index.php scheduled-activities ``` - **Note** - If you do not add this cron task, the following Castopod features - will not work: - - Importing a podcast from an existing RSS feed - - Broadcasting social activities to your followers in the fediverse - - Broadcasting episodes to open hubs using - [WebSub](https://en.wikipedia.org/wiki/WebSub) - - Generating video clips - - [requires FFmpeg](#optional-ffmpeg-v418-or-higher-for-video-clips) + - For having your episodes be broadcasted on open hubs upon publication using + [WebSub](https://en.wikipedia.org/wiki/WebSub): + + ```bash + * * * * * /usr/local/bin/php /castopod/public/index.php scheduled-websub-publish + ``` + + - For Video Clips to be created (see + [FFmpeg requirements](#ffmpeg-v418-or-higher-for-video-clips)): + + ```bash + * * * * * /path/to/php /path/to/castopod/public/index.php scheduled-video-clips + ``` + + > These tasks run **every minute**. You may set the frequency depending on + > your needs: every 5, 10 minutes or more. ### (recommended) Install Wizard @@ -96,30 +123,13 @@ want to generate Video Clips. The following extensions must be installed: 2. Follow the instructions on your screen. 3. Start podcasting! - - -### Using CLI - -1. Create a `.env` file in the package root based on the `.env.example` file. -2. Initialize the database using: - - ```sh - php spark install:init-database - ``` - -3. Create the superadmin user using: - - ```sh - php spark install:create-superadmin - ``` - -4. Head on to your admin gateway to start podcasting! +::: ### Email/SMTP setup @@ -150,50 +160,6 @@ email.SMTPPass="your_smtp_password" | **`SMTPPort`** | number | `25` | | **`SMTPCrypto`** | [`"tls"` or `"ssl"`] | `"tls"` | -### Media storage - -By default, files are saved to the `public/media` folder using the file system. -If you need to relocate the `media` folder to a different location, you can -specify it in your `.env` file as shown below: - -```ini -# […] - -media.root="media" -media.storage="/mnt/storage" -``` - -In this example, the files will be saved to the /mnt/storage/media folder. Make -sure to also update your web server configuration to reflect this change. - -### S3 - -If you prefer storing your media files on an S3 compatible storage, you may -specify it in your `.env`: - -```ini -# […] - -media.fileManager="s3" -media.s3.endpoint="your_s3_host" -media.s3.key="your_s3_key" -media.s3.secret="your_s3_secret" -media.s3.region="your_s3_region" -``` - -#### S3 config options - -| Variable name | Type | Default | -| ----------------------- | ------- | ----------- | -| **`endpoint`** | string | `undefined` | -| **`key`** | string | `undefined` | -| **`secret`** | string | `undefined` | -| **`region`** | string | `undefined` | -| **`bucket`** | string | `castopod` | -| **`protocol`** | number | `undefined` | -| **`pathStyleEndpoint`** | boolean | `false` | -| **`keyPrefix`** | string | `undefined` | - ## Community packages If you don't want to bother with installing Castopod manually, you may use one @@ -205,22 +171,15 @@ of the packages created and maintained by the open-source community. made up of free and open-source software packages. It manages the hardships of self-hosting for you. - - Install Castopod with YunoHost +
    + + + Install Castopod with YunoHost - - Github Repo - +Github +Repo + +
    diff --git a/docs/src/content/docs/da/getting-started/security.mdx b/docs/src/ar/getting-started/security.md similarity index 95% rename from docs/src/content/docs/da/getting-started/security.mdx rename to docs/src/ar/getting-started/security.md index c039493c..e205698d 100644 --- a/docs/src/content/docs/da/getting-started/security.mdx +++ b/docs/src/ar/getting-started/security.md @@ -1,7 +1,9 @@ --- -title: Security concerns +title: Security --- +# Security concerns + Castopod is built on top of [CodeIgniter4](https://codeigniter.com/), a PHP framework that encourages [good security practices](https://codeigniter.com/user_guide/concepts/security.html). diff --git a/docs/src/content/docs/ar/getting-started/update.mdx b/docs/src/ar/getting-started/update.md similarity index 70% rename from docs/src/content/docs/ar/getting-started/update.mdx rename to docs/src/ar/getting-started/update.md index d0bc9d57..51e372ee 100644 --- a/docs/src/content/docs/ar/getting-started/update.mdx +++ b/docs/src/ar/getting-started/update.md @@ -1,69 +1,56 @@ --- -title: How to update Castopod? +title: Update +sidebarDepth: 3 --- -import { Aside } from "@astrojs/starlight/components"; +# How to update Castopod? After installing Castopod, you may want to update your instance to the latest version in order to enjoy the latest features ✨, bug fixes 🐛 and performance improvements ⚡. -## Update instructions +## Automatic update instructions -0. ⚠️ Before any update, we highly recommend you backup your Castopod files and - database. - - cf. - [Should I make a backup before updating?](#should-i-make-a-backup-before-updating) +> Coming soon... 👀 + +## Manual update instructions 1. Go to the [releases page](https://code.castopod.org/adaures/castopod/-/releases) and see if your instance is up to date with the latest Castopod version + - cf. [Where can I find my Castopod version?](#where-can-i-find-my-castopod-version) 2. Download the latest release package named `Castopod Package`, you may choose between the `zip` or `tar.gz` archives + - ⚠️ Make sure you download the Castopod Package and **NOT** the Source Code - - Note that you can also download the latest package from - [castopod.org](https://castopod.org/) 3. On your server: + - Remove all files except `.env` and `public/media` - Copy the new files from the downloaded package into your server - + ::: -4. Update your database schema from your `Castopod Admin` > `About` page or by - running: +4. Releases may come with additional update instructions (see + [releases page](https://code.castopod.org/adaures/castopod/-/releases)). They + are usually database migration scripts in `.sql` format to update your + database schema. - ```bash - php spark castopod:database-update - ``` - -5. Clear your cache from your `Castopod Admin` > `Settings` > `general` > - `Housekeeping` + - 👉 Make sure you run the scripts on your phpmyadmin panel or using command + line to update the database along with the package files! + - I haven't updated my instance in a long time… What should I do? +5. If you are using redis, clear your cache. 6. ✨ Enjoy your fresh instance, you're all done! - - -## Fully Automated updates - -> Coming soon... 👀 - ## Frequently asked questions (FAQ) ### Where can I find my Castopod version? diff --git a/docs/src/ar/index.md b/docs/src/ar/index.md new file mode 100644 index 00000000..d89daccb --- /dev/null +++ b/docs/src/ar/index.md @@ -0,0 +1,295 @@ +--- +sidebarDepth: 2 +--- + +# Welcome 👋 + +[![release-badge]][release] [![license-badge]][license] [![contributions-badge]][contributions] [![semantic-release-badge]][semantic-release] [![crowdin-badge]][crowdin] [![discord-badge]][discord] [![stars-badge]][stars] + +Castopod is a free & open-source hosting platform made for podcasters who want +engage and interact with their audience. + +Castopod is easy to install and was built on top of +[CodeIgniter4](https://codeigniter.com/), a powerful PHP framework with a very +small footprint. + +::: info Status + +Castopod is currently in **beta** but already quite stable and used by +podcasters around the world! + +::: + +
    + Install +
    + +## Features + +- 🌱  Free & open-source (AGPL v3 License) +- 🔐  Focused on data sovereignty: your content, audience, and analytics + belong to you, and you only +- 🪄  Podcasting 2.0 features: GUID, locked, transcripts, funding, + chapters, location, persons, soundbites, … +- 💬  Built-in social network: + - 🚀  Castopod is part of the Fediverse, a decentralized social network + - ❤️  Create posts, share, favourite, and comment on episodes +- 📈  Built-in analytics: + - ⚖️  GDPR / CCPA / LGPD compliant + - 🪙  Standard IABv2 audience measurement + - 🏡  On-premises analytics, no third party involved +- 📢  Built-in marketing tools: + - ✅  SEO ready (open-graph meta-tags, JSON-LD, …) + - 📱  PWA: install as a standalone app + - 🎨  Customizable theme colors + - 🎬  Generate ready-to-share Video clips from episodes + - 🔉  Generate soundbites + - ▶️  Embeddable player, embed your episodes on any website +- 💸  Monetization: + - 🔗  Funding links + - 📲  listen-to-click ads + - 🤝  value4value / WebMonetization + - 💎  Premium podcasts +- 📡  Publish your episodes everywhere with RSS: + - 📱  On all indexes and apps: Podcast Index, Apple Podcasts, Spotify, + Google Podcasts, Deezer, Podcast Addict, Podfriend, … + - ⚡  Broadcast your episodes instantly with WebSub +- 📥  Podcast import: move your existing podcast into Castopod +- 📤  Move your podcast out of Castopod +- 🔀  Multi-tenant: host as many podcasts as you want +- 👥  Multi-user: add contributors and set roles +- 🌎  i18n support: translated in English, French, Polish, German, + Brazilian Portuguese & Spanish… with + [more to come](https://translate.castopod.org)! + +## Motivation + +The podcasting ecosystem is decentralized by nature: you can create your podcast +as an RSS file, publish it on the web and have it shared everywhere online. + +It is in fact one of the only media to have stayed this way for a long time. + +As usages are evolving, more and more people are getting into podcasts: whether +it is creators finding new ways to share their ideas, or listeners in the search +for better content. + +With podcasting becoming more widely used, some companies are trying to shift it +towards a more controlled and centralized medium. + +Castopod was created in an effort to provide an open and sustainable alternative +to hosting your podcasts, promoting decentralization to ensure that podcasters +creativity can express itself. + +This project is pushed by the open-source community, and specifically by the +[Fediverse](https://fediverse.party/en/fediverse/) and +[Podcasting 2.0](https://podcastindex.org/) movements. + +## Comparison with other solutions + +We believe that a solution is not necessarily right for everyone, it highly +depends on your needs. So, here are comparisons with other tools to help you to +gauge whether Castopod is the right fit for you. + +### Castopod vs Wordpress + +Castopod is often referred to as "the Wordpress for podcasts" because of the +similarities between the two. In some ways this is true. And actually, Castopod +was greatly inspired by the Wordpress ecosystem, seeing the ease of adoption +from the community and the number of websites running it. + +Just like Wordpress, Castopod is free & open source, built using PHP with a +MySQL database and is packaged in a way that you can easily install on most web +servers. + +Wordpress is a great way to create your website and extend it with plugins to +get what you want. It is a full fledged CMS that helps you get any type of +website online. + +On the other hand, Castopod is meant to address the podcasters needs +specifically, focusing on podcasting, and nothing else. You don't need any +plugin to get you started on your podcasting journey. + +This allows optimizing the processes specific to podcasting: ranging from the +creation of your podcasts and the publication of new episodes all the way to +broadcasting, marketing and analytics. + +Finally, depending on your needs, Wordpress and Castopod can even live side by +side as they share the same requirements! + +### Castopod vs Funkwhale + +Funkwhale is a self-hosted, modern free and open-source music server. Just as +Castopod, Funkwhale is on the fediverse, a decentralized social network allowing +interoperability between the two. + +Funkwhale was initially built around music. And later on, as the project +evolved, the ability to host podcasts was introduced. + +Unlike Funkwhale, Castopod has been designed and built around podcasting +exclusively. This allows easier implementation for features related to the +podcasting ecosystem, such as the podcasting 2.0 features (transcripts, +chapters, locations, persons, …). + +So, you should probably use Funkwhale if you want to host your music, and use +Castopod if you want to host your podcasts. + +### Castopod vs other podcast hosts + +There are many solutions for you to host your podcasts, some of which are really +great and [a lot of them](https://podcastindex.org/apps) are jumping into the +Podcasting 2.0 wagon just like Castopod! + +Each of these solutions differ from one another, you may compare with the +[list of features](#features). + +That being said, there are two main differences with other podcasting solutions: + +- Castopod can be self-hosted and is the only solution that allows you to keep + full control over what you produce. Also, as it is open-source, you can even + customize it as you wish. + +- Castopod is the only solution that currently integrates both a decentralized + social network with ActivityPub as well as many of the podcasting 2.0 + features, hoping to bridge the gap between the two. + +## Contributing + +Love Castopod and would like to help? Take a look at the following documentation +to get you started. + +### Code of conduct + +Castopod has adopted a Code of Conduct that we expect project participants to +adhere to. Please read the +[CODE_OF_CONDUCT manual](https://code.castopod.org/adaures/castopod/-/blob/beta/CODE_OF_CONDUCT.md) +so that you can understand what actions will and will not be tolerated. + +### Contributing guide + +Read our [contributing guide](./contributing/guidelines.md) to learn about our +development process, how to propose bugfixes and improvements, and how to build +and test your changes to Castopod. + +## Contributors ✨ + +Thanks goes to these wonderful people +([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Yassine Doghri

    💻 🐛 📖 👀 🚧 🖋 🎨 ️️️️♿️ 🌍 💬 🧑‍🏫 🚇 🤔 📆 📝

    Benjamin Bellamy

    💻 🐛 👀 🖋 🌍 💬 🚇 🤔 📝 📆 📢

    Ola Hneini

    💻 👀 📖 🚧 💬 🤔

    Romain de Laage

    💻 🚇 📖 🌍 🤔

    Lyonel Bernard

    🐛 💬 🔊 🤔

    Christopher Lagonick-Weitzel

    🐛 💬 🔊 🤔

    Ernesto Acosta

    🐛 🔊 🌍 💬 🤔

    Bastien Luneteau

    💻 🐛

    Cécile Ricordeau

    🎨

    Patryk Miś

    🌍

    Marcin Lewandowski

    🐛 🤔

    Sebastian Janik

    💻

    Patryk Karczmarczyk

    💻

    denis d

    🐛 🤔

    Douglas Kastle

    🐛 🤔

    cExplorer

    🐛 🌍

    ImaCrea

    🐛 🤔

    Jonas S

    💻

    LEFEBVRE Yann

    🐛

    Sebastian Späth

    🐛 🤔

    rocky III

    🐛

    Hermann Josef Eckl

    🐛

    Delhaye Cyrille

    🐛 🤔

    João Leandro

    🌍 🤔

    Angelos Chouvardas

    🌍

    Eivind

    🌍

    Ewen

    🌍 🤔

    forght

    🌍

    glottis0q

    🌍

    ButterflyOfFire

    🌍

    Lucian I. Last

    🌍

    LuuzViir

    🌍

    CTHTC

    🌍

    Russian Retro

    🌍

    Marek L'ach

    🌍

    GunChleoc

    🌍

    GabiSnow

    🌍

    bendaha

    🌍

    Samuel Roland

    🌍

    Dimitri Regnier

    🤔

    irithys

    🌍

    Sergi

    🌍

    ghose (XoseM)

    🌍
    + + + + + + +This project follows the +[all-contributors](https://github.com/all-contributors/all-contributors) +specification. Contributions of any kind welcome! + +## Contact + +You may reach us for help or ask any question you have on: + +- [Discord](https://castopod.org/discord) (for direct interaction with + developers and the community) +- [Issue tracker](https://code.castopod.org/adaures/castopod/-/issues) (for + feature requests & bug reports) + +Alternatively, you can follow us on social media platforms to get news about +Castopod: + +- [podlibre.social](https://podlibre.social/@Castopod) (Mastodon instance) +- [Twitter](https://twitter.com/castopod) +- [LinkedIn](https://linkedin.com/company/castopod) +- [Facebook](https://www.facebook.com/castopod) + +## Sponsors + +The ongoing development of Castopod is made possible with the support of its +backers. If you'd like to help, please consider +[sponsoring Castopod's development](https://opencollective.com/castopod/contribute). + +
    + Ad Aures Logo + NLnet Logo +
    + +## License + +[GNU Affero General Public License v3.0](https://choosealicense.com/licenses/agpl-3.0/) + +Copyright © 2020-present, [Ad Aures](https://adaures.com/). +https://img.shields.io/gitlab/v/release/2?color=brightgreen&gitlab_url=https%3A%2F%2Fcode.castopod.org%2F&include_prereleases&label=release +https://img.shields.io/github/license/ad-aures/castopod?color=blue +https://img.shields.io/badge/contributions-welcome-brightgreen.svg +https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg +https://img.shields.io/github/stars/ad-aures/castopod?style=social + +[release]: https://code.castopod.org/adaures/castopod/-/releases +[license]: https://code.castopod.org/adaures/castopod/-/blob/beta/LICENSE.md +[contributions]: https://code.castopod.org/adaures/castopod/-/issues +[semantic-release]: https://github.com/semantic-release/semantic-release +[discord]: https://castopod.org/discord +[stars]: https://github.com/ad-aures/castopod/stargazers +[crowdin]: https://translate.castopod.org/project/castopod diff --git a/docs/src/assets/images/sponsors/adaures.svg b/docs/src/assets/images/sponsors/adaures.svg deleted file mode 100644 index aded8d98..00000000 --- a/docs/src/assets/images/sponsors/adaures.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/src/assets/images/sponsors/nlnet.svg b/docs/src/assets/images/sponsors/nlnet.svg deleted file mode 100644 index 5fa21021..00000000 --- a/docs/src/assets/images/sponsors/nlnet.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/src/br/contributing/_category_.json b/docs/src/br/contributing/_category_.json new file mode 100644 index 00000000..e12f1ce5 --- /dev/null +++ b/docs/src/br/contributing/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Contributing", + "position": 3 +} diff --git a/docs/src/br/contributing/guidelines.md b/docs/src/br/contributing/guidelines.md new file mode 100644 index 00000000..1a53c89e --- /dev/null +++ b/docs/src/br/contributing/guidelines.md @@ -0,0 +1,154 @@ +--- +title: Guidelines +--- + +# Contributing to Castopod + +Love Castopod and want to help? Thanks so much, there's something to do for +everybody! + +Please take a moment to review this document in order to make the contribution +process easy and effective for everyone involved. + +Following these guidelines helps to communicate that you respect the time of the +developers managing and developing this open source project. In return, they +should reciprocate that respect in addressing your issue or assessing patches +and features. + +::: info Note + +**Any** contribution made on a repository other than +[the original repository](https://code.castopod.org/adaures/castopod) will not +be accepted. + +::: + +## Using the issue tracker + +The [issue tracker](https://code.castopod.org/adaures/castopod/-/issues) is the +preferred channel for [bug reports](#bug-reports), +[features requests](#feature-requests) and +[submitting pull requests](#pull-requests). + +## ⚠️ Security issues and vulnerabilities + +If you encounter any security issue or vulnerability in the Castopod source, +please contact us directly by email at +[security@castopod.org](mailto:security@castopod.org) + +## Bug reports + +A bug is a _demonstrable problem_ that is caused by the code in the repository. +Good bug reports are extremely helpful - thank you! + +Guidelines for bug reports: + +1. **Use the issue search** — check if the issue has already been + reported. + +2. **Check if the issue has been fixed** — try to reproduce it using the + latest `main` branch in the repository. + +3. **Isolate the problem** — ideally create a + [reduced test case](https://css-tricks.com/reduced-test-cases/) and a live + example. + +A good bug report shouldn't leave others needing to chase you up for more +information. Please try to be as detailed as possible in your report. What is +your environment? What steps will reproduce the issue? What browser(s) and OS +experience the problem? What would you expect to be the outcome? All these +details will help people to fix any potential bugs. + +> [Issue templates](https://docs.gitlab.com/ee/user/project/description_templates.html#using-the-templates) +> have been created for this project. You may use them to help you follow those +> guidelines. + +## Feature requests + +Feature requests are welcome. But take a moment to find out whether your idea +fits with the scope and aims of the project. It's up to _you_ to make a strong +case to convince the project's developers of the merits of this feature. Please +provide as much detail and context as possible. + +## Pull requests + +Good pull requests - patches, improvements, new features - are a fantastic help. +They should remain focused in scope and avoid containing unrelated commits. + +**Please ask first** before embarking on any significant pull request (e.g. +implementing features, refactoring code, porting to a different language), +otherwise you risk spending a lot of time working on something that the +project's developers might not want to merge into the project. + +Please adhere to the coding conventions used throughout a project (indentation, +accurate comments, etc.) and any other requirements (such as test coverage). + +Adhering to the following process is the best way to get your work included in +the project: + +1. [Fork](https://docs.gitlab.com/ee/gitlab-basics/fork-project.html) the + project, clone your fork, and configure the remotes: + +```bash +# Clone your fork of the repo into the current directory +git clone https://code.castopod.org//castopod.git + +# Navigate to the newly cloned directory +cd castopod + +# Assign the original repo to a remote called "upstream" +git remote add upstream https://code.castopod.org/adaures/castopod.git +``` + +2. If you cloned a while ago, get the latest changes from upstream: + +```bash +git checkout main +git pull upstream main +``` + +3. Create a new topic branch (off the `main` branch) to contain your feature, + change, or fix: + +```bash +git checkout -b +``` + +4. Commit your changes in logical chunks. Please adhere to these + [git commit message guidelines](https://conventionalcommits.org/) or your + code is unlikely be merged into the main project. Use Git's + [interactive rebase](https://help.github.com/articles/about-git-rebase/) + feature to tidy up your commits before making them public. + +5. Locally merge (or rebase) the upstream dev branch into your topic branch: + +```bash +git pull [--rebase] upstream main +``` + +6. Push your topic branch up to your fork: + +```bash +git push origin +``` + +7. [Open a Pull Request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html#new-merge-request-from-a-fork) + with a clear title and description. + +**IMPORTANT**: By submitting a patch, you agree to allow the project owners to +license your work under the terms of the +[GNU AGPLv3](https://code.castopod.org/adaures/castopod/-/blob/main/LICENSE). + +## Collaborating guidelines + +There are few basic rules to ensure high quality of the project: + +- Before merging, a PR requires at least two approvals from the collaborators + unless it's an architectural change, a large feature, etc. If it is, then at + least 50% of the core team have to agree to merge it, with every team member + having a full veto right. (i.e. every single one can block any PR) +- A PR should remain open for at least two days before merging (does not apply + for trivial contributions like fixing a typo). This way everyone has enough + time to look into it. + +You are always welcome to discuss and propose improvements to this guideline. diff --git a/docs/src/br/contributing/setup-development.md b/docs/src/br/contributing/setup-development.md new file mode 100644 index 00000000..6aafb50b --- /dev/null +++ b/docs/src/br/contributing/setup-development.md @@ -0,0 +1,423 @@ +--- +title: Development setup +sidebarDepth: 3 +--- + +# Setup your development environment + +## Introduction + +Castopod is a web app based on the `php` framework +[CodeIgniter 4](https://codeigniter.com). + +We use [Docker](https://www.docker.com/) quickly setup a dev environment. A +`docker-compose.yml` and `Dockerfile` are included in the project's root folder +to help you kickstart your contribution. + +> You don't need any prior knowledge of Docker to follow the next steps. +> However, if you wish to use your own environment, feel free to do so! + +## Setup instructions + +### 1. Pre-requisites + +0. Install [docker](https://docs.docker.com/get-docker). + +1. Clone Castopod project by running: + + ```bash + git clone https://code.castopod.org/adaures/castopod.git + ``` + +2. Create a `.env` file with the minimum required config to connect the app to + the database and use redis as a cache handler: + + ```ini + CI_ENVIRONMENT="development" + # If set to development, you must run `npm run dev` to start the static assets server + vite.environment="development" + + # By default, this is set to true in the app config. + # For development, this must be set to false as it is + # on a local environment + app.forceGlobalSecureRequests=false + + app.baseURL="http://localhost:8080/" + app.mediaBaseURL="http://localhost:8080/" + + admin.gateway="cp-admin" + auth.gateway="cp-auth" + + database.default.hostname="mariadb" + database.default.database="castopod" + database.default.username="castopod" + database.default.password="castopod" + + cache.handler="redis" + cache.redis.host = "redis" + + # You may not want to use redis as your cache handler + # Comment/remove the two lines above and uncomment + # the next line for file caching. + #cache.handler="file" + ``` + + > _NB._ You can tweak your environment by setting more environment variables + > in your custom `.env` file. See the `env` for examples or the + > [CodeIgniter4 User Guide](https://codeigniter.com/user_guide/index.html) + > for more info. + +3. (for docker desktop) Add the repository you've cloned to docker desktop's + `Settings` > `Resources` > `File Sharing` + +### 2. (recommended) Develop inside the app Container with VSCode + +If you're working in VSCode, you can take advantage of the `.devcontainer/` +folder. It defines a development environment (dev container) with preinstalled +requirements and VSCode extensions so you don't have to worry about them. All +required services will be loaded automagically! 🪄 + +1. Install the VSCode extension + [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) +2. `Ctrl/Cmd + Shift + P` > `Open in container` + + > The VSCode window will reload inside the dev container. Expect several + > minutes during first load as it is building all necessary services. + + **Note**: The dev container will start by running Castopod's php server. + During development, you will have to start [Vite](https://vitejs.dev)'s dev + server for compiling the typescript code and styles: + + ```bash + # run Vite dev server + npm run dev + ``` + + If there is any issue with the php server not running, you can restart them + using the following commands: + + ```bash + # run Castopod server + php spark serve - 0.0.0.0 + ``` + +3. You're all set! 🎉 + + You're now **inside the dev container**, you may use the VSCode console + (`Terminal` > `New Terminal`) to run any command: + + ```bash + # PHP is installed + php -v + + # Composer is installed + composer -V + + # npm is installed + npm -v + + # git is installed + git version + ``` + +For more info, see +[VSCode Remote Containers](https://code.visualstudio.com/docs/remote/containers) + +### 3. Start hacking + +You're all set! Start working your magic by updating the project's files! Help +yourself to the +[CodeIgniter4 User Guide](https://codeigniter.com/user_guide/index.html) for +more insights. + +To see your changes, go to: + +- `http://localhost:8080/` for the Castopod app +- `http://localhost:8888/` for the phpmyadmin interface: + + - username: **castopod** + - password: **castopod** + +### 2-alt. Develop outside the app container + +You do not wish to use the VSCode devcontainer? No problem! + +1. Start docker containers manually: + + Go to project's root folder and run: + + ```bash + # starts all services declared in docker-compose.yml file + # -d option starts the containers in the background + docker-compose up -d + + # See all running processes (you should see 3 processes running) + docker-compose ps + + # Alternatively, you can check all docker processes + docker ps -a + + ``` + + > The `docker-compose up -d` command will boot 4 containers in the + > background: + > + > - `castopod_app`: a php based container with Castopod requirements + > installed + > - `castopod_redis`: a [redis](https://redis.io/) database to handle queries + > and pages caching + > - `castopod_mariadb`: a [mariadb](https://mariadb.org/) server for + > persistent data + > - `castopod_phpmyadmin`: a phpmyadmin server to visualize the mariadb + > database. + +2. Run any command inside the containers by prefixing them with + `docker-compose run --rm app`: + + ```bash + # use PHP + docker-compose run --rm app php -v + + # use Composer + docker-compose run --rm app composer -V + + # use npm + docker-compose run --rm app npm -v + + # use git + docker-compose run --rm app git version + ``` + +--- + +## Going Further + +### Install Castopod's dependencies + +1. Install php dependencies with [Composer](https://getcomposer.org/) + + ```bash + composer install + ``` + + ::: info Note + + The php dependencies aren't included in the repository. Composer will check + the `composer.json` and `composer.lock` files to download the packages with + the right versions. The dependencies will live under the `vendor/` folder. + For more info, check out the + [Composer documentation](https://getcomposer.org/doc/). + + ::: + +2. Install javascript dependencies with [npm](https://www.npmjs.com/) + + ```bash + npm install + ``` + + ::: info Note + + The javascript dependencies aren't included in the repository. Npm will check + the `package.json` and `package.lock` files to download the packages with the + right versions. The dependencies will live under the `node_module` folder. + For more info, check out the [NPM documentation](https://docs.npmjs.com/). + + ::: + +3. Generate static assets: + + ```bash + # build all static assets at once + npm run build:static + + # build specific assets + npm run build:icons + npm run build:svg + ``` + + ::: info Note + + The static assets generated live under the `public/assets` folder, it + includes javascript, styles, images, fonts, icons and svg files. + + ::: + +### Initialize and populate database + +::: tip Tip + +You may skip this section if you go through the install wizard (go to +`/cp-install`). + +::: + +1. Build the database with the migrate command: + + ```bash + # loads the database schema during first migration + php spark migrate -all + ``` + + You may need to undo the migration (rollback): + + ```bash + # rolls back database schema (deletes all tables and their content) + php spark migrate:rollback + ``` + +2. Populate the database with the required data: + + ```bash + # Populates all required data + php spark db:seed AppSeeder + ``` + + You may choose to add data separately: + + ```bash + # Populates all categories + php spark db:seed CategorySeeder + + # Populates all Languages + php spark db:seed LanguageSeeder + + # Populates all podcasts platforms + php spark db:seed PlatformSeeder + + # Populates all Authentication data (roles definition…) + php spark db:seed AuthSeeder + ``` + +3. (optionnal) Populate the database with test data: + + - Populate test data (login: admin / password: AGUehL3P) + + ```bash + php spark db:seed TestSeeder + ``` + + - Populate with fake podcast analytics: + + ```bash + php spark db:seed FakePodcastsAnalyticsSeeder + ``` + + - Populate with fake website analytics: + + ```bash + php spark db:seed FakeWebsiteAnalyticsSeeder + ``` + + TestSeeder will add an active superadmin user with the following credentials: + + - username: **admin** + - password: **AGUehL3P** + +### Useful docker / docker-compose commands + +- Monitor the app container: + +```bash +docker-compose logs --tail 50 --follow --timestamps app +``` + +- Interact with redis server using included redis-cli command: + +```bash +docker exec -it castopod_redis redis-cli +``` + +- Monitor the redis container: + +```bash +docker-compose logs --tail 50 --follow --timestamps redis +``` + +- Monitor the mariadb container: + +```bash +docker-compose logs --tail 50 --follow --timestamps mariadb +``` + +- Monitor the phpmyadmin container: + +```bash +docker-compose logs --tail 50 --follow --timestamps phpmyadmin +``` + +- Restart docker containers: + +```bash +docker-compose restart +``` + +- Destroy all containers, opposite of `up` command: + +```bash +docker-compose down +``` + +- Rebuild app container: + +```bash +docker-compose build app +``` + +Check [docker](https://docs.docker.com/engine/reference/commandline/docker/) and +[docker-compose](https://docs.docker.com/compose/reference/) documentations for +more insights. + +## Known issues + +### Allocation failed - JavaScript heap out of memory + +This happens when running `npm install`. + +👉 By default, docker might not have access to enough RAM. Allocate more memory +and run `npm install` again. + +### (Linux) Files created inside container are attributed to root locally + +You may use Linux user namespaces to fix this on your machine: + +::: info Note + +Replace "username" with your local username + +::: + +1. Go to `/etc/docker/daemon.json` and add: + + ```json + { + "userns-remap": "username" + } + ``` + +2. Configure the subordinate uid/guid: + + ```bash + # in /etc/subuid + username:1000:1 + username:100000:65536 + ``` + + ```bash + # in /etc/subgid + username:1000:1 + username:100000:65536 + ``` + +3. Restart docker: + + ```bash + sudo systemctl restart docker + ``` + +4. That's it! Now, the root user in the container will be mapped to the user on + your local machine, no more permission issues! 🎉 + +You can check +[this great article](https://www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/) +to know more about how it works. diff --git a/docs/src/br/getting-started/_category_.json b/docs/src/br/getting-started/_category_.json new file mode 100644 index 00000000..877a378f --- /dev/null +++ b/docs/src/br/getting-started/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Getting Started", + "position": 2 +} diff --git a/docs/src/br/getting-started/docker.md b/docs/src/br/getting-started/docker.md new file mode 100644 index 00000000..ededc582 --- /dev/null +++ b/docs/src/br/getting-started/docker.md @@ -0,0 +1,148 @@ +--- +title: Official Docker images +sidebarDepth: 3 +--- + +# Official Docker images + +Castopod pushes 2 Docker images to the Docker Hub during its automated build +process: + +- [**`castopod/app`**](https://hub.docker.com/r/castopod/app): the app bundle + with all of Castopod dependencies +- [**`castopod/web-server`**](https://hub.docker.com/r/castopod/web-server): an + Nginx configuration for Castopod + +Additionally, Castopod requires a MySQL-compatible database. A Redis database +can be added as a cache handler. + +## Supported tags + +- `develop` [unstable], latest development branch build +- `beta` [stable], latest beta version build +- `1.0.0-beta.x` [stable], specific beta version build (since `1.0.0-beta.22`) + +## Example usage + +1. Install [docker](https://docs.docker.com/get-docker/) and + [docker-compose](https://docs.docker.com/compose/install/) +2. Create a `docker-compose.yml` file with the following: + + ```yml + version: "3.7" + + services: + app: + image: castopod/app:beta + container_name: "castopod-app" + volumes: + - castopod-media:/opt/castopod/public/media + environment: + MYSQL_DATABASE: castopod + MYSQL_USER: castopod + MYSQL_PASSWORD: changeme + CP_BASEURL: "http://castopod.example.com" + CP_ANALYTICS_SALT: changeme + CP_CACHE_HANDLER: redis + CP_REDIS_HOST: redis + networks: + - castopod-app + - castopod-db + restart: unless-stopped + + web-server: + image: castopod/web-server:beta + container_name: "castopod-web-server" + volumes: + - castopod-media:/var/www/html/media + networks: + - castopod-app + ports: + - 8080:80 + restart: unless-stopped + + mariadb: + image: mariadb:10.5 + container_name: "castopod-mariadb" + networks: + - castopod-db + volumes: + - castopod-db:/var/lib/mysql + environment: + MYSQL_ROOT_PASSWORD: changeme + MYSQL_DATABASE: castopod + MYSQL_USER: castopod + MYSQL_PASSWORD: changeme + restart: unless-stopped + + redis: + image: redis:7.0-alpine + container_name: "castopod-redis" + volumes: + - castopod-cache:/data + networks: + - castopod-app + + volumes: + castopod-media: + castopod-db: + castopod-cache: + + networks: + castopod-app: + castopod-db: + ``` + + You have to adapt some variables to your needs (e.g. `CP_BASEURL`, + `MYSQL_ROOT_PASSWORD`, `MYSQL_PASSWORD` and `CP_ANALYTICS_SALT`). + +3. Setup a reverse proxy for TLS (SSL/HTTPS) + + TLS is mandatory for ActivityPub to work. This job can easily be handled by + a reverse proxy, for example with [Caddy](https://caddyserver.com/): + + ``` + #castopod + castopod.example.com { + reverse_proxy localhost:8080 + } + ``` + +4. Run `docker-compose up -d`, wait for it to initialize and head on to + `https://castopod.example.com/cp-install` to finish setting up Castopod! + +5. You're all set, start podcasting! 🎙️🚀 + +## Environment Variables + +- **castopod/app** + + | Variable name | Type (`default`) | Default | + | ---------------------------- | ----------------------- | ---------------- | + | **`CP_BASEURL`** | string | `undefined` | + | **`CP_MEDIA_BASEURL`** | ?string | `CP_BASEURL` | + | **`CP_ADMIN_GATEWAY`** | ?string | `"cp-admin"` | + | **`CP_AUTH_GATEWAY`** | ?string | `"cp-auth"` | + | **`CP_ANALYTICS_SALT`** | string | `undefined` | + | **`CP_DATABASE_HOSTNAME`** | ?string | `"mariadb"` | + | **`CP_DATABASE_NAME`** | ?string | `MYSQL_DATABASE` | + | **`CP_DATABASE_USERNAME`** | ?string | `MYSQL_USER` | + | **`CP_DATABASE_PASSWORD`** | ?string | `MYSQL_PASSWORD` | + | **`CP_DATABASE_PREFIX`** | ?string | `"cp_"` | + | **`CP_CACHE_HANDLER`** | [`"file"` or `"redis"`] | `"file"` | + | **`CP_REDIS_HOST`** | ?string | `"localhost"` | + | **`CP_REDIS_PASSWORD`** | ?string | `null` | + | **`CP_REDIS_PORT`** | ?number | `6379` | + | **`CP_REDIS_DATABASE`** | ?number | `0` | + | **`CP_EMAIL_SMTP_HOST`** | ?string | `undefined` | + | **`CP_EMAIL_FROM`** | ?string | `undefined` | + | **`CP_EMAIL_SMTP_USERNAME`** | ?string | `"localhost"` | + | **`CP_EMAIL_SMTP_PASSWORD`** | ?string | `null` | + | **`CP_EMAIL_SMTP_PORT`** | ?number | `25` | + | **`CP_EMAIL_SMTP_CRYPTO`** | [`"tls"` or `"ssl"`] | `"tls"` | + +- **castopod/web-server** + + | Variable name | Type | Default | + | --------------------- | ------- | ------- | + | **`CP_APP_HOSTNAME`** | ?string | `"app"` | diff --git a/docs/src/content/docs/da/getting-started/install.mdx b/docs/src/br/getting-started/install.md similarity index 53% rename from docs/src/content/docs/da/getting-started/install.mdx rename to docs/src/br/getting-started/install.md index 316cd588..dac8517e 100644 --- a/docs/src/content/docs/da/getting-started/install.mdx +++ b/docs/src/br/getting-started/install.md @@ -1,23 +1,31 @@ --- -title: How to install Castopod? +title: Staliañ +sidebarDepth: 3 --- -import { Aside } from "@astrojs/starlight/components"; +# Penaos staliañ Castopod? Castopod was thought-out to be easy to install. Whether using dedicated or shared hosting, you can install it on most PHP-MySQL compatible web servers. +::: tip Note + +We've released official Docker images for Castopod! + +If you prefer using Docker, you may skip this and go straight to the +[docker documentation](./docker.md) for Castopod. + +::: + ## Requirements -- PHP v8.5 or higher -- MySQL version 8.4 or higher or MariaDB version 11.4 or higher +- PHP v8.0 or higher +- MySQL version 5.7 or higher or MariaDB version 10.2 or higher - HTTPS support -- An [ntp-synced clock](https://wiki.debian.org/NTP) to validate federation's - incoming requests -### PHP v8.5 or higher +### PHP v8.0 or higher -PHP version 8.5 or higher is required, with the following extensions installed: +PHP version 8.0 or higher is required, with the following extensions installed: - [intl](https://php.net/manual/en/intl.requirements.php) - [libcurl](https://php.net/manual/en/curl.requirements.php) @@ -36,6 +44,14 @@ Additionally, make sure that the following extensions are enabled in your PHP: > We recommend using [MariaDB](https://mariadb.org). +::: warning Warning + +Castopod only works with supported MySQL 5.7 or higher compatible databases. It +will break with the previous MySQL v5.6 for example as its end of life was on +February 5, 2021. + +::: + You will need the server hostname, database name, username and password to complete the installation process. If you do not have these, please contact your server administrator. @@ -76,18 +92,29 @@ want to generate Video Clips. The following extensions must be installed: 4. Add **cron tasks** on your web server for various background processes (replace the paths accordingly): + - For social features to work properly, this task is used to broadcast social + activities to your followers on the fediverse: + ```bash - * * * * * /path/to/php /path/to/castopod/spark tasks:run >> /dev/null 2>&1 + * * * * * /path/to/php /path/to/castopod/public/index.php scheduled-activities ``` - **Note** - If you do not add this cron task, the following Castopod features - will not work: - - Importing a podcast from an existing RSS feed - - Broadcasting social activities to your followers in the fediverse - - Broadcasting episodes to open hubs using - [WebSub](https://en.wikipedia.org/wiki/WebSub) - - Generating video clips - - [requires FFmpeg](#optional-ffmpeg-v418-or-higher-for-video-clips) + - For having your episodes be broadcasted on open hubs upon publication using + [WebSub](https://en.wikipedia.org/wiki/WebSub): + + ```bash + * * * * * /usr/local/bin/php /castopod/public/index.php scheduled-websub-publish + ``` + + - For Video Clips to be created (see + [FFmpeg requirements](#ffmpeg-v418-or-higher-for-video-clips)): + + ```bash + * * * * * /path/to/php /path/to/castopod/public/index.php scheduled-video-clips + ``` + + > These tasks run **every minute**. You may set the frequency depending on + > your needs: every 5, 10 minutes or more. ### (recommended) Install Wizard @@ -96,31 +123,13 @@ want to generate Video Clips. The following extensions must be installed: 2. Follow the instructions on your screen. 3. Start podcasting! - - -### Using CLI - -1. Create a `.env` file in the package root based on the `.env.example` file. - -2. Initialize the database using: - - ```sh - php spark install:init-database - ``` - -3. Create the superadmin user using: - - ```sh - php spark install:create-superadmin - ``` - -4. Head on to your admin gateway to start podcasting! +::: ### Email/SMTP setup @@ -151,50 +160,6 @@ email.SMTPPass="your_smtp_password" | **`SMTPPort`** | number | `25` | | **`SMTPCrypto`** | [`"tls"` or `"ssl"`] | `"tls"` | -### Media storage - -By default, files are saved to the `public/media` folder using the file system. -If you need to relocate the `media` folder to a different location, you can -specify it in your `.env` file as shown below: - -```ini -# […] - -media.root="media" -media.storage="/mnt/storage" -``` - -In this example, the files will be saved to the /mnt/storage/media folder. Make -sure to also update your web server configuration to reflect this change. - -### S3 - -If you prefer storing your media files on an S3 compatible storage, you may -specify it in your `.env`: - -```ini -# […] - -media.fileManager="s3" -media.s3.endpoint="your_s3_host" -media.s3.key="your_s3_key" -media.s3.secret="your_s3_secret" -media.s3.region="your_s3_region" -``` - -#### S3 config options - -| Variable name | Type | Default | -| ----------------------- | ------- | ----------- | -| **`endpoint`** | string | `undefined` | -| **`key`** | string | `undefined` | -| **`secret`** | string | `undefined` | -| **`region`** | string | `undefined` | -| **`bucket`** | string | `castopod` | -| **`protocol`** | number | `undefined` | -| **`pathStyleEndpoint`** | boolean | `false` | -| **`keyPrefix`** | string | `undefined` | - ## Community packages If you don't want to bother with installing Castopod manually, you may use one @@ -208,35 +173,13 @@ self-hosting for you. diff --git a/docs/src/content/docs/ar/getting-started/security.mdx b/docs/src/br/getting-started/security.md similarity index 95% rename from docs/src/content/docs/ar/getting-started/security.mdx rename to docs/src/br/getting-started/security.md index c039493c..e205698d 100644 --- a/docs/src/content/docs/ar/getting-started/security.mdx +++ b/docs/src/br/getting-started/security.md @@ -1,7 +1,9 @@ --- -title: Security concerns +title: Security --- +# Security concerns + Castopod is built on top of [CodeIgniter4](https://codeigniter.com/), a PHP framework that encourages [good security practices](https://codeigniter.com/user_guide/concepts/security.html). diff --git a/docs/src/content/docs/it/getting-started/update.mdx b/docs/src/br/getting-started/update.md similarity index 70% rename from docs/src/content/docs/it/getting-started/update.mdx rename to docs/src/br/getting-started/update.md index d0bc9d57..51e372ee 100644 --- a/docs/src/content/docs/it/getting-started/update.mdx +++ b/docs/src/br/getting-started/update.md @@ -1,69 +1,56 @@ --- -title: How to update Castopod? +title: Update +sidebarDepth: 3 --- -import { Aside } from "@astrojs/starlight/components"; +# How to update Castopod? After installing Castopod, you may want to update your instance to the latest version in order to enjoy the latest features ✨, bug fixes 🐛 and performance improvements ⚡. -## Update instructions +## Automatic update instructions -0. ⚠️ Before any update, we highly recommend you backup your Castopod files and - database. - - cf. - [Should I make a backup before updating?](#should-i-make-a-backup-before-updating) +> Coming soon... 👀 + +## Manual update instructions 1. Go to the [releases page](https://code.castopod.org/adaures/castopod/-/releases) and see if your instance is up to date with the latest Castopod version + - cf. [Where can I find my Castopod version?](#where-can-i-find-my-castopod-version) 2. Download the latest release package named `Castopod Package`, you may choose between the `zip` or `tar.gz` archives + - ⚠️ Make sure you download the Castopod Package and **NOT** the Source Code - - Note that you can also download the latest package from - [castopod.org](https://castopod.org/) 3. On your server: + - Remove all files except `.env` and `public/media` - Copy the new files from the downloaded package into your server - + ::: -4. Update your database schema from your `Castopod Admin` > `About` page or by - running: +4. Releases may come with additional update instructions (see + [releases page](https://code.castopod.org/adaures/castopod/-/releases)). They + are usually database migration scripts in `.sql` format to update your + database schema. - ```bash - php spark castopod:database-update - ``` - -5. Clear your cache from your `Castopod Admin` > `Settings` > `general` > - `Housekeeping` + - 👉 Make sure you run the scripts on your phpmyadmin panel or using command + line to update the database along with the package files! + - I haven't updated my instance in a long time… What should I do? +5. If you are using redis, clear your cache. 6. ✨ Enjoy your fresh instance, you're all done! - - -## Fully Automated updates - -> Coming soon... 👀 - ## Frequently asked questions (FAQ) ### Where can I find my Castopod version? diff --git a/docs/src/br/index.md b/docs/src/br/index.md new file mode 100644 index 00000000..d89daccb --- /dev/null +++ b/docs/src/br/index.md @@ -0,0 +1,295 @@ +--- +sidebarDepth: 2 +--- + +# Welcome 👋 + +[![release-badge]][release] [![license-badge]][license] [![contributions-badge]][contributions] [![semantic-release-badge]][semantic-release] [![crowdin-badge]][crowdin] [![discord-badge]][discord] [![stars-badge]][stars] + +Castopod is a free & open-source hosting platform made for podcasters who want +engage and interact with their audience. + +Castopod is easy to install and was built on top of +[CodeIgniter4](https://codeigniter.com/), a powerful PHP framework with a very +small footprint. + +::: info Status + +Castopod is currently in **beta** but already quite stable and used by +podcasters around the world! + +::: + +
    + Install +
    + +## Features + +- 🌱  Free & open-source (AGPL v3 License) +- 🔐  Focused on data sovereignty: your content, audience, and analytics + belong to you, and you only +- 🪄  Podcasting 2.0 features: GUID, locked, transcripts, funding, + chapters, location, persons, soundbites, … +- 💬  Built-in social network: + - 🚀  Castopod is part of the Fediverse, a decentralized social network + - ❤️  Create posts, share, favourite, and comment on episodes +- 📈  Built-in analytics: + - ⚖️  GDPR / CCPA / LGPD compliant + - 🪙  Standard IABv2 audience measurement + - 🏡  On-premises analytics, no third party involved +- 📢  Built-in marketing tools: + - ✅  SEO ready (open-graph meta-tags, JSON-LD, …) + - 📱  PWA: install as a standalone app + - 🎨  Customizable theme colors + - 🎬  Generate ready-to-share Video clips from episodes + - 🔉  Generate soundbites + - ▶️  Embeddable player, embed your episodes on any website +- 💸  Monetization: + - 🔗  Funding links + - 📲  listen-to-click ads + - 🤝  value4value / WebMonetization + - 💎  Premium podcasts +- 📡  Publish your episodes everywhere with RSS: + - 📱  On all indexes and apps: Podcast Index, Apple Podcasts, Spotify, + Google Podcasts, Deezer, Podcast Addict, Podfriend, … + - ⚡  Broadcast your episodes instantly with WebSub +- 📥  Podcast import: move your existing podcast into Castopod +- 📤  Move your podcast out of Castopod +- 🔀  Multi-tenant: host as many podcasts as you want +- 👥  Multi-user: add contributors and set roles +- 🌎  i18n support: translated in English, French, Polish, German, + Brazilian Portuguese & Spanish… with + [more to come](https://translate.castopod.org)! + +## Motivation + +The podcasting ecosystem is decentralized by nature: you can create your podcast +as an RSS file, publish it on the web and have it shared everywhere online. + +It is in fact one of the only media to have stayed this way for a long time. + +As usages are evolving, more and more people are getting into podcasts: whether +it is creators finding new ways to share their ideas, or listeners in the search +for better content. + +With podcasting becoming more widely used, some companies are trying to shift it +towards a more controlled and centralized medium. + +Castopod was created in an effort to provide an open and sustainable alternative +to hosting your podcasts, promoting decentralization to ensure that podcasters +creativity can express itself. + +This project is pushed by the open-source community, and specifically by the +[Fediverse](https://fediverse.party/en/fediverse/) and +[Podcasting 2.0](https://podcastindex.org/) movements. + +## Comparison with other solutions + +We believe that a solution is not necessarily right for everyone, it highly +depends on your needs. So, here are comparisons with other tools to help you to +gauge whether Castopod is the right fit for you. + +### Castopod vs Wordpress + +Castopod is often referred to as "the Wordpress for podcasts" because of the +similarities between the two. In some ways this is true. And actually, Castopod +was greatly inspired by the Wordpress ecosystem, seeing the ease of adoption +from the community and the number of websites running it. + +Just like Wordpress, Castopod is free & open source, built using PHP with a +MySQL database and is packaged in a way that you can easily install on most web +servers. + +Wordpress is a great way to create your website and extend it with plugins to +get what you want. It is a full fledged CMS that helps you get any type of +website online. + +On the other hand, Castopod is meant to address the podcasters needs +specifically, focusing on podcasting, and nothing else. You don't need any +plugin to get you started on your podcasting journey. + +This allows optimizing the processes specific to podcasting: ranging from the +creation of your podcasts and the publication of new episodes all the way to +broadcasting, marketing and analytics. + +Finally, depending on your needs, Wordpress and Castopod can even live side by +side as they share the same requirements! + +### Castopod vs Funkwhale + +Funkwhale is a self-hosted, modern free and open-source music server. Just as +Castopod, Funkwhale is on the fediverse, a decentralized social network allowing +interoperability between the two. + +Funkwhale was initially built around music. And later on, as the project +evolved, the ability to host podcasts was introduced. + +Unlike Funkwhale, Castopod has been designed and built around podcasting +exclusively. This allows easier implementation for features related to the +podcasting ecosystem, such as the podcasting 2.0 features (transcripts, +chapters, locations, persons, …). + +So, you should probably use Funkwhale if you want to host your music, and use +Castopod if you want to host your podcasts. + +### Castopod vs other podcast hosts + +There are many solutions for you to host your podcasts, some of which are really +great and [a lot of them](https://podcastindex.org/apps) are jumping into the +Podcasting 2.0 wagon just like Castopod! + +Each of these solutions differ from one another, you may compare with the +[list of features](#features). + +That being said, there are two main differences with other podcasting solutions: + +- Castopod can be self-hosted and is the only solution that allows you to keep + full control over what you produce. Also, as it is open-source, you can even + customize it as you wish. + +- Castopod is the only solution that currently integrates both a decentralized + social network with ActivityPub as well as many of the podcasting 2.0 + features, hoping to bridge the gap between the two. + +## Contributing + +Love Castopod and would like to help? Take a look at the following documentation +to get you started. + +### Code of conduct + +Castopod has adopted a Code of Conduct that we expect project participants to +adhere to. Please read the +[CODE_OF_CONDUCT manual](https://code.castopod.org/adaures/castopod/-/blob/beta/CODE_OF_CONDUCT.md) +so that you can understand what actions will and will not be tolerated. + +### Contributing guide + +Read our [contributing guide](./contributing/guidelines.md) to learn about our +development process, how to propose bugfixes and improvements, and how to build +and test your changes to Castopod. + +## Contributors ✨ + +Thanks goes to these wonderful people +([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Yassine Doghri

    💻 🐛 📖 👀 🚧 🖋 🎨 ️️️️♿️ 🌍 💬 🧑‍🏫 🚇 🤔 📆 📝

    Benjamin Bellamy

    💻 🐛 👀 🖋 🌍 💬 🚇 🤔 📝 📆 📢

    Ola Hneini

    💻 👀 📖 🚧 💬 🤔

    Romain de Laage

    💻 🚇 📖 🌍 🤔

    Lyonel Bernard

    🐛 💬 🔊 🤔

    Christopher Lagonick-Weitzel

    🐛 💬 🔊 🤔

    Ernesto Acosta

    🐛 🔊 🌍 💬 🤔

    Bastien Luneteau

    💻 🐛

    Cécile Ricordeau

    🎨

    Patryk Miś

    🌍

    Marcin Lewandowski

    🐛 🤔

    Sebastian Janik

    💻

    Patryk Karczmarczyk

    💻

    denis d

    🐛 🤔

    Douglas Kastle

    🐛 🤔

    cExplorer

    🐛 🌍

    ImaCrea

    🐛 🤔

    Jonas S

    💻

    LEFEBVRE Yann

    🐛

    Sebastian Späth

    🐛 🤔

    rocky III

    🐛

    Hermann Josef Eckl

    🐛

    Delhaye Cyrille

    🐛 🤔

    João Leandro

    🌍 🤔

    Angelos Chouvardas

    🌍

    Eivind

    🌍

    Ewen

    🌍 🤔

    forght

    🌍

    glottis0q

    🌍

    ButterflyOfFire

    🌍

    Lucian I. Last

    🌍

    LuuzViir

    🌍

    CTHTC

    🌍

    Russian Retro

    🌍

    Marek L'ach

    🌍

    GunChleoc

    🌍

    GabiSnow

    🌍

    bendaha

    🌍

    Samuel Roland

    🌍

    Dimitri Regnier

    🤔

    irithys

    🌍

    Sergi

    🌍

    ghose (XoseM)

    🌍
    + + + + + + +This project follows the +[all-contributors](https://github.com/all-contributors/all-contributors) +specification. Contributions of any kind welcome! + +## Contact + +You may reach us for help or ask any question you have on: + +- [Discord](https://castopod.org/discord) (for direct interaction with + developers and the community) +- [Issue tracker](https://code.castopod.org/adaures/castopod/-/issues) (for + feature requests & bug reports) + +Alternatively, you can follow us on social media platforms to get news about +Castopod: + +- [podlibre.social](https://podlibre.social/@Castopod) (Mastodon instance) +- [Twitter](https://twitter.com/castopod) +- [LinkedIn](https://linkedin.com/company/castopod) +- [Facebook](https://www.facebook.com/castopod) + +## Sponsors + +The ongoing development of Castopod is made possible with the support of its +backers. If you'd like to help, please consider +[sponsoring Castopod's development](https://opencollective.com/castopod/contribute). + +
    + Ad Aures Logo + NLnet Logo +
    + +## License + +[GNU Affero General Public License v3.0](https://choosealicense.com/licenses/agpl-3.0/) + +Copyright © 2020-present, [Ad Aures](https://adaures.com/). +https://img.shields.io/gitlab/v/release/2?color=brightgreen&gitlab_url=https%3A%2F%2Fcode.castopod.org%2F&include_prereleases&label=release +https://img.shields.io/github/license/ad-aures/castopod?color=blue +https://img.shields.io/badge/contributions-welcome-brightgreen.svg +https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg +https://img.shields.io/github/stars/ad-aures/castopod?style=social + +[release]: https://code.castopod.org/adaures/castopod/-/releases +[license]: https://code.castopod.org/adaures/castopod/-/blob/beta/LICENSE.md +[contributions]: https://code.castopod.org/adaures/castopod/-/issues +[semantic-release]: https://github.com/semantic-release/semantic-release +[discord]: https://castopod.org/discord +[stars]: https://github.com/ad-aures/castopod/stargazers +[crowdin]: https://translate.castopod.org/project/castopod diff --git a/docs/src/ca/getting-started/docker.md b/docs/src/ca/getting-started/docker.md new file mode 100644 index 00000000..7b967d92 --- /dev/null +++ b/docs/src/ca/getting-started/docker.md @@ -0,0 +1,150 @@ +--- +title: Imatges Docker oficials +sidebarDepth: 3 +--- + +# Imatges Docker oficials + +Castopod envia 2 imatges de Docker al Docker Hub durant el seu procés de creació +automatitzada: + +- [** code>castopod/app**](https://hub.docker.com/r/castopod/app): el + paquet incloent Castopod i totes les dependències +- [**`castopod/web-server`**](https://hub.docker.com/r/castopod/web-server): una + configuració de Nginx per a Castopod + +A més, Castopod requereix una base de dades compatible amb MySQL. Es pot afegir +una base de dades Redis com a gestor de memòria cau. + +## Etiquetes compatibles + +- `develop` [no-estable], darrera versió de la branca de desenvolupament +- `beta` [stable], latest beta version build +- `1.0.0-beta.x` [stable], specific beta version build (since `1.0.0-beta.22`) + +## Exemple d'ús + +1. Instal·leu [docker](https://docs.docker.com/get-docker/) i + [docker-compose](https://docs.docker.com/compose/install/) +2. Creeu un fitxer `docker-compose.yml` amb el següent: + + ```yml + version: "3.7" + + services: + app: + image: castopod/app:beta + container_name: "castopod-app" + volumes: + - castopod-media:/opt/castopod/public/media + environment: + MYSQL_DATABASE: castopod + MYSQL_USER: castopod + MYSQL_PASSWORD: changeme + CP_BASEURL: "http://castopod.example.com" + CP_ANALYTICS_SALT: changeme + CP_CACHE_HANDLER: redis + CP_REDIS_HOST: redis + networks: + - castopod-app + - castopod-db + restart: unless-stopped + + web-server: + image: castopod/web-server:beta + container_name: "castopod-web-server" + volumes: + - castopod-media:/var/www/html/media + networks: + - castopod-app + ports: + - 8080:80 + restart: unless-stopped + + mariadb: + image: mariadb:10.5 + container_name: "castopod-mariadb" + networks: + - castopod-db + volumes: + - castopod-db:/var/lib/mysql + environment: + MYSQL_ROOT_PASSWORD: changeme + MYSQL_DATABASE: castopod + MYSQL_USER: castopod + MYSQL_PASSWORD: changeme + restart: unless-stopped + + redis: + image: redis:7.0-alpine + container_name: "castopod-redis" + volumes: + - castopod-cache:/data + networks: + - castopod-app + + volumes: + castopod-media: + castopod-db: + castopod-cache: + + networks: + castopod-app: + castopod-db: + ``` + + Heu d'adaptar algunes variables a les vostres necessitats (per exemple, + `CP_BASEURL`, `MYSQL_ROOT_PASSWORD`, `MYSQL_PASSWORD` i + `CP_ANALYTICS_SALT`). + +3. Configureu un `reverse proxy` per a TLS (SSL/HTTPS) + + TLS és obligatori perquè ActivityPub funcioni. Aquest feina es pot gestionar + fàcilment amb un `reverse proxy`, per exemple amb + [Caddy](https://caddyserver.com/): + + ``` + #castopod + castopod.exemple.com { + reverse_proxy localhost:8080 + } + ``` + +4. Executeu `docker-compose up -d`, espereu que s'inicialitzi i aneu a + `https://castopod.exemple.com/cp-install` per acabar de configurar Castopod! + +5. Ja esteu a punt, podeu començar a fer podcasts! 🎙️🚀 + +## Variables d'entorn + +- **castopod/app** + + | Nom de la variable | Tipus (`default`) | Default | + | ---------------------------- | ----------------------- | ---------------- | + | **`CP_BASEURL`** | string | `undefined` | + | **`CP_MEDIA_BASEURL`** | ?string | `CP_BASEURL` | + | **`CP_ADMIN_GATEWAY`** | ?string | `"cp-admin"` | + | **`CP_AUTH_GATEWAY`** | ?string | `"cp-auth"` | + | **`CP_ANALYTICS_SALT`** | string | `undefined` | + | **`CP_DATABASE_HOSTNAME`** | ?string | `"mariadb"` | + | **`CP_DATABASE_NAME`** | ?string | `MYSQL_DATABASE` | + | **`CP_DATABASE_USERNAME`** | ?string | `MYSQL_USER` | + | **`CP_DATABASE_PASSWORD`** | ?string | `MYSQL_PASSWORD` | + | **`CP_DATABASE_PREFIX`** | ?string | `"cp_"` | + | **`CP_CACHE_HANDLER`** | [`"file"` or `"redis"`] | `"file"` | + | **`CP_REDIS_HOST`** | ?string | `"localhost"` | + | **`CP_REDIS_PASSWORD`** | ?string | `null` | + | **`CP_REDIS_PORT`** | ?number | `6379` | + | **`CP_REDIS_DATABASE`** | ?number | `0` | + | **`CP_EMAIL_SMTP_HOST`** | ?string | `undefined` | + | **`CP_EMAIL_FROM`** | ?string | `undefined` | + | **`CP_EMAIL_SMTP_USERNAME`** | ?string | `"localhost"` | + | **`CP_EMAIL_SMTP_PASSWORD`** | ?string | `null` | + | **`CP_EMAIL_SMTP_PORT`** | ?number | `25` | + | **`CP_EMAIL_SMTP_CRYPTO`** | [`"tls"` or `"ssl"`] | `"tls"` | + +- **castopod/web-server** + + | Nom de la variable | Type | Default | + | --------------------- | ------- | ------- | + | **`CP_APP_HOSTNAME`** | ?string | `"app"` | diff --git a/docs/src/ca/getting-started/install.md b/docs/src/ca/getting-started/install.md new file mode 100644 index 00000000..86a47cfd --- /dev/null +++ b/docs/src/ca/getting-started/install.md @@ -0,0 +1,190 @@ +--- +title: Instal·lació +sidebarDepth: 3 +--- + +# Com instal·lar Castopod? + +Castopod va ser pensat per ser fàcil d'instal·lar. Ja sigui utilitzant un +allotjament dedicat o un compartit, podeu instal·lar-lo a la majoria de +servidors web compatibles amb PHP-MySQL. + +::: tip Nota + +Hem publicat imatges oficials de Docker per a Castopod! + +Si preferiu utilitzar Docker, podeu ometre això i anar directament a la +[documentació de Docker](./docker.md) per a Castopod. + +::: + +## Requisits + +- PHP v8.0 o superior +- MySQL versió 5.7 o superior o MariaDB versió 10.2 o superior +- Support d'HTTPS + +### PHP v8.0 o superior + +Es requereix PHP versió 8.0 o superior, amb les extensions següents +instal·lades: + +- [intl](https://php.net/manual/en/intl.requirements.php) +- [libcurl](https://php.net/manual/en/curl.requirements.php) +- [mbstring](https://php.net/manual/en/mbstring.installation.php) +- [gd](https://www.php.net/manual/en/image.installation.php) amb les llibreries + **JPEG**, **PNG** i **WEBP**. +- [exif](https://www.php.net/manual/en/exif.installation.php) + +A més, assegureu-vos que les extensions següents estiguin habilitades al vostre +PHP: + +- json (activat per defecte; no el desactiveu) +- xml (activat per defecte; no el desactiveu) +- [mysqlnd](https://php.net/manual/en/mysqlnd.install.php) + +### Base de dades compatible amb MySQL + +> Us recomanem que utilitzeu [MariaDB](https://mariadb.org). + +::: warning Avís + +Castopod només funciona amb bases de dades compatibles amb MySQL 5.7 o superior. +No funcionarà amb l'anterior MySQL v5.6, per exemple, ja que el seu final de +vida va ser el 5 de febrer de 2021. + +::: + +Necessitareu el nom d'amfitrió del servidor (hostname), el nom de la base de +dades, el nom d'usuari i la contrasenya per completar el procés d'instal·lació. +Si no els teniu, poseu-vos en contacte amb l'administrador del vostre servidor. + +#### Privilegis + +User must have at least these privileges on the database for Castopod to work: +`CREATE`, `ALTER`, `DELETE`, `EXECUTE`, `INDEX`, `INSERT`, `SELECT`, `UPDATE`, +`REFERENCES`, `CREATE VIEW`. + +### (Opcional) FFmpeg v4.1.8 o superior per fer videoclips + +Si voleu generar videoclips, cal [FFmpeg](https://www.ffmpeg.org/) versió 4.1.8 +o superior. Cal instal·lar les següents extensions: + +- La llibreria **FreeType 2** per + [gd](https://www.php.net/manual/en/image.installation.php). + +### (Opcional) Altres recomanacions + +- Redis per a un millor rendiment de la memòria cau. +- CDN per a la memòria cau de fitxers estàtics i millors rendiments. +- Passarel·la de correu electrònic per a contrasenyes perdudes. + +## Instruccions d'instal·lació + +### Pre-requisits + +0. Obteniu un servidor web amb els [requisits](#requirements) instal·lats +1. Creeu una base de dades MySQL per a Castopod amb un usuari amb privilegis + d'accés i modificació (per a més informació, vegeu + [base de dades compatible MySQL](#mysql-compatible-database)). +2. Activeu HTTPS al vostre domini amb un _certificat SSL_. +3. Baixeu i descomprimiu el darrer [paquet Castopod](https://castopod.org/) al + servidor web si encara no ho heu fet. + - ⚠️ Establiu l'arrel del document del servidor web a la subcarpeta + `castopod/public/`. +4. Afegiu **tasques cron** al vostre servidor web per a diversos processos en + segon pla (substituïu les rutes d'acord a la vostra configuració de fitxers): + + - Perquè les funcions socials funcionin correctament, aquesta tasca + s'utilitza per transmetre activitats socials als vostres seguidors al + Fediverse: + + ```bash + * * * * * /ruta/al/php /ruta/al/castopod/public/index.php scheduled-activities + ``` + + - Per transmetre els vostres episodis en hubs oberts després de la publicació + mitjançant [WebSub](https://en.wikipedia.org/wiki/WebSub): + + ```bash + * * * * * /ruta/al/php /rutal/al/castopod/public/index.php scheduled-websub-publish + ``` + + - Per crear clips de vídeo (consulteu + [requisits de FFmpeg](#ffmpeg-v418-or-higher-for-video-clips)): + + ```bash + * * * * * /ruta/al/php /ruta/al/castopod/public/index.php scheduled-video-clips + ``` + + > Aquestes tasques s'executen **cada minut**. Podeu configurar la freqüència + > segons les vostres necessitats: cada 5, 10 minuts o més. + +### (recomanat) Assistent d'instal·lació + +1. Executeu l'script d'instal·lació de Castopod anant a la pàgina web de + l'assistent d'instal·lació (`https://exemple.com/cp-install`) al vostre + navegador web preferit. +2. Seguiu les instruccions a la vostra pantalla. +3. Comenceu a fer podcasts! + +::: info Nota + +L'script d'instal·lació escriu un fitxer `.env` a l'arrel del paquet. If you +cannot go through the install wizard, you can create and edit the `.env` file +manually based on the `.env.example` file. + +::: + +### Email/SMTP setup + +Email configuration is required for some features to work properly (eg. +retrieving your forgotten password, sending instructions to premium subscribers, +…) + +You may add your email configuration in your instance's `.env` like so: + +```ini +# […] + +email.fromEmail="your_email_address" +email.SMTPHost="your_smtp_host" +email.SMTPUser="your_smtp_user" +email.SMTPPass="your_smtp_password" +``` + +#### Email config options + +| Variable name | Type | Default | +| ---------------- | -------------------- | ------------ | +| **`fromEmail`** | string | `undefined` | +| **`fromName`** | string | `"Castopod"` | +| **`SMTPHost`** | string | `undefined` | +| **`SMTPUser`** | string | `undefined` | +| **`SMTPPass`** | string | `undefined` | +| **`SMTPPort`** | number | `25` | +| **`SMTPCrypto`** | [`"tls"` or `"ssl"`] | `"tls"` | + +## Paquets de la comunitat + +If you don't want to bother with installing Castopod manually, you may use one +of the packages created and maintained by the open-source community. + +### Install with YunoHost + +[YunoHost](https://yunohost.org/) is a distribution based on Debian GNU/Linux +made up of free and open-source software packages. It manages the hardships of +self-hosting for you. + + diff --git a/docs/src/content/docs/ca/getting-started/security.mdx b/docs/src/ca/getting-started/security.md similarity index 95% rename from docs/src/content/docs/ca/getting-started/security.mdx rename to docs/src/ca/getting-started/security.md index 75036e64..54caee00 100644 --- a/docs/src/content/docs/ca/getting-started/security.mdx +++ b/docs/src/ca/getting-started/security.md @@ -1,7 +1,9 @@ --- -title: Detalls de seguretat +title: Seguretat --- +# Detalls de seguretat + Castopod està fet amb [CodeIgniter4](https://codeigniter.com/), un framework PHP que fomenta les [bones pràctiques de seguretat](https://codeigniter.com/user_guide/concepts/security.html). diff --git a/docs/src/ca/getting-started/update.md b/docs/src/ca/getting-started/update.md new file mode 100644 index 00000000..cd282372 --- /dev/null +++ b/docs/src/ca/getting-started/update.md @@ -0,0 +1,94 @@ +--- +title: Actualitzar +sidebarDepth: 3 +--- + +# Com actualitzar Castopod? + +Després d'instal·lar Castopod, és possible que vulgueu actualitzar la vostra +instància a la darrera versió per gaudir de les últimes funcions ✨, correccions +d'errors 🐛 i millores de rendiment ⚡. + +## Instruccions d'actualització automàtica + +> Aviat... 👀 + +## Instruccions d'actualització manual + +1. Aneu a la + [pàgina de llançaments](https://code.castopod.org/adaures/castopod/-/releases) + i comproveu si la vostra instància està actualitzada amb la darrera versió de + Castopod + + - [On puc trobar la meva versió de Castopod?](#where-can-i-find-my-castopod-version) + +2. Baixeu l'últim paquet de llançament anomenat `Castopod Package`, podeu triar + entre els fitxers `zip` o `tar.gz` + + - ⚠️ Assegureu-vos de descarregar el paquet Castopod i **NO** el codi font + +3. Al vostre servidor: + + - Elimina tots els fitxers excepte `.env` i `public/media` + - Copieu els fitxers nous del paquet descarregat al vostre servidor + + ::: info Nota + + És possible que hàgiu de restablir els permisos dels fitxers durant el + procés d'instal·lació. Comproveu els [Detalls de seguretat](./security.md). + + ::: + +4. Les diferents versions poden incloure instruccions d'actualització + addicionals (vegeu la + [pàgina de versions](https://code.castopod.org/adaures/castopod/-/releases)). + Normalment són scripts de migració de bases de dades en format `.sql` per + actualitzar l'esquema de la base de dades. + + - 👉 Assegureu-vos que executeu els scripts al vostre panell phpmyadmin o + utilitzeu la línia d'ordres per actualitzar la base de dades juntament amb + els fitxers del paquet. + - [Fa molt de temps que no actualitzo la meva instància... Què hauria de fer?](#i-havent-updated-my-instance-in-a-long-time-what-should-i-do) + +5. Si utilitzeu redis, esborreu la memòria cau. +6. ✨ Gaudiu de la vostra nova instància, tot fet i preparat! + +## Preguntes més freqüents (FAQ) + +### On puc trobar la meva versió de Castopod? + +Aneu al vostre panell de control de Castopod, la versió es mostra a la cantonada +inferior esquerra. + +Alternativament, podeu trobar la versió al fitxer +`app > Config > Constants.php`. + +### Fa temps que no actualitzo la meva instància... Què hauria de fer? + +Cap problema. Només heu d'obtenir l'última versió tal com es descriu +anteriorment. Només, quan seguiu les instruccions de la versió en qüestió (4), +realitzeu-les de manera seqüencial, de la més antiga a la més nova. + +> És possible que vulgueu fer una còpia de seguretat de la vostra instància en +> funció del temps que no heu actualitzat Castopod. + +Per exemple, si sou a `v1.0.0-alpha.42` i voleu actualitzar a `v1.0.0-beta.1`: + +0. (molt recomanable) Feu una còpia de seguretat dels vostres fitxers i base de + dades. + +1. Baixeu la darrera versió, sobreescriu els vostres fitxers mantenint `.env` i + `public/media`. + +2. Seguiu les instruccions d'actualització de cada versió seqüencialment (de la + més antiga a la més recent) començant per `v1.0.0-alpha.43`, + `v1.0.0-alpha.44`, `v1.0.0-alpha.45`, ..., `v1.0.0-beta.1`. + +3. ✨ Gaudiu de la vostra nova instància, tot fet i preparat! + +### Hauria de fer una còpia de seguretat abans d'actualitzar? + +T'aconsellem que ho facis, perquè no ho perdis tot si alguna cosa va malament! + +De manera més general, us aconsellem que feu còpies de seguretat periòdiques +dels vostres fitxers i base de dades de Castopod per evitar que ho perdeu tot... diff --git a/docs/src/ca/index.md b/docs/src/ca/index.md new file mode 100644 index 00000000..a2df1fd6 --- /dev/null +++ b/docs/src/ca/index.md @@ -0,0 +1,304 @@ +--- +sidebarDepth: 2 +--- + +# Benvinguts 👋 + +[![release-badge]][release] [![license-badge]][license] [![contributions-badge]][contributions] [![semantic-release-badge]][semantic-release] [![crowdin-badge]][crowdin] [![discord-badge]][discord] [![stars-badge]][stars] + +Castopod és una plataforma d'allotjament gratuïta i de codi obert creada per a +podcasters que volen involucrar i interactuar amb el seu públic. + +Castopod és fàcil d'instal·lar i s'ha creat amb +[CodeIgniter4](https://codeigniter.com/), un marc PHP potent amb una empremta +molt petita. + +::: info Estat + +Castopod es troba actualment en **beta**, però ja és bastant estable i +l'utilitzen els podcasters d'arreu del món! + +::: + + + +## Característiques + +- 🌱  Gratis i de codi obert (llicència AGPL v3) +- 🔐  Centrat en la sobirania de les dades: el vostre contingut, audiència + i estadístiques us pertanyen, i només a vosaltres +- 🪄  Funcions de podcasting 2.0: GUID, bloqueigos, transcripcions, + finançament, capítols, geo-localització, persones, fragments d'àudio, … +- 💬  Xarxa social integrada: + - 🚀  Castopod forma part de Fediverse, una xarxa social descentralitzada + - ❤️  Creeu publicacions, compartiu-les, afegiu-hi com a preferits i + comenteu episodis +- 📈  Estadístiques integrades: + - ⚖️  Complint amb GDPR / CCPA / LGPD + - 🪙  Mesura d'audiència segons l'estàndard IABv2 + - 🏡  Estadístiques locals, sense cap tercer implicat +- 📢  Eines de màrqueting integrades: + - ✅  Preparada per a SEO (metaetiquetes de gràfics oberts, JSON-LD, …) + - 📱  PWA: instal·lable pels oients com a aplicació autònoma + - 🎨  Colors del tema personalitzables + - 🎬  Genereu videoclips d'episodis preparats per compartir + - 🔉  Genera fragments d'àudio de cada episodi + - ▶️  Reproductor incrustable, per incrustar els episodis a qualsevol + lloc web +- 💸  Monetització: + - 🔗  Enllaços de finançament + - 📲  Anuncis per escoltar-fent-clic + - 🤝  Integració amb value4value i WebMonetization + - 💎  Premium podcasts +- 📡  Publiqueu els vostres episodis a tot arreu amb RSS: + - 📱  A tots els directoris i aplicacions: Podcast Index, Apple Podcasts, + Spotify, Google Podcasts, Deezer, Podcast Addict, Podfriend, … + - ⚡  Emeteu els vostres episodis a l'instant amb WebSub +- 📥  Importació de podcasts: moveu el vostre podcast existent a Castopod +- 📤  Traieu el vostre podcast fora de Castopod +- 🔀  Multi-podcast: allotgeu tants programes com vulgueu en un mateix lloc +- 👥  Multi-usuari: afegiu col·laboradors i definiu rols +- 🌎  Suport i18n: traduït a l'anglès, català, espanyol, xinès, francès, + polonès, alemany, portuguès brasiler ... i + [més per venir](https://translate.castopod.org)! + +## Motivació + +L'ecosistema de podcasting ès descentralitzat per naturalesa: podeu crear el +vostre podcast com a fitxer RSS, publicar-lo a la web i compartir-lo a tot arreu +en línia. + +De fet, és un dels únics mitjans que s'han mantingut durant molt de temps +(dècades!). + +A mesura que els usos evolucionen, cada vegada hi ha més gent que s'incorpora +als podcasts: ja siguin els creadors que troben noves maneres de compartir les +seves idees o els oients a la recerca de millors continguts. + +Essent el podcasting cada cop més utilitzat, algunes empreses intenten +canviar-lo cap a un mitjà més controlat i centralitzat, creant plataformes de +publicació sota el seu control. + +Castopod es va crear amb l'objectiu de proporcionar una alternativa oberta i +sostenible per a que allotjeu els vostres podcasts, promovent la +descentralització i així garantir que la creativitat dels podcasters pugui +expressar-se. + +Aquest projecte és impulsat per la comunitat de codi obert, i concretament pels +moviments [Fediverse](https://fediverse.party/en/fediverse/) i [Podcasting +2.0](https://podcastindex .org/). + +## Comparació amb altres solucions + +Creiem que una mateixa solució no és necessàriament adequada per a tothom, depèn +molt de les vostres necessitats. Per tant, aquí us mostrem comparacions amb +altres eines per ajudar-vos a determinar si Castopod és l'adequat per a +vosaltres. + +### Castopod vs Wordpress + +Casopod es coneix sovint com "el Wordpress per a podcasts" a causa de les +similituds entre els dos. D'alguna manera això és cert. I, de fet, Castopod es +va inspirar molt en l'ecosistema de Wordpress, veient la facilitat d'adopció per +part de la comunitat i el nombre de llocs web que l'executen. + +Igual que Wordpress, Castopod és gratuït i de codi obert, fet amb PHP amb una +base de dades MySQL i està empaquetat de manera que es pot instal·lar fàcilment +a la majoria del servidors web. + +Wordpress és una manera fantàstica de crear el vostre lloc web i ampliar-lo amb +complements per obtenir el que voleu. És un CMS complet que us ajuda a tenir +qualsevol tipus de lloc web en línia. + +D'altra banda, Castopod està pensat per atendre les necessitats dels podcasters +específicament, centrant-se en el podcasting i res més. No necessiteu cap +complement o connector per començar el vostre viatge de podcasting. + +Això permet optimitzar els processos específics del podcasting: des de la +creació dels teus podcasts i la publicació de nous episodis fins a la difusió, +el màrqueting i l'anàlisi estadística. + +Finalment, depenent de les vostres necessitats, Wordpress i Castopod poden +conviure fins i tot, ja que comparteixen els mateixos requisits! + +### Castopod vs Funkwhale + +Funkwhale és un servidor de música de codi obert, modern i auto-allotjat. Igual +que Castopod, Funkwhale es troba al Fediverse, una xarxa social descentralitzada +que permet la interoperabilitat entre ambdues. + +Funkwhale es va construir inicialment al voltant de la música. I més tard, a +mesura que el projecte anava evolucionant, es va introduir la possibilitat +d'allotjar podcasts. + +A diferència de Funkwhale, Castopod ha estat dissenyat i construït exclusivament +al voltant del podcasting. Això permet una implementació més fàcil de funcions +relacionades amb l'ecosistema del podcasting, com ara les funcions del +podcasting 2.0 (transcripcions, capítols, geo-localitzacions, persones, ...). + +Per tant, probablement hauríeu d'utilitzar Funkwhale si voleu allotjar la vostra +música i utilitzar Castopod si voleu allotjar els vostres podcasts. + +### Castopod vs altres plataformes de podcast + +Hi ha moltes solucions per allotjar els vostres podcasts, algunes de les quals +són realment fantàstiques i [moltes](https://podcastindex.org/apps) s'estan +incorporant al carro Podcasting 2.0. com Castopod! + +Cadascuna d'aquestes solucions difereix entre si, podeu comparar-les amb la +[llista de funcions](#features). + +Dit això, hi ha dues diferències principals amb altres solucions de podcasting: + +- Castopod es pot auto-allotjar i és la única solució que us permet mantenir el + control total sobre el que produïu. A més, com que és de codi obert, fins i + tot podeu personalitzar-lo com vulgueu. + +- Castopod és l'única solució que actualment integra tant una xarxa social + descentralitzada amb ActivityPub com moltes de les funcions de podcasting 2.0, + amb l'esperança de salvar la bretxa entre les dues. + +## Col·laborar + +Us agrada Castopod i voleu ajudar? Fes una ullada a la documentació següent per +començar. + +### Codi de conducta + +Castopod ha adoptat un codi de conducta que esperem que els participants del +projecte compleixin. Si us plau, llegiu el +[manual CODE_OF_CONDUCT](https://code.castopod.org/adaures/castopod/-/blob/beta/CODE_OF_CONDUCT.md) +perquè pugueu entendre quines accions seran o no tolerades. + +### Guia de col·laboració + +Llegiu la nostra [guia de col·laboració](./contributing/guidelines.md) per +conèixer el nostre procés de desenvolupament, com proposar correccions d'errors +i millores, i com construir i prova els teus canvis a Castopod. + +## Col·laboradors ✨ + +Gràcies a aquestes persones meravelloses +([clau emoji](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Yassine Doghri

    💻 🐛 📖 👀 🚧 🖋 🎨 ️️️️♿️ 🌍 💬 🧑‍🏫 🚇 🤔 📆 📝

    Benjamin Bellamy

    💻 🐛 👀 🖋 🌍 💬 🚇 🤔 📝 📆 📢

    Ola Hneini

    💻 👀 📖 🚧 💬 🤔

    Romain de Laage

    💻 🚇 📖 🌍 🤔

    Lyonel Bernard

    🐛 💬 🔊 🤔

    Christopher Lagonick-Weitzel

    🐛 💬 🔊 🤔

    Ernesto Acosta

    🐛 🔊 🌍 💬 🤔

    Bastien Luneteau

    💻 🐛

    Cécile Ricordeau

    🎨

    Patryk Miś

    🌍

    Marcin Lewandowski

    🐛 🤔

    Sebastian Janik

    💻

    Patryk Karczmarczyk

    💻

    denis d

    🐛 🤔

    Douglas Kastle

    🐛 🤔

    cExplorer

    🐛 🌍

    ImaCrea

    🐛 🤔

    Jonas S

    💻

    LEFEBVRE Yann

    🐛

    Sebastian Späth

    🐛 🤔

    rocky III

    🐛

    Hermann Josef Eckl

    🐛

    Delhaye Cyrille

    🐛 🤔

    João Leandro

    🌍 🤔

    Angelos Chouvardas

    🌍

    Eivind

    🌍

    Ewen

    🌍 🤔

    forght

    🌍

    glottis0q

    🌍

    ButterflyOfFire

    🌍

    Lucian I. Last

    🌍

    LuuzViir

    🌍

    CTHTC

    🌍

    Russian Retro

    🌍

    Marek L'ach

    🌍

    GunChleoc

    🌍

    GabiSnow

    🌍

    bendaha

    🌍

    Samuel Roland

    🌍

    Dimitri Regnier

    🤔

    irithys

    🌍

    Sergi

    🌍

    ghose (XoseM)

    🌍
    + + + + + + +Aquest projecte segueix l'especificació +[all-contributors](https://github.com/all-contributors/all-contributors). +Benvingudes les col·laboracions de qualsevol mena! + +## Contacte + +Podeu contactar amb nosaltres per demanar ajuda o fer qualsevol pregunta que +tingueu via: + +- [Discord](https://castopod.org/discord) (per a la interacció directa amb + desenvolupadors i la comunitat) +- [Seguiment d'incidències](https://code.castopod.org/adaures/castopod/-/issues) + (per a sol·licituds de noves funcionalitats i informes d'errors) + +Alternativament, podeu seguir-nos a les plataformes de xarxes socials per rebre +notícies sobre Castopod: + +- [podlibre.social](https://podlibre.social/@Castopod) (instància de Mastodon) +- [Twitter](https://twitter.com/castopod) +- [LinkedIn](https://linkedin.com/company/castopod) +- [Facebook](https://www.facebook.com/castopod) + +## Patrocinadors + +El desenvolupament continu de Castopod és possible amb el suport dels seus +patrocinadors. Si voleu ajudar, considereu +[patrocinar el desenvolupament de Castopod](https://opencollective.com/castopod/contribute). + +
    + Ad Aures Logo + NLnet Logo +
    + +## Llicència + +[GNU Affero General Public License v3.0](https://choosealicense.com/licenses/agpl-3.0/) + +Copyright © 2020-avui, [Ad Aures](https://adaures.com/). +https://img.shields.io/gitlab/v/release/2?color=brightgreen&gitlab_url=https%3A%2F%2Fcode.castopod.org%2F&include_prereleases&label=release +https://img.shields.io/github/license/ad-aures/castopod?color=blue +https://img.shields.io/badge/contributions-welcome-brightgreen.svg +https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg +https://img.shields.io/github/stars/ad-aures/castopod?style=social + +[release]: https://code.castopod.org/adaures/castopod/-/releases +[license]: https://code.castopod.org/adaures/castopod/-/blob/beta/LICENSE.md +[contributions]: https://code.castopod.org/adaures/castopod/-/issues +[semantic-release]: https://github.com/semantic-release/semantic-release +[discord]: https://castopod.org/discord +[stars]: https://github.com/ad-aures/castopod/stargazers +[crowdin]: https://translate.castopod.org/project/castopod diff --git a/docs/src/components/DocsVersionSelect.astro b/docs/src/components/DocsVersionSelect.astro deleted file mode 100644 index 9bedafa9..00000000 --- a/docs/src/components/DocsVersionSelect.astro +++ /dev/null @@ -1,34 +0,0 @@ ---- -import Select from '@astrojs/starlight/components/Select.astro'; ---- - - - ' +# honeypot.container = '
    {template}
    ' + +#-------------------------------------------------------------------- +# SECURITY +#-------------------------------------------------------------------- + +# security.csrfProtection = 'cookie' +# security.tokenRandomize = false +# security.tokenName = 'csrf_token_name' +# security.headerName = 'X-CSRF-TOKEN' +# security.cookieName = 'csrf_cookie_name' +# security.expires = 7200 +# security.regenerate = true +# security.redirect = true +# security.samesite = 'Lax' #-------------------------------------------------------------------- # LOGGER #-------------------------------------------------------------------- # logger.threshold = 4 + +#-------------------------------------------------------------------- +# CURLRequest +#-------------------------------------------------------------------- + +# curlrequest.shareOptions = true diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index c9d330e6..00000000 --- a/eslint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -import globals from "globals"; -import eslint from "@eslint/js"; -import tseslint from "typescript-eslint"; -import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; - -export default [ - ...tseslint.config( - eslint.configs.recommended, - ...tseslint.configs.strict, - eslintPluginPrettierRecommended - ), - { - ignores: ["public/*", "docs/*", "vendor/*", "castopod/*"], - }, - { - languageOptions: { - globals: { - ...globals.browser, - ...globals.node, - }, - }, - }, -]; diff --git a/.devcontainer/initdb/01.sql b/initdb/01.sql similarity index 100% rename from .devcontainer/initdb/01.sql rename to initdb/01.sql diff --git a/modules/Admin/Config/Admin.php b/modules/Admin/Config/Admin.php index 56741428..4c289d9c 100644 --- a/modules/Admin/Config/Admin.php +++ b/modules/Admin/Config/Admin.php @@ -20,5 +20,5 @@ class Admin extends BaseConfig * Number of maximum ffmpeg processes to spawn in parallel when generating video clips. Processes are instance wide, * meaning that they are shared across all podcasts and episodes. */ - public int $videoClipWorkers = 1; + public int $videoClipWorkers = 2; } diff --git a/modules/Admin/Config/Routes.php b/modules/Admin/Config/Routes.php index 375b2943..ad767a0d 100644 --- a/modules/Admin/Config/Routes.php +++ b/modules/Admin/Config/Routes.php @@ -4,9 +4,7 @@ declare(strict_types=1); namespace Modules\Admin\Config; -use CodeIgniter\Router\RouteCollection; - -/** @var RouteCollection $routes */ +$routes = service('routes'); // video-clips scheduler $routes->add('scheduled-video-clips', 'SchedulerController::generateVideoClips', [ @@ -26,61 +24,61 @@ $routes->group( ]); $routes->group('settings', static function ($routes): void { $routes->get('/', 'SettingsController', [ - 'as' => 'settings-general', - 'filter' => 'permission:admin.settings', + 'as' => 'settings-general', + 'filter' => 'permission:settings-manage', ]); - $routes->post('instance', 'SettingsController::instanceEditAction', [ - 'as' => 'settings-instance', - 'filter' => 'permission:admin.settings', + $routes->post('instance', 'SettingsController::attemptInstanceEdit', [ + 'as' => 'settings-instance', + 'filter' => 'permission:settings-manage', ]); - $routes->get('instance-delete-icon', 'SettingsController::deleteIconAction', [ - 'as' => 'settings-instance-delete-icon', - 'filter' => 'permission:admin.settings', + $routes->get('instance-delete-icon', 'SettingsController::deleteIcon', [ + 'as' => 'settings-instance-delete-icon', + 'filter' => 'permission:settings-manage', ]); - $routes->post('instance-images-regenerate', 'SettingsController::regenerateImagesAction', [ - 'as' => 'settings-images-regenerate', - 'filter' => 'permission:admin.settings', + $routes->post('instance-images-regenerate', 'SettingsController::regenerateImages', [ + 'as' => 'settings-images-regenerate', + 'filter' => 'permission:settings-manage', ]); - $routes->post('instance-housekeeping-run', 'SettingsController::housekeepingAction', [ - 'as' => 'settings-housekeeping-run', - 'filter' => 'permission:admin.settings', + $routes->post('instance-housekeeping-run', 'SettingsController::runHousekeeping', [ + 'as' => 'settings-housekeeping-run', + 'filter' => 'permission:settings-manage', ]); - $routes->get('theme', 'SettingsController::themeView', [ - 'as' => 'settings-theme', - 'filter' => 'permission:admin.settings', + $routes->get('theme', 'SettingsController::theme', [ + 'as' => 'settings-theme', + 'filter' => 'permission:settings-manage', ]); - $routes->post('theme', 'SettingsController::themeAction', [ - 'as' => 'settings-theme', - 'filter' => 'permission:admin.settings', + $routes->post('theme', 'SettingsController::attemptSetInstanceTheme', [ + 'as' => 'settings-theme', + 'filter' => 'permission:settings-manage', ]); }); $routes->group('persons', static function ($routes): void { - $routes->get('/', 'PersonController::list', [ - 'as' => 'person-list', - 'filter' => 'permission:persons.manage', + $routes->get('/', 'PersonController', [ + 'as' => 'person-list', + 'filter' => 'permission:person-list', ]); - $routes->get('new', 'PersonController::createView', [ - 'as' => 'person-create', - 'filter' => 'permission:persons.manage', + $routes->get('new', 'PersonController::create', [ + 'as' => 'person-create', + 'filter' => 'permission:person-create', ]); - $routes->post('new', 'PersonController::createAction', [ - 'filter' => 'permission:persons.manage', + $routes->post('new', 'PersonController::attemptCreate', [ + 'filter' => 'permission:person-create', ]); $routes->group('(:num)', static function ($routes): void { $routes->get('/', 'PersonController::view/$1', [ - 'as' => 'person-view', - 'filter' => 'permission:persons.manage', + 'as' => 'person-view', + 'filter' => 'permission:person-view', ]); - $routes->get('edit', 'PersonController::editView/$1', [ - 'as' => 'person-edit', - 'filter' => 'permission:persons.manage', + $routes->get('edit', 'PersonController::edit/$1', [ + 'as' => 'person-edit', + 'filter' => 'permission:person-edit', ]); - $routes->post('edit', 'PersonController::editAction/$1', [ - 'filter' => 'permission:persons.manage', + $routes->post('edit', 'PersonController::attemptEdit/$1', [ + 'filter' => 'permission:person-edit', ]); - $routes->add('delete', 'PersonController::deleteAction/$1', [ - 'as' => 'person-delete', - 'filter' => 'permission:persons.manage', + $routes->add('delete', 'PersonController::delete/$1', [ + 'as' => 'person-delete', + 'filter' => 'permission:person-delete', ]); }); }); @@ -89,434 +87,558 @@ $routes->group( $routes->get('/', 'PodcastController::list', [ 'as' => 'podcast-list', ]); - $routes->get('new', 'PodcastController::createView', [ - 'as' => 'podcast-create', - 'filter' => 'permission:podcasts.create', + $routes->get('new', 'PodcastController::create', [ + 'as' => 'podcast-create', + 'filter' => 'permission:podcasts-create', ]); - $routes->post('new', 'PodcastController::createAction', [ - 'filter' => 'permission:podcasts.create', + $routes->post('new', 'PodcastController::attemptCreate', [ + 'filter' => 'permission:podcasts-create', + ]); + $routes->get('import', 'PodcastImportController', [ + 'as' => 'podcast-import', + 'filter' => 'permission:podcasts-import', + ]); + $routes->post('import', 'PodcastImportController::attemptImport', [ + 'filter' => 'permission:podcasts-import', ]); // Podcast // Use ids in admin area to help permission and group lookups $routes->group('(:num)', static function ($routes): void { $routes->get('/', 'PodcastController::view/$1', [ - 'as' => 'podcast-view', - 'filter' => 'permission:podcast$1.view', + 'as' => 'podcast-view', + 'filter' => 'permission:podcasts-view,podcast-view', ]); - $routes->get('edit', 'PodcastController::editView/$1', [ - 'as' => 'podcast-edit', - 'filter' => 'permission:podcast$1.edit', + $routes->get('edit', 'PodcastController::edit/$1', [ + 'as' => 'podcast-edit', + 'filter' => 'permission:podcast-edit', ]); - $routes->post('edit', 'PodcastController::editAction/$1', [ - 'filter' => 'permission:podcast$1.edit', + $routes->post('edit', 'PodcastController::attemptEdit/$1', [ + 'filter' => 'permission:podcast-edit', ]); $routes->get( 'publish', - 'PodcastController::publishView/$1', + 'PodcastController::publish/$1', [ - 'as' => 'podcast-publish', - 'filter' => 'permission:podcast$1.manage-publications', + 'as' => 'podcast-publish', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->post( 'publish', - 'PodcastController::publishAction/$1', + 'PodcastController::attemptPublish/$1', [ - 'filter' => 'permission:podcast$1.manage-publications', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->get( 'publish-edit', - 'PodcastController::publishEditView/$1', + 'PodcastController::publishEdit/$1', [ - 'as' => 'podcast-publish_edit', - 'filter' => 'permission:podcast$1.manage-publications', + 'as' => 'podcast-publish_edit', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->post( 'publish-edit', - 'PodcastController::publishEditAction/$1', + 'PodcastController::attemptPublishEdit/$1', [ - 'filter' => 'permission:podcast$1.manage-publications', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->get( 'publish-cancel', - 'PodcastController::publishCancelAction/$1', + 'PodcastController::publishCancel/$1', [ - 'as' => 'podcast-publish-cancel', - 'filter' => 'permission:podcast$1.manage-publications', + 'as' => 'podcast-publish-cancel', + 'filter' => + 'permission:podcast-manage_publications', ], ); - $routes->get('edit/delete-banner', 'PodcastController::deleteBannerAction/$1', [ - 'as' => 'podcast-banner-delete', - 'filter' => 'permission:podcast$1.edit', + $routes->get('edit/delete-banner', 'PodcastController::deleteBanner/$1', [ + 'as' => 'podcast-banner-delete', + 'filter' => 'permission:podcast-edit', ]); - $routes->get('delete', 'PodcastController::deleteView/$1', [ - 'as' => 'podcast-delete', - 'filter' => 'permission:podcast$1.delete', + $routes->get('delete', 'PodcastController::delete/$1', [ + 'as' => 'podcast-delete', + 'filter' => 'permission:podcasts-delete', ]); - $routes->post('delete', 'PodcastController::deleteAction/$1', [ - 'filter' => 'permission:podcast$1.delete', + $routes->post('delete', 'PodcastController::attemptDelete/$1', [ + 'filter' => 'permission:podcasts-delete', + ]); + $routes->get('update', 'PodcastImportController::updateImport/$1', [ + 'as' => 'podcast-update-feed', + 'filter' => 'permission:podcasts-import', ]); $routes->group('persons', static function ($routes): void { - $routes->get('/', 'PodcastPersonController::index/$1', [ - 'as' => 'podcast-persons-manage', - 'filter' => 'permission:podcast$1.manage-persons', + $routes->get('/', 'PodcastPersonController/$1', [ + 'as' => 'podcast-persons-manage', + 'filter' => 'permission:podcast-edit', ]); $routes->post( '/', - 'PodcastPersonController::createAction/$1', + 'PodcastPersonController::attemptAdd/$1', [ - 'filter' => 'permission:podcast$1.manage-persons', + 'filter' => 'permission:podcast-edit', ], ); $routes->get( '(:num)/remove', - 'PodcastPersonController::deleteAction/$1/$2', + 'PodcastPersonController::remove/$1/$2', [ - 'as' => 'podcast-person-remove', - 'filter' => 'permission:podcast$1.manage-persons', + 'as' => 'podcast-person-remove', + 'filter' => 'permission:podcast-edit', ], ); }); $routes->group('analytics', static function ($routes): void { - $routes->get('/', 'PodcastController::analyticsView/$1', [ - 'as' => 'podcast-analytics', - 'filter' => 'permission:podcast$1.view', + $routes->get('/', 'PodcastController::viewAnalytics/$1', [ + 'as' => 'podcast-analytics', + 'filter' => 'permission:podcasts-view,podcast-view', ]); $routes->get( 'webpages', - 'PodcastController::analyticsWebpagesView/$1', + 'PodcastController::viewAnalyticsWebpages/$1', [ - 'as' => 'podcast-analytics-webpages', - 'filter' => 'permission:podcast$1.view', + 'as' => 'podcast-analytics-webpages', + 'filter' => 'permission:podcasts-view,podcast-view', ], ); $routes->get( 'locations', - 'PodcastController::analyticsLocationsView/$1', + 'PodcastController::viewAnalyticsLocations/$1', [ - 'as' => 'podcast-analytics-locations', - 'filter' => 'permission:podcast$1.view', + 'as' => 'podcast-analytics-locations', + 'filter' => 'permission:podcasts-view,podcast-view', ], ); $routes->get( 'unique-listeners', - 'PodcastController::analyticsUniqueListenersView/$1', + 'PodcastController::viewAnalyticsUniqueListeners/$1', [ - 'as' => 'podcast-analytics-unique-listeners', - 'filter' => 'permission:podcast$1.view', + 'as' => 'podcast-analytics-unique-listeners', + 'filter' => 'permission:podcasts-view,podcast-view', ], ); $routes->get( 'listening-time', - 'PodcastController::analyticsListeningTimeView/$1', + 'PodcastController::viewAnalyticsListeningTime/$1', [ - 'as' => 'podcast-analytics-listening-time', - 'filter' => 'permission:podcast$1.view', + 'as' => 'podcast-analytics-listening-time', + 'filter' => 'permission:podcasts-view,podcast-view', ], ); $routes->get( 'time-periods', - 'PodcastController::analyticsTimePeriodsView/$1', + 'PodcastController::viewAnalyticsTimePeriods/$1', [ - 'as' => 'podcast-analytics-time-periods', - 'filter' => 'permission:podcast$1.view', + 'as' => 'podcast-analytics-time-periods', + 'filter' => 'permission:podcasts-view,podcast-view', ], ); $routes->get( 'players', - 'PodcastController::analyticsPlayersView/$1', + 'PodcastController::viewAnalyticsPlayers/$1', [ - 'as' => 'podcast-analytics-players', - 'filter' => 'permission:podcast$1.view', + 'as' => 'podcast-analytics-players', + 'filter' => 'permission:podcasts-view,podcast-view', ], ); }); // Podcast episodes $routes->group('episodes', static function ($routes): void { $routes->get('/', 'EpisodeController::list/$1', [ - 'as' => 'episode-list', - 'filter' => 'permission:podcast$1.episodes.view', + 'as' => 'episode-list', + 'filter' => + 'permission:episodes-list,podcast_episodes-list', ]); - $routes->get('new', 'EpisodeController::createView/$1', [ - 'as' => 'episode-create', - 'filter' => 'permission:podcast$1.episodes.create', + $routes->get('new', 'EpisodeController::create/$1', [ + 'as' => 'episode-create', + 'filter' => 'permission:podcast_episodes-create', ]); $routes->post( 'new', - 'EpisodeController::createAction/$1', + 'EpisodeController::attemptCreate/$1', [ - 'filter' => 'permission:podcast$1.episodes.create', + 'filter' => 'permission:podcast_episodes-create', ], ); // Episode $routes->group('(:num)', static function ($routes): void { $routes->get('/', 'EpisodeController::view/$1/$2', [ - 'as' => 'episode-view', - 'filter' => 'permission:podcast$1.episodes.view', + 'as' => 'episode-view', + 'filter' => + 'permission:episodes-view,podcast_episodes-view', ]); - $routes->get('edit', 'EpisodeController::editView/$1/$2', [ - 'as' => 'episode-edit', - 'filter' => 'permission:podcast$1.episodes.edit', + $routes->get('edit', 'EpisodeController::edit/$1/$2', [ + 'as' => 'episode-edit', + 'filter' => 'permission:podcast_episodes-edit', ]); $routes->post( 'edit', - 'EpisodeController::editAction/$1/$2', + 'EpisodeController::attemptEdit/$1/$2', [ - 'filter' => 'permission:podcast$1.episodes.edit', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'publish', - 'EpisodeController::publishView/$1/$2', + 'EpisodeController::publish/$1/$2', [ - 'as' => 'episode-publish', - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'as' => 'episode-publish', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->post( 'publish', - 'EpisodeController::publishAction/$1/$2', + 'EpisodeController::attemptPublish/$1/$2', [ - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->get( 'publish-edit', - 'EpisodeController::publishEditView/$1/$2', + 'EpisodeController::publishEdit/$1/$2', [ - 'as' => 'episode-publish_edit', - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'as' => 'episode-publish_edit', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->post( 'publish-edit', - 'EpisodeController::publishEditAction/$1/$2', + 'EpisodeController::attemptPublishEdit/$1/$2', [ - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->get( 'publish-cancel', - 'EpisodeController::publishCancelAction/$1/$2', + 'EpisodeController::publishCancel/$1/$2', [ - 'as' => 'episode-publish-cancel', - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'as' => 'episode-publish-cancel', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->get( 'publish-date-edit', - 'EpisodeController::publishDateEditView/$1/$2', + 'EpisodeController::publishDateEdit/$1/$2', [ - 'as' => 'episode-publish_date_edit', - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'as' => 'episode-publish_date_edit', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->post( 'publish-date-edit', - 'EpisodeController::publishDateEditAction/$1/$2', + 'EpisodeController::attemptPublishDateEdit/$1/$2', [ - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->get( 'unpublish', - 'EpisodeController::unpublishView/$1/$2', + 'EpisodeController::unpublish/$1/$2', [ - 'as' => 'episode-unpublish', - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'as' => 'episode-unpublish', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->post( 'unpublish', - 'EpisodeController::unpublishAction/$1/$2', + 'EpisodeController::attemptUnpublish/$1/$2', [ - 'filter' => 'permission:podcast$1.episodes.manage-publications', + 'filter' => + 'permission:podcast-manage_publications', ], ); $routes->get( 'delete', - 'EpisodeController::deleteView/$1/$2', + 'EpisodeController::delete/$1/$2', [ - 'as' => 'episode-delete', - 'filter' => 'permission:podcast$1.episodes.delete', + 'as' => 'episode-delete', + 'filter' => + 'permission:podcast_episodes-delete', ], ); $routes->post( 'delete', - 'EpisodeController::deleteAction/$1/$2', + 'EpisodeController::attemptDelete/$1/$2', [ - 'filter' => 'permission:podcast$1.episodes.delete', + 'filter' => + 'permission:podcast_episodes-delete', ], ); $routes->get( 'transcript-delete', 'EpisodeController::transcriptDelete/$1/$2', [ - 'as' => 'transcript-delete', - 'filter' => 'permission:podcast$1.episodes.edit', + 'as' => 'transcript-delete', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'chapters-delete', 'EpisodeController::chaptersDelete/$1/$2', [ - 'as' => 'chapters-delete', - 'filter' => 'permission:podcast$1.episodes.edit', + 'as' => 'chapters-delete', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'soundbites', 'SoundbiteController::list/$1/$2', [ - 'as' => 'soundbites-list', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'soundbites-list', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'soundbites/new', - 'SoundbiteController::createView/$1/$2', + 'SoundbiteController::create/$1/$2', [ - 'as' => 'soundbites-create', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'soundbites-create', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->post( 'soundbites/new', - 'SoundbiteController::createAction/$1/$2', + 'SoundbiteController::attemptCreate/$1/$2', [ - 'as' => 'soundbites-create', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'soundbites-create', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'soundbites/(:num)/delete', - 'SoundbiteController::deleteAction/$1/$2/$3', + 'SoundbiteController::delete/$1/$2/$3', [ - 'as' => 'soundbites-delete', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'soundbites-delete', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'video-clips', 'VideoClipsController::list/$1/$2', [ - 'as' => 'video-clips-list', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'video-clips-list', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'video-clips/new', - 'VideoClipsController::createView/$1/$2', + 'VideoClipsController::create/$1/$2', [ - 'as' => 'video-clips-create', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'video-clips-create', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->post( 'video-clips/new', - 'VideoClipsController::createAction/$1/$2', + 'VideoClipsController::attemptCreate/$1/$2', [ - 'as' => 'video-clips-create', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'video-clips-create', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'video-clips/(:num)', 'VideoClipsController::view/$1/$2/$3', [ - 'as' => 'video-clip', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'video-clip', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'video-clips/(:num)/retry', - 'VideoClipsController::retryAction/$1/$2/$3', + 'VideoClipsController::retry/$1/$2/$3', [ - 'as' => 'video-clip-retry', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'video-clip-retry', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'video-clips/(:num)/delete', - 'VideoClipsController::deleteAction/$1/$2/$3', + 'VideoClipsController::delete/$1/$2/$3', [ - 'as' => 'video-clip-delete', - 'filter' => 'permission:podcast$1.episodes.manage-clips', + 'as' => 'video-clip-delete', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->get( 'embed', - 'EpisodeController::embedView/$1/$2', + 'EpisodeController::embed/$1/$2', [ - 'as' => 'embed-add', - 'filter' => 'permission:podcast$1.episodes.edit', + 'as' => 'embed-add', + 'filter' => 'permission:podcast_episodes-edit', ], ); $routes->group('persons', static function ($routes): void { - $routes->get('/', 'EpisodePersonController::index/$1/$2', [ - 'as' => 'episode-persons-manage', - 'filter' => 'permission:podcast$1.episodes.manage-persons', + $routes->get('/', 'EpisodePersonController/$1/$2', [ + 'as' => 'episode-persons-manage', + 'filter' => 'permission:podcast_episodes-edit', ]); $routes->post( '/', - 'EpisodePersonController::createAction/$1/$2', + 'EpisodePersonController::attemptAdd/$1/$2', [ - 'filter' => 'permission:podcast$1.episodes.manage-persons', + 'filter' => + 'permission:podcast_episodes-edit', ], ); $routes->get( '(:num)/remove', - 'EpisodePersonController::deleteAction/$1/$2/$3', + 'EpisodePersonController::remove/$1/$2/$3', [ - 'as' => 'episode-person-remove', - 'filter' => 'permission:podcast$1.episodes.manage-persons', + 'as' => 'episode-person-remove', + 'filter' => + 'permission:podcast_episodes-edit', ], ); }); $routes->group('comments', static function ($routes): void { $routes->post( 'new', - 'EpisodeController::commentCreateAction/$1/$2', + 'EpisodeController::attemptCommentCreate/$1/$2', [ - 'as' => 'comment-attempt-create', - 'filter' => 'permission:podcast$1.episodes.manage-comments', - ], + 'as' => 'comment-attempt-create', + 'filter' => 'permission:podcast-manage_publications', + ] ); $routes->post( '(:uuid)/reply', - 'EpisodeController::commentReplyAction/$1/$2/$3', + 'EpisodeController::attemptCommentReply/$1/$2/$3', [ - 'as' => 'comment-attempt-reply', - 'filter' => 'permission:podcast$1.episodes.manage-comments', - ], + 'as' => 'comment-attempt-reply', + 'filter' => 'permission:podcast-manage_publications', + ] ); $routes->post( 'delete', - 'EpisodeController::commentDeleteAction/$1/$2', + 'EpisodeController::attemptCommentDelete/$1/$2', [ - 'as' => 'comment-attempt-delete', - 'filter' => 'permission:podcast$1.episodes.manage-comments', - ], + 'as' => 'comment-attempt-delete', + 'filter' => 'permission:podcast-manage_publications', + ] ); }); }); }); + // Podcast contributors + $routes->group('contributors', static function ($routes): void { + $routes->get('/', 'ContributorController::list/$1', [ + 'as' => 'contributor-list', + 'filter' => + 'permission:podcasts-view,podcast-manage_contributors', + ]); + $routes->get('add', 'ContributorController::add/$1', [ + 'as' => 'contributor-add', + 'filter' => 'permission:podcast-manage_contributors', + ]); + $routes->post( + 'add', + 'ContributorController::attemptAdd/$1', + [ + 'filter' => + 'permission:podcast-manage_contributors', + ], + ); + // Contributor + $routes->group('(:num)', static function ($routes): void { + $routes->get('/', 'ContributorController::view/$1/$2', [ + 'as' => 'contributor-view', + 'filter' => + 'permission:podcast-manage_contributors', + ]); + $routes->get( + 'edit', + 'ContributorController::edit/$1/$2', + [ + 'as' => 'contributor-edit', + 'filter' => + 'permission:podcast-manage_contributors', + ], + ); + $routes->post( + 'edit', + 'ContributorController::attemptEdit/$1/$2', + [ + 'filter' => + 'permission:podcast-manage_contributors', + ], + ); + $routes->get( + 'remove', + 'ContributorController::remove/$1/$2', + [ + 'as' => 'contributor-remove', + 'filter' => + 'permission:podcast-manage_contributors', + ], + ); + }); + }); + $routes->group('platforms', static function ($routes): void { + $routes->get( + '/', + 'PodcastPlatformController::platforms/$1/podcasting', + [ + 'as' => 'platforms-podcasting', + 'filter' => 'permission:podcast-manage_platforms', + ], + ); + $routes->get( + 'social', + 'PodcastPlatformController::platforms/$1/social', + [ + 'as' => 'platforms-social', + 'filter' => 'permission:podcast-manage_platforms', + ], + ); + $routes->get( + 'funding', + 'PodcastPlatformController::platforms/$1/funding', + [ + 'as' => 'platforms-funding', + 'filter' => 'permission:podcast-manage_platforms', + ], + ); + $routes->post( + 'save/(:platformType)', + 'PodcastPlatformController::attemptPlatformsUpdate/$1/$2', + [ + 'as' => 'platforms-save', + 'filter' => 'permission:podcast-manage_platforms', + ], + ); + $routes->get( + '(:slug)/podcast-platform-remove', + 'PodcastPlatformController::removePodcastPlatform/$1/$2', + [ + 'as' => 'podcast-platform-remove', + 'filter' => 'permission:podcast-manage_platforms', + ], + ); + }); // Podcast notifications $routes->group('notifications', static function ($routes): void { $routes->get('/', 'NotificationController::list/$1', [ - 'as' => 'notification-list', - 'filter' => 'permission:podcast$1.manage-notifications', + 'as' => 'notification-list', ]); - $routes->get('(:num)/mark-as-read', 'NotificationController::markAsReadAction/$1/$2', [ - 'as' => 'notification-mark-as-read', - 'filter' => 'permission:podcast$1.manage-notifications', + $routes->get('(:num)/mark-as-read', 'NotificationController::markAsRead/$1/$2', [ + 'as' => 'notification-mark-as-read', ]); - $routes->get('mark-all-as-read', 'NotificationController::markAllAsReadAction/$1', [ - 'as' => 'notification-mark-all-as-read', - 'filter' => 'permission:podcast$1.manage-notifications', + $routes->get('mark-all-as-read', 'NotificationController::markAllAsRead/$1', [ + 'as' => 'notification-mark-all-as-read', ]); }); }); @@ -528,60 +650,111 @@ $routes->group( ]); $routes->get( 'blocked-actors', - 'FediverseController::blockedActorsView', + 'FediverseController::blockedActors', [ - 'as' => 'fediverse-blocked-actors', - 'filter' => 'permission:fediverse.manage-blocks', + 'as' => 'fediverse-blocked-actors', + 'filter' => 'permission:fediverse-block_actors', ], ); $routes->get( 'blocked-domains', - 'FediverseController::blockedDomainsView', + 'FediverseController::blockedDomains', [ - 'as' => 'fediverse-blocked-domains', - 'filter' => 'permission:fediverse.manage-blocks', + 'as' => 'fediverse-blocked-domains', + 'filter' => 'permission:fediverse-block_domains', ], ); }); // Pages $routes->group('pages', static function ($routes): void { $routes->get('/', 'PageController::list', [ - 'as' => 'page-list', - 'filter' => 'permission:pages.manage', + 'as' => 'page-list', ]); - $routes->get('new', 'PageController::createView', [ - 'as' => 'page-create', - 'filter' => 'permission:pages.manage', + $routes->get('new', 'PageController::create', [ + 'as' => 'page-create', + 'filter' => 'permission:pages-manage', ]); - $routes->post('new', 'PageController::createAction', [ - 'filter' => 'permission:pages.manage', + $routes->post('new', 'PageController::attemptCreate', [ + 'filter' => 'permission:pages-manage', ]); $routes->group('(:num)', static function ($routes): void { $routes->get('/', 'PageController::view/$1', [ 'as' => 'page-view', ]); - $routes->get('edit', 'PageController::editView/$1', [ - 'as' => 'page-edit', - 'filter' => 'permission:pages.manage', + $routes->get('edit', 'PageController::edit/$1', [ + 'as' => 'page-edit', + 'filter' => 'permission:pages-manage', ]); - $routes->post('edit', 'PageController::editAction/$1', [ - 'filter' => 'permission:pages.manage', + $routes->post('edit', 'PageController::attemptEdit/$1', [ + 'filter' => 'permission:pages-manage', ]); - $routes->get('delete', 'PageController::deleteAction/$1', [ - 'as' => 'page-delete', - 'filter' => 'permission:pages.manage', + $routes->get('delete', 'PageController::delete/$1', [ + 'as' => 'page-delete', + 'filter' => 'permission:pages-manage', ]); }); }); - - $routes->get('about', 'AboutController', [ - 'as' => 'admin-about', - 'filter' => 'permission:admin.settings', - ]); - - $routes->post('update', 'AboutController::updateAction', [ - 'as' => 'update', - 'filter' => 'permission:admin.settings', - ]); + // Users + $routes->group('users', static function ($routes): void { + $routes->get('/', 'UserController::list', [ + 'as' => 'user-list', + 'filter' => 'permission:users-list', + ]); + $routes->get('new', 'UserController::create', [ + 'as' => 'user-create', + 'filter' => 'permission:users-create', + ]); + $routes->post('new', 'UserController::attemptCreate', [ + 'filter' => 'permission:users-create', + ]); + // User + $routes->group('(:num)', static function ($routes): void { + $routes->get('/', 'UserController::view/$1', [ + 'as' => 'user-view', + 'filter' => 'permission:users-view', + ]); + $routes->get('edit', 'UserController::edit/$1', [ + 'as' => 'user-edit', + 'filter' => 'permission:users-manage_authorizations', + ]); + $routes->post('edit', 'UserController::attemptEdit/$1', [ + 'filter' => 'permission:users-manage_authorizations', + ]); + $routes->get('ban', 'UserController::ban/$1', [ + 'as' => 'user-ban', + 'filter' => 'permission:users-manage_bans', + ]); + $routes->get('unban', 'UserController::unBan/$1', [ + 'as' => 'user-unban', + 'filter' => 'permission:users-manage_bans', + ]); + $routes->get( + 'force-pass-reset', + 'UserController::forcePassReset/$1', + [ + 'as' => 'user-force_pass_reset', + 'filter' => 'permission:users-force_pass_reset', + ], + ); + $routes->get('delete', 'UserController::delete/$1', [ + 'as' => 'user-delete', + 'filter' => 'permission:users-delete', + ]); + }); + }); + // My account + $routes->group('my-account', static function ($routes): void { + $routes->get('/', 'MyAccountController', [ + 'as' => 'my-account', + ]); + $routes->get( + 'change-password', + 'MyAccountController::changePassword/$1', + [ + 'as' => 'change-password', + ], + ); + $routes->post('change-password', 'MyAccountController::attemptChange/$1'); + }); }, ); diff --git a/modules/Admin/Controllers/AboutController.php b/modules/Admin/Controllers/AboutController.php deleted file mode 100644 index b61abf29..00000000 --- a/modules/Admin/Controllers/AboutController.php +++ /dev/null @@ -1,53 +0,0 @@ - current_domain(), - 'version' => CP_VERSION, - 'php_version' => PHP_VERSION, - 'os' => PHP_OS, - 'languages' => implode(', ', config('App')->supportedLocales), - ]; - - $this->setHtmlHead(lang('AboutCastopod.title')); - return view('settings/about', [ - 'info' => $instanceInfo, - ]); - } - - public function updateAction(): RedirectResponse - { - if ($this->request->getPost('action') === 'database') { - return $this->migrateDatabase(); - } - - return redirect()->back() - ->with('error', lang('Security.disallowedAction')); - } - - public function migrateDatabase(): RedirectResponse - { - $migrate = service('migrations'); - - $migrate->setNamespace(null) - ->latest(); - - return redirect()->back() - ->with('message', lang('AboutCastopod.messages.databaseUpdateSuccess')); - } -} diff --git a/modules/Admin/Controllers/BaseController.php b/modules/Admin/Controllers/BaseController.php index 1dc5d3bc..667460a1 100644 --- a/modules/Admin/Controllers/BaseController.php +++ b/modules/Admin/Controllers/BaseController.php @@ -4,61 +4,36 @@ declare(strict_types=1); namespace Modules\Admin\Controllers; -use App\Libraries\HtmlHead; use CodeIgniter\Controller; -use CodeIgniter\HTTP\IncomingRequest; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; -use Override; use Psr\Log\LoggerInterface; use ViewThemes\Theme; /** + * Class BaseController + * * BaseController provides a convenient place for loading components and performing functions that are needed by all - * your controllers. + * your controllers. Extend this class in any new controllers: class Home extends BaseController * - * Extend this class in any new controllers: - * ``` - * class Home extends BaseController - * ``` - * - * For security, be sure to declare any new methods as protected or private. + * For security be sure to declare any new methods as protected or private. */ abstract class BaseController extends Controller { /** - * Instance of the main Request object. - * - * @var IncomingRequest + * Constructor. */ - protected $request; - - #[Override] public function initController( RequestInterface $request, ResponseInterface $response, - LoggerInterface $logger, + LoggerInterface $logger ): void { - // Load here all helpers you want to be available in your controllers that extend BaseController. - // Caution: Do not put the this below the parent::initController() call below. - $this->helpers = [...$this->helpers, 'auth', 'breadcrumb', 'svg', 'components', 'misc']; + $this->helpers = array_merge($this->helpers, ['auth', 'breadcrumb', 'svg', 'components', 'misc']); // Do Not Edit This Line parent::initController($request, $response, $logger); Theme::setTheme('admin'); } - - protected function setHtmlHead(string $title): void - { - /** @var HtmlHead $head */ - $head = service('html_head'); - - $head - ->title($title . ' | Castopod Admin') - ->description( - 'Castopod is an open-source hosting platform made for podcasters who want engage and interact with their audience.', - ); - } } diff --git a/modules/Admin/Controllers/ContributorController.php b/modules/Admin/Controllers/ContributorController.php new file mode 100644 index 00000000..71dfc073 --- /dev/null +++ b/modules/Admin/Controllers/ContributorController.php @@ -0,0 +1,203 @@ +getPodcastById((int) $params[0])) === null) { + throw PageNotFoundException::forPageNotFound(); + } + + $this->podcast = $podcast; + + if (count($params) <= 1) { + return $this->{$method}(); + } + + if (($this->user = (new UserModel())->getPodcastContributor((int) $params[1], (int) $params[0])) !== null) { + return $this->{$method}(); + } + + throw PageNotFoundException::forPageNotFound(); + } + + public function list(): string + { + $data = [ + 'podcast' => $this->podcast, + ]; + + replace_breadcrumb_params([ + 0 => $this->podcast->title, + ]); + return view('contributor/list', $data); + } + + public function view(): string + { + $data = [ + 'podcast' => $this->podcast, + 'contributor' => (new UserModel())->getPodcastContributor($this->user->id, $this->podcast->id), + ]; + + replace_breadcrumb_params([ + 0 => $this->podcast->title, + 1 => $this->user->username, + ]); + return view('contributor/view', $data); + } + + public function add(): string + { + helper('form'); + + $users = (new UserModel())->findAll(); + $userOptions = array_reduce( + $users, + static function ($result, $user) { + $result[$user->id] = $user->username; + return $result; + }, + [], + ); + + $roles = (new GroupModel())->getContributorRoles(); + $roleOptions = array_reduce( + $roles, + static function ($result, $role) { + $result[$role->id] = lang('Contributor.roles.' . $role->name); + return $result; + }, + [], + ); + + $data = [ + 'podcast' => $this->podcast, + 'userOptions' => $userOptions, + 'roleOptions' => $roleOptions, + ]; + + replace_breadcrumb_params([ + 0 => $this->podcast->title, + ]); + return view('contributor/add', $data); + } + + public function attemptAdd(): RedirectResponse + { + try { + (new PodcastModel())->addPodcastContributor( + (int) $this->request->getPost('user'), + $this->podcast->id, + (int) $this->request->getPost('role'), + ); + } catch (Exception) { + return redirect() + ->back() + ->withInput() + ->with('errors', [lang('Contributor.messages.alreadyAddedError')]); + } + + return redirect()->route('contributor-list', [$this->podcast->id]); + } + + public function edit(): string + { + helper('form'); + + $roles = (new GroupModel())->getContributorRoles(); + $roleOptions = array_reduce( + $roles, + static function ($result, $role) { + $result[$role->id] = lang('Contributor.roles.' . $role->name); + return $result; + }, + [], + ); + + $data = [ + 'podcast' => $this->podcast, + 'user' => $this->user, + 'contributorGroupId' => (new PodcastModel())->getContributorGroupId( + $this->user->id, + $this->podcast->id, + ), + 'roleOptions' => $roleOptions, + ]; + + replace_breadcrumb_params([ + 0 => $this->podcast->title, + 1 => $this->user->username, + ]); + return view('contributor/edit', $data); + } + + public function attemptEdit(): RedirectResponse + { + (new PodcastModel())->updatePodcastContributor( + $this->user->id, + $this->podcast->id, + (int) $this->request->getPost('role'), + ); + + return redirect()->route('contributor-edit', [$this->podcast->id, $this->user->id])->with( + 'message', + lang('Contributor.messages.editSuccess') + ); + } + + public function remove(): RedirectResponse + { + if ($this->podcast->created_by === $this->user->id) { + return redirect() + ->back() + ->with('errors', [lang('Contributor.messages.removeOwnerError')]); + } + + $podcastModel = new PodcastModel(); + if ( + ! $podcastModel->removePodcastContributor($this->user->id, $this->podcast->id) + ) { + return redirect() + ->back() + ->with('errors', $podcastModel->errors()); + } + + return redirect() + ->route('contributor-list', [$this->podcast->id]) + ->with( + 'message', + lang('Contributor.messages.removeSuccess', [ + 'username' => $this->user->username, + 'podcastTitle' => $this->podcast->title, + ]), + ); + } +} diff --git a/modules/Admin/Controllers/DashboardController.php b/modules/Admin/Controllers/DashboardController.php index 725412a3..94cb7e8b 100644 --- a/modules/Admin/Controllers/DashboardController.php +++ b/modules/Admin/Controllers/DashboardController.php @@ -11,46 +11,41 @@ declare(strict_types=1); namespace Modules\Admin\Controllers; use App\Models\EpisodeModel; +use App\Models\MediaModel; use App\Models\PodcastModel; use CodeIgniter\I18n\Time; -use Modules\Media\Models\MediaModel; class DashboardController extends BaseController { public function index(): string { $podcastsData = []; - $podcastsCount = new PodcastModel() - ->builder() + $podcastsCount = (new PodcastModel())->builder() ->countAll(); - $podcastsLastPublishedAt = new PodcastModel() - ->builder() - ->selectMax('published_at', 'last_published_at') + $podcastsLastPublishedAt = (new PodcastModel())->builder() + ->select('MAX(published_at) as last_published_at') ->where('`published_at` <= UTC_TIMESTAMP()', null, false) ->get() ->getResultArray()[0]['last_published_at']; $podcastsData['number_of_podcasts'] = (int) $podcastsCount; $podcastsData['last_published_at'] = $podcastsLastPublishedAt === null ? null : new Time( - $podcastsLastPublishedAt, + $podcastsLastPublishedAt ); $episodesData = []; - $episodesCount = new EpisodeModel() - ->builder() + $episodesCount = (new EpisodeModel())->builder() ->countAll(); - $episodesLastPublishedAt = new EpisodeModel() - ->builder() - ->selectMax('published_at', 'last_published_at') + $episodesLastPublishedAt = (new EpisodeModel())->builder() + ->select('MAX(published_at) as last_published_at') ->where('`published_at` <= UTC_TIMESTAMP()', null, false) ->get() ->getResultArray()[0]['last_published_at']; $episodesData['number_of_episodes'] = (int) $episodesCount; $episodesData['last_published_at'] = $episodesLastPublishedAt === null ? null : new Time( - $episodesLastPublishedAt, + $episodesLastPublishedAt ); - $totalUploaded = new MediaModel() - ->builder() + $totalUploaded = (new MediaModel())->builder() ->selectSum('file_size') ->get() ->getResultArray()[0]; @@ -64,30 +59,24 @@ class DashboardController extends BaseController } $storageData = [ - 'limit' => formatBytes((int) $storageLimitBytes), - 'percentage' => round((((int) $totalUploaded['file_size']) / $storageLimitBytes) * 100, 0), + 'limit' => formatBytes((int) $storageLimitBytes), + 'percentage' => round((((int) $totalUploaded['file_size']) / $storageLimitBytes) * 100, 0), 'total_uploaded' => formatBytes((int) $totalUploaded['file_size']), ]; $onlyPodcastId = null; if ($podcastsData['number_of_podcasts'] === 1) { - $onlyPodcastId = new PodcastModel() - ->first() + $onlyPodcastId = (new PodcastModel())->first() ->id; } - $bandwidthLimit = config('App') - ->bandwidthLimit; - $data = [ - 'podcastsData' => $podcastsData, - 'episodesData' => $episodesData, - 'storageData' => $storageData, - 'bandwidthLimit' => $bandwidthLimit === null ? null : formatBytes($bandwidthLimit * 1000000000), - 'onlyPodcastId' => $onlyPodcastId, + 'podcastsData' => $podcastsData, + 'episodesData' => $episodesData, + 'storageData' => $storageData, + 'onlyPodcastId' => $onlyPodcastId, ]; - $this->setHtmlHead(lang('Dashboard.home')); return view('dashboard', $data); } } diff --git a/modules/Admin/Controllers/EpisodeController.php b/modules/Admin/Controllers/EpisodeController.php index 7319afd6..6c14d7f3 100644 --- a/modules/Admin/Controllers/EpisodeController.php +++ b/modules/Admin/Controllers/EpisodeController.php @@ -17,15 +17,12 @@ use App\Entities\Podcast; use App\Entities\Post; use App\Models\EpisodeCommentModel; use App\Models\EpisodeModel; +use App\Models\MediaModel; use App\Models\PodcastModel; use App\Models\PostModel; use CodeIgniter\Exceptions\PageNotFoundException; -use CodeIgniter\HTTP\Files\UploadedFile; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\I18n\Time; -use Modules\Media\Entities\Chapters; -use Modules\Media\Entities\Transcript; -use Modules\Media\Models\MediaModel; class EpisodeController extends BaseController { @@ -35,126 +32,116 @@ class EpisodeController extends BaseController public function _remap(string $method, string ...$params): mixed { - if ($params === []) { - throw PageNotFoundException::forPageNotFound(); - } - - if (count($params) === 1) { - if (! ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - return $this->{$method}($podcast); - } - if ( - ! ($episode = new EpisodeModel()->getEpisodeById((int) $params[1])) instanceof Episode + ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) === null ) { throw PageNotFoundException::forPageNotFound(); } - unset($params[0]); - unset($params[1]); + $this->podcast = $podcast; - return $this->{$method}($episode, ...$params); + if (count($params) > 1) { + if ( + ! ($episode = (new EpisodeModel()) + ->where([ + 'id' => $params[1], + 'podcast_id' => $params[0], + ]) + ->first()) + ) { + throw PageNotFoundException::forPageNotFound(); + } + + $this->episode = $episode; + + unset($params[1]); + unset($params[0]); + } + + return $this->{$method}(...$params); } - public function list(Podcast $podcast): string + public function list(): string { /** @var ?string $query */ $query = $this->request->getGet('q'); - $episodeModel = new EpisodeModel(); if ($query !== null && $query !== '') { // Default value for MySQL Full-Text Search's minimum length of words is 4. // Use LIKE operator as a fallback. if (strlen($query) < 4) { - $episodes = $episodeModel - ->where('podcast_id', $podcast->id) - ->like('title', $episodeModel->db->escapeLikeString($query)) - ->orLike('description_markdown', $episodeModel->db->escapeLikeString($query)) - ->orLike('slug', $episodeModel->db->escapeLikeString($query)) - ->orLike('location_name', $episodeModel->db->escapeLikeString($query)) - ->orderBy('-`published_at`', '', false) + $episodes = (new EpisodeModel()) + ->where('podcast_id', $this->podcast->id) + ->like('title', $query) + ->orLike('description_markdown', $query) ->orderBy('created_at', 'desc'); } else { - $episodes = $episodeModel - ->where('podcast_id', $podcast->id) - ->where( - "MATCH (title, description_markdown, slug, location_name) AGAINST ('{$episodeModel->db->escapeString( - $query, - )}')", - ); + $episodes = (new EpisodeModel()) + ->where('podcast_id', $this->podcast->id) + ->where("MATCH (title, description_markdown) AGAINST ('{$query}')"); } } else { - $episodes = $episodeModel - ->where('podcast_id', $podcast->id) - ->orderBy('-`published_at`', '', false) + $episodes = (new EpisodeModel()) + ->where('podcast_id', $this->podcast->id) ->orderBy('created_at', 'desc'); } helper('form'); $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, 'episodes' => $episodes->paginate(10), - 'pager' => $episodes->pager, - 'query' => $query, + 'pager' => $episodes->pager, + 'query' => $query, ]; - $this->setHtmlHead(lang('Episode.all_podcast_episodes')); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('episode/list', $data); } - public function view(Episode $episode): string + public function view(): string { $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, ]; - $this->setHtmlHead($episode->title); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/view', $data); } - public function createView(Podcast $podcast): string + public function create(): string { helper(['form']); - $currentSeasonNumber = new EpisodeModel() - ->getCurrentSeasonNumber($podcast->id); + $currentSeasonNumber = (new EpisodeModel())->getCurrentSeasonNumber($this->podcast->id); $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, 'currentSeasonNumber' => $currentSeasonNumber, - 'nextEpisodeNumber' => new EpisodeModel() - ->getNextEpisodeNumber($podcast->id, $currentSeasonNumber), + 'nextEpisodeNumber' => (new EpisodeModel())->getNextEpisodeNumber($this->podcast->id, $currentSeasonNumber), ]; - - $this->setHtmlHead(lang('Episode.create')); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('episode/create', $data); } - public function createAction(Podcast $podcast): RedirectResponse + public function attemptCreate(): RedirectResponse { $rules = [ - 'title' => 'required', - 'slug' => 'required|max_length[128]', - 'audio_file' => 'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]', - 'cover' => 'is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', - 'transcript_file' => 'ext_in[transcript_file,srt,vtt]', - 'chapters_file' => 'ext_in[chapters_file,json]|is_json[chapters_file]', + 'audio_file' => 'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]', + 'cover' => + 'is_image[cover]|ext_in[cover,jpg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', + 'transcript_file' => + 'ext_in[transcript,srt]|permit_empty', + 'chapters_file' => 'ext_in[chapters,json]|permit_empty', ]; - if ($podcast->type === 'serial' && $this->request->getPost('type') === 'full') { + if ($this->podcast->type === 'serial') { $rules['episode_number'] = 'required'; } @@ -165,36 +152,36 @@ class EpisodeController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - if (new EpisodeModel() + if ((new EpisodeModel()) ->where([ - 'slug' => $validData['slug'], - 'podcast_id' => $podcast->id, + 'slug' => $this->request->getPost('slug'), + 'podcast_id' => $this->podcast->id, ]) - ->first() instanceof Episode) { + ->first()) { return redirect() ->back() ->withInput() ->with('error', lang('Episode.messages.sameSlugError')); } + $db = db_connect(); + $db->transStart(); + $newEpisode = new Episode([ - 'created_by' => user_id(), - 'updated_by' => user_id(), - 'podcast_id' => $podcast->id, - 'title' => $this->request->getPost('title'), - 'slug' => $this->request->getPost('slug'), - 'guid' => null, - 'audio' => $this->request->getFile('audio_file'), - 'cover' => $this->request->getFile('cover'), + 'podcast_id' => $this->podcast->id, + 'title' => $this->request->getPost('title'), + 'slug' => $this->request->getPost('slug'), + 'guid' => null, + 'audio' => $this->request->getFile('audio_file'), + 'cover' => $this->request->getFile('cover'), 'description_markdown' => $this->request->getPost('description'), - 'location' => $this->request->getPost('location_name') === '' ? null : new Location( - $this->request->getPost('location_name'), - ), - 'transcript' => $this->request->getFile('transcript'), - 'chapters' => $this->request->getFile('chapters'), - 'parental_advisory' => $this->request->getPost('parental_advisory') !== 'undefined' + 'location' => $this->request->getPost('location_name') === '' ? null : new Location($this->request->getPost( + 'location_name' + )), + 'transcript' => $this->request->getFile('transcript'), + 'chapters' => $this->request->getFile('chapters'), + 'parental_advisory' => + $this->request->getPost('parental_advisory') !== 'undefined' ? $this->request->getPost('parental_advisory') : null, 'number' => $this->request->getPost('episode_number') @@ -203,9 +190,12 @@ class EpisodeController extends BaseController 'season_number' => $this->request->getPost('season_number') ? (int) $this->request->getPost('season_number') : null, - 'type' => $this->request->getPost('type'), - 'is_blocked' => $this->request->getPost('block') === 'yes', - 'is_premium' => $this->request->getPost('premium') === 'yes', + 'type' => $this->request->getPost('type'), + 'is_blocked' => $this->request->getPost('block') === 'yes', + 'custom_rss_string' => $this->request->getPost('custom_rss'), + 'is_premium' => $this->request->getPost('premium') === 'yes', + 'created_by' => user_id(), + 'updated_by' => user_id(), 'published_at' => null, ]); @@ -214,7 +204,7 @@ class EpisodeController extends BaseController $newEpisode->setTranscript($this->request->getFile('transcript_file')); } elseif ($transcriptChoice === 'remote-url') { $newEpisode->transcript_remote_url = $this->request->getPost( - 'transcript_remote_url', + 'transcript_remote_url' ) === '' ? null : $this->request->getPost('transcript_remote_url'); } @@ -223,53 +213,73 @@ class EpisodeController extends BaseController $newEpisode->setChapters($this->request->getFile('chapters_file')); } elseif ($chaptersChoice === 'remote-url') { $newEpisode->chapters_remote_url = $this->request->getPost( - 'chapters_remote_url', + 'chapters_remote_url' ) === '' ? null : $this->request->getPost('chapters_remote_url'); } $episodeModel = new EpisodeModel(); if (! ($newEpisodeId = $episodeModel->insert($newEpisode, true))) { + $db->transRollback(); return redirect() ->back() ->withInput() ->with('errors', $episodeModel->errors()); } - return redirect()->route('episode-view', [$podcast->id, $newEpisodeId])->with( + // update podcast's episode_description_footer_markdown if changed + $this->podcast->episode_description_footer_markdown = $this->request->getPost( + 'description_footer' + ) === '' ? null : $this->request->getPost('description_footer'); + + if ($this->podcast->hasChanged('episode_description_footer_markdown')) { + $podcastModel = new PodcastModel(); + + if (! $podcastModel->update($this->podcast->id, $this->podcast)) { + $db->transRollback(); + return redirect() + ->back() + ->withInput() + ->with('errors', $podcastModel->errors()); + } + } + + $db->transComplete(); + + return redirect()->route('episode-view', [$this->podcast->id, $newEpisodeId])->with( 'message', - lang('Episode.messages.createSuccess'), + lang('Episode.messages.createSuccess') ); } - public function editView(Episode $episode): string + public function edit(): string { helper(['form']); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, ]; - $this->setHtmlHead(lang('Episode.edit')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/edit', $data); } - public function editAction(Episode $episode): RedirectResponse + public function attemptEdit(): RedirectResponse { $rules = [ - 'title' => 'required', - 'slug' => 'required|max_length[128]', - 'audio_file' => 'ext_in[audio_file,mp3,m4a]', - 'cover' => 'is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', - 'transcript_file' => 'ext_in[transcript_file,srt,vtt]', - 'chapters_file' => 'ext_in[chapters_file,json]|is_json[chapters_file]', + 'audio_file' => + 'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]|permit_empty', + 'cover' => + 'is_image[cover]|ext_in[cover,jpg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', + 'transcript_file' => + 'ext_in[transcript_file,txt,html,srt,json]|permit_empty', + 'chapters_file' => 'ext_in[chapters_file,json]|permit_empty', ]; - if ($episode->podcast->type === 'serial' && $this->request->getPost('type') === 'full') { + if ($this->podcast->type === 'serial') { $rules['episode_number'] = 'required'; } @@ -280,91 +290,117 @@ class EpisodeController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - $episode->title = $this->request->getPost('title'); - $episode->slug = $validData['slug']; - $episode->description_markdown = $this->request->getPost('description'); - $episode->location = $this->request->getPost('location_name') === '' ? null : new Location( - $this->request->getPost('location_name'), + $this->episode->title = $this->request->getPost('title'); + $this->episode->slug = $this->request->getPost('slug'); + $this->episode->description_markdown = $this->request->getPost('description'); + $this->episode->location = $this->request->getPost('location_name') === '' ? null : new Location( + $this->request->getPost('location_name') ); - $episode->parental_advisory = + $this->episode->parental_advisory = $this->request->getPost('parental_advisory') !== 'undefined' ? $this->request->getPost('parental_advisory') : null; - $episode->number = $this->request->getPost('episode_number') ?: null; - $episode->season_number = $this->request->getPost('season_number') ?: null; - $episode->type = $this->request->getPost('type'); - $episode->is_blocked = $this->request->getPost('block') === 'yes'; - $episode->is_premium = $this->request->getPost('premium') === 'yes'; + $this->episode->number = $this->request->getPost('episode_number') + ? $this->request->getPost('episode_number') + : null; + $this->episode->season_number = $this->request->getPost('season_number') + ? $this->request->getPost('season_number') + : null; + $this->episode->type = $this->request->getPost('type'); + $this->episode->is_blocked = $this->request->getPost('block') === 'yes'; + $this->episode->custom_rss_string = $this->request->getPost('custom_rss'); + $this->episode->is_premium = $this->request->getPost('premium') === 'yes'; - $episode->updated_by = (int) user_id(); - $episode->setAudio($this->request->getFile('audio_file')); - $episode->setCover($this->request->getFile('cover')); + $this->episode->updated_by = (int) user_id(); + $this->episode->setAudio($this->request->getFile('audio_file')); + $this->episode->setCover($this->request->getFile('cover')); // republish on websub hubs upon edit - $episode->is_published_on_hubs = false; + $this->episode->is_published_on_hubs = false; $transcriptChoice = $this->request->getPost('transcript-choice'); if ($transcriptChoice === 'upload-file') { $transcriptFile = $this->request->getFile('transcript_file'); - if ($transcriptFile instanceof UploadedFile && $transcriptFile->isValid()) { - $episode->setTranscript($transcriptFile); - $episode->transcript_remote_url = null; + if ($transcriptFile !== null && $transcriptFile->isValid()) { + $this->episode->setTranscript($transcriptFile); + $this->episode->transcript_remote_url = null; } } elseif ($transcriptChoice === 'remote-url') { if ( ($transcriptRemoteUrl = $this->request->getPost('transcript_remote_url')) && - (($transcriptFile = $episode->transcript_id) !== null) + (($transcriptFile = $this->episode->transcript_id) !== null) ) { - new MediaModel() - ->deleteMedia($episode->transcript); + (new MediaModel())->deleteMedia($this->episode->transcript); } - $episode->transcript_remote_url = $transcriptRemoteUrl === '' ? null : $transcriptRemoteUrl; + $this->episode->transcript_remote_url = $transcriptRemoteUrl === '' ? null : $transcriptRemoteUrl; } $chaptersChoice = $this->request->getPost('chapters-choice'); if ($chaptersChoice === 'upload-file') { $chaptersFile = $this->request->getFile('chapters_file'); - if ($chaptersFile instanceof UploadedFile && $chaptersFile->isValid()) { - $episode->setChapters($chaptersFile); - $episode->chapters_remote_url = null; + if ($chaptersFile !== null && $chaptersFile->isValid()) { + $this->episode->setChapters($chaptersFile); + $this->episode->chapters_remote_url = null; } } elseif ($chaptersChoice === 'remote-url') { if ( ($chaptersRemoteUrl = $this->request->getPost('chapters_remote_url')) && - (($chaptersFile = $episode->chapters) instanceof Chapters) + (($chaptersFile = $this->episode->chapters) !== null) ) { - new MediaModel() - ->deleteMedia($episode->chapters); + (new MediaModel())->deleteMedia($this->episode->chapters); } - $episode->chapters_remote_url = $chaptersRemoteUrl === '' ? null : $chaptersRemoteUrl; + $this->episode->chapters_remote_url = $chaptersRemoteUrl === '' ? null : $chaptersRemoteUrl; } + $db = db_connect(); + $db->transStart(); + $episodeModel = new EpisodeModel(); - if (! $episodeModel->update($episode->id, $episode)) { + + if (! $episodeModel->update($this->episode->id, $this->episode)) { + $db->transRollback(); + return redirect() ->back() ->withInput() ->with('errors', $episodeModel->errors()); } - return redirect()->route('episode-edit', [$episode->podcast_id, $episode->id])->with( + // update podcast's episode_description_footer_markdown if changed + $this->podcast->episode_description_footer_markdown = $this->request->getPost( + 'description_footer' + ) === '' ? null : $this->request->getPost('description_footer'); + + if ($this->podcast->hasChanged('episode_description_footer_markdown')) { + $podcastModel = new PodcastModel(); + if (! $podcastModel->update($this->podcast->id, $this->podcast)) { + $db->transRollback(); + + return redirect() + ->back() + ->withInput() + ->with('errors', $podcastModel->errors()); + } + } + + $db->transComplete(); + + return redirect()->route('episode-edit', [$this->podcast->id, $this->episode->id])->with( 'message', - lang('Episode.messages.editSuccess'), + lang('Episode.messages.editSuccess') ); } - public function transcriptDelete(Episode $episode): RedirectResponse + public function transcriptDelete(): RedirectResponse { - if (! $episode->transcript instanceof Transcript) { + if ($this->episode->transcript === null) { return redirect()->back(); } $mediaModel = new MediaModel(); - if (! $mediaModel->deleteMedia($episode->transcript)) { + if (! $mediaModel->deleteMedia($this->episode->transcript)) { return redirect() ->back() ->withInput() @@ -374,14 +410,14 @@ class EpisodeController extends BaseController return redirect()->back(); } - public function chaptersDelete(Episode $episode): RedirectResponse + public function chaptersDelete(): RedirectResponse { - if (! $episode->chapters instanceof Chapters) { + if ($this->episode->chapters === null) { return redirect()->back(); } $mediaModel = new MediaModel(); - if (! $mediaModel->deleteMedia($episode->chapters)) { + if (! $mediaModel->deleteMedia($this->episode->chapters)) { return redirect() ->back() ->withInput() @@ -391,36 +427,36 @@ class EpisodeController extends BaseController return redirect()->back(); } - public function publishView(Episode $episode): string | RedirectResponse + public function publish(): string | RedirectResponse { - if ($episode->publication_status === 'not_published') { + if ($this->episode->publication_status === 'not_published') { helper(['form']); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, ]; - $this->setHtmlHead(lang('Episode.publish')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/publish', $data); } - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( 'error', - lang('Episode.publish_error'), + lang('Episode.publish_error') ); } - public function publishAction(Episode $episode): RedirectResponse + public function attemptPublish(): RedirectResponse { - if ($episode->podcast->publication_status === 'published') { + if ($this->podcast->publication_status === 'published') { $rules = [ - 'publication_method' => 'required', - 'scheduled_publication_date' => 'valid_date[Y-m-d H:i]|permit_empty', + 'publication_method' => 'required', + 'scheduled_publication_date' => + 'valid_date[Y-m-d H:i]|permit_empty', ]; if (! $this->validate($rules)) { @@ -435,18 +471,18 @@ class EpisodeController extends BaseController $db->transStart(); $newPost = new Post([ - 'actor_id' => $episode->podcast->actor_id, - 'episode_id' => $episode->id, - 'message' => $this->request->getPost('message'), + 'actor_id' => $this->podcast->actor_id, + 'episode_id' => $this->episode->id, + 'message' => $this->request->getPost('message'), 'created_by' => user_id(), ]); - if ($episode->podcast->publication_status === 'published') { + if ($this->podcast->publication_status === 'published') { $publishMethod = $this->request->getPost('publication_method'); if ($publishMethod === 'schedule') { $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date'); if ($scheduledPublicationDate) { - $episode->published_at = Time::createFromFormat( + $this->episode->published_at = Time::createFromFormat( 'Y-m-d H:i', $scheduledPublicationDate, $this->request->getPost('client_timezone'), @@ -459,16 +495,16 @@ class EpisodeController extends BaseController ->with('error', lang('Episode.messages.scheduleDateError')); } } else { - $episode->published_at = Time::now(); + $this->episode->published_at = Time::now(); } - } elseif ($episode->podcast->publication_status === 'scheduled') { + } elseif ($this->podcast->publication_status === 'scheduled') { // podcast publication date has already been set - $episode->published_at = $episode->podcast->published_at->addSeconds(1); + $this->episode->published_at = $this->podcast->published_at->addSeconds(1); } else { - $episode->published_at = Time::now(); + $this->episode->published_at = Time::now(); } - $newPost->published_at = $episode->published_at; + $newPost->published_at = $this->episode->published_at; $postModel = new PostModel(); if (! $postModel->addPost($newPost)) { @@ -480,7 +516,7 @@ class EpisodeController extends BaseController } $episodeModel = new EpisodeModel(); - if (! $episodeModel->update($episode->id, $episode)) { + if (! $episodeModel->update($this->episode->id, $this->episode)) { $db->transRollback(); return redirect() ->back() @@ -490,51 +526,51 @@ class EpisodeController extends BaseController $db->transComplete(); - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( 'message', lang('Episode.messages.publishSuccess', [ - 'publication_status' => $episode->publication_status, - ]), + 'publication_status' => $this->episode->publication_status, + ]) ); } - public function publishEditView(Episode $episode): string | RedirectResponse + public function publishEdit(): string | RedirectResponse { - if (in_array($episode->publication_status, ['scheduled', 'with_podcast'], true)) { + if (in_array($this->episode->publication_status, ['scheduled', 'with_podcast'], true)) { helper(['form']); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, - 'post' => new PostModel() + 'podcast' => $this->podcast, + 'episode' => $this->episode, + 'post' => (new PostModel()) ->where([ - 'actor_id' => $episode->podcast->actor_id, - 'episode_id' => $episode->id, + 'actor_id' => $this->podcast->actor_id, + 'episode_id' => $this->episode->id, ]) ->first(), ]; - $this->setHtmlHead(lang('Episode.publish_edit')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/publish_edit', $data); } - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( 'error', - lang('Episode.publish_edit_error'), + lang('Episode.publish_edit_error') ); } - public function publishEditAction(Episode $episode): RedirectResponse + public function attemptPublishEdit(): RedirectResponse { - if ($episode->podcast->publication_status === 'published') { + if ($this->podcast->publication_status === 'published') { $rules = [ - 'post_id' => 'required', - 'publication_method' => 'required', - 'scheduled_publication_date' => 'valid_date[Y-m-d H:i]|permit_empty', + 'post_id' => 'required', + 'publication_method' => 'required', + 'scheduled_publication_date' => + 'valid_date[Y-m-d H:i]|permit_empty', ]; if (! $this->validate($rules)) { @@ -548,12 +584,12 @@ class EpisodeController extends BaseController $db = db_connect(); $db->transStart(); - if ($episode->podcast->publication_status === 'published') { + if ($this->podcast->publication_status === 'published') { $publishMethod = $this->request->getPost('publication_method'); if ($publishMethod === 'schedule') { $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date'); if ($scheduledPublicationDate) { - $episode->published_at = Time::createFromFormat( + $this->episode->published_at = Time::createFromFormat( 'Y-m-d H:i', $scheduledPublicationDate, $this->request->getPost('client_timezone'), @@ -566,21 +602,20 @@ class EpisodeController extends BaseController ->with('error', lang('Episode.messages.scheduleDateError')); } } else { - $episode->published_at = Time::now(); + $this->episode->published_at = Time::now(); } - } elseif ($episode->podcast->publication_status === 'scheduled') { + } elseif ($this->podcast->publication_status === 'scheduled') { // podcast publication date has already been set - $episode->published_at = $episode->podcast->published_at->addSeconds(1); + $this->episode->published_at = $this->podcast->published_at->addSeconds(1); } else { - $episode->published_at = Time::now(); + $this->episode->published_at = Time::now(); } - $post = new PostModel() - ->getPostById($this->request->getPost('post_id')); + $post = (new PostModel())->getPostById($this->request->getPost('post_id')); - if ($post instanceof Post) { + if ($post !== null) { $post->message = $this->request->getPost('message'); - $post->published_at = $episode->published_at; + $post->published_at = $this->episode->published_at; $postModel = new PostModel(); if (! $postModel->editPost($post)) { @@ -593,7 +628,7 @@ class EpisodeController extends BaseController } $episodeModel = new EpisodeModel(); - if (! $episodeModel->update($episode->id, $episode)) { + if (! $episodeModel->update($this->episode->id, $this->episode)) { $db->transRollback(); return redirect() ->back() @@ -603,33 +638,33 @@ class EpisodeController extends BaseController $db->transComplete(); - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( 'message', lang('Episode.messages.publishSuccess', [ - 'publication_status' => $episode->publication_status, - ]), + 'publication_status' => $this->episode->publication_status, + ]) ); } - public function publishCancelAction(Episode $episode): RedirectResponse + public function publishCancel(): RedirectResponse { - if (in_array($episode->publication_status, ['scheduled', 'with_podcast'], true)) { + if (in_array($this->episode->publication_status, ['scheduled', 'with_podcast'], true)) { $db = db_connect(); $db->transStart(); $postModel = new PostModel(); $post = $postModel ->where([ - 'actor_id' => $episode->podcast->actor_id, - 'episode_id' => $episode->id, + 'actor_id' => $this->podcast->actor_id, + 'episode_id' => $this->episode->id, ]) ->first(); $postModel->removePost($post); - $episode->published_at = null; + $this->episode->published_at = null; $episodeModel = new EpisodeModel(); - if (! $episodeModel->update($episode->id, $episode)) { + if (! $episodeModel->update($this->episode->id, $this->episode)) { $db->transRollback(); return redirect() ->back() @@ -639,37 +674,37 @@ class EpisodeController extends BaseController $db->transComplete(); - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( 'message', - lang('Episode.messages.publishCancelSuccess'), + lang('Episode.messages.publishCancelSuccess') ); } - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id]); + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]); } - public function publishDateEditView(Episode $episode): string|RedirectResponse + public function publishDateEdit(): string|RedirectResponse { // only accessible if episode is already published - if ($episode->publication_status !== 'published') { - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with( + if ($this->episode->publication_status !== 'published') { + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( 'error', - lang('Episode.publish_date_edit_error'), + lang('Episode.publish_date_edit_error') ); } helper('form'); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, ]; - $this->setHtmlHead(lang('Episode.publish_date_edit')); replace_breadcrumb_params([ - 0 => $episode->podcast->title, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); + return view('episode/publish_date_edit', $data); } @@ -679,7 +714,7 @@ class EpisodeController extends BaseController * Prevents setting a future date as it does not make sense to set a future published date to an already published * episode. This also prevents any side-effects from occurring. */ - public function publishDateEditAction(Episode $episode): RedirectResponse + public function attemptPublishDateEdit(): RedirectResponse { $rules = [ 'new_publication_date' => 'valid_date[Y-m-d H:i]', @@ -692,9 +727,7 @@ class EpisodeController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - $newPublicationDate = $validData['new_publication_date']; + $newPublicationDate = $this->request->getPost('new_publication_date'); $newPublicationDate = Time::createFromFormat( 'Y-m-d H:i', @@ -709,47 +742,46 @@ class EpisodeController extends BaseController ->with('error', lang('Episode.publish_date_edit_future_error')); } - $episode->published_at = $newPublicationDate; + $this->episode->published_at = $newPublicationDate; $episodeModel = new EpisodeModel(); - if (! $episodeModel->update($episode->id, $episode)) { + if (! $episodeModel->update($this->episode->id, $this->episode)) { return redirect() ->back() ->withInput() ->with('errors', $episodeModel->errors()); } - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( 'message', - lang('Episode.publish_date_edit_success'), + lang('Episode.publish_date_edit_success') ); } - public function unpublishView(Episode $episode): string | RedirectResponse + public function unpublish(): string | RedirectResponse { - if ($episode->publication_status !== 'published') { - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id])->with( + if ($this->episode->publication_status !== 'published') { + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with( 'error', - lang('Episode.unpublish_error'), + lang('Episode.unpublish_error') ); } helper(['form']); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, ]; - $this->setHtmlHead(lang('Episode.unpublish')); replace_breadcrumb_params([ - 0 => $episode->podcast->title, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/unpublish', $data); } - public function unpublishAction(Episode $episode): RedirectResponse + public function attemptUnpublish(): RedirectResponse { $rules = [ 'understand' => 'required', @@ -766,34 +798,32 @@ class EpisodeController extends BaseController $db->transStart(); - $allPostsLinkedToEpisode = new PostModel() + $allPostsLinkedToEpisode = (new PostModel()) ->where([ - 'episode_id' => $episode->id, + 'episode_id' => $this->episode->id, 'in_reply_to_id' => null, - 'reblog_of_id' => null, + 'reblog_of_id' => null, ]) ->findAll(); foreach ($allPostsLinkedToEpisode as $post) { - new PostModel() - ->removePost($post); + (new PostModel())->removePost($post); } - $allCommentsLinkedToEpisode = new EpisodeCommentModel() + $allCommentsLinkedToEpisode = (new EpisodeCommentModel()) ->where([ - 'episode_id' => $episode->id, + 'episode_id' => $this->episode->id, 'in_reply_to_id' => null, ]) ->findAll(); foreach ($allCommentsLinkedToEpisode as $comment) { - new EpisodeCommentModel() - ->removeComment($comment); + (new EpisodeCommentModel())->removeComment($comment); } // set episode published_at to null to unpublish - $episode->published_at = null; + $this->episode->published_at = null; $episodeModel = new EpisodeModel(); - if (! $episodeModel->update($episode->id, $episode)) { + if (! $episodeModel->update($this->episode->id, $this->episode)) { $db->transRollback(); return redirect() ->back() @@ -802,34 +832,32 @@ class EpisodeController extends BaseController } // set podcast is_published_on_hubs to false to trigger websub push - new PodcastModel() - ->update($episode->podcast_id, [ - 'is_published_on_hubs' => 0, - ]); + (new PodcastModel())->update($this->episode->podcast->id, [ + 'is_published_on_hubs' => false, + ]); $db->transComplete(); - return redirect()->route('episode-view', [$episode->podcast_id, $episode->id]); + return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]); } - public function deleteView(Episode $episode): string + public function delete(): string { helper(['form']); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, ]; - $this->setHtmlHead(lang('Episode.delete')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/delete', $data); } - public function deleteAction(Episode $episode): RedirectResponse + public function attemptDelete(): RedirectResponse { $rules = [ 'understand' => 'required', @@ -842,7 +870,7 @@ class EpisodeController extends BaseController ->with('errors', $this->validator->getErrors()); } - if ($episode->published_at instanceof Time) { + if ($this->episode->published_at !== null) { return redirect() ->back() ->withInput() @@ -855,7 +883,7 @@ class EpisodeController extends BaseController $episodeModel = new EpisodeModel(); - if (! $episodeModel->delete($episode->id)) { + if (! $episodeModel->delete($this->episode->id)) { $db->transRollback(); return redirect() ->back() @@ -863,18 +891,16 @@ class EpisodeController extends BaseController ->with('errors', $episodeModel->errors()); } - $episodeMediaList = [$episode->transcript, $episode->chapters, $episode->audio]; + $episodeMediaList = [$this->episode->transcript, $this->episode->chapters, $this->episode->audio]; //only delete episode cover if different from podcast's - if ($episode->cover_id !== null) { - $episodeMediaList[] = $episode->cover; + if ($this->episode->cover_id !== null) { + $episodeMediaList[] = $this->episode->cover; } - $mediaModel = new MediaModel(); - //delete episode media records from database foreach ($episodeMediaList as $episodeMedia) { - if ($episodeMedia !== null && ! $mediaModel->delete($episodeMedia->id)) { + if ($episodeMedia !== null && ! $episodeMedia->delete()) { $db->transRollback(); return redirect() ->back() @@ -891,52 +917,45 @@ class EpisodeController extends BaseController //remove episode media files from disk foreach ($episodeMediaList as $episodeMedia) { - if ($episodeMedia === null) { - continue; + if ($episodeMedia !== null && ! $episodeMedia->deleteFile()) { + $warnings[] = lang('Episode.messages.deleteFileError', [ + 'type' => $episodeMedia->type, + 'file_path' => $episodeMedia->file_path, + ]); } - - if ($episodeMedia->deleteFile()) { - continue; - } - - $warnings[] = lang('Episode.messages.deleteFileError', [ - 'type' => $episodeMedia->type, - 'file_key' => $episodeMedia->file_key, - ]); } if ($warnings !== []) { return redirect() - ->route('episode-list', [$episode->podcast_id]) + ->route('episode-list', [$this->podcast->id]) ->with('message', lang('Episode.messages.deleteSuccess')) ->with('warnings', $warnings); } - return redirect()->route('episode-list', [$episode->podcast_id])->with( + return redirect()->route('episode-list', [$this->podcast->id])->with( 'message', - lang('Episode.messages.deleteSuccess'), + lang('Episode.messages.deleteSuccess') ); } - public function embedView(Episode $episode): string + public function embed(): string { helper(['form']); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, - 'themes' => EpisodeModel::$themes, + 'podcast' => $this->podcast, + 'episode' => $this->episode, + 'themes' => EpisodeModel::$themes, ]; - $this->setHtmlHead(lang('Episode.embed.title')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/embed', $data); } - public function commentCreateAction(Episode $episode): RedirectResponse + public function attemptCommentCreate(): RedirectResponse { $rules = [ 'message' => 'required|max_length[500]', @@ -949,12 +968,12 @@ class EpisodeController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); + $message = $this->request->getPost('message'); $newComment = new EpisodeComment([ - 'actor_id' => interact_as_actor_id(), - 'episode_id' => $episode->id, - 'message' => $validData['message'], + 'actor_id' => interact_as_actor_id(), + 'episode_id' => $this->episode->id, + 'message' => $message, 'created_at' => new Time('now'), 'created_by' => user_id(), ]); @@ -973,7 +992,7 @@ class EpisodeController extends BaseController return redirect()->back(); } - public function commentReplyAction(Episode $episode, string $commentId): RedirectResponse + public function attemptCommentReply(string $commentId): RedirectResponse { $rules = [ 'message' => 'required|max_length[500]', @@ -986,15 +1005,15 @@ class EpisodeController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); + $message = $this->request->getPost('message'); $newReply = new EpisodeComment([ - 'actor_id' => interact_as_actor_id(), - 'episode_id' => $episode->id, - 'message' => $validData['message'], + 'actor_id' => interact_as_actor_id(), + 'episode_id' => $this->episode->id, + 'message' => $message, 'in_reply_to_id' => $commentId, - 'created_at' => new Time('now'), - 'created_by' => user_id(), + 'created_at' => new Time('now'), + 'created_by' => user_id(), ]); $commentModel = new EpisodeCommentModel(); diff --git a/modules/Admin/Controllers/EpisodePersonController.php b/modules/Admin/Controllers/EpisodePersonController.php index dd8c8e4a..ee46c04d 100644 --- a/modules/Admin/Controllers/EpisodePersonController.php +++ b/modules/Admin/Controllers/EpisodePersonController.php @@ -20,54 +20,52 @@ use CodeIgniter\HTTP\RedirectResponse; class EpisodePersonController extends BaseController { + protected Podcast $podcast; + + protected Episode $episode; + public function _remap(string $method, string ...$params): mixed { - if ($params === []) { + if (count($params) < 2) { throw PageNotFoundException::forPageNotFound(); } - if (count($params) === 1) { - if (! ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - return $this->{$method}($podcast); - } - if ( - ! ($episode = new EpisodeModel()->getEpisodeById((int) $params[1])) instanceof Episode + ($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) && + ($this->episode = (new EpisodeModel()) + ->where([ + 'id' => $params[1], + 'podcast_id' => $params[0], + ]) + ->first()) ) { - throw PageNotFoundException::forPageNotFound(); + unset($params[1]); + unset($params[0]); + + return $this->{$method}(...$params); } - unset($params[0]); - unset($params[1]); - - return $this->{$method}($episode, ...$params); + throw PageNotFoundException::forPageNotFound(); } - public function index(Episode $episode): string + public function index(): string { helper('form'); $data = [ - 'episode' => $episode, - 'podcast' => $episode->podcast, - 'personOptions' => new PersonModel() - ->getPersonOptions(), - 'taxonomyOptions' => new PersonModel() - ->getTaxonomyOptions(), + 'episode' => $this->episode, + 'podcast' => $this->podcast, + 'personOptions' => (new PersonModel())->getPersonOptions(), + 'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(), ]; - - $this->setHtmlHead(lang('Person.episode_form.title')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/persons', $data); } - public function createAction(Episode $episode): RedirectResponse + public function attemptAdd(): RedirectResponse { $rules = [ 'persons' => 'required', @@ -80,23 +78,19 @@ class EpisodePersonController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - new PersonModel() - ->addEpisodePersons( - $episode->podcast_id, - $episode->id, - $validData['persons'], - $this->request->getPost('roles') ?? [], - ); + (new PersonModel())->addEpisodePersons( + $this->podcast->id, + $this->episode->id, + $this->request->getPost('persons'), + $this->request->getPost('roles') ?? [], + ); return redirect()->back(); } - public function deleteAction(Episode $episode, string $personId): RedirectResponse + public function remove(string $personId): RedirectResponse { - new PersonModel() - ->removePersonFromEpisode($episode->podcast_id, $episode->id, (int) $personId); + (new PersonModel())->removePersonFromEpisode($this->podcast->id, $this->episode->id, (int) $personId); return redirect()->back(); } diff --git a/modules/Admin/Controllers/FediverseController.php b/modules/Admin/Controllers/FediverseController.php index 55b9ffcd..d7cd40f5 100644 --- a/modules/Admin/Controllers/FediverseController.php +++ b/modules/Admin/Controllers/FediverseController.php @@ -10,36 +10,32 @@ declare(strict_types=1); namespace Modules\Admin\Controllers; -use CodeIgniter\HTTP\RedirectResponse; - class FediverseController extends BaseController { - public function dashboard(): RedirectResponse + public function dashboard(): string { - return redirect()->route('fediverse-blocked-actors'); + return view('fediverse/dashboard'); } - public function blockedActorsView(): string + public function blockedActors(): string { helper(['form']); $blockedActors = model('ActorModel', false) ->getBlockedActors(); - $this->setHtmlHead(lang('Fediverse.blocked_actors')); return view('fediverse/blocked_actors', [ 'blockedActors' => $blockedActors, ]); } - public function blockedDomainsView(): string + public function blockedDomains(): string { helper(['form']); $blockedDomains = model('BlockedDomainModel', false) ->getBlockedDomains(); - $this->setHtmlHead(lang('Fediverse.blocked_domains')); return view('fediverse/blocked_domains', [ 'blockedDomains' => $blockedDomains, ]); diff --git a/modules/Auth/Controllers/MyAccountController.php b/modules/Admin/Controllers/MyAccountController.php similarity index 50% rename from modules/Auth/Controllers/MyAccountController.php rename to modules/Admin/Controllers/MyAccountController.php index 844b0112..8ffa0247 100644 --- a/modules/Auth/Controllers/MyAccountController.php +++ b/modules/Admin/Controllers/MyAccountController.php @@ -8,17 +8,16 @@ declare(strict_types=1); * @link https://castopod.org/ */ -namespace Modules\Auth\Controllers; +namespace Modules\Admin\Controllers; +use App\Models\UserModel; use CodeIgniter\HTTP\RedirectResponse; -use CodeIgniter\Shield\Entities\User; -use Modules\Admin\Controllers\BaseController; +use Config\Services; class MyAccountController extends BaseController { public function index(): string { - $this->setHtmlHead(lang('MyAccount.info')); return view('my_account/view'); } @@ -26,14 +25,18 @@ class MyAccountController extends BaseController { helper('form'); - $this->setHtmlHead(lang('MyAccount.changePassword')); return view('my_account/change_password'); } - public function changeAction(): RedirectResponse + public function attemptChange(): RedirectResponse { + $auth = Services::authentication(); + $userModel = new UserModel(); + + // Validate here first, since some things, + // like the password, can only be validated properly here. $rules = [ - 'password' => 'required', + 'password' => 'required', 'new_password' => 'required|strong_password|differs[password]', ]; @@ -41,37 +44,30 @@ class MyAccountController extends BaseController return redirect() ->back() ->withInput() - ->with('errors', $this->validator->getErrors()); + ->with('errors', $userModel->errors()); } - $validData = $this->validator->getValidated(); - - // check credentials with the old password if logged in without magic link $credentials = [ - 'email' => auth() - ->user() + 'email' => user() ->email, - 'password' => $validData['password'], + 'password' => $this->request->getPost('password'), ]; - $validCreds = auth() - ->check($credentials); - - if (! $validCreds->isOK()) { - return redirect()->back() + if (! $auth->validate($credentials)) { + return redirect() + ->back() + ->withInput() ->with('error', lang('MyAccount.messages.wrongPasswordError')); } - $user = auth() - ->user(); + user() + ->password = $this->request->getPost('new_password'); - if ($user instanceof User) { - // set new password to user - $user->password = $validData['new_password']; - - $userModel = auth() - ->getProvider(); - $userModel->save($user); + if (! $userModel->update(user_id(), user())) { + return redirect() + ->back() + ->withInput() + ->with('errors', $userModel->errors()); } // Success! diff --git a/modules/Admin/Controllers/NotificationController.php b/modules/Admin/Controllers/NotificationController.php index 06f0cea1..f4bc5558 100644 --- a/modules/Admin/Controllers/NotificationController.php +++ b/modules/Admin/Controllers/NotificationController.php @@ -27,79 +27,81 @@ class NotificationController extends BaseController public function _remap(string $method, string ...$params): mixed { - if ($params === []) { - throw PageNotFoundException::forPageNotFound(); - } - if ( - ! ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast + ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) === null ) { throw PageNotFoundException::forPageNotFound(); } - $params[0] = $podcast; + $this->podcast = $podcast; if (count($params) > 1) { if ( - ! ($notification = new NotificationModel()->find($params[1])) instanceof Notification + ! ($notification = (new NotificationModel()) + ->where([ + 'id' => $params[1], + ]) + ->first()) ) { throw PageNotFoundException::forPageNotFound(); } - $params[1] = $notification; + $this->notification = $notification; + + unset($params[1]); + unset($params[0]); } return $this->{$method}(...$params); } - public function list(Podcast $podcast): string + public function list(): string { - $notifications = new NotificationModel() - ->where('target_actor_id', $podcast->actor_id) + $notifications = (new NotificationModel())->where('target_actor_id', $this->podcast->actor_id) ->orderBy('created_at', 'desc'); $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, 'notifications' => $notifications->paginate(10), - 'pager' => $notifications->pager, + 'pager' => $notifications->pager, ]; - $this->setHtmlHead(lang('Notifications.title')); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); + return view('podcast/notifications', $data); } - public function markAllAsReadAction(Podcast $podcast): RedirectResponse + public function markAsRead(): RedirectResponse { - $notifications = new NotificationModel() - ->where('target_actor_id', $podcast->actor_id) - ->where('read_at') + $this->notification->read_at = new Time('now'); + $notificationModel = new NotificationModel(); + $notificationModel->update($this->notification->id, $this->notification); + + if ($this->notification->post_id === null) { + return redirect()->route('podcast-activity', [esc($this->podcast->handle)]); + } + + $post = (new PostModel())->getPostById($this->notification->post_id); + + return redirect()->route( + 'post', + [esc((new PodcastModel())->getPodcastByActorId($this->notification->actor_id)->handle), $post->id] + ); + } + + public function markAllAsRead(): RedirectResponse + { + $notifications = (new NotificationModel())->where('target_actor_id', $this->podcast->actor_id) + ->where('read_at', null) ->findAll(); foreach ($notifications as $notification) { $notification->read_at = new Time('now'); - new NotificationModel() - ->update($notification->id, $notification); + (new NotificationModel())->update($notification->id, $notification); } return redirect()->back(); } - - public function markAsReadAction(Podcast $podcast, Notification $notification): RedirectResponse - { - $notification->read_at = new Time('now'); - $notificationModel = new NotificationModel(); - $notificationModel->update($notification->id, $notification); - - if ($notification->post_id === null) { - return redirect()->route('podcast-activity', [esc($podcast->handle)]); - } - - $post = new PostModel() - ->getPostById($notification->post_id); - - return redirect()->route('post', [$podcast->handle, $post->id]); - } } diff --git a/modules/Admin/Controllers/PageController.php b/modules/Admin/Controllers/PageController.php index 8c406463..464f13f7 100644 --- a/modules/Admin/Controllers/PageController.php +++ b/modules/Admin/Controllers/PageController.php @@ -17,14 +17,16 @@ use CodeIgniter\HTTP\RedirectResponse; class PageController extends BaseController { + protected ?Page $page; + public function _remap(string $method, string ...$params): mixed { if ($params === []) { return $this->{$method}(); } - if (($page = new PageModel()->find($params[0])) instanceof Page) { - return $this->{$method}($page); + if ($this->page = (new PageModel())->find($params[0])) { + return $this->{$method}(); } throw PageNotFoundException::forPageNotFound(); @@ -32,36 +34,32 @@ class PageController extends BaseController public function list(): string { - $this->setHtmlHead(lang('Page.all_pages')); $data = [ - 'pages' => new PageModel() - ->findAll(), + 'pages' => (new PageModel())->findAll(), ]; return view('page/list', $data); } - public function view(Page $page): string + public function view(): string { - $this->setHtmlHead($page->title); return view('page/view', [ - 'page' => $page, + 'page' => $this->page, ]); } - public function createView(): string + public function create(): string { helper('form'); - $this->setHtmlHead(lang('Page.create')); return view('page/create'); } - public function createAction(): RedirectResponse + public function attemptCreate(): RedirectResponse { $page = new Page([ - 'title' => $this->request->getPost('title'), - 'slug' => $this->request->getPost('slug'), + 'title' => $this->request->getPost('title'), + 'slug' => $this->request->getPost('slug'), 'content_markdown' => $this->request->getPost('content'), ]); @@ -81,41 +79,39 @@ class PageController extends BaseController ])); } - public function editView(Page $page): string + public function edit(): string { helper('form'); - $this->setHtmlHead(lang('Page.edit')); replace_breadcrumb_params([ - 0 => $page->title, + 0 => $this->page->title, ]); return view('page/edit', [ - 'page' => $page, + 'page' => $this->page, ]); } - public function editAction(Page $page): RedirectResponse + public function attemptEdit(): RedirectResponse { - $page->title = $this->request->getPost('title'); - $page->slug = $this->request->getPost('slug'); - $page->content_markdown = $this->request->getPost('content'); + $this->page->title = $this->request->getPost('title'); + $this->page->slug = $this->request->getPost('slug'); + $this->page->content_markdown = $this->request->getPost('content'); $pageModel = new PageModel(); - if (! $pageModel->update($page->id, $page)) { + if (! $pageModel->update($this->page->id, $this->page)) { return redirect() ->back() ->withInput() ->with('errors', $pageModel->errors()); } - return redirect()->route('page-edit', [$page->id])->with('message', lang('Page.messages.editSuccess')); + return redirect()->route('page-edit', [$this->page->id])->with('message', lang('Page.messages.editSuccess')); } - public function deleteAction(Page $page): RedirectResponse + public function delete(): RedirectResponse { - new PageModel() - ->delete($page->id); + (new PageModel())->delete($this->page->id); return redirect()->route('page-list'); } diff --git a/modules/Admin/Controllers/PersonController.php b/modules/Admin/Controllers/PersonController.php index 95bc4a28..9c0ffcfe 100644 --- a/modules/Admin/Controllers/PersonController.php +++ b/modules/Admin/Controllers/PersonController.php @@ -14,10 +14,11 @@ use App\Entities\Person; use App\Models\PersonModel; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; -use Modules\Media\Models\MediaModel; class PersonController extends BaseController { + protected ?Person $person; + public function _remap(string $method, string ...$params): mixed { if ($params === []) { @@ -25,51 +26,47 @@ class PersonController extends BaseController } if ( - ($person = new PersonModel()->getPersonById((int) $params[0])) instanceof Person + ($this->person = (new PersonModel())->getPersonById((int) $params[0])) !== null ) { - return $this->{$method}($person); + return $this->{$method}(); } throw PageNotFoundException::forPageNotFound(); } - public function list(): string + public function index(): string { $data = [ - 'persons' => new PersonModel() - ->orderBy('full_name') - ->findAll(), + 'persons' => (new PersonModel())->findAll(), ]; - $this->setHtmlHead(lang('Person.all_persons')); return view('person/list', $data); } - public function view(Person $person): string + public function view(): string { $data = [ - 'person' => $person, + 'person' => $this->person, ]; - $this->setHtmlHead($person->full_name); replace_breadcrumb_params([ - 0 => $person->full_name, + 0 => $this->person->full_name, ]); return view('person/view', $data); } - public function createView(): string + public function create(): string { helper(['form']); - $this->setHtmlHead(lang('Person.create')); return view('person/create'); } - public function createAction(): RedirectResponse + public function attemptCreate(): RedirectResponse { $rules = [ - 'avatar' => 'is_image[avatar]|ext_in[avatar,jpg,jpeg,png]|min_dims[avatar,400,400]|is_image_ratio[avatar,1,1]', + 'avatar' => + 'is_image[avatar]|ext_in[avatar,jpg,jpeg,png]|min_dims[avatar,400,400]|is_image_ratio[avatar,1,1]', ]; if (! $this->validate($rules)) { @@ -83,12 +80,12 @@ class PersonController extends BaseController $db->transStart(); $person = new Person([ - 'created_by' => user_id(), - 'updated_by' => user_id(), - 'full_name' => $this->request->getPost('full_name'), - 'unique_name' => $this->request->getPost('unique_name'), + 'full_name' => $this->request->getPost('full_name'), + 'unique_name' => $this->request->getPost('unique_name'), 'information_url' => $this->request->getPost('information_url'), - 'avatar' => $this->request->getFile('avatar'), + 'avatar' => $this->request->getFile('avatar'), + 'created_by' => user_id(), + 'updated_by' => user_id(), ]); $personModel = new PersonModel(); @@ -106,25 +103,25 @@ class PersonController extends BaseController ->with('message', lang('Person.messages.createSuccess')); } - public function editView(Person $person): string + public function edit(): string { helper('form'); $data = [ - 'person' => $person, + 'person' => $this->person, ]; - $this->setHtmlHead(lang('Person.edit')); replace_breadcrumb_params([ - 0 => $person->full_name, + 0 => $this->person->full_name, ]); return view('person/edit', $data); } - public function editAction(Person $person): RedirectResponse + public function attemptEdit(): RedirectResponse { $rules = [ - 'avatar' => 'is_image[avatar]|ext_in[avatar,jpg,jpeg,png]|min_dims[avatar,400,400]|is_image_ratio[avatar,1,1]', + 'avatar' => + 'is_image[avatar]|ext_in[avatar,jpg,jpeg,png]|min_dims[avatar,400,400]|is_image_ratio[avatar,1,1]', ]; if (! $this->validate($rules)) { @@ -134,36 +131,30 @@ class PersonController extends BaseController ->with('errors', $this->validator->getErrors()); } - $person->updated_by = user_id(); - $person->full_name = $this->request->getPost('full_name'); - $person->unique_name = $this->request->getPost('unique_name'); - $person->information_url = $this->request->getPost('information_url'); - $person->setAvatar($this->request->getFile('avatar')); + $this->person->full_name = $this->request->getPost('full_name'); + $this->person->unique_name = $this->request->getPost('unique_name'); + $this->person->information_url = $this->request->getPost('information_url'); + $this->person->setAvatar($this->request->getFile('avatar')); + + $this->person->updated_by = user_id(); $personModel = new PersonModel(); - if (! $personModel->update($person->id, $person)) { + if (! $personModel->update($this->person->id, $this->person)) { return redirect() ->back() ->withInput() ->with('errors', $personModel->errors()); } - return redirect()->route('person-edit', [$person->id])->with( + return redirect()->route('person-edit', [$this->person->id])->with( 'message', - lang('Person.messages.editSuccess'), + lang('Person.messages.editSuccess') ); } - public function deleteAction(Person $person): RedirectResponse + public function delete(): RedirectResponse { - if ($person->avatar_id !== null) { - // delete avatar to prevent collision if recreating person - new MediaModel() - ->deleteMedia($person->avatar); - } - - new PersonModel() - ->delete($person->id); + (new PersonModel())->delete($this->person->id); return redirect()->route('person-list') ->with('message', lang('Person.messages.deleteSuccess')); diff --git a/modules/Admin/Controllers/PodcastController.php b/modules/Admin/Controllers/PodcastController.php index 96204b66..7e9726af 100644 --- a/modules/Admin/Controllers/PodcastController.php +++ b/modules/Admin/Controllers/PodcastController.php @@ -10,7 +10,6 @@ declare(strict_types=1); namespace Modules\Admin\Controllers; -use App\Entities\Actor; use App\Entities\Location; use App\Entities\Podcast; use App\Entities\Post; @@ -18,11 +17,13 @@ use App\Models\ActorModel; use App\Models\CategoryModel; use App\Models\EpisodeModel; use App\Models\LanguageModel; +use App\Models\MediaModel; use App\Models\PodcastModel; use App\Models\PostModel; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\I18n\Time; +use Config\Services; use Modules\Analytics\Models\AnalyticsPodcastByCountryModel; use Modules\Analytics\Models\AnalyticsPodcastByEpisodeModel; use Modules\Analytics\Models\AnalyticsPodcastByHourModel; @@ -32,12 +33,11 @@ use Modules\Analytics\Models\AnalyticsPodcastModel; use Modules\Analytics\Models\AnalyticsWebsiteByBrowserModel; use Modules\Analytics\Models\AnalyticsWebsiteByEntryPageModel; use Modules\Analytics\Models\AnalyticsWebsiteByRefererModel; -use Modules\Media\Entities\Image; -use Modules\Media\FileManagers\FileManagerInterface; -use Modules\Media\Models\MediaModel; class PodcastController extends BaseController { + protected Podcast $podcast; + public function _remap(string $method, string ...$params): mixed { if ($params === []) { @@ -45,9 +45,10 @@ class PodcastController extends BaseController } if ( - ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast + ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) !== null ) { - return $this->{$method}($podcast); + $this->podcast = $podcast; + return $this->{$method}(); } throw PageNotFoundException::forPageNotFound(); @@ -55,149 +56,137 @@ class PodcastController extends BaseController public function list(): string { - if (auth()->user()->can('podcasts.view')) { + if (! has_permission('podcasts-list')) { $data = [ - 'podcasts' => new PodcastModel() - ->findAll(), + 'podcasts' => (new PodcastModel())->getUserPodcasts((int) user_id()), ]; } else { $data = [ - 'podcasts' => get_user_podcasts(auth()->user()), + 'podcasts' => (new PodcastModel())->findAll(), ]; } - $this->setHtmlHead(lang('Podcast.all_podcasts')); return view('podcast/list', $data); } - public function view(Podcast $podcast): string + public function view(): string { $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead($podcast->title); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/view', $data); } - public function analyticsView(Podcast $podcast): string + public function viewAnalytics(): string { $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead($podcast->title); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/analytics/index', $data); } - public function analyticsWebpagesView(Podcast $podcast): string + public function viewAnalyticsWebpages(): string { $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead($podcast->title); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/analytics/webpages', $data); } - public function analyticsLocationsView(Podcast $podcast): string + public function viewAnalyticsLocations(): string { $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead($podcast->title); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/analytics/locations', $data); } - public function analyticsUniqueListenersView(Podcast $podcast): string + public function viewAnalyticsUniqueListeners(): string { $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead($podcast->title); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/analytics/unique_listeners', $data); } - public function analyticsListeningTimeView(Podcast $podcast): string + public function viewAnalyticsListeningTime(): string { $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead($podcast->title); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/analytics/listening_time', $data); } - public function analyticsTimePeriodsView(Podcast $podcast): string + public function viewAnalyticsTimePeriods(): string { $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead($podcast->title); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/analytics/time_periods', $data); } - public function analyticsPlayersView(Podcast $podcast): string + public function viewAnalyticsPlayers(): string { $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead($podcast->title); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/analytics/players', $data); } - public function createView(): string + public function create(): string { helper(['form', 'misc']); - $languageOptions = new LanguageModel() - ->getLanguageOptions(); - $categoryOptions = new CategoryModel() - ->getCategoryOptions(); + $languageOptions = (new LanguageModel())->getLanguageOptions(); + $categoryOptions = (new CategoryModel())->getCategoryOptions(); $data = [ 'languageOptions' => $languageOptions, 'categoryOptions' => $categoryOptions, - 'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE')), + 'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE')), ]; - $this->setHtmlHead(lang('Podcast.create')); return view('podcast/create', $data); } - public function createAction(): RedirectResponse + public function attemptCreate(): RedirectResponse { $rules = [ - 'cover' => 'uploaded[cover]|is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', - 'banner' => 'is_image[banner]|ext_in[banner,jpg,jpeg,png]|min_dims[banner,1500,500]|is_image_ratio[banner,3,1]', + 'cover' => + 'uploaded[cover]|is_image[cover]|ext_in[cover,jpg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', + 'banner' => 'is_image[banner]|ext_in[banner,jpg,png]|min_dims[banner,1500,500]|is_image_ratio[banner,3,1]', ]; if (! $this->validate($rules)) { @@ -207,35 +196,52 @@ class PodcastController extends BaseController ->with('errors', $this->validator->getErrors()); } + if ( + ($partnerId = $this->request->getPost('partner_id')) === '' || + ($partnerLinkUrl = $this->request->getPost('partner_link_url')) === '' || + ($partnerImageUrl = $this->request->getPost('partner_image_url')) === '') { + $partnerId = null; + $partnerLinkUrl = null; + $partnerImageUrl = null; + } + $db = db_connect(); $db->transStart(); $newPodcast = new Podcast([ - 'created_by' => user_id(), - 'updated_by' => user_id(), - 'title' => $this->request->getPost('title'), - 'handle' => $this->request->getPost('handle'), - 'cover' => $this->request->getFile('cover'), - 'banner' => $this->request->getFile('banner'), + 'title' => $this->request->getPost('title'), + 'handle' => $this->request->getPost('handle'), + 'cover' => $this->request->getFile('cover'), + 'banner' => $this->request->getFile('banner'), 'description_markdown' => $this->request->getPost('description'), - 'language_code' => $this->request->getPost('language'), - 'category_id' => $this->request->getPost('category'), - 'parental_advisory' => $this->request->getPost('parental_advisory') !== 'undefined' + 'language_code' => $this->request->getPost('language'), + 'category_id' => $this->request->getPost('category'), + 'parental_advisory' => + $this->request->getPost('parental_advisory') !== 'undefined' ? $this->request->getPost('parental_advisory') : null, - 'owner_name' => $this->request->getPost('owner_name'), + 'owner_name' => $this->request->getPost('owner_name'), 'owner_email' => $this->request->getPost('owner_email'), - 'publisher' => $this->request->getPost('publisher'), - 'type' => $this->request->getPost('type'), - 'copyright' => $this->request->getPost('copyright'), - 'location' => $this->request->getPost('location_name') === '' ? null : new Location( - $this->request->getPost('location_name'), - ), - 'is_blocked' => $this->request->getPost('block') === 'yes', - 'is_completed' => $this->request->getPost('complete') === 'yes', - 'is_locked' => $this->request->getPost('lock') === 'yes', + 'publisher' => $this->request->getPost('publisher'), + 'type' => $this->request->getPost('type'), + 'copyright' => $this->request->getPost('copyright'), + 'location' => $this->request->getPost('location_name') === '' ? null : new Location($this->request->getPost( + 'location_name' + )), + 'payment_pointer' => $this->request->getPost( + 'payment_pointer' + ) === '' ? null : $this->request->getPost('payment_pointer'), + 'custom_rss_string' => $this->request->getPost('custom_rss'), + 'partner_id' => $partnerId, + 'partner_link_url' => $partnerLinkUrl, + 'partner_image_url' => $partnerImageUrl, + 'is_blocked' => $this->request->getPost('block') === 'yes', + 'is_completed' => $this->request->getPost('complete') === 'yes', + 'is_locked' => $this->request->getPost('lock') === 'yes', 'is_premium_by_default' => $this->request->getPost('premium_by_default') === 'yes', - 'published_at' => null, + 'created_by' => user_id(), + 'updated_by' => user_id(), + 'published_at' => null, ]); $podcastModel = new PodcastModel(); @@ -247,51 +253,54 @@ class PodcastController extends BaseController ->with('errors', $podcastModel->errors()); } - // generate podcast roles and permissions - // before setting current user as podcast admin - config('AuthGroups') - ->generatePodcastAuthorizations($newPodcastId); - add_podcast_group(auth()->user(), (int) $newPodcastId, setting('AuthGroups.mostPowerfulPodcastGroup')); + $authorize = Services::authorization(); + $podcastAdminGroup = $authorize->group('podcast_admin'); + + $podcastModel->addPodcastContributor(user_id(), $newPodcastId, (int) $podcastAdminGroup->id); // set Podcast categories - new CategoryModel() - ->setPodcastCategories((int) $newPodcastId, $this->request->getPost('other_categories') ?? []); + (new CategoryModel())->setPodcastCategories( + (int) $newPodcastId, + $this->request->getPost('other_categories') ?? [], + ); + + // set interact as the newly created podcast actor + $createdPodcast = (new PodcastModel())->getPodcastById($newPodcastId); + set_interact_as_actor($createdPodcast->actor_id); $db->transComplete(); return redirect()->route('podcast-view', [$newPodcastId])->with( 'message', - lang('Podcast.messages.createSuccess'), + lang('Podcast.messages.createSuccess') ); } - public function editView(Podcast $podcast): string + public function edit(): string { helper('form'); - $languageOptions = new LanguageModel() - ->getLanguageOptions(); - $categoryOptions = new CategoryModel() - ->getCategoryOptions(); + $languageOptions = (new LanguageModel())->getLanguageOptions(); + $categoryOptions = (new CategoryModel())->getCategoryOptions(); $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, 'languageOptions' => $languageOptions, 'categoryOptions' => $categoryOptions, ]; - $this->setHtmlHead(lang('Podcast.edit')); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/edit', $data); } - public function editAction(Podcast $podcast): RedirectResponse + public function attemptEdit(): RedirectResponse { $rules = [ - 'cover' => 'is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', - 'banner' => 'is_image[banner]|ext_in[banner,jpg,jpeg,png]|min_dims[banner,1500,500]|is_image_ratio[banner,3,1]', + 'cover' => + 'is_image[cover]|ext_in[cover,jpg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', + 'banner' => 'is_image[banner]|ext_in[banner,jpg,png]|min_dims[banner,1500,500]|is_image_ratio[banner,3,1]', ]; if (! $this->validate($rules)) { @@ -301,46 +310,60 @@ class PodcastController extends BaseController ->with('errors', $this->validator->getErrors()); } - $podcast->updated_by = (int) user_id(); + if ( + ($partnerId = $this->request->getPost('partner_id')) === '' || + ($partnerLinkUrl = $this->request->getPost('partner_link_url')) === '' || + ($partnerImageUrl = $this->request->getPost('partner_image_url')) === '') { + $partnerId = null; + $partnerLinkUrl = null; + $partnerImageUrl = null; + } - $podcast->title = $this->request->getPost('title'); - $podcast->description_markdown = $this->request->getPost('description'); - $podcast->setCover($this->request->getFile('cover')); - $podcast->setBanner($this->request->getFile('banner')); + $this->podcast->title = $this->request->getPost('title'); + $this->podcast->description_markdown = $this->request->getPost('description'); + $this->podcast->setCover($this->request->getFile('cover')); + $this->podcast->setBanner($this->request->getFile('banner')); - $podcast->language_code = $this->request->getPost('language'); - $podcast->category_id = $this->request->getPost('category'); - $podcast->parental_advisory = + $this->podcast->language_code = $this->request->getPost('language'); + $this->podcast->category_id = $this->request->getPost('category'); + $this->podcast->parental_advisory = $this->request->getPost('parental_advisory') !== 'undefined' ? $this->request->getPost('parental_advisory') : null; - $podcast->publisher = $this->request->getPost('publisher'); - $podcast->owner_name = $this->request->getPost('owner_name'); - $podcast->owner_email = $this->request->getPost('owner_email'); - $podcast->type = $this->request->getPost('type'); - $podcast->copyright = $this->request->getPost('copyright'); - $podcast->location = $this->request->getPost('location_name') === '' ? null : new Location( - $this->request->getPost('location_name'), + $this->podcast->publisher = $this->request->getPost('publisher'); + $this->podcast->owner_name = $this->request->getPost('owner_name'); + $this->podcast->owner_email = $this->request->getPost('owner_email'); + $this->podcast->type = $this->request->getPost('type'); + $this->podcast->copyright = $this->request->getPost('copyright'); + $this->podcast->location = $this->request->getPost('location_name') === '' ? null : new Location( + $this->request->getPost('location_name') ); - $podcast->new_feed_url = $this->request->getPost('new_feed_url') === '' ? null : $this->request->getPost( - 'new_feed_url', + $this->podcast->payment_pointer = $this->request->getPost( + 'payment_pointer' + ) === '' ? null : $this->request->getPost('payment_pointer'); + $this->podcast->custom_rss_string = $this->request->getPost('custom_rss'); + $this->podcast->new_feed_url = $this->request->getPost('new_feed_url') === '' ? null : $this->request->getPost( + 'new_feed_url' ); - - $podcast->is_blocked = $this->request->getPost('block') === 'yes'; - $podcast->is_completed = + $this->podcast->partner_id = $partnerId; + $this->podcast->partner_link_url = $partnerLinkUrl; + $this->podcast->partner_image_url = $partnerImageUrl; + $this->podcast->is_blocked = $this->request->getPost('block') === 'yes'; + $this->podcast->is_completed = $this->request->getPost('complete') === 'yes'; - $podcast->is_locked = $this->request->getPost('lock') === 'yes'; - $podcast->is_premium_by_default = $this->request->getPost('premium_by_default') === 'yes'; + $this->podcast->is_locked = $this->request->getPost('lock') === 'yes'; + $this->podcast->is_premium_by_default = $this->request->getPost('premium_by_default') === 'yes'; + $this->podcast->updated_by = (int) user_id(); // republish on websub hubs upon edit - $podcast->is_published_on_hubs = false; + $this->podcast->is_published_on_hubs = false; $db = db_connect(); $db->transStart(); $podcastModel = new PodcastModel(); - if (! $podcastModel->update($podcast->id, $podcast)) { + if (! $podcastModel->update($this->podcast->id, $this->podcast)) { $db->transRollback(); return redirect() ->back() @@ -349,28 +372,22 @@ class PodcastController extends BaseController } // set Podcast categories - new CategoryModel() - ->setPodcastCategories($podcast->id, $this->request->getPost('other_categories') ?? []); - - // New feed url redirect - service('settings') - ->set( - 'Podcast.redirect_to_new_feed', - $this->request->getPost('redirect_to_new_feed') === 'yes', - 'podcast:' . $podcast->id, - ); + (new CategoryModel())->setPodcastCategories( + $this->podcast->id, + $this->request->getPost('other_categories') ?? [], + ); $db->transComplete(); - return redirect()->route('podcast-edit', [$podcast->id])->with( + return redirect()->route('podcast-edit', [$this->podcast->id])->with( 'message', - lang('Podcast.messages.editSuccess'), + lang('Podcast.messages.editSuccess') ); } - public function deleteBannerAction(Podcast $podcast): RedirectResponse + public function deleteBanner(): RedirectResponse { - if (! $podcast->banner instanceof Image) { + if ($this->podcast->banner === null) { return redirect()->back(); } @@ -379,28 +396,25 @@ class PodcastController extends BaseController $db->transStart(); $mediaModel = new MediaModel(); - if (! $mediaModel->deleteMedia($podcast->banner)) { + if (! $mediaModel->deleteMedia($this->podcast->banner)) { return redirect() ->back() ->withInput() ->with('errors', $mediaModel->errors()); } - new PodcastModel() - ->clearCache([ - 'id' => $podcast->id, - ]); + (new PodcastModel())->clearCache([ + 'id' => $this->podcast->id, + ]); // remove banner url from actor - $actor = new ActorModel() - ->getActorById($podcast->actor_id); + $actor = (new ActorModel())->getActorById($this->podcast->actor_id); - if ($actor instanceof Actor) { + if ($actor !== null) { $actor->cover_image_url = null; $actor->cover_image_mimetype = null; - new ActorModel() - ->update($actor->id, $actor); + (new ActorModel())->update($actor->id, $actor); } $db->transComplete(); @@ -408,37 +422,34 @@ class PodcastController extends BaseController return redirect()->back(); } - public function latestEpisodesView(int $limit, int $podcastId): string + public function latestEpisodes(int $limit, int $podcastId): string { - $episodes = new EpisodeModel() + $episodes = (new EpisodeModel()) ->where('podcast_id', $podcastId) - ->orderBy('-`published_at`', '', false) ->orderBy('created_at', 'desc') ->findAll($limit); return view('podcast/latest_episodes', [ 'episodes' => $episodes, - 'podcast' => new PodcastModel() - ->getPodcastById($podcastId), + 'podcast' => (new PodcastModel())->getPodcastById($podcastId), ]); } - public function deleteView(Podcast $podcast): string + public function delete(): string { helper(['form']); $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead(lang('Podcast.delete')); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/delete', $data); } - public function deleteAction(Podcast $podcast): RedirectResponse + public function attemptDelete(): RedirectResponse { $rules = [ 'understand' => 'required', @@ -456,8 +467,7 @@ class PodcastController extends BaseController $db->transStart(); //delete podcast episodes - $podcastEpisodes = new EpisodeModel() - ->where('podcast_id', $podcast->id) + $podcastEpisodes = (new EpisodeModel())->where('podcast_id', $this->podcast->id) ->findAll(); foreach ($podcastEpisodes as $podcastEpisode) { @@ -478,17 +488,15 @@ class PodcastController extends BaseController $episodeMediaList[] = $podcastEpisode->cover; } - $mediaModel = new MediaModel(); - foreach ($episodeMediaList as $episodeMedia) { - if ($episodeMedia !== null && ! $mediaModel->delete($episodeMedia->id)) { + if ($episodeMedia !== null && ! $episodeMedia->delete()) { $db->transRollback(); return redirect() ->back() ->withInput() ->with('error', lang('Podcast.messages.deleteEpisodeMediaError', [ 'episode_slug' => $podcastEpisode->slug, - 'type' => $episodeMedia->type, + 'type' => $episodeMedia->type, ])); } } @@ -497,7 +505,7 @@ class PodcastController extends BaseController //delete podcast $podcastModel = new PodcastModel(); - if (! $podcastModel->delete($podcast->id)) { + if (! $podcastModel->delete($this->podcast->id)) { $db->transRollback(); return redirect() ->back() @@ -509,22 +517,20 @@ class PodcastController extends BaseController $podcastMediaList = [ [ 'type' => 'cover', - 'file' => $podcast->cover, + 'file' => $this->podcast->cover, ], ]; - if ($podcast->banner_id !== null) { + if ($this->podcast->banner_id !== null) { $podcastMediaList[] = [ 'type' => 'banner', - 'file' => $podcast->banner, + 'file' => $this->podcast->banner, ]; } - $mediaModel = new MediaModel(); - foreach ($podcastMediaList as $podcastMedia) { - if ($podcastMedia['file'] instanceof Image && ! $mediaModel->delete($podcastMedia['file']->id)) { + if ($podcastMedia['file'] !== null && ! $podcastMedia['file']->delete()) { $db->transRollback(); return redirect() ->back() @@ -538,7 +544,7 @@ class PodcastController extends BaseController //delete podcast actor $actorModel = new ActorModel(); - if (! $actorModel->delete($podcast->actor_id)) { + if (! $actorModel->delete($this->podcast->actor_id)) { $db->transRollback(); return redirect() ->back() @@ -560,7 +566,7 @@ class PodcastController extends BaseController ]; foreach ($analyticsModels as $analyticsModel) { if (! $analyticsModel->where([ - 'podcast_id' => $podcast->id, + 'podcast_id' => $this->podcast->id, ])->delete()) { $db->transRollback(); return redirect() @@ -570,17 +576,29 @@ class PodcastController extends BaseController } } + if ($this->podcast->actor_id === interact_as_actor_id()) { + //set interact to the most recently created podcast actor + $mostRecentPodcast = (new PodcastModel())->orderBy('created_at', 'desc') + ->first(); + if ($mostRecentPodcast !== null) { + set_interact_as_actor($mostRecentPodcast->actor_id); + } + } + $db->transComplete(); - /** @var FileManagerInterface $fileManager */ - $fileManager = service('file_manager'); - //delete podcast media files and folder - $folder = 'podcasts/' . $podcast->handle; - if (! $fileManager->deleteAll($folder)) { + $folder = 'podcasts/' . $this->podcast->handle; + + $mediaRoot = config('App') + ->mediaRoot . '/' . $folder; + + helper('filesystem'); + + if (! delete_files($mediaRoot) || ! rmdir($mediaRoot)) { return redirect()->route('podcast-list') ->with('message', lang('Podcast.messages.deleteSuccess', [ - 'podcast_handle' => $podcast->handle, + 'podcast_handle' => $this->podcast->handle, ])) ->with('warning', lang('Podcast.messages.deletePodcastMediaFolderError', [ 'folder_path' => $folder, @@ -589,37 +607,38 @@ class PodcastController extends BaseController return redirect()->route('podcast-list') ->with('message', lang('Podcast.messages.deleteSuccess', [ - 'podcast_handle' => $podcast->handle, + 'podcast_handle' => $this->podcast->handle, ])); } - public function publishView(Podcast $podcast): string | RedirectResponse + public function publish(): string | RedirectResponse { helper(['form']); $data = [ - 'podcast' => $podcast, + 'podcast' => $this->podcast, ]; - $this->setHtmlHead(lang('Podcast.publish')); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); + return view('podcast/publish', $data); } - public function publishAction(Podcast $podcast): RedirectResponse + public function attemptPublish(): RedirectResponse { - if ($podcast->publication_status !== 'not_published') { - return redirect()->route('podcast-view', [$podcast->id])->with( + if ($this->podcast->publication_status !== 'not_published') { + return redirect()->route('podcast-view', [$this->podcast->id])->with( 'error', - lang('Podcast.messages.publishError'), + lang('Podcast.messages.publishError') ); } $rules = [ - 'publication_method' => 'required', - 'scheduled_publication_date' => 'valid_date[Y-m-d H:i]|permit_empty', + 'publication_method' => 'required', + 'scheduled_publication_date' => + 'valid_date[Y-m-d H:i]|permit_empty', ]; if (! $this->validate($rules)) { @@ -629,16 +648,14 @@ class PodcastController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - $db = db_connect(); $db->transStart(); - $publishMethod = $validData['publication_method']; + $publishMethod = $this->request->getPost('publication_method'); if ($publishMethod === 'schedule') { - $scheduledPublicationDate = $validData['scheduled_publication_date']; + $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date'); if ($scheduledPublicationDate) { - $podcast->published_at = Time::createFromFormat( + $this->podcast->published_at = Time::createFromFormat( 'Y-m-d H:i', $scheduledPublicationDate, $this->request->getPost('client_timezone'), @@ -651,19 +668,19 @@ class PodcastController extends BaseController ->with('error', lang('Podcast.messages.scheduleDateError')); } } else { - $podcast->published_at = Time::now(); + $this->podcast->published_at = Time::now(); } $message = $this->request->getPost('message'); // only create post if message is not empty if ($message !== '') { $newPost = new Post([ - 'actor_id' => $podcast->actor_id, - 'message' => $message, + 'actor_id' => $this->podcast->actor_id, + 'message' => $message, 'created_by' => user_id(), ]); - $newPost->published_at = $podcast->published_at; + $newPost->published_at = $this->podcast->published_at; $postModel = new PostModel(); if (! $postModel->addPost($newPost)) { @@ -675,13 +692,13 @@ class PodcastController extends BaseController } } - $episodes = new EpisodeModel() - ->where('podcast_id', $podcast->id) - ->where('published_at !=') + $episodes = (new EpisodeModel()) + ->where('podcast_id', $this->podcast->id) + ->where('published_at !=', null) ->findAll(); foreach ($episodes as $episode) { - $episode->published_at = $podcast->published_at->addSeconds(1); + $episode->published_at = $this->podcast->published_at->addSeconds(1); $episodeModel = new EpisodeModel(); if (! $episodeModel->update($episode->id, $episode)) { @@ -692,11 +709,10 @@ class PodcastController extends BaseController ->with('errors', $episodeModel->errors()); } - $post = new PostModel() - ->where('episode_id', $episode->id) + $post = (new PostModel())->where('episode_id', $episode->id) ->first(); - if ($post instanceof Post) { + if ($post !== null) { $post->published_at = $episode->published_at; $postModel = new PostModel(); if (! $postModel->update($post->id, $post)) { @@ -710,7 +726,7 @@ class PodcastController extends BaseController } $podcastModel = new PodcastModel(); - if (! $podcastModel->update($podcast->id, $podcast)) { + if (! $podcastModel->update($this->podcast->id, $this->podcast)) { $db->transRollback(); return redirect() ->back() @@ -720,42 +736,43 @@ class PodcastController extends BaseController $db->transComplete(); - return redirect()->route('podcast-view', [$podcast->id]); + return redirect()->route('podcast-view', [$this->podcast->id]); } - public function publishEditView(Podcast $podcast): string | RedirectResponse + public function publishEdit(): string | RedirectResponse { helper(['form']); $data = [ - 'podcast' => $podcast, - 'post' => new PostModel() + 'podcast' => $this->podcast, + 'post' => (new PostModel()) ->where([ - 'actor_id' => $podcast->actor_id, + 'actor_id' => $this->podcast->actor_id, 'episode_id' => null, ]) ->first(), ]; - $this->setHtmlHead(lang('Podcast.publish_edit')); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); + return view('podcast/publish_edit', $data); } - public function publishEditAction(Podcast $podcast): RedirectResponse + public function attemptPublishEdit(): RedirectResponse { - if ($podcast->publication_status !== 'scheduled') { - return redirect()->route('podcast-view', [$podcast->id])->with( + if ($this->podcast->publication_status !== 'scheduled') { + return redirect()->route('podcast-view', [$this->podcast->id])->with( 'error', - lang('Podcast.messages.publishEditError'), + lang('Podcast.messages.publishEditError') ); } $rules = [ - 'publication_method' => 'required', - 'scheduled_publication_date' => 'valid_date[Y-m-d H:i]|permit_empty', + 'publication_method' => 'required', + 'scheduled_publication_date' => + 'valid_date[Y-m-d H:i]|permit_empty', ]; if (! $this->validate($rules)) { @@ -765,16 +782,14 @@ class PodcastController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - $db = db_connect(); $db->transStart(); - $publishMethod = $validData['publication_method']; + $publishMethod = $this->request->getPost('publication_method'); if ($publishMethod === 'schedule') { - $scheduledPublicationDate = $validData['scheduled_publication_date']; + $scheduledPublicationDate = $this->request->getPost('scheduled_publication_date'); if ($scheduledPublicationDate) { - $podcast->published_at = Time::createFromFormat( + $this->podcast->published_at = Time::createFromFormat( 'Y-m-d H:i', $scheduledPublicationDate, $this->request->getPost('client_timezone'), @@ -787,23 +802,23 @@ class PodcastController extends BaseController ->with('error', lang('Podcast.messages.scheduleDateError')); } } else { - $podcast->published_at = Time::now(); + $this->podcast->published_at = Time::now(); } - $post = new PostModel() + $post = (new PostModel()) ->where([ - 'actor_id' => $podcast->actor_id, + 'actor_id' => $this->podcast->actor_id, 'episode_id' => null, ]) ->first(); $newPostMessage = $this->request->getPost('message'); - if ($post instanceof Post) { + if ($post !== null) { if ($newPostMessage !== '') { // edit post if post exists and message is not empty $post->message = $newPostMessage; - $post->published_at = $podcast->published_at; + $post->published_at = $this->podcast->published_at; $postModel = new PostModel(); if (! $postModel->editPost($post)) { @@ -818,7 +833,7 @@ class PodcastController extends BaseController $postModel = new PostModel(); $post = $postModel ->where([ - 'actor_id' => $podcast->actor_id, + 'actor_id' => $this->podcast->actor_id, 'episode_id' => null, ]) ->first(); @@ -827,12 +842,12 @@ class PodcastController extends BaseController } elseif ($newPostMessage !== '') { // create post if there is no post and message is not empty $newPost = new Post([ - 'actor_id' => $podcast->actor_id, - 'message' => $newPostMessage, + 'actor_id' => $this->podcast->actor_id, + 'message' => $newPostMessage, 'created_by' => user_id(), ]); - $newPost->published_at = $podcast->published_at; + $newPost->published_at = $this->podcast->published_at; $postModel = new PostModel(); if (! $postModel->addPost($newPost)) { @@ -844,13 +859,13 @@ class PodcastController extends BaseController } } - $episodes = new EpisodeModel() - ->where('podcast_id', $podcast->id) - ->where('published_at !=') + $episodes = (new EpisodeModel()) + ->where('podcast_id', $this->podcast->id) + ->where('published_at !=', null) ->findAll(); foreach ($episodes as $episode) { - $episode->published_at = $podcast->published_at->addSeconds(1); + $episode->published_at = $this->podcast->published_at->addSeconds(1); $episodeModel = new EpisodeModel(); if (! $episodeModel->update($episode->id, $episode)) { @@ -861,11 +876,10 @@ class PodcastController extends BaseController ->with('errors', $episodeModel->errors()); } - $post = new PostModel() - ->where('episode_id', $episode->id) + $post = (new PostModel())->where('episode_id', $episode->id) ->first(); - if ($post instanceof Post) { + if ($post !== null) { $post->published_at = $episode->published_at; $postModel = new PostModel(); if (! $postModel->update($post->id, $post)) { @@ -879,7 +893,7 @@ class PodcastController extends BaseController } $podcastModel = new PodcastModel(); - if (! $podcastModel->update($podcast->id, $podcast)) { + if (! $podcastModel->update($this->podcast->id, $this->podcast)) { $db->transRollback(); return redirect() ->back() @@ -889,13 +903,13 @@ class PodcastController extends BaseController $db->transComplete(); - return redirect()->route('podcast-view', [$podcast->id]); + return redirect()->route('podcast-view', [$this->podcast->id]); } - public function publishCancelAction(Podcast $podcast): RedirectResponse + public function publishCancel(): RedirectResponse { - if ($podcast->publication_status !== 'scheduled') { - return redirect()->route('podcast-view', [$podcast->id]); + if ($this->podcast->publication_status !== 'scheduled') { + return redirect()->route('podcast-view', [$this->podcast->id]); } $db = db_connect(); @@ -904,17 +918,17 @@ class PodcastController extends BaseController $postModel = new PostModel(); $post = $postModel ->where([ - 'actor_id' => $podcast->actor_id, + 'actor_id' => $this->podcast->actor_id, 'episode_id' => null, ]) ->first(); - if ($post instanceof Post) { + if ($post !== null) { $postModel->removePost($post); } - $episodes = new EpisodeModel() - ->where('podcast_id', $podcast->id) - ->where('published_at !=') + $episodes = (new EpisodeModel()) + ->where('podcast_id', $this->podcast->id) + ->where('published_at !=', null) ->findAll(); foreach ($episodes as $episode) { @@ -935,10 +949,10 @@ class PodcastController extends BaseController $postModel->removePost($post); } - $podcast->published_at = null; + $this->podcast->published_at = null; $podcastModel = new PodcastModel(); - if (! $podcastModel->update($podcast->id, $podcast)) { + if (! $podcastModel->update($this->podcast->id, $this->podcast)) { $db->transRollback(); return redirect() ->back() @@ -948,9 +962,9 @@ class PodcastController extends BaseController $db->transComplete(); - return redirect()->route('podcast-view', [$podcast->id])->with( + return redirect()->route('podcast-view', [$this->podcast->id])->with( 'message', - lang('Podcast.messages.publishCancelSuccess'), + lang('Podcast.messages.publishCancelSuccess') ); } } diff --git a/modules/Admin/Controllers/PodcastImportController.php b/modules/Admin/Controllers/PodcastImportController.php new file mode 100644 index 00000000..39b0f09a --- /dev/null +++ b/modules/Admin/Controllers/PodcastImportController.php @@ -0,0 +1,706 @@ +{$method}(); + } + + if (($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) !== null) { + return $this->{$method}(); + } + + throw PageNotFoundException::forPageNotFound(); + } + + public function index(): string + { + helper(['form', 'misc']); + + $languageOptions = (new LanguageModel())->getLanguageOptions(); + $categoryOptions = (new CategoryModel())->getCategoryOptions(); + + $data = [ + 'languageOptions' => $languageOptions, + 'categoryOptions' => $categoryOptions, + 'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE')), + ]; + + return view('podcast/import', $data); + } + + public function attemptImport(): RedirectResponse + { + helper(['media', 'misc']); + + $rules = [ + 'handle' => 'required|regex_match[/^[a-zA-Z0-9\_]{1,32}$/]', + 'imported_feed_url' => 'required|validate_url', + 'season_number' => 'is_natural_no_zero|permit_empty', + 'max_episodes' => 'is_natural_no_zero|permit_empty', + ]; + + if (! $this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); + } + + try { + ini_set('user_agent', 'Castopod/' . CP_VERSION); + $feed = simplexml_load_file($this->request->getPost('imported_feed_url')); + } catch (ErrorException $errorException) { + return redirect() + ->back() + ->withInput() + ->with('errors', [ + $errorException->getMessage() . + ': ' . + $this->request->getPost('imported_feed_url') . + ' ⎋', + ]); + } + + $nsItunes = $feed->channel[0]->children('http://www.itunes.com/dtds/podcast-1.0.dtd'); + $nsPodcast = $feed->channel[0]->children( + 'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md', + ); + $nsContent = $feed->channel[0]->children('http://purl.org/rss/1.0/modules/content/'); + + if ((string) $nsPodcast->locked === 'yes') { + return redirect() + ->back() + ->withInput() + ->with('errors', [lang('PodcastImport.lock_import')]); + } + + $converter = new HtmlConverter(); + + $channelDescriptionHtml = (string) $feed->channel[0]->description; + + try { + if ( + property_exists($nsItunes, 'image') && $nsItunes->image !== null && + $nsItunes->image->attributes()['href'] !== null + ) { + $coverFile = download_file((string) $nsItunes->image->attributes()['href']); + } else { + $coverFile = download_file((string) $feed->channel[0]->image->url); + } + + $location = null; + if (property_exists($nsPodcast, 'location') && $nsPodcast->location !== null) { + $location = new Location( + (string) $nsPodcast->location, + $nsPodcast->location->attributes()['geo'] === null ? null : (string) $nsPodcast->location->attributes()['geo'], + $nsPodcast->location->attributes()['osm'] === null ? null : (string) $nsPodcast->location->attributes()['osm'], + ); + } + + $guid = null; + if (property_exists($nsPodcast, 'guid') && $nsPodcast->guid !== null) { + $guid = (string) $nsPodcast->guid; + } + + $db = db_connect(); + $db->transStart(); + + $podcast = new Podcast([ + 'guid' => $guid, + 'handle' => $this->request->getPost('handle'), + 'imported_feed_url' => $this->request->getPost('imported_feed_url'), + 'new_feed_url' => url_to('podcast-rss-feed', $this->request->getPost('handle')), + 'title' => (string) $feed->channel[0]->title, + 'description_markdown' => $converter->convert($channelDescriptionHtml), + 'description_html' => $channelDescriptionHtml, + 'cover' => $coverFile, + 'banner' => null, + 'language_code' => $this->request->getPost('language'), + 'category_id' => $this->request->getPost('category'), + 'parental_advisory' => + property_exists($nsItunes, 'explicit') && $nsItunes->explicit !== null + ? (in_array((string) $nsItunes->explicit, ['yes', 'true'], true) + ? 'explicit' + : (in_array((string) $nsItunes->explicit, ['no', 'false'], true) + ? 'clean' + : null)) + : null, + 'owner_name' => (string) $nsItunes->owner->name, + 'owner_email' => (string) $nsItunes->owner->email, + 'publisher' => (string) $nsItunes->author, + 'type' => property_exists( + $nsItunes, + 'type' + ) && $nsItunes->type !== null ? (string) $nsItunes->type : 'episodic', + 'copyright' => (string) $feed->channel[0]->copyright, + 'is_blocked' => + property_exists($nsItunes, 'block') && $nsItunes->block !== null && (string) $nsItunes->block === 'yes', + 'is_completed' => + property_exists( + $nsItunes, + 'complete' + ) && $nsItunes->complete !== null && (string) $nsItunes->complete === 'yes', + 'location' => $location, + 'created_by' => user_id(), + 'updated_by' => user_id(), + ]); + } catch (ErrorException $ex) { + return redirect() + ->back() + ->withInput() + ->with('errors', [ + $ex->getMessage() . + ': ' . + $this->request->getPost('imported_feed_url') . + ' ⎋', + ]); + } + + $podcastModel = new PodcastModel(); + if (! ($newPodcastId = $podcastModel->insert($podcast, true))) { + $db->transRollback(); + return redirect() + ->back() + ->withInput() + ->with('errors', $podcastModel->errors()); + } + + $authorize = Services::authorization(); + $podcastAdminGroup = $authorize->group('podcast_admin'); + + $podcastModel->addPodcastContributor(user_id(), $newPodcastId, (int) $podcastAdminGroup->id); + + $podcastsPlatformsData = []; + $platformTypes = [ + [ + 'name' => 'podcasting', + 'elements' => $nsPodcast->id, + 'account_url_key' => 'url', + 'account_id_key' => 'id', + ], + [ + 'name' => 'social', + 'elements' => $nsPodcast->social, + 'account_url_key' => 'accountUrl', + 'account_id_key' => 'accountId', + ], + [ + 'name' => 'funding', + 'elements' => $nsPodcast->funding, + 'account_url_key' => 'url', + 'account_id_key' => 'id', + ], + ]; + $platformModel = new PlatformModel(); + foreach ($platformTypes as $platformType) { + foreach ($platformType['elements'] as $platform) { + $platformLabel = $platform->attributes()['platform']; + $platformSlug = slugify((string) $platformLabel); + if ($platformModel->getPlatform($platformSlug) !== null) { + $podcastsPlatformsData[] = [ + 'platform_slug' => $platformSlug, + 'podcast_id' => $newPodcastId, + 'link_url' => $platform->attributes()[$platformType['account_url_key']], + 'account_id' => $platform->attributes()[$platformType['account_id_key']], + 'is_visible' => false, + ]; + } + } + } + + if (count($podcastsPlatformsData) > 1) { + $platformModel->createPodcastPlatforms($newPodcastId, $podcastsPlatformsData); + } + + foreach ($nsPodcast->person as $podcastPerson) { + $fullName = (string) $podcastPerson; + $personModel = new PersonModel(); + $newPersonId = null; + if (($newPerson = $personModel->getPerson($fullName)) !== null) { + $newPersonId = $newPerson->id; + } else { + $newPodcastPerson = new Person([ + 'full_name' => $fullName, + 'unique_name' => slugify($fullName), + 'information_url' => $podcastPerson->attributes()['href'], + 'avatar' => download_file((string) $podcastPerson->attributes()['img']), + 'created_by' => user_id(), + 'updated_by' => user_id(), + ]); + + if (! $newPersonId = $personModel->insert($newPodcastPerson)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $personModel->errors()); + } + } + + // TODO: these checks should be in the taxonomy as default values + $podcastPersonGroup = $podcastPerson->attributes()['group'] ?? 'Cast'; + $podcastPersonRole = $podcastPerson->attributes()['role'] ?? 'Host'; + + $personGroup = ReversedTaxonomy::$taxonomy[(string) $podcastPersonGroup]; + + $personGroupSlug = $personGroup['slug']; + $personRoleSlug = $personGroup['roles'][(string) $podcastPersonRole]['slug']; + + $podcastPersonModel = new PersonModel(); + if (! $podcastPersonModel->addPodcastPerson( + $newPodcastId, + $newPersonId, + $personGroupSlug, + $personRoleSlug + )) { + return redirect() + ->back() + ->withInput() + ->with('errors', $podcastPersonModel->errors()); + } + } + + $itemsCount = $feed->channel[0]->item->count(); + + $lastItem = + $this->request->getPost('max_episodes') !== '' && + $this->request->getPost('max_episodes') < $itemsCount + ? (int) $this->request->getPost('max_episodes') + : $itemsCount; + + $slugs = []; + for ($itemNumber = 1; $itemNumber <= $lastItem; ++$itemNumber) { + $item = $feed->channel[0]->item[$itemsCount - $itemNumber]; + + $nsItunes = $item->children('http://www.itunes.com/dtds/podcast-1.0.dtd'); + $nsPodcast = $item->children( + 'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md', + ); + $nsContent = $item->children('http://purl.org/rss/1.0/modules/content/'); + + $textToSlugify = $this->request->getPost('slug_field') === 'title' + ? (string) $item->title + : basename((string) $item->link); + $slug = slugify($textToSlugify, 120); + if (in_array($slug, $slugs, true)) { + $slugNumber = 2; + while (in_array($slug . '-' . $slugNumber, $slugs, true)) { + ++$slugNumber; + } + + $slug = $slug . '-' . $slugNumber; + } + + $slugs[] = $slug; + $itemDescriptionHtml = match ($this->request->getPost('description_field')) { + 'content' => (string) $nsContent->encoded, + 'summary' => (string) $nsItunes->summary, + 'subtitle_summary' => $nsItunes->subtitle . '
    ' . $nsItunes->summary, + default => (string) $item->description, + }; + + if ( + property_exists($nsItunes, 'image') && $nsItunes->image !== null && + $nsItunes->image->attributes()['href'] !== null + ) { + $episodeCover = download_file((string) $nsItunes->image->attributes()['href']); + } else { + $episodeCover = null; + } + + $location = null; + if (property_exists($nsPodcast, 'location') && $nsPodcast->location !== null) { + $location = new Location( + (string) $nsPodcast->location, + $nsPodcast->location->attributes()['geo'] === null ? null : (string) $nsPodcast->location->attributes()['geo'], + $nsPodcast->location->attributes()['osm'] === null ? null : (string) $nsPodcast->location->attributes()['osm'], + ); + } + + $newEpisode = new Episode([ + 'podcast_id' => $newPodcastId, + 'title' => $item->title, + 'slug' => $slug, + 'guid' => $item->guid ?? null, + 'audio' => download_file( + (string) $item->enclosure->attributes()['url'], + (string) $item->enclosure->attributes()['type'] + ), + 'description_markdown' => $converter->convert($itemDescriptionHtml), + 'description_html' => $itemDescriptionHtml, + 'cover' => $episodeCover, + 'parental_advisory' => + property_exists($nsItunes, 'explicit') && $nsItunes->explicit !== null + ? (in_array((string) $nsItunes->explicit, ['yes', 'true'], true) + ? 'explicit' + : (in_array((string) $nsItunes->explicit, ['no', 'false'], true) + ? 'clean' + : null)) + : null, + 'number' => + $this->request->getPost('force_renumber') === 'yes' + ? $itemNumber + : ((string) $nsItunes->episode === '' ? null : (int) $nsItunes->episode), + 'season_number' => + $this->request->getPost('season_number') === '' + ? ((string) $nsItunes->season === '' ? null : (int) $nsItunes->season) + : (int) $this->request->getPost('season_number'), + 'type' => property_exists($nsItunes, 'episodeType') && in_array( + $nsItunes->episodeType, + ['trailer', 'full', 'bonus'], + true + ) + ? (string) $nsItunes->episodeType + : 'full', + 'is_blocked' => property_exists( + $nsItunes, + 'block' + ) && $nsItunes->block !== null && (string) $nsItunes->block === 'yes', + 'location' => $location, + 'created_by' => user_id(), + 'updated_by' => user_id(), + 'published_at' => strtotime((string) $item->pubDate), + ]); + + $episodeModel = new EpisodeModel(); + + if (! ($newEpisodeId = $episodeModel->insert($newEpisode, true))) { + // FIXME: What shall we do? + return redirect() + ->back() + ->withInput() + ->with('errors', $episodeModel->errors()); + } + + foreach ($nsPodcast->person as $episodePerson) { + $fullName = (string) $episodePerson; + $personModel = new PersonModel(); + $newPersonId = null; + if (($newPerson = $personModel->getPerson($fullName)) !== null) { + $newPersonId = $newPerson->id; + } else { + $newPerson = new Person([ + 'full_name' => $fullName, + 'unique_name' => slugify($fullName), + 'information_url' => $episodePerson->attributes()['href'], + 'avatar' => download_file((string) $episodePerson->attributes()['img']), + 'created_by' => user_id(), + 'updated_by' => user_id(), + ]); + + if (! ($newPersonId = $personModel->insert($newPerson))) { + return redirect() + ->back() + ->withInput() + ->with('errors', $personModel->errors()); + } + } + + // TODO: these checks should be in the taxonomy as default values + $episodePersonGroup = $episodePerson->attributes()['group'] ?? 'Cast'; + $episodePersonRole = $episodePerson->attributes()['role'] ?? 'Host'; + + $personGroup = ReversedTaxonomy::$taxonomy[(string) $episodePersonGroup]; + + $personGroupSlug = $personGroup['slug']; + $personRoleSlug = $personGroup['roles'][(string) $episodePersonRole]['slug']; + + $episodePersonModel = new PersonModel(); + if (! $episodePersonModel->addEpisodePerson( + $newPodcastId, + $newEpisodeId, + $newPersonId, + $personGroupSlug, + $personRoleSlug + )) { + return redirect() + ->back() + ->withInput() + ->with('errors', $episodePersonModel->errors()); + } + } + + if ($itemNumber === 1) { + $firstEpisodePublicationDate = strtotime((string) $item->pubDate); + } + } + + // set interact as the newly imported podcast actor + $importedPodcast = (new PodcastModel())->getPodcastById($newPodcastId); + set_interact_as_actor($importedPodcast->actor_id); + + // set podcast publication date + $importedPodcast->published_at = $firstEpisodePublicationDate ?? $importedPodcast->created_at; + $podcastModel = new PodcastModel(); + if (! $podcastModel->update($importedPodcast->id, $importedPodcast)) { + $db->transRollback(); + return redirect() + ->back() + ->withInput() + ->with('errors', $podcastModel->errors()); + } + + $db->transComplete(); + + return redirect()->route('podcast-view', [$newPodcastId]); + } + + public function updateImport(): RedirectResponse + { + if ($this->podcast->imported_feed_url === null) { + return redirect() + ->back() + ->with('error', lang('Podcast.messages.podcastNotImported')); + } + + try { + ini_set('user_agent', 'Castopod/' . CP_VERSION); + $feed = simplexml_load_file($this->podcast->imported_feed_url); + } catch (ErrorException $errorException) { + return redirect() + ->back() + ->withInput() + ->with('errors', [ + $errorException->getMessage() . + ': ' . + $this->podcast->imported_feed_url . + ' ⎋', + ]); + } + + $nsPodcast = $feed->channel[0]->children( + 'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md', + ); + + if ((string) $nsPodcast->locked === 'yes') { + return redirect() + ->back() + ->withInput() + ->with('errors', [lang('PodcastImport.lock_import')]); + } + + $itemsCount = $feed->channel[0]->item->count(); + + $lastItem = $itemsCount; + + $lastEpisode = (new EpisodeModel())->where('podcast_id', $this->podcast->id) + ->orderBy('created_at', 'desc') + ->first(); + + if ($lastEpisode !== null) { + for ($itemNumber = 0; $itemNumber < $itemsCount; ++$itemNumber) { + $item = $feed->channel[0]->item[$itemNumber]; + + if (property_exists( + $item, + 'guid' + ) && $item->guid !== null && $lastEpisode->guid === (string) $item->guid) { + $lastItem = $itemNumber; + break; + } + } + } + + if ($lastItem === 0) { + return redirect() + ->back() + ->with('message', lang('Podcast.messages.podcastFeedUpToDate')); + } + + helper(['media', 'misc']); + + $converter = new HtmlConverter(); + + $slugs = []; + + $db = db_connect(); + $db->transStart(); + + for ($itemNumber = 1; $itemNumber <= $lastItem; ++$itemNumber) { + $item = $feed->channel[0]->item[$lastItem - $itemNumber]; + + $nsItunes = $item->children('http://www.itunes.com/dtds/podcast-1.0.dtd'); + $nsPodcast = $item->children( + 'https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md', + ); + + $textToSlugify = (string) $item->title; + $slug = slugify($textToSlugify, 120); + if (in_array($slug, $slugs, true) || (new EpisodeModel())->where([ + 'slug' => $slug, + 'podcast_id' => $this->podcast->id, + ])->first()) { + $slugNumber = 2; + while (in_array($slug . '-' . $slugNumber, $slugs, true) || (new EpisodeModel())->where([ + 'slug' => $slug . '-' . $slugNumber, + 'podcast_id' => $this->podcast->id, + ])->first()) { + ++$slugNumber; + } + + $slug = $slug . '-' . $slugNumber; + } + + $slugs[] = $slug; + + $itemDescriptionHtml = (string) $item->description; + + if ( + property_exists($nsItunes, 'image') && $nsItunes->image !== null && + $nsItunes->image->attributes()['href'] !== null + ) { + $episodeCover = download_file((string) $nsItunes->image->attributes()['href']); + } else { + $episodeCover = null; + } + + $location = null; + if (property_exists($nsPodcast, 'location') && $nsPodcast->location !== null) { + $location = new Location( + (string) $nsPodcast->location, + $nsPodcast->location->attributes()['geo'] === null ? null : (string) $nsPodcast->location->attributes()['geo'], + $nsPodcast->location->attributes()['osm'] === null ? null : (string) $nsPodcast->location->attributes()['osm'], + ); + } + + $newEpisode = new Episode([ + 'podcast_id' => $this->podcast->id, + 'title' => $item->title, + 'slug' => $slug, + 'guid' => $item->guid ?? null, + 'audio' => download_file( + (string) $item->enclosure->attributes()['url'], + (string) $item->enclosure->attributes()['type'] + ), + 'description_markdown' => $converter->convert($itemDescriptionHtml), + 'description_html' => $itemDescriptionHtml, + 'cover' => $episodeCover, + 'parental_advisory' => + property_exists($nsItunes, 'explicit') && $nsItunes->explicit !== null + ? (in_array((string) $nsItunes->explicit, ['yes', 'true'], true) + ? 'explicit' + : (in_array((string) $nsItunes->explicit, ['no', 'false'], true) + ? 'clean' + : null)) + : null, + 'number' => ((string) $nsItunes->episode === '' ? null : (int) $nsItunes->episode), + 'season_number' => ((string) $nsItunes->season === '' ? null : (int) $nsItunes->season), + 'type' => property_exists($nsItunes, 'episodeType') && $nsItunes->episodeType !== null + ? (string) $nsItunes->episodeType + : 'full', + 'is_blocked' => property_exists( + $nsItunes, + 'block' + ) && $nsItunes->block !== null && (string) $nsItunes->block === 'yes', + 'location' => $location, + 'created_by' => user_id(), + 'updated_by' => user_id(), + 'published_at' => strtotime((string) $item->pubDate), + ]); + + $episodeModel = new EpisodeModel(); + + if (! ($newEpisodeId = $episodeModel->insert($newEpisode, true))) { + // FIXME: What shall we do? + return redirect() + ->back() + ->withInput() + ->with('errors', $episodeModel->errors()); + } + + foreach ($nsPodcast->person as $episodePerson) { + $fullName = (string) $episodePerson; + $personModel = new PersonModel(); + $newPersonId = null; + if (($newPerson = $personModel->getPerson($fullName)) !== null) { + $newPersonId = $newPerson->id; + } else { + $newPerson = new Person([ + 'full_name' => $fullName, + 'unique_name' => slugify($fullName), + 'information_url' => $episodePerson->attributes()['href'], + 'avatar' => download_file((string) $episodePerson->attributes()['img']), + 'created_by' => user_id(), + 'updated_by' => user_id(), + ]); + + if (! ($newPersonId = $personModel->insert($newPerson))) { + return redirect() + ->back() + ->withInput() + ->with('errors', $personModel->errors()); + } + } + + // TODO: these checks should be in the taxonomy as default values + $episodePersonGroup = $episodePerson->attributes()['group'] ?? 'Cast'; + $episodePersonRole = $episodePerson->attributes()['role'] ?? 'Host'; + + $personGroup = ReversedTaxonomy::$taxonomy[(string) $episodePersonGroup]; + + $personGroupSlug = $personGroup['slug']; + $personRoleSlug = $personGroup['roles'][(string) $episodePersonRole]['slug']; + + $episodePersonModel = new PersonModel(); + if (! $episodePersonModel->addEpisodePerson( + $this->podcast->id, + $newEpisodeId, + $newPersonId, + $personGroupSlug, + $personRoleSlug + )) { + return redirect() + ->back() + ->withInput() + ->with('errors', $episodePersonModel->errors()); + } + } + } + + $db->transComplete(); + + return redirect()->route('podcast-view', [$this->podcast->id])->with( + 'message', + lang('Podcast.messages.podcastFeedUpdateSuccess', [ + 'number_of_new_episodes' => $lastItem, + ]) + ); + } +} diff --git a/modules/Admin/Controllers/PodcastPersonController.php b/modules/Admin/Controllers/PodcastPersonController.php index 7713bbfc..722ba28a 100644 --- a/modules/Admin/Controllers/PodcastPersonController.php +++ b/modules/Admin/Controllers/PodcastPersonController.php @@ -27,37 +27,32 @@ class PodcastPersonController extends BaseController } if ( - ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast + ($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) !== null ) { unset($params[0]); - return $this->{$method}($podcast, ...$params); + return $this->{$method}(...$params); } throw PageNotFoundException::forPageNotFound(); } - public function index(Podcast $podcast): string + public function index(): string { helper('form'); $data = [ - 'podcast' => $podcast, - 'podcastPersons' => new PersonModel() - ->getPodcastPersons($podcast->id), - 'personOptions' => new PersonModel() - ->getPersonOptions(), - 'taxonomyOptions' => new PersonModel() - ->getTaxonomyOptions(), + 'podcast' => $this->podcast, + 'podcastPersons' => (new PersonModel())->getPodcastPersons($this->podcast->id), + 'personOptions' => (new PersonModel())->getPersonOptions(), + 'taxonomyOptions' => (new PersonModel())->getTaxonomyOptions(), ]; - - $this->setHtmlHead(lang('Person.podcast_form.title')); replace_breadcrumb_params([ - 0 => $podcast->at_handle, + 0 => $this->podcast->title, ]); return view('podcast/persons', $data); } - public function createAction(Podcast $podcast): RedirectResponse + public function attemptAdd(): RedirectResponse { $rules = [ 'persons' => 'required', @@ -70,18 +65,18 @@ class PodcastPersonController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - new PersonModel() - ->addPodcastPersons($podcast->id, $validData['persons'], $this->request->getPost('roles') ?? []); + (new PersonModel())->addPodcastPersons( + $this->podcast->id, + $this->request->getPost('persons'), + $this->request->getPost('roles') ?? [], + ); return redirect()->back(); } - public function deleteAction(Podcast $podcast, string $personId): RedirectResponse + public function remove(string $personId): RedirectResponse { - new PersonModel() - ->removePersonFromPodcast($podcast->id, (int) $personId); + (new PersonModel())->removePersonFromPodcast($this->podcast->id, (int) $personId); return redirect()->back(); } diff --git a/modules/Admin/Controllers/PodcastPlatformController.php b/modules/Admin/Controllers/PodcastPlatformController.php new file mode 100644 index 00000000..08b8f961 --- /dev/null +++ b/modules/Admin/Controllers/PodcastPlatformController.php @@ -0,0 +1,110 @@ +{$method}(); + } + + if ( + ($this->podcast = (new PodcastModel())->getPodcastById((int) $params[0])) !== null + ) { + unset($params[0]); + return $this->{$method}(...$params); + } + + throw PageNotFoundException::forPageNotFound(); + } + + public function index(): string + { + return view('podcast/platforms\dashboard'); + } + + public function platforms(string $platformType): string + { + helper('form'); + + $data = [ + 'podcast' => $this->podcast, + 'platformType' => $platformType, + 'platforms' => (new PlatformModel())->getPlatformsWithLinks($this->podcast->id, $platformType), + ]; + + replace_breadcrumb_params([ + 0 => $this->podcast->title, + ]); + + return view('podcast/platforms', $data); + } + + public function attemptPlatformsUpdate(string $platformType): RedirectResponse + { + $platformModel = new PlatformModel(); + $validation = Services::validation(); + + $podcastsPlatformsData = []; + + foreach ( + $this->request->getPost('platforms') + as $platformSlug => $podcastPlatform + ) { + $podcastPlatformUrl = $podcastPlatform['url']; + if ($podcastPlatformUrl === null) { + continue; + } + + if (! $validation->check($podcastPlatformUrl, 'validate_url')) { + continue; + } + + $podcastsPlatformsData[] = [ + 'platform_slug' => $platformSlug, + 'podcast_id' => $this->podcast->id, + 'link_url' => $podcastPlatformUrl, + 'account_id' => $podcastPlatform['account_id'] === '' ? null : $podcastPlatform['account_id'], + 'is_visible' => + array_key_exists('visible', $podcastPlatform) && + $podcastPlatform['visible'] === 'yes', + 'is_on_embed' => + array_key_exists('on_embed', $podcastPlatform,) && $podcastPlatform['on_embed'] === 'yes', + ]; + } + + $platformModel->savePodcastPlatforms($this->podcast->id, $platformType, $podcastsPlatformsData); + + return redirect() + ->back() + ->with('message', lang('Platforms.messages.updateSuccess')); + } + + public function removePodcastPlatform(string $platformSlug): RedirectResponse + { + (new PlatformModel())->removePodcastPlatform($this->podcast->id, $platformSlug); + + return redirect() + ->back() + ->with('message', lang('Platforms.messages.removeLinkSuccess')); + } +} diff --git a/modules/MediaClipper/Commands/Generate.php b/modules/Admin/Controllers/SchedulerController.php similarity index 56% rename from modules/MediaClipper/Commands/Generate.php rename to modules/Admin/Controllers/SchedulerController.php index 656349ac..d13a29e4 100644 --- a/modules/MediaClipper/Commands/Generate.php +++ b/modules/Admin/Controllers/SchedulerController.php @@ -2,61 +2,56 @@ declare(strict_types=1); -namespace Modules\MediaClipper\Commands; +/** + * @copyright 2021 Ad Aures + * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 + * @link https://castopod.org/ + */ + +namespace Modules\Admin\Controllers; use App\Models\ClipModel; -use CodeIgniter\CLI\BaseCommand; -use CodeIgniter\Files\File; +use CodeIgniter\Controller; use CodeIgniter\I18n\Time; use Exception; -use Modules\MediaClipper\VideoClipper; -use Override; +use MediaClipper\VideoClipper; -class Generate extends BaseCommand +class SchedulerController extends Controller { - protected $group = 'media-clipper'; - - protected $name = 'video-clips:generate'; - - protected $description = 'Displays basic application information.'; - - #[Override] - public function run(array $params): void + public function generateVideoClips(): bool { // get number of running clips to prevent from having too much running in parallel // TODO: get the number of running ffmpeg processes directly from the machine? - $runningVideoClips = new ClipModel() - ->getRunningVideoClipsCount(); + $runningVideoClips = (new ClipModel())->getRunningVideoClipsCount(); if ($runningVideoClips >= config('Admin')->videoClipWorkers) { - return; + return true; } // get all clips that haven't been processed yet - $scheduledClips = new ClipModel() - ->getScheduledVideoClips(); + $scheduledClips = (new ClipModel())->getScheduledVideoClips(); if ($scheduledClips === []) { - return; + return true; } $data = []; foreach ($scheduledClips as $scheduledClip) { $data[] = [ - 'id' => $scheduledClip->id, + 'id' => $scheduledClip->id, 'status' => 'pending', ]; } - new ClipModel() - ->updateBatch($data, 'id'); + (new ClipModel())->updateBatch($data, 'id'); // Loop through clips to generate them foreach ($scheduledClips as $scheduledClip) { try { + // set clip to pending - new ClipModel() + (new ClipModel()) ->update($scheduledClip->id, [ - 'status' => 'running', + 'status' => 'running', 'job_started_at' => Time::now(), ]); $clipper = new VideoClipper( @@ -71,31 +66,32 @@ class Generate extends BaseCommand $clipModel = new ClipModel(); if ($exitCode === 0) { // success, video was generated - $scheduledClip->setMedia(new File($clipper->videoClipOutput), $clipper->videoClipFileKey); + $scheduledClip->setMedia($clipper->videoClipFilePath); $clipModel->update($scheduledClip->id, [ - 'media_id' => $scheduledClip->media_id, - 'status' => 'passed', - 'logs' => $clipper->logs, + 'media_id' => $scheduledClip->media_id, + 'status' => 'passed', + 'logs' => $clipper->logs, 'job_ended_at' => Time::now(), ]); } else { // error $clipModel->update($scheduledClip->id, [ - 'status' => 'failed', - 'logs' => $clipper->logs, + 'status' => 'failed', + 'logs' => $clipper->logs, 'job_ended_at' => Time::now(), ]); } $clipModel->clearVideoClipCache($scheduledClip->id); } catch (Exception $exception) { - new ClipModel() - ->update($scheduledClip->id, [ - 'status' => 'failed', - 'logs' => $exception, - 'job_ended_at' => Time::now(), - ]); + (new ClipModel())->update($scheduledClip->id, [ + 'status' => 'failed', + 'logs' => $exception, + 'job_ended_at' => Time::now(), + ]); } } + + return true; } } diff --git a/modules/Admin/Controllers/SettingsController.php b/modules/Admin/Controllers/SettingsController.php index f0e8c508..8fd936f4 100644 --- a/modules/Admin/Controllers/SettingsController.php +++ b/modules/Admin/Controllers/SettingsController.php @@ -10,19 +10,15 @@ declare(strict_types=1); namespace Modules\Admin\Controllers; -use App\Entities\Podcast; use App\Models\ActorModel; use App\Models\EpisodeCommentModel; use App\Models\EpisodeModel; +use App\Models\MediaModel; use App\Models\PersonModel; use App\Models\PodcastModel; use App\Models\PostModel; use CodeIgniter\Files\File; -use CodeIgniter\HTTP\Files\UploadedFile; use CodeIgniter\HTTP\RedirectResponse; -use Modules\Media\Entities\Audio; -use Modules\Media\FileManagers\FileManagerInterface; -use Modules\Media\Models\MediaModel; use PHP_ICO; class SettingsController extends BaseController @@ -30,14 +26,14 @@ class SettingsController extends BaseController public function index(): string { helper('form'); - $this->setHtmlHead(lang('Settings.title')); return view('settings/general'); } - public function instanceEditAction(): RedirectResponse + public function attemptInstanceEdit(): RedirectResponse { $rules = [ - 'site_icon' => 'is_image[site_icon]|ext_in[site_icon,png,jpeg]|is_image_ratio[site_icon,1,1]|min_dims[image,512,512]|permit_empty', + 'site_icon' => + 'is_image[site_icon]|ext_in[site_icon,png,jpeg]|is_image_ratio[site_icon,1,1]|min_dims[image,512,512]|permit_empty', ]; if (! $this->validate($rules)) { @@ -58,74 +54,56 @@ class SettingsController extends BaseController } $siteIconFile = $this->request->getFile('site_icon'); - if ($siteIconFile instanceof UploadedFile && $siteIconFile->isValid()) { - /** @var FileManagerInterface $fileManager */ - $fileManager = service('file_manager'); + if ($siteIconFile !== null && $siteIconFile->isValid()) { + helper(['filesystem', 'media']); // delete site folder in media before repopulating it - $fileManager->deleteAll('site'); + delete_files(media_path('/site')); + + // save original in disk + $originalFilename = save_media($siteIconFile, 'site', 'icon'); // convert jpeg image to png if not if ($siteIconFile->getClientMimeType() !== 'image/png') { - $tempFilePath = tempnam(WRITEPATH . 'temp', 'img_'); - service('image') - ->withFile($siteIconFile->getRealPath()) + service('image')->withFile(media_path($originalFilename)) ->convert(IMAGETYPE_JPEG) - ->save($tempFilePath); - - @unlink($siteIconFile->getRealPath()); - - $siteIconFile = new File($tempFilePath, true); + ->save(media_path('/site/icon.png')); } - $icoTempFilePath = WRITEPATH . 'temp/img_favicon.ico'; - - // generate ico - $ico_lib = new PHP_ICO(); - $ico_lib->add_image($siteIconFile->getRealPath(), [[32, 32], [64, 64]]); - $ico_lib->save_ico($icoTempFilePath); - // generate random hash to use as a suffix to renew browser cache $randomHash = substr(bin2hex(random_bytes(18)), 0, 8); - // save ico - $fileManager->save(new File($icoTempFilePath, true), "site/favicon.{$randomHash}.ico"); + // generate ico + $ico_lib = new PHP_ICO(); + $ico_lib->add_image(media_path('/site/icon.png'), [[32, 32], [64, 64]]); + $ico_lib->save_ico(media_path("/site/favicon.{$randomHash}.ico")); // resize original to needed sizes foreach ([64, 180, 192, 512] as $size) { - $tempFilePath = tempnam(WRITEPATH . 'temp', 'img_'); service('image') - ->withFile($siteIconFile->getRealPath()) + ->withFile(media_path('/site/icon.png')) ->resize($size, $size) - ->save($tempFilePath); - - // save sizes to - $fileManager->save(new File($tempFilePath), "site/icon-{$size}.{$randomHash}.png"); + ->save(media_path("/site/icon-{$size}.{$randomHash}.png")); } - // save original as png - $fileManager->save($siteIconFile, 'site/icon.png'); - service('settings') ->set('App.siteIcon', [ - 'ico' => "site/favicon.{$randomHash}.ico", - '64' => "site/icon-64.{$randomHash}.png", - '180' => "site/icon-180.{$randomHash}.png", - '192' => "site/icon-192.{$randomHash}.png", - '512' => "site/icon-512.{$randomHash}.png", + 'ico' => '/' . media_path("/site/favicon.{$randomHash}.ico"), + '64' => '/' . media_path("/site/icon-64.{$randomHash}.png"), + '180' => '/' . media_path("/site/icon-180.{$randomHash}.png"), + '192' => '/' . media_path("/site/icon-192.{$randomHash}.png"), + '512' => '/' . media_path("/site/icon-512.{$randomHash}.png"), ]); } return redirect('settings-general')->with('message', lang('Settings.instance.editSuccess')); } - public function deleteIconAction(): RedirectResponse + public function deleteIcon(): RedirectResponse { - /** @var FileManagerInterface $fileManager */ - $fileManager = service('file_manager'); - - // delete site folder - $fileManager->deleteAll('site'); + helper(['filesystem', 'media']); + // delete site folder in media + delete_files(media_path('/site')); service('settings') ->forget('App.siteIcon'); @@ -133,17 +111,25 @@ class SettingsController extends BaseController return redirect('settings-general')->with('message', lang('Settings.instance.deleteIconSuccess')); } - public function regenerateImagesAction(): RedirectResponse + public function regenerateImages(): RedirectResponse { - /** @var Podcast[] $allPodcasts */ - $allPodcasts = new PodcastModel() - ->findAll(); + helper('media'); - /** @var FileManagerInterface $fileManager */ - $fileManager = service('file_manager'); + $allPodcasts = (new PodcastModel())->findAll(); + $imageExt = ['jpg', 'png', 'webp']; foreach ($allPodcasts as $podcast) { - $fileManager->deletePodcastImageSizes($podcast->handle); + foreach ($imageExt as $ext) { + $podcastImages = glob(media_path("/podcasts/{$podcast->handle}/*_*{$ext}")); + + if ($podcastImages) { + foreach ($podcastImages as $podcastImage) { + if (is_file($podcastImage)) { + unlink($podcastImage); + } + } + } + } $podcast->cover->saveSizes(); if ($podcast->banner_id !== null) { @@ -157,10 +143,18 @@ class SettingsController extends BaseController } } - $fileManager->deletePersonImagesSizes(); + foreach ($imageExt as $ext) { + $personsImages = glob(media_path("/persons/*_*{$ext}")); + if ($personsImages) { + foreach ($personsImages as $personsImage) { + if (is_file($personsImage)) { + unlink($personsImage); + } + } + } + } - $persons = new PersonModel() - ->findAll(); + $persons = (new PersonModel())->findAll(); foreach ($persons as $person) { if ($person->avatar_id !== null) { $person->avatar->saveSizes(); @@ -170,30 +164,124 @@ class SettingsController extends BaseController return redirect('settings-general')->with('message', lang('Settings.images.regenerationSuccess')); } - public function housekeepingAction(): RedirectResponse + public function runHousekeeping(): RedirectResponse { if ($this->request->getPost('reset_counts') === 'yes') { // recalculate fediverse counts - new ActorModel() - ->resetFollowersCount(); - new ActorModel() - ->resetPostsCount(); - new PostModel() - ->setEpisodeIdForRepliesOfEpisodePosts(); - new PostModel() - ->resetFavouritesCount(); - new PostModel() - ->resetReblogsCount(); - new PostModel() - ->resetRepliesCount(); - new EpisodeModel() - ->resetCommentsCount(); - new EpisodeModel() - ->resetPostsCount(); - new EpisodeCommentModel() - ->resetLikesCount(); - new EpisodeCommentModel() - ->resetRepliesCount(); + (new ActorModel())->resetFollowersCount(); + (new ActorModel())->resetPostsCount(); + (new PostModel())->setEpisodeIdForRepliesOfEpisodePosts(); + (new PostModel())->resetFavouritesCount(); + (new PostModel())->resetReblogsCount(); + (new PostModel())->resetRepliesCount(); + (new EpisodeModel())->resetCommentsCount(); + (new EpisodeModel())->resetPostsCount(); + (new EpisodeCommentModel())->resetLikesCount(); + (new EpisodeCommentModel())->resetRepliesCount(); + } + + helper('media'); + + if ($this->request->getPost('rewrite_media') === 'yes') { + $imageExt = ['jpg', 'png', 'webp']; + // Delete all podcast image sizes to recreate them + $allPodcasts = (new PodcastModel())->findAll(); + foreach ($allPodcasts as $podcast) { + foreach ($imageExt as $ext) { + $podcastImages = glob(media_path("/podcasts/{$podcast->handle}/*_*{$ext}")); + + if ($podcastImages) { + foreach ($podcastImages as $podcastImage) { + if (is_file($podcastImage)) { + unlink($podcastImage); + } + } + } + } + } + + // Delete all person image sizes to recreate them + foreach ($imageExt as $ext) { + $personsImages = glob(media_path("/persons/*_*{$ext}")); + if ($personsImages) { + foreach ($personsImages as $personsImage) { + if (is_file($personsImage)) { + unlink($personsImage); + } + } + } + } + + $allImages = (new MediaModel('image'))->getAllOfType(); + foreach ($allImages as $image) { + if (str_starts_with($image->file_path, 'podcasts')) { + if (str_ends_with($image->file_path, 'banner.jpg') || str_ends_with( + $image->file_path, + 'banner.png' + ) || str_ends_with($image->file_path, 'banner.jpeg')) { + $image->sizes = config('Images') + ->podcastBannerSizes; + } else { + $image->sizes = config('Images') + ->podcastCoverSizes; + } + } elseif (str_starts_with($image->file_path, 'persons')) { + $image->sizes = config('Images') + ->personAvatarSizes; + } else { + $image->sizes = []; + } + + $image->setFile(new File(media_path($image->file_path))); + + (new MediaModel('image'))->updateMedia($image); + } + + $allAudio = (new MediaModel('audio'))->getAllOfType(); + foreach ($allAudio as $audio) { + $audio->setFile(new File(media_path($audio->file_path))); + + (new MediaModel('audio'))->updateMedia($audio); + } + + $allTranscripts = (new MediaModel('transcript'))->getAllOfType(); + foreach ($allTranscripts as $transcript) { + $transcript->setFile(new File(media_path($transcript->file_path))); + + (new MediaModel('transcript'))->updateMedia($transcript); + } + + $allChapters = (new MediaModel('chapters'))->getAllOfType(); + foreach ($allChapters as $chapters) { + $chapters->setFile(new File(media_path($chapters->file_path))); + + (new MediaModel('chapters'))->updateMedia($chapters); + } + + $allVideos = (new MediaModel('video'))->getAllOfType(); + foreach ($allVideos as $video) { + $video->setFile(new File(media_path($video->file_path))); + + (new MediaModel('video'))->updateMedia($video); + } + + // reset avatar and banner image urls for each podcast actor + foreach ($allPodcasts as $podcast) { + $actorModel = new ActorModel(); + $actor = $actorModel->getActorById($podcast->actor_id); + + if ($actor !== null) { + // update values + $actor->avatar_image_url = $podcast->cover->federation_url; + $actor->avatar_image_mimetype = $podcast->cover->file_mimetype; + $actor->cover_image_url = $podcast->banner->federation_url; + $actor->cover_image_mimetype = $podcast->banner->file_mimetype; + + if ($actor->hasChanged()) { + $actorModel->update($actor->id, $actor); + } + } + } } if ($this->request->getPost('clear_cache') === 'yes') { @@ -201,9 +289,7 @@ class SettingsController extends BaseController } if ($this->request->getPost('rename_episodes_files') === 'yes') { - /** @var Audio[] $allAudio */ - $allAudio = new MediaModel('audio') - ->getAllOfType(); + $allAudio = (new MediaModel('audio'))->getAllOfType(); foreach ($allAudio as $audio) { $audio->rename(); @@ -213,14 +299,13 @@ class SettingsController extends BaseController return redirect('settings-general')->with('message', lang('Settings.housekeeping.runSuccess')); } - public function themeView(): string + public function theme(): string { helper('form'); - $this->setHtmlHead(lang('Settings.theme.title')); return view('settings/theme'); } - public function themeAction(): RedirectResponse + public function attemptSetInstanceTheme(): RedirectResponse { $theme = $this->request->getPost('theme'); service('settings') diff --git a/modules/Admin/Controllers/SoundbiteController.php b/modules/Admin/Controllers/SoundbiteController.php index 2ca68bac..0016de24 100644 --- a/modules/Admin/Controllers/SoundbiteController.php +++ b/modules/Admin/Controllers/SoundbiteController.php @@ -15,89 +15,96 @@ use App\Entities\Episode; use App\Entities\Podcast; use App\Models\ClipModel; use App\Models\EpisodeModel; +use App\Models\MediaModel; use App\Models\PodcastModel; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; -use Modules\Media\Models\MediaModel; class SoundbiteController extends BaseController { + protected Podcast $podcast; + + protected Episode $episode; + public function _remap(string $method, string ...$params): mixed { - if ($params === []) { - throw PageNotFoundException::forPageNotFound(); - } - - if (count($params) === 1) { - if (! ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - return $this->{$method}($podcast); - } - if ( - ! ($episode = new EpisodeModel()->getEpisodeById((int) $params[1])) instanceof Episode + ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) === null ) { throw PageNotFoundException::forPageNotFound(); } - unset($params[0]); - unset($params[1]); + $this->podcast = $podcast; - return $this->{$method}($episode, ...$params); + if (count($params) > 1) { + if ( + ! ($episode = (new EpisodeModel()) + ->where([ + 'id' => $params[1], + 'podcast_id' => $params[0], + ]) + ->first()) + ) { + throw PageNotFoundException::forPageNotFound(); + } + + $this->episode = $episode; + + unset($params[1]); + unset($params[0]); + } + + return $this->{$method}(...$params); } - public function list(Episode $episode): string + public function list(): string { - $soundbitesBuilder = new ClipModel('audio') + $soundbitesBuilder = (new ClipModel('audio')) ->where([ - 'podcast_id' => $episode->podcast_id, - 'episode_id' => $episode->id, - 'type' => 'audio', + 'podcast_id' => $this->podcast->id, + 'episode_id' => $this->episode->id, + 'type' => 'audio', ]) ->orderBy('created_at', 'desc'); $soundbites = $soundbitesBuilder->paginate(10); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, 'soundbites' => $soundbites, - 'pager' => $soundbitesBuilder->pager, + 'pager' => $soundbitesBuilder->pager, ]; - $this->setHtmlHead(lang('Soundbite.list.title')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/soundbites_list', $data); } - public function createView(Episode $episode): string + public function create(): string { helper(['form']); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, ]; - $this->setHtmlHead(lang('Soundbite.form.title')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/soundbites_new', $data); } - public function createAction(Episode $episode): RedirectResponse + public function attemptCreate(): RedirectResponse { $rules = [ - 'title' => 'required', + 'title' => 'required', 'start_time' => 'required|greater_than_equal_to[0]', - 'duration' => 'required|greater_than[0]', + 'duration' => 'required|greater_than[0]', ]; if (! $this->validate($rules)) { @@ -107,16 +114,14 @@ class SoundbiteController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - $newSoundbite = new Soundbite([ - 'title' => $validData['title'], - 'start_time' => (float) $validData['start_time'], - 'duration' => (float) $validData['duration'], - 'type' => 'audio', - 'status' => '', - 'podcast_id' => $episode->podcast_id, - 'episode_id' => $episode->id, + 'title' => $this->request->getPost('title'), + 'start_time' => (float) $this->request->getPost('start_time'), + 'duration' => (float) $this->request->getPost('duration',), + 'type' => 'audio', + 'status' => '', + 'podcast_id' => $this->podcast->id, + 'episode_id' => $this->episode->id, 'created_by' => user_id(), 'updated_by' => user_id(), ]); @@ -129,16 +134,15 @@ class SoundbiteController extends BaseController ->with('errors', $clipModel->errors()); } - return redirect()->route('soundbites-list', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('soundbites-list', [$this->podcast->id, $this->episode->id])->with( 'message', - lang('Soundbite.messages.createSuccess'), + lang('Soundbite.messages.createSuccess') ); } - public function deleteAction(Episode $episode, string $soundbiteId): RedirectResponse + public function delete(string $soundbiteId): RedirectResponse { - $soundbite = new ClipModel() - ->getSoundbiteById((int) $soundbiteId); + $soundbite = (new ClipModel())->getSoundbiteById((int) $soundbiteId); if (! $soundbite instanceof Soundbite) { throw PageNotFoundException::forPageNotFound(); @@ -146,11 +150,9 @@ class SoundbiteController extends BaseController if ($soundbite->media === null) { // delete Clip directly - new ClipModel() - ->deleteSoundbite($episode->podcast_id, $episode->id, $soundbite->id); + (new ClipModel())->deleteSoundbite($this->podcast->id, $this->episode->id, $soundbite->id); } else { - new ClipModel() - ->clearSoundbiteCache($episode->podcast_id, $episode->id, $soundbite->id); + (new ClipModel())->clearSoundbiteCache($this->podcast->id, $this->episode->id, $soundbite->id); $mediaModel = new MediaModel(); // delete the soundbite file, the clip will be deleted on cascade @@ -162,9 +164,9 @@ class SoundbiteController extends BaseController } } - return redirect()->route('soundbites-list', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('soundbites-list', [$this->podcast->id, $this->episode->id])->with( 'message', - lang('Soundbite.messages.deleteSuccess'), + lang('Soundbite.messages.deleteSuccess') ); } } diff --git a/modules/Admin/Controllers/UserController.php b/modules/Admin/Controllers/UserController.php new file mode 100644 index 00000000..3dc70d44 --- /dev/null +++ b/modules/Admin/Controllers/UserController.php @@ -0,0 +1,258 @@ +{$method}(); + } + + if ($this->user = (new UserModel())->find($params[0])) { + return $this->{$method}(); + } + + throw PageNotFoundException::forPageNotFound(); + } + + public function list(): string + { + $data = [ + 'users' => (new UserModel())->findAll(), + ]; + + return view('user/list', $data); + } + + public function view(): string + { + $data = [ + 'user' => $this->user, + ]; + + replace_breadcrumb_params([ + 0 => $this->user->username, + ]); + return view('user/view', $data); + } + + public function create(): string + { + helper('form'); + + $data = [ + 'roles' => (new GroupModel())->getUserRoles(), + ]; + + return view('user/create', $data); + } + + public function attemptCreate(): RedirectResponse + { + $userModel = new UserModel(); + + // Validate here first, since some things, + // like the password, can only be validated properly here. + $rules = array_merge( + $userModel->getValidationRules([ + 'only' => ['username'], + ]), + [ + 'email' => 'required|valid_email|is_unique[users.email]', + 'password' => 'required|strong_password', + ], + ); + + if (! $this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $this->validator->getErrors()); + } + + // Save the user + $user = new User($this->request->getPost()); + + // Activate user + $user->activate(); + + // Force user to reset his password on first connection + $user->forcePasswordReset(); + + if (! $userModel->insert($user)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $userModel->errors()); + } + + // Success! + return redirect() + ->route('user-list') + ->with('message', lang('User.messages.createSuccess', [ + 'username' => $user->username, + ])); + } + + public function edit(): string + { + helper('form'); + + $roles = (new GroupModel())->getUserRoles(); + $roleOptions = array_reduce( + $roles, + static function ($result, $role) { + $result[$role->name] = lang('User.roles.' . $role->name); + return $result; + }, + [], + ); + + $data = [ + 'user' => $this->user, + 'roleOptions' => $roleOptions, + ]; + + replace_breadcrumb_params([ + 0 => $this->user->username, + ]); + return view('user/edit', $data); + } + + public function attemptEdit(): RedirectResponse + { + $authorize = Services::authorization(); + + $roles = $this->request->getPost('roles'); + + if ($this->user->isOwner) { + return redirect() + ->back() + ->with('errors', [ + lang('User.messages.editOwnerError', [ + 'username' => $this->user->username, + ]), + ]); + } + + $authorize->setUserGroups($this->user->id, $roles ?? []); + + // Success! + return redirect() + ->route('user-list') + ->with('message', lang('User.messages.rolesEditSuccess', [ + 'username' => $this->user->username, + ])); + } + + public function forcePassReset(): RedirectResponse + { + $userModel = new UserModel(); + $this->user->forcePasswordReset(); + + if (! $userModel->update($this->user->id, $this->user)) { + return redirect() + ->back() + ->with('errors', $userModel->errors()); + } + + // Success! + return redirect() + ->route('user-list') + ->with( + 'message', + lang('User.messages.forcePassResetSuccess', [ + 'username' => $this->user->username, + ]), + ); + } + + public function ban(): RedirectResponse + { + $authorize = Services::authorization(); + if ($authorize->inGroup('superadmin', $this->user->id)) { + return redirect() + ->back() + ->with('errors', [ + lang('User.messages.banSuperAdminError', [ + 'username' => $this->user->username, + ]), + ]); + } + + $userModel = new UserModel(); + // TODO: add ban reason? + $this->user->ban(''); + + if (! $userModel->update($this->user->id, $this->user)) { + return redirect() + ->back() + ->with('errors', $userModel->errors()); + } + + return redirect() + ->route('user-list') + ->with('message', lang('User.messages.banSuccess', [ + 'username' => $this->user->username, + ])); + } + + public function unBan(): RedirectResponse + { + $userModel = new UserModel(); + $this->user->unBan(); + + if (! $userModel->update($this->user->id, $this->user)) { + return redirect() + ->back() + ->with('errors', $userModel->errors()); + } + + return redirect() + ->route('user-list') + ->with('message', lang('User.messages.unbanSuccess', [ + 'username' => $this->user->username, + ])); + } + + public function delete(): RedirectResponse + { + $authorize = Services::authorization(); + if ($authorize->inGroup('superadmin', $this->user->id)) { + return redirect() + ->back() + ->with('errors', [ + lang('User.messages.deleteSuperAdminError', [ + 'username' => $this->user->username, + ]), + ]); + } + + (new UserModel())->delete($this->user->id); + + return redirect() + ->back() + ->with('message', lang('User.messages.deleteSuccess', [ + 'username' => $this->user->username, + ])); + } +} diff --git a/modules/Admin/Controllers/VideoClipsController.php b/modules/Admin/Controllers/VideoClipsController.php index b91305ca..49878800 100644 --- a/modules/Admin/Controllers/VideoClipsController.php +++ b/modules/Admin/Controllers/VideoClipsController.php @@ -10,57 +10,63 @@ declare(strict_types=1); namespace Modules\Admin\Controllers; -use App\Entities\Clip\BaseClip; use App\Entities\Clip\VideoClip; use App\Entities\Episode; use App\Entities\Podcast; use App\Models\ClipModel; use App\Models\EpisodeModel; +use App\Models\MediaModel; use App\Models\PodcastModel; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; -use Modules\Media\Entities\Transcript; -use Modules\Media\Models\MediaModel; class VideoClipsController extends BaseController { + protected Podcast $podcast; + + protected Episode $episode; + public function _remap(string $method, string ...$params): mixed { - if ($params === []) { - throw PageNotFoundException::forPageNotFound(); - } - - if (count($params) === 1) { - if (! ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - return $this->{$method}($podcast); - } - if ( - ! ($episode = new EpisodeModel()->getEpisodeById((int) $params[1])) instanceof Episode + ($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) === null ) { throw PageNotFoundException::forPageNotFound(); } - unset($params[0]); - unset($params[1]); + $this->podcast = $podcast; - return $this->{$method}($episode, ...$params); + if (count($params) > 1) { + if ( + ! ($episode = (new EpisodeModel()) + ->where([ + 'id' => $params[1], + 'podcast_id' => $params[0], + ]) + ->first()) + ) { + throw PageNotFoundException::forPageNotFound(); + } + + $this->episode = $episode; + + unset($params[1]); + unset($params[0]); + } + + return $this->{$method}(...$params); } - public function list(Episode $episode): string + public function list(): string { - $videoClipsBuilder = new ClipModel('video') + $videoClipsBuilder = (new ClipModel('video')) ->where([ - 'podcast_id' => $episode->podcast_id, - 'episode_id' => $episode->id, - 'type' => 'video', + 'podcast_id' => $this->podcast->id, + 'episode_id' => $this->episode->id, + 'type' => 'video', ]) ->orderBy('created_at', 'desc'); - /** @var BaseClip[] $clips */ $clips = $videoClipsBuilder->paginate(10); $videoClips = []; @@ -69,67 +75,61 @@ class VideoClipsController extends BaseController } $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, 'videoClips' => $videoClips, - 'pager' => $videoClipsBuilder->pager, + 'pager' => $videoClipsBuilder->pager, ]; - $this->setHtmlHead(lang('VideoClip.list.title')); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); return view('episode/video_clips_list', $data); } - public function view(Episode $episode, string $videoClipId): string + public function view($videoClipId): string { - $videoClip = new ClipModel() - ->getVideoClipById((int) $videoClipId); + $videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId); $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, 'videoClip' => $videoClip, ]; - $this->setHtmlHead(lang('VideoClip.title', [ - 'videoClipLabel' => esc($videoClip->title), - ])); replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, 2 => $videoClip->title, ]); return view('episode/video_clip', $data); } - public function createView(Episode $episode): string + public function create(): string { $data = [ - 'podcast' => $episode->podcast, - 'episode' => $episode, + 'podcast' => $this->podcast, + 'episode' => $this->episode, ]; replace_breadcrumb_params([ - 0 => $episode->podcast->at_handle, - 1 => $episode->title, + 0 => $this->podcast->title, + 1 => $this->episode->title, ]); // First, check that requirements to create a video clip are met $ffmpeg = shell_exec('which ffmpeg'); $checks = [ - 'ffmpeg' => $ffmpeg !== null, - 'gd' => extension_loaded('gd'), - 'freetype' => extension_loaded('gd') && gd_info()['FreeType Support'], - 'transcript' => $episode->transcript instanceof Transcript, + 'ffmpeg' => $ffmpeg !== null, + 'gd' => extension_loaded('gd'), + 'freetype' => extension_loaded('gd') && gd_info()['FreeType Support'], + 'transcript' => $this->episode->transcript !== null, ]; - $this->setHtmlHead(lang('VideoClip.form.title')); - - if (array_any($checks, fn (bool $value): bool => ! $value)) { + if (in_array(false, $checks, true)) { $data['checks'] = $checks; + return view('episode/video_clips_requirements', $data); } @@ -137,14 +137,14 @@ class VideoClipsController extends BaseController return view('episode/video_clips_new', $data); } - public function createAction(Episode $episode): RedirectResponse + public function attemptCreate(): RedirectResponse { $rules = [ - 'title' => 'required', + 'title' => 'required', 'start_time' => 'required|greater_than_equal_to[0]', - 'duration' => 'required|greater_than[0]', - 'format' => 'required|in_list[' . implode(',', array_keys(config('MediaClipper')->formats)) . ']', - 'theme' => 'required|in_list[' . implode(',', array_keys(config('Colors')->themes)) . ']', + 'duration' => 'required|greater_than[0]', + 'format' => 'required|in_list[' . implode(',', array_keys(config('MediaClipper')->formats)) . ']', + 'theme' => 'required|in_list[' . implode(',', array_keys(config('Colors')->themes)) . ']', ]; if (! $this->validate($rules)) { @@ -154,32 +154,30 @@ class VideoClipsController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - $themeName = $validData['theme']; + $themeName = $this->request->getPost('theme'); $themeColors = config('MediaClipper') ->themes[$themeName]; $theme = [ - 'name' => $themeName, + 'name' => $themeName, 'preview' => $themeColors['preview'], ]; $videoClip = new VideoClip([ - 'title' => $validData['title'], - 'start_time' => (float) $validData['start_time'], - 'duration' => (float) $validData['duration'], - 'theme' => $theme, - 'format' => $validData['format'], - 'type' => 'video', - 'status' => 'queued', - 'podcast_id' => $episode->podcast_id, - 'episode_id' => $episode->id, + 'title' => $this->request->getPost('title'), + 'start_time' => (float) $this->request->getPost('start_time'), + 'duration' => (float) $this->request->getPost('duration',), + 'theme' => $theme, + 'format' => $this->request->getPost('format'), + 'type' => 'video', + 'status' => 'queued', + 'podcast_id' => $this->podcast->id, + 'episode_id' => $this->episode->id, 'created_by' => user_id(), 'updated_by' => user_id(), ]); // Check if video clip exists before inserting a new line - if (new ClipModel()->doesVideoClipExist($videoClip)) { + if ((new ClipModel())->doesVideoClipExist($videoClip)) { // video clip already exists return redirect() ->back() @@ -187,38 +185,34 @@ class VideoClipsController extends BaseController ->with('error', lang('VideoClip.messages.alreadyExistingError')); } - new ClipModel() - ->insert($videoClip); + (new ClipModel())->insert($videoClip); - return redirect()->route('video-clips-list', [$episode->podcast_id, $episode->id])->with( + return redirect()->route('video-clips-list', [$this->podcast->id, $this->episode->id])->with( 'message', - lang('VideoClip.messages.addToQueueSuccess'), + lang('VideoClip.messages.addToQueueSuccess') ); } - public function retryAction(Episode $episode, string $videoClipId): RedirectResponse + public function retry(string $videoClipId): RedirectResponse { - $videoClip = new ClipModel() - ->getVideoClipById((int) $videoClipId); + $videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId); if (! $videoClip instanceof VideoClip) { throw PageNotFoundException::forPageNotFound(); } - new ClipModel() - ->update($videoClip->id, [ - 'status' => 'queued', - 'job_started_at' => null, - 'job_ended_at' => null, - ]); + (new ClipModel())->update($videoClip->id, [ + 'status' => 'queued', + 'job_started_at' => null, + 'job_ended_at' => null, + ]); return redirect()->back(); } - public function deleteAction(Episode $episode, string $videoClipId): RedirectResponse + public function delete(string $videoClipId): RedirectResponse { - $videoClip = new ClipModel() - ->getVideoClipById((int) $videoClipId); + $videoClip = (new ClipModel())->getVideoClipById((int) $videoClipId); if (! $videoClip instanceof VideoClip) { throw PageNotFoundException::forPageNotFound(); @@ -226,11 +220,9 @@ class VideoClipsController extends BaseController if ($videoClip->media === null) { // delete Clip directly - new ClipModel() - ->deleteVideoClip($videoClip->id); + (new ClipModel())->deleteVideoClip($this->podcast->id, $this->episode->id, $videoClip->id); } else { - new ClipModel() - ->clearVideoClipCache($videoClip->id); + (new ClipModel())->clearVideoClipCache($videoClip->id); $mediaModel = new MediaModel(); // delete the videoClip file, the clip will be deleted on cascade diff --git a/modules/Admin/Language/.rsync-filter b/modules/Admin/Language/.rsync-filter index b802a93d..2a742b26 100644 --- a/modules/Admin/Language/.rsync-filter +++ b/modules/Admin/Language/.rsync-filter @@ -2,11 +2,9 @@ + fr/*** + pl/*** + de/*** -+ pt-br/*** -+ nn-no/*** ++ pt-BR/*** ++ nn-NO/*** + es/*** -+ zh-hans/*** ++ zh-Hans/*** + ca/*** -+ br/*** -+ sr-latn/*** - ** diff --git a/modules/Admin/Language/ar/AboutCastopod.php b/modules/Admin/Language/ar/AboutCastopod.php deleted file mode 100644 index f5bc662b..00000000 --- a/modules/Admin/Language/ar/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'حول كاستوبود', - 'host_name' => 'إسم المضيف', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'نظام التشغيل', - 'languages' => 'اللغات', - 'update_database' => 'تحديث قاعدة البيانات', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/ar/Breadcrumb.php b/modules/Admin/Language/ar/Breadcrumb.php index 251d9788..0156d943 100644 --- a/modules/Admin/Language/ar/Breadcrumb.php +++ b/modules/Admin/Language/ar/Breadcrumb.php @@ -19,7 +19,6 @@ return [ 'pages' => 'صفحات', 'settings' => 'الإعدادات', 'theme' => 'الحلة', - 'about' => 'about', 'add' => 'إضافة', 'new' => 'جديد', 'edit' => 'تعديل', @@ -29,19 +28,15 @@ return [ 'publish-date-edit' => 'edit publication date', 'unpublish' => 'unpublish', 'delete' => 'احذف', - 'remove' => 'remove', 'fediverse' => 'الفديفرس', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'قوائم حجب', 'users' => 'مستخدمون', 'my-account' => 'حسابي', 'change-password' => 'تغيير الكلمة السرية', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'feed import', 'platforms' => 'منصات', 'social' => 'شبكات التواصل الاجتماعي', 'funding' => 'funding', - 'monetization-other' => 'other monetization', 'analytics' => 'analytics', 'locations' => 'locations', 'webpages' => 'صفحات ويب', diff --git a/modules/Admin/Language/ar/Charts.php b/modules/Admin/Language/ar/Charts.php index 525085f0..4f0e8556 100644 --- a/modules/Admin/Language/ar/Charts.php +++ b/modules/Admin/Language/ar/Charts.php @@ -9,7 +9,7 @@ declare(strict_types=1); */ return [ - 'by_service_weekly' => 'تنزيلات الحلقة حسب الخدمة (للأسبوع الماضي)', + 'by_service_weekly' => 'Episode downloads by service (for the past week)', 'by_player_weekly' => 'Episode downloads by player (for the past week)', 'by_player_yearly' => 'Episode downloads by player (for the past year)', 'by_device_weekly' => 'Episode downloads by device (for the past week)', @@ -24,7 +24,7 @@ return [ 'episode_by_month' => 'Episode monthly downloads', 'episodes_by_day' => '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'تنزيلات الحلقة حسب البلد (في الأسبوع الماضي)', + 'by_country_weekly' => 'Episode downloads by country (for the past week)', 'by_country_yearly' => 'Episode downloads by country (for the past year)', 'by_domain_weekly' => 'Web pages visits by source (for the past week)', 'by_domain_yearly' => 'Web pages visits by source (for the past year)', @@ -35,7 +35,6 @@ return [ 'by_weekday' => 'By week day (for the past 60 days)', 'by_hour' => 'By time of day (for the past 60 days)', 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'التخزين الشهري (بالميغابايت)', + 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/ar/Common.php b/modules/Admin/Language/ar/Common.php index fc39a83b..9dff13c6 100644 --- a/modules/Admin/Language/ar/Common.php +++ b/modules/Admin/Language/ar/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'إرسال ملف', 'remote_url' => 'Remote URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'تشغيل', diff --git a/modules/Auth/Language/ar/Contributor.php b/modules/Admin/Language/ar/Contributor.php similarity index 72% rename from modules/Auth/Language/ar/Contributor.php rename to modules/Admin/Language/ar/Contributor.php index 4731c799..92ddf0b8 100644 --- a/modules/Auth/Language/ar/Contributor.php +++ b/modules/Admin/Language/ar/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'إضافة مساهم', 'submit_edit' => 'حدّث الدور', ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', + 'roles' => [ + 'podcast_admin' => 'Podcast admin', ], 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", 'removeOwnerError' => "لا يمكنك إزالة صاحب البودكاست!", 'removeSuccess' => 'You have successfully removed {username} from {podcastTitle}', diff --git a/modules/Admin/Language/ar/Episode.php b/modules/Admin/Language/ar/Episode.php index 1a1cdeeb..99eed5ba 100644 --- a/modules/Admin/Language/ar/Episode.php +++ b/modules/Admin/Language/ar/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'كافة حلقات البودكاست', 'back_to_podcast' => 'العودة إلى البودكاست', 'edit' => 'تعديل', - 'preview' => 'Preview', 'publish' => 'نشر', 'publish_edit' => 'تعديل المنشور', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'الحلقة', 'visibility' => 'الظهور', - 'downloads' => 'Downloads', 'comments' => 'التعليقات', 'actions' => 'الإجراءات', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'الفصول', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/ar/MyAccount.php b/modules/Admin/Language/ar/MyAccount.php similarity index 100% rename from modules/Auth/Language/ar/MyAccount.php rename to modules/Admin/Language/ar/MyAccount.php diff --git a/modules/Admin/Language/ar/Navigation.php b/modules/Admin/Language/ar/Navigation.php index 6a8bd0fa..f264138a 100644 --- a/modules/Admin/Language/ar/Navigation.php +++ b/modules/Admin/Language/ar/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'الانتقال إلى موقع الويب', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'لوحة التحكم', 'admin' => 'الرئيسية', 'podcasts' => 'البودكاستات', 'podcast-list' => 'كافة البودكاستات', 'podcast-create' => 'بودكاست جديد', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'استيراد بودكاست', 'persons' => 'أشخاص', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -35,7 +33,6 @@ return [ 'settings' => 'الإعدادات', 'settings-general' => 'العامة', 'settings-theme' => 'الحلة', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'حسابي', 'change-password' => 'تغيير الكلمة السرية', diff --git a/modules/Admin/Language/ar/Notifications.php b/modules/Admin/Language/ar/Notifications.php index 8e86a2b3..2b139d51 100644 --- a/modules/Admin/Language/ar/Notifications.php +++ b/modules/Admin/Language/ar/Notifications.php @@ -9,11 +9,11 @@ declare(strict_types=1); */ return [ - 'title' => 'الإشعارات', + 'title' => 'Notifications', 'reply' => '{actor_username} replied to your post', 'favourite' => '{actor_username} favourited your post', 'reblog' => '{actor_username} shared your post', 'follow' => '{actor_username} started following you', - 'no_notifications' => 'لا توجد إشعارات', + 'no_notifications' => 'No notifications', 'mark_all_as_read' => 'Mark all as read', ]; diff --git a/modules/Admin/Language/ar/Page.php b/modules/Admin/Language/ar/Page.php index 31dde5a1..d4145ddc 100644 --- a/modules/Admin/Language/ar/Page.php +++ b/modules/Admin/Language/ar/Page.php @@ -24,7 +24,7 @@ return [ 'submit_edit' => 'حفظ', ], 'messages' => [ - 'createSuccess' => 'تم إنشاء الصفحة "{pageTitle}" بنجاح!', + 'createSuccess' => 'The page “{pageTitle}” was created successfully!', 'editSuccess' => 'تم تحديث الصفحة بنجاح!', ], ]; diff --git a/modules/Admin/Language/ar/Platforms.php b/modules/Admin/Language/ar/Platforms.php index 7c01243d..5b17c098 100644 --- a/modules/Admin/Language/ar/Platforms.php +++ b/modules/Admin/Language/ar/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'المنصات', 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', 'remove' => 'Remove {platformName}', diff --git a/modules/Admin/Language/ar/Podcast.php b/modules/Admin/Language/ar/Podcast.php index 08ebcdd4..bcd6f9dd 100644 --- a/modules/Admin/Language/ar/Podcast.php +++ b/modules/Admin/Language/ar/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No podcast found!', 'create' => 'إنشاء بودكاست', 'import' => 'استيراد بودكاست', - 'all_imports' => 'Podcast imports', 'new_episode' => 'حلقة جديدة', 'view' => 'View podcast', 'edit' => 'Edit podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Delete podcast', 'see_episodes' => 'See episodes', 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'الانتقال إلى الصفحة', 'latest_episodes' => 'أحدث الحلقات', 'see_all_episodes' => 'See all episodes', @@ -50,6 +48,7 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], 'description' => 'الوصف', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/ar/PodcastImport.php b/modules/Admin/Language/ar/PodcastImport.php new file mode 100644 index 00000000..cccbaa65 --- /dev/null +++ b/modules/Admin/Language/ar/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'رقم الموسم', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/ar/PodcastNavigation.php b/modules/Admin/Language/ar/PodcastNavigation.php index b82f78d9..ad114d10 100644 --- a/modules/Admin/Language/ar/PodcastNavigation.php +++ b/modules/Admin/Language/ar/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'انتقل إلى صفحة البودكاست', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'الرئيسية', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'الحلقات', 'episode-list' => 'جميع الحلقات', 'episode-create' => 'حلقة جديدة', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'المساهمون', 'contributor-list' => 'كل المساهمين', 'contributor-add' => 'إضافة مساهم', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Auth/Language/ar/User.php b/modules/Admin/Language/ar/User.php similarity index 75% rename from modules/Auth/Language/ar/User.php rename to modules/Admin/Language/ar/User.php index 39f78c2e..f2a33409 100644 --- a/modules/Auth/Language/ar/User.php +++ b/modules/Admin/Language/ar/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Edit {username}'s role", + 'edit_roles' => "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', 'ban' => 'Ban', 'unban' => 'Unban', 'delete' => 'احذف', @@ -18,7 +19,7 @@ return [ 'all_users' => 'كافة المستخدمين', 'list' => [ 'user' => 'مستخدم', - 'role' => 'Role', + 'roles' => 'الأدوار', 'banned' => 'Banned?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'اسم المستخدم', 'password' => 'كلمة المرور', 'new_password' => 'كلمة المرور الجديدة', - 'role' => 'Role', 'roles' => 'الأدوار', 'permissions' => 'Permissions', 'submit_create' => 'Create user', 'submit_edit' => 'حفظ', 'submit_password_change' => 'Change!', ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', + 'roles' => [ + 'superadmin' => 'Super admin', ], 'messages' => [ 'createSuccess' => 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', 'banSuccess' => '{username} has been banned.', 'unbanSuccess' => '{username} has been unbanned.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', 'deleteSuperAdminError' => '{username} is a superadmin, one does not simply delete a superadmin…', 'deleteSuccess' => '{username} has been deleted.', diff --git a/modules/Admin/Language/ar/Validation.php b/modules/Admin/Language/ar/Validation.php index f76c3163..750b1968 100644 --- a/modules/Admin/Language/ar/Validation.php +++ b/modules/Admin/Language/ar/Validation.php @@ -13,5 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/br/AboutCastopod.php b/modules/Admin/Language/br/AboutCastopod.php deleted file mode 100644 index d0f56d6b..00000000 --- a/modules/Admin/Language/br/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Diwar-benn Castopod', - 'host_name' => 'Anv an ostiz', - 'version' => 'Stumm Castopod', - 'php_version' => 'Stumm PHP', - 'os' => 'Sistem oberiañ', - 'languages' => 'Yezhoù', - 'update_database' => 'Nevesaat an diaz roadennoù', - 'messages' => [ - 'databaseUpdateSuccess' => 'Nevesaet eo an diaz roadennoù!', - ], -]; diff --git a/modules/Admin/Language/br/Breadcrumb.php b/modules/Admin/Language/br/Breadcrumb.php index 65d62836..c2eb298a 100644 --- a/modules/Admin/Language/br/Breadcrumb.php +++ b/modules/Admin/Language/br/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Degemer', 'podcasts' => 'podkastoù', 'episodes' => 'rannoù', - 'subscriptions' => 'koumanantoù', + 'subscriptions' => 'subscriptions', 'contributors' => 'perzhidi, perzhiadezed', 'pages' => 'pajennoù', 'settings' => 'arventennoù', 'theme' => 'neuz', - 'about' => 'a-zivout', 'add' => 'ouzhpennañ', 'new' => 'krouiñ', 'edit' => 'kemmañ', 'persons' => 'emellerien·ezed', 'publish' => 'embann', 'publish-edit' => 'kemmañ an embannadur', - 'publish-date-edit' => 'kemmañ deiziad an embannadur', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'diembannañ', 'delete' => 'dilemel', - 'remove' => 'lemel', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'aktourien·ezed stanket', - 'blocked-domains' => 'domanioù stanket', + 'fediverse' => 'kevrebed', + 'block-lists' => 'roll ar re stanket', 'users' => 'implijerien·ezed', 'my-account' => 'ma c\'hont', 'change-password' => 'kemmañ ar ger-tremen', - 'imports' => 'enporzhiadennoù', - 'sync-feeds' => 'sinkronekaat ar gwazhoù', + 'import' => 'enporzhiañ ul lanv', 'platforms' => 'savennoù', 'social' => 'rouedadoù sokial', 'funding' => 'arc\'hantaouiñ', - 'monetization-other' => 'doare arc\'hantaouiñ all', 'analytics' => 'muzulioù heklev', 'locations' => 'lec\'hioù', 'webpages' => 'pajennoù web', @@ -50,8 +45,8 @@ return [ 'listening-time' => 'padelezh ar selaou', 'time-periods' => 'mareoù ar selaou', 'soundbites' => 'tennadoù son', - 'video-clips' => 'klipoù video', + 'video-clips' => 'tennadoù video', 'embed' => 'lenner enkorfet', - 'notifications' => 'kemennoù', - 'suspend' => 'ehanañ', + 'notifications' => 'notifications', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/br/Charts.php b/modules/Admin/Language/br/Charts.php index 687ea057..7de3c6ac 100644 --- a/modules/Admin/Language/br/Charts.php +++ b/modules/Admin/Language/br/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Lec\'hed bann implijet bemdez (e MB)', 'total_storage_by_month' => 'Kadaviñ bep miz (e MB)', 'total_bandwidth_by_month' => 'Lec\'hed bann implijet bep miz (e MB)', - 'total_bandwidth_by_month_limit' => 'Bevennet da {totalBandwidth} bep miz', ]; diff --git a/modules/Admin/Language/br/Common.php b/modules/Admin/Language/br/Common.php index 40491496..1cb6c3b2 100644 --- a/modules/Admin/Language/br/Common.php +++ b/modules/Admin/Language/br/Common.php @@ -14,7 +14,7 @@ return [ 'cancel' => 'Nullañ', 'optional' => 'Diret', 'more' => 'Muioc\'h', - 'no_data' => 'Roadenn ebet kavet !', + 'no_data' => 'Roadenn ebet kavet!', 'close' => 'Serriñ', 'edit' => 'Kemmañ', 'copy' => 'Eilañ', @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Uskargit ur restr', 'remote_url' => 'URL a-bell', - 'save' => 'Enrollañ', ], 'play_episode_button' => [ 'play' => 'Lenn', diff --git a/modules/Auth/Language/br/Contributor.php b/modules/Admin/Language/br/Contributor.php similarity index 67% rename from modules/Auth/Language/br/Contributor.php rename to modules/Admin/Language/br/Contributor.php index bffc79e0..637fe9f1 100644 --- a/modules/Auth/Language/br/Contributor.php +++ b/modules/Admin/Language/br/Contributor.php @@ -13,7 +13,7 @@ return [ 'view' => "Perzh {username} e {podcastTitle}", 'add' => 'Ouzhpennañ ur perzhiad pe ur berzhiadez', 'add_contributor' => 'Ouzhpennañ ur perzhiad pe ur berzhiadez da {0}', - 'edit_role' => 'Nevesaat roll {0}', + 'edit_role' => 'Hizivaat roll {0}', 'edit' => 'Kemmañ', 'remove' => 'Lemel', 'list' => [ @@ -26,18 +26,12 @@ return [ 'role' => 'Roll', 'role_placeholder' => 'Dibabit e·he roll…', 'submit_add' => 'Ouzhpennañ ur perzhiad pe ur berzhiadez', - 'submit_edit' => 'Nevesaat ar roll', + 'submit_edit' => 'Hizivaat ar roll', ], - 'delete_form' => [ - 'title' => 'Dilemel {contributor}', - 'disclaimer' => - 'Emaoc\'h o vont da lemel {contributor} eus ar berzhidi/perzhiadezed. Ne c\'hallo ket gwelet "{podcastTitle}" ken.', - 'understand' => 'Komprenet em eus. Fellout a ra din lemel {contributor} eus "{podcastTitle}"', - 'submit' => 'Lemel', + 'roles' => [ + 'podcast_admin' => 'Merour podkastoù', ], 'messages' => [ - 'editSuccess' => 'Cheñchet eo bet ar roll gant berzh!', - 'editOwnerError' => "Ne c'hellit ket kemmañ perc'henn·ez ar podkast!", 'removeOwnerError' => "Ne c'hellit ket lemel perc'henn ar podkast!", 'removeSuccess' => 'Lamet ho peus {username} diouzh {podcastTitle} gant berzh', diff --git a/modules/Admin/Language/br/Countries.php b/modules/Admin/Language/br/Countries.php index 229abb0d..2187df89 100644 --- a/modules/Admin/Language/br/Countries.php +++ b/modules/Admin/Language/br/Countries.php @@ -116,7 +116,7 @@ return [ 'IL' => 'Israel', 'IM' => 'Enez-Vanav', 'IN' => 'Indez', - 'IO' => 'Tiriad Meurvor Indez Breizh-Veur', + 'IO' => 'British Indian Ocean Territory', 'IQ' => 'Irak', 'IR' => 'Iran', 'IS' => 'Island', @@ -136,7 +136,7 @@ return [ 'KW' => 'Kowait', 'KY' => 'Cayman, Inizi', 'KZ' => 'Kazakstan', - 'LA' => "Bro-Laos", + 'LA' => "Lao People's Democratic Republic", 'LB' => 'Liban', 'LC' => 'Santez-Lusia', 'LI' => 'Liechtenstein', @@ -210,7 +210,7 @@ return [ 'SD' => 'Soudan', 'SE' => 'Sveden', 'SG' => 'Singapoura', - 'SH' => 'Saint Helena, Ascension ha Tristan da Cunha', + 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', 'SI' => 'Sloveni', 'SJ' => 'Svalbard ha Jan Mayen', 'SK' => 'Slovaki', @@ -243,7 +243,7 @@ return [ 'TZ' => 'Tanzania, Republik Unanet', 'UA' => 'Ukraina', 'UG' => 'Ouganda', - 'UM' => 'Inizi bihan diabell ar Stadoù-Unanet', + 'UM' => 'United States Minor Outlying Islands', 'US' => 'Stadoù-Unanet', 'UY' => 'Uruguay', 'UZ' => 'Uzbekistan', diff --git a/modules/Admin/Language/br/Dashboard.php b/modules/Admin/Language/br/Dashboard.php index 255e0aca..881073fd 100644 --- a/modules/Admin/Language/br/Dashboard.php +++ b/modules/Admin/Language/br/Dashboard.php @@ -9,20 +9,20 @@ declare(strict_types=1); */ return [ - 'home' => 'Taolenn-stur', - 'welcome_message' => 'Degemer mat en daolenn-stur!', + 'home' => 'Admin dashboard', + 'welcome_message' => 'Welcome to the admin area!', 'podcasts' => [ - 'title' => 'Podkastoù', - 'not_found' => 'Podkast embannet ebet', - 'last_published' => 'Embannet da ziwezhañ d\'an/ar {lastPublicationDate}', + 'title' => 'Podcasts', + 'not_found' => 'No published podcast', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'episodes' => [ - 'title' => 'Rannoù', - 'not_found' => 'Rann embannet ebet', - 'last_published' => 'Embannet da ziwezhañ d\'an/ar {lastPublicationDate}', + 'title' => 'Episodes', + 'not_found' => 'No published episode', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'storage' => [ - 'title' => 'Stokañ', - 'subtitle' => '{totalUploaded} war {totalStorage}', + 'title' => 'Storage', + 'subtitle' => '{totalUploaded} out of {totalStorage}', ], ]; diff --git a/modules/Admin/Language/br/Episode.php b/modules/Admin/Language/br/Episode.php index 7f73831b..56e1c93d 100644 --- a/modules/Admin/Language/br/Episode.php +++ b/modules/Admin/Language/br/Episode.php @@ -23,17 +23,16 @@ return [ 'all_podcast_episodes' => 'Holl rannoù ar podkast', 'back_to_podcast' => 'Mont d\'ar podkast en-dro', 'edit' => 'Kemmañ', - 'preview' => 'Rakwel', 'publish' => 'Embann', 'publish_edit' => 'Kemmañ an embannadur', - 'publish_date_edit' => 'Kemmañ deiziad an embannadur', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Diembannañ', 'publish_error' => 'Embannet eo bet ar rann dija.', 'publish_edit_error' => 'Embannet eo bet ar rann dija.', 'publish_cancel_error' => 'Embannet eo bet ar rann dija.', - 'publish_date_edit_error' => 'N\'eo ket bet embannet ar podkast c\'hoazh, ne c\'hallit ket kemmañ an deiziad an embann.', - 'publish_date_edit_future_error' => 'Rankout a ra deiziad embannadur ar rann bezañ en amzer dremenet! M\'ho peus c\'hoant da steuñviñ an embannadur en amzer da zont e rankit diembann ar rann da gentañ.', - 'publish_date_edit_success' => 'Cheñchet eo bet deiziad embannadur ar rann gant berzh!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'N\'eo ket bet embannet ar rann.', 'delete' => 'Dilemel', 'go_to_page' => 'Gwelet ar bajenn', @@ -58,16 +57,15 @@ return [ }', 'episode' => 'Rann', 'visibility' => 'Gwelusted', - 'downloads' => 'Pellgargadennoù', 'comments' => 'Evezhiadennoù', 'actions' => 'Obererezhioù', ], 'messages' => [ 'createSuccess' => 'Krouet eo bet ar rann gant berzh!', - 'editSuccess' => 'Nevesaet eo bet ar rann gant berzh!', + 'editSuccess' => 'Hizivaet eo bet ar rann gant berzh!', 'publishSuccess' => '{publication_status, select, - published {Embannet eo bet ar rann gant berzh !} - scheduled {Raktreset eo bet embannadur ar rann gant berzh !} + published {Embannet eo bet ar rann gant berzh!} + scheduled {Raktreset eo bet embannadur ar rann gant berzh!} with_podcast {Ar rann-mañ a vo embannet war un dro gant ar podkast.} other {N\'eo ket bet embannet ar rann-mañ.} }', @@ -89,7 +87,7 @@ return [ image {ar golo} audio {an aodio} other {ar media} - } {file_key}. Gallout a rit lemel kuit ar restr-mañ diouzh ar gantenn dre zorn.', + } ({file_path}). Gallout a rit lemel kuit ar restr-mañ diouzh ar gantenn dre zorn.', 'sameSlugError' => 'Bez ez eus eus ur rann gant ar berradur-mañ (slug) dija.', ], 'form' => [ @@ -118,7 +116,7 @@ return [ 'bonus_hint' => 'Danvez ouzhpenn ar podkast (da skouer, titouroù diwar-benn kostezioù pe atersadennoù gant an aktourien·ezed), pe bruderezh kroaziet evit ur podkast all', ], 'premium_title' => 'Premium', - 'premium' => 'Ne vo gwelet ar rann nemet gant koumananterien·ezed Premium', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Kemenn evit ar gerent', 'hint' => 'Hag ar rann-mañ a zo danvez ha ne zlefe ket gwelet gant bugale?', @@ -141,9 +139,9 @@ return [ 'location_name' => 'Anv pe chomlec\'h al lec\'h', 'location_name_hint' => 'Al lec\'h-mañ a c\'hell bezañ unan gwir pe unan faltaziet', 'transcript' => 'Treuzskrivadur (istitloù)', - 'transcript_hint' => 'Aotreet e vez nemet .srt pe .vtt.', + 'transcript_hint' => 'Aotreet e vez nemet .srt.', 'transcript_download' => 'Pellgargañ an treuzskrivadur', - 'transcript_file' => 'Restr an treuzskrivadur (.srt pe .vtt)', + 'transcript_file' => 'Restr an treuzskrivadur (.srt)', 'transcript_remote_url' => 'URL a-bell evit restr an treuzskrivadur', 'transcript_file_delete' => 'Dilemel restr an treuzskrivadur', 'chapters' => 'Chabistroù', @@ -167,7 +165,7 @@ return [ 'back_to_episode_dashboard' => 'Distreiñ da daolenn-stur ar rann', 'post' => 'Ho kemennadenn vrudañ', 'post_hint' => - "Skrivit ur gemennadenn evit brudañ embannadur ho rann. Skignet e vo ar gemennadenn-se d'an holl re a heuilh ac'hanoc'h war ar Fediverse ha lakaet e vo war well war pajenn ho podkast.", + "Skrivit ur gemennadenn evit brudañ embannadur ho rann. Skignet e vo ar gemennadenn-se d'an holl re a heuilh ac'hanoc'h war ar c'hevrebed (fediverse) ha lakaet e vo war well war pajenn ho podkast.", 'message_placeholder' => 'Skrivit ho kemennadenn…', 'publication_date' => 'Deiziad embannadur', 'publication_method' => [ @@ -180,26 +178,26 @@ return [ 'scheduled_publication_date_hint' => 'Gallout a rit steuñviñ embannadur ar rann en ur steuñviñ embannadur ar rann en dazont. Dleout a ra ar vaezienn bezañ er furmad YYYY-MM-DD HH:mm', 'submit' => 'Embann', - 'submit_edit' => 'Kemmañ an embann', + 'submit_edit' => 'Kemmañ an embannadur', 'cancel_publication' => 'Nullañ an embannadur', 'message_warning' => 'N\'ho peus ket skrivet ur gemennadenn evit brudañ ho rann!', 'message_warning_hint' => 'Ouzhpennañ ur gemennadenn a lakay muioc\'h a dud er jeu, ha diwar se e vo gwelet muioc\'h ho rann.', 'message_warning_submit' => 'Embann memestra', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Deiziad embannadur nevez', - 'new_publication_date_hint' => 'An dra-se a rank bezañ un deiziad tremenet.', - 'submit' => 'Kemmañ deiziad an embann', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "Diembann ar rann a zilamo an holl gemennadennoù liammet outi ha skarzhet e vo eus gwazh RSS ar podkast.", + "Diembann ar rann a zilamo an holl gemennadennoù liammet outi ha skarzhet e vo eus lanv RSS ar podkast.", 'understand' => 'Komprennet eo, diembann ar rann a fell din', 'submit' => 'Diembann', ], 'delete_form' => [ 'disclaimer' => - "Gant ar rann e vo dilamet an holl restroù media, evezhiadennoù, klipoù video ha son liammet outi.", + "Gant ar rann e vo dilamet an holl restroù media, evezhiadennoù, tennadoù video ha son liammet outi.", 'understand' => 'Komprennet eo, dilemel ar rann a fell din', 'submit' => 'Dilemel', ], @@ -214,14 +212,4 @@ return [ 'light' => 'Sklaer', 'light-transparent' => 'Sklaer treuzwelus', ], - 'publication_status_banner' => [ - 'draft_mode' => 'mod brouilhed', - 'text' => '{publication_status, select, - published {N\'eo ket bet embannet ar rann-mañ c\'hoazh.} - scheduled {Raktreset eo an embann a-benn an/ar {publication_date}.} - with_podcast {Ar rann-mañ a vo embannet war un dro gant ar podkast.} - other {N\'eo ket bet embannet ar rann-mañ c\'hoazh.} - }', - 'preview' => 'Rakwel', - ], ]; diff --git a/modules/Admin/Language/br/EpisodeNavigation.php b/modules/Admin/Language/br/EpisodeNavigation.php index 7f4c0afc..214e2aca 100644 --- a/modules/Admin/Language/br/EpisodeNavigation.php +++ b/modules/Admin/Language/br/EpisodeNavigation.php @@ -15,9 +15,9 @@ return [ 'episode-edit' => 'Kemm ar rann', 'episode-persons-manage' => 'Merañ an emellerien·ezed', 'embed-add' => 'Lenner enkorfet', - 'clips' => 'Klipoù', - 'video-clips-list' => 'Klipoù video', - 'video-clips-create' => 'Klip video nevez', + 'clips' => 'Tennadoù', + 'video-clips-list' => 'Tennadoù video', + 'video-clips-create' => 'Tennad video nevez', 'soundbites-list' => 'Tennadoù son', 'soundbites-create' => 'Tennad son nevez', ]; diff --git a/modules/Admin/Language/br/Fediverse.php b/modules/Admin/Language/br/Fediverse.php index f8aeebf4..9dd1559a 100644 --- a/modules/Admin/Language/br/Fediverse.php +++ b/modules/Admin/Language/br/Fediverse.php @@ -10,7 +10,7 @@ declare(strict_types=1); return [ 'messages' => [ - 'actorNotFound' => 'N\'eo ket bet kavet ar gont-se !', + 'actorNotFound' => 'N\'eo ket bet kavet ar gont-se!', 'blockActorSuccess' => 'Stanket eo bet {actor}!', 'unblockActorSuccess' => 'Distanket eo bet an implijer·ez!', 'blockDomainSuccess' => 'Stanket eo bet {domain}!', diff --git a/modules/Admin/Language/br/Home.php b/modules/Admin/Language/br/Home.php index 6cbea879..285392b4 100644 --- a/modules/Admin/Language/br/Home.php +++ b/modules/Admin/Language/br/Home.php @@ -10,5 +10,5 @@ declare(strict_types=1); return [ 'all_podcasts' => 'An holl bodkastoù', - 'no_podcast' => 'N\'eus bet kavet podkast ebet', + 'no_podcast' => 'N\'eo bet kavet podkast ebet', ]; diff --git a/modules/Admin/Language/br/Install.php b/modules/Admin/Language/br/Install.php index 2f86bafd..e73f08a3 100644 --- a/modules/Admin/Language/br/Install.php +++ b/modules/Admin/Language/br/Install.php @@ -11,7 +11,7 @@ declare(strict_types=1); return [ 'manual_config' => 'Kefluniañ dre zorn', 'manual_config_subtitle' => - 'Krouit ur restr `.env` gant hoc’h arventennoù ha nevesait ar bajenn evit kenderc\'hel gant ar staliañ.', + 'Krouit ur restr `.env` gant hoc’h arventennoù ha hizivait ar bajenn evit kenderc\'hel gant ar staliañ.', 'form' => [ 'instance_config' => 'Arventennoù an istañs', 'hostname' => 'Anv an ostiz', diff --git a/modules/Auth/Language/br/MyAccount.php b/modules/Admin/Language/br/MyAccount.php similarity index 100% rename from modules/Auth/Language/br/MyAccount.php rename to modules/Admin/Language/br/MyAccount.php diff --git a/modules/Admin/Language/br/Navigation.php b/modules/Admin/Language/br/Navigation.php index de1da33e..b82240f9 100644 --- a/modules/Admin/Language/br/Navigation.php +++ b/modules/Admin/Language/br/Navigation.php @@ -12,18 +12,16 @@ return [ 'toggle_sidebar' => 'Kuzhat/diskouez ar varrenn gostez', 'go_to_website' => 'Mont d\'al lec\'hienn', 'go_to_admin' => 'Mont d\'an daolenn-stur', - 'not-authorized' => 'Difennet', 'dashboard' => 'Taolenn-stur', 'admin' => 'Degemer', 'podcasts' => 'Podkastoù', 'podcast-list' => 'An holl bodkastoù', 'podcast-create' => 'Krouiñ ur podkast', - 'all-podcast-imports' => 'An holl bodkastoù enporzhiet', - 'podcast-imports-add' => 'Enporzhiañ ur podkast', + 'podcast-import' => 'Enporzhiañ ur podkast', 'persons' => 'Emellerien·ezed', 'person-list' => 'An holl emellerien·ezed', 'person-create' => 'Krouiñ un emeller·ez', - 'fediverse' => 'Fediverse', + 'fediverse' => 'Kevrebed', 'fediverse-blocked-actors' => 'Implijerien·ezed stanket', 'fediverse-blocked-domains' => 'Domanioù stanket', 'users' => 'Implijerien·ezed', @@ -35,7 +33,6 @@ return [ 'settings' => 'Arventennoù', 'settings-general' => 'Hollek', 'settings-theme' => 'Neuz', - 'admin-about' => 'A-zivout', 'account' => [ 'my-account' => 'Ma c\'hont', 'change-password' => 'Kemmañ ar ger-tremen', diff --git a/modules/Admin/Language/br/Notifications.php b/modules/Admin/Language/br/Notifications.php index 3f2ed5f5..2b139d51 100644 --- a/modules/Admin/Language/br/Notifications.php +++ b/modules/Admin/Language/br/Notifications.php @@ -9,11 +9,11 @@ declare(strict_types=1); */ return [ - 'title' => 'Kemennoù', - 'reply' => 'Respontet eo bet d\'ho kemennadenn gant {actor_username}', - 'favourite' => 'Ouzhpennet eo bet ho kemennadenn d\'h·e re garetañ gant {actor_username}', - 'reblog' => 'Rannet eo bet ho kemennadenn gant {actor_username}', - 'follow' => 'Krog eo {actor_username} da heuliañ ac\'hanoc\'h', - 'no_notifications' => 'Kemenn ebet', - 'mark_all_as_read' => 'Merkañ pep tra evel lennet', + 'title' => 'Notifications', + 'reply' => '{actor_username} replied to your post', + 'favourite' => '{actor_username} favourited your post', + 'reblog' => '{actor_username} shared your post', + 'follow' => '{actor_username} started following you', + 'no_notifications' => 'No notifications', + 'mark_all_as_read' => 'Mark all as read', ]; diff --git a/modules/Admin/Language/br/Page.php b/modules/Admin/Language/br/Page.php index b99aa723..dccaa097 100644 --- a/modules/Admin/Language/br/Page.php +++ b/modules/Admin/Language/br/Page.php @@ -25,6 +25,6 @@ return [ ], 'messages' => [ 'createSuccess' => 'Krouet eo bet ar bajenn "{pageTitle}" gant berzh!', - 'editSuccess' => 'Nevesaet eo bet ar bajenn gant berzh!', + 'editSuccess' => 'Hizivaet eo bet ar bajenn gant berzh!', ], ]; diff --git a/modules/Admin/Language/br/Person.php b/modules/Admin/Language/br/Person.php index e91d9fcd..9a1d0f69 100644 --- a/modules/Admin/Language/br/Person.php +++ b/modules/Admin/Language/br/Person.php @@ -11,14 +11,14 @@ declare(strict_types=1); return [ 'persons' => 'Emellerien·ezed', 'all_persons' => 'An holl emellerien·ezed', - 'no_person' => 'Emeller·ez ebet !', + 'no_person' => 'Emeller·ez ebet!', 'create' => 'Krouiñ un emeller·ez', 'view' => 'Gwelet an emeller·ez', 'edit' => 'Kemmañ an emeller·ez', 'delete' => 'Dilemel an emeller·ez', 'messages' => [ 'createSuccess' => 'Krouet eo bet an emeller·ez gant berzh!', - 'editSuccess' => 'Nevesaet eo bet an emeller·ez gant berzh!', + 'editSuccess' => 'Hizivaet eo bet an emeller·ez gant berzh!', 'deleteSuccess' => 'Tennet eo bet an emeller·ez!', ], 'form' => [ diff --git a/modules/Admin/Language/br/Platforms.php b/modules/Admin/Language/br/Platforms.php index 959e9f60..71d04168 100644 --- a/modules/Admin/Language/br/Platforms.php +++ b/modules/Admin/Language/br/Platforms.php @@ -9,28 +9,15 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Savennoù podkastoù', - 'social' => 'Rouedadoù sokial', - 'funding' => 'Liammoù arc\'hantaouiñ', - ], - 'website' => 'Lec\'hienn', + 'title' => 'Savennoù', 'home_url' => 'Mont da lec\'hienn {platformName}', - 'register' => 'Enskrivañ', 'submit_url' => 'Kasit ho podkast war {platformName}', - 'your_link' => 'Ho liamm', - 'your_id' => [ - 'podcasting' => 'Hoc’h anaout (ID)', - 'social' => 'Hoc’h anaout (ID)', - 'funding' => 'Ho CTA', - ], - 'your_cta' => 'Ho kalv da ober', 'visible' => 'Diskouez e pajenn ar podkast?', 'on_embed' => 'Diskouez el lenner enkorfet?', 'remove' => 'Dilemel {platformName}', 'submit' => 'Enrollañ', 'messages' => [ - 'updateSuccess' => 'Nevesaet eo bet ereoù ar savennoù gant berzh!', + 'updateSuccess' => 'Hizivaet eo bet ereoù ar savennoù gant berzh!', 'removeLinkSuccess' => 'Dilamet eo bet ere ar savenn.', 'removeLinkError' => 'N\'eo ket bet dilamet ere ar savenn. Klaskit en-dro.', diff --git a/modules/Admin/Language/br/Podcast.php b/modules/Admin/Language/br/Podcast.php index 2a754f54..0ecaa7fb 100644 --- a/modules/Admin/Language/br/Podcast.php +++ b/modules/Admin/Language/br/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'N\'eo bet kavet podkast ebet!', 'create' => 'Krouiñ ur podkast', 'import' => 'Enporzhiañ ur podkast', - 'all_imports' => 'Ar podkastoù enporzhiet', 'new_episode' => 'Rann nevez', 'view' => 'Gwelet ar podkast', 'edit' => 'Kemmañ ar podkast', @@ -22,15 +21,14 @@ return [ 'delete' => 'Dilemel ar podkast', 'see_episodes' => 'Gwelet ar rannoù', 'see_contributors' => 'Gwelet ar berzhidi, ar perzhiadezed', - 'monetization_other' => 'Doare arc\'hantaouiñ all', 'go_to_page' => 'Gwelet ar bajenn', 'latest_episodes' => 'Rannoù diwezhañ', 'see_all_episodes' => 'Gwelet an holl rannoù', 'draft' => 'Brouilhed', 'messages' => [ 'createSuccess' => 'Krouet eo bet ar podkast gant berzh!', - 'editSuccess' => 'Nevesaet eo bet ar podkast gant berzh!', - 'importSuccess' => 'Enporzhiet eo bet ar podkast gant berzh!', + 'editSuccess' => 'Hizivaet eo bet ar podkast gant berzh!', + 'importSuccess' => 'Enporzhet eo bet ar podkast gant berzh!', 'deleteSuccess' => 'Dilamet eo bet ar podkast @{podcast_handle} gant berzh!', 'deletePodcastMediaError' => 'C\'hwitadenn war dilemel {type, select, cover {golo} @@ -45,14 +43,15 @@ return [ other {media} } ar rann {episode_slug}.', 'deletePodcastMediaFolderError' => 'C\'hwitadenn war dilemel teuliad ar mediaioù {folder_path}. Gallout a rit lemel an teuliad-mañ diouzh ar gantenn dre zorn.', - 'podcastFeedUpdateSuccess' => 'Nevesadenn: {number_of_new_episodes, plural, + 'podcastFeedUpdateSuccess' => 'Hizivadenn: {number_of_new_episodes, plural, one {# rann} two {# rann} few {# rann} many {# rann} other {# rann} } a zo bet ouzhpennet d\'ar podkast gant berzh!', - 'podcastFeedUpToDate' => 'Nevesaet eo bet ar podkast dija.', + 'podcastFeedUpToDate' => 'Hizivaet eo bet ar podkast dija.', + 'podcastNotImported' => 'C\'hwitadenn war hizivadenn ar podkast peogwir n\'eo ket bet enporzhiet.', 'publishError' => 'Ar podkast-mañ a zo bet embannet dija pe steuñvet eo e embannadur.', 'publishEditError' => 'N\'eo ket steuñvet embannadur ar podkast-mañ.', 'publishCancelSuccess' => 'Nullet eo bet embannadur ar podkast gant berzh!', @@ -61,8 +60,6 @@ return [ 'form' => [ 'identity_section_title' => 'Titouroù diwar-benn ar podkast', 'identity_section_subtitle' => 'Ar maeziennoù a laka ac\'hanoc\'h da vezañ remerket.', - 'fediverse_section_title' => 'Identelezh er Fediverse', - 'cover' => 'Golo ar podkast', 'cover_size_hint' => 'Ar golo a rankfe bezañ ur c\'harrez ha 1400px e vent da nebeutañ.', 'banner' => 'Giton ar podkast', @@ -77,17 +74,7 @@ return [ 'episodic' => 'Bep ur mare', 'episodic_hint' => 'M\'eo ar rannoù da vezañ selaouet hep urzh resis. Ar rannoù nevesoc’h a vo kinniget da gentañ.', 'serial' => 'Heuliad', - 'serial_hint' => 'M\'eo ar rannoù da vezañ selaouet gant un urzh resis. Ar rannoù a vo kinniget hervez urzh an niverennoù.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Ar medium evel ma vez kinniget gant ar valizenn RSS podcast:medium. Cheñch an dra-se a c\'hell cheñch an doare ma vo kinniget ho kwazh gant al lennerien.', - 'podcast' => 'Podkast', - 'podcast_hint' => 'Evit deskrivañ gwazh ur podkast.', - 'music' => 'Sonerezh', - 'music_hint' => 'Ur wazh gant sonerezh aozet e-barzh un "album". Pep item zo un ton en album.', - 'audiobook' => 'Levr klevet', - 'audiobook_hint' => 'Ur seurt aodio dibar gant un item dre wazh, peotramant pa glot an itemoù gant chabistroù al levr.', + 'serial_hint' => 'M\'eo ar rannoù da vezañ selaouet gant un urzh resis. Ar rannoù koshoc\'h a vo kinniget da gentañ.', ], 'description' => 'Deskrivadur', 'classification_section_title' => 'Rummatadur', @@ -106,14 +93,12 @@ return [ ], 'author_section_title' => 'Aozer·ez', 'author_section_subtitle' => 'Piv zo o verañ ar podkast?', - 'owner_name' => 'Anv ar perc\'henn·ez', + 'owner_name' => 'Anv ar perc\'henn', 'owner_name_hint' => - 'Evit a sell ouzh ar mererezh. War ar wazh RSS publik e vo.', - 'owner_email' => 'Chomlec\'h postel ar perc\'henn·ez', + 'Evit a sell ouzh ar mererezh. War al lanv RSS publik e vo.', + 'owner_email' => 'Chomlec\'h postel ar perc\'henn', 'owner_email_hint' => - 'Implijet e vo gant an darn vrasañ eus ar savennoù evit gwiriañ perc\'hentiezh ar podkast. War ar wazh RSS publik e vo.', - 'is_owner_email_removed_from_feed' => 'Lemel chomlec\'h postel ar perc\'henn·ez diouzh ar wazh RSS publik', - 'is_owner_email_removed_from_feed_hint' => 'Rankout a rafec\'h lakaat ar chomlec\'h war wel adarre, evit ur mare, evit ma vefe gouest ur meneger da wiriañ oc\'h ar perc\'henn·ez.', + 'Implijet e vo gant an darn vrasañ eus ar savennoù evit gwiriañ perc\'hentiezh ar podkast. War al lanv RSS publik e vo.', 'publisher' => 'Embanner·ez', 'publisher_hint' => 'Ar strollad kiriek eus sevel ar podkast. Alies eo embregerezh pe rouedad ar podkast. A-wechoù e vez anvet ar vaezienn-mañ "Aozer·ez".', @@ -126,13 +111,8 @@ return [ 'monetization_section_subtitle' => 'Dastum arc\'hant a-drugarez d\'ho selaouerien·ezed.', 'premium' => 'Premium', - 'premium_by_default' => 'Ar rannoù a zo evit ar re bremium dre ziouer', - 'premium_by_default_hint' => 'Rannoù ar podkast a vo merket Premium dre ziouer. Gallout a rit lakaat rannoù zo evel publik.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Mont da welet ho taolenn-stur OP3 (liamm diavaez)', - 'op3_hint' => 'Talvoudekait ho roadennoù gant OP3, zo ur servij open source diavaez evit dielfennañ ar muzulioù heklev. Rannit, kadarnait ha lakait ho roadennoù keñver-ha-keñver gant re ekosistem ar podkastoù digor.', - 'op3_enable' => 'Gweredekaat ar servij dielfennañ OP3', - 'op3_enable_hint' => 'Evit abegoù surentez ne vo ket rannet roadennoù ar rannoù Premium gant OP3.', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', 'payment_pointer' => 'Chomlec\'h paeañ (Payment Poienter) evit Web Monetization', 'payment_pointer_hint' => 'Ar chomlec\'h ma vo dastumet an arc\'hant ganeoc\'h a-drugarez da Web Monetization', @@ -141,12 +121,11 @@ return [ 'M\'ho peus ezhomm eus balizennoù RSS ha n\'eus ket anezho e Castopod e c\'hellit o lakaat amañ.', 'custom_rss' => 'Balizennoù RSS personelaet evit ar podkast', 'custom_rss_hint' => 'An dra-se a vo ouzhpennet e-barzh ar valizenn ❬channel❭.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'URL nevez ar wazh', - 'new_feed_url_hint' => 'Implijit ar vaezienn-mañ pa cheñchit anv domani pe savenn herberc\'hiañ ho podkast. M\'eo enporzhiet ar podkast e vez lakaet enni URL a-vremañ ar wazh dre ziouer.', - 'old_feed_url' => 'URL kozh ar wazh', + 'new_feed_url' => 'URL nevez al lanv', + 'new_feed_url_hint' => 'Implijit ar vaezienn-mañ pa cheñchit anv domani pe savenn herberc\'hiañ ho podkast. M\'eo enporzhiet ar podkast e vez lakaet enni URL a-vremañ al lanv dre ziouer.', + 'old_feed_url' => 'URL kozh al lanv', + 'update_feed' => 'Hizivaat al lanv', + 'update_feed_tip' => 'Enporzhiañ rannoù diwezhañ ar podkast-mañ', 'partnership' => 'Kevelerezh', 'partner_id' => 'ID', 'partner_link_url' => 'Ere URL', @@ -154,13 +133,14 @@ return [ 'partner_id_hint' => 'Hoc’h ID deoc\'h-c\'hwi e ti ar c\'heveler', 'partner_link_url_hint' => 'Chomlec\'h generek an ereoù gant ar c\'heveler', 'partner_image_url_hint' => 'Chomlec\'h generek ar skeudennoù gant ar c\'heveler', + 'status_section_title' => 'Statud', 'block' => 'Ar podkast a rankfe bezañ kuzhet diouzh ar rolladoù publik', 'block_hint' => 'Diskouez pe kuzhat ar podkast: trec\'haoliñ an afell-mañ a viro ar podkast a-bezh ouzh bezañ diskouezet war Apple Podcasts, Google Podcasts pe savennoù all hag a implij ar renabloù-se. (N\'eus gwarant ebet)', 'complete' => 'Ne vo mui rannoù nevez gant ar podkast', 'lock' => 'Mirout ar podkast ouzh bezañ eilet', 'lock_hint' => - 'Ar pal eo lavaret d\'ar savennoù all hag aotreet int da enporzhiañ ar wazh-mañ pe get. "Ya" a dalv eo nac\'het an holl c\'houlennoù enporzhiañ.', + 'Ar pal eo lavaret d\'ar savennoù all hag aotreet int da enporzhiañ al lanv-mañ pe get. "Ya" a dalv eo nac\'het an holl c\'houlennoù enporzhiañ.', 'submit_create' => 'Krouiñ ar podkast', 'submit_edit' => 'Enrollañ ar podkast', ], @@ -264,74 +244,70 @@ return [ 'golf' => 'Golf', 'hockey' => 'Hockey', 'rugby' => 'Rugbi', - 'running' => 'Redek', - 'soccer' => 'Mell-droad', - 'swimming' => 'Neuierezh', + 'running' => 'Running', + 'soccer' => 'Soccer', + 'swimming' => 'Swimming', 'tennis' => 'Tennis', 'volleyball' => 'Volleyball', - 'wilderness' => 'Natur', - 'wrestling' => 'Gouren', - 'after_shows' => 'Goude abadenn', - 'film_history' => 'Istor ar sinema', - 'film_interviews' => 'Atersadennoù er sinema', - 'film_reviews' => 'Barnadennoù filmoù', - 'tv_reviews' => 'Barnadennoù tele', + 'wilderness' => 'Wilderness', + 'wrestling' => 'Wrestling', + 'after_shows' => 'After Shows', + 'film_history' => 'Film History', + 'film_interviews' => 'Film Interviews', + 'film_reviews' => 'Film Reviews', + 'tv_reviews' => 'TV Reviews', ], 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Distreiñ da daolenn-stur ar podkast', - 'post' => 'Ho kemennadenn vrudañ', + 'back_to_podcast_dashboard' => 'Back to podcast dashboard', + 'post' => 'Your announcement post', 'post_hint' => - "Skrivit ur gemennadenn evit kemenn embannadur ho podkast. War bajenn degemer ho podkast e vo diskouezet ar gemennadenn.", - 'message_placeholder' => 'Skrivit ho kemennadenn…', - 'submit' => 'Embann', - 'publication_date' => 'Deiziad an embann', + "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", + 'message_placeholder' => 'Write your message…', + 'submit' => 'Publish', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Bremañ', - 'schedule' => 'Steuñviñ', + 'now' => 'Now', + 'schedule' => 'Schedule', ], - 'scheduled_publication_date' => 'Deiziad embannadur steuñvet', + 'scheduled_publication_date' => 'Scheduled publication date', 'scheduled_publication_date_hint' => - 'Gallout a rit steuñviñ embannadur ar podkast en ur choaz un deiziad evit an embannadur. Dleout a ra ar vaezienn bezañ er furmad YYYY-MM-DD HH:mm', - 'submit_edit' => 'Kemmañ an embannadur', - 'cancel_publication' => 'Nullañ an embann', - 'message_warning' => 'N\'ho peus ket skrivet ur gemennadenn evit brudañ ho rann !', - 'message_warning_hint' => 'Ouzhpennañ ur gemennadenn a lakay muioc\'h a dud er jeu, ha diwar se e vo gwelet muioc\'h ho podkast.', - 'message_warning_submit' => 'Embann memestra', + 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', + 'message_warning' => 'You did not write a message for your announcement post!', + 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ - 'draft_mode' => 'mod brouilhed', - 'not_published' => 'N\'eo ket embannet ar podkast-mañ c\'hoazh.', - 'scheduled' => 'Ar podkast-mañ a vo embannet d\'an/d\'ar {publication_date}.', + 'draft_mode' => 'draft mode', + 'not_published' => 'This podcast is not yet published.', + 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => - "Pa vo dilamet ar podkast e vo dilamet an holl rannoù, restroù media, kemennadennoù ha stadegoù liammet outañ. Ur wech dilamet, ne c'hell bezañ adtapet an traoù.", - 'understand' => 'Kompren a ran, c\'hoant am eus da zilemel ar podkast da vat', - 'submit' => 'Dilemel', + "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", + 'understand' => 'I understand, I want the podcast to be permanently deleted', + 'submit' => 'Delete', ], - 'by' => 'Gant {publisher}', - 'season' => 'Koulzad {seasonNumber}', - 'list_of_episodes_year' => 'Rannoù {year} ({episodeCount})', + 'by' => 'By {publisher}', + 'season' => 'Season {seasonNumber}', + 'list_of_episodes_year' => '{year} episodes ({episodeCount})', 'list_of_episodes_season' => - 'Rannoù ar c\'houlzad {seasonNumber} ({episodeCount})', - 'no_episode' => 'N\'eus bet kavet rann ebet !', - 'follow' => 'Heuliañ', + 'Season {seasonNumber} episodes ({episodeCount})', + 'no_episode' => 'No episode found!', + 'follow' => 'Follow', 'followers' => '{numberOfFollowers, plural, - one {# heulier·ez} - two {# heulier·ez} - other {# heulier·ez} + one {# follower} + other {# followers} }', 'posts' => '{numberOfPosts, plural, - one {# gemennadenn} - two {# gemennadenn} - few {# c\'hemennadenn} - many {a gemennadennoù} - other {# kemennadenn} + one {# post} + other {# posts} }', - 'activity' => 'Oberiantiz', - 'episodes' => 'Rannoù', - 'sponsor' => 'Harpit ac\'hanomp', - 'funding_links' => 'Ereoù evit arc\'hantaouiñ {podcastTitle}', - 'find_on' => 'Kavit {podcastTitle} war', + 'activity' => 'Activity', + 'episodes' => 'Episodes', + 'sponsor' => 'Sponsor', + 'funding_links' => 'Funding links for {podcastTitle}', + 'find_on' => 'Find {podcastTitle} on', 'listen_on' => 'Selaouit war', ]; diff --git a/modules/Admin/Language/br/PodcastImport.php b/modules/Admin/Language/br/PodcastImport.php new file mode 100644 index 00000000..7ba8d909 --- /dev/null +++ b/modules/Admin/Language/br/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'URL al lanv', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'Ar podkast nevez', + 'advanced_params_section_title' => 'Arventennoù kempleshoc\'h', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Niverenn ar c\'houlzad', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Enporzhiañ ar podkast', +]; diff --git a/modules/Admin/Language/br/PodcastNavigation.php b/modules/Admin/Language/br/PodcastNavigation.php index f3d2a8e6..5c3842ca 100644 --- a/modules/Admin/Language/br/PodcastNavigation.php +++ b/modules/Admin/Language/br/PodcastNavigation.php @@ -10,33 +10,29 @@ declare(strict_types=1); return [ 'go_to_page' => 'Mont da pajenn ar podkast', - 'rss_feed' => 'Gwazh RSS', 'dashboard' => 'Taolenn-stur ar podkast', 'podcast-view' => 'Degemer', 'podcast-edit' => 'Kemmañ ar podkast', 'podcast-persons-manage' => 'Merañ an emellerien·ezed', - 'podcast-imports' => 'Ar podkastoù enporzhiet', - 'podcast-imports-sync' => 'Sinkronaat ar gwazhoù', 'episodes' => 'Rannoù', 'episode-list' => 'An holl rannoù', 'episode-create' => 'Rann nevez', 'analytics' => 'Muzulioù heklev', - 'podcast-analytics' => 'Gwel a-vras', - 'podcast-analytics-webpages' => 'Gweladennoù ar pajennoù web', + 'podcast-analytics' => 'Audience overview', + 'podcast-analytics-webpages' => 'Web pages visits', 'podcast-analytics-locations' => 'Lec\'hioù', 'podcast-analytics-unique-listeners' => 'Selaouerien·ezed unel', 'podcast-analytics-players' => 'Lennerioù', 'podcast-analytics-listening-time' => 'Padelezh ar selaou', 'podcast-analytics-time-periods' => 'Mareoù ar selaou', - 'monetization' => 'Moneisaat', - 'subscription-list' => 'An holl goumanantoù', - 'subscription-create' => 'Ouzhpennañ ur c\'houmanant', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', 'contributors' => 'Perzhidi, perzhiadezed', 'contributor-list' => 'An holl berzhidi ha perzhiadezed', 'contributor-add' => 'Ouzhpennañ ur perzhiad pe ur berzhiadez', - 'broadcast' => 'Skignañ', - 'platforms-podcasting' => 'Arloadoù podkastoù', + 'platforms' => 'Savennoù diavaez', + 'platforms-podcasting' => 'Podkast', 'platforms-social' => 'Rouedadoù sokial', - 'platforms-funding' => 'Liammoù arc\'hantaouiñ', - 'podcast-monetization-other' => 'Un dra all', + 'platforms-funding' => 'Arc\'hantaouiñ', ]; diff --git a/modules/Admin/Language/br/Settings.php b/modules/Admin/Language/br/Settings.php index 62dab9f1..4929034f 100644 --- a/modules/Admin/Language/br/Settings.php +++ b/modules/Admin/Language/br/Settings.php @@ -14,42 +14,42 @@ return [ 'title' => 'Istañs', 'site_icon' => 'Arlun al lec\'hienn', 'site_icon_delete' => 'Dilemel arlun al lec\'hienn', - 'site_icon_hint' => 'Arlunioù al lec\'hienn zo ar pezh a welit war ivinelloù ho merdeer, barrenn ar pennrolloù, ha pa vez ouzhpennet al lec\'hienn d\'ur pellgomzer evel ur verradenn.', + 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', 'site_icon_helper' => 'An arlun a rankfe bezañ ur c\'harrez ha 512px e vent da nebeutañ.', 'site_name' => 'Titl al lec\'hienn', 'site_description' => 'Deskrivadur al lec\'hienn', 'submit' => 'Enrollañ', - 'editSuccess' => 'Nevesaet eo bet an istañs gant berzh!', - 'deleteIconSuccess' => 'Skarzhet eo bet arlun al lec\'hienn gant berzh!', + 'editSuccess' => 'Instance has been updated successfully!', + 'deleteIconSuccess' => 'Site icon has been remove successfully!', ], 'images' => [ 'title' => 'Skeudennoù', - 'subtitle' => 'Amañ e c\'hellit azgenel an holl skeudennoù diwar ar skeudennoù orin a oa bet karget. Da vezañ implijet ma kav deoc\'h e vank skeudennoù zo. Hir a-walc\'h e c\'hell bezañ al labour-mañ.', - 'regenerate' => 'Azgenel ar skeudennoù', - 'regenerationSuccess' => 'An holl skeudennoù zo bet azganet gant berzh!', + 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', + 'regenerate' => 'Regenerate images', + 'regenerationSuccess' => 'All images have been regenerated successfully!', ], 'housekeeping' => [ - 'title' => 'Kempenn an istañs', - 'subtitle' => 'Lañsañ labourioù a bep seurt evit kempenn an istañs. Da vezañ implijet ma welit kudennoù gant restroù media pe aterinder ar roadennoù. Hir a-walc\'h e c\'hell bezañ al labourioù-mañ.', - 'reset_counts' => 'Adderaouekaat ar c\'honterioù', - 'reset_counts_helper' => 'Gant an dibarzh-mañ e vo adjedet hag adderaouekaet ar c\'hontoù (niver a heulierien·ezed, a bostoù, a evezhiadennoù, …).', - 'rewrite_media' => 'Adskrivañ metaroadennoù ar media', - 'rewrite_media_helper' => 'Gant an dibarzh-mañ e vo skarzhet ar restroù media diezhomm hag adkrouet en-dro (skeudennoù, restroù aodio, treuzskrivadurioù, chabistroù, …)', - 'rename_episodes_files' => 'Adenvel restroù aodio ar rannoù', - 'rename_episodes_files_hint' => 'Gant an dibarzh-mañ e vo adanvet restroù aodio an holl rannoù gant ur chadenn arouezennoù dre zegouezh. Da implijout m\'eo bet kavet unan eus liammoù ho rannoù prevez, rak an dra-se a guzho anezhañ en-dro.', - 'clear_cache' => 'Naetaat ar grubuilh', - 'clear_cache_helper' => 'Gant an dibarzh-mañ e vo naetaet krubuilh Redis pe restroù an teuliad writable/cache.', - 'run' => 'Lañsañ ar c\'hempenn', - 'runSuccess' => 'Echu eo ar c\'hempenn gant berzh!', + 'title' => 'Housekeeping', + 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', + 'reset_counts' => 'Reset counts', + 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', + 'rewrite_media' => 'Rewrite media metadata', + 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', + 'clear_cache' => 'Clear all cache', + 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', + 'run' => 'Run housekeeping', + 'runSuccess' => 'Housekeeping has been run successfully!', ], 'theme' => [ 'title' => 'Neuz', 'accent_section_title' => 'Liv kentañ', - 'accent_section_subtitle' => 'Choazit al liv a roio an neuz d\'an holl bajennoù publik.', - 'pine' => 'Pin', - 'crimson' => 'Ruz-mouk', - 'amber' => 'Goularz', - 'lake' => 'Lenn', + 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', + 'pine' => 'Pine', + 'crimson' => 'Crimson', + 'amber' => 'Amber', + 'lake' => 'Lake', 'jacaranda' => 'Jacaranda', 'onyx' => 'Onyx', 'submit' => 'Enrollañ', diff --git a/modules/Auth/Language/br/User.php b/modules/Admin/Language/br/User.php similarity index 50% rename from modules/Auth/Language/br/User.php rename to modules/Admin/Language/br/User.php index accd5af9..314e676a 100644 --- a/modules/Auth/Language/br/User.php +++ b/modules/Admin/Language/br/User.php @@ -9,52 +9,48 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Kemmañ roll {username}", - 'ban' => 'Stankañ', - 'unban' => 'Distankañ', + 'edit_roles' => "Kemm rolloù {username}", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', 'delete' => 'Dilemel', 'create' => 'Krouiñ un implijer·ez', 'view' => "Titouroù diwar-benn {username}", 'all_users' => 'An holl implijerien·ezed', 'list' => [ 'user' => 'Implijer·ez', - 'role' => 'Roll', - 'banned' => 'Stanket?', + 'roles' => 'Rolloù', + 'banned' => 'Banned?', ], 'form' => [ 'email' => 'Postel', 'username' => 'Anv implijer·ez', 'password' => 'Ger-tremen', 'new_password' => 'Ger-tremen nevez', - 'role' => 'Roll', 'roles' => 'Rolloù', 'permissions' => 'Aotreoù', 'submit_create' => 'Krouiñ an implijer·ez', 'submit_edit' => 'Enrollañ', 'submit_password_change' => 'Kemm!', ], - 'delete_form' => [ - 'title' => 'Dilemel {user}', - 'disclaimer' => - "Emaoc'h o vont da lemel {user} da vat. Ne c'hallo ket gwelet an daolenn-stur ken.", - 'understand' => 'Komprenet em eus. Fellout a ra din lemel {user} da vat', - 'submit' => 'Dilemel', + 'roles' => [ + 'superadmin' => 'Super admin', ], 'messages' => [ 'createSuccess' => 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "Rolloù {username} zo bet nevesaet gant berzh.", - 'banSuccess' => 'Stanket eo bet {username}.', - 'unbanSuccess' => 'Distanket eo bet {username}.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', 'editOwnerError' => - '{username} eo perc\'henn·ez an istañs. Ne c\'hallit ket kemmañ e rolloù…', + '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => - 'Dreistmerour·ez eo {username}, n\'haller ket stankañ un dreistmerour·ez ken aes-se…', - 'deleteOwnerError' => - '{username} eo perc\'henn·ez an istañs. N\'haller ket lemel ar perc\'henn·ez ken aes-se…', + '{username} is a superadmin, one does not simply ban a superadmin…', 'deleteSuperAdminError' => - 'Dreistmerour·ez eo {username}, n\'haller ket lemel un dreistmerour·ez ken aes-se…', + '{username} is a superadmin, one does not simply delete a superadmin…', 'deleteSuccess' => 'Dilamet eo bet {username}.', ], ]; diff --git a/modules/Admin/Language/br/Validation.php b/modules/Admin/Language/br/Validation.php index 59c49e93..750b1968 100644 --- a/modules/Admin/Language/br/Validation.php +++ b/modules/Admin/Language/br/Validation.php @@ -10,8 +10,9 @@ declare(strict_types=1); return [ 'min_dims' => - '{field} n\'eo ket ur skeudenn, peotrament n\'eo ket ledan a-walc\'h pe uhel a-walc\'h.', + '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => - '{field} n\'eo ket ur skeudenn, peotrament n\'eo ket mat ar ratio.', - 'is_json' => 'JSON direizh a zo e-barzh {field}.', + '{field} is either not an image or not of the right ratio.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/br/VideoClip.php b/modules/Admin/Language/br/VideoClip.php index 1ce237b3..fa2adf21 100644 --- a/modules/Admin/Language/br/VideoClip.php +++ b/modules/Admin/Language/br/VideoClip.php @@ -10,60 +10,60 @@ declare(strict_types=1); return [ 'list' => [ - 'title' => 'Klipoù video', + 'title' => 'Tennadoù video', 'status' => [ 'label' => 'Statud', 'queued' => 'el lost', - 'queued_hint' => 'Emañ ar c\'hlip video el lost.', + 'queued_hint' => 'Emañ an tennad video el lost.', 'pending' => 'o c\'hortoz', - 'pending_hint' => 'Ganet e vo ar c\'hlip a-benn nebeut.', - 'running' => 'war ar stern', - 'running_hint' => 'Emañ ar c\'hlip o vezañ ganet.', + 'pending_hint' => 'Clip will be generated shortly.', + 'running' => 'running', + 'running_hint' => 'Clip is being generated.', 'failed' => 'c\'hwitet', - 'failed_hint' => 'Ar c\'hlip n\'eo ket bet ganet: fazi skript.', - 'passed' => 'berzh', - 'passed_hint' => 'Ganet eo bet ar c\'hlip gant berzh!', + 'failed_hint' => 'Clip could not be generated: script failure.', + 'passed' => 'passed', + 'passed_hint' => 'Clip was generated successfully!', ], - 'clip' => 'Klip', - 'duration' => 'Padelezh al labour', + 'clip' => 'Tennad', + 'duration' => 'Job duration', ], - 'title' => 'Klip video: {videoClipLabel}', - 'download_clip' => 'Pellgargañ ar c\'hlip', - 'create' => 'Klip video nevez', - 'go_to_page' => 'Mont da pajenn ar c\'hlip', - 'retry' => 'Klask genel ar c\'hlip en-dro', - 'delete' => 'Dilemel ar c\'hlip', - 'logs' => 'Roll istor al labourioù', + 'title' => 'Video clip: {videoClipLabel}', + 'download_clip' => 'Pellgargañ an tennad', + 'create' => 'Tennad video nevez', + 'go_to_page' => 'Mont da pajenn an tennad', + 'retry' => 'Retry clip generation', + 'delete' => 'Dilemel an tennad', + 'logs' => 'Job logs', 'messages' => [ - 'alreadyExistingError' => 'Bez ez eus eus ur c\'hlip video heñvel-mik dija!', - 'addToQueueSuccess' => 'Ouzhpennet eo bet ar c\'hlip video d\'al lost, o c\'hortoz e vefe krouet!', - 'deleteSuccess' => 'Dilamet eo bet ar c\'hlip video gant berzh!', + 'alreadyExistingError' => 'The video clip you are trying to create already exists!', + 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', + 'deleteSuccess' => 'Video clip has been successfully removed!', ], 'format' => [ - 'landscape' => 'A-led', - 'portrait' => 'A-blom', - 'squared' => 'Karrezek', + 'landscape' => 'Landscape', + 'portrait' => 'Portrait', + 'squared' => 'Squared', ], 'form' => [ - 'title' => 'Klip video nevez', - 'params_section_title' => 'Arventennoù ar c\'hlip video', - 'clip_title' => 'Titl ar c\'hlip', + 'title' => 'New video clip', + 'params_section_title' => 'Video clip parameters', + 'clip_title' => 'Titl an tennad', 'format' => [ - 'label' => 'Choazit ur furmad', - 'landscape_hint' => 'Videoioù a-led gant ur ratio 16:9 a zo dispar evit PeerTube, Youtube ha Vimeo.', - 'portrait_hint' => 'Videoioù a-blom gant ur ratio 9:16 a zo dispar evit TikTok, Youtube shorts ha stories Instagram.', - 'squared_hint' => 'Videoioù karrezek gant ur ratio 1:1 a zo dispar evit Mastodon, Facebook, Twitter ha LinkedIn.', + 'label' => 'Choose a format', + 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', + 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', + 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', ], 'theme' => 'Dibab un neuz', - 'start_time' => 'Kregiñ da', - 'duration' => 'Padelezh', - 'trim_start' => 'Krennañ ar penn-kentañ', - 'trim_end' => 'Krennañ an dibenn', - 'submit' => 'Krouiñ ur c\'hlip video', + 'start_time' => 'Start at', + 'duration' => 'Duration', + 'trim_start' => 'Trim start', + 'trim_end' => 'Trim end', + 'submit' => 'Create video clip', ], 'requirements' => [ 'title' => 'Mankout a ra binvioù', - 'missing' => 'Mankout a ra ostilhoù. Bezit sur eo bet ouzhpennet an holl vinvioù ez ezhomm anezho evit bezañ gouest da sevel ur video diwar ar rann-mañ!', + 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', 'ffmpeg' => 'FFmpeg', 'gd' => 'Graphics Draw (GD)', 'freetype' => 'Levraoueg Freetype evit GD', diff --git a/modules/Admin/Language/ca/AboutCastopod.php b/modules/Admin/Language/ca/AboutCastopod.php deleted file mode 100644 index c8598e13..00000000 --- a/modules/Admin/Language/ca/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Sobre Castopod', - 'host_name' => 'Nom del servidor', - 'version' => 'Versió de Castopod', - 'php_version' => 'Versió de PHP', - 'os' => 'Sistema operatiu', - 'languages' => 'Idiomes', - 'update_database' => 'Actualitza la base de dades', - 'messages' => [ - 'databaseUpdateSuccess' => 'La base de dades està actualitzada!', - ], -]; diff --git a/modules/Admin/Language/ca/Breadcrumb.php b/modules/Admin/Language/ca/Breadcrumb.php index 8beefd66..9fa7362a 100644 --- a/modules/Admin/Language/ca/Breadcrumb.php +++ b/modules/Admin/Language/ca/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Inici', 'podcasts' => 'podcasts', 'episodes' => 'episodis', - 'subscriptions' => 'subscripcions', + 'subscriptions' => 'subscriptions', 'contributors' => 'col·laboradors', 'pages' => 'pàgines', 'settings' => 'preferències', 'theme' => 'tema', - 'about' => 'quant a', 'add' => 'afegir', 'new' => 'nova', 'edit' => 'editar', 'persons' => 'persones', 'publish' => 'publicar', 'publish-edit' => 'editar la publicació', - 'publish-date-edit' => 'edita la data de publicació', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'desfer la publicació', 'delete' => 'eliminar', - 'remove' => 'suprimeix', 'fediverse' => 'Fediverse', - 'blocked-actors' => 'comptes bloquejats', - 'blocked-domains' => 'dominis bloquejats', + 'block-lists' => 'llista de bloquejats', 'users' => 'usuaris', 'my-account' => 'el meu compte', 'change-password' => 'canviar la contrasenya', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'importar un feed', 'platforms' => 'plataformes', 'social' => 'xarxes socials', 'funding' => 'financiació', - 'monetization-other' => 'other monetization', 'analytics' => 'estadístiques', 'locations' => 'ubicacions', 'webpages' => 'pàgines web', @@ -53,5 +48,5 @@ return [ 'video-clips' => 'vídeoclips', 'embed' => 'reproductor incrustable', 'notifications' => 'notificacions', - 'suspend' => 'suspèn', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/ca/Charts.php b/modules/Admin/Language/ca/Charts.php index b1085117..4873a6ee 100644 --- a/modules/Admin/Language/ca/Charts.php +++ b/modules/Admin/Language/ca/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Ample de banda emprat diàriament (en MB)', 'total_storage_by_month' => 'Emmagatzematge mensual (en MB)', 'total_bandwidth_by_month' => 'Ample de banda emprat mensualment (en MB)', - 'total_bandwidth_by_month_limit' => 'Limitat a {totalBandwidth} al mes', ]; diff --git a/modules/Admin/Language/ca/Common.php b/modules/Admin/Language/ca/Common.php index 8ce267d5..c178db60 100644 --- a/modules/Admin/Language/ca/Common.php +++ b/modules/Admin/Language/ca/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Pujar un fitxer', 'remote_url' => 'URL remota', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Reproduir', diff --git a/modules/Auth/Language/ca/Contributor.php b/modules/Admin/Language/ca/Contributor.php similarity index 72% rename from modules/Auth/Language/ca/Contributor.php rename to modules/Admin/Language/ca/Contributor.php index 4105f38e..61a8b380 100644 --- a/modules/Auth/Language/ca/Contributor.php +++ b/modules/Admin/Language/ca/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Afegir un col·laborador', 'submit_edit' => 'Actualitzar el rol', ], - 'delete_form' => [ - 'title' => 'Suprimeix {contributor}', - 'disclaimer' => - 'Esteu a punt d\'eliminar {contributor} dels col·laboradors. Ja no podrà accedir a "{podcastTitle}".', - 'understand' => 'Entenc, vull eliminar {contributor} de "{podcastTitle}"', - 'submit' => 'Suprimeix', + 'roles' => [ + 'podcast_admin' => 'Administrador del podcast', ], 'messages' => [ - 'editSuccess' => 'El rol ha canviat correctament!', - 'editOwnerError' => "No pots editar el propietari del podcast!", 'removeOwnerError' => "No podeu eliminar al propietari del podcast!", 'removeSuccess' => 'S\'ha eliminat a {username} de {podcastTitle}', diff --git a/modules/Admin/Language/ca/Episode.php b/modules/Admin/Language/ca/Episode.php index ba0ff1f2..ed05a8d7 100644 --- a/modules/Admin/Language/ca/Episode.php +++ b/modules/Admin/Language/ca/Episode.php @@ -22,17 +22,16 @@ return [ 'all_podcast_episodes' => 'Tots els episodis del podcast', 'back_to_podcast' => 'Tornar al podcast', 'edit' => 'Editar', - 'preview' => 'Preview', 'publish' => 'Publicar', 'publish_edit' => 'Editar la publicació', - 'publish_date_edit' => 'Edita la data de publicació', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Desfer la publicació', 'publish_error' => 'L\'episodi ja està publicat.', 'publish_edit_error' => 'L\'episodi ja està publicat.', 'publish_cancel_error' => 'L\'episodi ja està publicat.', - 'publish_date_edit_error' => 'L\'episodi encara no s\'ha publicat, no podeu editar-ne la data de publicació.', - 'publish_date_edit_future_error' => 'La data de publicació de l\'episodi només es pot establir en una data passada! Si voleu reprogramar-lo, cancel·leu-lo primer.', - 'publish_date_edit_success' => 'La data de publicació de l\'episodi ha estat actualitzada correctament!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'L\'episodi no està publicat.', 'delete' => 'Eliminar', 'go_to_page' => 'Anar a la pàgina ', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episodi', 'visibility' => 'Visibilitat', - 'downloads' => 'Downloads', 'comments' => 'Comentaris', 'actions' => 'Accions', ], @@ -81,13 +79,13 @@ return [ audio {l\'àudio} other {el material} } de l\'episodi.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', + 'deleteFileError' => 'No s\'ha pogut esborrar el fitxer {file_path} {type, select, + transcript {de la transcripció} + chapters {dels episodis} + image {de la portada} + audio {de l\'àudio} + other {del material} + }. Podeu esborrar-los manualment del disc.', 'sameSlugError' => 'Ja existeix un episodi amb aquest àlies.', ], 'form' => [ @@ -115,8 +113,8 @@ return [ 'bonus' => 'Bonificació', 'bonus_hint' => 'Contingut addicional per al programa (per exemple, informació entre bastidors o entrevistes amb el repartiment) o contingut promocional creuat per a un altre programa', ], - 'premium_title' => 'Prèmium', - 'premium' => 'L\'episodi ha de ser accessible només per a subscriptors prèmium', + 'premium_title' => 'Premium', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Avís parental', 'hint' => 'L\'episodi conté contingut explícit?', @@ -139,9 +137,9 @@ return [ 'location_name' => 'Nom i adreça de la ubicació', 'location_name_hint' => 'Pot ser una ubicació real o fictícia', 'transcript' => 'Transcripció (subtítols)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Només es permet fitxers .srt', 'transcript_download' => 'Baixar la transcripció', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Fitxer de la transcripció (.srt)', 'transcript_remote_url' => 'URL remota per a la transcripció', 'transcript_file_delete' => 'Eliminar el fitxer de la transcripció', 'chapters' => 'Capítols', @@ -185,9 +183,9 @@ return [ 'message_warning_submit' => 'Publicar de totes maneres', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nova data de publicació', - 'new_publication_date_hint' => 'Has de posar una data passada.', - 'submit' => 'Edita la data de publicació', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => @@ -212,14 +210,4 @@ return [ 'light' => 'Clar', 'light-transparent' => 'Clar i transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/ca/MyAccount.php b/modules/Admin/Language/ca/MyAccount.php similarity index 100% rename from modules/Auth/Language/ca/MyAccount.php rename to modules/Admin/Language/ca/MyAccount.php diff --git a/modules/Admin/Language/ca/Navigation.php b/modules/Admin/Language/ca/Navigation.php index 5fc3659b..77b48aee 100644 --- a/modules/Admin/Language/ca/Navigation.php +++ b/modules/Admin/Language/ca/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Ocultar/mostrar barra lateral', 'go_to_website' => 'Anar al lloc web', 'go_to_admin' => 'Anar al panell de control', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Panell de control', 'admin' => 'Inici', 'podcasts' => 'Podcasts', 'podcast-list' => 'Tots els podcasts', 'podcast-create' => 'Nou podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Importar un podcast', 'persons' => 'Persones', 'person-list' => 'Totes les persones', 'person-create' => 'Persona nova', @@ -35,7 +33,6 @@ return [ 'settings' => 'Preferències', 'settings-general' => 'General', 'settings-theme' => 'Tema', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'El meu compte', 'change-password' => 'Canviar la contrasenya', diff --git a/modules/Admin/Language/ca/Notifications.php b/modules/Admin/Language/ca/Notifications.php index 35032ab1..bd1849f5 100644 --- a/modules/Admin/Language/ca/Notifications.php +++ b/modules/Admin/Language/ca/Notifications.php @@ -13,7 +13,7 @@ return [ 'reply' => '{actor_username} ha respost a la vostra publicació', 'favourite' => '{actor_username} ha marcat com a preferit la vostra publicació', 'reblog' => '{actor_username} ha compartit la vostra publicació', - 'follow' => '{actor_username} t\'ha començat a seguir', + 'follow' => '{actor_username} started following you', 'no_notifications' => 'Cap notificació', 'mark_all_as_read' => 'Marca tot com a llegit', ]; diff --git a/modules/Admin/Language/ca/Platforms.php b/modules/Admin/Language/ca/Platforms.php index cfa50efb..cb1abfff 100644 --- a/modules/Admin/Language/ca/Platforms.php +++ b/modules/Admin/Language/ca/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Plataformes', 'home_url' => 'Visitar el lloc web de {platformName}', - 'register' => 'Register', 'submit_url' => 'Enviar el vostre podcast a {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Mostrar a la pàgina d\'inici del podcast?', 'on_embed' => 'Mostrar al reproductor incrustable?', 'remove' => 'Suprimir {platformName}', diff --git a/modules/Admin/Language/ca/Podcast.php b/modules/Admin/Language/ca/Podcast.php index 022e8797..71772510 100644 --- a/modules/Admin/Language/ca/Podcast.php +++ b/modules/Admin/Language/ca/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No s\'han trobat podcasts!', 'create' => 'Crear un podcast', 'import' => 'Importar el podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'Nou episodi', 'view' => 'Veure el podcast', 'edit' => 'Editar el podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Suprimir el podcast', 'see_episodes' => 'Veure els episodis', 'see_contributors' => 'Veure els col·laboradors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Anar a la pàgina ', 'latest_episodes' => 'Darrers episodis', 'see_all_episodes' => 'Veure tots els episodis', @@ -50,6 +48,7 @@ return [ other {s\'han afegit # episodis} } al podcast.', 'podcastFeedUpToDate' => 'El podcast ja està actualitzat.', + 'podcastNotImported' => 'No s\'ha pogut actualitzar el podcast perquè no s\'havia importat.', 'publishError' => 'Aquest podcast ja està publicat o bé està programat per a la seva publicació.', 'publishEditError' => 'Aquest podcast no està programat per a la seva publicació.', 'publishCancelSuccess' => 'La publicació del podcast s\'ha cancel·lat correctament.', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Identitat del podcast', 'identity_section_subtitle' => 'Aquests camps permeten fer-se notar.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Portada del podcast', 'cover_size_hint' => 'La portada ha de ser quadrada i com a mínim de 1400 px d\'amplada i alçada.', 'banner' => 'Bàner del podcast', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episòdic', 'episodic_hint' => 'Si els episodis estan pensats per ser consumits sense cap ordre específic. Els episodis més recents es presentaran primer.', 'serial' => 'En sèrie', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'Si els episodis estan pensats per ser consumits en ordre seqüencial. Primer es presentaran els episodis més antics.', ], 'description' => 'Descripció', 'classification_section_title' => 'Classificació', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Correu electrònic del propietari', 'owner_email_hint' => 'La majoria de plataformes l\'utilitzaran per verificar la propietat del podcast. Visible al fil RSS públic.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Editor', 'publisher_hint' => 'El grup encarregat de crear el programa. Sovint es refereix a l\'empresa matriu o a la xarxa d\'un podcast. Aquest camp de vegades s\'etiqueta com a "Autor".', @@ -122,14 +107,9 @@ return [ 'monetization_section_title' => 'Monetització', 'monetization_section_subtitle' => 'Guanyeu diners gràcies al vostre públic.', - 'premium' => 'Prèmium', - 'premium_by_default' => 'Els episodis s\'han d\'establir com a prèmium de manera predeterminada', - 'premium_by_default_hint' => 'Els episodis de pòdcast es marcaran com a prèmium de manera predeterminada. Encara podreu escollir configurar alguns episodis, tràilers o bonificacions com a públics.', - 'op3' => 'Projecte obert de prefix de pòdcast (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Valoreu les vostres dades estadístiques amb OP3, un servei d\'anàlisi de tercers de codi obert i de confiança. Compartiu, valideu i compareu les vostres dades d\'anàlisi amb l\'ecosistema de podcasting obert.', - 'op3_enable' => 'Habilita el servei d\'estadístiques OP3', - 'op3_enable_hint' => 'Per motius de seguretat, les dades d\'anàlisi dels episodis prèmium no es compartiran amb OP3.', + 'premium' => 'Premium', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', 'payment_pointer' => '`Payment Pointer` per a `Web Monetization`', 'payment_pointer_hint' => 'Aquí és on rebreu diners gràcies al servei `Web Monetization`', @@ -138,12 +118,11 @@ return [ 'Si necessiteu etiquetes RSS que Castopod no manega, configureu-les aquí.', 'custom_rss' => 'Etiquetes RSS personalitzades per al podcast', 'custom_rss_hint' => 'Això s\'injectarà dins de l\'etiqueta ❬channel❭.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'Nova adreça URL del fil RSS', 'new_feed_url_hint' => 'Utilitzeu aquest camp quan us moveu a un altre domini o plataforma d\'allotjament de podcasts. De manera predeterminada, el valor s\'estableix a l\'URL RSS actual si s\'importa el podcast.', 'old_feed_url' => 'Antiga adreça URL del fil RSS', + 'update_feed' => 'Actualitzar el fil', + 'update_feed_tip' => 'Importar els darrers episodis d\'aquest podcast', 'partnership' => 'Socis', 'partner_id' => 'ID', 'partner_link_url' => 'URL de l\'enllaç', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'El vostre propi ID de soci', 'partner_link_url_hint' => 'L\'adreça genèrica de l\'enllaç del soci', 'partner_image_url_hint' => 'L\'adreça genèrica de la imatge del soci', + 'status_section_title' => 'Estat', 'block' => 'El podcast s\'ha d\'amagar als catàlegs públics', 'block_hint' => 'L\'estat de visibilitat del podcast: activar aquesta opció evita que el podcast aparegui a Apple Podcasts, Google Podcasts i qualsevol aplicació de tercers que extreu programes d\'aquests directoris. (No garantit)', diff --git a/modules/Admin/Language/ca/PodcastImport.php b/modules/Admin/Language/ca/PodcastImport.php new file mode 100644 index 00000000..81de5fdf --- /dev/null +++ b/modules/Admin/Language/ca/PodcastImport.php @@ -0,0 +1,37 @@ + + 'Aquest procediment pot trigar molt de temps. Com que la versió actual no mostra cap progrés mentre s\'executa, no veureu res actualitzat fins que no s\'hagi fet. En cas d\'error de temps d\'espera, augmenteu el valor `max_execution_time` a la configuració del PHP del servidor.', + 'old_podcast_section_title' => 'El podcast a importar', + 'old_podcast_section_subtitle' => + 'Assegura\'t de tenir els drets d\'aquest podcast abans d\'importar-lo. Copiar i difondre un podcast sense els drets adequats és pirateria i pot ser processat.', + 'imported_feed_url' => 'Adreça URL del fil', + 'imported_feed_url_hint' => 'El contingut del fil ha d\'estar en format xml o rss.', + 'new_podcast_section_title' => 'El nou podcast', + 'advanced_params_section_title' => 'Paràmetres avançats', + 'advanced_params_section_subtitle' => + 'Mantingueu els valors predeterminats si no teniu idea de per a què serveixen els camps.', + 'slug_field' => 'Camp que s\'utilitzarà per calcular l\'àlies d\'un episodi', + 'description_field' => + 'Camp d\'origen utilitzat per a la descripció de l\'episodi / notes del programa', + 'force_renumber' => 'Forçar la renumeració dels episodis', + 'force_renumber_hint' => + 'Utilitzeu aquesta funcionalitat si el vostre podcast no té números d\'episodi però voleu configurar-los durant la importació.', + 'season_number' => 'Número de temporada', + 'season_number_hint' => + 'Utilitzeu aquesta opció si el vostre podcast no té un número de temporada però voleu establir-ne un durant la importació. Deixeu en blanc en cas contrari.', + 'max_episodes' => 'Nombre màxim d\'episodis per importar', + 'max_episodes_hint' => 'Deixeu en blanc per importar tots els episodis', + 'lock_import' => + 'Aquest feed està protegit. No el podeu importar. Si sou el propietari, desprotegiu-lo a la plataforma d\'origen.', + 'submit' => 'Importar el podcast', +]; diff --git a/modules/Admin/Language/ca/PodcastNavigation.php b/modules/Admin/Language/ca/PodcastNavigation.php index bcbc8120..e2e57dfb 100644 --- a/modules/Admin/Language/ca/PodcastNavigation.php +++ b/modules/Admin/Language/ca/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Anar a la pàgina del podcast', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Panell de control del podcast', 'podcast-view' => 'Inici', 'podcast-edit' => 'Editar el podcast', 'podcast-persons-manage' => 'Administrar persones', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodis', 'episode-list' => 'Tots els episodis', 'episode-create' => 'Nou episodi', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Reproductors', 'podcast-analytics-listening-time' => 'Temps d\'escolta', 'podcast-analytics-time-periods' => 'Períodes de temps', - 'monetization' => 'Monetization', - 'subscription-list' => 'Totes les subscripcions', - 'subscription-create' => 'Add subscription', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', 'contributors' => 'Col·laboradors', 'contributor-list' => 'Tots els col·laboradors', 'contributor-add' => 'Afegir un col·laborador', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'Plataformes de tercers', + 'platforms-podcasting' => 'Podcasts', 'platforms-social' => 'Xarxes socials', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Financiació', ]; diff --git a/modules/Auth/Language/ca/User.php b/modules/Admin/Language/ca/User.php similarity index 74% rename from modules/Auth/Language/ca/User.php rename to modules/Admin/Language/ca/User.php index c269cfa4..9e2f172a 100644 --- a/modules/Auth/Language/ca/User.php +++ b/modules/Admin/Language/ca/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Editeu el rol de {username}", + 'edit_roles' => "Editar els rols de {username}", + 'forcePassReset' => 'Força el restabliment de la contrasenya', 'ban' => 'Bandejar', 'unban' => 'Re-admetre', 'delete' => 'Eliminar', @@ -18,7 +19,7 @@ return [ 'all_users' => 'Tots els usuaris', 'list' => [ 'user' => 'Usuari', - 'role' => 'Rol', + 'roles' => 'Rols', 'banned' => 'Bandejat?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Nom de l\'usuari', 'password' => 'Contrasenya', 'new_password' => 'Nova contrasenya', - 'role' => 'Rol', 'roles' => 'Rols', 'permissions' => 'Permisos', 'submit_create' => 'Crea un usuari', 'submit_edit' => 'Desar', 'submit_password_change' => 'Canviat!', ], - 'delete_form' => [ - 'title' => 'Suprimeix {user}', - 'disclaimer' => - "Esteu a punt de suprimir {user} permanentment. Ja no podrà accedir a l'àrea d'administració.", - 'understand' => 'Entenc, vull suprimir {user} permanentment', - 'submit' => 'Suprimeix', + 'roles' => [ + 'superadmin' => 'Super administrador/a', ], 'messages' => [ 'createSuccess' => 'S\'ha creat l\'usuari! Es demanarà a {username} un restabliment de la contrasenya durant la primera autenticació.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "S'han actualitzat correctament els rols de {username}.", + 'forcePassResetSuccess' => + 'Es demanarà a {username} un restabliment de contrasenya durant la següent visita.', 'banSuccess' => '{username} ha estat bandejat.', 'unbanSuccess' => '{username} ha estat desbandejat.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} és un superadministrador, hom simplement no bandeja a un superadministrador...', - 'deleteOwnerError' => - '{username} és el propietari de la instància, un no pot suprimir senzillament el propietari…', 'deleteSuperAdminError' => '{username} és un superadministrador, hom simplement no elimina a un superadministrador...', 'deleteSuccess' => '{username} ha estat eliminat.', diff --git a/modules/Admin/Language/ca/Validation.php b/modules/Admin/Language/ca/Validation.php index fc83ea02..6740204a 100644 --- a/modules/Admin/Language/ca/Validation.php +++ b/modules/Admin/Language/ca/Validation.php @@ -13,5 +13,6 @@ return [ '{field} no és una imatge, o no és prou ample o alt.', 'is_image_ratio' => '{field} no és una imatge o no té la proporció correcta.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'El camp {field} ha de ser una adreça URL vàlida (p. ex., https://exemple.com/).', ]; diff --git a/modules/Admin/Language/da/AboutCastopod.php b/modules/Admin/Language/da/AboutCastopod.php deleted file mode 100644 index 7ac4aeca..00000000 --- a/modules/Admin/Language/da/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Om Castopod', - 'host_name' => 'Værtsnavn', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operativsystem', - 'languages' => 'Sprog', - 'update_database' => 'Opdater databasen', - 'messages' => [ - 'databaseUpdateSuccess' => 'Databasen er opdateret!', - ], -]; diff --git a/modules/Admin/Language/da/Breadcrumb.php b/modules/Admin/Language/da/Breadcrumb.php deleted file mode 100644 index f02c83ac..00000000 --- a/modules/Admin/Language/da/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'brødkrumme', - config('Admin') - ->gateway => 'Hjem', - 'podcasts' => 'podcasts', - 'episodes' => 'episoder', - 'subscriptions' => 'abonnementer', - 'contributors' => 'bidragydere', - 'pages' => 'sider', - 'settings' => 'indstillinger', - 'theme' => 'tema', - 'about' => 'om', - 'add' => 'tilføj', - 'new' => 'ny', - 'edit' => 'redigér', - 'persons' => 'personer', - 'publish' => 'publicér', - 'publish-edit' => 'redigér udgivelse', - 'publish-date-edit' => 'redigér udgivelsesdato', - 'unpublish' => 'afpublicér', - 'delete' => 'slet', - 'remove' => 'fjern', - 'fediverse' => 'fediverset', - 'blocked-actors' => 'blokerede aktører', - 'blocked-domains' => 'blokerede domæner', - 'users' => 'brugere', - 'my-account' => 'min konto', - 'change-password' => 'skift adgangskode', - 'imports' => 'importer', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforme', - 'social' => 'sociale netværk', - 'funding' => 'finansiering', - 'monetization-other' => 'other monetization', - 'analytics' => 'analyse', - 'locations' => 'lokationer', - 'webpages' => 'websider', - 'unique-listeners' => 'unikke lyttere', - 'players' => 'afspillere', - 'listening-time' => 'lyttetid', - 'time-periods' => 'periode', - 'soundbites' => 'lydbid', - 'video-clips' => 'videoklip', - 'embed' => 'integreret afspiller', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/da/Charts.php b/modules/Admin/Language/da/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/da/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/da/Common.php b/modules/Admin/Language/da/Common.php deleted file mode 100644 index b53eff26..00000000 --- a/modules/Admin/Language/da/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Indlæser…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/da/Countries.php b/modules/Admin/Language/da/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/da/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/da/Episode.php b/modules/Admin/Language/da/Episode.php deleted file mode 100644 index 7fad23ff..00000000 --- a/modules/Admin/Language/da/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episoden er allerede publiceret.', - 'publish_cancel_error' => 'Episoden er allerede publiceret.', - 'publish_date_edit_error' => 'Episode er endnu ikke blevet offentliggjort. Du kan ikke redigere dens publiceringsdato.', - 'publish_date_edit_future_error' => 'Episodes publiceringsdato kan kun indstilles til en tidligere dato! Hvis du ønsker at omlægge den, så afpublicér den først.', - 'publish_date_edit_success' => 'Episodens udgivelsesdato er blevet opdateret!', - 'unpublish_error' => 'Episoden er ikke publiceret.', - 'delete' => 'Slet', - 'go_to_page' => 'Gå til side', - 'create' => 'Tilføj en episode', - 'publication_status' => [ - 'published' => 'Udgivet', - 'with_podcast' => 'Udgivet', - 'scheduled' => 'Planlagt', - 'not_published' => 'Ikke offentliggjort', - ], - 'with_podcast_hint' => 'Skal offentliggøres samtidig med podcasten', - 'list' => [ - 'search' => [ - 'placeholder' => 'Søg efter en episode', - 'clear' => 'Ryd søgning', - 'submit' => 'Søg', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episoder} - }', - 'episode' => 'Episode', - 'visibility' => 'Synlighed', - 'downloads' => 'Downloads', - 'comments' => 'Kommentarer', - 'actions' => 'Handlinger', - ], - 'messages' => [ - 'createSuccess' => 'Episoden er blevet oprettet!', - 'editSuccess' => 'Episoden er blevet opdateret!', - 'publishSuccess' => '{publication_status, select, - published {Episode udgivet!} - scheduled {Episodeudgivelse planlagt!} - with_podcast {Denne episode vil blive offentliggjort samtidig med podcasten.} - other {Denne episode er ikke offentliggjort.} - }', - 'publishCancelSuccess' => 'Udgivelsen blev annulleret!', - 'unpublishBeforeDeleteTip' => 'Du skal afpublicere episoden, før du sletter den.', - 'scheduleDateError' => 'Udgivelsesdato skal være sat!', - 'deletePublishedEpisodeError' => 'Afpublicér venligst episoden, før du sletter den.', - 'deleteSuccess' => 'Episode slettet succesfuldt!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/da/EpisodeNavigation.php b/modules/Admin/Language/da/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/da/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/da/Fediverse.php b/modules/Admin/Language/da/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/da/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/da/Home.php b/modules/Admin/Language/da/Home.php deleted file mode 100644 index 3ff4c04d..00000000 --- a/modules/Admin/Language/da/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found', -]; diff --git a/modules/Admin/Language/da/Install.php b/modules/Admin/Language/da/Install.php deleted file mode 100644 index 36e373a2..00000000 --- a/modules/Admin/Language/da/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/da/Navigation.php b/modules/Admin/Language/da/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/da/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/da/Page.php b/modules/Admin/Language/da/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/da/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/da/Pager.php b/modules/Admin/Language/da/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/da/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/da/Person.php b/modules/Admin/Language/da/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/da/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/da/Platforms.php b/modules/Admin/Language/da/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/da/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/da/Podcast.php b/modules/Admin/Language/da/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/da/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/da/PodcastNavigation.php b/modules/Admin/Language/da/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/da/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/da/Settings.php b/modules/Admin/Language/da/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/da/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/da/Soundbite.php b/modules/Admin/Language/da/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/da/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/da/Validation.php b/modules/Admin/Language/da/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/da/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/da/VideoClip.php b/modules/Admin/Language/da/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/da/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/de/AboutCastopod.php b/modules/Admin/Language/de/AboutCastopod.php deleted file mode 100644 index 7e8780ad..00000000 --- a/modules/Admin/Language/de/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Über Castopod', - 'host_name' => 'Hostname', - 'version' => 'Castopod Version', - 'php_version' => 'PHP Version', - 'os' => 'Betriebssystem', - 'languages' => 'Sprachen', - 'update_database' => 'Datenbank aktualisieren', - 'messages' => [ - 'databaseUpdateSuccess' => 'Die Datenbank ist aktuell!', - ], -]; diff --git a/modules/Admin/Language/de/Breadcrumb.php b/modules/Admin/Language/de/Breadcrumb.php index 986f03dd..2bf0fc70 100644 --- a/modules/Admin/Language/de/Breadcrumb.php +++ b/modules/Admin/Language/de/Breadcrumb.php @@ -14,44 +14,39 @@ return [ ->gateway => 'Startseite', 'podcasts' => 'Podcasts', 'episodes' => 'Folgen', - 'subscriptions' => 'Abonnements', - 'contributors' => 'Mitwirkende', + 'subscriptions' => 'subscriptions', + 'contributors' => 'Administratoren', 'pages' => 'Seiten', 'settings' => 'Einstellungen', 'theme' => 'Erscheinungsbild', - 'about' => 'Über', 'add' => 'hinzufügen', 'new' => 'neu', 'edit' => 'bearbeiten', 'persons' => 'Mitwirkende', 'publish' => 'veröffentlichen', 'publish-edit' => 'Veröffentlichung bearbeiten', - 'publish-date-edit' => 'Veröffentlichungsdatum bearbeiten', - 'unpublish' => 'zurückziehen', + 'publish-date-edit' => 'edit publication date', + 'unpublish' => 'Veröffentlichung aufheben', 'delete' => 'löschen', - 'remove' => 'Entfernen', 'fediverse' => 'Fediversum', - 'blocked-actors' => 'blockierte Konten', - 'blocked-domains' => 'Blockierte Domains', + 'block-lists' => 'Sperrlisten', 'users' => 'Benutzer', 'my-account' => 'Mein Konto', 'change-password' => 'Passwort ändern', - 'imports' => 'Importe', - 'sync-feeds' => 'Feeds synchronisieren', + 'import' => 'Feed-Import', 'platforms' => 'Plattformen', 'social' => 'soziale Netzwerke', 'funding' => 'Finanzierung', - 'monetization-other' => 'sonstige Monetarisierung', - 'analytics' => 'Statistiken', + 'analytics' => 'Analysen', 'locations' => 'Orte', 'webpages' => 'Webseiten', - 'unique-listeners' => 'eindeutige Zuhörer', + 'unique-listeners' => 'einzigartige Zuhörer', 'players' => 'Podcast-Player', 'listening-time' => 'Hörzeit', 'time-periods' => 'Zeiträume', 'soundbites' => 'Tonschnipsel', 'video-clips' => 'Videoclips', 'embed' => 'einbettbarer Spieler', - 'notifications' => 'Benachrichtigungen', - 'suspend' => 'Unterbrechen', + 'notifications' => 'notifications', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/de/Charts.php b/modules/Admin/Language/de/Charts.php index 89cea21b..c96b1dcb 100644 --- a/modules/Admin/Language/de/Charts.php +++ b/modules/Admin/Language/de/Charts.php @@ -15,8 +15,8 @@ return [ 'by_device_weekly' => 'Downloads von Folgen nach Gerät (für die vergangene Woche)', 'by_os_weekly' => 'Downloads von Folgen nach Betriebssystem (für die vergangene Woche)', 'podcast_by_region' => 'Downloads von Folgen nach Region (für die vergangene Woche)', - 'unique_daily_listeners' => 'Tägliche eindeutige Zuhörer', - 'unique_monthly_listeners' => 'Monatliche eindeutige Zuhörer', + 'unique_daily_listeners' => 'Tägliche einzigartige Zuhörer', + 'unique_monthly_listeners' => 'Monatliche einzigartige Zuhörer', 'by_browser' => 'Nutzung der Webseiten nach Browser (für die vergangene Woche)', 'podcast_by_day' => 'Tägliche Downloads von Folgen', 'podcast_by_month' => 'Monatliche Downloads von Folgen', @@ -35,7 +35,6 @@ return [ 'by_weekday' => 'Nach Wochentag (für die letzten 60 Tage)', 'by_hour' => 'Nach Tageszeit (für die letzten 60 Tage)', 'podcast_by_bandwidth' => 'Täglich genutzte Bandbreite (in MB)', - 'total_storage_by_month' => 'Monatlicher Speicher (in MB)', - 'total_bandwidth_by_month' => 'Monatlich genutzte Bandbreite (in MB)', - 'total_bandwidth_by_month_limit' => 'Begrenzt auf {totalBandwidth} pro Monat', + 'total_storage_by_month' => 'Monthly storage (in MB)', + 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', ]; diff --git a/modules/Admin/Language/de/Common.php b/modules/Admin/Language/de/Common.php index cc668a33..f9b6a99c 100644 --- a/modules/Admin/Language/de/Common.php +++ b/modules/Admin/Language/de/Common.php @@ -21,7 +21,7 @@ return [ 'copied' => 'Kopiert!', 'home' => 'Startseite', 'explicit' => 'Anstößig', - 'powered_by' => 'Betrieben mit {castopod}', + 'powered_by' => 'Betrieben durch {castopod}', 'actions' => 'Aktionen', 'pageInfo' => 'Seite {currentPage} von {pageCount}', 'go_back' => 'Zurück', @@ -40,13 +40,12 @@ return [ ], 'upload_file' => 'Eine Datei hochladen', 'remote_url' => 'Externe URL', - 'save' => 'Speichern', ], 'play_episode_button' => [ 'play' => 'Abspielen', 'playing' => 'Spielt', ], 'size_limit' => 'Größenlimit: {0}.', - 'choose_interact' => 'Wählen Sie, wie Sie interagieren möchten', - 'view' => 'Ansicht', + 'choose_interact' => 'Choose how to interact', + 'view' => 'View', ]; diff --git a/modules/Auth/Language/de/Contributor.php b/modules/Admin/Language/de/Contributor.php similarity index 60% rename from modules/Auth/Language/de/Contributor.php rename to modules/Admin/Language/de/Contributor.php index 27ff60dc..c21e05b8 100644 --- a/modules/Auth/Language/de/Contributor.php +++ b/modules/Admin/Language/de/Contributor.php @@ -10,9 +10,9 @@ declare(strict_types=1); return [ 'podcast_contributors' => 'Podcast-Administratoren', - 'view' => "{username}'s Mitwirkung an {podcastTitle}", - 'add' => 'Mitwirkenden zufügen', - 'add_contributor' => 'Mitwirkenden zufügen für {0}', + 'view' => "{username}'s Administration von {podcastTitle}", + 'add' => 'Adminstrator zufügen', + 'add_contributor' => 'Administrator zufügen für {0}', 'edit_role' => 'Rolle aktualisieren für {0}', 'edit' => 'Bearbeiten', 'remove' => 'Entfernen', @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Administrator zufügen', 'submit_edit' => 'Rolle aktualisieren', ], - 'delete_form' => [ - 'title' => '{contributor} entfernen', - 'disclaimer' => - 'Sie sind dabei, {contributor} von den Mitwirkenden zu entfernen. Es wird kein Zugriff mehr auf "{podcastTitle}" möglich sein.', - 'understand' => 'Ich verstehe, ich möchte {contributor} von "{podcastTitle}" entfernen', - 'submit' => 'Entfernen', + 'roles' => [ + 'podcast_admin' => 'Podcast Administrator', ], 'messages' => [ - 'editSuccess' => 'Rolle erfolgreich geändert!', - 'editOwnerError' => "Sie können den Podcast-Besitzer nicht verändern!", 'removeOwnerError' => "Der Podcast Inhaber kann nicht entfernt werden!", 'removeSuccess' => '{username} wurde von {podcastTitle} entfernt', diff --git a/modules/Admin/Language/de/Dashboard.php b/modules/Admin/Language/de/Dashboard.php index 2b539a71..881073fd 100644 --- a/modules/Admin/Language/de/Dashboard.php +++ b/modules/Admin/Language/de/Dashboard.php @@ -9,20 +9,20 @@ declare(strict_types=1); */ return [ - 'home' => 'Admin-Dashboard', - 'welcome_message' => 'Willkommen im Administrationsbereich!', + 'home' => 'Admin dashboard', + 'welcome_message' => 'Welcome to the admin area!', 'podcasts' => [ 'title' => 'Podcasts', - 'not_found' => 'Kein veröffentlichter Podcast', - 'last_published' => 'Zuletzt veröffentlicht am {lastPublicationDate}', + 'not_found' => 'No published podcast', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'episodes' => [ - 'title' => 'Folgen', - 'not_found' => 'Keine veröffentlichte Episode', - 'last_published' => 'Zuletzt veröffentlicht am {lastPublicationDate}', + 'title' => 'Episodes', + 'not_found' => 'No published episode', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'storage' => [ - 'title' => 'Speicher', - 'subtitle' => '{totalUploaded} von {totalStorage}', + 'title' => 'Storage', + 'subtitle' => '{totalUploaded} out of {totalStorage}', ], ]; diff --git a/modules/Admin/Language/de/Episode.php b/modules/Admin/Language/de/Episode.php index 15009e31..d20fd716 100644 --- a/modules/Admin/Language/de/Episode.php +++ b/modules/Admin/Language/de/Episode.php @@ -13,7 +13,7 @@ return [ 'season_abbr' => 'S{seasonNumber}', 'number' => 'Folge {episodeNumber}', 'number_abbr' => 'F. {episodeNumber}', - 'season_episode' => 'Staffel {seasonNumber} Folge {episodeNumber}', + 'season_episode' => 'Staffel {seasonNumber} episode {episodeNumber}', 'season_episode_abbr' => 'S{seasonNumber}F{episodeNumber}', 'number_of_comments' => '{numberOfComments, plural, one {# Kommentar} @@ -22,28 +22,27 @@ return [ 'all_podcast_episodes' => 'Alle Podcast-Episoden', 'back_to_podcast' => 'Zurück zum Podcast', 'edit' => 'Bearbeiten', - 'preview' => 'Vorschau', 'publish' => 'Veröffentllichen', 'publish_edit' => 'Veröffentlichung bearbeiten', - 'publish_date_edit' => 'Veröffentlichungsdatum bearbeiten', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Veröffentlichung zurücknehmen', 'publish_error' => 'Folge ist bereits veröffentlicht.', 'publish_edit_error' => 'Folge ist bereits veröffentlicht.', 'publish_cancel_error' => 'Folge ist bereits veröffentlicht.', - 'publish_date_edit_error' => 'Die Folge wurde noch nicht veröffentlicht, Sie können das Veröffentlichungsdatum nicht bearbeiten.', - 'publish_date_edit_future_error' => 'Das Veröffentlichungsdatum der Folge kann nur auf ein vergangenes Datum gesetzt werden! Wenn Sie es neu planen möchten, heben Sie die Veröffentlichung zuerst auf.', - 'publish_date_edit_success' => 'Das Veröffentlichungsdatum der Folge wurde erfolgreich aktualisiert!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'Folge ist nicht veröffentlicht.', 'delete' => 'Löschen', 'go_to_page' => 'Gehe zu Seite', 'create' => 'Folge hinzufügen', 'publication_status' => [ 'published' => 'Veröffentlicht', - 'with_podcast' => 'Veröffentlicht', + 'with_podcast' => 'Published', 'scheduled' => 'Geplant', 'not_published' => 'Nicht veröffentlicht', ], - 'with_podcast_hint' => 'Wird zeitgleich mit dem Podcast veröffentlicht', + 'with_podcast_hint' => 'To be published at the same time as the podcast', 'list' => [ 'search' => [ 'placeholder' => 'Suche nach einer Episode', @@ -51,43 +50,42 @@ return [ 'submit' => 'Suche', ], 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# Folge} - other {# Folgen} + one {# episode} + other {# episodes} }', 'episode' => 'Folge', - 'visibility' => 'Sichtbarkeit', - 'downloads' => 'Downloads', - 'comments' => 'Kommentar', + 'visibility' => 'Sichtweite', + 'comments' => 'Komemntar', 'actions' => 'Aktionen', ], 'messages' => [ 'createSuccess' => 'Folge wurde erfolgreich erstellt!', 'editSuccess' => 'Folge wurde erfolgreich aktualisiert!', 'publishSuccess' => '{publication_status, select, - published {Folge erfolgreich veröffentlicht!} - scheduled {Veröffentlichung der Folge erfolgreich geplant!} - with_podcast {Diese Folge wird zeitgleich mit dem Podcast veröffentlicht.} - other {Diese Folge ist nicht veröffentlicht.} + published {Episode successfully published!} + scheduled {Episode publication successfully scheduled!} + with_podcast {This episode will be published at the same time as the podcast.} + other {This episode is not published.} }', - 'publishCancelSuccess' => 'Veröffentlichung der Episode abgebrochen!', + 'publishCancelSuccess' => 'Veröffentlichung der Episode erfolgreich abgebrochen!', 'unpublishBeforeDeleteTip' => 'Du musst die Episode zurückziehen, bevor du sie löschst.', - 'scheduleDateError' => 'Veröffentlichungsdatum muss gesetzt sein!', + 'scheduleDateError' => 'Schedule date must be set!', 'deletePublishedEpisodeError' => 'Bitte ziehe die Episode zurück, bevor du sie löschst.', 'deleteSuccess' => 'Folge erfolgreich gelöscht!', - 'deleteError' => 'Fehler beim Löschen der {type, select, - transcript {Abschrift} - chapters {Kapitel} - image {Cover} - audio {Audio} - other {Medien} - }-Datei dieser Episode.', - 'deleteFileError' => 'Fehler beim Löschen der {type, select, - transcript {Abschrift} - chapters {Kapitel} - image {Cover} - audio {Audio} - other {Medien} - }-Datei {file_key}. Sie können es manuell von der Festplatte entfernen.', + 'deleteError' => 'Failed to delete episode {type, select, + transcript {transcript} + chapters {chapters} + image {cover} + audio {audio} + other {media} + }.', + 'deleteFileError' => 'Failed to delete {type, select, + transcript {transcript} + chapters {chapters} + image {cover} + audio {audio} + other {media} + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'Eine Folge mit dem ausgewählten Slug existiert bereits.', ], 'form' => [ @@ -99,7 +97,7 @@ return [ 'cover' => 'Episoden-Cover', 'cover_hint' => 'Wenn Du kein Cover festlegst, wird stattdessen das Podcast-Cover verwendet.', - 'cover_size_hint' => 'Das Cover muss quadratisch und mindestens 1400px breit und hoch sein.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'title' => 'Titel', 'title_hint' => 'Nutze einen klaren und einprägsamen Episodennamen. Gib hier nicht die Episoden- oder Staffelnummern an.', @@ -116,12 +114,12 @@ return [ 'bonus_hint' => 'Zusätzliche Inhalte für die Sendung (zum Beispiel hinter den Kulissen, Informationen oder Interviews mit dem Team) oder übergreifende Promotionsinhalte für eine andere Show', ], 'premium_title' => 'Premium', - 'premium' => 'Diese Episode darf nur für Premium-Abonnenten zugänglich sein', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ - 'label' => 'Hinweis für Erziehungsberechtigte', + 'label' => 'Elternberatung', 'hint' => 'Enthält die Folge anstößige Inhalte?', 'undefined' => 'undefiniert', - 'clean' => 'Sauber', + 'clean' => 'Zurücksetzen', 'explicit' => 'Anstößig', ], 'show_notes_section_title' => 'Notizen anzeigen', @@ -133,15 +131,15 @@ return [ 'Dieser Text wird am Ende jeder Episodenbeschreibung hinzugefügt, es ist ein guter Ort, um zum Beispiel Ihre sozialen Links einzufügen.', 'additional_files_section_title' => 'Zusätzliche Dateien', 'additional_files_section_subtitle' => - 'Diese Dateien könnten von anderen Plattformen genutzt werden, um eine bessere Nutzererfahrung zu bieten. Weitere Informationen finden Sie unter {podcastNamespaceLink}.', + 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', 'location_section_title' => 'Standort', 'location_section_subtitle' => 'Über welchen Ort handelt diese Folge?', 'location_name' => 'Standortname oder Adresse', 'location_name_hint' => 'Dies kann ein realer oder fiktiver Ort sein', 'transcript' => 'Transkript (Untertitel)', - 'transcript_hint' => 'Nur .srt oder .vtt sind erlaubt.', + 'transcript_hint' => 'Nur .srt ist erlaubt.', 'transcript_download' => 'Transkript herunterladen', - 'transcript_file' => 'Transkriptdatei (.srt oder .vtt)', + 'transcript_file' => 'Transkriptionsdatei (.srt)', 'transcript_remote_url' => 'Remote-URL für Transkript', 'transcript_file_delete' => 'Transkriptionsdatei löschen', 'chapters' => 'Kapitel', @@ -155,9 +153,9 @@ return [ 'Wenn du RSS-Tags benötigst, die Castopod nicht behandelt, setze diese hier.', 'custom_rss' => 'Eigene RSS-Tags für die Episode', 'custom_rss_hint' => 'Dies wird innerhalb des ❬item❭ Tags eingefügt.', - 'block' => 'Episode soll vor öffentlichen Katalogen versteckt werden', + 'block' => 'Episode should be hidden from public catalogues', 'block_hint' => - 'Die Episode zeigt oder versteckt den Status: Beim Einschalten dieser Option wird verhindert, dass die Episode in Apple Podcasts, Google Podcasts und alle Apps von Drittanbietern, die Inhalte aus diesen Verzeichnissen ziehen, erscheint. (Nicht garantiert)', + 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'submit_create' => 'Folge erstellen', 'submit_edit' => 'Folge speichern', ], @@ -171,7 +169,7 @@ return [ 'publication_method' => [ 'now' => 'Jetzt', 'schedule' => 'Zeitplan', - 'with_podcast' => 'Zusammen mit dem Podcast veröffentlichen', + 'with_podcast' => 'Publish alongside podcast', ], 'scheduled_publication_date' => 'Geplantes Veröffentlichungsdatum', 'scheduled_publication_date_clear' => 'Veröffentlichungsdatum löschen', @@ -185,21 +183,21 @@ return [ 'message_warning_submit' => 'Trotzdem veröffentlichen', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Neues Veröffentlichungsdatum', - 'new_publication_date_hint' => 'Muss auf ein vergangenes Datum gesetzt werden.', - 'submit' => 'Veröffentlichungsdatum bearbeiten', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "Das Zurückziehen dieser Episode löscht alle damit verbundenen Kommentare und Beiträge und entferne sie aus dem RSS-Feed des Podcasts.", + "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", 'understand' => 'Ich verstehe, ich möchte die Episode zurückziehen', 'submit' => 'Zurückziehen', ], 'delete_form' => [ 'disclaimer' => - "Das Löschen der Episode wird auch alle verknüpften Mediendateien, Kommentare, Videoclips und Soundbites löschen.", + "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", 'understand' => 'Ich verstehe, ich möchte die Folge löschen', - 'submit' => 'Löschen', + 'submit' => 'Delete', ], 'embed' => [ 'title' => 'Einbettbarer Spieler', @@ -212,14 +210,4 @@ return [ 'light' => 'Hell', 'light-transparent' => 'Hell (transparent)', ], - 'publication_status_banner' => [ - 'draft_mode' => 'Entwurfsmodus', - 'text' => '{publication_status, select, - published {Diese Episode ist noch nicht veröffentlicht.} - scheduled {Diese Episode ist für die Veröffentlichung geplant am {publication_date}.} - with_podcast {Diese Episode wird zur gleichen Zeit wie der Podcast veröffentlicht.} - other {Diese Episode ist noch nicht veröffentlicht.} - }', - 'preview' => 'Vorschau', - ], ]; diff --git a/modules/Admin/Language/de/Fediverse.php b/modules/Admin/Language/de/Fediverse.php index 1c2a060d..5a22c8dc 100644 --- a/modules/Admin/Language/de/Fediverse.php +++ b/modules/Admin/Language/de/Fediverse.php @@ -12,7 +12,7 @@ return [ 'messages' => [ 'actorNotFound' => 'Das Konto konnte nicht gefunden werden!', 'blockActorSuccess' => '{actor} wurde blockiert!', - 'unblockActorSuccess' => 'Benutzer wurde entsperrt!', + 'unblockActorSuccess' => 'Darsteller wurde freigegeben!', 'blockDomainSuccess' => '{domain} wurde blockiert!', 'unblockDomainSuccess' => '{domain} wurde freigegeben!', ], diff --git a/modules/Admin/Language/de/Install.php b/modules/Admin/Language/de/Install.php index 89a8b267..d901d1c5 100644 --- a/modules/Admin/Language/de/Install.php +++ b/modules/Admin/Language/de/Install.php @@ -20,10 +20,10 @@ return [ 'Um optional CDN und/oder einen externen Analysedienst verwenden zu können, müssen die Daten eingegeben werden.', 'admin_gateway' => 'Admin-Gateway', 'admin_gateway_hint' => - 'Der Pfad zum Zugriff auf den Admin-Bereich (z.B. https://example.com/cp-admin). Standardmäßig als cp-admin festgelegt. Wir empfehlen, sie aus Sicherheitsgründen zu ändern.', + 'Die Route zum Zugriff auf den Admin-Bereich (z.B. https://example.com/cp-admin). Standardmäßig als cp-admin festgelegt. Wir empfehlen, sie aus Sicherheitsgründen zu ändern.', 'auth_gateway' => 'Auth-Gateway', 'auth_gateway_hint' => - 'Der Pfad zum Zugriff auf die Authentifizierungsseiten (z. B. https://example.com/cp-auth). Standardmäßig als cp-auth gesetzt. Wir empfehlen, sie aus Sicherheitsgründen zu ändern.', + 'Die Route zum Zugriff auf die Authentifizierungsseiten (z. B. https://example.com/cp-auth). Standardmäßig als cp-auth gesetzt. Wir empfehlen, sie aus Sicherheitsgründen zu ändern.', 'database_config' => 'Datenbankkonfiguration', 'database_config_hint' => 'Castopod muss sich mit der MySQL-Datenbank (oder MariaDB) verbinden. Wenn diese erforderlichen Informationen nicht verfügbar sind, wenden Sie sich bitte an Ihren Serveradministrator.', @@ -31,12 +31,12 @@ return [ 'db_name' => 'Datenbankname', 'db_username' => 'Datenbankbenutzername', 'db_password' => 'Datenbankpasswort', - 'db_prefix' => 'Tabellenpräfix', + 'db_prefix' => 'Datenbankpräfix', 'db_prefix_hint' => - "Das Präfix der Castopod-Tabellennamen. Nicht anpassen, wenn du nicht weißt, was damit gemeint ist.", + "Das Präfix der Castopod-Tabellennamen. Nicht anpassen, wenn nicht gewiss, was damit gemeint ist.", 'cache_config' => 'Cachekonfiguration', 'cache_config_hint' => - 'Wählen Sie Ihren bevorzugten Cache-Handler. Standardwert verwenden, wenn Sie nicht wissen, was damit gemeint ist.', + 'Wählen Sie Ihren bevorzugten Cache-Handler. Standardwert verwenden, wenn nicht gewiss, was damit gemeint ist.', 'cache_handler' => 'Cache-Handler', 'cacheHandlerOptions' => [ 'file' => 'Datei', diff --git a/modules/Auth/Language/de/MyAccount.php b/modules/Admin/Language/de/MyAccount.php similarity index 100% rename from modules/Auth/Language/de/MyAccount.php rename to modules/Admin/Language/de/MyAccount.php diff --git a/modules/Admin/Language/de/Navigation.php b/modules/Admin/Language/de/Navigation.php index f7b7b0ba..04fad137 100644 --- a/modules/Admin/Language/de/Navigation.php +++ b/modules/Admin/Language/de/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Seitenleiste ein/aus', 'go_to_website' => 'Gehe zur Webseite', 'go_to_admin' => 'Gehe zu Admin', - 'not-authorized' => 'Nicht berechtigt', 'dashboard' => 'Übersicht', 'admin' => 'Startseite', 'podcasts' => 'Podcasts', 'podcast-list' => 'Alle Podcasts', 'podcast-create' => 'Neuer Podcast', - 'all-podcast-imports' => 'Alle Podcast-Importe', - 'podcast-imports-add' => 'Podcast importieren', + 'podcast-import' => 'Podcast importieren', 'persons' => 'Mitwirkende', 'person-list' => 'Alle Mitwirkenden', 'person-create' => 'Neuer Mitwirkender', @@ -35,7 +33,6 @@ return [ 'settings' => 'Einstellungen', 'settings-general' => 'Allgemein', 'settings-theme' => 'Erscheinungsbild', - 'admin-about' => 'Über', 'account' => [ 'my-account' => 'Mein Konto', 'change-password' => 'Passwort ändern', diff --git a/modules/Admin/Language/de/Notifications.php b/modules/Admin/Language/de/Notifications.php index 88439bb4..2b139d51 100644 --- a/modules/Admin/Language/de/Notifications.php +++ b/modules/Admin/Language/de/Notifications.php @@ -9,11 +9,11 @@ declare(strict_types=1); */ return [ - 'title' => 'Benachrichtigungen', - 'reply' => '{actor_username} hat auf Ihren Beitrag geantwortet', - 'favourite' => '{actor_username} hat Ihren Beitrag favorisiert', - 'reblog' => '{actor_username} hat Ihren Beitrag geteilt', - 'follow' => '{actor_username} folgt Ihnen jetzt', - 'no_notifications' => 'Keine Benachrichtigungen', - 'mark_all_as_read' => 'Alle als gelesen markieren', + 'title' => 'Notifications', + 'reply' => '{actor_username} replied to your post', + 'favourite' => '{actor_username} favourited your post', + 'reblog' => '{actor_username} shared your post', + 'follow' => '{actor_username} started following you', + 'no_notifications' => 'No notifications', + 'mark_all_as_read' => 'Mark all as read', ]; diff --git a/modules/Admin/Language/de/Page.php b/modules/Admin/Language/de/Page.php index 801ff2e7..e5e5febb 100644 --- a/modules/Admin/Language/de/Page.php +++ b/modules/Admin/Language/de/Page.php @@ -18,7 +18,7 @@ return [ 'delete' => 'Seite löschen', 'form' => [ 'title' => 'Titel', - 'permalink' => 'Permalink', + 'permalink' => 'Permanenter Link', 'content' => 'Inhalt', 'submit_create' => 'Seite erstellen', 'submit_edit' => 'Speichern', diff --git a/modules/Admin/Language/de/Pager.php b/modules/Admin/Language/de/Pager.php index 54c96cbe..d2bddfb6 100644 --- a/modules/Admin/Language/de/Pager.php +++ b/modules/Admin/Language/de/Pager.php @@ -10,10 +10,10 @@ declare(strict_types=1); return [ 'pageNavigation' => 'Seiten-Navigation', - 'first' => 'Erste Seite', - 'previous' => 'Vorherige', - 'next' => 'Nächste', - 'last' => 'Letzte Seite', + 'first' => 'Erste', + 'previous' => 'Zurück', + 'next' => 'Weiter', + 'last' => 'Letzte', 'older' => 'Älter', 'newer' => 'Neuer', 'invalidTemplate' => '{0} ist kein gültiges Pager Template.', diff --git a/modules/Admin/Language/de/Person.php b/modules/Admin/Language/de/Person.php index a9287867..96724be0 100644 --- a/modules/Admin/Language/de/Person.php +++ b/modules/Admin/Language/de/Person.php @@ -24,7 +24,7 @@ return [ 'form' => [ 'avatar' => 'Profilbild', 'avatar_size_hint' => - 'Das Profilbild muss quadratisch und mindestens 400px breit und hoch sein.', + 'Avatar must be squared and at least 400px wide and tall.', 'full_name' => 'Vollständiger Name', 'full_name_hint' => 'Dies ist der vollständige Name oder der Alias der Person.', 'unique_name' => 'Eindeutiger Name', @@ -44,7 +44,7 @@ return [ 'Es können eine oder mehrere Personen mit der gleichen Rolle ausgewählt werden. Die Personen müssen zuerst erstellt werden.', 'roles' => 'Rollen', 'roles_hint' => - 'Es können sowohl keine, eine als auch mehrere Rollen für eine Person ausgewählt werden.', + 'Es können sowhol keine, eine als auch mehrere Rollen für eine Person ausgewählt werden.', 'submit_add' => 'Person:en hinzufügen', 'remove' => 'Entfernen', ], @@ -57,9 +57,9 @@ return [ 'Es können eine oder mehrere Personen mit der gleichen Rolle ausgewählt werden. Die Personen müssen zuerst erstellt werden.', 'roles' => 'Rollen', 'roles_hint' => - 'Es können sowohl keine, eine als auch mehrere Rollen für eine Person ausgewählt werden.', + 'Es können sowhol keine, eine als auch mehrere Rollen für eine Person ausgewählt werden.', 'submit_add' => 'Person:en hinzufügen', 'remove' => 'Entfernen', ], - 'credits' => 'Credits', + 'credits' => 'Danksagungen', ]; diff --git a/modules/Admin/Language/de/Platforms.php b/modules/Admin/Language/de/Platforms.php index 41751316..5e55a2a3 100644 --- a/modules/Admin/Language/de/Platforms.php +++ b/modules/Admin/Language/de/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcast-Plattformen', - 'social' => 'Soziale Medien', - 'funding' => 'Finanzierungslinks', - ], - 'website' => 'Webseite', + 'title' => 'Plattformen', 'home_url' => 'Gehe zu {platformName} Webseite', - 'register' => 'Registrieren', 'submit_url' => 'Sende deinen Podcast an {platformName}', - 'your_link' => 'Dein Link', - 'your_id' => [ - 'podcasting' => 'Deine ID', - 'social' => 'Deine ID', - 'funding' => 'Deine CTA', - ], - 'your_cta' => 'Dein Aufruf zur Aktion', 'visible' => 'Auf Podcast-Homepage anzeigen?', 'on_embed' => 'Auf einbettbarem Player anzeigen?', 'remove' => 'Entferne {platformName}', diff --git a/modules/Admin/Language/de/Podcast.php b/modules/Admin/Language/de/Podcast.php index d2165791..8cff53a1 100644 --- a/modules/Admin/Language/de/Podcast.php +++ b/modules/Admin/Language/de/Podcast.php @@ -13,78 +13,65 @@ return [ 'no_podcast' => 'Kein Podcast gefunden!', 'create' => 'Podcast erstellen', 'import' => 'Podcast importieren', - 'all_imports' => 'Podcast-Importe', 'new_episode' => 'Neue Folge', 'view' => 'Podcast ansehen', 'edit' => 'Podcast bearbeiten', - 'publish' => 'Podcast veröffentlichen', - 'publish_edit' => 'Veröffentlichung bearbeiten', + 'publish' => 'Publish podcast', + 'publish_edit' => 'Edit publication', 'delete' => 'Podcast löschen', 'see_episodes' => 'Episoden ansehen', - 'see_contributors' => 'Mitwirkende anzeigen', - 'monetization_other' => 'Sonstige Monetarisierung', + 'see_contributors' => 'Administratoren anzeigen', 'go_to_page' => 'Gehe zur Seite', 'latest_episodes' => 'Neueste Folgen', 'see_all_episodes' => 'Alle Folgen anzeigen', - 'draft' => 'Entwurf', + 'draft' => 'Draft', 'messages' => [ - 'createSuccess' => 'Podcast erfolgreich erstellt!', + 'createSuccess' => 'Podcast successfully created!', 'editSuccess' => 'Der Podcast wurde erfolgreich aktualisiert!', 'importSuccess' => 'Der Podcast wurde erfolgreich importiert!', - 'deleteSuccess' => 'Podcast @{podcast_handle} erfolgreich gelöscht!', - 'deletePodcastMediaError' => 'Fehler beim Löschen des Podcast-{type, select, - cover {Covers} - banner {Banners} - other {Media} + 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', + 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, + cover {cover} + banner {banner} + other {media} }.', - 'deleteEpisodeMediaError' => 'Fehler beim Löschen {type, select, - transcript {der Abschrift} - chapters {der Kapitel} - image {des Covers} - audio {der Audio} - other {der Medien} - } von Episode {episode_slug}.', - 'deletePodcastMediaFolderError' => 'Fehler beim Löschen des Podcast-Medienordners {folder_path}. Sie können ihn manuell von der Festplatte löschen.', - 'podcastFeedUpdateSuccess' => 'Erfolgreiche Aktualisierung: {number_of_new_episodes, plural, - one {# Episode wurde} - other {# Episoden wurden} - } zum Podcast hinzugefügt!', - 'podcastFeedUpToDate' => 'Der Podcast ist bereits auf dem neuesten Stand.', - 'publishError' => 'Dieser Podcast ist entweder bereits veröffentlicht oder zur Veröffentlichung geplant.', - 'publishEditError' => 'Dieser Podcast ist nicht zur Veröffentlichung geplant.', - 'publishCancelSuccess' => 'Veröffentlichung des Podcasts erfolgreich abgebrochen!', - 'scheduleDateError' => 'Veröffentlichungsdatum muss gesetzt sein!', + 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, + transcript {transcript} + chapters {chapters} + image {cover} + audio {audio} + other {media} + }.', + 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', + 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, + one {# episode was} + other {# episodes were} + } added to the podcast!', + 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', + 'publishError' => 'This podcast is either already published or scheduled for publication.', + 'publishEditError' => 'This podcast is not scheduled for publication.', + 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', + 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ 'identity_section_title' => 'Podcast-Identität', 'identity_section_subtitle' => 'Diese Felder erlauben es dir, Aufmerksamkeit zu bekommen.', - 'fediverse_section_title' => 'Fediverse-Identität', - 'cover' => 'Podcast-Cover', - 'cover_size_hint' => 'Das Cover muss quadratisch und mindestens 1400px breit und hoch sein.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast-Banner', - 'banner_size_hint' => 'Der Banner muss ein 3:1-Verhältnis haben und mindestens 1500px breit sein.', + 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', 'banner_delete' => 'Podcast-Banner löschen', 'title' => 'Titel', 'handle' => 'Identifikator', 'handle_hint' => - 'Wird genutzt, um den Podcast zu identifizieren. Großbuchstaben, Kleinbuchstaben, Zahlen und Unterstriche sind erlaubt.', + 'Verwendet um den Podcast zu identifizieren. Großbuchstaben, Kleinbuchstaben, Zahlen und Unterstriche sind erlaubt.', 'type' => [ 'label' => 'Typ', 'episodic' => 'Episodisch', 'episodic_hint' => 'Wenn Folgen ohne bestimmte Reihenfolge abgespielt werden sollen. Neueste Folgen werden zuerst angezeigt.', 'serial' => 'Seriell', - 'serial_hint' => 'Wenn Episoden in sequenzieller Reihenfolge konsumiert werden sollen. Episoden werden in numerischer Reihenfolge angezeigt.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Beschreibt einen Feed für eine Podcast-Show.', - 'music' => 'Musik', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Hörbuch', - 'audiobook_hint' => 'Spezifische Arten von Audio mit einem Eintrag pro Feed, oder wenn Elemente Kapitel innerhalb des Buches darstellen.', + 'serial_hint' => 'Wenn Folgen in bestimmter Reihenfolge abgespielt werden sollen. Älteste Folgen werden zuerst angezeigt.', ], 'description' => 'Beschreibung', 'classification_section_title' => 'Klassifikation', @@ -93,12 +80,12 @@ return [ 'language' => 'Sprache', 'category' => 'Kategorie', 'category_placeholder' => 'Kategorie wählen...', - 'other_categories' => 'Andere Kategorien', + 'other_categories' => 'Andere Kategorieen', 'parental_advisory' => [ 'label' => 'Hinweis an Eltern', 'hint' => 'Enthält die Folge anstößige Inhalte?', 'undefined' => 'nicht definiert', - 'clean' => 'Sauber', + 'clean' => 'Zurücksetzen', 'explicit' => 'Anstößig', ], 'author_section_title' => 'Autor', @@ -109,51 +96,44 @@ return [ 'owner_email' => 'E-Mail des Eigentümers', 'owner_email_hint' => 'Wird von den meisten Plattformen verwendet werden, um den Podcast-Besitz zu überprüfen. Sichtbar im öffentlichen RSS-Feed.', - 'is_owner_email_removed_from_feed' => 'Entferne die Eigentümer-E-Mail aus dem öffentlichen RSS-Feed', - 'is_owner_email_removed_from_feed_hint' => 'Möglicherweise müssen Sie die E-Mail vorübergehend freigeben, damit ein Verzeichnis Ihren Podcast-Besitz verifizieren kann.', 'publisher' => 'Herausgeber', 'publisher_hint' => 'Die Gruppe, die für die Erstellung des Podcasts verantwortlich ist. Oft bezogen auf die Muttergesellschaft oder das Netzwerk eines Podcasts. Dieses Feld wird manchmal als \'Autor\' bezeichnet.', 'copyright' => 'Urheberrecht', 'location_section_title' => 'Standort', - 'location_section_subtitle' => 'Um welchen Ort geht es in diesem Podcast?', + 'location_section_subtitle' => 'Über welchen Ort handelt dieser Podcast?', 'location_name' => 'Standortname oder Adresse', - 'location_name_hint' => 'Dies kann ein echter oder ein fiktiver Ort sein', + 'location_name_hint' => 'Dies kann ein echter Ort oder fiktiv sein', 'monetization_section_title' => 'Monetarisierung', 'monetization_section_subtitle' => - 'Geld dank der Zuhörer verdienen.', + 'Geld dank der Zuhöhrer verdienen.', 'premium' => 'Premium', - 'premium_by_default' => 'Episoden müssen standardmäßig als Premium festgelegt werden', - 'premium_by_default_hint' => 'Podcast-Episoden werden standardmäßig als Premium markiert. Sie können dennoch einzelne Episoden, Trailer oder Boni als öffentlich festlegen.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Besuche dein OP3-Dashboard (externer Link)', - 'op3_hint' => 'Werten Sie Ihre Analysedaten mit OP3 auf, einem quelloffenen und vertrauenswürdigen Analysedienst eines Drittanbieters. Teilen, validieren und vergleichen Sie Ihre Analysedaten in dem offenen Podcast-Ökosystem.', - 'op3_enable' => 'OP3-Analysedienst aktivieren', - 'op3_enable_hint' => 'Aus Sicherheitsgründen werden die Analysedaten von Premium-Episoden nicht mit OP3 geteilt.', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', 'payment_pointer' => 'Zahlungsadresse (Payment Pointer) für Web-Monetarisierung', 'payment_pointer_hint' => 'Hier erhalten Sie dank Monetarisierung Geld', 'advanced_section_title' => 'Erweiterte Einstellungen', 'advanced_section_subtitle' => - 'Wenn RSS-Tags benötigt werden, die Castopod nicht verwendet, können diese hier gesetzt werden.', + 'Wenn RSS-Tags benötigt werden, die Castopod nicht verwendet, können diese hier gesetz werden.', 'custom_rss' => 'Eigene RSS-Tags für den Podcast', 'custom_rss_hint' => 'Dies wird innerhalb des ❬channel❭ Tags eingefügt.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'Neue Feed-URL', 'new_feed_url_hint' => 'Benutzen Sie dieses Feld, wenn Sie zu einer anderen Domain oder Podcast-Plattform wechseln. Standardmäßig wird der Wert auf die aktuelle RSS URL gesetzt, wenn der Podcast importiert wird.', - 'old_feed_url' => 'Alte Feed-URL', + 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnerschaft:en', 'partner_id' => 'ID', 'partner_link_url' => 'Link', 'partner_image_url' => 'Bildadresse', 'partner_id_hint' => 'Ihre eigene Partner-ID', 'partner_link_url_hint' => 'Die generische Partnerlink-Adresse', - 'partner_image_url_hint' => 'Die generische Partnerbild-Adresse', - 'block' => 'Podcast soll vor öffentlichen Katalogen versteckt werden', + 'partner_image_url_hint' => 'Die generische Partnerbild-adresse', + 'status_section_title' => 'Status', + 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => - 'Der Podcast zeigt oder versteckt den Status: Beim Einschalten dieser Option wird verhindert, dass der Podcast in Apple Podcasts, Google Podcasts und alle Apps von Drittanbietern, die Inhalte aus diesen Verzeichnissen ziehen, erscheint. (Ohne Garantie!)', + 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'complete' => 'Der Podcast wird keine neuen Folgen erhalten', 'lock' => 'Schütze den Podcast davor kopiert zu werden', 'lock_hint' => @@ -164,8 +144,8 @@ return [ 'category_options' => [ 'uncategorized' => 'unkategorisiert', 'arts' => 'Kunst', - 'business' => 'Geschäftliches', - 'comedy' => 'Comedy', + 'business' => 'Geschäftlich', + 'comedy' => 'Komödie', 'education' => 'Bildung', 'fiction' => 'Fiktion', 'government' => 'Regierung', @@ -188,12 +168,12 @@ return [ 'food' => 'Essen', 'performing_arts' => 'Darstellende Kunst', 'visual_arts' => 'Visuelle Kunst', - 'careers' => 'Karriere', - 'entrepreneurship' => 'Unternehmertum', + 'careers' => 'Karrieren', + 'entrepreneurship' => 'Entrepreneurship', 'investing' => 'Investment', 'management' => 'Management', 'marketing' => 'Marketing', - 'non_profit' => 'Gemeinnützigkeit', + 'non_profit' => 'Gemeinnützig', 'comedy_interviews' => 'Comedy-Interviews', 'improv' => 'Improvisation', 'stand_up' => 'Stand-Up', @@ -275,36 +255,36 @@ return [ 'tv_reviews' => 'TV-Kritiken', ], 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Zurück zum Podcast-Dashboard', - 'post' => 'Dein Ankündigungsbeitrag', + 'back_to_podcast_dashboard' => 'Back to podcast dashboard', + 'post' => 'Your announcement post', 'post_hint' => - "Schreiben Sie eine Nachricht, um die Veröffentlichung Ihres Podcasts anzukündigen. Diese Nachricht wird auf der Homepage des Podcasts erscheinen.", - 'message_placeholder' => 'Schreiben Sie Ihre Nachricht…', - 'submit' => 'Veröffentlichen', - 'publication_date' => 'Veröffentlichungsdatum', + "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", + 'message_placeholder' => 'Write your message…', + 'submit' => 'Publish', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Jetzt', - 'schedule' => 'Planen', + 'now' => 'Now', + 'schedule' => 'Schedule', ], - 'scheduled_publication_date' => 'Geplantes Veröffentlichungsdatum', + 'scheduled_publication_date' => 'Scheduled publication date', 'scheduled_publication_date_hint' => - 'Du kannst die Veröffentlichung des Podcasts planen, indem du ein zukünftiges Veröffentlichungsdatum festlegst. Dieses Feld muss als YYYY-MM-TT HH:mm formatiert werden', - 'submit_edit' => 'Veröffentlichung bearbeiten', - 'cancel_publication' => 'Veröffentlichung abbrechen', - 'message_warning' => 'Sie haben keinen Text für Ihren Ankündigungsbeitrag geschrieben!', - 'message_warning_hint' => 'Eine Nachricht erhöht das soziale Engagement, was zu einer besseren Sichtbarkeit des Podcasts führt.', - 'message_warning_submit' => 'Dennoch veröffentlichen', + 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', + 'message_warning' => 'You did not write a message for your announcement post!', + 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ - 'draft_mode' => 'Entwurfsmodus', - 'not_published' => 'Dieser Podcast ist noch nicht veröffentlicht.', - 'scheduled' => 'Dieser Podcast ist für eine Veröffentlichung am {publication_date} vorgesehen.', + 'draft_mode' => 'draft mode', + 'not_published' => 'This podcast is not yet published.', + 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => - "Beim Löschen des Podcasts werden alle damit verbundenen Episoden, Mediendateien, Beiträge und Analysen gelöscht. Diese Aktion ist unumkehrbar, Sie können diese danach nicht mehr abrufen.", - 'understand' => 'Ich verstehe, ich möchte, dass der Podcast dauerhaft gelöscht wird', - 'submit' => 'Löschen', + "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", + 'understand' => 'I understand, I want the podcast to be permanently deleted', + 'submit' => 'Delete', ], 'by' => 'Von {publisher}', 'season' => 'Staffel {seasonNumber}', @@ -314,12 +294,12 @@ return [ 'no_episode' => 'Keine Folge gefunden!', 'follow' => 'Folgen', 'followers' => '{numberOfFollowers, plural, - one {# Follower} - other {# Follower} + one {# follower} + other {# followers} }', 'posts' => '{numberOfPosts, plural, - one {# Beitrag} - other {# Beiträge} + one {# post} + other {# posts} }', 'activity' => 'Aktivitäten', 'episodes' => 'Folgen', diff --git a/modules/Admin/Language/de/PodcastImport.php b/modules/Admin/Language/de/PodcastImport.php new file mode 100644 index 00000000..20153bc7 --- /dev/null +++ b/modules/Admin/Language/de/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'Der zu importierende Podcast', + 'old_podcast_section_subtitle' => + 'Stellen Sie sicher, dass Sie die Rechte für diesen Podcast besitzen, bevor Sie ihn importieren. Vervielfältigung und Ausstrahlung eines Podcasts ohne die entsprechenden Rechte sind Piraterie und strafbar.', + 'imported_feed_url' => 'Feed-URL', + 'imported_feed_url_hint' => 'Der Feed muss im xml oder RSS-Format sein.', + 'new_podcast_section_title' => 'Der neue Podcast', + 'advanced_params_section_title' => 'Erweiterte Parameter', + 'advanced_params_section_subtitle' => + 'Behalten Sie die Standardwerte, wenn Sie keine Ahnung haben, wofür die Felder sind.', + 'slug_field' => 'Feld zum Berechnen der Episoden-URL (epiode slug)', + 'description_field' => + 'Quellfeld für Episodenbeschreibung verwendet / Notizen anzeigen', + 'force_renumber' => 'Erzwinge Neu-Nummerierung der Folgen', + 'force_renumber_hint' => + 'Verwende dies, wenn dein Podcast keine Episodennummern hat, aber du diese während des Imports setzen möchtest.', + 'season_number' => 'Staffelnummer', + 'season_number_hint' => + 'Benutze dies, wenn dein Podcast keine Staffelnummer hat, aber du eine beim Import setzen möchtest. Lasse es andernfalls leer.', + 'max_episodes' => 'Maximale Anzahl der zu importierenden Episoden', + 'max_episodes_hint' => 'Leer lassen um alle Episoden zu importieren', + 'lock_import' => + 'Dieser Feed ist geschützt. Du kannst ihn nicht importieren. Wenn du der Besitzer bist, entferne den Schutz auf der Ursprungsplattform.', + 'submit' => 'Podcast importieren', +]; diff --git a/modules/Admin/Language/de/PodcastNavigation.php b/modules/Admin/Language/de/PodcastNavigation.php index 6fa2e17d..088887f3 100644 --- a/modules/Admin/Language/de/PodcastNavigation.php +++ b/modules/Admin/Language/de/PodcastNavigation.php @@ -10,17 +10,14 @@ declare(strict_types=1); return [ 'go_to_page' => 'Zur Podcast-Seite gehen', - 'rss_feed' => 'RSS-Feed', 'dashboard' => 'Podcast-Dashboard', 'podcast-view' => 'Startseite', 'podcast-edit' => 'Podcast bearbeiten', 'podcast-persons-manage' => 'Mitwirkende verwalten', - 'podcast-imports' => 'Podcast-Importe', - 'podcast-imports-sync' => 'Feeds synchronisieren', 'episodes' => 'Folgen', 'episode-list' => 'Alle Episoden', 'episode-create' => 'Neue Episoden', - 'analytics' => 'Statistiken', + 'analytics' => 'Analysen', 'podcast-analytics' => 'Zuhörer-Übersicht', 'podcast-analytics-webpages' => 'Webseiten-Besuche', 'podcast-analytics-locations' => 'Standorte', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Podcast-Player', 'podcast-analytics-listening-time' => 'Hörzeit', 'podcast-analytics-time-periods' => 'Zeiträume', - 'monetization' => 'Monetarisierung', - 'subscription-list' => 'Alle Abonnements', - 'subscription-create' => 'Abonnement hinzufügen', - 'contributors' => 'Mitwirkende', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', + 'contributors' => 'Administratoren', 'contributor-list' => 'Alle Unterstützer', - 'contributor-add' => 'Mitwirkenden hinzufügen', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcast-Apps', + 'contributor-add' => 'Administrator hinzufügen', + 'platforms' => 'Externe Plattformen', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Soziale Netzwerke', - 'platforms-funding' => 'Finanzierungslinks', - 'podcast-monetization-other' => 'Andere', + 'platforms-funding' => 'Finanzierung', ]; diff --git a/modules/Admin/Language/de/Settings.php b/modules/Admin/Language/de/Settings.php index d046a40e..9484c30e 100644 --- a/modules/Admin/Language/de/Settings.php +++ b/modules/Admin/Language/de/Settings.php @@ -14,8 +14,8 @@ return [ 'title' => 'Instanz', 'site_icon' => 'Webseiten-Icon', 'site_icon_delete' => 'Lösche Webseiten-Icon', - 'site_icon_hint' => 'Webseiten-Icons sind das, was Sie in Ihren Browser-Tabs, der Lesezeichenleiste und als Verknüpfung auf mobilen Geräten sehen.', - 'site_icon_helper' => 'Das Icon muss quadratisch und mindestens 512px breit und hoch sein.', + 'site_icon_hint' => 'Webseiten-Icons sind das, was Sie auf Ihrem Browser Tabs, Lesezeichenleiste und wenn Sie eine Website als Verknüpfung auf mobilen Geräten hinzufügen, sehen.', + 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', 'site_name' => 'Seitenname', 'site_description' => 'Seitenbeschreibung', 'submit' => 'Speichern', @@ -35,10 +35,10 @@ return [ 'reset_counts_helper' => 'Diese Option wird alle Datenzähler neu berechnen und zurücksetzen (Anzahl der Follower, Beiträge, Kommentare, …).', 'rewrite_media' => 'Medien-Metadaten neu schreiben', 'rewrite_media_helper' => 'Diese Option wird alle überflüssigen Mediendateien löschen und neu erstellen (Bilder, Audiodateien, Transkripte, Kapitel …)', - 'rename_episodes_files' => 'Audiodateien der Episode umbenennen', - 'rename_episodes_files_hint' => 'Diese Option wird alle Audiodateien der Episode mit einer zufälligen Zeichenkette umbenennen. Benutzen Sie diese Option, wenn einer Ihrer privaten Episoden-Links durchsickert, da diese dadurch versteckt werden.', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', 'clear_cache' => 'Alle Caches löschen', - 'clear_cache_helper' => 'Diese Option leert den redis-Cache oder beschreibbare/Cache-Dateien.', + 'clear_cache_helper' => 'Diese Option leert den redis-Cache oder beschreibbare/cache-Dateien.', 'run' => 'Systempflege starten', 'runSuccess' => 'Die Systempflege wurde erfolgreich durchgeführt!', ], diff --git a/modules/Admin/Language/de/Soundbite.php b/modules/Admin/Language/de/Soundbite.php index e8d6782f..75f0103d 100644 --- a/modules/Admin/Language/de/Soundbite.php +++ b/modules/Admin/Language/de/Soundbite.php @@ -10,22 +10,22 @@ declare(strict_types=1); return [ 'list' => [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', + 'title' => 'Tonschnipsel', + 'soundbite' => 'Tonschnipsel', ], 'messages' => [ - 'createSuccess' => 'Soundbite wurde erfolgreich erstellt!', - 'deleteSuccess' => 'Soundbite wurde erfolgreich entfernt!', + 'createSuccess' => 'Tonschnipsel wurde erfolgreich erstellt!', + 'deleteSuccess' => 'Tonschnipsel wurde erfolgreich entfernt!', ], 'form' => [ - 'title' => 'Neues Soundbite', - 'soundbite_title' => 'Soundbite-Titel', + 'title' => 'Neuer Tonschnipsel', + 'soundbite_title' => 'Tonschnipsel-Titel', 'start_time' => 'Beginne bei', 'duration' => 'Länge', - 'submit' => 'Soundbite erstellen', + 'submit' => 'Tonschnipsel erstellen', ], - 'play' => 'Soundbite abspielen', + 'play' => 'Tonschnipsel abspielen', 'stop' => 'Tonschnipsel stoppen', - 'create' => 'Neues Soundbite', - 'delete' => 'Soundbite löschen', + 'create' => 'Neuer Tonschnipsel', + 'delete' => 'Tonschnipsel löschen', ]; diff --git a/modules/Auth/Language/de/User.php b/modules/Admin/Language/de/User.php similarity index 63% rename from modules/Auth/Language/de/User.php rename to modules/Admin/Language/de/User.php index 68649b0a..a4d261be 100644 --- a/modules/Auth/Language/de/User.php +++ b/modules/Admin/Language/de/User.php @@ -9,50 +9,46 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Die Rolle(n) von {username} bearbeiten", - 'ban' => 'Sperren', - 'unban' => 'Entsperren', + 'edit_roles' => "Bearbeite {username}'s Rollen", + 'forcePassReset' => 'Erzwinge Pass-Zurücksetzung', + 'ban' => 'Bannen', + 'unban' => 'Entbannen', 'delete' => 'Löschen', 'create' => 'Neuer Benutzer', - 'view' => "{username}-Infos", + 'view' => "{username}'s Info", 'all_users' => 'Alle Benutzer', 'list' => [ 'user' => 'Benutzer', - 'role' => 'Rolle', - 'banned' => 'Gesperrt?', + 'roles' => 'Rollen', + 'banned' => 'Gebannt?', ], 'form' => [ 'email' => 'E-mail', 'username' => 'Benutzername', 'password' => 'Passwort', 'new_password' => 'Neues Passwort', - 'role' => 'Rolle', 'roles' => 'Rollen', 'permissions' => 'Berechtigungen', 'submit_create' => 'Benutzer erstellen', 'submit_edit' => 'Speichern', 'submit_password_change' => 'Verändern!', ], - 'delete_form' => [ - 'title' => '{user} löschen', - 'disclaimer' => - "Sie sind dabei {user} dauerhaft zu löschen. Es wird für den Benutzer nicht mehr möglich sein, den Admin-Bereich zu nutzen.", - 'understand' => 'Ich verstehe, Ich will {user} dauerhaft löschen', - 'submit' => 'Löschen', + 'roles' => [ + 'superadmin' => 'Super-Admin', ], 'messages' => [ 'createSuccess' => 'Benutzer wurde erfolgreich erstellt! {username} wird bei der ersten Authentifizierung zu einer Passwortzurücksetzung aufgefordert.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "{username}'s Rollen wurden erfolgreich aktualisiert.", + 'forcePassResetSuccess' => + '{username} wird beim nächsten Besuch zu einem Zurücksetzen des Passworts aufgefordert.', 'banSuccess' => '{username} wurde gebannt.', 'unbanSuccess' => '{username} wurde entbannt.', 'editOwnerError' => - '{username} ist Eigentümer der Instanz, Eigentümer können nicht gelöscht werden…', + '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} ist ein Superadmin, man bannt nicht einfach einen Superadmin…', - 'deleteOwnerError' => - '{username} ist Eigentümer der Instanz, Eigentümer können nicht gelöscht werden…', 'deleteSuperAdminError' => '{username} ist ein Superadmin, man löscht nicht einfach einen Superadmin…', 'deleteSuccess' => '{username} wurde gelöscht.', diff --git a/modules/Admin/Language/de/Validation.php b/modules/Admin/Language/de/Validation.php index bae6668c..f973bf67 100644 --- a/modules/Admin/Language/de/Validation.php +++ b/modules/Admin/Language/de/Validation.php @@ -13,5 +13,6 @@ return [ '{field} ist entweder kein Bild, oder es ist nicht breit oder hoch genug.', 'is_image_ratio' => '{field} ist entweder kein Bild oder nicht das richtige Verhältnis.', - 'is_json' => '{field} enthält ungültiges JSON.', + 'validate_url' => + 'Das {field} -Feld muss eine gültige URL sein (z.B. https://example.com/).', ]; diff --git a/modules/Admin/Language/de/VideoClip.php b/modules/Admin/Language/de/VideoClip.php index ccf9841b..bffcd16c 100644 --- a/modules/Admin/Language/de/VideoClip.php +++ b/modules/Admin/Language/de/VideoClip.php @@ -25,7 +25,7 @@ return [ 'passed_hint' => 'Clip wurde erfolgreich erstellt!', ], 'clip' => 'Clip', - 'duration' => 'Laufzeit', + 'duration' => 'Job Laufzeit', ], 'title' => 'Video-Clip: {videoClipLabel}', 'download_clip' => 'Clip herunterladen', @@ -33,7 +33,7 @@ return [ 'go_to_page' => 'Zur Clip-Seite gehen', 'retry' => 'Clip-Generierung wiederholen', 'delete' => 'Clip löschen', - 'logs' => 'Jobprotokoll', + 'logs' => 'Job-Logs', 'messages' => [ 'alreadyExistingError' => 'Der Videoclip, den Sie zu erstellen versuchen, existiert bereits!', 'addToQueueSuccess' => 'Videoclip wurde zur Warteschlange hinzugefügt und wartet darauf, erstellt zu werden!', @@ -57,9 +57,9 @@ return [ 'theme' => 'Wähle ein Design', 'start_time' => 'Beginne bei', 'duration' => 'Laufzeit', - 'trim_start' => 'Startpunkt', - 'trim_end' => 'Ende trimmen', - 'submit' => 'Neuen Clip erstellen', + 'trim_start' => 'Trimm-Start', + 'trim_end' => 'Trimm-Ende', + 'submit' => 'Erstelle Videoclip', ], 'requirements' => [ 'title' => 'Fehlende Anforderungen', diff --git a/modules/Admin/Language/el/AboutCastopod.php b/modules/Admin/Language/el/AboutCastopod.php deleted file mode 100644 index df1c81f4..00000000 --- a/modules/Admin/Language/el/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Περί Του Castopod', - 'host_name' => 'Όνομα εξυπηρετητή', - 'version' => 'Έκδοση Castopod', - 'php_version' => 'Έκδοση PHP', - 'os' => 'Λειτουργικό σύστημα', - 'languages' => 'Γλώσσες', - 'update_database' => 'Ενημέρωση Βάσης Δεδομένων', - 'messages' => [ - 'databaseUpdateSuccess' => 'Η βάση δεδομένων είναι ενημερωμένη!', - ], -]; diff --git a/modules/Admin/Language/el/Breadcrumb.php b/modules/Admin/Language/el/Breadcrumb.php index 217f6edb..38b8ec92 100644 --- a/modules/Admin/Language/el/Breadcrumb.php +++ b/modules/Admin/Language/el/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Αρχική σελίδα', 'podcasts' => 'podcasts', 'episodes' => 'επεισόδια', - 'subscriptions' => 'συνδρομές', + 'subscriptions' => 'subscriptions', 'contributors' => 'συντελεστές', 'pages' => 'σελίδες', 'settings' => 'ρυθμίσεις', 'theme' => 'θέμα', - 'about' => 'σχετικά', 'add' => 'προσθήκη', 'new' => 'νέο', 'edit' => 'επεξεργασία', 'persons' => 'άτομα', 'publish' => 'δημοσίευση', 'publish-edit' => 'επεξεργασία δημοσίευσης', - 'publish-date-edit' => 'επεξεργασία ημερομηνίας δημοσίευσης', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'αναίρεση δημοσίευσης', 'delete' => 'διαγραφή', - 'remove' => 'αφαίρεση', 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'λίστες αποκλεισμένων', 'users' => 'χρήστες', 'my-account' => 'ο λογαριασμός μου', 'change-password' => 'αλλαγή κωδικού πρόσβασης', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'εισαγωγή ροής', 'platforms' => 'πλατφόρμες', 'social' => 'κοινωνικά δίκτυα', 'funding' => 'χρηματοδότηση', - 'monetization-other' => 'other monetization', 'analytics' => 'αναλυτικά στοιχεία', 'locations' => 'τοποθεσίες', 'webpages' => 'ιστοσελίδες', @@ -52,6 +47,6 @@ return [ 'soundbites' => 'ήχοι', 'video-clips' => 'βίντεο κλιπς', 'embed' => 'ενσωματώσιμος αναπαραγωγέας', - 'notifications' => 'ειδοποιήσεις', - 'suspend' => 'αναστολή', + 'notifications' => 'notifications', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/el/Charts.php b/modules/Admin/Language/el/Charts.php index 247a77e7..be7ed2ee 100644 --- a/modules/Admin/Language/el/Charts.php +++ b/modules/Admin/Language/el/Charts.php @@ -35,7 +35,6 @@ return [ 'by_weekday' => 'Την ημέρα της εβδομάδας (για τις τελευταίες 60 ημέρες)', 'by_hour' => 'Κατά την ώρα της ημέρας (για τις τελευταίες 60 ημέρες)', 'podcast_by_bandwidth' => 'Ημερήσιο χρησιμοποιούμενο bandwidth (σε MB)', - 'total_storage_by_month' => 'Μηνιαία αποθήκευση (σε MB)', - 'total_bandwidth_by_month' => 'Μηνιαίο χρησιμοποιούμενο εύρος ζώνης (σε MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', + 'total_storage_by_month' => 'Monthly storage (in MB)', + 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', ]; diff --git a/modules/Admin/Language/el/Common.php b/modules/Admin/Language/el/Common.php index 7bf5bbec..13b75af4 100644 --- a/modules/Admin/Language/el/Common.php +++ b/modules/Admin/Language/el/Common.php @@ -40,13 +40,12 @@ return [ ], 'upload_file' => 'Μεταφορτώστε ένα αρχείο', 'remote_url' => 'Απομακρυσμένη διεύθυνση URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Αναπαραγωγή', 'playing' => 'Αναπαράγεται', ], 'size_limit' => 'Όριο μεγέθους: {0}.', - 'choose_interact' => 'Επιλέξτε τον τρόπο αλληλεπίδρασης', - 'view' => 'Προβολή', + 'choose_interact' => 'Choose how to interact', + 'view' => 'View', ]; diff --git a/modules/Auth/Language/el/Contributor.php b/modules/Admin/Language/el/Contributor.php similarity index 77% rename from modules/Auth/Language/el/Contributor.php rename to modules/Admin/Language/el/Contributor.php index 1acec63a..132d9abb 100644 --- a/modules/Auth/Language/el/Contributor.php +++ b/modules/Admin/Language/el/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Προσθήκη συντελεστή', 'submit_edit' => 'Ενημέρωση ρόλου', ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', + 'roles' => [ + 'podcast_admin' => 'Διαχειριστής Podcast', ], 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", 'removeOwnerError' => "Δεν μπορείτε να καταργήσετε τον ιδιοκτήτη podcast!", 'removeSuccess' => 'Έχετε αφαιρέσει με επιτυχία τον χρήστη {username} από το {podcastTitle}', diff --git a/modules/Admin/Language/el/Dashboard.php b/modules/Admin/Language/el/Dashboard.php index b780ea20..881073fd 100644 --- a/modules/Admin/Language/el/Dashboard.php +++ b/modules/Admin/Language/el/Dashboard.php @@ -9,20 +9,20 @@ declare(strict_types=1); */ return [ - 'home' => 'Πίνακας ελέγχου διαχειριστή', - 'welcome_message' => 'Καλώς ήρθατε στην περιοχή διαχείρισης!', + 'home' => 'Admin dashboard', + 'welcome_message' => 'Welcome to the admin area!', 'podcasts' => [ 'title' => 'Podcasts', - 'not_found' => 'Δεν υπάρχει δημοσιευμένο podcast', - 'last_published' => 'Τελευταία δημοσίευση στις {lastPublicationDate}', + 'not_found' => 'No published podcast', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'episodes' => [ - 'title' => 'Επεισόδια', - 'not_found' => 'Κανένα δημοσιευμένο επεισόδιο', - 'last_published' => 'Τελευταία δημοσίευση στις {lastPublicationDate}', + 'title' => 'Episodes', + 'not_found' => 'No published episode', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'storage' => [ - 'title' => 'Αποθηκευτικός χώρος', - 'subtitle' => '{totalUploaded} από {totalStorage}', + 'title' => 'Storage', + 'subtitle' => '{totalUploaded} out of {totalStorage}', ], ]; diff --git a/modules/Admin/Language/el/Episode.php b/modules/Admin/Language/el/Episode.php index cf72d9e7..53c6ea41 100644 --- a/modules/Admin/Language/el/Episode.php +++ b/modules/Admin/Language/el/Episode.php @@ -22,41 +22,39 @@ return [ 'all_podcast_episodes' => 'Όλα τα επεισόδια του podcast', 'back_to_podcast' => 'Μετάβαση πίσω στο podcast', 'edit' => 'Επεξεργασία', - 'preview' => 'Preview', 'publish' => 'Δημοσίευση', 'publish_edit' => 'Επεξεργασία δημοσίευσης', - 'publish_date_edit' => 'Επεξεργασία ημερομηνίας δημοσίευσης', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Αναίρεση δημοσίευσης', 'publish_error' => 'Το επεισόδιο έχει ήδη δημοσιευθεί.', 'publish_edit_error' => 'Το επεισόδιο έχει ήδη δημοσιευθεί.', 'publish_cancel_error' => 'Το επεισόδιο έχει ήδη δημοσιευθεί.', - 'publish_date_edit_error' => 'Το επεισόδιο δεν έχει δημοσιευθεί ακόμα, δεν μπορείτε να επεξεργαστείτε την ημερομηνία έκδοσής του.', - 'publish_date_edit_future_error' => 'Η ημερομηνία δημοσίευσης του επεισοδίου μπορεί να οριστεί μόνο σε μια προηγούμενη ημερομηνία! Αν θέλετε να την προγραμματίσετε εκ νέου, αποδημοσιεύστε την πρώτα.', - 'publish_date_edit_success' => 'Η ημερομηνία δημοσίευσης του επεισοδίου έχει ενημερωθεί με επιτυχία!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'Το επεισόδιο δεν έχει δημοσιευθεί.', 'delete' => 'Διαγραφή', 'go_to_page' => 'Μετάβαση στη σελίδα', 'create' => 'Προσθήκη επεισοδίου', 'publication_status' => [ 'published' => 'Δημοσιευμένο', - 'with_podcast' => 'Δημοσιευμένο', + 'with_podcast' => 'Published', 'scheduled' => 'Προγραμματισμένο', 'not_published' => 'Δεν έχει δημοσιευτεί', ], - 'with_podcast_hint' => 'Να δημοσιευτεί ταυτόχρονα με το podcast', + 'with_podcast_hint' => 'To be published at the same time as the podcast', 'list' => [ 'search' => [ - 'placeholder' => 'Αναζήτηση ενός επεισοδίου', - 'clear' => 'Καθαρισμός αναζήτησης', - 'submit' => 'Αναζήτηση', + 'placeholder' => 'Search for an episode', + 'clear' => 'Clear search', + 'submit' => 'Search', ], 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# επισόδειο} - other {# επισόδεια} + one {# episode} + other {# episodes} }', 'episode' => 'Επεισόδιο', 'visibility' => 'Ορατότητα', - 'downloads' => 'Downloads', 'comments' => 'Σχόλια', 'actions' => 'Ενέργειες', ], @@ -64,22 +62,22 @@ return [ 'createSuccess' => 'Το επεισόδιο δημιουργήθηκε με επιτυχία!', 'editSuccess' => 'Το επεισόδιο ενημερώθηκε με επιτυχία!', 'publishSuccess' => '{publication_status, select, - published {Το επεισόδιο δημοσιεύτηκε με επιτυχία!} - scheduled {Η έκδοση για το επεισόδιο έχει προγραμματιστεί επιτυχώς!} - with_podcast {Αυτό το επεισόδιο θα δημοσιευθεί ταυτόχρονα με το podcast.} - other {Αυτό το επεισόδιο δεν έχει δημοσιευθεί.} + published {Episode successfully published!} + scheduled {Episode publication successfully scheduled!} + with_podcast {This episode will be published at the same time as the podcast.} + other {This episode is not published.} }', 'publishCancelSuccess' => 'Η δημοσίευση του επεισοδίου ακυρώθηκε επιτυχώς!', - 'unpublishBeforeDeleteTip' => 'Πρέπει να καταργήσετε τη δημοσίευση του επεισοδίου πριν τη διαγραφή.', - 'scheduleDateError' => 'Η ημερομηνία πρέπει να οριστεί!', - 'deletePublishedEpisodeError' => 'Πρέπει να καταργήσετε τη δημοσίευση του επεισοδίου πριν τη διαγραφή.', - 'deleteSuccess' => 'Το επεισόδιο διαγράφτηκε με επιτυχία!', - 'deleteError' => 'Αποτυχία διαγραφής επεισοδίου {type, select, + 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', + 'scheduleDateError' => 'Schedule date must be set!', + 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', + 'deleteSuccess' => 'Episode successfully deleted!', + 'deleteError' => 'Failed to delete episode {type, select, transcript {transcript} - chapters {κεφάλαια} - image {καλύπτουν} - audio {ήχος} - other {πολυμέσα} + chapters {chapters} + image {cover} + audio {audio} + other {media} }.', 'deleteFileError' => 'Failed to delete {type, select, transcript {transcript} @@ -87,8 +85,8 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'Ένα επεισόδιο με το επιλεγμένο slug υπάρχει ήδη.', + } file {file_path}. You may manually remove it from your disk.', + 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ 'file_size_error' => @@ -99,7 +97,7 @@ return [ 'cover' => 'Εξώφυλλο επισοδίου', 'cover_hint' => 'Εάν δεν ορίσετε ένα εξώφυλλο, το εξώφυλλο του podcast θα χρησιμοποιηθεί αντ \'αυτού.', - 'cover_size_hint' => 'Το εξώφυλλο πρέπει να είναι τουλάχιστον 1400px πλάτος και ύψος.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'title' => 'Τίτλος', 'title_hint' => 'Θα πρέπει να υπάρχει ένα σαφές και συνοπτικό όνομα επεισοδίου. Μην καθορίσετε εδώ το επεισόδιο ή τους αριθμούς της σεζόν.', @@ -116,7 +114,7 @@ return [ 'bonus_hint' => 'Επιπλέον περιεχόμενο για την παράσταση (για παράδειγμα, πίσω από τις σκηνές πληροφορίες ή συνεντεύξεις με τη cast) ή δια-διαφημιστικό περιεχόμενο για μια άλλη παράσταση', ], 'premium_title' => 'Premium', - 'premium' => 'Το επεισόδιο πρέπει να είναι προσβάσιμο μόνο σε συνδρομητές premium', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Γονικός σύμβουλος', 'hint' => 'Μήπως το επεισόδιο περιέχει ακατάλληλο περιεχόμενο;', @@ -139,9 +137,9 @@ return [ 'location_name' => 'Όνομα τοποθεσίας ή διεύθυνση', 'location_name_hint' => 'Αυτή μπορεί να είναι μια πραγματική ή φανταστική τοποθεσία', 'transcript' => 'Απομαγνητοφώνηση (υπότιτλοι / κλειστοί υπότιτλοι)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Επιτρέπονται μόνο .srt αρχεία.', 'transcript_download' => 'Λήψη απομαγνητοφώνησης', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Αρχείο απομαγνητοφώνησης (.srt)', 'transcript_remote_url' => 'Απομακρυσμένη διεύθυνση url για απομαγνητοφώνηση', 'transcript_file_delete' => 'Διαγραφή αρχείου απομαγνητοφώνησης', 'chapters' => 'Κεφάλαια', @@ -155,9 +153,9 @@ return [ 'Αν χρειάζεστε ετικέτες RSS που δεν χειρίζεται το Castopod, ορίστε τις εδώ.', 'custom_rss' => 'Προσαρμοσμένες ετικέτες RSS για το επεισόδιο', 'custom_rss_hint' => 'Αυτό θα ενεθεί εντός της ετικέτας "item".', - 'block' => 'Το επεισόδιο πρέπει να είναι κρυμμένο από όλες τις πλατφόρμες', + 'block' => 'Episode should be hidden from public catalogues', 'block_hint' => - 'H κατάσταση εμφάνιση ή απόκρυψη επισοδείου: Η εναλλαγή αποτρέπει την εμφάνιση του επεισοδίου στο Apple Podcast Google Podcasts, και σε οποιεσδήποτε εφαρμογή τρίτων που τραβούν τις εμφανίσεις από αυτούς τους καταλόγους. (Μη εγγυημένη)', + 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'submit_create' => 'Δημιουργία επεισοδίου', 'submit_edit' => 'Αποθήκευση επεισοδίου', ], @@ -171,7 +169,7 @@ return [ 'publication_method' => [ 'now' => 'Τώρα', 'schedule' => 'Προγραμματισμός', - 'with_podcast' => 'Δημοσίευση παράλληλα με podcast', + 'with_podcast' => 'Publish alongside podcast', ], 'scheduled_publication_date' => 'Ημερομηνία προγραμματισμένης δημοσίευσης', 'scheduled_publication_date_clear' => 'Εκκαθάριση ημερομηνίας δημοσίευσης', @@ -185,21 +183,21 @@ return [ 'message_warning_submit' => 'Δημοσίευση ούτως ή άλλως', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Ημερομηνία νέας δημοσίευσης', - 'new_publication_date_hint' => 'Πρέπει να οριστεί σε μια προηγούμενη ημερομηνία.', - 'submit' => 'Επεξεργασία ημερομηνίας δημοσίευσης', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "Η κατάργηση της δημοσίευσης του επεισοδίου θα διαγράψει όλα τα σχόλια και τις δημοσιεύσεις που σχετίζονται με αυτό και θα τα αφαιρέσει από τη ροή RSS του podcast.", + "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", 'understand' => 'Καταλαβαίνω, θέλω να αποδημοσιεύσει το επεισόδιο', 'submit' => 'Αναίρεση δημοσίευσης', ], 'delete_form' => [ 'disclaimer' => - "Διαγράφοντας το επεισόδιο θα διαγράψετε όλα τα αρχεία πολυμέσων, τα σχόλια, τα βίντεο κλιπ και τα ηχητικά δεδομένα που σχετίζονται με αυτό.", + "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", 'understand' => 'Καταλαβαίνω, θέλω να διαγράψω το επεισόδιο', - 'submit' => 'Διαγραφή', + 'submit' => 'Delete', ], 'embed' => [ 'title' => 'Ενσωματώσιμος αναπαραγωγέας', @@ -212,14 +210,4 @@ return [ 'light' => 'Ανοιχτόχρωμο', 'light-transparent' => 'Ανοιχτό διαφανές', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/el/MyAccount.php b/modules/Admin/Language/el/MyAccount.php similarity index 100% rename from modules/Auth/Language/el/MyAccount.php rename to modules/Admin/Language/el/MyAccount.php diff --git a/modules/Admin/Language/el/Navigation.php b/modules/Admin/Language/el/Navigation.php index 8d766a63..2325bd38 100644 --- a/modules/Admin/Language/el/Navigation.php +++ b/modules/Admin/Language/el/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Εναλλαγή πλαϊνής μπάρας', 'go_to_website' => 'Μεταβείτε στον ιστότοπο', 'go_to_admin' => 'Μεταβείτε στον πίνακα διαχείρισης', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Πίνακας εργαλείων', 'admin' => 'Αρχική σελίδα', 'podcasts' => 'Podcasts', 'podcast-list' => 'Όλα τα podcasts', 'podcast-create' => 'Νέο podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Εισαγωγή ενός podcast', 'persons' => 'Πρόσωπα', 'person-list' => 'Όλα τα άτομα', 'person-create' => 'Νέο άτομο', @@ -35,7 +33,6 @@ return [ 'settings' => 'Ρυθμίσεις', 'settings-general' => 'Γενικά', 'settings-theme' => 'Θέμα', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'Ο λογαριασμός μου', 'change-password' => 'Αλλαγή κωδικού πρόσβασης', diff --git a/modules/Admin/Language/el/Notifications.php b/modules/Admin/Language/el/Notifications.php index 3e87ddba..2b139d51 100644 --- a/modules/Admin/Language/el/Notifications.php +++ b/modules/Admin/Language/el/Notifications.php @@ -9,11 +9,11 @@ declare(strict_types=1); */ return [ - 'title' => 'Ειδοποιήσεις', - 'reply' => '{actor_username} απάντησε στο post σας', - 'favourite' => '{actor_username} έβαλε αγαπημένη τη δημοσίευσή σας', - 'reblog' => '{actor_username} κοινοποίησε τη δημοσίευσή σας', - 'follow' => '{actor_username} ξεκίνησε να σας ακολουθεί', - 'no_notifications' => 'Καμία ειδοποίηση', - 'mark_all_as_read' => 'Σήμανση όλων ως αναγνωσμένα', + 'title' => 'Notifications', + 'reply' => '{actor_username} replied to your post', + 'favourite' => '{actor_username} favourited your post', + 'reblog' => '{actor_username} shared your post', + 'follow' => '{actor_username} started following you', + 'no_notifications' => 'No notifications', + 'mark_all_as_read' => 'Mark all as read', ]; diff --git a/modules/Admin/Language/el/Platforms.php b/modules/Admin/Language/el/Platforms.php index 2c5a10ec..4b5f2fb5 100644 --- a/modules/Admin/Language/el/Platforms.php +++ b/modules/Admin/Language/el/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Πλατφόρμες', 'home_url' => 'Μεταβείτε στην ιστοσελίδα {platformName}', - 'register' => 'Register', 'submit_url' => 'Υποβάλετε το podcast σας στην πλατφόρμα {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Εμφάνιση στην αρχική σελίδα του podcast;', 'on_embed' => 'Εμφάνιση σε ενσωματωμένο player;', 'remove' => 'Κατάργηση {platformName}', diff --git a/modules/Admin/Language/el/Podcast.php b/modules/Admin/Language/el/Podcast.php index d24fa87c..a0f061b4 100644 --- a/modules/Admin/Language/el/Podcast.php +++ b/modules/Admin/Language/el/Podcast.php @@ -13,137 +13,116 @@ return [ 'no_podcast' => 'Δεν βρέθηκαν podcast!', 'create' => 'Δημιουργία podcast', 'import' => 'Εισαγωγή ενός podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'Νέο Επεισόδιο', 'view' => 'Προβολή podcast', 'edit' => 'Επεξεργασία podcast', - 'publish' => 'Δημοσίευση podcast', - 'publish_edit' => 'Επεξεργασία δημοσίευσης', + 'publish' => 'Publish podcast', + 'publish_edit' => 'Edit publication', 'delete' => 'Διαγραφή podcast', 'see_episodes' => 'Δείτε επεισόδια', 'see_contributors' => 'Βλέπε συντελεστές', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Μετάβαση στη σελίδα', 'latest_episodes' => 'Τελευταία επεισόδια', 'see_all_episodes' => 'Δείτε όλα τα επεισόδια', - 'draft' => 'Πρόχειρο', + 'draft' => 'Draft', 'messages' => [ - 'createSuccess' => 'Το επεισόδιο δημιουργήθηκε με επιτυχία!', + 'createSuccess' => 'Podcast successfully created!', 'editSuccess' => 'Το Podcast ενημερώθηκε με επιτυχία!', 'importSuccess' => 'Το Podcast εισήχθη με επιτυχία!', - 'deleteSuccess' => 'Το Podcast @{podcast_handle} διαγράφηκε επιτυχώς!', - 'deletePodcastMediaError' => 'Αποτυχία διαγραφής podcast {type, select, - cover {εξώφυλλο} + 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', + 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, + cover {cover} banner {banner} - other {πολυμέσα} + other {media} }.', - 'deleteEpisodeMediaError' => 'Αποτυχία διαγραφής του podcast επεισοδίου {episode_slug} {type, select, + 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, transcript {transcript} - chapters {κεφάλαια} - image {κάλυμμα} - audio {ήχος} - other {πολυμέσα} + chapters {chapters} + image {cover} + audio {audio} + other {media} }.', - 'deletePodcastMediaFolderError' => 'Αποτυχία διαγραφής του φακέλου μέσων podcast {folder_path}. Μπορείτε να τον αφαιρέσετε χειροκίνητα από το δίσκο σας.', - 'podcastFeedUpdateSuccess' => 'Επιτυχημένη ενημέρωση: {number_of_new_episodes, plural, - one {# επεισόδιο ήταν} - other {# επεισόδια ήταν} - } προστέθηκαν στο podcast!', - 'podcastFeedUpToDate' => 'Το Podcast είναι ήδη ενημερωμένο.', - 'publishError' => 'Αυτό το podcast είτε έχει ήδη δημοσιευθεί είτε έχει προγραμματιστεί για δημοσίευση.', - 'publishEditError' => 'Αυτό το podcast δεν έχει προγραμματιστεί για δημοσίευση.', - 'publishCancelSuccess' => 'Η δημοσίευση του επεισοδίου ακυρώθηκε επιτυχώς!', - 'scheduleDateError' => 'Η ημερομηνία πρέπει να οριστεί!', + 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', + 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, + one {# episode was} + other {# episodes were} + } added to the podcast!', + 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', + 'publishError' => 'This podcast is either already published or scheduled for publication.', + 'publishEditError' => 'This podcast is not scheduled for publication.', + 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', + 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ 'identity_section_title' => 'Αναγνωριστικό Podcast', 'identity_section_subtitle' => 'Αυτά τα πεδία σας επιτρέπουν να ξεχωρίσει το podcast σας.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Εξώφυλο podcast', - 'cover_size_hint' => 'Το εξώφυλλο πρέπει να είναι τουλάχιστον 1400px πλάτος και ύψος.', - 'banner' => 'Banner podcast', - 'banner_size_hint' => 'Το Banner πρέπει να έχει αναλογία 3:1 και να είναι τουλάχιστον 1500px πλάτος.', - 'banner_delete' => 'Διαγραφή του podcast banner', - 'title' => 'Τίτλος', + 'cover' => 'Podcast cover', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', + 'banner' => 'Podcast banner', + 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', + 'banner_delete' => 'Delete podcast banner', + 'title' => 'Title', 'handle' => 'Handle', 'handle_hint' => - 'Χρησιμοποιείται για τον προσδιορισμό του podcast. Τα κεφαλαία, τα πεζά, οι αριθμοί και οι κάτω παύλες γίνονται αποδεκτές.', + 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', 'type' => [ - 'label' => 'Είδος', + 'label' => 'Type', 'episodic' => 'Episodic', - 'episodic_hint' => 'Εάν τα επεισόδια προορίζονται να καταναλωθούν χωρίς καμία συγκεκριμένη σειρά.', - 'serial' => 'Σειριακός Αριθμός', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', + 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', + 'serial' => 'Serial', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Περιγραφή', - 'classification_section_title' => 'Χαρακτηρισμός', + 'description' => 'Description', + 'classification_section_title' => 'Classification', 'classification_section_subtitle' => - 'Αυτά τα πεδία θα επηρεάσουν το κοινό και τον ανταγωνισμό σας.', - 'language' => 'Γλώσσα', - 'category' => 'Κατηγορία', - 'category_placeholder' => 'Επιλέξτε μια κατηγορία…', - 'other_categories' => 'Άλλες κατηγορίες', + 'These fields will impact your audience and competition.', + 'language' => 'Language', + 'category' => 'Category', + 'category_placeholder' => 'Select a category…', + 'other_categories' => 'Other categories', 'parental_advisory' => [ - 'label' => 'Γονικός σύμβουλος', - 'hint' => 'Μήπως το επεισόδιο περιέχει ακατάλληλο περιεχόμενο;', - 'undefined' => 'απροσδιόριστο', - 'clean' => 'Καθαρισμός', - 'explicit' => 'Άσεμνο περιεχόμενο', + 'label' => 'Parental advisory', + 'hint' => 'Does it contain explicit content?', + 'undefined' => 'undefined', + 'clean' => 'Clean', + 'explicit' => 'Explicit', ], - 'author_section_title' => 'Συντάκτης', - 'author_section_subtitle' => 'Ποιος διαχειρίζεται το podcast;', - 'owner_name' => 'Όνομα κατόχου', + 'author_section_title' => 'Author', + 'author_section_subtitle' => 'Who is managing the podcast?', + 'owner_name' => 'Owner name', 'owner_name_hint' => - 'Μόνο για διοικητική χρήση. Ορατό στη δημόσια τροφοδοσία RSS.', - 'owner_email' => 'Email ιδιοκτήτη', + 'For administrative use only. Visible in the public RSS feed.', + 'owner_email' => 'Owner email', 'owner_email_hint' => - 'Θα χρησιμοποιηθεί από τις περισσότερες πλατφόρμες για να επαληθεύσει την ιδιοκτησία του podcast. Ορατό στη δημόσια τροφοδοσία RSS.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Εκδότης', + 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', + 'publisher' => 'Publisher', 'publisher_hint' => - 'Η ομάδα που είναι υπεύθυνη για τη δημιουργία της παράστασης. Συχνά αναφέρεται στη μητρική εταιρεία ή στο δίκτυο ενός podcast. Αυτό το πεδίο μερικές φορές χαρακτηρίζεται ως \'Συγγραφέας\'.', - 'copyright' => 'Πνευματικά δικαιώματα', - 'location_section_title' => 'Τοποθεσία', - 'location_section_subtitle' => 'Σε ποιο μέρος είναι αυτό το επεισόδιο;', - 'location_name' => 'Όνομα τοποθεσίας ή διεύθυνση', - 'location_name_hint' => 'Αυτό μπορεί να είναι ένα πραγματικό μέρος ή φανταστικό', + 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', + 'copyright' => 'Copyright', + 'location_section_title' => 'Location', + 'location_section_subtitle' => 'What place is this podcast about?', + 'location_name' => 'Location name or address', + 'location_name_hint' => 'This can be a real place or fictional', 'monetization_section_title' => 'Monetization', 'monetization_section_subtitle' => - 'Κερδίστε χρήματα χάρη στο κοινό σας.', + 'Earn money thanks to your audience.', 'premium' => 'Premium', - 'premium_by_default' => 'Τα επεισόδια πρέπει να ορίζονται ως premium από προεπιλογή', - 'premium_by_default_hint' => 'Τα επεισόδια Podcast θα επισημανθούν ως premium από προεπιλογή. Μπορείτε ακόμα να επιλέξετε να ορίσετε κάποια επεισόδια, trailers ή μπόνους ως δημόσια.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Δείκτης πληρωμής για Monetization Web', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', + 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => - 'Αυτό είναι το πού θα λάβετε χρήματα χάρη στην Monetization Web', + 'This is your where you will receive money thanks to Web Monetization', 'advanced_section_title' => 'Advanced Parameters', 'advanced_section_subtitle' => 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', @@ -188,56 +168,56 @@ return [ 'food' => 'Food', 'performing_arts' => 'Performing Arts', 'visual_arts' => 'Visual Arts', - 'careers' => 'Καριέρες', - 'entrepreneurship' => 'Επιχειρηματικότητα', - 'investing' => 'Επενδύσεις', - 'management' => 'Διαχείριση', - 'marketing' => 'Μάρκετινγκ', - 'non_profit' => 'Μη κερδοσκοπικού χαρακτήρα', - 'comedy_interviews' => 'Συνεντεύξεις Κωμωδίας', - 'improv' => 'Βελτίωση', + 'careers' => 'Careers', + 'entrepreneurship' => 'Entrepreneurship', + 'investing' => 'Investing', + 'management' => 'Management', + 'marketing' => 'Marketing', + 'non_profit' => 'Non-Profit', + 'comedy_interviews' => 'Comedy Interviews', + 'improv' => 'Improv', 'stand_up' => 'Stand-Up', - 'courses' => 'Σεμινάρια', + 'courses' => 'Courses', 'how_to' => 'How To', - 'language_learning' => 'Εκμάθηση γλωσσών', - 'self_improvement' => 'Αυτοβελτίωση', - 'comedy_fiction' => 'Φαντασία Κωμωδίας', - 'drama' => 'Δράμα', - 'science_fiction' => 'Επιστημονικής φαντασίας', - 'alternative_health' => 'Εναλλακτική Υγεία', - 'fitness' => 'Γυμναστική', - 'medicine' => 'Ιατρική', - 'mental_health' => 'Ψυχική Υγεία', - 'nutrition' => 'Διατροφή', - 'sexuality' => 'Σεξουαλικότητα', - 'education_for_kids' => 'Εκπαίδευση για παιδιά', - 'parenting' => 'Γονείς', - 'pets_and_animals' => 'Κατοικίδια & Ζώα', - 'stories_for_kids' => 'Ιστορίες για παιδιά', + 'language_learning' => 'Language Learning', + 'self_improvement' => 'Self-Improvement', + 'comedy_fiction' => 'Comedy Fiction', + 'drama' => 'Drama', + 'science_fiction' => 'Science Fiction', + 'alternative_health' => 'Alternative Health', + 'fitness' => 'Fitness', + 'medicine' => 'Medicine', + 'mental_health' => 'Mental Health', + 'nutrition' => 'Nutrition', + 'sexuality' => 'Sexuality', + 'education_for_kids' => 'Education for Kids', + 'parenting' => 'Parenting', + 'pets_and_animals' => 'Pets & Animals', + 'stories_for_kids' => 'Stories for Kids', 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Αυτοκίνητα', - 'aviation' => 'Αεροπορία', - 'crafts' => 'Χειροτεχνίες', - 'games' => 'Παιχνίδια', - 'hobbies' => 'Χόμπι', - 'home_and_garden' => 'Σπίτι & Κήπος', - 'video_games' => 'Βιντεοπαιχνίδια', - 'music_commentary' => 'Σχολιασμός Μουσικής', - 'music_history' => 'Ιστορία Μουσικής', - 'music_interviews' => 'Συνεντεύξεις Μουσικής', - 'business_news' => 'Επιχειρηματικά Νέα', - 'daily_news' => 'Καθημερινές Ειδήσεις', - 'entertainment_news' => 'Ειδήσεις ψυχαγωγίας', + 'automotive' => 'Automotive', + 'aviation' => 'Aviation', + 'crafts' => 'Crafts', + 'games' => 'Games', + 'hobbies' => 'Hobbies', + 'home_and_garden' => 'Home & Garden', + 'video_games' => 'Video Games', + 'music_commentary' => 'Music Commentary', + 'music_history' => 'Music History', + 'music_interviews' => 'Music Interviews', + 'business_news' => 'Business News', + 'daily_news' => 'Daily News', + 'entertainment_news' => 'Entertainment News', 'news_commentary' => 'News Commentary', - 'politics' => 'Πολιτική', - 'sports_news' => 'Αθλητικά νέα', - 'tech_news' => 'Ειδήσεις Τεχνολογίας', - 'buddhism' => 'Βουδισμός', - 'christianity' => 'Χριστιανισμός', + 'politics' => 'Politics', + 'sports_news' => 'Sports News', + 'tech_news' => 'Tech News', + 'buddhism' => 'Buddhism', + 'christianity' => 'Christianity', 'hinduism' => 'Hinduism', - 'islam' => 'Ισλαμισμός', - 'judaism' => 'Ιουδαϊσμός', - 'religion' => 'Θρησκεία', + 'islam' => 'Islam', + 'judaism' => 'Judaism', + 'religion' => 'Religion', 'spirituality' => 'Spirituality', 'astronomy' => 'Astronomy', 'chemistry' => 'Chemistry', @@ -292,39 +272,39 @@ return [ 'submit_edit' => 'Edit publication', 'cancel_publication' => 'Cancel publication', 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Έχοντας ένα μήνυμα αυξάνει την κοινωνική δέσμευση, με αποτέλεσμα μια καλύτερη ορατότητα για το podcast σας.', - 'message_warning_submit' => 'Δημοσίευση ούτως ή άλλως', + 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ - 'draft_mode' => 'λειτουργία πρόχειρου', - 'not_published' => 'Αυτό το podcast δεν έχει ακόμη δημοσιευθεί.', - 'scheduled' => 'Αυτό το podcast έχει προγραμματιστεί για δημοσίευση στις {publication_date}.', + 'draft_mode' => 'draft mode', + 'not_published' => 'This podcast is not yet published.', + 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => - "Διαγράφοντας το podcast θα διαγράψει όλα τα επεισόδια, τα αρχεία πολυμέσων, τις δημοσιεύσεις και τα αναλυτικά στοιχεία που σχετίζονται με αυτό. Αυτή η ενέργεια είναι μη αναστρέψιμη, δεν θα είστε σε θέση να τις ανακτήσετε αργότερα.", - 'understand' => 'Καταλαβαίνω, θέλω το podcast να διαγραφεί οριστικά', - 'submit' => 'Διαγραφή', + "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", + 'understand' => 'I understand, I want the podcast to be permanently deleted', + 'submit' => 'Delete', ], - 'by' => 'Από {publisher}', - 'season' => 'Σεζόν {seasonNumber}', - 'list_of_episodes_year' => '{year} επεισόδια ({episodeCount})', + 'by' => 'By {publisher}', + 'season' => 'Season {seasonNumber}', + 'list_of_episodes_year' => '{year} episodes ({episodeCount})', 'list_of_episodes_season' => - 'Σεζόν {seasonNumber} επεισόδεια ({episodeCount})', - 'no_episode' => 'Δεν βρέθηκε επεισόδιο!', - 'follow' => 'Ακολουθήστε', + 'Season {seasonNumber} episodes ({episodeCount})', + 'no_episode' => 'No episode found!', + 'follow' => 'Follow', 'followers' => '{numberOfFollowers, plural, - one {# ακόλουθος} - other {# ακόλουθοι} + one {# follower} + other {# followers} }', 'posts' => '{numberOfPosts, plural, - one {# δημοσίευση} - other {# δημοσιεύσεις} + one {# post} + other {# posts} }', - 'activity' => 'Δραστηριότητα', - 'episodes' => 'Επεισόδια', - 'sponsor' => 'Χορηγός', - 'funding_links' => 'Σύνδεσμοι χρηματοδότησης για το {podcastTitle}', - 'find_on' => 'Βρείτε το {podcastTitle} στο', - 'listen_on' => 'Ακούστε το', + 'activity' => 'Activity', + 'episodes' => 'Episodes', + 'sponsor' => 'Sponsor', + 'funding_links' => 'Funding links for {podcastTitle}', + 'find_on' => 'Find {podcastTitle} on', + 'listen_on' => 'Listen on', ]; diff --git a/modules/Admin/Language/el/PodcastImport.php b/modules/Admin/Language/el/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/el/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/el/PodcastNavigation.php b/modules/Admin/Language/el/PodcastNavigation.php index d5310a9a..b4d7ddc0 100644 --- a/modules/Admin/Language/el/PodcastNavigation.php +++ b/modules/Admin/Language/el/PodcastNavigation.php @@ -9,34 +9,30 @@ declare(strict_types=1); */ return [ - 'go_to_page' => 'Μετάβαση στη σελίδα podcast', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Πίνακας ελέγχου Podcast', - 'podcast-view' => 'Αρχική σελίδα', - 'podcast-edit' => 'Επεξεργασία podcast', - 'podcast-persons-manage' => 'Διαχείριση ατόμων', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Επεισόδια', - 'episode-list' => 'Όλα τα επεισόδια', - 'episode-create' => 'Νέο Επεισόδιο', - 'analytics' => 'Στατιστικά', - 'podcast-analytics' => 'Επισκόπηση κοινού', - 'podcast-analytics-webpages' => 'Επίσκεψη ιστοσελίδων', - 'podcast-analytics-locations' => 'Τοποθεσίες', - 'podcast-analytics-unique-listeners' => 'Μοναδικοί ακροατές', - 'podcast-analytics-players' => 'Αναπαραγωγές', - 'podcast-analytics-listening-time' => 'Χρόνος ακρόασης', - 'podcast-analytics-time-periods' => 'Χρονικές περίοδοι', - 'monetization' => 'Monetization', - 'subscription-list' => 'Όλες οι συνδρομές', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Συντελεστές', - 'contributor-list' => 'Όλοι οι συντελεστές', - 'contributor-add' => 'Προσθήκη συντελεστή', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Κοινωνικά δίκτυα', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'go_to_page' => 'Go to podcast page', + 'dashboard' => 'Podcast dashboard', + 'podcast-view' => 'Home', + 'podcast-edit' => 'Edit podcast', + 'podcast-persons-manage' => 'Manage persons', + 'episodes' => 'Episodes', + 'episode-list' => 'All episodes', + 'episode-create' => 'New episode', + 'analytics' => 'Analytics', + 'podcast-analytics' => 'Audience overview', + 'podcast-analytics-webpages' => 'Web pages visits', + 'podcast-analytics-locations' => 'Locations', + 'podcast-analytics-unique-listeners' => 'Unique listeners', + 'podcast-analytics-players' => 'Players', + 'podcast-analytics-listening-time' => 'Listening time', + 'podcast-analytics-time-periods' => 'Time periods', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', + 'contributors' => 'Contributors', + 'contributor-list' => 'All contributors', + 'contributor-add' => 'Add contributor', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', + 'platforms-social' => 'Social networks', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/el/Settings.php b/modules/Admin/Language/el/Settings.php index d4ff241b..4a70dcba 100644 --- a/modules/Admin/Language/el/Settings.php +++ b/modules/Admin/Language/el/Settings.php @@ -9,50 +9,50 @@ declare(strict_types=1); */ return [ - 'title' => 'Γενικές ρυθμίσεις', + 'title' => 'General settings', 'instance' => [ - 'title' => 'Διακομιστής', - 'site_icon' => 'Εικονίδιο ιστοσελίδας', - 'site_icon_delete' => 'Διαγραφή εικονιδίου ιστότοπου', - 'site_icon_hint' => 'Τα εικονίδια της ιστοσελίδας είναι αυτά που βλέπετε στις καρτέλες του προγράμματος περιήγησης, στη γραμμή σελιδοδεικτών, και όταν προσθέτετε μια ιστοσελίδα ως συντόμευση σε κινητές συσκευές.', - 'site_icon_helper' => 'Το εικονίδιο πρέπει να είναι τετράγωνο και τουλάχιστον 512px πλάτος και ψηλό.', - 'site_name' => 'Όνομα ιστοτόπου', - 'site_description' => 'Περιγραφή ιστοτόπου', - 'submit' => 'Αποθήκευση', - 'editSuccess' => 'Ο Διακομιστής έχει ενημερωθεί με επιτυχία!', - 'deleteIconSuccess' => 'Το εικονίδιο της ιστοσελίδας έχει καταργηθεί με επιτυχία!', + 'title' => 'Instance', + 'site_icon' => 'Site icon', + 'site_icon_delete' => 'Delete site icon', + 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', + 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', + 'site_name' => 'Site name', + 'site_description' => 'Site description', + 'submit' => 'Save', + 'editSuccess' => 'Instance has been updated successfully!', + 'deleteIconSuccess' => 'Site icon has been remove successfully!', ], 'images' => [ - 'title' => 'Εικόνες', - 'subtitle' => 'Εδώ μπορείτε να επαναδημιουργήσετε όλες τις εικόνες με βάση τα πρωτότυπα που φορτώθηκαν. Για να χρησιμοποιηθεί αν βρείτε κάποιες εικόνες που λείπουν. Αυτή η εργασία μπορεί να διαρκέσει λίγο.', - 'regenerate' => 'Αναδημιουργία εικόνων', - 'regenerationSuccess' => 'Όλες οι εικόνες έχουν δημιουργηθεί επιτυχώς!', + 'title' => 'Images', + 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', + 'regenerate' => 'Regenerate images', + 'regenerationSuccess' => 'All images have been regenerated successfully!', ], 'housekeeping' => [ 'title' => 'Housekeeping', 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Επαναφορά μετρήσεων', - 'reset_counts_helper' => 'Αυτή η επιλογή θα επαναϋπολογίσει και θα επαναφέρει όλους τους αριθμούς δεδομένων (αριθμός των ακολούθων, αναρτήσεις, σχόλια, …).', - 'rewrite_media' => 'Επανεγγραφή μεταδεδομένων πολυμέσων', - 'rewrite_media_helper' => 'Αυτή η επιλογή θα διαγράψει όλα τα περιττά αρχεία πολυμέσων και θα τα αναπαράγει (εικόνες, αρχεία ήχου, μεταγραφές, κεφάλαια, …)', - 'rename_episodes_files' => 'Μετονομασία αρχείων ήχου επεισοδίου', - 'rename_episodes_files_hint' => 'Αυτή η επιλογή θα μετονομάσει όλα τα αρχεία ήχου επεισόδια σε μια τυχαία συμβολοσειρά χαρακτήρων. Χρησιμοποιήστε αυτό αν διαρρεύσει ένας από τους ιδιωτικούς συνδέσμους επεισοδίων σας, καθώς αυτό θα τον αποκρύψει αποτελεσματικά.', - 'clear_cache' => 'Εκκαθάριση συνολικού cache', - 'clear_cache_helper' => 'Αυτή η επιλογή θα εκκαθαρίσει αρχεία cache redis ή εγγράψιμο/cache.', + 'reset_counts' => 'Reset counts', + 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', + 'rewrite_media' => 'Rewrite media metadata', + 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', + 'clear_cache' => 'Clear all cache', + 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', 'run' => 'Run housekeeping', 'runSuccess' => 'Housekeeping has been run successfully!', ], 'theme' => [ - 'title' => 'Θέμα', - 'accent_section_title' => 'Χρώμα έμφασης', - 'accent_section_subtitle' => 'Επιλέξτε το χρώμα για να καθορίσετε την εμφάνιση και την αίσθηση όλων των δημόσιων σελίδων.', - 'pine' => 'Πεύκο', - 'crimson' => 'Βυσσινί', - 'amber' => 'Κεχριμπάρι', - 'lake' => 'Λίμνη', + 'title' => 'Theme', + 'accent_section_title' => 'Accent color', + 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', + 'pine' => 'Pine', + 'crimson' => 'Crimson', + 'amber' => 'Amber', + 'lake' => 'Lake', 'jacaranda' => 'Jacaranda', - 'onyx' => 'Όνυξ', - 'submit' => 'Αποθήκευση', - 'setInstanceThemeSuccess' => 'Το θέμα έχει ενημερωθεί με επιτυχία!', + 'onyx' => 'Onyx', + 'submit' => 'Save', + 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', ], ]; diff --git a/modules/Admin/Language/el/Soundbite.php b/modules/Admin/Language/el/Soundbite.php index 122bdb1d..a3f828fe 100644 --- a/modules/Admin/Language/el/Soundbite.php +++ b/modules/Admin/Language/el/Soundbite.php @@ -10,22 +10,22 @@ declare(strict_types=1); return [ 'list' => [ - 'title' => 'Ήχοι', - 'soundbite' => 'Ήχος', + 'title' => 'Soundbites', + 'soundbite' => 'Soundbite', ], 'messages' => [ - 'createSuccess' => 'Το Soundbite δημιουργήθηκε με επιτυχία!', - 'deleteSuccess' => 'Το Soundbite αφαιρέθηκε με επιτυχία!', + 'createSuccess' => 'Soundbite has been successfully created!', + 'deleteSuccess' => 'Soundbite has been successfully removed!', ], 'form' => [ - 'title' => 'Νέο soundbite', - 'soundbite_title' => 'Τίτλος Soundbite', - 'start_time' => 'Έναρξη από', - 'duration' => 'Διάρκεια', - 'submit' => 'Δημιουργία soundbite', + 'title' => 'New soundbite', + 'soundbite_title' => 'Soundbite title', + 'start_time' => 'Start at', + 'duration' => 'Duration', + 'submit' => 'Create soundbite', ], - 'play' => 'Αναπαραγωγή soundbite', - 'stop' => 'Σταμάτημα soundbite', - 'create' => 'Νέο soundbite', - 'delete' => 'Διαγραφή soundbite', + 'play' => 'Play soundbite', + 'stop' => 'Stop soundbite', + 'create' => 'New soundbite', + 'delete' => 'Delete soundbite', ]; diff --git a/modules/Auth/Language/id/User.php b/modules/Admin/Language/el/User.php similarity index 73% rename from modules/Auth/Language/id/User.php rename to modules/Admin/Language/el/User.php index e7908f5b..585d6799 100644 --- a/modules/Auth/Language/id/User.php +++ b/modules/Admin/Language/el/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Edit {username}'s role", + 'edit_roles' => "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', 'ban' => 'Ban', 'unban' => 'Unban', 'delete' => 'Delete', @@ -18,7 +19,7 @@ return [ 'all_users' => 'All users', 'list' => [ 'user' => 'User', - 'role' => 'Role', + 'roles' => 'Roles', 'banned' => 'Banned?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Username', 'password' => 'Password', 'new_password' => 'New Password', - 'role' => 'Role', 'roles' => 'Roles', 'permissions' => 'Permissions', 'submit_create' => 'Create user', 'submit_edit' => 'Save', 'submit_password_change' => 'Change!', ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', + 'roles' => [ + 'superadmin' => 'Super admin', ], 'messages' => [ 'createSuccess' => 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', 'banSuccess' => '{username} has been banned.', 'unbanSuccess' => '{username} has been unbanned.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', 'deleteSuperAdminError' => '{username} is a superadmin, one does not simply delete a superadmin…', 'deleteSuccess' => '{username} has been deleted.', diff --git a/modules/Admin/Language/el/Validation.php b/modules/Admin/Language/el/Validation.php index 2c5bcf7c..750b1968 100644 --- a/modules/Admin/Language/el/Validation.php +++ b/modules/Admin/Language/el/Validation.php @@ -10,8 +10,9 @@ declare(strict_types=1); return [ 'min_dims' => - '{field} είτε δεν είναι μια εικόνα, είτε δεν είναι αρκετά ευρεία ή ψηλή.', + '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => - '{field} είτε δεν είναι εικόνα είτε όχι της σωστής αναλογίας.', - 'is_json' => '{field} contains invalid JSON.', + '{field} is either not an image or not of the right ratio.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/el/VideoClip.php b/modules/Admin/Language/el/VideoClip.php index 64388b13..638de697 100644 --- a/modules/Admin/Language/el/VideoClip.php +++ b/modules/Admin/Language/el/VideoClip.php @@ -10,63 +10,63 @@ declare(strict_types=1); return [ 'list' => [ - 'title' => 'Βίντεο κλιπ', + 'title' => 'Video clips', 'status' => [ - 'label' => 'Κατάσταση', - 'queued' => 'στην ουρά', - 'queued_hint' => 'Το κλιπ περιμένει να υποβληθεί σε επεξεργασία.', - 'pending' => 'εκκρεμεί', - 'pending_hint' => 'Το κλιπ θα δημιουργηθεί σύντομα.', - 'running' => 'εκτελείται', - 'running_hint' => 'Το κλιπ δημιουργείται.', - 'failed' => 'απέτυχε', - 'failed_hint' => 'Το κλιπ δεν μπόρεσε να δημιουργηθεί: αποτυχία δέσμης ενεργειών.', + 'label' => 'Status', + 'queued' => 'queued', + 'queued_hint' => 'Clip is waiting to be processed.', + 'pending' => 'pending', + 'pending_hint' => 'Clip will be generated shortly.', + 'running' => 'running', + 'running_hint' => 'Clip is being generated.', + 'failed' => 'failed', + 'failed_hint' => 'Clip could not be generated: script failure.', 'passed' => 'passed', - 'passed_hint' => 'Το κλιπ δημιουργήθηκε με επιτυχία!', + 'passed_hint' => 'Clip was generated successfully!', ], - 'clip' => 'Αποσπάσματα', - 'duration' => 'Διάρκεια εργασίας', + 'clip' => 'Clip', + 'duration' => 'Job duration', ], - 'title' => 'Βίντεο κλιπ: {videoClipLabel}', - 'download_clip' => 'Κατεβάστε το κλιπ', - 'create' => 'Νέο βίντεο κλιπ', + 'title' => 'Video clip: {videoClipLabel}', + 'download_clip' => 'Download clip', + 'create' => 'New video clip', 'go_to_page' => 'Go to clip page', 'retry' => 'Retry clip generation', - 'delete' => 'Διαγραφή κλιπ', - 'logs' => 'Αρχεία καταγραφής εργασίας', + 'delete' => 'Delete clip', + 'logs' => 'Job logs', 'messages' => [ - 'alreadyExistingError' => 'Το βίντεο κλιπ που προσπαθείτε να δημιουργήσετε υπάρχει ήδη!', - 'addToQueueSuccess' => 'Το βίντεο κλιπ έχει προστεθεί στην ουρά αναμονής, αναμένοντας να δημιουργηθεί!', - 'deleteSuccess' => 'Το βίντεο κλιπ αφαιρέθηκε με επιτυχία!', + 'alreadyExistingError' => 'The video clip you are trying to create already exists!', + 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', + 'deleteSuccess' => 'Video clip has been successfully removed!', ], 'format' => [ - 'landscape' => 'Οριζόντια', - 'portrait' => 'Κατακόρυφα', - 'squared' => 'Τετράγωνα', + 'landscape' => 'Landscape', + 'portrait' => 'Portrait', + 'squared' => 'Squared', ], 'form' => [ - 'title' => 'Νέο βίντεο κλιπ', - 'params_section_title' => 'Παράμετροι βίντεο κλιπ', - 'clip_title' => 'Τίτλος κλιπ', + 'title' => 'New video clip', + 'params_section_title' => 'Video clip parameters', + 'clip_title' => 'Clip title', 'format' => [ - 'label' => 'Επιλογή μορφής', - 'landscape_hint' => 'Με αναλογία 16:9, τα βίντεο τοπίου είναι υπέροχα για το PeerTube, το Youtube και το Vimeo.', - 'portrait_hint' => 'Με αναλογία 9:16, πορτρέτο βίντεο είναι μεγάλη για TikTok, shorts Youtube και ιστορίες Instagram.', - 'squared_hint' => 'Με αναλογία 1:1, τα τετράγωνα βίντεο είναι υπέροχα για Mastodon, Facebook, Twitter και LinkedIn.', + 'label' => 'Choose a format', + 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', + 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', + 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', ], - 'theme' => 'Επιλογή θέματος', - 'start_time' => 'Έναρξη από', - 'duration' => 'Διάρκεια', - 'trim_start' => 'Περικοπή έναρξης', - 'trim_end' => 'Περικοπή τέλους', - 'submit' => 'Δημιουργία βίντεο κλιπ', + 'theme' => 'Select a theme', + 'start_time' => 'Start at', + 'duration' => 'Duration', + 'trim_start' => 'Trim start', + 'trim_end' => 'Trim end', + 'submit' => 'Create video clip', ], 'requirements' => [ - 'title' => 'Λείπουν προαπαιτούμενα', - 'missing' => 'Έχετε απαιτήσεις που λείπουν. Σιγουρευτείτε ότι προσθέστε όλα τα απαιτούμενα στοιχεία για να μπορέσετε να δημιουργήσετε ένα βίντεο για αυτό το επεισόδιο!', + 'title' => 'Missing requirements', + 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', 'ffmpeg' => 'FFmpeg', - 'gd' => 'Σχεδίαση Γραφικών (GD)', - 'freetype' => 'Βιβλιοθήκη Freetype για GD', - 'transcript' => 'Αρχείο απομαγνητοφώνησης (.srt)', + 'gd' => 'Graphics Draw (GD)', + 'freetype' => 'Freetype library for GD', + 'transcript' => 'Transcript file (.srt)', ], ]; diff --git a/modules/Admin/Language/en/AboutCastopod.php b/modules/Admin/Language/en/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/en/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/en/Breadcrumb.php b/modules/Admin/Language/en/Breadcrumb.php index fedd6b19..f3269bfa 100644 --- a/modules/Admin/Language/en/Breadcrumb.php +++ b/modules/Admin/Language/en/Breadcrumb.php @@ -19,30 +19,24 @@ return [ 'pages' => 'pages', 'settings' => 'settings', 'theme' => 'theme', - 'about' => 'about', 'add' => 'add', 'new' => 'new', 'edit' => 'edit', - 'plugins' => 'plugins', 'persons' => 'persons', 'publish' => 'publish', 'publish-edit' => 'edit publication', 'publish-date-edit' => 'edit publication date', 'unpublish' => 'unpublish', 'delete' => 'delete', - 'remove' => 'remove', 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'block lists', 'users' => 'users', 'my-account' => 'my account', 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'feed import', 'platforms' => 'platforms', 'social' => 'social networks', 'funding' => 'funding', - 'monetization-other' => 'other monetization', 'analytics' => 'analytics', 'locations' => 'locations', 'webpages' => 'web pages', diff --git a/modules/Admin/Language/en/Charts.php b/modules/Admin/Language/en/Charts.php index 6ede2510..4b33530e 100644 --- a/modules/Admin/Language/en/Charts.php +++ b/modules/Admin/Language/en/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/en/Common.php b/modules/Admin/Language/en/Common.php index 4dff9dd4..596c8bcd 100644 --- a/modules/Admin/Language/en/Common.php +++ b/modules/Admin/Language/en/Common.php @@ -38,13 +38,8 @@ return [ 'noChoicesText' => 'No choices to choose from', 'maxItemText' => 'Cannot add more items', ], - 'fieldArray' => [ - 'add' => 'Add', - 'remove' => 'Remove', - ], 'upload_file' => 'Upload a file', 'remote_url' => 'Remote URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Play', diff --git a/modules/Auth/Language/fr-ca/Contributor.php b/modules/Admin/Language/en/Contributor.php similarity index 70% rename from modules/Auth/Language/fr-ca/Contributor.php rename to modules/Admin/Language/en/Contributor.php index c70badc0..d0f3b93d 100644 --- a/modules/Auth/Language/fr-ca/Contributor.php +++ b/modules/Admin/Language/en/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Add contributor', 'submit_edit' => 'Update role', ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', + 'roles' => [ + 'podcast_admin' => 'Podcast admin', ], 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", 'removeOwnerError' => "You can't remove the podcast owner!", 'removeSuccess' => 'You have successfully removed {username} from {podcastTitle}', diff --git a/modules/Admin/Language/en/Episode.php b/modules/Admin/Language/en/Episode.php index f7eb1290..91313a7c 100644 --- a/modules/Admin/Language/en/Episode.php +++ b/modules/Admin/Language/en/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'All podcast episodes', 'back_to_podcast' => 'Go back to podcast', 'edit' => 'Edit', - 'preview' => 'Preview', 'publish' => 'Publish', 'publish_edit' => 'Edit publication', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episode', 'visibility' => 'Visibility', - 'downloads' => 'Downloads', 'comments' => 'Comments', 'actions' => 'Actions', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -109,11 +107,11 @@ return [ 'type' => [ 'label' => 'Type', 'full' => 'Full', - 'full_description' => 'Complete content (the episode)', + 'full_hint' => 'Complete content (the episode)', 'trailer' => 'Trailer', - 'trailer_description' => 'Short, promotional piece of content that represents a preview of the current show', + 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', 'bonus' => 'Bonus', - 'bonus_description' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', + 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', ], 'premium_title' => 'Premium', 'premium' => 'Episode must be accessible to premium subscribers only', @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'Chapters', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Admin/Language/en/EpisodeNavigation.php b/modules/Admin/Language/en/EpisodeNavigation.php index ef3cdec0..1406e301 100644 --- a/modules/Admin/Language/en/EpisodeNavigation.php +++ b/modules/Admin/Language/en/EpisodeNavigation.php @@ -20,5 +20,4 @@ return [ 'video-clips-create' => 'New video clip', 'soundbites-list' => 'Soundbites', 'soundbites-create' => 'New soundbite', - 'plugins' => 'Plugins', ]; diff --git a/modules/Auth/Language/da/MyAccount.php b/modules/Admin/Language/en/MyAccount.php similarity index 100% rename from modules/Auth/Language/da/MyAccount.php rename to modules/Admin/Language/en/MyAccount.php diff --git a/modules/Admin/Language/en/Navigation.php b/modules/Admin/Language/en/Navigation.php index fc7cfc30..68d4609d 100644 --- a/modules/Admin/Language/en/Navigation.php +++ b/modules/Admin/Language/en/Navigation.php @@ -12,16 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Dashboard', 'admin' => 'Home', 'podcasts' => 'Podcasts', 'podcast-list' => 'All podcasts', 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'plugins' => 'Plugins', - 'plugins-installed' => 'Installed', + 'podcast-import' => 'Import a podcast', 'persons' => 'Persons', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -37,7 +33,6 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Admin/Language/en/Platforms.php b/modules/Admin/Language/en/Platforms.php index e161181c..ab17d599 100644 --- a/modules/Admin/Language/en/Platforms.php +++ b/modules/Admin/Language/en/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Platforms', 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', 'remove' => 'Remove {platformName}', diff --git a/modules/Admin/Language/en/Podcast.php b/modules/Admin/Language/en/Podcast.php index 89fa9491..426b763b 100644 --- a/modules/Admin/Language/en/Podcast.php +++ b/modules/Admin/Language/en/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No podcast found!', 'create' => 'Create podcast', 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'New Episode', 'view' => 'View podcast', 'edit' => 'Edit podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Delete podcast', 'see_episodes' => 'See episodes', 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Go to page', 'latest_episodes' => 'Latest episodes', 'see_all_episodes' => 'See all episodes', @@ -50,6 +48,7 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', @@ -72,19 +69,9 @@ return [ 'type' => [ 'label' => 'Type', 'episodic' => 'Episodic', - 'episodic_description' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', + 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_description' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_description' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_description' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_description' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], 'description' => 'Description', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,14 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'redirect_to_new_feed' => 'Automatically redirect to new feed (301 redirect)', - 'redirect_to_new_feed_hint' => 'Check this when migrating your Castopod RSS feed to the new feed url set above. To ensure followers receive your most recent episodes from the new feed URL, maintain this redirect and the tag in your new feed for at least four weeks.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -153,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/en/PodcastImport.php b/modules/Admin/Language/en/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/en/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/en/PodcastNavigation.php b/modules/Admin/Language/en/PodcastNavigation.php index a6b73e4a..b4d7ddc0 100644 --- a/modules/Admin/Language/en/PodcastNavigation.php +++ b/modules/Admin/Language/en/PodcastNavigation.php @@ -10,17 +10,13 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'Home', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodes', 'episode-list' => 'All episodes', 'episode-create' => 'New episode', - 'plugins' => 'Plugins', 'analytics' => 'Analytics', 'podcast-analytics' => 'Audience overview', 'podcast-analytics-webpages' => 'Web pages visits', @@ -29,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Auth/Language/it/User.php b/modules/Admin/Language/en/User.php similarity index 73% rename from modules/Auth/Language/it/User.php rename to modules/Admin/Language/en/User.php index e7908f5b..585d6799 100644 --- a/modules/Auth/Language/it/User.php +++ b/modules/Admin/Language/en/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Edit {username}'s role", + 'edit_roles' => "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', 'ban' => 'Ban', 'unban' => 'Unban', 'delete' => 'Delete', @@ -18,7 +19,7 @@ return [ 'all_users' => 'All users', 'list' => [ 'user' => 'User', - 'role' => 'Role', + 'roles' => 'Roles', 'banned' => 'Banned?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Username', 'password' => 'Password', 'new_password' => 'New Password', - 'role' => 'Role', 'roles' => 'Roles', 'permissions' => 'Permissions', 'submit_create' => 'Create user', 'submit_edit' => 'Save', 'submit_password_change' => 'Change!', ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', + 'roles' => [ + 'superadmin' => 'Super admin', ], 'messages' => [ 'createSuccess' => 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', 'banSuccess' => '{username} has been banned.', 'unbanSuccess' => '{username} has been unbanned.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', 'deleteSuperAdminError' => '{username} is a superadmin, one does not simply delete a superadmin…', 'deleteSuccess' => '{username} has been deleted.', diff --git a/modules/Admin/Language/en/Validation.php b/modules/Admin/Language/en/Validation.php index 4db0fe89..750b1968 100644 --- a/modules/Admin/Language/en/Validation.php +++ b/modules/Admin/Language/en/Validation.php @@ -13,7 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', - 'is_boolean' => 'The {field} field must be a boolean (true or false).', - 'is_list' => 'The {field} field must be an array.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/es/AboutCastopod.php b/modules/Admin/Language/es/AboutCastopod.php deleted file mode 100644 index 93d4142b..00000000 --- a/modules/Admin/Language/es/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Acerca de Castopod', - 'host_name' => 'Nombre del host', - 'version' => 'Versión de Castopod', - 'php_version' => 'Versión de PHP', - 'os' => 'Sistema Operativo', - 'languages' => 'Idiomas', - 'update_database' => 'Actualizar base de datos', - 'messages' => [ - 'databaseUpdateSuccess' => 'La base de datos esta actualizada!', - ], -]; diff --git a/modules/Admin/Language/es/Breadcrumb.php b/modules/Admin/Language/es/Breadcrumb.php index 6ffb6387..621ca94e 100644 --- a/modules/Admin/Language/es/Breadcrumb.php +++ b/modules/Admin/Language/es/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Inicio', 'podcasts' => 'podcasts', 'episodes' => 'episodios', - 'subscriptions' => 'suscripciones', + 'subscriptions' => 'subscriptions', 'contributors' => 'colaboradores', 'pages' => 'páginas', 'settings' => 'configuración', 'theme' => 'tema', - 'about' => 'acerca de', 'add' => 'añadir', 'new' => 'nuevo', 'edit' => 'editar', 'persons' => 'personas', 'publish' => 'publicar', 'publish-edit' => 'editar publicación', - 'publish-date-edit' => 'editar fecha de publicación', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'anular publicación', 'delete' => 'borrar', - 'remove' => 'eliminar', 'fediverse' => 'fediverso', - 'blocked-actors' => 'actores bloqueado', - 'blocked-domains' => 'dominios bloqueados', + 'block-lists' => 'listas de bloqueo', 'users' => 'usuarios', 'my-account' => 'mi cuenta', 'change-password' => 'cambiar contraseña', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'importar feed', 'platforms' => 'plataformas', 'social' => 'redes sociales', 'funding' => 'financiación | fondos', - 'monetization-other' => 'other monetization', 'analytics' => 'estadísticas', 'locations' => 'ubicaciones', 'webpages' => 'páginas web', @@ -53,5 +48,5 @@ return [ 'video-clips' => 'clips de vídeo', 'embed' => 'reproductor embebido', 'notifications' => 'notificaciones', - 'suspend' => 'suspender', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/es/Charts.php b/modules/Admin/Language/es/Charts.php index 7294231c..fee7dda4 100644 --- a/modules/Admin/Language/es/Charts.php +++ b/modules/Admin/Language/es/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Ancho de banda diario usado (en MB)', 'total_storage_by_month' => 'Almacenamiento mensual (en MB)', 'total_bandwidth_by_month' => 'Ancho de banda mensual usado (en MB)', - 'total_bandwidth_by_month_limit' => 'Limitado a {totalBandwidth} al mes', ]; diff --git a/modules/Admin/Language/es/Common.php b/modules/Admin/Language/es/Common.php index ff3987cc..b64ee73d 100644 --- a/modules/Admin/Language/es/Common.php +++ b/modules/Admin/Language/es/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Subir un archivo', 'remote_url' => 'URL remoto', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Reproducir', diff --git a/modules/Auth/Language/es/Contributor.php b/modules/Admin/Language/es/Contributor.php similarity index 72% rename from modules/Auth/Language/es/Contributor.php rename to modules/Admin/Language/es/Contributor.php index d5b3a256..7cd774b2 100644 --- a/modules/Auth/Language/es/Contributor.php +++ b/modules/Admin/Language/es/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Añadir colaborador', 'submit_edit' => 'Actualizar Cargo', ], - 'delete_form' => [ - 'title' => 'Eliminar {contributor}', - 'disclaimer' => - 'Estás a punto de eliminar a {contributor} de los colaboradores. Ya no podrán acceder a "{podcastTitle}".', - 'understand' => 'Entiendo, quiero eliminar a {contributor} de "{podcastTitle}"', - 'submit' => 'Eliminar', + 'roles' => [ + 'podcast_admin' => 'Administrador del Podcast', ], 'messages' => [ - 'editSuccess' => '¡Rol cambiado con éxito!', - 'editOwnerError' => "¡No puedes editar el dueño del podcast!", 'removeOwnerError' => "¡No puedes eliminar al dueño del podcast!", 'removeSuccess' => 'Has eliminado con éxito a {username} de {podcastTitle}', diff --git a/modules/Admin/Language/es/Episode.php b/modules/Admin/Language/es/Episode.php index 48f93ad4..4cb492e8 100644 --- a/modules/Admin/Language/es/Episode.php +++ b/modules/Admin/Language/es/Episode.php @@ -22,17 +22,16 @@ return [ 'all_podcast_episodes' => 'Todos los episodios del podcast', 'back_to_podcast' => 'Regresar al podcast', 'edit' => 'Editar', - 'preview' => 'Preview', 'publish' => 'Publicar', 'publish_edit' => 'Editar publicación', - 'publish_date_edit' => 'Editar fecha de publicación', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Anular publicación', 'publish_error' => 'El episodio ya está publicado.', 'publish_edit_error' => 'El episodio ya está publicado.', 'publish_cancel_error' => 'El episodio ya está publicado.', - 'publish_date_edit_error' => 'El episodio no ha sido publicado todavía, no puede editar su fecha de publicación.', - 'publish_date_edit_future_error' => '¡La fecha de publicación del episodio sólo puede establecerse a una fecha pasada! Si desea reprogramarla, despublicarla primero.', - 'publish_date_edit_success' => '¡La fecha de publicación del episodio se ha actualizado con éxito!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'El episodio no está publicado.', 'delete' => 'Borrar', 'go_to_page' => 'Ir a la página', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episodio', 'visibility' => 'Visibilidad', - 'downloads' => 'Descargas', 'comments' => 'Comentarios', 'actions' => 'Acciones', ], @@ -81,13 +79,13 @@ return [ audio {audio} other {media} }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', + 'deleteFileError' => 'Hubo un problema al tratar de eliminar el archivo {file_path} {type, select, + transcript {de la transcripción} + chapters {de los episodios} + image {de la portada} + audio {del audio} + other {} + }. Puedes eliminarlo manualmente de tu disco.', 'sameSlugError' => 'Ya existe un episodio con el slug elegido.', ], 'form' => [ @@ -116,7 +114,7 @@ return [ 'bonus_hint' => 'Contenido extra para la serie (por ejemplo, detrás de escenas o entrevistas con el elenco) o contenido promocional para otra serie', ], 'premium_title' => 'Premium', - 'premium' => 'El episodio debe ser accesible solamente para los suscriptores premium', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Aviso parental', 'hint' => '¿El episodio contiene contenido explícito?', @@ -139,9 +137,9 @@ return [ 'location_name' => 'Nombre o dirección de ubicación', 'location_name_hint' => 'Esta puede ser una ubicación real o ficticia', 'transcript' => 'Transcripción (subtítulos / subtítulos ocultos)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Sólo se permiten .srt.', 'transcript_download' => 'Descargar transcripción', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Archivo de transcripción (.srt)', 'transcript_remote_url' => 'Url remota para transcripción', 'transcript_file_delete' => 'Eliminar archivo de transcripción', 'chapters' => 'Capítulos', @@ -185,9 +183,9 @@ return [ 'message_warning_submit' => 'Publicar de todos modos', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nueva fecha de publicación', - 'new_publication_date_hint' => 'Debe establecerse en una fecha pasada.', - 'submit' => 'Editar fecha de publicación', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => @@ -212,14 +210,4 @@ return [ 'light' => 'Claro', 'light-transparent' => 'Transparente claro', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/es/MyAccount.php b/modules/Admin/Language/es/MyAccount.php similarity index 100% rename from modules/Auth/Language/es/MyAccount.php rename to modules/Admin/Language/es/MyAccount.php diff --git a/modules/Admin/Language/es/Navigation.php b/modules/Admin/Language/es/Navigation.php index c8936b27..43c58893 100644 --- a/modules/Admin/Language/es/Navigation.php +++ b/modules/Admin/Language/es/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Ocultar/mostrar barra lateral', 'go_to_website' => 'Ir al sitio web', 'go_to_admin' => 'Ir al panel de administración', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Panel de control', 'admin' => 'Inicio', 'podcasts' => 'Podcasts', 'podcast-list' => 'Todos los podcasts', 'podcast-create' => 'Nuevo podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Importar un podcast', 'persons' => 'Personas', 'person-list' => 'Todas las personas', 'person-create' => 'Nueva persona', @@ -35,7 +33,6 @@ return [ 'settings' => 'Configuración', 'settings-general' => 'General', 'settings-theme' => 'Tema', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'Mi cuenta', 'change-password' => 'Cambiar contraseña', diff --git a/modules/Admin/Language/es/Notifications.php b/modules/Admin/Language/es/Notifications.php index 70e375fb..d6c93ba9 100644 --- a/modules/Admin/Language/es/Notifications.php +++ b/modules/Admin/Language/es/Notifications.php @@ -13,7 +13,7 @@ return [ 'reply' => '{actor_username} respondió a tu publicación', 'favourite' => '{actor_username} ha marcado como favorita tu publicación', 'reblog' => '{actor_username} ha compartido tu publicación', - 'follow' => '{actor_username} ha empezado a seguirte', + 'follow' => '{actor_username} started following you', 'no_notifications' => 'No hay notificaciones', 'mark_all_as_read' => 'Marcar todas como leídas', ]; diff --git a/modules/Admin/Language/es/Platforms.php b/modules/Admin/Language/es/Platforms.php index f045e36c..48effd90 100644 --- a/modules/Admin/Language/es/Platforms.php +++ b/modules/Admin/Language/es/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Plataformas', 'home_url' => 'Ir al sitio web de {platformName}', - 'register' => 'Register', 'submit_url' => 'Envía tu podcast en {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => '¿Mostrar en la página de inicio del podcast?', 'on_embed' => '¿Mostrar en el reproductor incrustable?', 'remove' => 'Eliminar {platformName}', diff --git a/modules/Admin/Language/es/Podcast.php b/modules/Admin/Language/es/Podcast.php index 3786cfda..c10b2374 100644 --- a/modules/Admin/Language/es/Podcast.php +++ b/modules/Admin/Language/es/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No se encontró el podcast!', 'create' => 'Crear podcasts', 'import' => 'Importar un podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'Nuevo episodio', 'view' => 'Ver Podcast', 'edit' => 'Editar el Podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Eliminar podcast', 'see_episodes' => 'Ver episodios', 'see_contributors' => 'Ver colaboradores', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Ir a la página', 'latest_episodes' => 'Últimos Episodios', 'see_all_episodes' => 'Mostrar todos los episodios', @@ -50,6 +48,7 @@ return [ other {se han añadido # episodios} } al podcast!', 'podcastFeedUpToDate' => 'El Podcast ya está actualizado.', + 'podcastNotImported' => 'Podcast no pudo ser actualizado porque no fue importado.', 'publishError' => 'Este podcast ya ha sido publicado o está programado para su publicación.', 'publishEditError' => 'Este podcast no está programado para ser publicado.', 'publishCancelSuccess' => '¡La publicación del podcast ha sido cancelada con éxito!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Identidad de Podcast', 'identity_section_subtitle' => 'Estos campos le permiten recibir un aviso.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Portada de Podcast', 'cover_size_hint' => 'La portada debe ser cuadrada y con al menos 1400 px de ancho y alto.', 'banner' => 'Cartel del Podcast', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Por episodios', 'episodic_hint' => 'Si los episodios están destinados a ser consumidos sin ningún orden específico. Los episodios más nuevos serán presentados primero.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'Si los episodios están destinados a ser consumidos en orden secuencial. Los episodios más antiguos serán presentados primero.', ], 'description' => 'Descripción', 'classification_section_title' => 'Clasificación', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Email del propietario', 'owner_email_hint' => 'Será utilizado por la mayoría de las plataformas para verificar la propiedad del podcast. Visible en el feed RSS público.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publicador', 'publisher_hint' => 'El grupo responsable de la creación del espectáculo. A menudo se refiere a la empresa matriz o red de un podcast. Este campo a veces se etiqueta como \'Autor\'.', @@ -123,13 +108,8 @@ return [ 'monetization_section_subtitle' => 'Gana dinero gracias a tu audiencia.', 'premium' => 'Premium', - 'premium_by_default' => 'Los episodios deben establecerse como premium por defecto', - 'premium_by_default_hint' => 'Los episodios Podcast se marcarán como premium de forma predeterminada. Todavía puedes elegir establecer algunos episodios, trailers o bonificaciones como públicos.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Analiza tus datos de estadísticas con OP3, un servicio de analíticas fiable y de código abierto. Comparte, valida y compara tus estadísticas con el ecosistema de podcasting abierto.', - 'op3_enable' => 'Activa el servicio de estadísticas OP3', - 'op3_enable_hint' => 'Por motivos de seguridad, las estadísticas de los episodios premium no serán compartidas con OP3.', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', 'payment_pointer' => 'Puntero de pago para Monetización web', 'payment_pointer_hint' => 'Aquí es donde usted recibirá dinero gracias a la Monetización Web', @@ -138,12 +118,11 @@ return [ 'Si necesita etiquetas RSS que Castopod no maneja, póngalas aquí.', 'custom_rss' => 'Etiquetas RSS personalizadas para el podcast', 'custom_rss_hint' => 'Esto se inyectará dentro de la etiqueta de canal.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'Nueva URL de feed', 'new_feed_url_hint' => 'Utilice este campo cuando se mueva a otro dominio o plataforma de alojamiento podcast. De forma predeterminada, el valor se establece en la URL actual de RSS si el podcast es importado.', 'old_feed_url' => 'Antigua URL del feed RSS', + 'update_feed' => 'Actualizar el feed', + 'update_feed_tip' => 'Importar los últimos episodios de este podcast', 'partnership' => 'Asociación', 'partner_id' => 'ID', 'partner_link_url' => 'URL del enlace', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Su propio ID de socio', 'partner_link_url_hint' => 'La dirección genérica de enlace de socio', 'partner_image_url_hint' => 'La dirección de imagen genérica del socio', + 'status_section_title' => 'Estado', 'block' => 'El podcast debe ocultarse a los catálogos públicos', 'block_hint' => 'El estado de visibilidad del podcast: al activar esto se impide que este podcast al completo aparezca en Apple Podcasts, Google Podcasts y cualquier aplicación de terceros que extraiga episodios de estos directorios. (no está garantizado al 100%)', diff --git a/modules/Admin/Language/es/PodcastImport.php b/modules/Admin/Language/es/PodcastImport.php new file mode 100644 index 00000000..96cef94d --- /dev/null +++ b/modules/Admin/Language/es/PodcastImport.php @@ -0,0 +1,37 @@ + + 'Este procedimiento puede llevar mucho tiempo. Como la versión actual no muestra ningún progreso mientras se ejecuta, no verás nada actualizado hasta que termine. En el caso de recibir un mensaje de error por falta de tiempo (Timeout error), incrementa el valor `max_execution_time` en la configuración del PHP del servidor.', + 'old_podcast_section_title' => 'Podcasts para importar', + 'old_podcast_section_subtitle' => + 'Asegúrese de que tiene los derechos para este podcast antes de importarlo. Copiar y difundir un podcast sin los derechos apropiados es piratería y puede ser procesado.', + 'imported_feed_url' => 'URL del Feed', + 'imported_feed_url_hint' => 'El feed debe estar en formato xml o rss.', + 'new_podcast_section_title' => 'El nuevo Podcast', + 'advanced_params_section_title' => 'Parámetros avanzados', + 'advanced_params_section_subtitle' => + 'Mantenga los valores por defecto si no tiene idea de para qué sirven los campos.', + 'slug_field' => 'Campo a utilizar para calcular el slug de episodio', + 'description_field' => + 'Campo de origen usado para la descripción del episodio / mostrar notas', + 'force_renumber' => 'Forzar renumeración de episodios', + 'force_renumber_hint' => + 'Utilice esto si su podcast no tiene números de episodios pero desea establecerlos durante la importación.', + 'season_number' => 'Número de Temporada', + 'season_number_hint' => + 'Utilice esto si su podcast no tiene un número de temporada pero desea establecer uno durante la importación. Deje en blanco de lo contrario.', + 'max_episodes' => 'Número máximo de episodios a importar', + 'max_episodes_hint' => 'Dejar en blanco para importar todos los episodios', + 'lock_import' => + 'Este feed está protegido. No puedes importarlo. Si eres el propietario, debes desprotegerlo en la plataforma de origen.', + 'submit' => 'Importar podcast', +]; diff --git a/modules/Admin/Language/es/PodcastNavigation.php b/modules/Admin/Language/es/PodcastNavigation.php index 43a142bb..8bbe1733 100644 --- a/modules/Admin/Language/es/PodcastNavigation.php +++ b/modules/Admin/Language/es/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Ir a la página del podcast', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Panel de Podcast', 'podcast-view' => 'Inicio', 'podcast-edit' => 'Editar podcast', 'podcast-persons-manage' => 'Administrar personas', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodios', 'episode-list' => 'Todos los episodios', 'episode-create' => 'Nuevo episodio', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Reproductores', 'podcast-analytics-listening-time' => 'Tiempo de escucha', 'podcast-analytics-time-periods' => 'Periodos de tiempo', - 'monetization' => 'Monetization', - 'subscription-list' => 'Todas las suscripciones', - 'subscription-create' => 'Add subscription', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', 'contributors' => 'Colaboradores', 'contributor-list' => 'Todos los colaboradores', 'contributor-add' => 'Añadir colaborador', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'Plataformas externas', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Redes sociales', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Financiamiento', ]; diff --git a/modules/Admin/Language/es/Settings.php b/modules/Admin/Language/es/Settings.php index 6c63c82d..245ee615 100644 --- a/modules/Admin/Language/es/Settings.php +++ b/modules/Admin/Language/es/Settings.php @@ -35,8 +35,8 @@ return [ 'reset_counts_helper' => 'Esta opción recalculará y restablecerá todos los conteos de datos (número de seguidores, publicaciones, comentarios, …).', 'rewrite_media' => 'Reescribir metadatos de medios', 'rewrite_media_helper' => 'Esta opción eliminará todos los archivos multimedia superfluos y los volverá a crear (imágenes, archivos de audio, transcripciones, capítulos, …)', - 'rename_episodes_files' => 'Renombrar archivos de audio del episodio', - 'rename_episodes_files_hint' => 'Esta opción renombrará todos los archivos de audio de episodios a una cadena aleatoria de caracteres. Usa esto si uno de tus episodios privados fue filtrado ya que esto lo ocultará efectivamente.', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', 'clear_cache' => 'Borrar toda la caché', 'clear_cache_helper' => 'Esta opción eliminará la caché de redis o archivos de escritura/caché.', 'run' => 'Ejecutar tareas de mantenimiento', diff --git a/modules/Auth/Language/es/User.php b/modules/Admin/Language/es/User.php similarity index 74% rename from modules/Auth/Language/es/User.php rename to modules/Admin/Language/es/User.php index ce11ceb6..1b37eec2 100644 --- a/modules/Auth/Language/es/User.php +++ b/modules/Admin/Language/es/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Editar rol de {username}", + 'edit_roles' => "Editar rol de {username}", + 'forcePassReset' => 'Forzar el reseteo de la contraseña', 'ban' => 'Banear', 'unban' => 'Desbanear', 'delete' => 'Borrar', @@ -18,7 +19,7 @@ return [ 'all_users' => 'Todos los usuarios', 'list' => [ 'user' => 'Usuario', - 'role' => 'Rol', + 'roles' => 'Roles', 'banned' => '¿Baneado?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Nombre de usuario', 'password' => 'Contraseña', 'new_password' => 'Nueva Contraseña', - 'role' => 'Rol', 'roles' => 'Roles', 'permissions' => 'Permisos', 'submit_create' => 'Crear usuario', 'submit_edit' => 'Guardar', 'submit_password_change' => '¡Cambiar!', ], - 'delete_form' => [ - 'title' => 'Eliminar {user}', - 'disclaimer' => - "Estás a punto de eliminar {user} permanentemente. Ya no podrán acceder al área de administración.", - 'understand' => 'Entiendo, quiero eliminar {user} permanentemente', - 'submit' => 'Eliminar', + 'roles' => [ + 'superadmin' => 'Super administrador', ], 'messages' => [ 'createSuccess' => '¡Usuario creado con éxito! Se le pedirá a {username} que restablezca la contraseña en la primera autenticación.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "Los roles de {username} se han actualizado correctamente.", + 'forcePassResetSuccess' => + 'Se pedirá a {username} que restablezca su contraseña en la próxima visita.', 'banSuccess' => '{username} ha sido baneado.', 'unbanSuccess' => '{username} ha sido desbaneado.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} es un superadmin, no puedes banear a un superadministrador…', - 'deleteOwnerError' => - '{username} es el propietario de la instancia, uno no simplemente elimina al propietario…', 'deleteSuperAdminError' => '{username} es un superadmin, no puedes borrar a un superadministrador…', 'deleteSuccess' => '{username} ha sido eliminado.', diff --git a/modules/Admin/Language/es/Validation.php b/modules/Admin/Language/es/Validation.php index 5478dfe8..7b2d4379 100644 --- a/modules/Admin/Language/es/Validation.php +++ b/modules/Admin/Language/es/Validation.php @@ -13,5 +13,6 @@ return [ '{field} no es una imagen, o no es suficientemente ancha o alta.', 'is_image_ratio' => '{field} no es una imagen o no es de la proporción correcta.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'El campo {field} debe ser una URL válida (ej. https://ejemplo.com/).', ]; diff --git a/modules/Admin/Language/eu/AboutCastopod.php b/modules/Admin/Language/eu/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/eu/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/eu/Breadcrumb.php b/modules/Admin/Language/eu/Breadcrumb.php deleted file mode 100644 index 408c9f9f..00000000 --- a/modules/Admin/Language/eu/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb', - config('Admin') - ->gateway => 'Home', - 'podcasts' => 'podcasts', - 'episodes' => 'episodes', - 'subscriptions' => 'subscriptions', - 'contributors' => 'contributors', - 'pages' => 'pages', - 'settings' => 'settings', - 'theme' => 'theme', - 'about' => 'about', - 'add' => 'add', - 'new' => 'new', - 'edit' => 'edit', - 'persons' => 'persons', - 'publish' => 'publish', - 'publish-edit' => 'edit publication', - 'publish-date-edit' => 'edit publication date', - 'unpublish' => 'unpublish', - 'delete' => 'delete', - 'remove' => 'remove', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'users', - 'my-account' => 'my account', - 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforms', - 'social' => 'social networks', - 'funding' => 'funding', - 'monetization-other' => 'other monetization', - 'analytics' => 'analytics', - 'locations' => 'locations', - 'webpages' => 'web pages', - 'unique-listeners' => 'unique listeners', - 'players' => 'players', - 'listening-time' => 'listening time', - 'time-periods' => 'time periods', - 'soundbites' => 'soundbites', - 'video-clips' => 'video clips', - 'embed' => 'embeddable player', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/eu/Charts.php b/modules/Admin/Language/eu/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/eu/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/eu/Common.php b/modules/Admin/Language/eu/Common.php deleted file mode 100644 index 74addcf2..00000000 --- a/modules/Admin/Language/eu/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Loading…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/eu/Countries.php b/modules/Admin/Language/eu/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/eu/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/eu/Dashboard.php b/modules/Admin/Language/eu/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/eu/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/eu/Episode.php b/modules/Admin/Language/eu/Episode.php deleted file mode 100644 index 4fa846e3..00000000 --- a/modules/Admin/Language/eu/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episode is already published.', - 'publish_cancel_error' => 'Episode is already published.', - 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', - 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', - 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', - 'unpublish_error' => 'Episode is not published.', - 'delete' => 'Delete', - 'go_to_page' => 'Go to page', - 'create' => 'Add an episode', - 'publication_status' => [ - 'published' => 'Published', - 'with_podcast' => 'Published', - 'scheduled' => 'Scheduled', - 'not_published' => 'Not published', - ], - 'with_podcast_hint' => 'To be published at the same time as the podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Search for an episode', - 'clear' => 'Clear search', - 'submit' => 'Search', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episodes} - }', - 'episode' => 'Episode', - 'visibility' => 'Visibility', - 'downloads' => 'Downloads', - 'comments' => 'Comments', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'Episode has been successfully created!', - 'editSuccess' => 'Episode has been successfully updated!', - 'publishSuccess' => '{publication_status, select, - published {Episode successfully published!} - scheduled {Episode publication successfully scheduled!} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not published.} - }', - 'publishCancelSuccess' => 'Episode publication successfully cancelled!', - 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', - 'scheduleDateError' => 'Schedule date must be set!', - 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', - 'deleteSuccess' => 'Episode successfully deleted!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/eu/EpisodeNavigation.php b/modules/Admin/Language/eu/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/eu/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/eu/Fediverse.php b/modules/Admin/Language/eu/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/eu/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/eu/Home.php b/modules/Admin/Language/eu/Home.php deleted file mode 100644 index 3ff4c04d..00000000 --- a/modules/Admin/Language/eu/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found', -]; diff --git a/modules/Admin/Language/eu/Install.php b/modules/Admin/Language/eu/Install.php deleted file mode 100644 index 36e373a2..00000000 --- a/modules/Admin/Language/eu/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/eu/Navigation.php b/modules/Admin/Language/eu/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/eu/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/eu/Page.php b/modules/Admin/Language/eu/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/eu/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/eu/Pager.php b/modules/Admin/Language/eu/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/eu/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/eu/Person.php b/modules/Admin/Language/eu/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/eu/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/eu/Platforms.php b/modules/Admin/Language/eu/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/eu/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/eu/Podcast.php b/modules/Admin/Language/eu/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/eu/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/eu/PodcastNavigation.php b/modules/Admin/Language/eu/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/eu/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/eu/Settings.php b/modules/Admin/Language/eu/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/eu/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/eu/Soundbite.php b/modules/Admin/Language/eu/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/eu/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/eu/Validation.php b/modules/Admin/Language/eu/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/eu/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/eu/VideoClip.php b/modules/Admin/Language/eu/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/eu/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/fa/AboutCastopod.php b/modules/Admin/Language/fa/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/fa/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/fa/Breadcrumb.php b/modules/Admin/Language/fa/Breadcrumb.php index 408c9f9f..f3269bfa 100644 --- a/modules/Admin/Language/fa/Breadcrumb.php +++ b/modules/Admin/Language/fa/Breadcrumb.php @@ -19,7 +19,6 @@ return [ 'pages' => 'pages', 'settings' => 'settings', 'theme' => 'theme', - 'about' => 'about', 'add' => 'add', 'new' => 'new', 'edit' => 'edit', @@ -29,19 +28,15 @@ return [ 'publish-date-edit' => 'edit publication date', 'unpublish' => 'unpublish', 'delete' => 'delete', - 'remove' => 'remove', 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'block lists', 'users' => 'users', 'my-account' => 'my account', 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'feed import', 'platforms' => 'platforms', 'social' => 'social networks', 'funding' => 'funding', - 'monetization-other' => 'other monetization', 'analytics' => 'analytics', 'locations' => 'locations', 'webpages' => 'web pages', diff --git a/modules/Admin/Language/fa/Charts.php b/modules/Admin/Language/fa/Charts.php index 6ede2510..4b33530e 100644 --- a/modules/Admin/Language/fa/Charts.php +++ b/modules/Admin/Language/fa/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/fa/Common.php b/modules/Admin/Language/fa/Common.php index 74addcf2..596c8bcd 100644 --- a/modules/Admin/Language/fa/Common.php +++ b/modules/Admin/Language/fa/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Upload a file', 'remote_url' => 'Remote URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Play', diff --git a/modules/Auth/Language/en/Contributor.php b/modules/Admin/Language/fa/Contributor.php similarity index 70% rename from modules/Auth/Language/en/Contributor.php rename to modules/Admin/Language/fa/Contributor.php index c70badc0..d0f3b93d 100644 --- a/modules/Auth/Language/en/Contributor.php +++ b/modules/Admin/Language/fa/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Add contributor', 'submit_edit' => 'Update role', ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', + 'roles' => [ + 'podcast_admin' => 'Podcast admin', ], 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", 'removeOwnerError' => "You can't remove the podcast owner!", 'removeSuccess' => 'You have successfully removed {username} from {podcastTitle}', diff --git a/modules/Admin/Language/fa/Episode.php b/modules/Admin/Language/fa/Episode.php index 4fa846e3..91313a7c 100644 --- a/modules/Admin/Language/fa/Episode.php +++ b/modules/Admin/Language/fa/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'All podcast episodes', 'back_to_podcast' => 'Go back to podcast', 'edit' => 'Edit', - 'preview' => 'Preview', 'publish' => 'Publish', 'publish_edit' => 'Edit publication', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episode', 'visibility' => 'Visibility', - 'downloads' => 'Downloads', 'comments' => 'Comments', 'actions' => 'Actions', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'Chapters', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Admin/Language/fa/Home.php b/modules/Admin/Language/fa/Home.php index bc83fd98..3ff4c04d 100644 --- a/modules/Admin/Language/fa/Home.php +++ b/modules/Admin/Language/fa/Home.php @@ -9,6 +9,6 @@ declare(strict_types=1); */ return [ - 'all_podcasts' => 'تمامی پادکست‌ها', - 'no_podcast' => 'هیچ پادکستی پیدا نشد', + 'all_podcasts' => 'All podcasts', + 'no_podcast' => 'No podcast found', ]; diff --git a/modules/Admin/Language/fa/Install.php b/modules/Admin/Language/fa/Install.php index a2643d24..36e373a2 100644 --- a/modules/Admin/Language/fa/Install.php +++ b/modules/Admin/Language/fa/Install.php @@ -9,46 +9,46 @@ declare(strict_types=1); */ return [ - 'manual_config' => 'پیکربندی دستی', + 'manual_config' => 'Manual configuration', 'manual_config_subtitle' => 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ - 'instance_config' => 'پیکربندی نمونه', - 'hostname' => 'نام میزبان', - 'media_base_url' => 'نشانی پایهٔ رسانه', + 'instance_config' => 'Instance configuration', + 'hostname' => 'Hostname', + 'media_base_url' => 'Media base URL', 'media_base_url_hint' => 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'دروازهٔ مدیر', + 'admin_gateway' => 'Admin gateway', 'admin_gateway_hint' => 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'دروازهٔ هویت‌سنجی', + 'auth_gateway' => 'Auth gateway', 'auth_gateway_hint' => 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'پیکربندی پایگاه داده', + 'database_config' => 'Database configuration', 'database_config_hint' => 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'نام میزبان پایگاه داده', - 'db_name' => 'نام پایگاه‌داده', - 'db_username' => 'نام کاربری پایگاه‌داده', - 'db_password' => 'گذرواژهٔ پایگاه‌داده', - 'db_prefix' => 'پيشوند پايگاه‌داده', + 'db_hostname' => 'Database hostname', + 'db_name' => 'Database name', + 'db_username' => 'Database username', + 'db_password' => 'Database password', + 'db_prefix' => 'Database prefix', 'db_prefix_hint' => "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'پیکربندی انباره', + 'cache_config' => 'Cache configuration', 'cache_config_hint' => 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'مدیر انباره', + 'cache_handler' => 'Cache handler', 'cacheHandlerOptions' => [ - 'file' => 'پرونده', - 'redis' => 'ردیس', + 'file' => 'File', + 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'بعدی', - 'submit' => 'پایان نصب', - 'create_superadmin' => 'ایجاد حساب ابرمدیریتان', - 'email' => 'رایانامه', - 'username' => 'نام‌کاربری', - 'password' => 'گذرواژه', + 'next' => 'Next', + 'submit' => 'Finish install', + 'create_superadmin' => 'Create your superadmin account', + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', ], 'messages' => [ 'createSuperAdminSuccess' => diff --git a/modules/Auth/Language/en/MyAccount.php b/modules/Admin/Language/fa/MyAccount.php similarity index 100% rename from modules/Auth/Language/en/MyAccount.php rename to modules/Admin/Language/fa/MyAccount.php diff --git a/modules/Admin/Language/fa/Navigation.php b/modules/Admin/Language/fa/Navigation.php index f3ffb129..68d4609d 100644 --- a/modules/Admin/Language/fa/Navigation.php +++ b/modules/Admin/Language/fa/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Dashboard', 'admin' => 'Home', 'podcasts' => 'Podcasts', 'podcast-list' => 'All podcasts', 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Import a podcast', 'persons' => 'Persons', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -35,7 +33,6 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Admin/Language/fa/Person.php b/modules/Admin/Language/fa/Person.php index 3465af96..a652be9f 100644 --- a/modules/Admin/Language/fa/Person.php +++ b/modules/Admin/Language/fa/Person.php @@ -9,57 +9,57 @@ declare(strict_types=1); */ return [ - 'persons' => 'افراد', - 'all_persons' => 'تمامی افراد', - 'no_person' => 'هیچ‌کس پیدا نشد!', - 'create' => 'ایجاد یک نفر', - 'view' => 'دیدن فرد', - 'edit' => 'ویرایش فرد', - 'delete' => 'حذف فرد', + 'persons' => 'Persons', + 'all_persons' => 'All persons', + 'no_person' => 'Nobody found!', + 'create' => 'Create a person', + 'view' => 'View person', + 'edit' => 'Edit person', + 'delete' => 'Delete person', 'messages' => [ - 'createSuccess' => 'فرد با موفّقیت ساخته شد!', - 'editSuccess' => 'فرد با موفّقیت به‌روز شد!', - 'deleteSuccess' => 'فرد برداشته شد!', + 'createSuccess' => 'Person has been successfully created!', + 'editSuccess' => 'Person has been successfully updated!', + 'deleteSuccess' => 'Person has been removed!', ], 'form' => [ - 'avatar' => 'چهرک', + 'avatar' => 'Avatar', 'avatar_size_hint' => - 'چهرک باید مربّعی بوده و کمینه ۴۰۰ پیکسل پنها و بلندا داشته باشد.', - 'full_name' => 'نام کامل', + 'Avatar must be squared and at least 400px wide and tall.', + 'full_name' => 'Full name', 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'نام یکتا', - 'unique_name_hint' => 'استفاده شده برای نشانی‌ها', - 'information_url' => 'نشانی اطّلاعات', + 'unique_name' => 'Unique name', + 'unique_name_hint' => 'Used for URLs', + 'information_url' => 'Information URL', 'information_url_hint' => 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'ایجاد فرد', - 'submit_edit' => 'ذخیرهٔ فرد', + 'submit_create' => 'Create person', + 'submit_edit' => 'Save person', ], 'podcast_form' => [ - 'title' => 'مدیریت افراد', - 'add_section_title' => 'افزودن افراد به این پادکست', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this podcast', 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'افراد', + 'persons' => 'Persons', 'persons_hint' => 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'نقش‌ها', + 'roles' => 'Roles', 'roles_hint' => 'You may select none, one or several roles for a person.', - 'submit_add' => 'افزودن فرد(ها)', - 'remove' => 'برداشتن', + 'submit_add' => 'Add person(s)', + 'remove' => 'Remove', ], 'episode_form' => [ - 'title' => 'مدیریت افراد', - 'add_section_title' => 'افزودن افراد به این قسمت', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this episode', 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'افراد', + 'persons' => 'Persons', 'persons_hint' => 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'نقش‌ها', + 'roles' => 'Roles', 'roles_hint' => 'You may select none, one or several roles for a person.', - 'submit_add' => 'افزودن فرد(ها)', - 'remove' => 'برداشتن', + 'submit_add' => 'Add person(s)', + 'remove' => 'Remove', ], - 'credits' => 'اعتبارها', + 'credits' => 'Credits', ]; diff --git a/modules/Admin/Language/fa/Platforms.php b/modules/Admin/Language/fa/Platforms.php index 7dc10de7..ab17d599 100644 --- a/modules/Admin/Language/fa/Platforms.php +++ b/modules/Admin/Language/fa/Platforms.php @@ -9,35 +9,22 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'رفتن به پایگاه وب {platformName}', - 'register' => 'Register', - 'submit_url' => 'ثبت پادکستتان روی {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'نمایش در صفحهٔ خانگی پادکست؟', - 'on_embed' => 'نمایش در پخش‌کنندهٔ تعبیه شده؟', - 'remove' => 'برداشتن {platformName}', - 'submit' => 'ذخیره', + 'title' => 'Platforms', + 'home_url' => 'Go to {platformName} website', + 'submit_url' => 'Submit your podcast on {platformName}', + 'visible' => 'Display in podcast homepage?', + 'on_embed' => 'Display on embeddable player?', + 'remove' => 'Remove {platformName}', + 'submit' => 'Save', 'messages' => [ - 'updateSuccess' => 'پیوندهای بن‌سازه با موفّقیت به‌روز شدند!', - 'removeLinkSuccess' => 'پیوند بن‌سازه برداشته شد.', + 'updateSuccess' => 'Platform links have been successfully updated!', + 'removeLinkSuccess' => 'The platform link has been removed.', 'removeLinkError' => - 'پیوند بن‌سازه نتوانست برداشته شود. دوباره تلاش کنید.', + 'The platform link could not be removed. Try again.', ], 'description' => [ - 'podcasting' => 'شناسهٔ پادکست روی این بن‌سازه', - 'social' => 'شناسهٔ حساب پادکست روی این بن‌سازه', - 'funding' => 'پیام فراخوانی کنش', + 'podcasting' => 'The podcast ID on this platform', + 'social' => 'The podcast account ID on this platform', + 'funding' => 'Call to action message', ], ]; diff --git a/modules/Admin/Language/fa/Podcast.php b/modules/Admin/Language/fa/Podcast.php index 9b1f047e..426b763b 100644 --- a/modules/Admin/Language/fa/Podcast.php +++ b/modules/Admin/Language/fa/Podcast.php @@ -9,24 +9,22 @@ declare(strict_types=1); */ return [ - 'all_podcasts' => 'تمامی پادکست‌ها', - 'no_podcast' => 'هیچ پادکستی پیدا نشد!', - 'create' => 'ایجاد پادکست', - 'import' => 'درون‌ریزی پادکست', - 'all_imports' => 'درون‌ریزی‌های پادکست', - 'new_episode' => 'قسمت جدید', - 'view' => 'دیدن پادکست', - 'edit' => 'ویرایش پادکست', - 'publish' => 'انتشار پادکست', + 'all_podcasts' => 'All podcasts', + 'no_podcast' => 'No podcast found!', + 'create' => 'Create podcast', + 'import' => 'Import podcast', + 'new_episode' => 'New Episode', + 'view' => 'View podcast', + 'edit' => 'Edit podcast', + 'publish' => 'Publish podcast', 'publish_edit' => 'Edit publication', - 'delete' => 'حذف پادکست', - 'see_episodes' => 'دیدن قسمت‌ّا', - 'see_contributors' => 'دیدن مشارکت‌کنندگان', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'رفتن به صفحه', - 'latest_episodes' => 'جدیدترین قسمت‌ها', - 'see_all_episodes' => 'دیدن تمامی قسمت‌ها', - 'draft' => 'پیش‌نویس', + 'delete' => 'Delete podcast', + 'see_episodes' => 'See episodes', + 'see_contributors' => 'See contributors', + 'go_to_page' => 'Go to page', + 'latest_episodes' => 'Latest episodes', + 'see_all_episodes' => 'See all episodes', + 'draft' => 'Draft', 'messages' => [ 'createSuccess' => 'Podcast successfully created!', 'editSuccess' => 'Podcast has been successfully updated!', @@ -50,44 +48,33 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ - 'identity_section_title' => 'هویت پادکست', + 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'جلد پادکست', - 'cover_size_hint' => 'جلد باید مربّعی بوده و کمینه ۱۴۰۰ پیکسل پنها و بلندا داشته باشد.', - 'banner' => 'بیرق پادکست', + 'cover' => 'Podcast cover', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', + 'banner' => 'Podcast banner', 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'حذف بیرق پادکست', - 'title' => 'عنوان', - 'handle' => 'شناسه', + 'banner_delete' => 'Delete podcast banner', + 'title' => 'Title', + 'handle' => 'Handle', 'handle_hint' => 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', 'type' => [ - 'label' => 'گونه', - 'episodic' => 'قسمتی', + 'label' => 'Type', + 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'سریالی', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', + 'serial' => 'Serial', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'شرح', - 'classification_section_title' => 'طبقه‌بندی', + 'description' => 'Description', + 'classification_section_title' => 'Classification', 'classification_section_subtitle' => 'These fields will impact your audience and competition.', 'language' => 'Language', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/fa/PodcastImport.php b/modules/Admin/Language/fa/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/fa/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/fa/PodcastNavigation.php b/modules/Admin/Language/fa/PodcastNavigation.php index bb777707..b4d7ddc0 100644 --- a/modules/Admin/Language/fa/PodcastNavigation.php +++ b/modules/Admin/Language/fa/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'Home', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodes', 'episode-list' => 'All episodes', 'episode-create' => 'New episode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Auth/Language/oc/User.php b/modules/Admin/Language/fa/User.php similarity index 73% rename from modules/Auth/Language/oc/User.php rename to modules/Admin/Language/fa/User.php index e7908f5b..585d6799 100644 --- a/modules/Auth/Language/oc/User.php +++ b/modules/Admin/Language/fa/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Edit {username}'s role", + 'edit_roles' => "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', 'ban' => 'Ban', 'unban' => 'Unban', 'delete' => 'Delete', @@ -18,7 +19,7 @@ return [ 'all_users' => 'All users', 'list' => [ 'user' => 'User', - 'role' => 'Role', + 'roles' => 'Roles', 'banned' => 'Banned?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Username', 'password' => 'Password', 'new_password' => 'New Password', - 'role' => 'Role', 'roles' => 'Roles', 'permissions' => 'Permissions', 'submit_create' => 'Create user', 'submit_edit' => 'Save', 'submit_password_change' => 'Change!', ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', + 'roles' => [ + 'superadmin' => 'Super admin', ], 'messages' => [ 'createSuccess' => 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', 'banSuccess' => '{username} has been banned.', 'unbanSuccess' => '{username} has been unbanned.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', 'deleteSuperAdminError' => '{username} is a superadmin, one does not simply delete a superadmin…', 'deleteSuccess' => '{username} has been deleted.', diff --git a/modules/Admin/Language/fa/Validation.php b/modules/Admin/Language/fa/Validation.php index 0659cd86..750b1968 100644 --- a/modules/Admin/Language/fa/Validation.php +++ b/modules/Admin/Language/fa/Validation.php @@ -10,8 +10,9 @@ declare(strict_types=1); return [ 'min_dims' => - '{field} تصویر نبوده یا پنها و بلندایش کافی نیست.', + '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => - '{field} تصویر نبوده یا ابعادش درست نیست.', - 'is_json' => '{field} contains invalid JSON.', + '{field} is either not an image or not of the right ratio.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/fr-ca/AboutCastopod.php b/modules/Admin/Language/fr-ca/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/fr-ca/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/fr-ca/Breadcrumb.php b/modules/Admin/Language/fr-ca/Breadcrumb.php deleted file mode 100644 index 408c9f9f..00000000 --- a/modules/Admin/Language/fr-ca/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb', - config('Admin') - ->gateway => 'Home', - 'podcasts' => 'podcasts', - 'episodes' => 'episodes', - 'subscriptions' => 'subscriptions', - 'contributors' => 'contributors', - 'pages' => 'pages', - 'settings' => 'settings', - 'theme' => 'theme', - 'about' => 'about', - 'add' => 'add', - 'new' => 'new', - 'edit' => 'edit', - 'persons' => 'persons', - 'publish' => 'publish', - 'publish-edit' => 'edit publication', - 'publish-date-edit' => 'edit publication date', - 'unpublish' => 'unpublish', - 'delete' => 'delete', - 'remove' => 'remove', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'users', - 'my-account' => 'my account', - 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforms', - 'social' => 'social networks', - 'funding' => 'funding', - 'monetization-other' => 'other monetization', - 'analytics' => 'analytics', - 'locations' => 'locations', - 'webpages' => 'web pages', - 'unique-listeners' => 'unique listeners', - 'players' => 'players', - 'listening-time' => 'listening time', - 'time-periods' => 'time periods', - 'soundbites' => 'soundbites', - 'video-clips' => 'video clips', - 'embed' => 'embeddable player', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/fr-ca/Charts.php b/modules/Admin/Language/fr-ca/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/fr-ca/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/fr-ca/Common.php b/modules/Admin/Language/fr-ca/Common.php deleted file mode 100644 index 74addcf2..00000000 --- a/modules/Admin/Language/fr-ca/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Loading…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/fr-ca/Countries.php b/modules/Admin/Language/fr-ca/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/fr-ca/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/fr-ca/Dashboard.php b/modules/Admin/Language/fr-ca/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/fr-ca/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/fr-ca/Episode.php b/modules/Admin/Language/fr-ca/Episode.php deleted file mode 100644 index 4fa846e3..00000000 --- a/modules/Admin/Language/fr-ca/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episode is already published.', - 'publish_cancel_error' => 'Episode is already published.', - 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', - 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', - 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', - 'unpublish_error' => 'Episode is not published.', - 'delete' => 'Delete', - 'go_to_page' => 'Go to page', - 'create' => 'Add an episode', - 'publication_status' => [ - 'published' => 'Published', - 'with_podcast' => 'Published', - 'scheduled' => 'Scheduled', - 'not_published' => 'Not published', - ], - 'with_podcast_hint' => 'To be published at the same time as the podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Search for an episode', - 'clear' => 'Clear search', - 'submit' => 'Search', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episodes} - }', - 'episode' => 'Episode', - 'visibility' => 'Visibility', - 'downloads' => 'Downloads', - 'comments' => 'Comments', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'Episode has been successfully created!', - 'editSuccess' => 'Episode has been successfully updated!', - 'publishSuccess' => '{publication_status, select, - published {Episode successfully published!} - scheduled {Episode publication successfully scheduled!} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not published.} - }', - 'publishCancelSuccess' => 'Episode publication successfully cancelled!', - 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', - 'scheduleDateError' => 'Schedule date must be set!', - 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', - 'deleteSuccess' => 'Episode successfully deleted!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/fr-ca/EpisodeNavigation.php b/modules/Admin/Language/fr-ca/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/fr-ca/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/fr-ca/Fediverse.php b/modules/Admin/Language/fr-ca/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/fr-ca/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/fr-ca/Install.php b/modules/Admin/Language/fr-ca/Install.php deleted file mode 100644 index 36e373a2..00000000 --- a/modules/Admin/Language/fr-ca/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/fr-ca/Navigation.php b/modules/Admin/Language/fr-ca/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/fr-ca/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/fr-ca/Notifications.php b/modules/Admin/Language/fr-ca/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/fr-ca/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/fr-ca/Page.php b/modules/Admin/Language/fr-ca/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/fr-ca/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/fr-ca/Pager.php b/modules/Admin/Language/fr-ca/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/fr-ca/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/fr-ca/Person.php b/modules/Admin/Language/fr-ca/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/fr-ca/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/fr-ca/Platforms.php b/modules/Admin/Language/fr-ca/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/fr-ca/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/fr-ca/Podcast.php b/modules/Admin/Language/fr-ca/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/fr-ca/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/fr-ca/PodcastNavigation.php b/modules/Admin/Language/fr-ca/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/fr-ca/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/fr-ca/Settings.php b/modules/Admin/Language/fr-ca/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/fr-ca/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/fr-ca/Soundbite.php b/modules/Admin/Language/fr-ca/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/fr-ca/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/fr-ca/Validation.php b/modules/Admin/Language/fr-ca/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/fr-ca/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/fr-ca/VideoClip.php b/modules/Admin/Language/fr-ca/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/fr-ca/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/fr/AboutCastopod.php b/modules/Admin/Language/fr/AboutCastopod.php deleted file mode 100644 index 7cd9412b..00000000 --- a/modules/Admin/Language/fr/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'À propos de Castopod', - 'host_name' => 'Nom d’hôte', - 'version' => 'Version de Castopod', - 'php_version' => 'Version de PHP', - 'os' => 'Système d\'exploitation', - 'languages' => 'Langues', - 'update_database' => 'Mettre à jour la base de données', - 'messages' => [ - 'databaseUpdateSuccess' => 'La base de données est à jour!', - ], -]; diff --git a/modules/Admin/Language/fr/Breadcrumb.php b/modules/Admin/Language/fr/Breadcrumb.php index a4ac57a2..375caa16 100644 --- a/modules/Admin/Language/fr/Breadcrumb.php +++ b/modules/Admin/Language/fr/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Accueil', 'podcasts' => 'podcasts', 'episodes' => 'épisodes', - 'subscriptions' => 'abonnements', + 'subscriptions' => 'subscriptions', 'contributors' => 'contributeurs', 'pages' => 'pages', 'settings' => 'paramètres', 'theme' => 'thème', - 'about' => 'à propos', 'add' => 'ajouter', 'new' => 'créer', 'edit' => 'modifier', 'persons' => 'intervenants', 'publish' => 'publier', 'publish-edit' => 'modifier la publication', - 'publish-date-edit' => 'définir la date de publication', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'dépublier', 'delete' => 'supprimer', - 'remove' => 'retirer', 'fediverse' => 'fédiverse', - 'blocked-actors' => 'acteurs bloqués', - 'blocked-domains' => 'domaines bloqués', + 'block-lists' => 'listes de blocage', 'users' => 'utilisateurs', 'my-account' => 'mon compte', 'change-password' => 'changer le mot de passe', - 'imports' => 'imports', - 'sync-feeds' => 'synchroniser les flux', + 'import' => 'importer un flux', 'platforms' => 'plateformes', 'social' => 'réseaux sociaux', 'funding' => 'financement', - 'monetization-other' => 'autres monétisations', 'analytics' => 'mesures d’audience', 'locations' => 'localisations', 'webpages' => 'pages web', @@ -53,5 +48,5 @@ return [ 'video-clips' => 'extraits vidéo', 'embed' => 'lecteur intégré', 'notifications' => 'notifications', - 'suspend' => 'suspendre', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/fr/Charts.php b/modules/Admin/Language/fr/Charts.php index 0c32f623..43fb6717 100644 --- a/modules/Admin/Language/fr/Charts.php +++ b/modules/Admin/Language/fr/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Bande passante quotidienne consommée (en Mo)', 'total_storage_by_month' => 'Stockage mensuel (en Mo)', 'total_bandwidth_by_month' => 'Bande passante mensuelle utilisée (en Mo)', - 'total_bandwidth_by_month_limit' => 'Limité à {totalBandwidth} par mois', ]; diff --git a/modules/Admin/Language/fr/Common.php b/modules/Admin/Language/fr/Common.php index d53347fb..f66f2a29 100644 --- a/modules/Admin/Language/fr/Common.php +++ b/modules/Admin/Language/fr/Common.php @@ -40,13 +40,12 @@ return [ ], 'upload_file' => 'Téléversez un fichier', 'remote_url' => 'URL distante', - 'save' => 'Sauvegarder', ], 'play_episode_button' => [ 'play' => 'Lire', 'playing' => 'En cours', ], 'size_limit' => 'Taille maximale : {0}.', - 'choose_interact' => 'Choisissez comment interagir', - 'view' => 'Voir', + 'choose_interact' => 'Choose how to interact', + 'view' => 'View', ]; diff --git a/modules/Auth/Language/fr/Contributor.php b/modules/Admin/Language/fr/Contributor.php similarity index 71% rename from modules/Auth/Language/fr/Contributor.php rename to modules/Admin/Language/fr/Contributor.php index a9006130..700f760b 100644 --- a/modules/Auth/Language/fr/Contributor.php +++ b/modules/Admin/Language/fr/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Ajouter le contributeur', 'submit_edit' => 'Mettre à jour le rôle', ], - 'delete_form' => [ - 'title' => 'Supprimer {contributor}', - 'disclaimer' => - 'Vous êtes sur le point de supprimer {contributor} des contributeurs. Ils ne pourront plus accéder à "{podcastTitle}".', - 'understand' => 'Je comprends, je veux retirer {contributor} de "{podcastTitle}"', - 'submit' => 'Retirer', + 'roles' => [ + 'podcast_admin' => 'Administrateur de Podcasts', ], 'messages' => [ - 'editSuccess' => 'Rôle modifié avec succès !', - 'editOwnerError' => "Vous ne pouvez pas modifier le propriétaire du podcast !", 'removeOwnerError' => "Vous ne pouvez pas retirer le propriétaire du podcast !", 'removeSuccess' => 'Vous avez retiré {username} de {podcastTitle}', diff --git a/modules/Admin/Language/fr/Dashboard.php b/modules/Admin/Language/fr/Dashboard.php index 010761fa..881073fd 100644 --- a/modules/Admin/Language/fr/Dashboard.php +++ b/modules/Admin/Language/fr/Dashboard.php @@ -9,20 +9,20 @@ declare(strict_types=1); */ return [ - 'home' => 'Tableau de bord', - 'welcome_message' => 'Bienvenue dans l\'espace d\'administration !', + 'home' => 'Admin dashboard', + 'welcome_message' => 'Welcome to the admin area!', 'podcasts' => [ 'title' => 'Podcasts', - 'not_found' => 'Pas de podcast publié', - 'last_published' => 'Dernière publication le {lastPublicationDate}', + 'not_found' => 'No published podcast', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'episodes' => [ - 'title' => 'Épisodes', - 'not_found' => 'Aucun épisode publié', - 'last_published' => 'Dernière publication le {lastPublicationDate}', + 'title' => 'Episodes', + 'not_found' => 'No published episode', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'storage' => [ - 'title' => 'Espace de stockage', - 'subtitle' => '{totalUploaded} sur {totalStorage}', + 'title' => 'Storage', + 'subtitle' => '{totalUploaded} out of {totalStorage}', ], ]; diff --git a/modules/Admin/Language/fr/Episode.php b/modules/Admin/Language/fr/Episode.php index 5b479992..dbdf875c 100644 --- a/modules/Admin/Language/fr/Episode.php +++ b/modules/Admin/Language/fr/Episode.php @@ -22,17 +22,16 @@ return [ 'all_podcast_episodes' => 'Tous les épisodes du podcast', 'back_to_podcast' => 'Revenir au podcast', 'edit' => 'Modifier', - 'preview' => 'Prévisualisation', 'publish' => 'Publier', 'publish_edit' => 'Modifier la publication', - 'publish_date_edit' => 'Définir la date de publication', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Dépublier', 'publish_error' => 'L’épisode est déjà publié.', 'publish_edit_error' => 'L’épisode est déjà publié.', 'publish_cancel_error' => 'L’épisode est déjà publié.', - 'publish_date_edit_error' => 'L\'épisode n\'a pas encore été publié, vous ne pouvez pas modifier sa date de publication.', - 'publish_date_edit_future_error' => 'La date de publication de l\'épisode ne peut être définie qu\'à une date antérieure! Si vous souhaitez la replanifier, dépubliez-la d\'abord.', - 'publish_date_edit_success' => 'La date de publication de l\'épisode a été mise à jour avec succès !', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'L’épisode n’est pas publié.', 'delete' => 'Supprimer', 'go_to_page' => 'Voir', @@ -43,7 +42,7 @@ return [ 'scheduled' => 'Planifié', 'not_published' => 'Non publié', ], - 'with_podcast_hint' => 'Publier en même temps que le podcast', + 'with_podcast_hint' => 'To be published at the same time as the podcast', 'list' => [ 'search' => [ 'placeholder' => 'Rechercher un épisode', @@ -51,12 +50,11 @@ return [ 'submit' => 'Recherche', ], 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# épisode} - other {# épisodes} + one {# episode} + other {# episodes} }', 'episode' => 'Épisode', 'visibility' => 'Visibilité', - 'downloads' => 'Téléchargements', 'comments' => 'Commentaires', 'actions' => 'Actions', ], @@ -64,31 +62,31 @@ return [ 'createSuccess' => 'L’épisode a été créé avec succès !', 'editSuccess' => 'L’épisode a bien été mis à jour !', 'publishSuccess' => '{publication_status, select, - published {Épisode publié avec succès !} - scheduled {La publication de l\'épisode est planifiée avec succès !} - with_podcast {Cet épisode sera publié en même temps que le podcast.} - other {Cet épisode n\'est pas publié.} + published {Episode successfully published!} + scheduled {Episode publication successfully scheduled!} + with_podcast {This episode will be published at the same time as the podcast.} + other {This episode is not published.} }', 'publishCancelSuccess' => 'La publication de l’épisode a bien été annulée !', - 'unpublishBeforeDeleteTip' => 'Vous devez dépublier l\'épisode avant de le supprimer.', - 'scheduleDateError' => 'La date de planification doit être définie !', - 'deletePublishedEpisodeError' => 'Vous devez dépublier l\'épisode avant de le supprimer.', + 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', + 'scheduleDateError' => 'Schedule date must be set!', + 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', 'deleteSuccess' => 'L\'épisode a bien été supprimé !', - 'deleteError' => 'Impossible de supprimer l\'épisode {type, select, - transcript {transcription} - chapters {chapitres} - image {couverture} - audio {audio} - other {média} - }.', - 'deleteFileError' => 'Impossible de supprimer le fichier {type, select, - transcript {de transcription} - chapters {de chapitres} - image {d’image de couverture} + 'deleteError' => 'Failed to delete episode {type, select, + transcript {transcript} + chapters {chapters} + image {cover} audio {audio} other {media} - } {file_key}. Vous pouvez le supprimer manuellement de votre disque.', - 'sameSlugError' => 'Il existe déjà un épisode avec le slug choisi.', + }.', + 'deleteFileError' => 'Failed to delete {type, select, + transcript {transcript} + chapters {chapters} + image {cover} + audio {audio} + other {media} + } file {file_path}. You may manually remove it from your disk.', + 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ 'file_size_error' => @@ -99,7 +97,7 @@ return [ 'cover' => 'Image de couverture', 'cover_hint' => 'Si vous ne définissez pas d’image, celle du podcast sera utilisée à la place.', - 'cover_size_hint' => 'L’image doit être carrée et avoir au moins 1400px de largeur et de hauteur.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'title' => 'Titre', 'title_hint' => 'Doit contenir un titre d’épisode clair et concis. Ne précisez ici aucun numéro de saison ou d’épisode.', @@ -116,7 +114,7 @@ return [ 'bonus_hint' => 'Contenu supplémentaire pour le podcast (par exemple des informations sur les coulisses ou des interviews avec les acteurs) ou du contenu promotionnel croisé pour un autre podcast', ], 'premium_title' => 'Premium', - 'premium' => 'L\'épisode doit être accessible aux abonnés premium uniquement', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Avertissement parental', 'hint' => 'L’épisode contient-il un contenu explicite ?', @@ -133,15 +131,15 @@ return [ 'Ce texte est ajouté à la fin de chaque description d’épisode, c’est un bon endroit pour placer vos liens sociaux par exemple.', 'additional_files_section_title' => 'Fichiers additionels', 'additional_files_section_subtitle' => - 'Ces fichiers pourront être utilisées par d’autres plate-formes pour procurer une meilleure expérience à vos auditeurs. Consulter le {podcastNamespaceLink} pour plus d’informations.', + 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', 'location_section_title' => 'Localisation', 'location_section_subtitle' => 'De quel lieu cet épisode parle-t-il ?', 'location_name' => 'Nom ou adresse du lieu', 'location_name_hint' => 'Ce lieu peut être réel ou fictif', 'transcript' => 'Transcription (sous-titrage)', - 'transcript_hint' => 'Seuls les .srt ou .vtt sont autorisés.', + 'transcript_hint' => 'Seulement les .srt sont autorisés', 'transcript_download' => 'Télécharger le transcript', - 'transcript_file' => 'Fichier de transcription (.srt ou .vtt)', + 'transcript_file' => 'Fichier de transcription (.srt)', 'transcript_remote_url' => 'URL distante pour le fichier de transcription', 'transcript_file_delete' => 'Supprimer le fichier de transcription', 'chapters' => 'Chapitrage', @@ -155,9 +153,9 @@ return [ 'Si vous avez besoin d’une balise que Castopod ne couvre pas, définissez-la ici.', 'custom_rss' => 'Balises RSS personnalisées pour l’épisode', 'custom_rss_hint' => 'Ceci sera injecté dans la balise ❬item❭.', - 'block' => 'L\'épisode doit être masqué dans les catalogues publics', + 'block' => 'Episode should be hidden from public catalogues', 'block_hint' => - 'L\'épisode montre ou masque le statut: activer ceci empêche l\'épisode d\'apparaître dans les Podcasts Apple, Google Podcasts, et toutes les applications tierces qui tirent vers ces répertoires. (non garanti)', + 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'submit_create' => 'Créer l’épisode', 'submit_edit' => 'Enregistrer l’épisode', ], @@ -171,7 +169,7 @@ return [ 'publication_method' => [ 'now' => 'Maintenant', 'schedule' => 'Planifier', - 'with_podcast' => 'Publier à côté du podcast', + 'with_podcast' => 'Publish alongside podcast', ], 'scheduled_publication_date' => 'Date de publication programmée', 'scheduled_publication_date_clear' => 'Effacer la date de publication', @@ -185,19 +183,19 @@ return [ 'message_warning_submit' => 'Publier quand même', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Date de la prochaine publication', - 'new_publication_date_hint' => 'Doit être défini à une date antérieure.', - 'submit' => 'Définir la date de publication', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "Dépublier l'épisode supprimera tous les commentaires et messages qui lui sont associés et le supprimera du flux RSS du podcast.", + "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", 'understand' => 'Je comprends, je veux dépublier l’épisode', 'submit' => 'Dépublier', ], 'delete_form' => [ 'disclaimer' => - "La suppression de l'épisode supprimera tous les fichiers multimédia, les commentaires, les clips vidéo et les parties sonores qui y sont associées.", + "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", 'understand' => 'Je comprends, je veux supprimer l’épisode', 'submit' => 'Supprimer', ], @@ -212,14 +210,4 @@ return [ 'light' => 'Clair', 'light-transparent' => 'Clair transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'mode brouillon', - 'text' => '{publication_status, select, - published {Cet épisode n’est pas encore publié.} - scheduled {Cet épisode est programmé pour le {publication_date}.} - with_podcast {Cet épisode va être publié au même moment que le podcast.} - other {Cet épisode n’est pas encore publié.} - }', - 'preview' => 'Prévisualisation', - ], ]; diff --git a/modules/Auth/Language/fr/MyAccount.php b/modules/Admin/Language/fr/MyAccount.php similarity index 100% rename from modules/Auth/Language/fr/MyAccount.php rename to modules/Admin/Language/fr/MyAccount.php diff --git a/modules/Admin/Language/fr/Navigation.php b/modules/Admin/Language/fr/Navigation.php index b3fd182b..8e870a14 100644 --- a/modules/Admin/Language/fr/Navigation.php +++ b/modules/Admin/Language/fr/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Afficher ou cacher la barre latérale', 'go_to_website' => 'Aller au site', 'go_to_admin' => 'Aller à l’admin', - 'not-authorized' => 'Non autorisé', 'dashboard' => 'Tableau de bord', 'admin' => 'Accueil', 'podcasts' => 'Podcasts', 'podcast-list' => 'Tous les podcasts', 'podcast-create' => 'Créer un podcast', - 'all-podcast-imports' => 'Tous les imports de Podcast', - 'podcast-imports-add' => 'Importer un podcast', + 'podcast-import' => 'Importer un podcast', 'persons' => 'Intervenants', 'person-list' => 'Tous les intervenants', 'person-create' => 'Créer un intervenant', @@ -35,7 +33,6 @@ return [ 'settings' => 'Paramètres', 'settings-general' => 'Général', 'settings-theme' => 'Thème', - 'admin-about' => 'À propos', 'account' => [ 'my-account' => 'Mon compte', 'change-password' => 'Modifier le mot de passe', diff --git a/modules/Admin/Language/fr/Notifications.php b/modules/Admin/Language/fr/Notifications.php index 003b2bbb..42f1149b 100644 --- a/modules/Admin/Language/fr/Notifications.php +++ b/modules/Admin/Language/fr/Notifications.php @@ -10,10 +10,10 @@ declare(strict_types=1); return [ 'title' => 'Notifications', - 'reply' => '{actor_username} a répondu à votre message', - 'favourite' => '{actor_username} a mis en favori votre message', - 'reblog' => '{actor_username} à partagé votre message', - 'follow' => '{actor_username} commencé à te suivre', + 'reply' => '{actor_username} replied to your post', + 'favourite' => '{actor_username} favourited your post', + 'reblog' => '{actor_username} shared your post', + 'follow' => '{actor_username} started following you', 'no_notifications' => 'Aucune notification', 'mark_all_as_read' => 'Tout marquer comme lu', ]; diff --git a/modules/Admin/Language/fr/Person.php b/modules/Admin/Language/fr/Person.php index afd6d28f..e5f3128a 100644 --- a/modules/Admin/Language/fr/Person.php +++ b/modules/Admin/Language/fr/Person.php @@ -24,7 +24,7 @@ return [ 'form' => [ 'avatar' => 'Avatar', 'avatar_size_hint' => - 'L\'avatar doit être carré et au moins 400px de largeur et de hauteur.', + 'Avatar must be squared and at least 400px wide and tall.', 'full_name' => 'Nom complet', 'full_name_hint' => 'Le nom complet ou le pseudonyme de l’intervenant', 'unique_name' => 'Nom unique', diff --git a/modules/Admin/Language/fr/Platforms.php b/modules/Admin/Language/fr/Platforms.php index 3e2f9eee..e6605532 100644 --- a/modules/Admin/Language/fr/Platforms.php +++ b/modules/Admin/Language/fr/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Plateformes de Podcasting', - 'social' => 'Réseaux sociaux', - 'funding' => 'Liens de financement', - ], - 'website' => 'Site web', + 'title' => 'Plateformes', 'home_url' => 'Aller au site {platformName}', - 'register' => 'S\'inscrire', 'submit_url' => 'Soumettez votre podcast sur {platformName}', - 'your_link' => 'Votre lien', - 'your_id' => [ - 'podcasting' => 'Votre identifiant', - 'social' => 'Votre identifiant', - 'funding' => 'Votre CTA', - ], - 'your_cta' => 'Votre appel à l\'action', 'visible' => 'Afficher sur la page d’accueil du podcast ?', 'on_embed' => 'Afficher sur le lecteur intégré ?', 'remove' => 'Supprimer {platformName}', diff --git a/modules/Admin/Language/fr/Podcast.php b/modules/Admin/Language/fr/Podcast.php index feadf6d3..41255ff2 100644 --- a/modules/Admin/Language/fr/Podcast.php +++ b/modules/Admin/Language/fr/Podcast.php @@ -13,57 +13,54 @@ return [ 'no_podcast' => 'Aucun podcast trouvé !', 'create' => 'Créer un podcast', 'import' => 'Importer un podcast', - 'all_imports' => 'Imports de podcasts', 'new_episode' => 'Créer un épisode', 'view' => 'Voir le podcast', 'edit' => 'Modifier le podcast', - 'publish' => 'Publier le podcast', - 'publish_edit' => 'Modifier la publication', + 'publish' => 'Publish podcast', + 'publish_edit' => 'Edit publication', 'delete' => 'Supprimer le podcast', 'see_episodes' => 'Voir les épisodes', 'see_contributors' => 'Voir les contributeurs', - 'monetization_other' => 'Autres monétisations', 'go_to_page' => 'Aller à la page', 'latest_episodes' => 'Derniers épisodes', 'see_all_episodes' => 'Voir tous les épisodes', - 'draft' => 'Brouillon', + 'draft' => 'Draft', 'messages' => [ - 'createSuccess' => 'Le podcast a été créé avec succès !', + 'createSuccess' => 'Podcast successfully created!', 'editSuccess' => 'Le podcast a bien été mis à jour !', 'importSuccess' => 'Le podcast a été importé avec succès !', - 'deleteSuccess' => 'Podcast @{podcast_handle} a été supprimé avec succès !', - 'deletePodcastMediaError' => 'Impossible de supprimer le podcast {type, select, - cover {couverture} - banner {bannière} - other {média} + 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', + 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, + cover {cover} + banner {banner} + other {media} }.', - 'deleteEpisodeMediaError' => 'Impossible de supprimer l\'épisode de podcast {episode_slug} {type, select, - transcript {transcription} - chapters {chapitres} - image {couverture} + 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, + transcript {transcript} + chapters {chapters} + image {cover} audio {audio} - other {média} + other {media} }.', - 'deletePodcastMediaFolderError' => 'Impossible de supprimer le dossier de podcast {folder_path}. Vous pouvez le supprimer manuellement de votre disque.', - 'podcastFeedUpdateSuccess' => 'Mise à jour réussie : {number_of_new_episodes, plural, - one {# épisode a été} - other {# épisodes ont été} - } ajoutés au podcast!', - 'podcastFeedUpToDate' => 'Le podcast est déjà à jour.', - 'publishError' => 'Ce podcast est soit déjà publié, soit programmé pour publication.', - 'publishEditError' => 'Ce podcast n\'est pas programmé pour publication.', - 'publishCancelSuccess' => 'Publication de Podcast annulée avec succès !', - 'scheduleDateError' => 'La date de planification doit être définie !', + 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', + 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, + one {# episode was} + other {# episodes were} + } added to the podcast!', + 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', + 'publishError' => 'This podcast is either already published or scheduled for publication.', + 'publishEditError' => 'This podcast is not scheduled for publication.', + 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', + 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ 'identity_section_title' => 'Informations sur le Podcast', 'identity_section_subtitle' => 'Ces champs vous permettent de vous faire remarquer.', - 'fediverse_section_title' => 'Identité dans le Fédivers', - 'cover' => 'Couverture du podcast', - 'cover_size_hint' => 'La couverture du podcast doit être carrée, avec au minimum 1400px de largeur et de hauteur.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Bannière du podcast', - 'banner_size_hint' => 'La bannière doit être au format 3/1, avec au minimum 1500px de largeur.', + 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', 'banner_delete' => 'Supprimer la bannière du podcast', 'title' => 'Titre', 'handle' => 'Identifiant', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Épisodique', 'episodic_hint' => 'Si les épisodes sont destinés à être consommés sans ordre spécifique. Les épisodes les plus récents seront présentés en premier.', 'serial' => 'Série', - 'serial_hint' => 'Si les épisodes sont destinés à êtres lus dans un ordre séquentiel. Les épisodes seront présentés dans l’ordre de numérotation.', - ], - 'medium' => [ - 'label' => 'Médium', - 'hint' => 'Médium tel que représenté par la balise podcast:medium dans le flux RSS. Changer ceci peut changer la façon dont les lecteurs présentent votre flux.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Décrit un flux pour une émission de podcast.', - 'music' => 'Musique', - 'music_hint' => 'Un flux de musique organisé en un "album", chaque élément étant une chanson de l\'album.', - 'audiobook' => 'Livre audio', - 'audiobook_hint' => 'Types d\'audio spécifiques avec un élément par flux, ou lorsque des éléments représentent des chapitres dans le livre.', + 'serial_hint' => 'Si les épisodes sont destinés à être consommés dans un ordre séquentiel bien défini. Les épisodes les plus anciens seront présentés en premier.', ], 'description' => 'Description', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'E-mail du/de la propriétaire', 'owner_email_hint' => 'Utilisé par la plupart des plateformes pour vérifier la propriété du podcast. Visible dans le flux RSS public.', - 'is_owner_email_removed_from_feed' => 'Retirer l\'email du propriétaire du flux RSS publique', - 'is_owner_email_removed_from_feed_hint' => 'Il se peut que vous deviez temporairement exposer l’email pour qu\'un index puisse valider la propriété de votre podcast.', 'publisher' => 'Éditeur / Éditrice', 'publisher_hint' => 'Le groupe responsable de la création du podcast. Fait souvent référence à la société mère ou au réseau d’un podcast. Ce champ est parfois appelé « Auteur ».', @@ -123,13 +108,8 @@ return [ 'monetization_section_subtitle' => 'Gagnez de l’argent grâce à votre audience.', 'premium' => 'Premium', - 'premium_by_default' => 'Les épisodes doivent être définis comme premium par défaut', - 'premium_by_default_hint' => 'Les épisodes de Podcast seront marqués comme premium par défaut. Vous pouvez toujours choisir de définir certains épisodes, bandes-annonces ou bonus comme publics.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visitez votre tableau de bord OP3 (lien externe)', - 'op3_hint' => 'Valorisez vos données d\'analyse avec OP3, un service d\'analyse tiers open source et de confiance. Partagez, validez et comparez vos données analytiques avec l\'écosystème de podcasting ouvert.', - 'op3_enable' => 'Activer le service d\'analyse OP3', - 'op3_enable_hint' => 'Pour des raisons de sécurité, les données d\'analyse des épisodes premium ne seront pas partagées avec OP3.', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', 'payment_pointer' => 'Adresse de paiement (Payment Pointer) pour Web Monetization', 'payment_pointer_hint' => 'L’adresse où vous recevrez de l’argent grâce à Web Monetization', @@ -138,12 +118,11 @@ return [ 'Si vous avez besoin d’une balise que nous n’avons pas couverte, définissez-la ici.', 'custom_rss' => 'Balises RSS personnalisées pour le podcast', 'custom_rss_hint' => 'Ceci sera injecté dans la balise ❬channel❭.', - 'verify_txt' => 'Vérification de propriété TXT', - 'verify_txt_hint' => 'Plutôt que de se fier au courrier électronique, certains services tiers peuvent confirmer la propriété de votre podcast en vous demandant d\'intégrer un texte de vérification dans votre flux.', - 'verify_txt_helper' => 'Ce texte est injecté dans une balise .', 'new_feed_url' => 'URL du nouveau flux', 'new_feed_url_hint' => 'Utilisez ce champ lorsque vous déplacez ce podcast vers un autre domaine ou que vous changez d’hébergeur. Par défaut, ce champ est rempli avec l’URL du flux actuel si le podcast est importé.', - 'old_feed_url' => 'URL de l\'ancien flux', + 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partenariat', 'partner_id' => 'ID', 'partner_link_url' => 'URL lien', @@ -151,9 +130,10 @@ return [ 'partner_id_hint' => 'Votre identifiant personnel partenaire', 'partner_link_url_hint' => 'L’adresse générique des liens partenaire', 'partner_image_url_hint' => 'L’adresse générique des images partenaire', - 'block' => 'L\'épisode doit être masqué dans les catalogues publics', + 'status_section_title' => 'Statut', + 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => - 'Le statut d\'affichage ou de masquage du podcast : activer cette option empêche l\'intégralité du podcast d\'apparaître dans les podcasts Apple, Google Podcasts et toutes les applications tierces qui extraient des émissions de ces répertoires. (Pas garantie)', + 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'complete' => 'Le podcast n’aura plus de nouveaux épisodes.', 'lock' => 'Empêcher la copie du podcast', 'lock_hint' => @@ -275,36 +255,36 @@ return [ 'tv_reviews' => 'Critiques TV', ], 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Retour au tableau de bord des podcasts', - 'post' => 'Votre message de publication', + 'back_to_podcast_dashboard' => 'Back to podcast dashboard', + 'post' => 'Your announcement post', 'post_hint' => - "Écrivez un message pour annoncer la publication de votre podcast. Le message sera affiché sur la page d'accueil de votre podcast.", - 'message_placeholder' => 'Rédiger votre message…', - 'submit' => 'Publier', - 'publication_date' => 'Date de publication', + "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", + 'message_placeholder' => 'Write your message…', + 'submit' => 'Publish', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Maintenant', - 'schedule' => 'Planifier', + 'now' => 'Now', + 'schedule' => 'Schedule', ], - 'scheduled_publication_date' => 'Date de publication programmée', + 'scheduled_publication_date' => 'Scheduled publication date', 'scheduled_publication_date_hint' => - 'Vous pouvez planifier la sortie de l’épisode en saisissant une date de publication. Ce champ doit être au format YYYY-MM-DD HH:mm', - 'submit_edit' => 'Modifier la publication', - 'cancel_publication' => 'Annuler la publication', - 'message_warning' => 'Vous n’avez pas saisi de message pour l’annonce de votre épisode !', - 'message_warning_hint' => 'Avoir un message augmente l\'engagement social, résultant en une meilleure visibilité pour votre podcast.', - 'message_warning_submit' => 'Publier quand même', + 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', + 'message_warning' => 'You did not write a message for your announcement post!', + 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ - 'draft_mode' => 'Mode brouillon', - 'not_published' => 'Ce podcast n\'est pas encore publié.', - 'scheduled' => 'Ce podcast est programmé pour être publié le {publication_date}.', + 'draft_mode' => 'draft mode', + 'not_published' => 'This podcast is not yet published.', + 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => - "La suppression du podcast supprimera tous les épisodes, fichiers multimédia, messages et statistiques qui y sont associées. Cette action est irréversible, vous ne pourrez plus les récupérer par la suite.", - 'understand' => 'Je comprends, je souhaite que le podcast soit définitivement supprimé', - 'submit' => 'Supprimer', + "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", + 'understand' => 'I understand, I want the podcast to be permanently deleted', + 'submit' => 'Delete', ], 'by' => 'Par {publisher}', 'season' => 'Saison {seasonNumber}', @@ -314,12 +294,12 @@ return [ 'no_episode' => 'Aucun épisode trouvé !', 'follow' => 'Suivre', 'followers' => '{numberOfFollowers, plural, - one {# abonné·e} - other {# abonné·e·s} + one {# follower} + other {# followers} }', 'posts' => '{numberOfPosts, plural, - one {# publication} - other {# publications} + one {# post} + other {# posts} }', 'activity' => 'Activité', 'episodes' => 'Épisodes', diff --git a/modules/Admin/Language/fr/PodcastImport.php b/modules/Admin/Language/fr/PodcastImport.php new file mode 100644 index 00000000..b72cf0d2 --- /dev/null +++ b/modules/Admin/Language/fr/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'Le podcast à importer', + 'old_podcast_section_subtitle' => + 'Assurez-vous d’être détenteur des droits du podcast avant de l’importer. Copier et diffuser un podcast sans en détenir les droits est assimilable à de la contrefaçon et est passible de poursuites.', + 'imported_feed_url' => 'Adresse du flux', + 'imported_feed_url_hint' => 'Le flux doit être au format xml ou rss.', + 'new_podcast_section_title' => 'Le nouveau podcast', + 'advanced_params_section_title' => 'Paramètres avancés', + 'advanced_params_section_subtitle' => + 'Si vous ne savez pas à quoi servent ces champs, conservez les valeurs par défaut.', + 'slug_field' => 'Champ à utiliser pour calculer l’identifiant de l’épisode', + 'description_field' => + 'Champs pour la description des épisodes', + 'force_renumber' => 'Forcer la re-numérotation des épisodes', + 'force_renumber_hint' => + 'Utilisez ceci si le podcast à importer ne contient pas de numéros d’épisodes mais que vous souhaitez en ajouter pendant l’import.', + 'season_number' => 'Numéro de saison', + 'season_number_hint' => + 'Utilisez ceci si le podcast à importer ne contient pas de numéros de saison mais que vous souhaitez en définir un. Laissez vide sinon.', + 'max_episodes' => 'Nombre maximum d’épisodes à importer', + 'max_episodes_hint' => 'Laissez vide pour importer tous les épisodes', + 'lock_import' => + 'Ce flux est protégé. Vous ne pouvez pas l’importer. Si en vous êtes le propriétaire, déprotégez-le sur la plate-forme d’origine.', + 'submit' => 'Importer le podcast', +]; diff --git a/modules/Admin/Language/fr/PodcastNavigation.php b/modules/Admin/Language/fr/PodcastNavigation.php index f02631d4..86a1bf52 100644 --- a/modules/Admin/Language/fr/PodcastNavigation.php +++ b/modules/Admin/Language/fr/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Aller à la page du podcast', - 'rss_feed' => 'Flux RSS', 'dashboard' => 'Tableau de bord du podcast', 'podcast-view' => 'Accueil', 'podcast-edit' => 'Modifier le podcast', 'podcast-persons-manage' => 'Gestion des intervenants', - 'podcast-imports' => 'Imports de podcasts', - 'podcast-imports-sync' => 'Synchronisation des flux', 'episodes' => 'Épisodes', 'episode-list' => 'Tous les épisodes', 'episode-create' => 'Créer un épisode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Lecteurs', 'podcast-analytics-listening-time' => 'Durée d’écoute', 'podcast-analytics-time-periods' => 'Périodes', - 'monetization' => 'Monétisation', - 'subscription-list' => 'Tous les abonnements', - 'subscription-create' => 'Ajouter un abonnement', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributeurs', 'contributor-list' => 'Tous les contributeurs', 'contributor-add' => 'Ajouter un contributeur', - 'broadcast' => 'Diffusion', - 'platforms-podcasting' => 'Apps de Podcasting', + 'platforms' => 'Plate-formes externes', + 'platforms-podcasting' => 'Podcasts', 'platforms-social' => 'Réseaux sociaux', - 'platforms-funding' => 'Liens de financement', - 'podcast-monetization-other' => 'Autre', + 'platforms-funding' => 'Financement', ]; diff --git a/modules/Admin/Language/fr/Settings.php b/modules/Admin/Language/fr/Settings.php index f32fc3ec..e6b0f547 100644 --- a/modules/Admin/Language/fr/Settings.php +++ b/modules/Admin/Language/fr/Settings.php @@ -35,8 +35,8 @@ return [ 'reset_counts_helper' => 'Cette option recalcule et réinitialise les compteurs de données (nombre d’abonné·e·s, de publications, de commentaires, …).', 'rewrite_media' => 'Réécrire les métadonnées des fichiers média', 'rewrite_media_helper' => 'Cette option supprimera tous les fichiers média superflus et les recréera (images, fichiers audio, transcripts, chapitrages, …)', - 'rename_episodes_files' => 'Renommer les fichiers audio de l\'épisode', - 'rename_episodes_files_hint' => 'Cette option renommera tous les fichiers audio des épisodes en une chaîne de caractères aléatoire. Utilisez-le si l\'un de vos liens d\'épisodes privés a été divulgué, car cela le masquera efficacement.', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', 'clear_cache' => 'Supprimer tout le cache', 'clear_cache_helper' => 'Cette option supprimera l’intégralité du cache redis ou des fichiers cache du dossier writable/cache.', 'run' => 'Faire le ménage', diff --git a/modules/Auth/Language/fr/User.php b/modules/Admin/Language/fr/User.php similarity index 73% rename from modules/Auth/Language/fr/User.php rename to modules/Admin/Language/fr/User.php index 91139158..c5d33a12 100644 --- a/modules/Auth/Language/fr/User.php +++ b/modules/Admin/Language/fr/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Modifier le rôle de {username}", + 'edit_roles' => "Modifier les rôles de {username}", + 'forcePassReset' => 'Forcer la réinitialisation du mot de passe', 'ban' => 'Bloquer', 'unban' => 'Débloquer', 'delete' => 'Supprimer', @@ -18,7 +19,7 @@ return [ 'all_users' => 'Tous les utilisateurs', 'list' => [ 'user' => 'Utilisateurs', - 'role' => 'Rôle', + 'roles' => 'Rôles', 'banned' => 'Bloqué ?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Identifiant', 'password' => 'Mot de passe', 'new_password' => 'Nouveau mot de passe', - 'role' => 'Rôle', 'roles' => 'Rôles', 'permissions' => 'Permissions', 'submit_create' => 'Créer un utilisateur', 'submit_edit' => 'Enregistrer', 'submit_password_change' => 'Valider !', ], - 'delete_form' => [ - 'title' => 'Supprimer {user}', - 'disclaimer' => - "Vous êtes sur le point de supprimer {user} définitivement. Ils ne pourront plus accéder à la zone d'administration.", - 'understand' => 'Je comprends, je veux supprimer {user} définitivement', - 'submit' => 'Supprimer', + 'roles' => [ + 'superadmin' => 'Super-utilisateur', ], 'messages' => [ 'createSuccess' => 'Utilisateur créé avec succès ! {username} devra modifier son mot de passe à la première authentification.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "Les rôles de {username} ont été mis à jour avec succès.", + 'forcePassResetSuccess' => + '{username} devra modifier son mot de passe à la prochaine visite.', 'banSuccess' => '{username} a été bloqué.', 'unbanSuccess' => '{username} a été débloqué.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} est un super-utilisateur, on ne bloque pas un super-utilisateur comme ça…', - 'deleteOwnerError' => - '{username} est le propriétaire de l\'instance, on ne supprime pas le propriétaire…', 'deleteSuperAdminError' => '{username} est un super-utilisateur, on ne supprime pas un super-utilisateur comme ça…', 'deleteSuccess' => '{username} a été supprimé.', diff --git a/modules/Admin/Language/fr/Validation.php b/modules/Admin/Language/fr/Validation.php index 2054829b..e9989330 100644 --- a/modules/Admin/Language/fr/Validation.php +++ b/modules/Admin/Language/fr/Validation.php @@ -13,5 +13,6 @@ return [ '{field} n’est pas une image ou n’a pas la taille minimale requise.', 'is_image_ratio' => '{field} n’est pas une image ou n’est pas au bon format.', - 'is_json' => '{field} contient un JSON non valide.', + 'validate_url' => + 'Le champs {field} doit être une adresse valide (par exemple https://exemple.com/).', ]; diff --git a/modules/Admin/Language/fr2/AboutCastopod.php b/modules/Admin/Language/fr2/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/fr2/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/fr2/Breadcrumb.php b/modules/Admin/Language/fr2/Breadcrumb.php deleted file mode 100644 index 52e423ee..00000000 --- a/modules/Admin/Language/fr2/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'fil d’Ariane', - config('Admin') - ->gateway => 'Accueil', - 'podcasts' => 'podcasts', - 'episodes' => 'épisodes', - 'subscriptions' => 'abonnements', - 'contributors' => 'contributeurs', - 'pages' => 'pages', - 'settings' => 'paramètres', - 'theme' => 'thème', - 'about' => 'à propos', - 'add' => 'ajouter', - 'new' => 'créer', - 'edit' => 'modifier', - 'persons' => 'intervenants', - 'publish' => 'publier', - 'publish-edit' => 'modifier la publication', - 'publish-date-edit' => 'modifier la date de publication', - 'unpublish' => 'dépublier', - 'delete' => 'supprimer', - 'remove' => 'retirer', - 'fediverse' => 'fédiverse', - 'blocked-actors' => 'utilisateurs bloqués', - 'blocked-domains' => 'domaines bloqués', - 'users' => 'utilisateurs', - 'my-account' => 'mon compte', - 'change-password' => 'changer le mot de passe', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'plateformes', - 'social' => 'réseaux sociaux', - 'funding' => 'financement', - 'monetization-other' => 'other monetization', - 'analytics' => 'mesure d’audience', - 'locations' => 'localisation', - 'webpages' => 'pages web', - 'unique-listeners' => 'auditeurs uniques', - 'players' => 'lecteurs', - 'listening-time' => 'durée d’écoute', - 'time-periods' => 'périodes', - 'soundbites' => 'extraits sonores', - 'video-clips' => 'extraits vidéo', - 'embed' => 'lecteur intégré', - 'notifications' => 'notifications', - 'suspend' => 'suspendre', -]; diff --git a/modules/Admin/Language/fr2/Charts.php b/modules/Admin/Language/fr2/Charts.php deleted file mode 100644 index 22759389..00000000 --- a/modules/Admin/Language/fr2/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Téléchargements d’épisodes par service (la semaine dernière)', - 'by_player_weekly' => 'Téléchargements d’épisodes par lecteur (la semaine dernière)', - 'by_player_yearly' => 'Téléchargements d’épisodes par lecteur (cette année)', - 'by_device_weekly' => 'Téléchargements d’épisodes par appareil (la semaine dernière)', - 'by_os_weekly' => 'Téléchargements d’épisodes par OS (la semaine dernière)', - 'podcast_by_region' => 'Téléchargements d’épisodes par région (la semaine dernière)', - 'unique_daily_listeners' => 'Auditeurs uniques quotidiens', - 'unique_monthly_listeners' => 'Auditeurs uniques mensuels', - 'by_browser' => 'Fréquentation des pages web par navigateur (la semaine dernière)', - 'podcast_by_day' => 'Téléchargements quotidiens d’épisodes', - 'podcast_by_month' => 'Téléchargements mensuels d’épisodes', - 'episode_by_day' => 'Téléchargements quotidiens de l’épisode (les 60 premiers jours)', - 'episode_by_month' => 'Téléchargements mensuels de l’épisode', - 'episodes_by_day' => - 'Téléchargements des 5 derniers épisodes (lors de leurs 60 premiers jours)', - 'by_country_weekly' => 'Téléchargements d’épisodes par pays (la dernière semaine)', - 'by_country_yearly' => 'Téléchargements d’épisodes par pays (l\'année dernière)', - 'by_domain_weekly' => 'Fréquentation des pages web par origine (la semaine dernière)', - 'by_domain_yearly' => 'Fréquentation des pages web par origine (la semaine dernière)', - 'by_entry_page' => 'Fréquentation des pages web par page d’entrée (la semaine dernière)', - 'podcast_bots' => 'Robots (bots)', - 'daily_listening_time' => 'Durée quotidienne d’écoute cumulée', - 'monthly_listening_time' => 'Durée mensuelle d’écoute cumulée', - 'by_weekday' => 'Par jour de la semaine (les 60 derniers jours)', - 'by_hour' => 'Par heure de la journée (les 60 derniers jours)', - 'podcast_by_bandwidth' => 'Bande passante quotidienne consommée (en Mo)', - 'total_storage_by_month' => 'Stockage mensuel (en Mo)', - 'total_bandwidth_by_month' => 'Bande passante mensuelle utilisée (en Mo)', - 'total_bandwidth_by_month_limit' => 'Limité à {totalBandwidth} par mois', -]; diff --git a/modules/Admin/Language/fr2/Common.php b/modules/Admin/Language/fr2/Common.php deleted file mode 100644 index 73daacf7..00000000 --- a/modules/Admin/Language/fr2/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Oui', - 'no' => 'Non', - 'cancel' => 'Annuler', - 'optional' => 'Optionnel', - 'more' => 'Plus', - 'no_data' => 'Aucune donnée trouvée  !', - 'close' => 'Fermer', - 'edit' => 'Modifier', - 'copy' => 'Copier', - 'copied' => 'Copié  !', - 'home' => 'Accueil', - 'explicit' => 'Explicite', - 'powered_by' => 'Propulsé par {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} sur {pageCount}', - 'go_back' => 'Retour en arrière', - 'forms' => [ - 'editor' => [ - 'write' => 'Écrire', - 'preview' => 'Aperçu', - 'help' => 'Propulsé par markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Cliquez pour selectionner', - 'loadingText' => 'Chargement…', - 'noResultsText' => 'Aucun résultat trouvé', - 'noChoicesText' => 'Aucune sélection possible', - 'maxItemText' => 'Impossible de rajouter un élément', - ], - 'upload_file' => 'Téléverser un fichier', - 'remote_url' => 'URL distante', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Lire', - 'playing' => 'En cours', - ], - 'size_limit' => 'Taille maximale : {0}.', - 'choose_interact' => 'Choisissez le mode d\'interaction', - 'view' => 'Voir', -]; diff --git a/modules/Admin/Language/fr2/Countries.php b/modules/Admin/Language/fr2/Countries.php deleted file mode 100644 index a0e70692..00000000 --- a/modules/Admin/Language/fr2/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorre', - 'AE' => 'Émirats Arabes Unis', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua-Et-Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albanie', - 'AM' => 'Arménie', - 'AO' => 'Angola', - 'AQ' => 'Antarctique', - 'AR' => 'Argentine', - 'AS' => 'Samoa Américaines', - 'AT' => 'Autriche', - 'AU' => 'Australie', - 'AW' => 'Aruba', - 'AX' => 'Åland, Îles', - 'AZ' => 'Azerbaïdjan', - 'BA' => 'Bosnie-Herzégovine', - 'BB' => 'Barbade', - 'BD' => 'Bangladesh', - 'BE' => 'Belgique', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgarie', - 'BH' => 'Bahreïn', - 'BI' => 'Burundi', - 'BJ' => 'Bénin', - 'BL' => 'Saint-Barthélemy', - 'BM' => 'Bermudes', - 'BN' => 'Brunéi Darussalam', - 'BO' => 'Bolivie, État Plurinational De', - 'BQ' => 'Bonaire, Saint-Eustache Et Saba', - 'BR' => 'Brésil', - 'BS' => 'Bahamas', - 'BT' => 'Bhoutan', - 'BV' => 'Bouvet, Île', - 'BW' => 'Botswana', - 'BY' => 'Bélarus', - 'BZ' => 'Bélize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling), Îles', - 'CD' => 'Congo, La République Démocratique Du', - 'CF' => 'Centrafricaine, République', - 'CG' => 'Congo', - 'CH' => 'Suisse', - 'CI' => "Côte D’ivoire", - 'CK' => 'Cook, Îles', - 'CL' => 'Chili', - 'CM' => 'Cameroun', - 'CN' => 'Chine', - 'CO' => 'Colombie', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cap-Vert', - 'CW' => 'Curaçao', - 'CX' => 'Christmas, Île', - 'CY' => 'Chypre', - 'CZ' => 'Tchéquie', - 'DE' => 'Allemagne', - 'DJ' => 'Djibouti', - 'DK' => 'Danemark', - 'DM' => 'Dominique', - 'DO' => 'République Dominicaine', - 'DZ' => 'Algérie', - 'EC' => 'Équateur', - 'EE' => 'Estonie', - 'EG' => 'Égypte', - 'EH' => 'Sahara Occidental', - 'ER' => 'Érythrée', - 'ES' => 'Espagne', - 'ET' => 'Éthiopie', - 'FI' => 'Finlande', - 'FJ' => 'Fidji', - 'FK' => 'Falkland, Îles (Malvinas)', - 'FM' => 'Micronésie, États Fédérés De', - 'FO' => 'Féroé, Îles', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'Royaume-Uni', - 'GD' => 'Grenade', - 'GE' => 'Géorgie', - 'GF' => 'Guyane Française', - 'GG' => 'Guernesey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Groenland', - 'GM' => 'Gambie', - 'GN' => 'Guinée', - 'GP' => 'Guadeloupe', - 'GQ' => 'Guinée Équatoriale', - 'GR' => 'Grèce', - 'GS' => 'Géorgie Du Sud Et Les Îles Sandwich Du Sud', - 'GT' => 'Guatémala', - 'GU' => 'Guam', - 'GW' => 'Guinée-Bissau', - 'GY' => 'Guyane', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Et Macdonald, Îles', - 'HN' => 'Honduras', - 'HR' => 'Croatie', - 'HT' => 'Haïti', - 'HU' => 'Hongrie', - 'ID' => 'Indonésie', - 'IE' => 'Irlande', - 'IL' => 'Israël', - 'IM' => 'Île De Man', - 'IN' => 'Inde', - 'IO' => 'Océan Indien, Territoire Britannique De L’', - 'IQ' => 'Irak', - 'IR' => 'Iran, République Islamique D’', - 'IS' => 'Islande', - 'IT' => 'Italie', - 'JE' => 'Jersey', - 'JM' => 'Jamaïque', - 'JO' => 'Jordanie', - 'JP' => 'Japon', - 'KE' => 'Kenya', - 'KG' => 'Kirghizistan', - 'KH' => 'Cambodge', - 'KI' => 'Kiribati', - 'KM' => 'Comores', - 'KN' => 'Saint-Kitts-Et-Nevis', - 'KP' => "Corée, République Populaire Démocratique De", - 'KR' => 'Corée, République De', - 'KW' => 'Koweït', - 'KY' => 'Caïmanes, Îles', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao, République Démocratique Populaire", - 'LB' => 'Liban', - 'LC' => 'Sainte-Lucie', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Libéria', - 'LS' => 'Lesotho', - 'LT' => 'Lituanie', - 'LU' => 'Luxembourg', - 'LV' => 'Lettonie', - 'LY' => 'Libye', - 'MA' => 'Maroc', - 'MC' => 'Monaco', - 'MD' => 'Moldavie', - 'ME' => 'Monténégro', - 'MF' => 'Saint-Martin (Partie Française)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall, Îles', - 'MK' => 'République De Macédoine', - 'ML' => 'Mali', - 'MM' => 'Birmanie', - 'MN' => 'Mongolie', - 'MO' => 'Macao', - 'MP' => 'Mariannes Du Nord, Îles', - 'MQ' => 'Martinique', - 'MR' => 'Mauritanie', - 'MS' => 'Montserrat', - 'MT' => 'Malte', - 'MU' => 'Maurice', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexique', - 'MY' => 'Malaisie', - 'MZ' => 'Mozambique', - 'N/A' => 'Non Applicable (IP locale…)', - 'NA' => 'Namibie', - 'NC' => 'Nouvelle-Calédonie', - 'NE' => 'Niger', - 'NF' => 'Norfolk, Île', - 'NG' => 'Nigéria', - 'NI' => 'Nicaragua', - 'NL' => 'Pays-Bas', - 'NO' => 'Norvège', - 'NP' => 'Népal', - 'NR' => 'Nauru', - 'NU' => 'Niué', - 'NZ' => 'Nouvelle-Zélande', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Pérou', - 'PF' => 'Polynésie Française', - 'PG' => 'Papouasie-Nouvelle-Guinée', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Pologne', - 'PM' => 'Saint-Pierre-Et-Miquelon', - 'PN' => 'Îles Pitcairn', - 'PR' => 'Porto Rico', - 'PS' => 'État De Palestine', - 'PT' => 'Portugal', - 'PW' => 'Palaos', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'La Réunion', - 'RO' => 'Roumanie', - 'RS' => 'Serbie', - 'RU' => 'Russie, Fédération De', - 'RW' => 'Rwanda', - 'SA' => 'Arabie Saoudite', - 'SB' => 'Salomon, Îles', - 'SC' => 'Seychelles', - 'SD' => 'Soudan', - 'SE' => 'Suède', - 'SG' => 'Singapour', - 'SH' => 'Sainte-Hélène, Ascension Et Tristan Da Cunha', - 'SI' => 'Slovénie', - 'SJ' => 'Svalbard Et Île Jan Mayen', - 'SK' => 'Slovaquie', - 'SL' => 'Sierra Leone', - 'SM' => 'Saint-Marin', - 'SN' => 'Sénégal', - 'SO' => 'Somalie', - 'SR' => 'Suriname', - 'SS' => 'Soudan Du Sud', - 'ST' => 'Sao Tomé-Et-Principe', - 'SV' => 'El Salvador', - 'SX' => 'Saint-Martin (Partie Néerlandaise)', - 'SY' => 'Syrienne, République Arabe', - 'SZ' => 'Eswatini', - 'TC' => 'Turks Et Caïques, Îles', - 'TD' => 'Tchad', - 'TF' => 'Terres Australes Françaises', - 'TG' => 'Togo', - 'TH' => 'Thaïlande', - 'TJ' => 'Tadjikistan', - 'TK' => 'Tokélaou', - 'TL' => 'Timor oriental', - 'TM' => 'Turkménistan', - 'TN' => 'Tunisie', - 'TO' => 'Tonga', - 'TR' => 'Turquie', - 'TT' => 'Trinité-Et-Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taïwan', - 'TZ' => 'Tanzanie, République Unie De', - 'UA' => 'Ukraine', - 'UG' => 'Ouganda', - 'UM' => 'Îles Mineures Éloignées Des États-Unis', - 'US' => 'États-Unis', - 'UY' => 'Uruguay', - 'UZ' => 'Ouzbékistan', - 'VA' => 'Saint-Siège (État de la Cité du Vatican)', - 'VC' => 'Saint-Vincent-Et-Les-Grenadines', - 'VE' => 'Venezuela, République Bolivarienne Du', - 'VG' => 'Îles Vierges Britanniques', - 'VI' => 'Îles Vierges des États-Unis', - 'VN' => 'Vietnam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis-Et-Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yémen', - 'YT' => 'Mayotte', - 'ZA' => 'Afrique Du Sud', - 'ZM' => 'Zambie', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/fr2/Dashboard.php b/modules/Admin/Language/fr2/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/fr2/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/fr2/Episode.php b/modules/Admin/Language/fr2/Episode.php deleted file mode 100644 index 98838164..00000000 --- a/modules/Admin/Language/fr2/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Saison {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Épisode {episodeNumber}', - 'number_abbr' => 'Ép. {episodeNumber}', - 'season_episode' => 'Saison {seasonNumber} épisode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}:E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# commentaire} - other {# commentaires} - }', - 'all_podcast_episodes' => 'Tous les épisodes du podcast', - 'back_to_podcast' => 'Revenir au podcast', - 'edit' => 'Modifier', - 'preview' => 'Preview', - 'publish' => 'Publier', - 'publish_edit' => 'Modifier la publication', - 'publish_date_edit' => 'Modifier la date de publication', - 'unpublish' => 'Dépublier', - 'publish_error' => 'L’épisode est déjà publié.', - 'publish_edit_error' => 'L’épisode est déjà publié.', - 'publish_cancel_error' => 'L’épisode est déjà publié.', - 'publish_date_edit_error' => 'L\'épisode n\'a pas encore été publié, vous ne pouvez pas modifier sa date de publication.', - 'publish_date_edit_future_error' => 'La date de publication de l\'épisode ne peut être définie qu\'à une date antérieure ! Si vous souhaitez la replanifier, dépubliez-le d\'abord.', - 'publish_date_edit_success' => 'La date de publication de l\'épisode a été mise à jour avec succès !', - 'unpublish_error' => 'L’épisode n’est pas publié.', - 'delete' => 'Supprimer', - 'go_to_page' => 'Voir', - 'create' => 'Ajouter un épisode', - 'publication_status' => [ - 'published' => 'Publié', - 'with_podcast' => 'Publié', - 'scheduled' => 'Planifié', - 'not_published' => 'Non publié', - ], - 'with_podcast_hint' => 'Publier en même temps que le podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Rechercher un épisode', - 'clear' => 'Effacer la recherche', - 'submit' => 'Recherche', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# épisode} - other {# épisodes} - }', - 'episode' => 'Épisode', - 'visibility' => 'Visibilité', - 'downloads' => 'Downloads', - 'comments' => 'Commentaires', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'L’épisode a été créé avec succès  !', - 'editSuccess' => 'L’épisode a bien été mis à jour  !', - 'publishSuccess' => '{publication_status, select, - published {Épisode publié avec succès !} - scheduled {La publication de l\'épisode est planifiée avec succès !} - with_podcast {Cet épisode sera publié en même temps que le podcast.} - other {Cet épisode n\'est pas publié.} - }', - 'publishCancelSuccess' => 'La publication de l’épisode a bien été annulée  !', - 'unpublishBeforeDeleteTip' => 'Vous devez dépublier l\'épisode avant de le supprimer.', - 'scheduleDateError' => 'La date de planification doit être définie !', - 'deletePublishedEpisodeError' => 'Vous devez dépublier l\'épisode avant de le supprimer.', - 'deleteSuccess' => 'L\'épisode a bien été supprimé !', - 'deleteError' => 'Impossible de supprimer {type, select, - transcript {la transcription} - chapters {les chapitres} - image {la couverture} - audio {l\'audio} - other {le média} - } de l\'épisode.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'Il existe déjà un épisode avec le slug choisi.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapitrage', - 'chapters_hint' => 'Le fichier doit être en format “JSON Chapters”.', - 'chapters_download' => 'Télécharger le chapitrage', - 'chapters_file' => 'Fichier de chapitrage', - 'chapters_remote_url' => 'URL distante pour le fichier de chapitrage', - 'chapters_file_delete' => 'Supprimer le fichier de chapitrage', - 'advanced_section_title' => 'Paramètres avancés', - 'advanced_section_subtitle' => - 'Si vous avez besoin d’une balise RSS que Castopod ne couvre pas, définissez-la ici.', - 'custom_rss' => 'Balises RSS personnalisées pour l’épisode', - 'custom_rss_hint' => 'Ceci sera injecté dans la balise ❬item❭.', - 'block' => 'L\'épisode doit être masqué dans les catalogues publics', - 'block_hint' => - 'Statut caché ou visible de l\'épisode : activer ceci empêche l\'épisode d\'apparaître dans les Apple Podcasts, Google Podcasts, et toutes les applications tierces qui utilisent ces répertoires. (Sans garantie)', - 'submit_create' => 'Créer l’épisode', - 'submit_edit' => 'Enregistrer l’épisode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Retour au tableau de bord de l’épisode', - 'post' => 'Votre message de publication', - 'post_hint' => - "Écrivez un message pour annoncer la publication de votre épisode. Ce message sera diffusé à toutes les personnes qui vous suivent dans le fédiverse et mis en évidence sur la page d’accueil de votre podcast.", - 'message_placeholder' => 'Entrez votre message…', - 'publication_date' => 'Date de publication', - 'publication_method' => [ - 'now' => 'Maintenant', - 'schedule' => 'Planifier', - 'with_podcast' => 'Publier en même temps que le podcast', - ], - 'scheduled_publication_date' => 'Date de publication programmée', - 'scheduled_publication_date_clear' => 'Effacer la date de publication', - 'scheduled_publication_date_hint' => - 'Vous pouvez planifier la sortie de l’épisode en saisissant une date de publication future. Ce champ doit être au format YYYY-MM-DD HH:mm', - 'submit' => 'Publier', - 'submit_edit' => 'Modifier la publication', - 'cancel_publication' => 'Annuler la publication', - 'message_warning' => 'Vous n’avez pas saisi de message pour l’annonce de votre épisode  !', - 'message_warning_hint' => 'Ajouter un message augmente l’engagement sur les réseaux sociaux, donnant une meilleure visibilité à votre épisode.', - 'message_warning_submit' => 'Publier quand même', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nouvelle date de publication', - 'new_publication_date_hint' => 'Doit être défini à une date antérieure.', - 'submit' => 'Modifier la date de publication', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Dépublier l'épisode supprimera tous les commentaires et messages qui lui sont associés et le retirera du flux RSS du podcast.", - 'understand' => 'Je comprends, je veux dépublier l’épisode', - 'submit' => 'Dépublier', - ], - 'delete_form' => [ - 'disclaimer' => - "La suppression de l'épisode supprimera tous les fichiers multimédia, les commentaires, les clips vidéo et les parties sonores qui y sont associés.", - 'understand' => 'Je comprends, je veux supprimer l’épisode', - 'submit' => 'Supprimer', - ], - 'embed' => [ - 'title' => 'Lecteur intégré', - 'label' => - 'Sélectionnez une couleur de thème, copiez le code dans le presse-papier, puis collez-le sur votre site internet.', - 'clipboard_iframe' => 'Copier le code du lecteur intégré dans le presse papier', - 'clipboard_url' => 'Copier l’adresse dans le presse papier', - 'dark' => 'Sombre', - 'dark-transparent' => 'Sombre transparent', - 'light' => 'Clair', - 'light-transparent' => 'Clair transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/fr2/EpisodeNavigation.php b/modules/Admin/Language/fr2/EpisodeNavigation.php deleted file mode 100644 index 2f7ff829..00000000 --- a/modules/Admin/Language/fr2/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'Aller à la page de l’épisode', - 'dashboard' => 'Tableau de bord de l’épisode', - 'episode-view' => 'Accueil', - 'episode-edit' => 'Modifier l’épisode', - 'episode-persons-manage' => 'Gérer les intervenants', - 'embed-add' => 'Lecteur intégré', - 'clips' => 'Extraits', - 'video-clips-list' => 'Extraits vidéo', - 'video-clips-create' => 'Nouvel extrait vidéo', - 'soundbites-list' => 'Extraits sonores', - 'soundbites-create' => 'Nouvel extrait sonore', -]; diff --git a/modules/Admin/Language/fr2/Fediverse.php b/modules/Admin/Language/fr2/Fediverse.php deleted file mode 100644 index 3e7a0b26..00000000 --- a/modules/Admin/Language/fr2/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'L’utilisateur n’a pu être trouvé  !', - 'blockActorSuccess' => '{actor} a été bloqué  !', - 'unblockActorSuccess' => 'L’utilisateur a été débloqué  !', - 'blockDomainSuccess' => '{domain} a été bloqué  !', - 'unblockDomainSuccess' => '{domain} a été débloqué  !', - ], - 'blocked_actors' => 'Utilisateurs bloqués', - 'blocked_domains' => 'Domaines bloqués', - 'block_lists_form' => [ - 'handle' => 'Identifiant', - 'handle_hint' => 'Saisissez l’utilisateur @nom@domaine.', - 'domain' => 'Nom de domaine', - 'submit' => 'Bloquer !', - ], - 'list' => [ - 'actor' => 'Utilisateur', - 'domain' => 'Nom de domaine', - 'unblock' => 'Débloquer', - ], -]; diff --git a/modules/Admin/Language/fr2/Home.php b/modules/Admin/Language/fr2/Home.php deleted file mode 100644 index 0ec83396..00000000 --- a/modules/Admin/Language/fr2/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'Tous les podcasts', - 'no_podcast' => 'Aucun podcast trouvé', -]; diff --git a/modules/Admin/Language/fr2/Install.php b/modules/Admin/Language/fr2/Install.php deleted file mode 100644 index b7d6ea1b..00000000 --- a/modules/Admin/Language/fr2/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Configuration manuelle', - 'manual_config_subtitle' => - 'Créez un fichier `.env` qui contient tous vos paramètres puis rafraîchissez la page pour continuer l’installation.', - 'form' => [ - 'instance_config' => 'Paramètres de l’instance', - 'hostname' => 'Nom d’hôte', - 'media_base_url' => 'Adresse racine des médias', - 'media_base_url_hint' => - 'Si vous utilisez un CDN et/ou un service de mesure d’audience externe, vous pouvez les définir ici.', - 'admin_gateway' => 'Adresse d’administration', - 'admin_gateway_hint' => - 'Chemin pour accéder à l’administration (par exemple https://example.com/cp-admin). Il est défini par défaut à cp-admin, nous vous recommandons de le changer par mesure de sécurité.', - 'auth_gateway' => 'Adresse d’authentification', - 'auth_gateway_hint' => - 'Le chemin des pages d’authentication (par exemple https://example.fr/cp-auth). Il est défini par défaut à cp-auth, nous vous recommandons de le changer par mesure de sécurité.', - 'database_config' => 'Paramètres de la base de données', - 'database_config_hint' => - 'Castopod doit se connecter à votre base de données MySQL (ou MariaDB). Si vous ne disposez pas de ces informations, merci de contacter l’administrateur du serveur.', - 'db_hostname' => 'Nom d’hôte (ou IP) de la base de données', - 'db_name' => 'Nom de la base de données', - 'db_username' => 'Utilisateur de la base de données', - 'db_password' => 'Mot de passe de la base de données', - 'db_prefix' => 'Préfixe des tables', - 'db_prefix_hint' => - "Le préfixe des noms de tables de Castopod, laissez la valeur par défaut si vous ne savez pas de quoi il s’agit.", - 'cache_config' => 'Paramètres du cache', - 'cache_config_hint' => - 'Sélectionnez votre gestionnaire de cache préféré. Laissez la valeur par défaut si vous ne savez pas de quoi il s’agit.', - 'cache_handler' => 'Gestionnaire de cache', - 'cacheHandlerOptions' => [ - 'file' => 'Fichier', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Suivant', - 'submit' => 'Terminer l’installation', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/fr2/Navigation.php b/modules/Admin/Language/fr2/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/fr2/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/fr2/Notifications.php b/modules/Admin/Language/fr2/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/fr2/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/fr2/Page.php b/modules/Admin/Language/fr2/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/fr2/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/fr2/Pager.php b/modules/Admin/Language/fr2/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/fr2/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/fr2/Person.php b/modules/Admin/Language/fr2/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/fr2/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/fr2/Platforms.php b/modules/Admin/Language/fr2/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/fr2/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/fr2/Podcast.php b/modules/Admin/Language/fr2/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/fr2/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/fr2/PodcastNavigation.php b/modules/Admin/Language/fr2/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/fr2/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/fr2/Settings.php b/modules/Admin/Language/fr2/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/fr2/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/fr2/Soundbite.php b/modules/Admin/Language/fr2/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/fr2/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/fr2/Validation.php b/modules/Admin/Language/fr2/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/fr2/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/fr2/VideoClip.php b/modules/Admin/Language/fr2/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/fr2/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/gd/AboutCastopod.php b/modules/Admin/Language/gd/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/gd/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/gd/Breadcrumb.php b/modules/Admin/Language/gd/Breadcrumb.php index 408c9f9f..f3269bfa 100644 --- a/modules/Admin/Language/gd/Breadcrumb.php +++ b/modules/Admin/Language/gd/Breadcrumb.php @@ -19,7 +19,6 @@ return [ 'pages' => 'pages', 'settings' => 'settings', 'theme' => 'theme', - 'about' => 'about', 'add' => 'add', 'new' => 'new', 'edit' => 'edit', @@ -29,19 +28,15 @@ return [ 'publish-date-edit' => 'edit publication date', 'unpublish' => 'unpublish', 'delete' => 'delete', - 'remove' => 'remove', 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'block lists', 'users' => 'users', 'my-account' => 'my account', 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'feed import', 'platforms' => 'platforms', 'social' => 'social networks', 'funding' => 'funding', - 'monetization-other' => 'other monetization', 'analytics' => 'analytics', 'locations' => 'locations', 'webpages' => 'web pages', diff --git a/modules/Admin/Language/gd/Charts.php b/modules/Admin/Language/gd/Charts.php index 6ede2510..4b33530e 100644 --- a/modules/Admin/Language/gd/Charts.php +++ b/modules/Admin/Language/gd/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/gd/Common.php b/modules/Admin/Language/gd/Common.php index 74addcf2..596c8bcd 100644 --- a/modules/Admin/Language/gd/Common.php +++ b/modules/Admin/Language/gd/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Upload a file', 'remote_url' => 'Remote URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Play', diff --git a/modules/Auth/Language/eu/Contributor.php b/modules/Admin/Language/gd/Contributor.php similarity index 70% rename from modules/Auth/Language/eu/Contributor.php rename to modules/Admin/Language/gd/Contributor.php index c70badc0..d0f3b93d 100644 --- a/modules/Auth/Language/eu/Contributor.php +++ b/modules/Admin/Language/gd/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Add contributor', 'submit_edit' => 'Update role', ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', + 'roles' => [ + 'podcast_admin' => 'Podcast admin', ], 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", 'removeOwnerError' => "You can't remove the podcast owner!", 'removeSuccess' => 'You have successfully removed {username} from {podcastTitle}', diff --git a/modules/Admin/Language/gd/Episode.php b/modules/Admin/Language/gd/Episode.php index 4fa846e3..91313a7c 100644 --- a/modules/Admin/Language/gd/Episode.php +++ b/modules/Admin/Language/gd/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'All podcast episodes', 'back_to_podcast' => 'Go back to podcast', 'edit' => 'Edit', - 'preview' => 'Preview', 'publish' => 'Publish', 'publish_edit' => 'Edit publication', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episode', 'visibility' => 'Visibility', - 'downloads' => 'Downloads', 'comments' => 'Comments', 'actions' => 'Actions', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'Chapters', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/eu/MyAccount.php b/modules/Admin/Language/gd/MyAccount.php similarity index 100% rename from modules/Auth/Language/eu/MyAccount.php rename to modules/Admin/Language/gd/MyAccount.php diff --git a/modules/Admin/Language/gd/Navigation.php b/modules/Admin/Language/gd/Navigation.php index f3ffb129..68d4609d 100644 --- a/modules/Admin/Language/gd/Navigation.php +++ b/modules/Admin/Language/gd/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Dashboard', 'admin' => 'Home', 'podcasts' => 'Podcasts', 'podcast-list' => 'All podcasts', 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Import a podcast', 'persons' => 'Persons', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -35,7 +33,6 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Admin/Language/gd/Platforms.php b/modules/Admin/Language/gd/Platforms.php index e161181c..ab17d599 100644 --- a/modules/Admin/Language/gd/Platforms.php +++ b/modules/Admin/Language/gd/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Platforms', 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', 'remove' => 'Remove {platformName}', diff --git a/modules/Admin/Language/gd/Podcast.php b/modules/Admin/Language/gd/Podcast.php index ff0daebc..426b763b 100644 --- a/modules/Admin/Language/gd/Podcast.php +++ b/modules/Admin/Language/gd/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No podcast found!', 'create' => 'Create podcast', 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'New Episode', 'view' => 'View podcast', 'edit' => 'Edit podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Delete podcast', 'see_episodes' => 'See episodes', 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Go to page', 'latest_episodes' => 'Latest episodes', 'see_all_episodes' => 'See all episodes', @@ -50,6 +48,7 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], 'description' => 'Description', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/gd/PodcastImport.php b/modules/Admin/Language/gd/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/gd/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/gd/PodcastNavigation.php b/modules/Admin/Language/gd/PodcastNavigation.php index bb777707..b4d7ddc0 100644 --- a/modules/Admin/Language/gd/PodcastNavigation.php +++ b/modules/Admin/Language/gd/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'Home', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodes', 'episode-list' => 'All episodes', 'episode-create' => 'New episode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Auth/Language/pt/User.php b/modules/Admin/Language/gd/User.php similarity index 73% rename from modules/Auth/Language/pt/User.php rename to modules/Admin/Language/gd/User.php index e7908f5b..585d6799 100644 --- a/modules/Auth/Language/pt/User.php +++ b/modules/Admin/Language/gd/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Edit {username}'s role", + 'edit_roles' => "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', 'ban' => 'Ban', 'unban' => 'Unban', 'delete' => 'Delete', @@ -18,7 +19,7 @@ return [ 'all_users' => 'All users', 'list' => [ 'user' => 'User', - 'role' => 'Role', + 'roles' => 'Roles', 'banned' => 'Banned?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Username', 'password' => 'Password', 'new_password' => 'New Password', - 'role' => 'Role', 'roles' => 'Roles', 'permissions' => 'Permissions', 'submit_create' => 'Create user', 'submit_edit' => 'Save', 'submit_password_change' => 'Change!', ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', + 'roles' => [ + 'superadmin' => 'Super admin', ], 'messages' => [ 'createSuccess' => 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', 'banSuccess' => '{username} has been banned.', 'unbanSuccess' => '{username} has been unbanned.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', 'deleteSuperAdminError' => '{username} is a superadmin, one does not simply delete a superadmin…', 'deleteSuccess' => '{username} has been deleted.', diff --git a/modules/Admin/Language/gd/Validation.php b/modules/Admin/Language/gd/Validation.php index f76c3163..750b1968 100644 --- a/modules/Admin/Language/gd/Validation.php +++ b/modules/Admin/Language/gd/Validation.php @@ -13,5 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/gl/AboutCastopod.php b/modules/Admin/Language/gl/AboutCastopod.php deleted file mode 100644 index 3c26b13f..00000000 --- a/modules/Admin/Language/gl/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Acerca de Castopod', - 'host_name' => 'Nome do servidor', - 'version' => 'Versión de Castopod', - 'php_version' => 'Versión de PHP', - 'os' => 'Sistema Operativo', - 'languages' => 'Idiomas', - 'update_database' => 'Anovar base de datos', - 'messages' => [ - 'databaseUpdateSuccess' => 'A base de datos está ao día!', - ], -]; diff --git a/modules/Admin/Language/gl/Breadcrumb.php b/modules/Admin/Language/gl/Breadcrumb.php index fa515f15..7aa07fba 100644 --- a/modules/Admin/Language/gl/Breadcrumb.php +++ b/modules/Admin/Language/gl/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Inicio', 'podcasts' => 'podcasts', 'episodes' => 'episodios', - 'subscriptions' => 'subscricións', + 'subscriptions' => 'subscriptions', 'contributors' => 'contribúen', 'pages' => 'páxinas', 'settings' => 'axustes', 'theme' => 'decorado', - 'about' => 'acerca de', 'add' => 'engadir', 'new' => 'novo', 'edit' => 'editar', 'persons' => 'persoas', 'publish' => 'publicar', 'publish-edit' => 'editar publicación', - 'publish-date-edit' => 'editar data de publicación', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'retirar publicación', 'delete' => 'eliminar', - 'remove' => 'eliminar', 'fediverse' => 'fediverso', - 'blocked-actors' => 'contas bloqueadas', - 'blocked-domains' => 'dominios bloqueados', + 'block-lists' => 'listas de bloqueo', 'users' => 'usuarias', 'my-account' => 'a miña conta', 'change-password' => 'cambiar contrasinal', - 'imports' => 'importacións', - 'sync-feeds' => 'sincronizar fontes', + 'import' => 'importar fonte', 'platforms' => 'plataformas', 'social' => 'redes sociais', 'funding' => 'financiamento', - 'monetization-other' => 'outros xeitos', 'analytics' => 'análise', 'locations' => 'localizacións', 'webpages' => 'páxinas web', @@ -53,5 +48,5 @@ return [ 'video-clips' => 'clips de vídeo', 'embed' => 'reprodutor para incluír', 'notifications' => 'notificacións', - 'suspend' => 'suspender', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/gl/Charts.php b/modules/Admin/Language/gl/Charts.php index 0e232ad4..edd2f8af 100644 --- a/modules/Admin/Language/gl/Charts.php +++ b/modules/Admin/Language/gl/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Ancho de banda diario utilizado (en MB)', 'total_storage_by_month' => 'Almacenaxe mensual (en MB)', 'total_bandwidth_by_month' => 'Ancho de banda mensual utilizado (en MB)', - 'total_bandwidth_by_month_limit' => 'Limitado a {totalBandwidth} ao mes', ]; diff --git a/modules/Admin/Language/gl/Common.php b/modules/Admin/Language/gl/Common.php index 97f03466..66a6f8d2 100644 --- a/modules/Admin/Language/gl/Common.php +++ b/modules/Admin/Language/gl/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Subir un ficheiro', 'remote_url' => 'URL remoto', - 'save' => 'Gardar', ], 'play_episode_button' => [ 'play' => 'Reproducir', diff --git a/modules/Auth/Language/gl/Contributor.php b/modules/Admin/Language/gl/Contributor.php similarity index 71% rename from modules/Auth/Language/gl/Contributor.php rename to modules/Admin/Language/gl/Contributor.php index 14dcf288..a09021cd 100644 --- a/modules/Auth/Language/gl/Contributor.php +++ b/modules/Admin/Language/gl/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Engadir colaboración', 'submit_edit' => 'Actualizar rol', ], - 'delete_form' => [ - 'title' => 'Eliminar {contributor}', - 'disclaimer' => - 'Vas a eliminar a {contributor} de entre as contribuíntes. Non poderá volver acceder a "{podcastTitle}".', - 'understand' => 'Enténdoo, quero eliminar a {contributor} de "{podcastTitle}"', - 'submit' => 'Eliminar', + 'roles' => [ + 'podcast_admin' => 'Admin podcast', ], 'messages' => [ - 'editSuccess' => 'Rol cambiado correctamente!', - 'editOwnerError' => "Non podes editar a propietaria do podcast!", 'removeOwnerError' => "Non podes eliminar a propietaria do podcast!", 'removeSuccess' => 'Quitaches correctamente a {username} de {podcastTitle}', diff --git a/modules/Admin/Language/gl/Countries.php b/modules/Admin/Language/gl/Countries.php index c79e1632..587c4d49 100644 --- a/modules/Admin/Language/gl/Countries.php +++ b/modules/Admin/Language/gl/Countries.php @@ -15,29 +15,29 @@ return [ 'AE' => 'Emiratos Árabes Unidos', 'AF' => 'Afganistán', 'AG' => 'Antigua e Barbuda', - 'AI' => 'Anguila', + 'AI' => 'Anguilla', 'AL' => 'Albania', 'AM' => 'Armenia', 'AO' => 'Angola', - 'AQ' => 'Antártida', - 'AR' => 'Arxentina', - 'AS' => 'Samoa Americana', + 'AQ' => 'Antarctica', + 'AR' => 'Argentina', + 'AS' => 'American Samoa', 'AT' => 'Austria', 'AU' => 'Australia', 'AW' => 'Aruba', - 'AX' => 'Illas Åland', - 'AZ' => 'Acerbaixán', - 'BA' => 'Bosnia e Hercegovina', + 'AX' => 'Åland Islands', + 'AZ' => 'Azerbaijan', + 'BA' => 'Bosnia and Herzegovina', 'BB' => 'Barbados', 'BD' => 'Bangladesh', - 'BE' => 'Bélxica', + 'BE' => 'Belgium', 'BF' => 'Burkina Faso', 'BG' => 'Bulgaria', 'BH' => 'Bahrain', 'BI' => 'Burundi', - 'BJ' => 'Benín', - 'BL' => 'San Bartolomé', - 'BM' => 'Bermudas', + 'BJ' => 'Benin', + 'BL' => 'Saint Barthélemy', + 'BM' => 'Bermuda', 'BN' => 'Brunei Darussalam', 'BO' => 'Bolivia, Plurinational State of', 'BQ' => 'Bonaire, Sint Eustatius and Saba', diff --git a/modules/Admin/Language/gl/Episode.php b/modules/Admin/Language/gl/Episode.php index 00919216..9e2da4b4 100644 --- a/modules/Admin/Language/gl/Episode.php +++ b/modules/Admin/Language/gl/Episode.php @@ -22,17 +22,16 @@ return [ 'all_podcast_episodes' => 'Tódolos episodios do podcast', 'back_to_podcast' => 'Volver ao podcast', 'edit' => 'Editar', - 'preview' => 'Vista previa', 'publish' => 'Publicar', 'publish_edit' => 'Editar publicación', - 'publish_date_edit' => 'Editar data de publicación', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Retirar publicación', 'publish_error' => 'O episodio xa está publicado.', 'publish_edit_error' => 'O episodio xa está publicado.', 'publish_cancel_error' => 'O episodio xa está publicado.', - 'publish_date_edit_error' => 'O episodio aínda non se publicou, non podes editar a súa data de publicación.', - 'publish_date_edit_future_error' => 'A data de publicación do episodio só pode establecerse nun momento do pasado! Se queres reprogramalo, primeiro retira a súa publicación.', - 'publish_date_edit_success' => 'Actualizada correctamente a data de publicación do episodio!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'O episodio non foi publicado.', 'delete' => 'Eliminar', 'go_to_page' => 'Ir á páxina', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episodio', 'visibility' => 'Visibilidade', - 'downloads' => 'Descargas', 'comments' => 'Comentarios', 'actions' => 'Accións', ], @@ -82,12 +80,12 @@ return [ other {do multimedia} } do episodio.', 'deleteFileError' => 'Fallou a eliminación do ficheiro {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } {file_key}. Deberías eliminalo a man do disco.', + transcript {da transcrición} + chapters {dos capítulos} + image {da imaxe} + audio {do audio} + other {do multimedia} + } {file_path}. Deberías eliminala manualmente do disco.', 'sameSlugError' => 'Xa existe un episodio co id de url elexido.', ], 'form' => [ @@ -116,7 +114,7 @@ return [ 'bonus_hint' => 'Contido extra para o programa (por exemplo, info sobre a elaboración ou conversa casual cos participantes) ou contido promocional de outras creadoras', ], 'premium_title' => 'Premium', - 'premium' => 'Episodio dispoñible só para subscricións premium', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Aviso sobre o contido', 'hint' => 'Contén o episodio elementos explícitos?', @@ -139,9 +137,9 @@ return [ 'location_name' => 'Nome da localización e enderezo', 'location_name_hint' => 'Pode ser unha localización real ou ficticia', 'transcript' => 'Transcrición (subtítulos / texto descritivo)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Só admite .srt', 'transcript_download' => 'Descargar transcrición', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Fichero da transcrición (.srt)', 'transcript_remote_url' => 'URL remoto da transcrición', 'transcript_file_delete' => 'Eliminar ficheiro coa transcrición', 'chapters' => 'Capítulos', @@ -185,9 +183,9 @@ return [ 'message_warning_submit' => 'Publicar igualmente', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nova data de publicación', - 'new_publication_date_hint' => 'Ten que ser unha data do pasado.', - 'submit' => 'Editar data de publicación', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => @@ -212,14 +210,4 @@ return [ 'light' => 'Claro', 'light-transparent' => 'Claro transparente', ], - 'publication_status_banner' => [ - 'draft_mode' => 'modo borrador', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Vista previa', - ], ]; diff --git a/modules/Auth/Language/gl/MyAccount.php b/modules/Admin/Language/gl/MyAccount.php similarity index 100% rename from modules/Auth/Language/gl/MyAccount.php rename to modules/Admin/Language/gl/MyAccount.php diff --git a/modules/Admin/Language/gl/Navigation.php b/modules/Admin/Language/gl/Navigation.php index eddbd6cb..68d4609d 100644 --- a/modules/Admin/Language/gl/Navigation.php +++ b/modules/Admin/Language/gl/Navigation.php @@ -9,36 +9,33 @@ declare(strict_types=1); */ return [ - 'toggle_sidebar' => 'Activar barra lateral', - 'go_to_website' => 'Ir ao sitio web', - 'go_to_admin' => 'Ir á administración', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Taboleiro', - 'admin' => 'Inicio', + 'toggle_sidebar' => 'Toggle sidebar', + 'go_to_website' => 'Go to website', + 'go_to_admin' => 'Go to admin', + 'dashboard' => 'Dashboard', + 'admin' => 'Home', 'podcasts' => 'Podcasts', - 'podcast-list' => 'Tódolos podcast', - 'podcast-create' => 'Novo podcast', - 'all-podcast-imports' => 'Todas as importancións de Podcast', - 'podcast-imports-add' => 'Importar un podcast', - 'persons' => 'Persoas', - 'person-list' => 'Tódalas persoas', - 'person-create' => 'Nova persoa', - 'fediverse' => 'Fediverso', - 'fediverse-blocked-actors' => 'Contas bloqueadas', - 'fediverse-blocked-domains' => 'Dominios bloqueados', - 'users' => 'Usuarias', - 'user-list' => 'Tódalas usuarias', - 'user-create' => 'Nova usuaria', - 'pages' => 'Páxinas', - 'page-list' => 'Tódalas páxinas', - 'page-create' => 'Nova páxina', - 'settings' => 'Axustes', - 'settings-general' => 'Xeral', - 'settings-theme' => 'Decorado', - 'admin-about' => 'Acerca de', + 'podcast-list' => 'All podcasts', + 'podcast-create' => 'New podcast', + 'podcast-import' => 'Import a podcast', + 'persons' => 'Persons', + 'person-list' => 'All persons', + 'person-create' => 'New person', + 'fediverse' => 'Fediverse', + 'fediverse-blocked-actors' => 'Blocked accounts', + 'fediverse-blocked-domains' => 'Blocked domains', + 'users' => 'Users', + 'user-list' => 'All users', + 'user-create' => 'New user', + 'pages' => 'Pages', + 'page-list' => 'All pages', + 'page-create' => 'New Page', + 'settings' => 'Settings', + 'settings-general' => 'General', + 'settings-theme' => 'Theme', 'account' => [ - 'my-account' => 'A miña conta', - 'change-password' => 'Cambiar contrasinal', - 'logout' => 'Saír', + 'my-account' => 'My account', + 'change-password' => 'Change password', + 'logout' => 'Logout', ], ]; diff --git a/modules/Admin/Language/gl/Notifications.php b/modules/Admin/Language/gl/Notifications.php index b2b82a68..2b139d51 100644 --- a/modules/Admin/Language/gl/Notifications.php +++ b/modules/Admin/Language/gl/Notifications.php @@ -9,11 +9,11 @@ declare(strict_types=1); */ return [ - 'title' => 'Notificacións', - 'reply' => '{actor_username} respondeu á túa publicación', - 'favourite' => '{actor_username} fixo favorita a túa publicación', - 'reblog' => '{actor_username} compartiu a túa publicación', - 'follow' => '{actor_username} comezou a seguirte', - 'no_notifications' => 'Sen notificacións', - 'mark_all_as_read' => 'Marcar todo como lido', + 'title' => 'Notifications', + 'reply' => '{actor_username} replied to your post', + 'favourite' => '{actor_username} favourited your post', + 'reblog' => '{actor_username} shared your post', + 'follow' => '{actor_username} started following you', + 'no_notifications' => 'No notifications', + 'mark_all_as_read' => 'Mark all as read', ]; diff --git a/modules/Admin/Language/gl/Page.php b/modules/Admin/Language/gl/Page.php index 15dbde00..b6f49de5 100644 --- a/modules/Admin/Language/gl/Page.php +++ b/modules/Admin/Language/gl/Page.php @@ -9,22 +9,22 @@ declare(strict_types=1); */ return [ - 'back_to_home' => 'Volver ao inicio', - 'page' => 'Páxina', - 'all_pages' => 'Tódalas páxinas', - 'create' => 'Nova páxina', - 'go_to_page' => 'Ir á páxina', - 'edit' => 'Editar páxina', - 'delete' => 'Eliminar páxina', + 'back_to_home' => 'Back to home', + 'page' => 'Page', + 'all_pages' => 'All pages', + 'create' => 'New page', + 'go_to_page' => 'Go to page', + 'edit' => 'Edit page', + 'delete' => 'Delete page', 'form' => [ - 'title' => 'Título', - 'permalink' => 'Ligazón permanente', - 'content' => 'Contido', - 'submit_create' => 'Crear páxina', - 'submit_edit' => 'Gardar', + 'title' => 'Title', + 'permalink' => 'Permalink', + 'content' => 'Content', + 'submit_create' => 'Create page', + 'submit_edit' => 'Save', ], 'messages' => [ - 'createSuccess' => 'Creouse correctamente a páxina "{pageTitle}"!', - 'editSuccess' => 'Actualizouse correctamente a páxina!', + 'createSuccess' => 'The page “{pageTitle}” was created successfully!', + 'editSuccess' => 'The page was successfully updated!', ], ]; diff --git a/modules/Admin/Language/gl/Pager.php b/modules/Admin/Language/gl/Pager.php index 390b2e72..e25ee638 100644 --- a/modules/Admin/Language/gl/Pager.php +++ b/modules/Admin/Language/gl/Pager.php @@ -9,13 +9,13 @@ declare(strict_types=1); */ return [ - 'pageNavigation' => 'Navegador de páxinas', - 'first' => 'Primeira', - 'previous' => 'Anterior', - 'next' => 'Seguinte', - 'last' => 'Última', - 'older' => 'Máis antiga', - 'newer' => 'Máis nova', - 'invalidTemplate' => '{0} non é un modelo para páxinas válido.', - 'invalidPaginationGroup' => '{0} non é un grupo de navegación de páxinas válido.', + 'pageNavigation' => 'Page navigation', + 'first' => 'First', + 'previous' => 'Previous', + 'next' => 'Next', + 'last' => 'Last', + 'older' => 'Older', + 'newer' => 'Newer', + 'invalidTemplate' => '{0} is not a valid Pager template.', + 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', ]; diff --git a/modules/Admin/Language/gl/Person.php b/modules/Admin/Language/gl/Person.php index b8d5bd5d..a652be9f 100644 --- a/modules/Admin/Language/gl/Person.php +++ b/modules/Admin/Language/gl/Person.php @@ -9,57 +9,57 @@ declare(strict_types=1); */ return [ - 'persons' => 'Persoas', - 'all_persons' => 'Tódalas persoas', - 'no_person' => 'Non hai ninguén!', - 'create' => 'Crear unha persoa', - 'view' => 'Ver persoa', - 'edit' => 'Editar persoa', - 'delete' => 'Eliminar persoa', + 'persons' => 'Persons', + 'all_persons' => 'All persons', + 'no_person' => 'Nobody found!', + 'create' => 'Create a person', + 'view' => 'View person', + 'edit' => 'Edit person', + 'delete' => 'Delete person', 'messages' => [ - 'createSuccess' => 'Persoa creada correctamente!', - 'editSuccess' => 'Persoa actualizada correctamente!', - 'deleteSuccess' => 'Eliminouse a Persoa!', + 'createSuccess' => 'Person has been successfully created!', + 'editSuccess' => 'Person has been successfully updated!', + 'deleteSuccess' => 'Person has been removed!', ], 'form' => [ - 'avatar' => 'Imaxe de perfil', + 'avatar' => 'Avatar', 'avatar_size_hint' => - 'A imaxe do perfil ten que ser cadrada e como pouco de 400px de alto e ancho.', - 'full_name' => 'Nome completo', - 'full_name_hint' => 'Este é o nome completo ou alias da persoa.', - 'unique_name' => 'Nome único', - 'unique_name_hint' => 'Usado nos URLs', - 'information_url' => 'URL de información', + 'Avatar must be squared and at least 400px wide and tall.', + 'full_name' => 'Full name', + 'full_name_hint' => 'This is the full name or alias of the person.', + 'unique_name' => 'Unique name', + 'unique_name_hint' => 'Used for URLs', + 'information_url' => 'Information URL', 'information_url_hint' => - 'Url a un recurso con información relevante sobre a persoa, como unha web ou plataforma de terceiras partes.', - 'submit_create' => 'Crear persoa', - 'submit_edit' => 'Gardar persoa', + 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', + 'submit_create' => 'Create person', + 'submit_edit' => 'Save person', ], 'podcast_form' => [ - 'title' => 'Xestionar persoas', - 'add_section_title' => 'Engadir persoas a este podcast', - 'add_section_subtitle' => 'Podes elexir varias persoas e roles.', - 'persons' => 'Persoas', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this podcast', + 'add_section_subtitle' => 'You may pick several persons and roles.', + 'persons' => 'Persons', 'persons_hint' => - 'Podes elexir unha ou varias persoas cos mesmos roles. Precisas crear primeiro as persoas.', + 'You may select one or several persons with the same roles. You need to create the persons first.', 'roles' => 'Roles', 'roles_hint' => - 'Podes seleccionar un, ningún ou varios roles para a persoa.', - 'submit_add' => 'Engadir persoa(s)', - 'remove' => 'Eliminar', + 'You may select none, one or several roles for a person.', + 'submit_add' => 'Add person(s)', + 'remove' => 'Remove', ], 'episode_form' => [ - 'title' => 'Xestionar persoas', - 'add_section_title' => 'Engdir persoas a este episodio', - 'add_section_subtitle' => 'Podes elexir varias persoas e roles.', - 'persons' => 'Persoas', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this episode', + 'add_section_subtitle' => 'You may pick several persons and roles.', + 'persons' => 'Persons', 'persons_hint' => - 'Podes elexir unha ou varias persoas cos mesmos roles. Primeiro tes que crear as persoas.', + 'You may select one or several persons with the same roles. You need to create the persons first.', 'roles' => 'Roles', 'roles_hint' => - 'Podes seleccionar un, ningún ou varios roles para unha persoa.', - 'submit_add' => 'Engadir persoa(s)', - 'remove' => 'Eliminar', + 'You may select none, one or several roles for a person.', + 'submit_add' => 'Add person(s)', + 'remove' => 'Remove', ], - 'credits' => 'Créditos', + 'credits' => 'Credits', ]; diff --git a/modules/Admin/Language/gl/Platforms.php b/modules/Admin/Language/gl/Platforms.php index 9d34da3a..ab17d599 100644 --- a/modules/Admin/Language/gl/Platforms.php +++ b/modules/Admin/Language/gl/Platforms.php @@ -9,35 +9,22 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Plataformas de podcast', - 'social' => 'Redes sociais', - 'funding' => 'Finanzamento', - ], - 'website' => 'Sitio web', - 'home_url' => 'Ir á web de {platformName}', - 'register' => 'Crear conta', - 'submit_url' => 'Envía o teu podcast en {platformName}', - 'your_link' => 'A túa ligazón', - 'your_id' => [ - 'podcasting' => 'O teu ID', - 'social' => 'O teu ID', - 'funding' => 'O teu CTA', - ], - 'your_cta' => 'Chamar á acción', - 'visible' => 'Mostrar na páxina de inicio do podcast?', - 'on_embed' => 'Mostrar no navegador incrustable?', - 'remove' => 'Eliminar {platformName}', - 'submit' => 'Gardar', + 'title' => 'Platforms', + 'home_url' => 'Go to {platformName} website', + 'submit_url' => 'Submit your podcast on {platformName}', + 'visible' => 'Display in podcast homepage?', + 'on_embed' => 'Display on embeddable player?', + 'remove' => 'Remove {platformName}', + 'submit' => 'Save', 'messages' => [ - 'updateSuccess' => 'Actualizáronse correctamente as ligazóns á plataforma!', - 'removeLinkSuccess' => 'Eliminouse a ligazón á plataforma.', + 'updateSuccess' => 'Platform links have been successfully updated!', + 'removeLinkSuccess' => 'The platform link has been removed.', 'removeLinkError' => - 'A ligazón á plataforma non se puido eliminar. Inténtao outra vez.', + 'The platform link could not be removed. Try again.', ], 'description' => [ - 'podcasting' => 'ID do podcast nesta plataforma', - 'social' => 'ID da conta do podcast nesta plataforma', - 'funding' => 'Mensaxe de convite a realizar acción', + 'podcasting' => 'The podcast ID on this platform', + 'social' => 'The podcast account ID on this platform', + 'funding' => 'Call to action message', ], ]; diff --git a/modules/Admin/Language/gl/Podcast.php b/modules/Admin/Language/gl/Podcast.php index baa05597..80e9d971 100644 --- a/modules/Admin/Language/gl/Podcast.php +++ b/modules/Admin/Language/gl/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'Non se atopan podcast!', 'create' => 'Crear un podcast', 'import' => 'Importar podcast', - 'all_imports' => 'Importacións de podcasts', 'new_episode' => 'Novo Episodio', 'view' => 'Ver podcast', 'edit' => 'Editar podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Eliminar podcast', 'see_episodes' => 'Ver episodios', 'see_contributors' => 'Ver colaboradoras', - 'monetization_other' => 'Outros xeitos', 'go_to_page' => 'Ir á páxina', 'latest_episodes' => 'Últimos episodios', 'see_all_episodes' => 'Ver tódolos episodios', @@ -50,86 +48,68 @@ return [ other {# episodios foron engadidos} } ao podcast!', 'podcastFeedUpToDate' => 'O podcast xa está ao día.', - 'publishError' => 'Este podcast ou ben xa foi publicado ou está programada a súa publicación.', - 'publishEditError' => 'Este podcast non ten a publicación programada.', - 'publishCancelSuccess' => 'Cancelouse correctamente a publicación do podcast!', - 'scheduleDateError' => 'Hai que establecer a data da publicación!', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', + 'publishError' => 'This podcast is either already published or scheduled for publication.', + 'publishEditError' => 'This podcast is not scheduled for publication.', + 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', + 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ - 'identity_section_title' => 'Identidade do podcast', - 'identity_section_subtitle' => 'Estes campos permítenche recibir notificacións.', - 'fediverse_section_title' => 'Identidade no fediverso', - - 'cover' => 'Portada do podcast', - 'cover_size_hint' => 'A portada ten que ser cadrada e como mínimo de 1400px de alto e ancho.', - 'banner' => 'Cabeceira do podcast', - 'banner_size_hint' => 'A imaxe de cabeceira debe ter proporción 3:1 e 1500px. como mínimo.', - 'banner_delete' => 'Eliminar cabeceira do podcast', - 'title' => 'Título', - 'handle' => 'Identificador', + 'identity_section_title' => 'Podcast identity', + 'identity_section_subtitle' => 'These fields allow you to get noticed.', + 'cover' => 'Podcast cover', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', + 'banner' => 'Podcast banner', + 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', + 'banner_delete' => 'Delete podcast banner', + 'title' => 'Title', + 'handle' => 'Handle', 'handle_hint' => - 'Utilizado para identificar o podcast. Permítense maiúsculas, minúsculas, números e trazo baixo.', + 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', 'type' => [ - 'label' => 'Tipo', - 'episodic' => 'Recurrente', - 'episodic_hint' => 'Se os episodios non teñen unha orde predeterminada para ser escoitados. Os novos episodios serán mostrados antes.', - 'serial' => 'Serie', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', + 'label' => 'Type', + 'episodic' => 'Episodic', + 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', + 'serial' => 'Serial', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Descrición', - 'classification_section_title' => 'Clasificación', + 'description' => 'Description', + 'classification_section_title' => 'Classification', 'classification_section_subtitle' => - 'Estos campos terán impacto na túa audiencia e competencia.', - 'language' => 'Idioma', - 'category' => 'Categoría', - 'category_placeholder' => 'Elixe unha categoría…', - 'other_categories' => 'Outras categorías', + 'These fields will impact your audience and competition.', + 'language' => 'Language', + 'category' => 'Category', + 'category_placeholder' => 'Select a category…', + 'other_categories' => 'Other categories', 'parental_advisory' => [ - 'label' => 'Aviso parental', - 'hint' => 'Inclúe contidos explícitos?', - 'undefined' => 'sen definir', - 'clean' => 'Aceptable', - 'explicit' => 'Explícito', + 'label' => 'Parental advisory', + 'hint' => 'Does it contain explicit content?', + 'undefined' => 'undefined', + 'clean' => 'Clean', + 'explicit' => 'Explicit', ], - 'author_section_title' => 'Autoría', - 'author_section_subtitle' => 'Quen xestiona o podcast?', - 'owner_name' => 'Nome da propietaria', + 'author_section_title' => 'Author', + 'author_section_subtitle' => 'Who is managing the podcast?', + 'owner_name' => 'Owner name', 'owner_name_hint' => - 'Só para uso administrativo. Visible na fonte RSS pública.', - 'owner_email' => 'Correo da propietaria', + 'For administrative use only. Visible in the public RSS feed.', + 'owner_email' => 'Owner email', 'owner_email_hint' => - 'Será utilizado pola maioría das plataformas para verificar a propiedade do podcast. Visible na fonte RSS pública.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Editorial', + 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', + 'publisher' => 'Publisher', 'publisher_hint' => - 'O grupo responsable da creación do programa. Normalmente refírese á empresa nai ou rede do podcast. O campo a veces etiquétase como \'Autor\'.', - 'copyright' => 'Dereitos', - 'location_section_title' => 'Localización', - 'location_section_subtitle' => 'De qué lugar trata o podcast?', - 'location_name' => 'Nome do lugar ou enderezo', - 'location_name_hint' => 'Pode ser un lugar real ou ficticio', - 'monetization_section_title' => 'Monetización', + 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', + 'copyright' => 'Copyright', + 'location_section_title' => 'Location', + 'location_section_subtitle' => 'What place is this podcast about?', + 'location_name' => 'Location name or address', + 'location_name_hint' => 'This can be a real place or fictional', + 'monetization_section_title' => 'Monetization', 'monetization_section_subtitle' => - 'Obter cartos grazas á túa audiencia.', + 'Earn money thanks to your audience.', 'premium' => 'Premium', - 'premium_by_default' => 'Os episodios estableceranse por defecto como premium', - 'premium_by_default_hint' => 'Os episodios vanse marcar por defecto como premium. Podes igualmente elexir algúns episodios, mostras ou extras como públicos.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/gl/PodcastImport.php b/modules/Admin/Language/gl/PodcastImport.php new file mode 100644 index 00000000..a5200334 --- /dev/null +++ b/modules/Admin/Language/gl/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Campo a utilizar para crear o id de url para o episodio', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/gl/PodcastNavigation.php b/modules/Admin/Language/gl/PodcastNavigation.php index c47b51dc..b4d7ddc0 100644 --- a/modules/Admin/Language/gl/PodcastNavigation.php +++ b/modules/Admin/Language/gl/PodcastNavigation.php @@ -9,34 +9,30 @@ declare(strict_types=1); */ return [ - 'go_to_page' => 'Ir á páxina do podcast', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Taboleiro do podcast', - 'podcast-view' => 'Inicio', - 'podcast-edit' => 'Editar podcast', - 'podcast-persons-manage' => 'Xestionar persoas', - 'podcast-imports' => 'Importacións de podcasts', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodios', - 'episode-list' => 'Todos os episodios', - 'episode-create' => 'Novo episodio', - 'analytics' => 'Análise', - 'podcast-analytics' => 'Ollada sobre a audiencia', - 'podcast-analytics-webpages' => 'Visitas á páxina web', - 'podcast-analytics-locations' => 'Localizacións', - 'podcast-analytics-unique-listeners' => 'Oíntes únicos', - 'podcast-analytics-players' => 'Reprodutores', - 'podcast-analytics-listening-time' => 'Tempo de escoita', - 'podcast-analytics-time-periods' => 'Período de tempo', - 'monetization' => 'Monetization', - 'subscription-list' => 'Todas as subscricións', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contribúen', - 'contributor-list' => 'Todas as contribucións', - 'contributor-add' => 'Engadir colaboración', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Redes sociais', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'go_to_page' => 'Go to podcast page', + 'dashboard' => 'Podcast dashboard', + 'podcast-view' => 'Home', + 'podcast-edit' => 'Edit podcast', + 'podcast-persons-manage' => 'Manage persons', + 'episodes' => 'Episodes', + 'episode-list' => 'All episodes', + 'episode-create' => 'New episode', + 'analytics' => 'Analytics', + 'podcast-analytics' => 'Audience overview', + 'podcast-analytics-webpages' => 'Web pages visits', + 'podcast-analytics-locations' => 'Locations', + 'podcast-analytics-unique-listeners' => 'Unique listeners', + 'podcast-analytics-players' => 'Players', + 'podcast-analytics-listening-time' => 'Listening time', + 'podcast-analytics-time-periods' => 'Time periods', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', + 'contributors' => 'Contributors', + 'contributor-list' => 'All contributors', + 'contributor-add' => 'Add contributor', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', + 'platforms-social' => 'Social networks', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Auth/Language/gl/User.php b/modules/Admin/Language/gl/User.php similarity index 73% rename from modules/Auth/Language/gl/User.php rename to modules/Admin/Language/gl/User.php index 668d56a5..4bdfcab9 100644 --- a/modules/Auth/Language/gl/User.php +++ b/modules/Admin/Language/gl/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Editar os roles de {username}", + 'edit_roles' => "Editar os roles de {username}", + 'forcePassReset' => 'Forzar restablecemento do contrasinal', 'ban' => 'Vetar', 'unban' => 'Retirar veto', 'delete' => 'Eliminar', @@ -18,7 +19,7 @@ return [ 'all_users' => 'Tódalas usuarias', 'list' => [ 'user' => 'Usuaria', - 'role' => 'Rol', + 'roles' => 'Roles', 'banned' => 'Vetada?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Identificador', 'password' => 'Contrasinal', 'new_password' => 'Novo contrasinal', - 'role' => 'Rol', 'roles' => 'Roles', 'permissions' => 'Permisos', 'submit_create' => 'Crear usuaria', 'submit_edit' => 'Gardar', 'submit_password_change' => 'Cambiar!', ], - 'delete_form' => [ - 'title' => 'Eliminar {user}', - 'disclaimer' => - "Vas eliminar de xeito permanente a {user}. Non poderá volver a acceder á páxina de administración.", - 'understand' => 'Enténdoo, quero eliminar a {user} para sempre', - 'submit' => 'Eliminar', + 'roles' => [ + 'superadmin' => 'Super admin', ], 'messages' => [ 'createSuccess' => 'Usuaria creada correctamente! Váiselle pedir a {username} que cambie o seu contrasinal após o primeiro acceso.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "Os roles de {username} actualizáronse correctamente.", + 'forcePassResetSuccess' => + 'Solicitarase que {username} restableza o contrasinal na seguinte visita.', 'banSuccess' => '{username} foi vetada.', 'unbanSuccess' => 'Retirouse o veto sobre {username}.', 'editOwnerError' => 'A instancia pertence a {username}, ti non podes editar os roles.', 'banSuperAdminError' => '{username} é superadmin, non se pode vetar a superadmin…', - 'deleteOwnerError' => - '{username} é dona da instancia, non se pode eliminar a propietaria…', 'deleteSuperAdminError' => '{username} é superadmin, non se pode eliminar a superadmin…', 'deleteSuccess' => 'Eliminouse a {username}.', diff --git a/modules/Admin/Language/gl/Validation.php b/modules/Admin/Language/gl/Validation.php index 42d6a672..54aaef52 100644 --- a/modules/Admin/Language/gl/Validation.php +++ b/modules/Admin/Language/gl/Validation.php @@ -13,5 +13,6 @@ return [ 'ou ben {field} non é unha imaxe ou non é suficientemente alta ou ancha.', 'is_image_ratio' => 'ou ben {field} non é unha imaxe ou non ten proporcións axeitadas.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'O campo {field} ten que ser un URL válido (ex. https://exemplo.com/).', ]; diff --git a/modules/Admin/Language/id/AboutCastopod.php b/modules/Admin/Language/id/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/id/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/id/Breadcrumb.php b/modules/Admin/Language/id/Breadcrumb.php index 4e6f3a8e..676e47b7 100644 --- a/modules/Admin/Language/id/Breadcrumb.php +++ b/modules/Admin/Language/id/Breadcrumb.php @@ -19,7 +19,6 @@ return [ 'pages' => 'pages', 'settings' => 'settings', 'theme' => 'theme', - 'about' => 'about', 'add' => 'add', 'new' => 'new', 'edit' => 'edit', @@ -29,19 +28,15 @@ return [ 'publish-date-edit' => 'edit publication date', 'unpublish' => 'unpublish', 'delete' => 'delete', - 'remove' => 'remove', 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'block lists', 'users' => 'pengguna', 'my-account' => 'akun saya', 'change-password' => 'ubah kata sandi', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'feed import', 'platforms' => 'platforms', 'social' => 'social networks', 'funding' => 'funding', - 'monetization-other' => 'other monetization', 'analytics' => 'analitik', 'locations' => 'locations', 'webpages' => 'web pages', diff --git a/modules/Admin/Language/id/Charts.php b/modules/Admin/Language/id/Charts.php index 6ede2510..4b33530e 100644 --- a/modules/Admin/Language/id/Charts.php +++ b/modules/Admin/Language/id/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/id/Common.php b/modules/Admin/Language/id/Common.php index 74addcf2..596c8bcd 100644 --- a/modules/Admin/Language/id/Common.php +++ b/modules/Admin/Language/id/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Upload a file', 'remote_url' => 'Remote URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Play', diff --git a/modules/Auth/Language/fa/Contributor.php b/modules/Admin/Language/id/Contributor.php similarity index 70% rename from modules/Auth/Language/fa/Contributor.php rename to modules/Admin/Language/id/Contributor.php index c70badc0..d0f3b93d 100644 --- a/modules/Auth/Language/fa/Contributor.php +++ b/modules/Admin/Language/id/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Add contributor', 'submit_edit' => 'Update role', ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', + 'roles' => [ + 'podcast_admin' => 'Podcast admin', ], 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", 'removeOwnerError' => "You can't remove the podcast owner!", 'removeSuccess' => 'You have successfully removed {username} from {podcastTitle}', diff --git a/modules/Admin/Language/id/Episode.php b/modules/Admin/Language/id/Episode.php index 4fa846e3..91313a7c 100644 --- a/modules/Admin/Language/id/Episode.php +++ b/modules/Admin/Language/id/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'All podcast episodes', 'back_to_podcast' => 'Go back to podcast', 'edit' => 'Edit', - 'preview' => 'Preview', 'publish' => 'Publish', 'publish_edit' => 'Edit publication', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episode', 'visibility' => 'Visibility', - 'downloads' => 'Downloads', 'comments' => 'Comments', 'actions' => 'Actions', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'Chapters', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/fa/MyAccount.php b/modules/Admin/Language/id/MyAccount.php similarity index 100% rename from modules/Auth/Language/fa/MyAccount.php rename to modules/Admin/Language/id/MyAccount.php diff --git a/modules/Admin/Language/id/Navigation.php b/modules/Admin/Language/id/Navigation.php index f3ffb129..68d4609d 100644 --- a/modules/Admin/Language/id/Navigation.php +++ b/modules/Admin/Language/id/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Dashboard', 'admin' => 'Home', 'podcasts' => 'Podcasts', 'podcast-list' => 'All podcasts', 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Import a podcast', 'persons' => 'Persons', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -35,7 +33,6 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Admin/Language/id/Platforms.php b/modules/Admin/Language/id/Platforms.php index e161181c..ab17d599 100644 --- a/modules/Admin/Language/id/Platforms.php +++ b/modules/Admin/Language/id/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Platforms', 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', 'remove' => 'Remove {platformName}', diff --git a/modules/Admin/Language/id/Podcast.php b/modules/Admin/Language/id/Podcast.php index ff0daebc..426b763b 100644 --- a/modules/Admin/Language/id/Podcast.php +++ b/modules/Admin/Language/id/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No podcast found!', 'create' => 'Create podcast', 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'New Episode', 'view' => 'View podcast', 'edit' => 'Edit podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Delete podcast', 'see_episodes' => 'See episodes', 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Go to page', 'latest_episodes' => 'Latest episodes', 'see_all_episodes' => 'See all episodes', @@ -50,6 +48,7 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], 'description' => 'Description', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/id/PodcastImport.php b/modules/Admin/Language/id/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/id/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/id/PodcastNavigation.php b/modules/Admin/Language/id/PodcastNavigation.php index bb777707..b4d7ddc0 100644 --- a/modules/Admin/Language/id/PodcastNavigation.php +++ b/modules/Admin/Language/id/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'Home', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodes', 'episode-list' => 'All episodes', 'episode-create' => 'New episode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/id/User.php b/modules/Admin/Language/id/User.php new file mode 100644 index 00000000..585d6799 --- /dev/null +++ b/modules/Admin/Language/id/User.php @@ -0,0 +1,56 @@ + "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', + 'delete' => 'Delete', + 'create' => 'New user', + 'view' => "{username}'s info", + 'all_users' => 'All users', + 'list' => [ + 'user' => 'User', + 'roles' => 'Roles', + 'banned' => 'Banned?', + ], + 'form' => [ + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', + 'new_password' => 'New Password', + 'roles' => 'Roles', + 'permissions' => 'Permissions', + 'submit_create' => 'Create user', + 'submit_edit' => 'Save', + 'submit_password_change' => 'Change!', + ], + 'roles' => [ + 'superadmin' => 'Super admin', + ], + 'messages' => [ + 'createSuccess' => + 'User created successfully! {username} will be prompted with a password reset upon first authentication.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', + 'editOwnerError' => + '{username} is the instance owner, you cannot edit its roles.', + 'banSuperAdminError' => + '{username} is a superadmin, one does not simply ban a superadmin…', + 'deleteSuperAdminError' => + '{username} is a superadmin, one does not simply delete a superadmin…', + 'deleteSuccess' => '{username} has been deleted.', + ], +]; diff --git a/modules/Admin/Language/id/Validation.php b/modules/Admin/Language/id/Validation.php index f76c3163..750b1968 100644 --- a/modules/Admin/Language/id/Validation.php +++ b/modules/Admin/Language/id/Validation.php @@ -13,5 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/it/AboutCastopod.php b/modules/Admin/Language/it/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/it/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/it/Breadcrumb.php b/modules/Admin/Language/it/Breadcrumb.php index 7c492350..9876ee9b 100644 --- a/modules/Admin/Language/it/Breadcrumb.php +++ b/modules/Admin/Language/it/Breadcrumb.php @@ -19,7 +19,6 @@ return [ 'pages' => 'pagine', 'settings' => 'impostazioni', 'theme' => 'tema', - 'about' => 'about', 'add' => 'aggiungi', 'new' => 'nuovo', 'edit' => 'modifica', @@ -29,19 +28,15 @@ return [ 'publish-date-edit' => 'edit publication date', 'unpublish' => 'annulla pubblicazione', 'delete' => 'elimina', - 'remove' => 'remove', 'fediverse' => 'fediverso', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'elenco bloccati', 'users' => 'utenti', 'my-account' => 'il mio profilo', 'change-password' => 'cambia la password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'importazione feed', 'platforms' => 'piattaforme', 'social' => 'social networks', 'funding' => 'finanziamento', - 'monetization-other' => 'other monetization', 'analytics' => 'analytics', 'locations' => 'posizioni', 'webpages' => 'pagine web', diff --git a/modules/Admin/Language/it/Charts.php b/modules/Admin/Language/it/Charts.php index 88455fc2..383d7bf8 100644 --- a/modules/Admin/Language/it/Charts.php +++ b/modules/Admin/Language/it/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/it/Common.php b/modules/Admin/Language/it/Common.php index 82ad7a8c..bff79dff 100644 --- a/modules/Admin/Language/it/Common.php +++ b/modules/Admin/Language/it/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Carica un file', 'remote_url' => 'URL remoto', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Riproduci', diff --git a/modules/Auth/Language/it/Contributor.php b/modules/Admin/Language/it/Contributor.php similarity index 72% rename from modules/Auth/Language/it/Contributor.php rename to modules/Admin/Language/it/Contributor.php index b82b51bb..ab685c04 100644 --- a/modules/Auth/Language/it/Contributor.php +++ b/modules/Admin/Language/it/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Aggiungi collaboratore', 'submit_edit' => 'Aggiorna Ruolo', ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', + 'roles' => [ + 'podcast_admin' => 'Amministratore del podcast', ], 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", 'removeOwnerError' => "Non puoi rimuovere il proprietario del podcast!", 'removeSuccess' => 'Hai rimosso con successo {username} da {podcastTitle}', diff --git a/modules/Admin/Language/it/Episode.php b/modules/Admin/Language/it/Episode.php index a583463a..6cb572a3 100644 --- a/modules/Admin/Language/it/Episode.php +++ b/modules/Admin/Language/it/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'Tutti gli episodi del podcast', 'back_to_podcast' => 'Torna a podcast', 'edit' => 'Modifica', - 'preview' => 'Preview', 'publish' => 'Pubblica', 'publish_edit' => 'Modifica pubblicazione', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episode', 'visibility' => 'Visibility', - 'downloads' => 'Downloads', 'comments' => 'Comments', 'actions' => 'Actions', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'Chapters', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/fr-ca/MyAccount.php b/modules/Admin/Language/it/MyAccount.php similarity index 100% rename from modules/Auth/Language/fr-ca/MyAccount.php rename to modules/Admin/Language/it/MyAccount.php diff --git a/modules/Admin/Language/it/Navigation.php b/modules/Admin/Language/it/Navigation.php index f3ffb129..68d4609d 100644 --- a/modules/Admin/Language/it/Navigation.php +++ b/modules/Admin/Language/it/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Dashboard', 'admin' => 'Home', 'podcasts' => 'Podcasts', 'podcast-list' => 'All podcasts', 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Import a podcast', 'persons' => 'Persons', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -35,7 +33,6 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Admin/Language/it/Platforms.php b/modules/Admin/Language/it/Platforms.php index e161181c..ab17d599 100644 --- a/modules/Admin/Language/it/Platforms.php +++ b/modules/Admin/Language/it/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Platforms', 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', 'remove' => 'Remove {platformName}', diff --git a/modules/Admin/Language/it/Podcast.php b/modules/Admin/Language/it/Podcast.php index ff0daebc..426b763b 100644 --- a/modules/Admin/Language/it/Podcast.php +++ b/modules/Admin/Language/it/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No podcast found!', 'create' => 'Create podcast', 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'New Episode', 'view' => 'View podcast', 'edit' => 'Edit podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Delete podcast', 'see_episodes' => 'See episodes', 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Go to page', 'latest_episodes' => 'Latest episodes', 'see_all_episodes' => 'See all episodes', @@ -50,6 +48,7 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], 'description' => 'Description', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/it/PodcastImport.php b/modules/Admin/Language/it/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/it/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/it/PodcastNavigation.php b/modules/Admin/Language/it/PodcastNavigation.php index bb777707..b4d7ddc0 100644 --- a/modules/Admin/Language/it/PodcastNavigation.php +++ b/modules/Admin/Language/it/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'Home', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodes', 'episode-list' => 'All episodes', 'episode-create' => 'New episode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/it/User.php b/modules/Admin/Language/it/User.php new file mode 100644 index 00000000..585d6799 --- /dev/null +++ b/modules/Admin/Language/it/User.php @@ -0,0 +1,56 @@ + "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', + 'delete' => 'Delete', + 'create' => 'New user', + 'view' => "{username}'s info", + 'all_users' => 'All users', + 'list' => [ + 'user' => 'User', + 'roles' => 'Roles', + 'banned' => 'Banned?', + ], + 'form' => [ + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', + 'new_password' => 'New Password', + 'roles' => 'Roles', + 'permissions' => 'Permissions', + 'submit_create' => 'Create user', + 'submit_edit' => 'Save', + 'submit_password_change' => 'Change!', + ], + 'roles' => [ + 'superadmin' => 'Super admin', + ], + 'messages' => [ + 'createSuccess' => + 'User created successfully! {username} will be prompted with a password reset upon first authentication.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', + 'editOwnerError' => + '{username} is the instance owner, you cannot edit its roles.', + 'banSuperAdminError' => + '{username} is a superadmin, one does not simply ban a superadmin…', + 'deleteSuperAdminError' => + '{username} is a superadmin, one does not simply delete a superadmin…', + 'deleteSuccess' => '{username} has been deleted.', + ], +]; diff --git a/modules/Admin/Language/it/Validation.php b/modules/Admin/Language/it/Validation.php index f76c3163..750b1968 100644 --- a/modules/Admin/Language/it/Validation.php +++ b/modules/Admin/Language/it/Validation.php @@ -13,5 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/ja/AboutCastopod.php b/modules/Admin/Language/ja/AboutCastopod.php deleted file mode 100644 index 16c3c2b2..00000000 --- a/modules/Admin/Language/ja/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Castopodについて', - 'host_name' => 'ホスト名', - 'version' => 'Castopodバージョン', - 'php_version' => 'PHPバージョン', - 'os' => '(OS) オペレーティング システム', - 'languages' => '言語', - 'update_database' => 'データベースを更新', - 'messages' => [ - 'databaseUpdateSuccess' => 'データベースは最新です', - ], -]; diff --git a/modules/Admin/Language/ja/Breadcrumb.php b/modules/Admin/Language/ja/Breadcrumb.php deleted file mode 100644 index 408c9f9f..00000000 --- a/modules/Admin/Language/ja/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb', - config('Admin') - ->gateway => 'Home', - 'podcasts' => 'podcasts', - 'episodes' => 'episodes', - 'subscriptions' => 'subscriptions', - 'contributors' => 'contributors', - 'pages' => 'pages', - 'settings' => 'settings', - 'theme' => 'theme', - 'about' => 'about', - 'add' => 'add', - 'new' => 'new', - 'edit' => 'edit', - 'persons' => 'persons', - 'publish' => 'publish', - 'publish-edit' => 'edit publication', - 'publish-date-edit' => 'edit publication date', - 'unpublish' => 'unpublish', - 'delete' => 'delete', - 'remove' => 'remove', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'users', - 'my-account' => 'my account', - 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforms', - 'social' => 'social networks', - 'funding' => 'funding', - 'monetization-other' => 'other monetization', - 'analytics' => 'analytics', - 'locations' => 'locations', - 'webpages' => 'web pages', - 'unique-listeners' => 'unique listeners', - 'players' => 'players', - 'listening-time' => 'listening time', - 'time-periods' => 'time periods', - 'soundbites' => 'soundbites', - 'video-clips' => 'video clips', - 'embed' => 'embeddable player', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/ja/Charts.php b/modules/Admin/Language/ja/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/ja/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/ja/Common.php b/modules/Admin/Language/ja/Common.php deleted file mode 100644 index 74addcf2..00000000 --- a/modules/Admin/Language/ja/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Loading…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/ja/Countries.php b/modules/Admin/Language/ja/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/ja/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/ja/Dashboard.php b/modules/Admin/Language/ja/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/ja/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/ja/Episode.php b/modules/Admin/Language/ja/Episode.php deleted file mode 100644 index 4fa846e3..00000000 --- a/modules/Admin/Language/ja/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episode is already published.', - 'publish_cancel_error' => 'Episode is already published.', - 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', - 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', - 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', - 'unpublish_error' => 'Episode is not published.', - 'delete' => 'Delete', - 'go_to_page' => 'Go to page', - 'create' => 'Add an episode', - 'publication_status' => [ - 'published' => 'Published', - 'with_podcast' => 'Published', - 'scheduled' => 'Scheduled', - 'not_published' => 'Not published', - ], - 'with_podcast_hint' => 'To be published at the same time as the podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Search for an episode', - 'clear' => 'Clear search', - 'submit' => 'Search', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episodes} - }', - 'episode' => 'Episode', - 'visibility' => 'Visibility', - 'downloads' => 'Downloads', - 'comments' => 'Comments', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'Episode has been successfully created!', - 'editSuccess' => 'Episode has been successfully updated!', - 'publishSuccess' => '{publication_status, select, - published {Episode successfully published!} - scheduled {Episode publication successfully scheduled!} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not published.} - }', - 'publishCancelSuccess' => 'Episode publication successfully cancelled!', - 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', - 'scheduleDateError' => 'Schedule date must be set!', - 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', - 'deleteSuccess' => 'Episode successfully deleted!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/ja/EpisodeNavigation.php b/modules/Admin/Language/ja/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/ja/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/ja/Fediverse.php b/modules/Admin/Language/ja/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/ja/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/ja/Home.php b/modules/Admin/Language/ja/Home.php deleted file mode 100644 index 3ff4c04d..00000000 --- a/modules/Admin/Language/ja/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found', -]; diff --git a/modules/Admin/Language/ja/Install.php b/modules/Admin/Language/ja/Install.php deleted file mode 100644 index 36e373a2..00000000 --- a/modules/Admin/Language/ja/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/ja/Navigation.php b/modules/Admin/Language/ja/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/ja/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/ja/Notifications.php b/modules/Admin/Language/ja/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/ja/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/ja/Page.php b/modules/Admin/Language/ja/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/ja/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/ja/Pager.php b/modules/Admin/Language/ja/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/ja/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/ja/Person.php b/modules/Admin/Language/ja/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/ja/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/ja/Platforms.php b/modules/Admin/Language/ja/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/ja/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/ja/Podcast.php b/modules/Admin/Language/ja/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/ja/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/ja/PodcastNavigation.php b/modules/Admin/Language/ja/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/ja/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/ja/Settings.php b/modules/Admin/Language/ja/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/ja/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/ja/Soundbite.php b/modules/Admin/Language/ja/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/ja/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/ja/Validation.php b/modules/Admin/Language/ja/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/ja/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/ja/VideoClip.php b/modules/Admin/Language/ja/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/ja/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/kk/AboutCastopod.php b/modules/Admin/Language/kk/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/kk/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/kk/Breadcrumb.php b/modules/Admin/Language/kk/Breadcrumb.php deleted file mode 100644 index 408c9f9f..00000000 --- a/modules/Admin/Language/kk/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb', - config('Admin') - ->gateway => 'Home', - 'podcasts' => 'podcasts', - 'episodes' => 'episodes', - 'subscriptions' => 'subscriptions', - 'contributors' => 'contributors', - 'pages' => 'pages', - 'settings' => 'settings', - 'theme' => 'theme', - 'about' => 'about', - 'add' => 'add', - 'new' => 'new', - 'edit' => 'edit', - 'persons' => 'persons', - 'publish' => 'publish', - 'publish-edit' => 'edit publication', - 'publish-date-edit' => 'edit publication date', - 'unpublish' => 'unpublish', - 'delete' => 'delete', - 'remove' => 'remove', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'users', - 'my-account' => 'my account', - 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforms', - 'social' => 'social networks', - 'funding' => 'funding', - 'monetization-other' => 'other monetization', - 'analytics' => 'analytics', - 'locations' => 'locations', - 'webpages' => 'web pages', - 'unique-listeners' => 'unique listeners', - 'players' => 'players', - 'listening-time' => 'listening time', - 'time-periods' => 'time periods', - 'soundbites' => 'soundbites', - 'video-clips' => 'video clips', - 'embed' => 'embeddable player', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/kk/Charts.php b/modules/Admin/Language/kk/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/kk/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/kk/Common.php b/modules/Admin/Language/kk/Common.php deleted file mode 100644 index 74addcf2..00000000 --- a/modules/Admin/Language/kk/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Loading…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/kk/Countries.php b/modules/Admin/Language/kk/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/kk/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/kk/Dashboard.php b/modules/Admin/Language/kk/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/kk/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/kk/Episode.php b/modules/Admin/Language/kk/Episode.php deleted file mode 100644 index 4fa846e3..00000000 --- a/modules/Admin/Language/kk/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episode is already published.', - 'publish_cancel_error' => 'Episode is already published.', - 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', - 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', - 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', - 'unpublish_error' => 'Episode is not published.', - 'delete' => 'Delete', - 'go_to_page' => 'Go to page', - 'create' => 'Add an episode', - 'publication_status' => [ - 'published' => 'Published', - 'with_podcast' => 'Published', - 'scheduled' => 'Scheduled', - 'not_published' => 'Not published', - ], - 'with_podcast_hint' => 'To be published at the same time as the podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Search for an episode', - 'clear' => 'Clear search', - 'submit' => 'Search', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episodes} - }', - 'episode' => 'Episode', - 'visibility' => 'Visibility', - 'downloads' => 'Downloads', - 'comments' => 'Comments', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'Episode has been successfully created!', - 'editSuccess' => 'Episode has been successfully updated!', - 'publishSuccess' => '{publication_status, select, - published {Episode successfully published!} - scheduled {Episode publication successfully scheduled!} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not published.} - }', - 'publishCancelSuccess' => 'Episode publication successfully cancelled!', - 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', - 'scheduleDateError' => 'Schedule date must be set!', - 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', - 'deleteSuccess' => 'Episode successfully deleted!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/kk/EpisodeNavigation.php b/modules/Admin/Language/kk/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/kk/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/kk/Fediverse.php b/modules/Admin/Language/kk/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/kk/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/kk/Home.php b/modules/Admin/Language/kk/Home.php deleted file mode 100644 index 3ff4c04d..00000000 --- a/modules/Admin/Language/kk/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found', -]; diff --git a/modules/Admin/Language/kk/Install.php b/modules/Admin/Language/kk/Install.php deleted file mode 100644 index 36e373a2..00000000 --- a/modules/Admin/Language/kk/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/kk/Navigation.php b/modules/Admin/Language/kk/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/kk/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/kk/Notifications.php b/modules/Admin/Language/kk/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/kk/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/kk/Page.php b/modules/Admin/Language/kk/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/kk/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/kk/Pager.php b/modules/Admin/Language/kk/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/kk/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/kk/Person.php b/modules/Admin/Language/kk/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/kk/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/kk/Platforms.php b/modules/Admin/Language/kk/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/kk/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/kk/Podcast.php b/modules/Admin/Language/kk/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/kk/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/kk/PodcastNavigation.php b/modules/Admin/Language/kk/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/kk/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/kk/Settings.php b/modules/Admin/Language/kk/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/kk/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/kk/Soundbite.php b/modules/Admin/Language/kk/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/kk/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/kk/Validation.php b/modules/Admin/Language/kk/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/kk/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/kk/VideoClip.php b/modules/Admin/Language/kk/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/kk/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/ko/AboutCastopod.php b/modules/Admin/Language/ko/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/ko/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/ko/Breadcrumb.php b/modules/Admin/Language/ko/Breadcrumb.php deleted file mode 100644 index 408c9f9f..00000000 --- a/modules/Admin/Language/ko/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb', - config('Admin') - ->gateway => 'Home', - 'podcasts' => 'podcasts', - 'episodes' => 'episodes', - 'subscriptions' => 'subscriptions', - 'contributors' => 'contributors', - 'pages' => 'pages', - 'settings' => 'settings', - 'theme' => 'theme', - 'about' => 'about', - 'add' => 'add', - 'new' => 'new', - 'edit' => 'edit', - 'persons' => 'persons', - 'publish' => 'publish', - 'publish-edit' => 'edit publication', - 'publish-date-edit' => 'edit publication date', - 'unpublish' => 'unpublish', - 'delete' => 'delete', - 'remove' => 'remove', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'users', - 'my-account' => 'my account', - 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforms', - 'social' => 'social networks', - 'funding' => 'funding', - 'monetization-other' => 'other monetization', - 'analytics' => 'analytics', - 'locations' => 'locations', - 'webpages' => 'web pages', - 'unique-listeners' => 'unique listeners', - 'players' => 'players', - 'listening-time' => 'listening time', - 'time-periods' => 'time periods', - 'soundbites' => 'soundbites', - 'video-clips' => 'video clips', - 'embed' => 'embeddable player', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/ko/Charts.php b/modules/Admin/Language/ko/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/ko/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/ko/Common.php b/modules/Admin/Language/ko/Common.php deleted file mode 100644 index 74addcf2..00000000 --- a/modules/Admin/Language/ko/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Loading…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/ko/Countries.php b/modules/Admin/Language/ko/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/ko/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/ko/Dashboard.php b/modules/Admin/Language/ko/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/ko/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/ko/Episode.php b/modules/Admin/Language/ko/Episode.php deleted file mode 100644 index 4fa846e3..00000000 --- a/modules/Admin/Language/ko/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episode is already published.', - 'publish_cancel_error' => 'Episode is already published.', - 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', - 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', - 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', - 'unpublish_error' => 'Episode is not published.', - 'delete' => 'Delete', - 'go_to_page' => 'Go to page', - 'create' => 'Add an episode', - 'publication_status' => [ - 'published' => 'Published', - 'with_podcast' => 'Published', - 'scheduled' => 'Scheduled', - 'not_published' => 'Not published', - ], - 'with_podcast_hint' => 'To be published at the same time as the podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Search for an episode', - 'clear' => 'Clear search', - 'submit' => 'Search', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episodes} - }', - 'episode' => 'Episode', - 'visibility' => 'Visibility', - 'downloads' => 'Downloads', - 'comments' => 'Comments', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'Episode has been successfully created!', - 'editSuccess' => 'Episode has been successfully updated!', - 'publishSuccess' => '{publication_status, select, - published {Episode successfully published!} - scheduled {Episode publication successfully scheduled!} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not published.} - }', - 'publishCancelSuccess' => 'Episode publication successfully cancelled!', - 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', - 'scheduleDateError' => 'Schedule date must be set!', - 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', - 'deleteSuccess' => 'Episode successfully deleted!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/ko/EpisodeNavigation.php b/modules/Admin/Language/ko/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/ko/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/ko/Fediverse.php b/modules/Admin/Language/ko/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/ko/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/ko/Home.php b/modules/Admin/Language/ko/Home.php deleted file mode 100644 index 3ff4c04d..00000000 --- a/modules/Admin/Language/ko/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found', -]; diff --git a/modules/Admin/Language/ko/Install.php b/modules/Admin/Language/ko/Install.php deleted file mode 100644 index 36e373a2..00000000 --- a/modules/Admin/Language/ko/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/ko/Navigation.php b/modules/Admin/Language/ko/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/ko/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/ko/Notifications.php b/modules/Admin/Language/ko/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/ko/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/ko/Page.php b/modules/Admin/Language/ko/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/ko/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/ko/Pager.php b/modules/Admin/Language/ko/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/ko/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/ko/Person.php b/modules/Admin/Language/ko/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/ko/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/ko/Platforms.php b/modules/Admin/Language/ko/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/ko/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/ko/Podcast.php b/modules/Admin/Language/ko/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/ko/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/ko/PodcastNavigation.php b/modules/Admin/Language/ko/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/ko/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/ko/Settings.php b/modules/Admin/Language/ko/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/ko/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/ko/Soundbite.php b/modules/Admin/Language/ko/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/ko/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/ko/Validation.php b/modules/Admin/Language/ko/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/ko/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/ko/VideoClip.php b/modules/Admin/Language/ko/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/ko/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/nl/AboutCastopod.php b/modules/Admin/Language/nl/AboutCastopod.php deleted file mode 100644 index efefa11f..00000000 --- a/modules/Admin/Language/nl/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Over Castopod', - 'host_name' => 'Servernaam', - 'version' => 'Castopod versie', - 'php_version' => 'PHP versie', - 'os' => 'Besturingssystem', - 'languages' => 'Talen', - 'update_database' => 'Database bijwerken', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up-to-date!', - ], -]; diff --git a/modules/Admin/Language/nl/Breadcrumb.php b/modules/Admin/Language/nl/Breadcrumb.php index 2d120967..a5c08f43 100644 --- a/modules/Admin/Language/nl/Breadcrumb.php +++ b/modules/Admin/Language/nl/Breadcrumb.php @@ -14,44 +14,39 @@ return [ ->gateway => 'Hoofdpagina', 'podcasts' => 'podcasts', 'episodes' => 'afleveringen', - 'subscriptions' => 'abonnementen', + 'subscriptions' => 'subscriptions', 'contributors' => 'bijdragers', 'pages' => 'paginas', 'settings' => 'instellingen', 'theme' => 'thema', - 'about' => 'over', 'add' => 'toevoegen', 'new' => 'nieuw', 'edit' => 'bewerken', 'persons' => 'personen', 'publish' => 'publiceren', 'publish-edit' => 'publicatie aanpassen', - 'publish-date-edit' => 'publicatiedatum bewerken', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'publicatie ongedaan maken', 'delete' => 'verwijder', - 'remove' => 'verwijder', 'fediverse' => 'fediverse', - 'blocked-actors' => 'geblokkeerde actoren', - 'blocked-domains' => 'geblokkeerde domeinen', + 'block-lists' => 'blokkeerlijst', 'users' => 'gebruikers', 'my-account' => 'mijn account', 'change-password' => 'wachtwoord wijzigen', - 'imports' => 'imports', - 'sync-feeds' => 'feeds synchroniseren', - 'platforms' => 'platformen', + 'import' => 'feed importeren', + 'platforms' => 'platforms', 'social' => 'sociale netwerken', 'funding' => 'financiering', - 'monetization-other' => 'andere inkomsten', 'analytics' => 'statistieken', 'locations' => 'locaties', - 'webpages' => 'webpagina\'s', + 'webpages' => 'web pagina\'s', 'unique-listeners' => 'unieke luisteraars', 'players' => 'spelers', 'listening-time' => 'afspeeltijd', - 'time-periods' => 'tijdspanne', - 'soundbites' => 'geluidsfragment', - 'video-clips' => 'videoclips', - 'embed' => 'embedbare speler', + 'time-periods' => 'tijds blok', + 'soundbites' => 'geluidsbeet', + 'video-clips' => 'video clips', + 'embed' => 'integreerbare speler', 'notifications' => 'meldingen', - 'suspend' => 'opschorten', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/nl/Charts.php b/modules/Admin/Language/nl/Charts.php index 213e94ab..6f2b1ea5 100644 --- a/modules/Admin/Language/nl/Charts.php +++ b/modules/Admin/Language/nl/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Dagelijks gebruikte bandbreedte (in MB)', 'total_storage_by_month' => 'Maandelijkse opslagruimte (in MB)', 'total_bandwidth_by_month' => 'Maandelijkse gebruikte bandbreedte (in MB)', - 'total_bandwidth_by_month_limit' => 'Gelimiteerd tot {totalBandwidth} per maand', ]; diff --git a/modules/Admin/Language/nl/Common.php b/modules/Admin/Language/nl/Common.php index 65bbbdfe..a6194f73 100644 --- a/modules/Admin/Language/nl/Common.php +++ b/modules/Admin/Language/nl/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Bestand uploaden', 'remote_url' => 'Externe URL', - 'save' => 'Opslaan', ], 'play_episode_button' => [ 'play' => 'Afspelen', diff --git a/modules/Auth/Language/nl/Contributor.php b/modules/Admin/Language/nl/Contributor.php similarity index 70% rename from modules/Auth/Language/nl/Contributor.php rename to modules/Admin/Language/nl/Contributor.php index f6b11364..a9d938d6 100644 --- a/modules/Auth/Language/nl/Contributor.php +++ b/modules/Admin/Language/nl/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Voeg bijdrager toe', 'submit_edit' => 'Rol bijwerken', ], - 'delete_form' => [ - 'title' => 'Verwijder {contributor}', - 'disclaimer' => - 'Je staat op het punt {contributor} te verwijderen van bijdragers. Ze zullen geen toegang meer hebben tot "{podcastTitle}".', - 'understand' => 'Ik begrijp het, ik wil {contributor} verwijderen van "{podcastTitle}"', - 'submit' => 'Verwijder', + 'roles' => [ + 'podcast_admin' => 'Podcast beheerder', ], 'messages' => [ - 'editSuccess' => 'Rol succesvol veranderd!', - 'editOwnerError' => "Je kunt de eigenaar van podcast niet bewerken!", 'removeOwnerError' => "Je kunt de eigenaar van podcast niet verwijderen!", 'removeSuccess' => 'Je hebt {username} met succes verwijderd van {podcastTitle}', diff --git a/modules/Admin/Language/nl/Countries.php b/modules/Admin/Language/nl/Countries.php index 82cb1990..7652b137 100644 --- a/modules/Admin/Language/nl/Countries.php +++ b/modules/Admin/Language/nl/Countries.php @@ -94,171 +94,171 @@ return [ 'GG' => 'Guernsey', 'GH' => 'Ghana', 'GI' => 'Gibraltar', - 'GL' => 'Groenland', + 'GL' => 'Greenland', 'GM' => 'Gambia', - 'GN' => 'Guinee', + 'GN' => 'Guinea', 'GP' => 'Guadeloupe', - 'GQ' => 'Equatoriaal-Guinea', - 'GR' => 'Griekenland', - 'GS' => 'Zuid-Georgia en de Zuidelijke Sandwicheilanden', + 'GQ' => 'Equatorial Guinea', + 'GR' => 'Greece', + 'GS' => 'South Georgia and the South Sandwich Islands', 'GT' => 'Guatemala', 'GU' => 'Guam', - 'GW' => 'Guinee-Bissau', + 'GW' => 'Guinea-Bissau', 'GY' => 'Guyana', 'HK' => 'Hong Kong', - 'HM' => 'Heard- en MacDonaldeilanden', + 'HM' => 'Heard Island and McDonald Islands', 'HN' => 'Honduras', - 'HR' => 'Kroatië', - 'HT' => 'Haïti', - 'HU' => 'Hongarije', - 'ID' => 'Indonesië', - 'IE' => 'Ierland', - 'IL' => 'Israël', + 'HR' => 'Croatia', + 'HT' => 'Haiti', + 'HU' => 'Hungary', + 'ID' => 'Indonesia', + 'IE' => 'Ireland', + 'IL' => 'Israel', 'IM' => 'Isle of Man', 'IN' => 'India', - 'IO' => 'Britse Gebieden in de Indische Oceaan', - 'IQ' => 'Irak', - 'IR' => 'Iran, Islamitische Republiek', - 'IS' => 'Ijsland', - 'IT' => 'Italië', + 'IO' => 'British Indian Ocean Territory', + 'IQ' => 'Iraq', + 'IR' => 'Iran, Islamic Republic of', + 'IS' => 'Iceland', + 'IT' => 'Italy', 'JE' => 'Jersey', 'JM' => 'Jamaica', - 'JO' => 'Jordanië', + 'JO' => 'Jordan', 'JP' => 'Japan', - 'KE' => 'Kenia', - 'KG' => 'Kirgizië', - 'KH' => 'Cambodja', + 'KE' => 'Kenya', + 'KG' => 'Kyrgyzstan', + 'KH' => 'Cambodia', 'KI' => 'Kiribati', - 'KM' => 'Comoren', - 'KN' => 'Saint Kitts en Nevis', - 'KP' => "Korea, Democratische Volksrepubliek", - 'KR' => 'Zuid-Korea', - 'KW' => 'Koeweit', - 'KY' => 'Kaaimaneilanden', - 'KZ' => 'Kazachstan', - 'LA' => "Lao Democratische Volksrepubliek", + 'KM' => 'Comoros', + 'KN' => 'Saint Kitts and Nevis', + 'KP' => "Korea, Democratic People's Republic of", + 'KR' => 'Korea, Republic of', + 'KW' => 'Kuwait', + 'KY' => 'Cayman Islands', + 'KZ' => 'Kazakhstan', + 'LA' => "Lao People's Democratic Republic", 'LB' => 'Lebanon', - 'LC' => 'Sint Lucia', + 'LC' => 'Saint Lucia', 'LI' => 'Liechtenstein', 'LK' => 'Sri Lanka', 'LR' => 'Liberia', 'LS' => 'Lesotho', - 'LT' => 'Litauen', - 'LU' => 'Luxemburg', - 'LV' => 'Letland', - 'LY' => 'Libië', - 'MA' => 'Marokko', + 'LT' => 'Lithuania', + 'LU' => 'Luxembourg', + 'LV' => 'Latvia', + 'LY' => 'Libya', + 'MA' => 'Morocco', 'MC' => 'Monaco', - 'MD' => 'Moldavië, Republiek', + 'MD' => 'Moldova, Republic of', 'ME' => 'Montenegro', - 'MF' => 'Sint Maarten (Frans deel)', - 'MG' => 'Madagaskar', - 'MH' => 'Marshalleilanden', - 'MK' => 'Macedonië', + 'MF' => 'Saint Martin (French part)', + 'MG' => 'Madagascar', + 'MH' => 'Marshall Islands', + 'MK' => 'Macedonia, the Former Yugoslav Republic of', 'ML' => 'Mali', 'MM' => 'Myanmar', - 'MN' => 'Mongolië', - 'MO' => 'Macau', - 'MP' => 'Noordelijke Mariana eilanden', + 'MN' => 'Mongolia', + 'MO' => 'Macao', + 'MP' => 'Northern Mariana Islands', 'MQ' => 'Martinique', - 'MR' => 'Mauritanië', + 'MR' => 'Mauritania', 'MS' => 'Montserrat', 'MT' => 'Malta', 'MU' => 'Mauritius', - 'MV' => 'Maldiven', + 'MV' => 'Maldives', 'MW' => 'Malawi', 'MX' => 'Mexico', - 'MY' => 'Maleisië', + 'MY' => 'Malaysia', 'MZ' => 'Mozambique', - 'N/A' => 'Niet van toepassing (lokale IP…)', - 'NA' => 'Namibië', - 'NC' => 'Nieuw-Caledonië', + 'N/A' => 'Not Applicable (local IP…)', + 'NA' => 'Namibia', + 'NC' => 'New Caledonia', 'NE' => 'Niger', - 'NF' => 'Norfolk Eiland', + 'NF' => 'Norfolk Island', 'NG' => 'Nigeria', 'NI' => 'Nicaragua', - 'NL' => 'Nederland', - 'NO' => 'Noorwegen', + 'NL' => 'Netherlands', + 'NO' => 'Norway', 'NP' => 'Nepal', 'NR' => 'Nauru', 'NU' => 'Niue', - 'NZ' => 'Nieuw-Zeeland', + 'NZ' => 'New Zealand', 'OM' => 'Oman', 'PA' => 'Panama', 'PE' => 'Peru', - 'PF' => 'Frans-Polynesië', - 'PG' => 'Papua Nieuw-Guinea', - 'PH' => 'Filipijnen', + 'PF' => 'French Polynesia', + 'PG' => 'Papua New Guinea', + 'PH' => 'Philippines', 'PK' => 'Pakistan', - 'PL' => 'Polen', - 'PM' => 'Saint-Pierre en Miquelon', + 'PL' => 'Poland', + 'PM' => 'Saint Pierre and Miquelon', 'PN' => 'Pitcairn', 'PR' => 'Puerto Rico', - 'PS' => 'Palestina', + 'PS' => 'Palestine, State of', 'PT' => 'Portugal', 'PW' => 'Palau', 'PY' => 'Paraguay', 'QA' => 'Qatar', 'RE' => 'Réunion', - 'RO' => 'Roemenië', - 'RS' => 'Servië', - 'RU' => 'Russische Federatie', + 'RO' => 'Romania', + 'RS' => 'Serbia', + 'RU' => 'Russian Federation', 'RW' => 'Rwanda', - 'SA' => 'Saudi-Arabië', - 'SB' => 'Solomon-eilanden', - 'SC' => 'Seychellen', - 'SD' => 'Soedan', - 'SE' => 'Zweden', + 'SA' => 'Saudi Arabia', + 'SB' => 'Solomon Islands', + 'SC' => 'Seychelles', + 'SD' => 'Sudan', + 'SE' => 'Sweden', 'SG' => 'Singapore', - 'SH' => 'Sint-Helena, Ascension en Tristan da Cunha', - 'SI' => 'Slovenië', - 'SJ' => 'Spitsbergen en Jan Mayen', - 'SK' => 'Slowakije', - 'SL' => 'Siërra Leone', + 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', + 'SI' => 'Slovenia', + 'SJ' => 'Svalbard and Jan Mayen', + 'SK' => 'Slovakia', + 'SL' => 'Sierra Leone', 'SM' => 'San Marino', 'SN' => 'Senegal', - 'SO' => 'Somalië', + 'SO' => 'Somalia', 'SR' => 'Suriname', - 'SS' => 'Zuid-Soedan', - 'ST' => 'Sao Tomé en Principe', + 'SS' => 'South Sudan', + 'ST' => 'Sao Tome and Principe', 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Nederlands deel)', - 'SY' => 'Syrië, Arabische Republiek', + 'SX' => 'Sint Maarten (Dutch part)', + 'SY' => 'Syrian Arab Republic', 'SZ' => 'Swaziland', - 'TC' => 'Turks- en Caicos-eilanden', - 'TD' => 'Tsjaad', - 'TF' => 'Franse Gebieden in de zuidelijke Indische Oceaan', + 'TC' => 'Turks and Caicos Islands', + 'TD' => 'Chad', + 'TF' => 'French Southern Territories', 'TG' => 'Togo', 'TH' => 'Thailand', - 'TJ' => 'Tadzjikistan', + 'TJ' => 'Tajikistan', 'TK' => 'Tokelau', - 'TL' => 'Oost-Timor', + 'TL' => 'Timor-Leste', 'TM' => 'Turkmenistan', - 'TN' => 'Tunesië', + 'TN' => 'Tunisia', 'TO' => 'Tonga', - 'TR' => 'Turkije', - 'TT' => 'Trinidad en Tobago', + 'TR' => 'Turkey', + 'TT' => 'Trinidad and Tobago', 'TV' => 'Tuvalu', - 'TW' => 'Taiwan', - 'TZ' => 'Tanzania', - 'UA' => 'Oekraïne', - 'UG' => 'Oeganda', - 'UM' => 'Kleine afgelegen eilanden van de Verenigde Staten', - 'US' => 'Verenigde Staten', + 'TW' => 'Taiwan, Province of China', + 'TZ' => 'Tanzania, United Republic of', + 'UA' => 'Ukraine', + 'UG' => 'Uganda', + 'UM' => 'United States Minor Outlying Islands', + 'US' => 'United States', 'UY' => 'Uruguay', - 'UZ' => 'Oezbekistan', - 'VA' => 'Holy See (Vaticaanstad)', - 'VC' => 'Sint Vincent en de Grenadines', - 'VE' => 'Venezuela, Bolivariaanse Republiek', - 'VG' => 'Britse Maagdeneilanden', - 'VI' => 'Maagdeneilanden, Amerikaanse', - 'VN' => 'Vietnam', + 'UZ' => 'Uzbekistan', + 'VA' => 'Holy See (Vatican City State)', + 'VC' => 'Saint Vincent and the Grenadines', + 'VE' => 'Venezuela, Bolivarian Republic of', + 'VG' => 'Virgin Islands, British', + 'VI' => 'Virgin Islands, U.S.', + 'VN' => 'Viet Nam', 'VU' => 'Vanuatu', - 'WF' => 'Wallis en Futuna', + 'WF' => 'Wallis and Futuna', 'WS' => 'Samoa', - 'YE' => 'Jemen', + 'YE' => 'Yemen', 'YT' => 'Mayotte', - 'ZA' => 'Zuid-Afrika', + 'ZA' => 'South Africa', 'ZM' => 'Zambia', 'ZW' => 'Zimbabwe', ]; diff --git a/modules/Admin/Language/nl/Dashboard.php b/modules/Admin/Language/nl/Dashboard.php index 15c43acb..881073fd 100644 --- a/modules/Admin/Language/nl/Dashboard.php +++ b/modules/Admin/Language/nl/Dashboard.php @@ -9,20 +9,20 @@ declare(strict_types=1); */ return [ - 'home' => 'Beheerdersdashboard', - 'welcome_message' => 'Welkom bij de beheeromgeving!', + 'home' => 'Admin dashboard', + 'welcome_message' => 'Welcome to the admin area!', 'podcasts' => [ 'title' => 'Podcasts', - 'not_found' => 'Geen gepubliceerde podcast', - 'last_published' => 'Laatst gepubliceerd op {lastPublicationDate}', + 'not_found' => 'No published podcast', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'episodes' => [ - 'title' => 'Afleveringen', - 'not_found' => 'Geen gepubliceerde aflevering', - 'last_published' => 'Laatst gepubliceerd op {lastPublicationDate}', + 'title' => 'Episodes', + 'not_found' => 'No published episode', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'storage' => [ - 'title' => 'Opslagruimte', - 'subtitle' => '{totalUploaded} van {totalStorage}', + 'title' => 'Storage', + 'subtitle' => '{totalUploaded} out of {totalStorage}', ], ]; diff --git a/modules/Admin/Language/nl/Episode.php b/modules/Admin/Language/nl/Episode.php index 70a11518..60845744 100644 --- a/modules/Admin/Language/nl/Episode.php +++ b/modules/Admin/Language/nl/Episode.php @@ -22,41 +22,39 @@ return [ 'all_podcast_episodes' => 'Alle podcast afleveringen', 'back_to_podcast' => 'Terug naar podcast', 'edit' => 'Bewerken', - 'preview' => 'Voorbeeld', 'publish' => 'Publiceren', 'publish_edit' => 'Publicatie bewerken', - 'publish_date_edit' => 'Publicatiedatum bewerken', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Publicatie ongedaan maken', 'publish_error' => 'Aflevering is reeds gepubliceerd.', 'publish_edit_error' => 'Aflevering is reeds gepubliceerd.', 'publish_cancel_error' => 'Aflevering is reeds gepubliceerd.', - 'publish_date_edit_error' => 'Aflevering is nog niet gepubliceerd, u kunt de publicatiedatum niet bewerken.', - 'publish_date_edit_future_error' => 'Aflevering publicatiedatum kan alleen worden ingesteld op een datum in het verleden! Als u het opnieuw wilt inplannen, verwijder dan de publicatie eerst.', - 'publish_date_edit_success' => 'De publicatiedatum van aflevering is met succes bijgewerkt!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'Aflevering is niet gepubliceerd.', 'delete' => 'Verwijder', 'go_to_page' => 'Ga naar pagina', 'create' => 'Aflevering toevoegen', 'publication_status' => [ 'published' => 'Gepubliceerd', - 'with_podcast' => 'Gepubliceerd', + 'with_podcast' => 'Published', 'scheduled' => 'Gepland', 'not_published' => 'Niet gepubliceerd', ], - 'with_podcast_hint' => 'Nog te publiceren op hetzelfde moment als de podcast', + 'with_podcast_hint' => 'To be published at the same time as the podcast', 'list' => [ 'search' => [ - 'placeholder' => 'Zoek naar een aflevering', - 'clear' => 'Wis zoekopdracht', - 'submit' => 'Zoeken', + 'placeholder' => 'Search for an episode', + 'clear' => 'Clear search', + 'submit' => 'Search', ], 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# aflevering} - other {# afleveringen} + one {# episode} + other {# episodes} }', 'episode' => 'Aflevering', 'visibility' => 'Zichtbaarheid', - 'downloads' => 'Downloads', 'comments' => 'Reacties', 'actions' => 'Acties', ], @@ -64,31 +62,31 @@ return [ 'createSuccess' => 'Aflevering is succesvol aangemaakt!', 'editSuccess' => 'Aflevering is succesvol bijgewerkt!', 'publishSuccess' => '{publication_status, select, - published {Deze aflevering is nog niet gepubliceerd!} - scheduled {Deze aflevering is successvol gepland!} - with_podcast {Deze aflevering zal op hetzelfde moment als de podcast worden gepubliceerd.} - other {Deze aflevering is nog niet gepubliceerd.} + published {Episode successfully published!} + scheduled {Episode publication successfully scheduled!} + with_podcast {This episode will be published at the same time as the podcast.} + other {This episode is not published.} }', 'publishCancelSuccess' => 'Aflevering publicatie is geannuleerd!', - 'unpublishBeforeDeleteTip' => 'Je moet de publicatie van de aflevering ongedaan maken voordat je deze verwijdert.', - 'scheduleDateError' => 'Geplande datum moet worden ingesteld!', - 'deletePublishedEpisodeError' => 'Je moet de publicatie van de aflevering ongedaan maken voordat je deze verwijdert.', - 'deleteSuccess' => 'Aflevering succesvol verwijderd!', - 'deleteError' => 'Kan de aflevering niet verwijderen {type, select, + 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', + 'scheduleDateError' => 'Schedule date must be set!', + 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', + 'deleteSuccess' => 'Episode successfully deleted!', + 'deleteError' => 'Failed to delete episode {type, select, transcript {transcript} - chapters {hoofdstukken} + chapters {chapters} image {cover} audio {audio} other {media} }.', - 'deleteFileError' => 'Mislukt om te verwijderen {type, select, + 'deleteFileError' => 'Failed to delete {type, select, transcript {transcript} - chapters {hoofdstukken} + chapters {chapters} image {cover} audio {audio} other {media} - } bestand {file_key}. Je kunt het handmatig verwijderen van je schijf.', - 'sameSlugError' => 'Er bestaat al een aflevering met de gekozen slug.', + } file {file_path}. You may manually remove it from your disk.', + 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ 'file_size_error' => @@ -99,7 +97,7 @@ return [ 'cover' => 'Aflevering omslag', 'cover_hint' => 'Als je geen omslag instelt, zal de podcast omslag worden gebruikt.', - 'cover_size_hint' => 'Omslag moet minstens 1400px breed en hoog zijn.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'title' => 'Titel', 'title_hint' => 'Moet een duidelijke en beknopte afleveringsnaam bevatten. Geef hier geen aflevering of seizoen nummers op.', @@ -111,115 +109,105 @@ return [ 'full' => 'Vol', 'full_hint' => 'Volledige inhoud (aflevering)', 'trailer' => 'Trailer', - 'trailer_hint' => 'Korte, promotionele inhoud die een voorbeeld van de huidige show vertegenwoordigt', + 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra inhoud voor de show (bijvoorbeeld achter de scène-info of interviews met de deelnemers) of cross-promotionele inhoud voor een andere show', + 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', ], 'premium_title' => 'Premium', - 'premium' => 'Aflevering mag alleen toegankelijk zijn voor premium abonnees', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ - 'label' => 'Ouderlijk advies', - 'hint' => 'Bevat de aflevering de expliciete inhoud?', - 'undefined' => 'niet gedefineerd', - 'clean' => 'Fatsoenlijk', - 'explicit' => 'Expliciet', + 'label' => 'Parental advisory', + 'hint' => 'Does the episode contain explicit content?', + 'undefined' => 'undefined', + 'clean' => 'Clean', + 'explicit' => 'Explicit', ], - 'show_notes_section_title' => 'Toon notities', + 'show_notes_section_title' => 'Show notes', 'show_notes_section_subtitle' => - 'Maximaal 4000 tekens, wees duidelijk en beknopt. Notities helpen potentiële luisteraars om de aflevering te vinden.', - 'description' => 'Omschrijving', - 'description_footer' => 'Omschrijving voettekst', + 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', + 'description' => 'Description', + 'description_footer' => 'Description footer', 'description_footer_hint' => - 'Deze tekst wordt aan het einde van elke aflevering beschrijving toegevoegd, het is een goede plek om bijvoorbeeld je sociale links te plaatsen.', - 'additional_files_section_title' => 'Extra bestanden', + 'This text is added at the end of each episode description, it is a good place to input your social links for example.', + 'additional_files_section_title' => 'Additional files', 'additional_files_section_subtitle' => - 'Deze bestanden kunnen door andere platforms worden gebruikt om uw publiek een betere ervaring te bieden. Zie de {podcastNamespaceLink} voor meer informatie.', - 'location_section_title' => 'Locatie', - 'location_section_subtitle' => 'Over welke plaats gaat deze aflevering?', - 'location_name' => 'Locatienaam of adres', - 'location_name_hint' => 'Dit kan een echte of fictieve locatie zijn', - 'transcript' => 'Transcript (ondertiteling / gesloten ondertitels)', - 'transcript_hint' => 'Alleen .srt of .vtt zijn toegestaan.', - 'transcript_download' => 'Transcriptie downloaden', - 'transcript_file' => 'Transcript-bestand (.srt of .vtt)', - 'transcript_remote_url' => 'Externe URL voor transcript', - 'transcript_file_delete' => 'Verwijder transcript-bestand', - 'chapters' => 'Hoofdstukken', - 'chapters_hint' => 'Bestand moet in JSON Hoofdstuk indeling zijn.', - 'chapters_download' => 'Hoofdstukken downloaden', - 'chapters_file' => 'Hoofdstukken bestand', - 'chapters_remote_url' => 'Externe URL voor hoofdstukken bestand', - 'chapters_file_delete' => 'Verwijder hoofdstukken bestand', - 'advanced_section_title' => 'Geavanceerde parameters', + 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', + 'location_section_title' => 'Location', + 'location_section_subtitle' => 'What place is this episode about?', + 'location_name' => 'Location name or address', + 'location_name_hint' => 'This can be a real or fictional location', + 'transcript' => 'Transcript (subtitles / closed captions)', + 'transcript_hint' => 'Only .srt are allowed.', + 'transcript_download' => 'Download transcript', + 'transcript_file' => 'Transcript file (.srt)', + 'transcript_remote_url' => 'Remote url for transcript', + 'transcript_file_delete' => 'Delete transcript file', + 'chapters' => 'Chapters', + 'chapters_hint' => 'File must be in JSON Chapters format.', + 'chapters_download' => 'Download chapters', + 'chapters_file' => 'Chapters file', + 'chapters_remote_url' => 'Remote url for chapters file', + 'chapters_file_delete' => 'Delete chapters file', + 'advanced_section_title' => 'Advanced Parameters', 'advanced_section_subtitle' => - 'Als je RSS tags nodig hebt die Castopod niet afhandelt, stel ze hier in.', - 'custom_rss' => 'Aangepaste RSS labels voor de aflevering', + 'If you need RSS tags that Castopod does not handle, set them here.', + 'custom_rss' => 'Custom RSS tags for the episode', 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', 'block' => 'Episode should be hidden from public catalogues', 'block_hint' => 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Aflevering aanmaken', - 'submit_edit' => 'Aflevering opslaan', + 'submit_create' => 'Create episode', + 'submit_edit' => 'Save episode', ], 'publish_form' => [ 'back_to_episode_dashboard' => 'Back to episode dashboard', 'post' => 'Your announcement post', 'post_hint' => "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Schrijf uw bericht…', - 'publication_date' => 'Publicatiedatum', + 'message_placeholder' => 'Write your message…', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Nu', - 'schedule' => 'Plannen', - 'with_podcast' => 'Publiceer samen met podcast', + 'now' => 'Now', + 'schedule' => 'Schedule', + 'with_podcast' => 'Publish alongside podcast', ], - 'scheduled_publication_date' => 'Gepland publicatiedatum', - 'scheduled_publication_date_clear' => 'Publicatiedatum wissen', + 'scheduled_publication_date' => 'Scheduled publication date', + 'scheduled_publication_date_clear' => 'Clear publication date', 'scheduled_publication_date_hint' => 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publiceren', - 'submit_edit' => 'Publicatie bewerken', - 'cancel_publication' => 'Publicatie annuleren', + 'submit' => 'Publish', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', 'message_warning' => 'You did not write a message for your announcement post!', 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Toch publiceren', + 'message_warning_submit' => 'Publish anyways', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nieuwe publicatiedatum', + 'new_publication_date' => 'New publication date', 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Publicatiedatum bewerken', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Publicatie ongedaan maken', + 'submit' => 'Unpublish', ], 'delete_form' => [ 'disclaimer' => "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Verwijderen', + 'submit' => 'Delete', ], 'embed' => [ 'title' => 'Embeddable player', 'label' => 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Kopieer adres naar klembord', - 'dark' => 'Donker', + 'clipboard_url' => 'Copy address to clipboard', + 'dark' => 'Dark', 'dark-transparent' => 'Dark transparent', - 'light' => 'Licht', + 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Voorbeeld', - ], ]; diff --git a/modules/Admin/Language/nl/EpisodeNavigation.php b/modules/Admin/Language/nl/EpisodeNavigation.php index 34577f82..1406e301 100644 --- a/modules/Admin/Language/nl/EpisodeNavigation.php +++ b/modules/Admin/Language/nl/EpisodeNavigation.php @@ -11,13 +11,13 @@ declare(strict_types=1); return [ 'go_to_page' => 'View episode page', 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Hoofdpagina', - 'episode-edit' => 'Aflevering bewerken', - 'episode-persons-manage' => 'Personen beheren', + 'episode-view' => 'Home', + 'episode-edit' => 'Edit episode', + 'episode-persons-manage' => 'Manage persons', 'embed-add' => 'Embeddable player', 'clips' => 'Clips', - 'video-clips-list' => 'Videoclips', - 'video-clips-create' => 'Nieuwe videoclip', + 'video-clips-list' => 'Video clips', + 'video-clips-create' => 'New video clip', 'soundbites-list' => 'Soundbites', 'soundbites-create' => 'New soundbite', ]; diff --git a/modules/Admin/Language/nl/Fediverse.php b/modules/Admin/Language/nl/Fediverse.php index 2ce69a02..0e4ca66d 100644 --- a/modules/Admin/Language/nl/Fediverse.php +++ b/modules/Admin/Language/nl/Fediverse.php @@ -10,23 +10,23 @@ declare(strict_types=1); return [ 'messages' => [ - 'actorNotFound' => 'Het account werd niet gevonden!', - 'blockActorSuccess' => '{actor} is geblokkeerd!', - 'unblockActorSuccess' => 'Acteur is gedeblokkeerd!', - 'blockDomainSuccess' => '{domain} is geblokkeerd!', - 'unblockDomainSuccess' => '{domain} is gedeblokkeerd!', + 'actorNotFound' => 'The account could not be found!', + 'blockActorSuccess' => '{actor} has been blocked!', + 'unblockActorSuccess' => 'Actor has been unblocked!', + 'blockDomainSuccess' => '{domain} has been blocked!', + 'unblockDomainSuccess' => '{domain} has been unblocked!', ], - 'blocked_actors' => 'Geblokkeerde accounts', - 'blocked_domains' => 'Geblokkeerde domeinen', + 'blocked_actors' => 'Blocked accounts', + 'blocked_domains' => 'Blocked domains', 'block_lists_form' => [ 'handle' => 'Account handle', 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domeinnaam', + 'domain' => 'Domain name', 'submit' => 'Block!', ], 'list' => [ 'actor' => 'Account', - 'domain' => 'Domeinnaam', - 'unblock' => 'Deblokkeren', + 'domain' => 'Domain name', + 'unblock' => 'Unblock', ], ]; diff --git a/modules/Admin/Language/nl/Home.php b/modules/Admin/Language/nl/Home.php index 8620f125..3ff4c04d 100644 --- a/modules/Admin/Language/nl/Home.php +++ b/modules/Admin/Language/nl/Home.php @@ -9,6 +9,6 @@ declare(strict_types=1); */ return [ - 'all_podcasts' => 'Alle podcasts', - 'no_podcast' => 'Geen podcast gevonden', + 'all_podcasts' => 'All podcasts', + 'no_podcast' => 'No podcast found', ]; diff --git a/modules/Admin/Language/nl/Install.php b/modules/Admin/Language/nl/Install.php index cfd92f3f..36e373a2 100644 --- a/modules/Admin/Language/nl/Install.php +++ b/modules/Admin/Language/nl/Install.php @@ -9,12 +9,12 @@ declare(strict_types=1); */ return [ - 'manual_config' => 'Handmatige configuratie', + 'manual_config' => 'Manual configuration', 'manual_config_subtitle' => 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostnaam', + 'hostname' => 'Hostname', 'media_base_url' => 'Media base URL', 'media_base_url_hint' => 'If you use a CDN and/or an external analytics service, you may set them here.', @@ -28,7 +28,7 @@ return [ 'database_config_hint' => 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', 'db_hostname' => 'Database hostname', - 'db_name' => 'Databasenaam', + 'db_name' => 'Database name', 'db_username' => 'Database username', 'db_password' => 'Database password', 'db_prefix' => 'Database prefix', @@ -39,16 +39,16 @@ return [ 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', 'cache_handler' => 'Cache handler', 'cacheHandlerOptions' => [ - 'file' => 'Bestand', + 'file' => 'File', 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'Volgende', - 'submit' => 'Installatie voltooien', + 'next' => 'Next', + 'submit' => 'Finish install', 'create_superadmin' => 'Create your superadmin account', - 'email' => 'E-mail', - 'username' => 'Gebruikersnaam', - 'password' => 'Wachtwoord', + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', ], 'messages' => [ 'createSuperAdminSuccess' => diff --git a/modules/Auth/Language/fr2/MyAccount.php b/modules/Admin/Language/nl/MyAccount.php similarity index 100% rename from modules/Auth/Language/fr2/MyAccount.php rename to modules/Admin/Language/nl/MyAccount.php diff --git a/modules/Admin/Language/nl/Navigation.php b/modules/Admin/Language/nl/Navigation.php index 62f09b7c..68d4609d 100644 --- a/modules/Admin/Language/nl/Navigation.php +++ b/modules/Admin/Language/nl/Navigation.php @@ -9,36 +9,33 @@ declare(strict_types=1); */ return [ - 'toggle_sidebar' => 'Zijbalk tonen/verbergen', - 'go_to_website' => 'Ga naar website', + 'toggle_sidebar' => 'Toggle sidebar', + 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Niet geautoriseerd', 'dashboard' => 'Dashboard', - 'admin' => 'Hoofdpagina', + 'admin' => 'Home', 'podcasts' => 'Podcasts', - 'podcast-list' => 'Alle podcasts', - 'podcast-create' => 'Nieuwe podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Importeer een podcast', - 'persons' => 'Personen', - 'person-list' => 'Alle personen', - 'person-create' => 'Nieuwe persoon', + 'podcast-list' => 'All podcasts', + 'podcast-create' => 'New podcast', + 'podcast-import' => 'Import a podcast', + 'persons' => 'Persons', + 'person-list' => 'All persons', + 'person-create' => 'New person', 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Geblokkeerde accounts', - 'fediverse-blocked-domains' => 'Geblokkeerde domeinen', - 'users' => 'Gebruikers', - 'user-list' => 'Alle gebruikers', - 'user-create' => 'Nieuwe gebruiker', - 'pages' => 'Pagina\'s', - 'page-list' => 'Alle pagina\'s', - 'page-create' => 'Nieuwe pagina', - 'settings' => 'Instellingen', - 'settings-general' => 'Algemeen', - 'settings-theme' => 'Thema', - 'admin-about' => 'Over', + 'fediverse-blocked-actors' => 'Blocked accounts', + 'fediverse-blocked-domains' => 'Blocked domains', + 'users' => 'Users', + 'user-list' => 'All users', + 'user-create' => 'New user', + 'pages' => 'Pages', + 'page-list' => 'All pages', + 'page-create' => 'New Page', + 'settings' => 'Settings', + 'settings-general' => 'General', + 'settings-theme' => 'Theme', 'account' => [ - 'my-account' => 'Mijn account', - 'change-password' => 'Wachtwoord wijzigen', - 'logout' => 'Uitloggen', + 'my-account' => 'My account', + 'change-password' => 'Change password', + 'logout' => 'Logout', ], ]; diff --git a/modules/Admin/Language/nl/Notifications.php b/modules/Admin/Language/nl/Notifications.php index 76d9697b..2b139d51 100644 --- a/modules/Admin/Language/nl/Notifications.php +++ b/modules/Admin/Language/nl/Notifications.php @@ -9,11 +9,11 @@ declare(strict_types=1); */ return [ - 'title' => 'Meldingen', - 'reply' => '{actor_username} heeft op uw bericht gereageerd', - 'favourite' => '{actor_username} heeft je post als favoriet gemarkeerd', - 'reblog' => '{actor_username} heeft je bericht gedeeld', - 'follow' => '{actor_username} volgt je nu', - 'no_notifications' => 'Geen meldingen', - 'mark_all_as_read' => 'Alles als gelezen markeren', + 'title' => 'Notifications', + 'reply' => '{actor_username} replied to your post', + 'favourite' => '{actor_username} favourited your post', + 'reblog' => '{actor_username} shared your post', + 'follow' => '{actor_username} started following you', + 'no_notifications' => 'No notifications', + 'mark_all_as_read' => 'Mark all as read', ]; diff --git a/modules/Admin/Language/nl/Page.php b/modules/Admin/Language/nl/Page.php index 566bbd92..b6f49de5 100644 --- a/modules/Admin/Language/nl/Page.php +++ b/modules/Admin/Language/nl/Page.php @@ -9,22 +9,22 @@ declare(strict_types=1); */ return [ - 'back_to_home' => 'Terug naar de hoofdpagina', - 'page' => 'Pagina', - 'all_pages' => 'Alle pagina\'s', - 'create' => 'Nieuwe pagina', - 'go_to_page' => 'Ga naar pagina', - 'edit' => 'Pagina bewerken', - 'delete' => 'Pagina verwijderen', + 'back_to_home' => 'Back to home', + 'page' => 'Page', + 'all_pages' => 'All pages', + 'create' => 'New page', + 'go_to_page' => 'Go to page', + 'edit' => 'Edit page', + 'delete' => 'Delete page', 'form' => [ - 'title' => 'Titel', + 'title' => 'Title', 'permalink' => 'Permalink', - 'content' => 'Inhoud', - 'submit_create' => 'Pagina aanmaken', - 'submit_edit' => 'Opslaan', + 'content' => 'Content', + 'submit_create' => 'Create page', + 'submit_edit' => 'Save', ], 'messages' => [ - 'createSuccess' => 'De pagina "{pageTitle}" is succesvol aangemaakt!', - 'editSuccess' => 'De pagina is succesvol bijgewerkt!', + 'createSuccess' => 'The page “{pageTitle}” was created successfully!', + 'editSuccess' => 'The page was successfully updated!', ], ]; diff --git a/modules/Admin/Language/nl/Pager.php b/modules/Admin/Language/nl/Pager.php index 210448d8..e25ee638 100644 --- a/modules/Admin/Language/nl/Pager.php +++ b/modules/Admin/Language/nl/Pager.php @@ -9,13 +9,13 @@ declare(strict_types=1); */ return [ - 'pageNavigation' => 'Paginanavigatie', - 'first' => 'Eerste', - 'previous' => 'Vorige', - 'next' => 'Volgende', - 'last' => 'Laatste', - 'older' => 'Ouder', - 'newer' => 'Nieuwer', + 'pageNavigation' => 'Page navigation', + 'first' => 'First', + 'previous' => 'Previous', + 'next' => 'Next', + 'last' => 'Last', + 'older' => 'Older', + 'newer' => 'Newer', 'invalidTemplate' => '{0} is not a valid Pager template.', 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', ]; diff --git a/modules/Admin/Language/nl/Person.php b/modules/Admin/Language/nl/Person.php index 19a25696..a652be9f 100644 --- a/modules/Admin/Language/nl/Person.php +++ b/modules/Admin/Language/nl/Person.php @@ -9,57 +9,57 @@ declare(strict_types=1); */ return [ - 'persons' => 'Personen', - 'all_persons' => 'Alle personen', - 'no_person' => 'Niemand gevonden!', - 'create' => 'Een persoon aanmaken', - 'view' => 'Persoon weergeven', - 'edit' => 'Persoon bewerken', - 'delete' => 'Persoon verwijderen', + 'persons' => 'Persons', + 'all_persons' => 'All persons', + 'no_person' => 'Nobody found!', + 'create' => 'Create a person', + 'view' => 'View person', + 'edit' => 'Edit person', + 'delete' => 'Delete person', 'messages' => [ - 'createSuccess' => 'Persoon is succesvol aangemaakt!', - 'editSuccess' => 'Persoon is succesvol bijgewerkt!', - 'deleteSuccess' => 'Persoon is verwijderd!', + 'createSuccess' => 'Person has been successfully created!', + 'editSuccess' => 'Person has been successfully updated!', + 'deleteSuccess' => 'Person has been removed!', ], 'form' => [ 'avatar' => 'Avatar', 'avatar_size_hint' => 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Volledige naam', - 'full_name_hint' => 'Dit is de volledige naam of alias van de persoon.', - 'unique_name' => 'Unieke naam', - 'unique_name_hint' => 'Gebruikt voor URLs', - 'information_url' => 'Informatie URL', + 'full_name' => 'Full name', + 'full_name_hint' => 'This is the full name or alias of the person.', + 'unique_name' => 'Unique name', + 'unique_name_hint' => 'Used for URLs', + 'information_url' => 'Information URL', 'information_url_hint' => 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Persoon aanmaken', - 'submit_edit' => 'Persoon opslaan', + 'submit_create' => 'Create person', + 'submit_edit' => 'Save person', ], 'podcast_form' => [ - 'title' => 'Personen beheren', - 'add_section_title' => 'Voeg personen toe aan deze podcast', - 'add_section_subtitle' => 'U kunt meerdere personen en rollen kiezen.', - 'persons' => 'Personen', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this podcast', + 'add_section_subtitle' => 'You may pick several persons and roles.', + 'persons' => 'Persons', 'persons_hint' => 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Rollen', + 'roles' => 'Roles', 'roles_hint' => 'You may select none, one or several roles for a person.', 'submit_add' => 'Add person(s)', - 'remove' => 'Verwijderen', + 'remove' => 'Remove', ], 'episode_form' => [ - 'title' => 'Personen beheren', - 'add_section_title' => 'Voeg personen toe aan deze aflevering', - 'add_section_subtitle' => 'U kunt meerdere personen en rollen kiezen.', - 'persons' => 'Personen', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this episode', + 'add_section_subtitle' => 'You may pick several persons and roles.', + 'persons' => 'Persons', 'persons_hint' => 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Rollen', + 'roles' => 'Roles', 'roles_hint' => 'You may select none, one or several roles for a person.', 'submit_add' => 'Add person(s)', - 'remove' => 'Verwijderen', + 'remove' => 'Remove', ], 'credits' => 'Credits', ]; diff --git a/modules/Admin/Language/nl/Platforms.php b/modules/Admin/Language/nl/Platforms.php index 67f69651..ab17d599 100644 --- a/modules/Admin/Language/nl/Platforms.php +++ b/modules/Admin/Language/nl/Platforms.php @@ -9,26 +9,13 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Sociale netwerken', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Ga naar de {platformName} website', - 'register' => 'Registreren', - 'submit_url' => 'Dien jouw podcast in op {platformName}', - 'your_link' => 'Jouw link', - 'your_id' => [ - 'podcasting' => 'Jouw ID', - 'social' => 'Jouw ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', + 'title' => 'Platforms', + 'home_url' => 'Go to {platformName} website', + 'submit_url' => 'Submit your podcast on {platformName}', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', - 'remove' => '{platformName} verwijderen', - 'submit' => 'Opslaan', + 'remove' => 'Remove {platformName}', + 'submit' => 'Save', 'messages' => [ 'updateSuccess' => 'Platform links have been successfully updated!', 'removeLinkSuccess' => 'The platform link has been removed.', diff --git a/modules/Admin/Language/nl/Podcast.php b/modules/Admin/Language/nl/Podcast.php index 12cf5f2a..426b763b 100644 --- a/modules/Admin/Language/nl/Podcast.php +++ b/modules/Admin/Language/nl/Podcast.php @@ -9,29 +9,27 @@ declare(strict_types=1); */ return [ - 'all_podcasts' => 'Alle podcasts', - 'no_podcast' => 'Geen podcast gevonden!', - 'create' => 'Podcast aanmaken', - 'import' => 'Podcast importeren', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'Nieuwe aflevering', - 'view' => 'Podcast bekijken', - 'edit' => 'Podcast bewerken', - 'publish' => 'Podcast publiceren', - 'publish_edit' => 'Publicatie bewerken', - 'delete' => 'Podcast verwijderen', - 'see_episodes' => 'Afleveringen bekijken', - 'see_contributors' => 'Bekijk bijdragers', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Ga naar pagina', - 'latest_episodes' => 'Laatste afleveringen', - 'see_all_episodes' => 'Toon alle afleveringen', - 'draft' => 'Concept', + 'all_podcasts' => 'All podcasts', + 'no_podcast' => 'No podcast found!', + 'create' => 'Create podcast', + 'import' => 'Import podcast', + 'new_episode' => 'New Episode', + 'view' => 'View podcast', + 'edit' => 'Edit podcast', + 'publish' => 'Publish podcast', + 'publish_edit' => 'Edit publication', + 'delete' => 'Delete podcast', + 'see_episodes' => 'See episodes', + 'see_contributors' => 'See contributors', + 'go_to_page' => 'Go to page', + 'latest_episodes' => 'Latest episodes', + 'see_all_episodes' => 'See all episodes', + 'draft' => 'Draft', 'messages' => [ - 'createSuccess' => 'Podcast succesvol aangemaakt!', - 'editSuccess' => 'Podcast is succesvol bijgewerkt!', - 'importSuccess' => 'Podcast is succesvol geïmporteerd!', - 'deleteSuccess' => 'Podcast @{podcast_handle} succesvol verwijderd!', + 'createSuccess' => 'Podcast successfully created!', + 'editSuccess' => 'Podcast has been successfully updated!', + 'importSuccess' => 'Podcast has been successfully imported!', + 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, cover {cover} banner {banner} @@ -49,87 +47,69 @@ return [ one {# episode was} other {# episodes were} } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is al up-to-date.', - 'publishError' => 'Deze podcast is al gepubliceerd of gepland voor publicatie.', - 'publishEditError' => 'Deze podcast is niet gepland voor publicatie.', + 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', + 'publishError' => 'This podcast is either already published or scheduled for publication.', + 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', 'banner_delete' => 'Delete podcast banner', - 'title' => 'Titel', + 'title' => 'Title', 'handle' => 'Handle', 'handle_hint' => 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', 'type' => [ - 'label' => 'Soort', + 'label' => 'Type', 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Omschrijving', - 'classification_section_title' => 'Classificatie', + 'description' => 'Description', + 'classification_section_title' => 'Classification', 'classification_section_subtitle' => 'These fields will impact your audience and competition.', - 'language' => 'Taal', - 'category' => 'Categorie', - 'category_placeholder' => 'Selecteer een categorie…', - 'other_categories' => 'Andere categorieën', + 'language' => 'Language', + 'category' => 'Category', + 'category_placeholder' => 'Select a category…', + 'other_categories' => 'Other categories', 'parental_advisory' => [ - 'label' => 'Ouderlijk advies', - 'hint' => 'Bevat de aflevering de expliciete inhoud?', - 'undefined' => 'niet gedefineerd', + 'label' => 'Parental advisory', + 'hint' => 'Does it contain explicit content?', + 'undefined' => 'undefined', 'clean' => 'Clean', - 'explicit' => 'Expliciet', + 'explicit' => 'Explicit', ], - 'author_section_title' => 'Auteur', - 'author_section_subtitle' => 'Wie beheert de podcast?', - 'owner_name' => 'Naam eigenaar', + 'author_section_title' => 'Author', + 'author_section_subtitle' => 'Who is managing the podcast?', + 'owner_name' => 'Owner name', 'owner_name_hint' => 'For administrative use only. Visible in the public RSS feed.', 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Uitgever', + 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Auteursrecht', - 'location_section_title' => 'Locatie', + 'copyright' => 'Copyright', + 'location_section_title' => 'Location', 'location_section_subtitle' => 'What place is this podcast about?', 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real place or fictional', 'monetization_section_title' => 'Monetization', 'monetization_section_subtitle' => - 'Verdien geld dankzij uw publiek.', + 'Earn money thanks to your audience.', 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,19 +118,19 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Samenwerking', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', + 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', 'partner_image_url' => 'Image URL', 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', @@ -158,42 +138,42 @@ return [ 'lock' => 'Prevent podcast from being copied', 'lock_hint' => 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Podcast aanmaken', - 'submit_edit' => 'Podcast opslaan', + 'submit_create' => 'Create podcast', + 'submit_edit' => 'Save podcast', ], 'category_options' => [ - 'uncategorized' => 'niet gecategoriseerd', - 'arts' => 'Kunsten', - 'business' => 'Zakelijk', - 'comedy' => 'Komedie', - 'education' => 'Educatie', - 'fiction' => 'Fictie', + 'uncategorized' => 'uncategorized', + 'arts' => 'Arts', + 'business' => 'Business', + 'comedy' => 'Comedy', + 'education' => 'Education', + 'fiction' => 'Fiction', 'government' => 'Government', - 'health_and_fitness' => 'Gezondheid & Fitness', - 'history' => 'Geschiedenis', - 'kids_and_family' => 'Kinderen & Familie', - 'leisure' => 'Vrije tijd', - 'music' => 'Muziek', - 'news' => 'Nieuws', - 'religion_and_spirituality' => 'Geloof & Spiritualiteit', - 'science' => 'Wetenschap', - 'society_and_culture' => 'Maatschappij & Cultuur', - 'sports' => 'Sporten', - 'technology' => 'Technologie', + 'health_and_fitness' => 'Health & Fitness', + 'history' => 'History', + 'kids_and_family' => 'Kids & Family', + 'leisure' => 'Leisure', + 'music' => 'Music', + 'news' => 'News', + 'religion_and_spirituality' => 'Religion & Spirituality', + 'science' => 'Science', + 'society_and_culture' => 'Society & Culture', + 'sports' => 'Sports', + 'technology' => 'Technology', 'true_crime' => 'True Crime', 'tv_and_film' => 'TV & Film', - 'books' => 'Boeken', - 'design' => 'Ontwerp', + 'books' => 'Books', + 'design' => 'Design', 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Voeding', - 'performing_arts' => 'Podiumkunsten', - 'visual_arts' => 'Beeldende kunsten', - 'careers' => 'Carrières', - 'entrepreneurship' => 'Ondernemerschap', - 'investing' => 'Investeren', - 'management' => 'Beheer', + 'food' => 'Food', + 'performing_arts' => 'Performing Arts', + 'visual_arts' => 'Visual Arts', + 'careers' => 'Careers', + 'entrepreneurship' => 'Entrepreneurship', + 'investing' => 'Investing', + 'management' => 'Management', 'marketing' => 'Marketing', - 'non_profit' => 'Non-profit', + 'non_profit' => 'Non-Profit', 'comedy_interviews' => 'Comedy Interviews', 'improv' => 'Improv', 'stand_up' => 'Stand-Up', @@ -230,101 +210,101 @@ return [ 'entertainment_news' => 'Entertainment News', 'news_commentary' => 'News Commentary', 'politics' => 'Politics', - 'sports_news' => 'Sportnieuws', + 'sports_news' => 'Sports News', 'tech_news' => 'Tech News', - 'buddhism' => 'Boeddhisme', - 'christianity' => 'Christendom', - 'hinduism' => 'Hindoeïsme', + 'buddhism' => 'Buddhism', + 'christianity' => 'Christianity', + 'hinduism' => 'Hinduism', 'islam' => 'Islam', - 'judaism' => 'Jodendom', - 'religion' => 'Religie', - 'spirituality' => 'Spiritualiteit', - 'astronomy' => 'Astronomie', - 'chemistry' => 'Chemie', - 'earth_sciences' => 'Aardwetenschappen', - 'life_sciences' => 'Levenswetenschappen', - 'mathematics' => 'Wiskunde', - 'natural_sciences' => 'Natuurwetenschappen', - 'nature' => 'Natuur', - 'physics' => 'Fysica', - 'social_sciences' => 'Sociale wetenschappen', + 'judaism' => 'Judaism', + 'religion' => 'Religion', + 'spirituality' => 'Spirituality', + 'astronomy' => 'Astronomy', + 'chemistry' => 'Chemistry', + 'earth_sciences' => 'Earth Sciences', + 'life_sciences' => 'Life Sciences', + 'mathematics' => 'Mathematics', + 'natural_sciences' => 'Natural Sciences', + 'nature' => 'Nature', + 'physics' => 'Physics', + 'social_sciences' => 'Social Sciences', 'documentary' => 'Documentary', - 'personal_journals' => 'Persoonlijke dagboeken', - 'philosophy' => 'Filosofie', - 'places_and_travel' => 'Plaatsen & Reizen', - 'relationships' => 'Relaties', - 'baseball' => 'Honkbal', - 'basketball' => 'Basketbal', + 'personal_journals' => 'Personal Journals', + 'philosophy' => 'Philosophy', + 'places_and_travel' => 'Places & Travel', + 'relationships' => 'Relationships', + 'baseball' => 'Baseball', + 'basketball' => 'Basketball', 'cricket' => 'Cricket', 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Voetbal', + 'football' => 'Football', 'golf' => 'Golf', 'hockey' => 'Hockey', 'rugby' => 'Rugby', - 'running' => 'Rennen', - 'soccer' => 'Voetbal', - 'swimming' => 'Zwemmen', + 'running' => 'Running', + 'soccer' => 'Soccer', + 'swimming' => 'Swimming', 'tennis' => 'Tennis', - 'volleyball' => 'Volleybal', + 'volleyball' => 'Volleyball', 'wilderness' => 'Wilderness', - 'wrestling' => 'Worstelen', + 'wrestling' => 'Wrestling', 'after_shows' => 'After Shows', - 'film_history' => 'Filmgeschiedenis', + 'film_history' => 'Film History', 'film_interviews' => 'Film Interviews', 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV-beoordelingen', + 'tv_reviews' => 'TV Reviews', ], 'publish_form' => [ 'back_to_podcast_dashboard' => 'Back to podcast dashboard', 'post' => 'Your announcement post', 'post_hint' => "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Schrijf uw bericht…', - 'submit' => 'Publiceren', - 'publication_date' => 'Publicatiedatum', + 'message_placeholder' => 'Write your message…', + 'submit' => 'Publish', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Nu', - 'schedule' => 'Plannen', + 'now' => 'Now', + 'schedule' => 'Schedule', ], - 'scheduled_publication_date' => 'Gepland publicatiedatum', + 'scheduled_publication_date' => 'Scheduled publication date', 'scheduled_publication_date_hint' => 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Publicatie bewerken', - 'cancel_publication' => 'Publicatie annuleren', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', 'message_warning' => 'You did not write a message for your announcement post!', 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Toch publiceren', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ 'draft_mode' => 'draft mode', - 'not_published' => 'De podcast is nog niet gepubliceerd.', - 'scheduled' => 'Deze podcast is gepland voor publicatie op {publication_date}.', + 'not_published' => 'This podcast is not yet published.', + 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Verwijderen', + 'submit' => 'Delete', ], - 'by' => 'Door {publisher}', - 'season' => 'Seizoen {seasonNumber}', - 'list_of_episodes_year' => '{year} afleveringen ({episodeCount})', + 'by' => 'By {publisher}', + 'season' => 'Season {seasonNumber}', + 'list_of_episodes_year' => '{year} episodes ({episodeCount})', 'list_of_episodes_season' => - 'Seizoen {seasonNumber} afleveringen ({episodeCount})', - 'no_episode' => 'Er zijn geen afleveringen gevonden!', - 'follow' => 'Volgen', + 'Season {seasonNumber} episodes ({episodeCount})', + 'no_episode' => 'No episode found!', + 'follow' => 'Follow', 'followers' => '{numberOfFollowers, plural, - one {# volger} - other {# volgers} + one {# follower} + other {# followers} }', 'posts' => '{numberOfPosts, plural, - one {# bericht} - other {# berichten} + one {# post} + other {# posts} }', - 'activity' => 'Activiteit', - 'episodes' => 'Afleveringen', + 'activity' => 'Activity', + 'episodes' => 'Episodes', 'sponsor' => 'Sponsor', 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Vind {podcastTitle} op', - 'listen_on' => 'Beluister op', + 'find_on' => 'Find {podcastTitle} on', + 'listen_on' => 'Listen on', ]; diff --git a/modules/Admin/Language/nl/PodcastImport.php b/modules/Admin/Language/nl/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/nl/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/nl/PodcastNavigation.php b/modules/Admin/Language/nl/PodcastNavigation.php index 6cbfcdbb..b4d7ddc0 100644 --- a/modules/Admin/Language/nl/PodcastNavigation.php +++ b/modules/Admin/Language/nl/PodcastNavigation.php @@ -10,33 +10,29 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Hoofdpagina', - 'podcast-edit' => 'Podcast bewerken', - 'podcast-persons-manage' => 'Personen beheren', - 'podcast-imports' => 'Podcast importeren', - 'podcast-imports-sync' => 'Synchroniseer feeds', - 'episodes' => 'Afleveringen', - 'episode-list' => 'Alle afleveringen', - 'episode-create' => 'Nieuwe aflevering', - 'analytics' => 'Statistieken', + 'podcast-view' => 'Home', + 'podcast-edit' => 'Edit podcast', + 'podcast-persons-manage' => 'Manage persons', + 'episodes' => 'Episodes', + 'episode-list' => 'All episodes', + 'episode-create' => 'New episode', + 'analytics' => 'Analytics', 'podcast-analytics' => 'Audience overview', 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locaties', - 'podcast-analytics-unique-listeners' => 'Unieke luisteraars', + 'podcast-analytics-locations' => 'Locations', + 'podcast-analytics-unique-listeners' => 'Unique listeners', 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Luistertijd', + 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'Alle abonnementen', - 'subscription-create' => 'Abonnement toevoegen', - 'contributors' => 'Bijdragers', - 'contributor-list' => 'Alle bijdragers', - 'contributor-add' => 'Bijdragers toevoegen', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Sociale netwerken', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Andere', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', + 'contributors' => 'Contributors', + 'contributor-list' => 'All contributors', + 'contributor-add' => 'Add contributor', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', + 'platforms-social' => 'Social networks', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/nl/Settings.php b/modules/Admin/Language/nl/Settings.php index 5ce212db..4a70dcba 100644 --- a/modules/Admin/Language/nl/Settings.php +++ b/modules/Admin/Language/nl/Settings.php @@ -9,7 +9,7 @@ declare(strict_types=1); */ return [ - 'title' => 'Algemene instellingen', + 'title' => 'General settings', 'instance' => [ 'title' => 'Instance', 'site_icon' => 'Site icon', @@ -18,18 +18,18 @@ return [ 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', 'site_name' => 'Site name', 'site_description' => 'Site description', - 'submit' => 'Opslaan', + 'submit' => 'Save', 'editSuccess' => 'Instance has been updated successfully!', 'deleteIconSuccess' => 'Site icon has been remove successfully!', ], 'images' => [ - 'title' => 'Afbeeldingen', + 'title' => 'Images', 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Afbeeldingen regenereren', + 'regenerate' => 'Regenerate images', 'regenerationSuccess' => 'All images have been regenerated successfully!', ], 'housekeeping' => [ - 'title' => 'Huishouden', + 'title' => 'Housekeeping', 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', 'reset_counts' => 'Reset counts', 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', @@ -43,16 +43,16 @@ return [ 'runSuccess' => 'Housekeeping has been run successfully!', ], 'theme' => [ - 'title' => 'Thema', - 'accent_section_title' => 'Accentkleur', - 'accent_section_subtitle' => 'Kies de kleur om het uiterlijk van alle openbare pagina\'s te bepalen.', - 'pine' => 'Den', + 'title' => 'Theme', + 'accent_section_title' => 'Accent color', + 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', + 'pine' => 'Pine', 'crimson' => 'Crimson', 'amber' => 'Amber', - 'lake' => 'Meer', + 'lake' => 'Lake', 'jacaranda' => 'Jacaranda', 'onyx' => 'Onyx', - 'submit' => 'Opslaan', - 'setInstanceThemeSuccess' => 'Thema is succesvol bijgewerkt!', + 'submit' => 'Save', + 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', ], ]; diff --git a/modules/Admin/Language/nl/Soundbite.php b/modules/Admin/Language/nl/Soundbite.php index 0f67581e..a3f828fe 100644 --- a/modules/Admin/Language/nl/Soundbite.php +++ b/modules/Admin/Language/nl/Soundbite.php @@ -20,8 +20,8 @@ return [ 'form' => [ 'title' => 'New soundbite', 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Begintijd', - 'duration' => 'Duur', + 'start_time' => 'Start at', + 'duration' => 'Duration', 'submit' => 'Create soundbite', ], 'play' => 'Play soundbite', diff --git a/modules/Admin/Language/nl/User.php b/modules/Admin/Language/nl/User.php new file mode 100644 index 00000000..585d6799 --- /dev/null +++ b/modules/Admin/Language/nl/User.php @@ -0,0 +1,56 @@ + "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', + 'delete' => 'Delete', + 'create' => 'New user', + 'view' => "{username}'s info", + 'all_users' => 'All users', + 'list' => [ + 'user' => 'User', + 'roles' => 'Roles', + 'banned' => 'Banned?', + ], + 'form' => [ + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', + 'new_password' => 'New Password', + 'roles' => 'Roles', + 'permissions' => 'Permissions', + 'submit_create' => 'Create user', + 'submit_edit' => 'Save', + 'submit_password_change' => 'Change!', + ], + 'roles' => [ + 'superadmin' => 'Super admin', + ], + 'messages' => [ + 'createSuccess' => + 'User created successfully! {username} will be prompted with a password reset upon first authentication.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', + 'editOwnerError' => + '{username} is the instance owner, you cannot edit its roles.', + 'banSuperAdminError' => + '{username} is a superadmin, one does not simply ban a superadmin…', + 'deleteSuperAdminError' => + '{username} is a superadmin, one does not simply delete a superadmin…', + 'deleteSuccess' => '{username} has been deleted.', + ], +]; diff --git a/modules/Admin/Language/nl/Validation.php b/modules/Admin/Language/nl/Validation.php index 1e61ef35..750b1968 100644 --- a/modules/Admin/Language/nl/Validation.php +++ b/modules/Admin/Language/nl/Validation.php @@ -12,6 +12,7 @@ return [ 'min_dims' => '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => - '{field} is geen afbeelding of niet van de juiste verhouding.', - 'is_json' => '{field} contains invalid JSON.', + '{field} is either not an image or not of the right ratio.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/nl/VideoClip.php b/modules/Admin/Language/nl/VideoClip.php index c277d850..638de697 100644 --- a/modules/Admin/Language/nl/VideoClip.php +++ b/modules/Admin/Language/nl/VideoClip.php @@ -10,16 +10,16 @@ declare(strict_types=1); return [ 'list' => [ - 'title' => 'Videoclips', + 'title' => 'Video clips', 'status' => [ 'label' => 'Status', - 'queued' => 'in wachtrij', + 'queued' => 'queued', 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'in behandeling', + 'pending' => 'pending', 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'actief', + 'running' => 'running', 'running_hint' => 'Clip is being generated.', - 'failed' => 'mislukt', + 'failed' => 'failed', 'failed_hint' => 'Clip could not be generated: script failure.', 'passed' => 'passed', 'passed_hint' => 'Clip was generated successfully!', @@ -40,23 +40,23 @@ return [ 'deleteSuccess' => 'Video clip has been successfully removed!', ], 'format' => [ - 'landscape' => 'Liggend', + 'landscape' => 'Landscape', 'portrait' => 'Portrait', - 'squared' => 'Vierkant', + 'squared' => 'Squared', ], 'form' => [ - 'title' => 'Nieuwe videoclip', + 'title' => 'New video clip', 'params_section_title' => 'Video clip parameters', 'clip_title' => 'Clip title', 'format' => [ - 'label' => 'Kies een formaat', + 'label' => 'Choose a format', 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', ], - 'theme' => 'Selecteer een thema', - 'start_time' => 'Begintijd', - 'duration' => 'Duur', + 'theme' => 'Select a theme', + 'start_time' => 'Start at', + 'duration' => 'Duration', 'trim_start' => 'Trim start', 'trim_end' => 'Trim end', 'submit' => 'Create video clip', diff --git a/modules/Admin/Language/nn-no/Breadcrumb.php b/modules/Admin/Language/nn-NO/Breadcrumb.php similarity index 74% rename from modules/Admin/Language/nn-no/Breadcrumb.php rename to modules/Admin/Language/nn-NO/Breadcrumb.php index 422e71df..d59e34ef 100644 --- a/modules/Admin/Language/nn-no/Breadcrumb.php +++ b/modules/Admin/Language/nn-NO/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Heim', 'podcasts' => 'podkastar', 'episodes' => 'episodar', - 'subscriptions' => 'tingingar', + 'subscriptions' => 'subscriptions', 'contributors' => 'bidragsytarar', 'pages' => 'sider', 'settings' => 'innstillingar', 'theme' => 'bunad', - 'about' => 'om', 'add' => 'legg til', 'new' => 'ny', 'edit' => 'rediger', 'persons' => 'personar', 'publish' => 'legg ut', 'publish-edit' => 'rediger publiseringa', - 'publish-date-edit' => 'rediger publiseringsdato', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'avpubliser', 'delete' => 'slett', - 'remove' => 'fjern', 'fediverse' => 'fødiverset', - 'blocked-actors' => 'blokkerte aktørar', - 'blocked-domains' => 'blokkerte domene', + 'block-lists' => 'blokkeringslister', 'users' => 'brukarar', 'my-account' => 'kontoen min', 'change-password' => 'endre passord', - 'imports' => 'importar', - 'sync-feeds' => 'synkroniser straumar', + 'import' => 'importer straumar', 'platforms' => 'plattformer', 'social' => 'sosiale nettverk', 'funding' => 'finansiering', - 'monetization-other' => 'andre måtar å tena pengar på', 'analytics' => 'analysar', 'locations' => 'stader', 'webpages' => 'nettsider', @@ -52,6 +47,6 @@ return [ 'soundbites' => 'lydbetar', 'video-clips' => 'videoklypp', 'embed' => 'innbyggbar spelar', - 'notifications' => 'varslingar', - 'suspend' => 'utvis', + 'notifications' => 'notifications', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/nn-no/Charts.php b/modules/Admin/Language/nn-NO/Charts.php similarity index 89% rename from modules/Admin/Language/nn-no/Charts.php rename to modules/Admin/Language/nn-NO/Charts.php index 5890aa0d..c0880f32 100644 --- a/modules/Admin/Language/nn-no/Charts.php +++ b/modules/Admin/Language/nn-NO/Charts.php @@ -35,7 +35,6 @@ return [ 'by_weekday' => 'Etter vekedag (dei siste 60 dagane)', 'by_hour' => 'Etter tid på dagen (dei siste 60 dagane)', 'podcast_by_bandwidth' => 'Dagleg bandbreidde (i MB)', - 'total_storage_by_month' => 'Lagrinsgsplass kvar månad (i MB)', - 'total_bandwidth_by_month' => 'Brukt bandbreidd pr. månad (i MB)', - 'total_bandwidth_by_month_limit' => 'Avgrensa til {totalBandwidth} pr. månad', + 'total_storage_by_month' => 'Monthly storage (in MB)', + 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', ]; diff --git a/modules/Admin/Language/nn-no/Common.php b/modules/Admin/Language/nn-NO/Common.php similarity index 92% rename from modules/Admin/Language/nn-no/Common.php rename to modules/Admin/Language/nn-NO/Common.php index f9678459..db095fd9 100644 --- a/modules/Admin/Language/nn-no/Common.php +++ b/modules/Admin/Language/nn-NO/Common.php @@ -40,13 +40,12 @@ return [ ], 'upload_file' => 'Last opp ei fil', 'remote_url' => 'Ekstern URL-adresse', - 'save' => 'Lagre', ], 'play_episode_button' => [ 'play' => 'Spel', 'playing' => 'Spelar', ], 'size_limit' => 'Maks storleik: {0}.', - 'choose_interact' => 'Vel korleis du vil samhandla', - 'view' => 'Vis', + 'choose_interact' => 'Choose how to interact', + 'view' => 'View', ]; diff --git a/modules/Auth/Language/nn-no/Contributor.php b/modules/Admin/Language/nn-NO/Contributor.php similarity index 72% rename from modules/Auth/Language/nn-no/Contributor.php rename to modules/Admin/Language/nn-NO/Contributor.php index 941af518..0fe4cc66 100644 --- a/modules/Auth/Language/nn-no/Contributor.php +++ b/modules/Admin/Language/nn-NO/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Legg til bidragsytar', 'submit_edit' => 'Oppdater rolla', ], - 'delete_form' => [ - 'title' => 'Fjern {contributor}', - 'disclaimer' => - 'Du er i ferd med å fjerna {contributor} som bidragsytar. Dei vil mista tilgangen til "{podcastTitle}".', - 'understand' => 'Eg forstår, og vil fjerna {contributor} frå "{podcastTitle}"', - 'submit' => 'Fjern', + 'roles' => [ + 'podcast_admin' => 'Podkaststyrar', ], 'messages' => [ - 'editSuccess' => 'Rolle endra!', - 'editOwnerError' => "Du kan ikkje endra podkast-eigaren.", 'removeOwnerError' => "Du kan ikkje fjerna podkast-eigaren!", 'removeSuccess' => 'Du har fjerna {username} frå {podcastTitle}', diff --git a/modules/Admin/Language/nn-no/Countries.php b/modules/Admin/Language/nn-NO/Countries.php similarity index 100% rename from modules/Admin/Language/nn-no/Countries.php rename to modules/Admin/Language/nn-NO/Countries.php diff --git a/modules/Admin/Language/da/Dashboard.php b/modules/Admin/Language/nn-NO/Dashboard.php similarity index 100% rename from modules/Admin/Language/da/Dashboard.php rename to modules/Admin/Language/nn-NO/Dashboard.php diff --git a/modules/Admin/Language/nn-no/Episode.php b/modules/Admin/Language/nn-NO/Episode.php similarity index 68% rename from modules/Admin/Language/nn-no/Episode.php rename to modules/Admin/Language/nn-NO/Episode.php index 4e7bb526..12a3672a 100644 --- a/modules/Admin/Language/nn-no/Episode.php +++ b/modules/Admin/Language/nn-NO/Episode.php @@ -22,41 +22,39 @@ return [ 'all_podcast_episodes' => 'Alle podkast-episodane', 'back_to_podcast' => 'Gå tilbake til podkasten', 'edit' => 'Rediger', - 'preview' => 'Førehandsvising', 'publish' => 'Legg ut', 'publish_edit' => 'Rediger publiseringa', - 'publish_date_edit' => 'Rediger publiseringsdatoen', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Avpubliser', 'publish_error' => 'Episoden er allereie publisert.', 'publish_edit_error' => 'Episoden er allereie publisert.', 'publish_cancel_error' => 'Episoden er allereie publisert.', - 'publish_date_edit_error' => 'Episoden er ikkje lagt ut enno, så du kan ikkje endra publiseringsdatoen.', - 'publish_date_edit_future_error' => 'Du kan berre setja publiseringsdatoen til ein tidlegare dato. Viss du vil endra planlagd publisering, kan du avpublisera episoden fyrst.', - 'publish_date_edit_success' => 'Publiseringsdatoen er endra.', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'Episoden er ikkje publisert.', 'delete' => 'Slett', 'go_to_page' => 'Gå til side', 'create' => 'Legg til ein episode', 'publication_status' => [ 'published' => 'Lagt ut', - 'with_podcast' => 'Lagt ut', + 'with_podcast' => 'Published', 'scheduled' => 'Planlagt', 'not_published' => 'Ikkje lagt ut', ], - 'with_podcast_hint' => 'Skal gjevast ut samstundes som podkasten', + 'with_podcast_hint' => 'To be published at the same time as the podcast', 'list' => [ 'search' => [ - 'placeholder' => 'Søk etter ein episode', - 'clear' => 'Tøm søket', - 'submit' => 'Søk', + 'placeholder' => 'Search for an episode', + 'clear' => 'Clear search', + 'submit' => 'Search', ], 'number_of_episodes' => '{numberOfEpisodes, plural, one {# episode} - other {# episodar} + other {# episodes} }', 'episode' => 'Episode', 'visibility' => 'Synlegheit', - 'downloads' => 'Nedlastingar', 'comments' => 'Kommentarar', 'actions' => 'Handlingar', ], @@ -64,31 +62,31 @@ return [ 'createSuccess' => 'Episoden er oppretta!', 'editSuccess' => 'Episoden er oppdatert!', 'publishSuccess' => '{publication_status, select, - published {Episoden er lagt ut.} - scheduled {Episoden er planlagt lagt ut.} - with_podcast {Denne episoden blir lagt ut samstundes som podkasten.} - other {Denne episoden er ikkje lagt ut.} + published {Episode successfully published!} + scheduled {Episode publication successfully scheduled!} + with_podcast {This episode will be published at the same time as the podcast.} + other {This episode is not published.} }', 'publishCancelSuccess' => 'Du har avbrote å leggja ut episoden.', - 'unpublishBeforeDeleteTip' => 'Du må avpublisera episoden før du slettar han.', - 'scheduleDateError' => 'Du må velja publiseringsdato.', - 'deletePublishedEpisodeError' => 'Du må avpublisera episoden før du slettar han.', - 'deleteSuccess' => 'Episoden er sletta.', - 'deleteError' => 'Greidde ikkje sletta {type, select, - transcript {transkripsjon} - chapters {kapittel} - image {omslag} - audio {lyd} + 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', + 'scheduleDateError' => 'Schedule date must be set!', + 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', + 'deleteSuccess' => 'Episode successfully deleted!', + 'deleteError' => 'Failed to delete episode {type, select, + transcript {transcript} + chapters {chapters} + image {cover} + audio {audio} other {media} - } for episoden.', - 'deleteFileError' => 'Greidde ikkje sletta {type, select, - transcript {transkripsjons} - chapters {kapittel} - image {omslags} - audio {lyd} + }.', + 'deleteFileError' => 'Failed to delete {type, select, + transcript {transcript} + chapters {chapters} + image {cover} + audio {audio} other {media} - }fila {file_key}. Du kan fjerna ho manuelt.', - 'sameSlugError' => 'Ei episode med denne kortadressa finst allereie.', + } file {file_path}. You may manually remove it from your disk.', + 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ 'file_size_error' => @@ -99,7 +97,7 @@ return [ 'cover' => 'Episodeomslag', 'cover_hint' => 'Viss du ikkje bruker eige omslag, blir omslaget til podkasten brukt i staden.', - 'cover_size_hint' => 'Omslaget må vera kvadratisk, og minst 1400pkt breitt og høgt.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'title' => 'Tittel', 'title_hint' => 'Bør innehalda eit klårt og konsist episodenamn. Ikkje skriv inn nummer på episode eller sesong her.', @@ -116,7 +114,7 @@ return [ 'bonus_hint' => 'Ekstra innhald (til dømes bakominfo eller intervju med skodespelarane) eller innhald for å framheva ein annan serie', ], 'premium_title' => 'Premium', - 'premium' => 'Episoden må vera tilgjengeleg berre for premium-abonnentar', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Råd til foreldre', 'hint' => 'Inneheld episoden grov prat?', @@ -133,15 +131,15 @@ return [ 'Denne teksten ligg på slutten av kvar episodeskildring, og er ein god stad å ha lenker til td. sosiale nettverk.', 'additional_files_section_title' => 'Fleire filer', 'additional_files_section_subtitle' => - 'Desse filene kan brukast av andre plattformer for å gje publikum ei betre oppleving. Sjå {podcastNamespaceLink} for meir informasjon.', + 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', 'location_section_title' => 'Stad', 'location_section_subtitle' => 'Kva stad handlar denne episoden om?', 'location_name' => 'Stadnamn eller adresse', 'location_name_hint' => 'Dette kan vera ein verkeleg eller oppdikta stad', 'transcript' => 'Transkribering (undertitlar eller teksting)', - 'transcript_hint' => 'Berre .srt eller .vtt er lov.', + 'transcript_hint' => 'Berre .srt.', 'transcript_download' => 'Last ned transkriberinga', - 'transcript_file' => 'Transkriberingsfil (.srt eller .vtt)', + 'transcript_file' => 'Transkriberingsfil (.srt)', 'transcript_remote_url' => 'Ekstern URL for teksting', 'transcript_file_delete' => 'Slett transkriberingsfila', 'chapters' => 'Kapittel', @@ -155,9 +153,9 @@ return [ 'Viss du treng RSS-merkelappar som Castopod ikkje handterer, kan du skriva dei inn her.', 'custom_rss' => 'Eigne RSS-merkelappar for episoden', 'custom_rss_hint' => 'Dette blir sett inn i ❬item❭-elementet.', - 'block' => 'Episoden skal gøymast frå offentlege katalogar', + 'block' => 'Episode should be hidden from public catalogues', 'block_hint' => - 'Vis- eller gøym- status for episoden: Dersom du skrur på dette, hindrar det at episoden kjem opp i Apple podcasts, Google podcasts og andre tredjeparts-appar som hentar podkastar frå desse (men ingen garanti)', + 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'submit_create' => 'Lag episode', 'submit_edit' => 'Lagre episode', ], @@ -171,7 +169,7 @@ return [ 'publication_method' => [ 'now' => 'No', 'schedule' => 'Planlegg', - 'with_podcast' => 'Legg ut saman med podkast', + 'with_podcast' => 'Publish alongside podcast', ], 'scheduled_publication_date' => 'Planlagt publiseringsdato', 'scheduled_publication_date_clear' => 'Tøm publiseringsdatoen', @@ -185,21 +183,21 @@ return [ 'message_warning_submit' => 'Legg ut likevel', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Ny publiseringsdato', - 'new_publication_date_hint' => 'Må vera ein dato i fortida.', - 'submit' => 'Rediger publiseringsdatoen', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "Viss du avpubliserer episoden, slettar du alle kommentarar og innlegg til han, og fjernar han frå RSS-straumen til podkasten.", + "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", 'understand' => 'Eg forstår, eg vil avpublisera episoden', 'submit' => 'Avpubliser', ], 'delete_form' => [ 'disclaimer' => - "Viss du slettar episoden, slettar du òg alle tilknytte mediafiler, kommentarar, filmklypp og lydbetar.", + "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", 'understand' => 'Eg forstår, eg vil sletta episoden', - 'submit' => 'Slett', + 'submit' => 'Delete', ], 'embed' => [ 'title' => 'Innbyggbar spelar', @@ -212,14 +210,4 @@ return [ 'light' => 'Lys', 'light-transparent' => 'Lys gjennomsiktig', ], - 'publication_status_banner' => [ - 'draft_mode' => 'kladdemodus', - 'text' => '{publication_status, select, - published {Episoden er ikkje lagt ut enno.} - scheduled {Episoden er planlagt lagt ut på {publication_date}.} - with_podcast {Denne episoden blir lagt ut samstundes som podkasten.} - other {Denne episoden er ikkje lagt ut enno.} - }', - 'preview' => 'Førehandsvising', - ], ]; diff --git a/modules/Admin/Language/nn-no/EpisodeNavigation.php b/modules/Admin/Language/nn-NO/EpisodeNavigation.php similarity index 100% rename from modules/Admin/Language/nn-no/EpisodeNavigation.php rename to modules/Admin/Language/nn-NO/EpisodeNavigation.php diff --git a/modules/Admin/Language/nn-no/Fediverse.php b/modules/Admin/Language/nn-NO/Fediverse.php similarity index 100% rename from modules/Admin/Language/nn-no/Fediverse.php rename to modules/Admin/Language/nn-NO/Fediverse.php diff --git a/modules/Admin/Language/nn-no/Home.php b/modules/Admin/Language/nn-NO/Home.php similarity index 100% rename from modules/Admin/Language/nn-no/Home.php rename to modules/Admin/Language/nn-NO/Home.php diff --git a/modules/Admin/Language/nn-no/Install.php b/modules/Admin/Language/nn-NO/Install.php similarity index 100% rename from modules/Admin/Language/nn-no/Install.php rename to modules/Admin/Language/nn-NO/Install.php diff --git a/modules/Auth/Language/nn-no/MyAccount.php b/modules/Admin/Language/nn-NO/MyAccount.php similarity index 100% rename from modules/Auth/Language/nn-no/MyAccount.php rename to modules/Admin/Language/nn-NO/MyAccount.php diff --git a/modules/Admin/Language/nn-no/Navigation.php b/modules/Admin/Language/nn-NO/Navigation.php similarity index 87% rename from modules/Admin/Language/nn-no/Navigation.php rename to modules/Admin/Language/nn-NO/Navigation.php index d7101730..ce1b2185 100644 --- a/modules/Admin/Language/nn-no/Navigation.php +++ b/modules/Admin/Language/nn-NO/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Vis/gøym sidepanelet', 'go_to_website' => 'Gå til nettsida', 'go_to_admin' => 'Gå til styringspanelet', - 'not-authorized' => 'Ikkje godkjent', 'dashboard' => 'Styringspanel', 'admin' => 'Heim', 'podcasts' => 'Podkastar', 'podcast-list' => 'Alle podkastar', 'podcast-create' => 'Ny podkast', - 'all-podcast-imports' => 'Alle podkast-importar', - 'podcast-imports-add' => 'Importer ein podkast', + 'podcast-import' => 'Importer ein podkast', 'persons' => 'Personar', 'person-list' => 'Alle personar', 'person-create' => 'Ny person', @@ -35,7 +33,6 @@ return [ 'settings' => 'Innstillingar', 'settings-general' => 'Generelt', 'settings-theme' => 'Bunad', - 'admin-about' => 'Om', 'account' => [ 'my-account' => 'Kontoen min', 'change-password' => 'Endre passord', diff --git a/modules/Admin/Language/da/Notifications.php b/modules/Admin/Language/nn-NO/Notifications.php similarity index 100% rename from modules/Admin/Language/da/Notifications.php rename to modules/Admin/Language/nn-NO/Notifications.php diff --git a/modules/Admin/Language/nn-no/Page.php b/modules/Admin/Language/nn-NO/Page.php similarity index 100% rename from modules/Admin/Language/nn-no/Page.php rename to modules/Admin/Language/nn-NO/Page.php diff --git a/modules/Admin/Language/nn-no/Pager.php b/modules/Admin/Language/nn-NO/Pager.php similarity index 100% rename from modules/Admin/Language/nn-no/Pager.php rename to modules/Admin/Language/nn-NO/Pager.php diff --git a/modules/Admin/Language/nn-no/Person.php b/modules/Admin/Language/nn-NO/Person.php similarity index 96% rename from modules/Admin/Language/nn-no/Person.php rename to modules/Admin/Language/nn-NO/Person.php index 33578a54..3b12626f 100644 --- a/modules/Admin/Language/nn-no/Person.php +++ b/modules/Admin/Language/nn-NO/Person.php @@ -24,7 +24,7 @@ return [ 'form' => [ 'avatar' => 'Profilbilete', 'avatar_size_hint' => - 'Profilbiletet må vera kvadratisk og minst 400pkt breitt og høgt.', + 'Avatar must be squared and at least 400px wide and tall.', 'full_name' => 'Fullt namn', 'full_name_hint' => 'Dette er det fulle namnet eller aliaset til personen.', 'unique_name' => 'Unikt namn', diff --git a/modules/Admin/Language/nn-no/Platforms.php b/modules/Admin/Language/nn-NO/Platforms.php similarity index 68% rename from modules/Admin/Language/nn-no/Platforms.php rename to modules/Admin/Language/nn-NO/Platforms.php index 5d1e2a75..3cf5f254 100644 --- a/modules/Admin/Language/nn-no/Platforms.php +++ b/modules/Admin/Language/nn-NO/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podkastplattformer', - 'social' => 'Sosiale nettverk', - 'funding' => 'Donasjonslenker', - ], - 'website' => 'Nettside', + 'title' => 'Plattformer', 'home_url' => 'Gå til {platformName}-nettstaden', - 'register' => 'Registrer deg', 'submit_url' => 'Send podkasten din til {platformName}', - 'your_link' => 'Lenka di', - 'your_id' => [ - 'podcasting' => 'ID-en din', - 'social' => 'ID-en din', - 'funding' => 'Lokkeordet ditt', - ], - 'your_cta' => 'Lokkeordet ditt', 'visible' => 'Vis på heimesida til podkasten?', 'on_embed' => 'Vis i den innbyggbare spelaren?', 'remove' => 'Fjern {platformName}', diff --git a/modules/Admin/Language/nn-no/Podcast.php b/modules/Admin/Language/nn-NO/Podcast.php similarity index 63% rename from modules/Admin/Language/nn-no/Podcast.php rename to modules/Admin/Language/nn-NO/Podcast.php index 18ef937e..f18cefc2 100644 --- a/modules/Admin/Language/nn-no/Podcast.php +++ b/modules/Admin/Language/nn-NO/Podcast.php @@ -13,57 +13,54 @@ return [ 'no_podcast' => 'Fann ingen podkast!', 'create' => 'Lag ein podcast', 'import' => 'Importer ein podkast', - 'all_imports' => 'Podkast-importar', 'new_episode' => 'Ny episode', 'view' => 'Sjå podkasten', 'edit' => 'Rediger podkasten', - 'publish' => 'Legg ut podkasten', - 'publish_edit' => 'Rediger publiseringa', + 'publish' => 'Publish podcast', + 'publish_edit' => 'Edit publication', 'delete' => 'Slett podkasten', 'see_episodes' => 'Sjå episodane', 'see_contributors' => 'Sjå bidragsytarane', - 'monetization_other' => 'Andre måtar å tena pengar på', 'go_to_page' => 'Gå til side', 'latest_episodes' => 'Dei nyaste episodane', 'see_all_episodes' => 'Sjå alle episodane', - 'draft' => 'Kladd', + 'draft' => 'Draft', 'messages' => [ - 'createSuccess' => 'Podkasten er oppretta!', + 'createSuccess' => 'Podcast successfully created!', 'editSuccess' => 'Podkasten er oppdatert!', 'importSuccess' => 'Podkasten er importert!', - 'deleteSuccess' => 'Podkasten @{podcast_handle} vart sletta.', - 'deletePodcastMediaError' => 'Greidde ikkje sletta {type, select, - cover {omslaget} - banner {banneret} + 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', + 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, + cover {cover} + banner {banner} other {media} - } til podkasten.', - 'deleteEpisodeMediaError' => 'Greidde ikkje sletta {type, select, - transcript {transkripsjonen} - chapters {kapittel} - image {omslag} - audio {lyd} + }.', + 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, + transcript {transcript} + chapters {chapters} + image {cover} + audio {audio} other {media} - } frå {episode_slug}.', - 'deletePodcastMediaFolderError' => 'Greidde ikkje sletta mediemappa {folder_path} for podkasten. Du kan sletta mappa manuelt.', - 'podcastFeedUpdateSuccess' => 'Vellukka oppdatering: {number_of_new_episodes, plural, - one {# episode vart lagt} - other {# episodar vart lagde} - } til podkasten!', - 'podcastFeedUpToDate' => 'Podkasten er allereie oppdatert.', - 'publishError' => 'Denne podkasten er allereie lagt ut eller planlagt for offentleggjering.', - 'publishEditError' => 'Denne podkasten er ikkje planlagt publisert.', - 'publishCancelSuccess' => 'Du har avbrote å leggja ut podkasten.', - 'scheduleDateError' => 'Du må velja publiseringsdato.', + }.', + 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', + 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, + one {# episode was} + other {# episodes were} + } added to the podcast!', + 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', + 'publishError' => 'This podcast is either already published or scheduled for publication.', + 'publishEditError' => 'This podcast is not scheduled for publication.', + 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', + 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ 'identity_section_title' => 'Podkastidentitet', 'identity_section_subtitle' => 'Desse felta gjer at du blir lagt merke til.', - 'fediverse_section_title' => 'Allheim-identitet', - 'cover' => 'Podkastomslag', - 'cover_size_hint' => 'Omslaget må vera kvadratisk, og minst 1400pkt breitt og høgt.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podkastbanner', - 'banner_size_hint' => 'Banneret må ha 3:1-forhold og vera minst 1500pkt breitt.', + 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', 'banner_delete' => 'Slett podkastbanneret', 'title' => 'Tittel', 'handle' => 'Handtak', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Med episodar', 'episodic_hint' => 'Viss det er meininga at episodane skal kunna lyttast til uansett rekkjefylgje. Dei nyaste episodane blir presenterte fyrst.', 'serial' => 'I serie', - 'serial_hint' => 'Om det er meininga at episodane skal koma i ei bestemt rekkjefylgje. Episodane med lågast nummer blir presenterte fyrst.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium slik det blir vist av podcast:medium-merkelappen i RSS. Viss du endrar dette, kan det påverka korleis avspelarar viser straumen din.', - 'podcast' => 'Podkast', - 'podcast_hint' => 'Skildrar ein straum for eit podkast-show.', - 'music' => 'Musikk', - 'music_hint' => 'Ein straum med musikk organisert i eit "album" der kvart element er ein song på albumet.', - 'audiobook' => 'Lydbok', - 'audiobook_hint' => 'Spesifikke typar lyd med eit element per straum, eller der elementa er kapittel i boka.', + 'serial_hint' => 'Viss det er meininga at episodane skal koma i ei bestemt rekkjefylgje. Dei eldste episodane blir presenterte fyrst.', ], 'description' => 'Skildring', 'classification_section_title' => 'Klassifisering', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Epost til eigaren', 'owner_email_hint' => 'Blir brukt av dei fleste plattformer til å stadfesta eigarskapen til podkasten. Synleg i den offentlege RSS-straumen.', - 'is_owner_email_removed_from_feed' => 'Fjernar eposten til eigaren frå den offentlege RSS-straumen', - 'is_owner_email_removed_from_feed_hint' => 'Det kan henda du mellombels må visa eposten din slik at ei katalogtenest kan stadfesta at du eig podkasten.', 'publisher' => 'Utgjevar', 'publisher_hint' => 'Gruppa som er ansvarleg for serien. Det er vanlegvis morselskapet eller nettverket til ein podkast. Dette feltet er stundom merka med «forfattar».', @@ -123,13 +108,8 @@ return [ 'monetization_section_subtitle' => 'Ten pengar med hjelp frå publikummet ditt.', 'premium' => 'Premium', - 'premium_by_default' => 'Episodane må ha premium som standardval', - 'premium_by_default_hint' => 'Podkastepisodane vil få premium som standardmerking. Du kan likevel ha nokre episodar, trailerar eller bonusar som offentlege.', - 'op3' => 'Open Podcast Prefix-prosjekt (OP3)', - 'op3_link' => 'Gå til OP3-styringspanelet ditt (ekstern lenke)', - 'op3_hint' => 'Verdiset analysedataa dine med OP3, som er ein tredjeparts analyseteneste med open kjeldekode. Del, stadfest og samanlikne analysedataa dine med det opne podkast-økosystemet.', - 'op3_enable' => 'Bruk OP3-analysetenesta', - 'op3_enable_hint' => 'Av tryggleiksgrunnar deler me ikkje analysedata for premium-episodar med OP3.', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', 'payment_pointer' => 'Betalingspunkt for nettkommersialisering', 'payment_pointer_hint' => 'Det er her du vil få inn pengar frå nettkommersialiseringa', @@ -138,12 +118,11 @@ return [ 'Viss du treng RSS-merkelappar som Castopod ikkje handterer, kan du skriva dei inn her.', 'custom_rss' => 'Eigne RSS-merkelappar for podkasten', 'custom_rss_hint' => 'Dette blir sett inn i ❬channel❭-elementet.', - 'verify_txt' => 'Stadfesting av eigarskap TXT', - 'verify_txt_hint' => 'I staden for å bruka epost, kan nokre tredjepartstenester stadfesta at du eig podkasten ved å be deg setja inn ein godkjenningstekst i straumen din.', - 'verify_txt_helper' => 'Denne teksten blir sett inn i ein -knagg.', 'new_feed_url' => 'Ny straum-URL', 'new_feed_url_hint' => 'Bruk dette feltet når du flyttar til eit anna domene eller vertsplattform. Standardvalet for verdien er den noverande RSS-adresse viss podkasten er importert.', - 'old_feed_url' => 'Gamal straum-URL', + 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnarskap', 'partner_id' => 'ID', 'partner_link_url' => 'Lenke-URL', @@ -151,9 +130,10 @@ return [ 'partner_id_hint' => 'Din eigen partnar-ID', 'partner_link_url_hint' => 'Lenkeadressa til den generelle partnaren', 'partner_image_url_hint' => 'Biletadressa til den generelle partnaren', - 'block' => 'Podkasten skal gøymast frå offentlege katalogar', + 'status_section_title' => 'Status', + 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => - 'Vis- eller gøym- status for podkasten: Dersom du skrur på dette, hindrar det heile podkasten frå å syna i Apple podcasts, Google podcasts og andre tredjeparts-appar som hentar podkastar frå desse (men ingen garanti)', + 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'complete' => 'Podkasten vil ikkje få fleire episodar', 'lock' => 'Hindre at podkasten blir kopiert', 'lock_hint' => @@ -275,36 +255,36 @@ return [ 'tv_reviews' => 'TV-meldingar', ], 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Tilbake til podkast-styringspanelet', - 'post' => 'Kunngjeringsinnlegget ditt', + 'back_to_podcast_dashboard' => 'Back to podcast dashboard', + 'post' => 'Your announcement post', 'post_hint' => - "Skriv ei melding for å kunngjera at du legg ut podkasten. Dette vil stå på hiemesida til podkasten din.", - 'message_placeholder' => 'Skriv kunngjeringa di…', - 'submit' => 'Legg ut', - 'publication_date' => 'Publiseringsdato', + "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", + 'message_placeholder' => 'Write your message…', + 'submit' => 'Publish', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'No', - 'schedule' => 'Tidsplan', + 'now' => 'Now', + 'schedule' => 'Schedule', ], - 'scheduled_publication_date' => 'Planlagd publiseringsdato', + 'scheduled_publication_date' => 'Scheduled publication date', 'scheduled_publication_date_hint' => - 'Du kan planleggja å offengleggjera podkasten seinare ved å skriva inn eit publiseringstidspunkt. Feltet må vera i formatet ÅÅÅÅ-MM-DD HH:mm', - 'submit_edit' => 'Rediger publiseringa', - 'cancel_publication' => 'Avbryt publisering', - 'message_warning' => 'Du skreiv inga melding til kunngjeringsinnlegget ditt!', - 'message_warning_hint' => 'Viss du skriv ei melding, kan det gje meir sosialt engasjement og syta for at podkasten din blir meir synleg.', - 'message_warning_submit' => 'Legg ut likevel', + 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', + 'message_warning' => 'You did not write a message for your announcement post!', + 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ - 'draft_mode' => 'kladdemodus', - 'not_published' => 'Denne podkasten er ikkje lagt ut enno.', - 'scheduled' => 'Denne podkasten er planlagt for utgjeving {publication_date}.', + 'draft_mode' => 'draft mode', + 'not_published' => 'This podcast is not yet published.', + 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => - "Viss du slettar podkasten, vil det sletta alle episodar, mediafiler, innlegg og analyse som høyrer til. Du kan ikkje angra dette, og vil ikkje få det tilbake etterpå.", - 'understand' => 'Eg forstår, og vil sletta podkasten for alltid', - 'submit' => 'Slett', + "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", + 'understand' => 'I understand, I want the podcast to be permanently deleted', + 'submit' => 'Delete', ], 'by' => 'Av {publisher}', 'season' => 'Sesong {seasonNumber}', @@ -314,12 +294,12 @@ return [ 'no_episode' => 'Fann ingen episode!', 'follow' => 'Fylg', 'followers' => '{numberOfFollowers, plural, - one {# fylgjar} - other {# fylgjarar} + one {# follower} + other {# followers} }', 'posts' => '{numberOfPosts, plural, - one {# innlegg} - other {# innlegg} + one {# post} + other {# posts} }', 'activity' => 'Aktivitet', 'episodes' => 'Episodar', diff --git a/modules/Admin/Language/nn-NO/PodcastImport.php b/modules/Admin/Language/nn-NO/PodcastImport.php new file mode 100644 index 00000000..2ef0f072 --- /dev/null +++ b/modules/Admin/Language/nn-NO/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'Podkast å importera', + 'old_podcast_section_subtitle' => + 'Syt for at du har rettane til podkasten før du importerer han. Å kopiera og kringkasta ein podkast utan løyve er ulovleg og straffbart.', + 'imported_feed_url' => 'URL til straumen', + 'imported_feed_url_hint' => 'Straumen må vera i xml- eller rss-format.', + 'new_podcast_section_title' => 'Den nye podkasten', + 'advanced_params_section_title' => 'Avanserte innstilingar', + 'advanced_params_section_subtitle' => + 'Bruk standardverdiane viss du ikkje veit kva desse felta er til.', + 'slug_field' => 'Felt som skal brukast til å laga kortadressa til episoden', + 'description_field' => + 'Kjeldefelt som skal brukast for å skildra episoden og syna notat', + 'force_renumber' => 'Tving renummerering av episodane', + 'force_renumber_hint' => + 'Bruk dette viss podkasten din ikkje har episodenummer, men du vil laga nummer når du importerer.', + 'season_number' => 'Sesongnummer', + 'season_number_hint' => + 'Bruk dette viss podkasten din ikkje har eit sesongnummer, men du vil laga eit når du importerer. La stå tomt i andre tilfelle.', + 'max_episodes' => 'Makstal på episodar å importera', + 'max_episodes_hint' => 'La stå tomt for å importera alle episodane', + 'lock_import' => + 'Denne straumen er verna. Du kan ikkje importera han. Viss du er eigaren, må du ta bort vernet på den originale plattforma.', + 'submit' => 'Importer ein podkast', +]; diff --git a/modules/Admin/Language/nn-no/PodcastNavigation.php b/modules/Admin/Language/nn-NO/PodcastNavigation.php similarity index 71% rename from modules/Admin/Language/nn-no/PodcastNavigation.php rename to modules/Admin/Language/nn-NO/PodcastNavigation.php index 301692bd..d62080ae 100644 --- a/modules/Admin/Language/nn-no/PodcastNavigation.php +++ b/modules/Admin/Language/nn-NO/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Gå til podkastsida', - 'rss_feed' => 'RSS-straum', 'dashboard' => 'Podkast-styringspanel', 'podcast-view' => 'Heim', 'podcast-edit' => 'Rediger podkasten', 'podcast-persons-manage' => 'Handter personar', - 'podcast-imports' => 'Podkast-importar', - 'podcast-imports-sync' => 'Synkroniser straumar', 'episodes' => 'Episodar', 'episode-list' => 'Alle episodane', 'episode-create' => 'Ny episode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Spelarar', 'podcast-analytics-listening-time' => 'Lyttetid', 'podcast-analytics-time-periods' => 'Tidsperiodar', - 'monetization' => 'Kommersialisering', - 'subscription-list' => 'Alle abonnement', - 'subscription-create' => 'Legg til abonnement', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', 'contributors' => 'Bidragsytarar', 'contributor-list' => 'Alle bidragsytarane', 'contributor-add' => 'Legg til bidragsytar', - 'broadcast' => 'Kringkast', - 'platforms-podcasting' => 'Podkastingsappar', + 'platforms' => 'Eksterne plattformer', + 'platforms-podcasting' => 'Podkasting', 'platforms-social' => 'Sosiale nettverk', - 'platforms-funding' => 'Donasjonslenker', - 'podcast-monetization-other' => 'Anna', + 'platforms-funding' => 'Finansiering', ]; diff --git a/modules/Admin/Language/nn-no/Settings.php b/modules/Admin/Language/nn-NO/Settings.php similarity index 86% rename from modules/Admin/Language/nn-no/Settings.php rename to modules/Admin/Language/nn-NO/Settings.php index d05ccfc9..6d9f6641 100644 --- a/modules/Admin/Language/nn-no/Settings.php +++ b/modules/Admin/Language/nn-NO/Settings.php @@ -15,7 +15,7 @@ return [ 'site_icon' => 'Sideikon', 'site_icon_delete' => 'Slett sideikonet', 'site_icon_hint' => 'Nettstadikon er det du ser i fanene på nettlesaren, bokmerkelina og når du legg til ein nettstad som snarveg på mobile einingar.', - 'site_icon_helper' => 'Ikonet må vera kvadratisk og minst 512pkt breitt og høgt.', + 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', 'site_name' => 'Nettstadnamn', 'site_description' => 'Skildring av nettstaden', 'submit' => 'Lagre', @@ -35,8 +35,8 @@ return [ 'reset_counts_helper' => 'Dette nullstiller alle datateljarar (tal på fylgjarar, innlegg, kommentarar…).', 'rewrite_media' => 'Overskriv metadata for medium', 'rewrite_media_helper' => 'Dette vil sletta alle overflødige mediafiler og laga dei på nytt (bilete, lydfiler, transkriberingar, kapittel, …)', - 'rename_episodes_files' => 'Gje episode-lydfilene nytt namn', - 'rename_episodes_files_hint' => 'Dette alternativet gjev alle episode-lydfilene tilfeldige nye namn. Bruk dette viss lenka til dei private episodane vart leken, for då blir ho i praksis gøymt att.', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', 'clear_cache' => 'Slett bufferinnhald', 'clear_cache_helper' => 'Dette tømmer redis-mellomlageret eller skrivbare/mellomlagra filer.', 'run' => 'Gjer reinhald', diff --git a/modules/Admin/Language/nn-no/Soundbite.php b/modules/Admin/Language/nn-NO/Soundbite.php similarity index 100% rename from modules/Admin/Language/nn-no/Soundbite.php rename to modules/Admin/Language/nn-NO/Soundbite.php diff --git a/modules/Auth/Language/nn-no/User.php b/modules/Admin/Language/nn-NO/User.php similarity index 74% rename from modules/Auth/Language/nn-no/User.php rename to modules/Admin/Language/nn-NO/User.php index fedf303b..0a51b30d 100644 --- a/modules/Auth/Language/nn-no/User.php +++ b/modules/Admin/Language/nn-NO/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Endre rollene til {username}", + 'edit_roles' => "Endre rollene til {username}", + 'forcePassReset' => 'Tving passordnullstilling', 'ban' => 'Steng ute', 'unban' => 'Slepp inn att', 'delete' => 'Slett', @@ -18,7 +19,7 @@ return [ 'all_users' => 'Alle brukarane', 'list' => [ 'user' => 'Brukar', - 'role' => 'Rolle', + 'roles' => 'Roller', 'banned' => 'Utestengd?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Brukarnamn', 'password' => 'Passord', 'new_password' => 'Nytt passord', - 'role' => 'Rolle', 'roles' => 'Roller', 'permissions' => 'Løyve', 'submit_create' => 'Lag brukar', 'submit_edit' => 'Lagre', 'submit_password_change' => 'Endre!', ], - 'delete_form' => [ - 'title' => 'Slett {user}', - 'disclaimer' => - "Du er i ferd med å sletta {user} for alltid. Dei vil ikkje få tilgang til styringspanelet lenger.", - 'understand' => 'Eg forstår, og vil sletta {user} for alltid', - 'submit' => 'Slett', + 'roles' => [ + 'superadmin' => 'Superstyrar', ], 'messages' => [ 'createSuccess' => 'Brukaren er oppretta! {username} vil få spørsmål om å endra passord fyrste gong hen loggar inn.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "Rollene til {username} er oppdaterte.", + 'forcePassResetSuccess' => + '{username} vil bli beden om å endra passord neste gong hen loggar inn.', 'banSuccess' => '{username} er utestengd.', 'unbanSuccess' => '{username} fekk sleppa inn att.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} er superstyrar, og du stengjer ikkje ute ein superstyrar…', - 'deleteOwnerError' => - '{username} eig nettstaden. Du kan ikkje berre sletta eigaren…', 'deleteSuperAdminError' => '{username} er superstyrar, og du slettar ikkje ein superstyrar…', 'deleteSuccess' => '{username} er sletta.', diff --git a/modules/Admin/Language/nn-no/Validation.php b/modules/Admin/Language/nn-NO/Validation.php similarity index 79% rename from modules/Admin/Language/nn-no/Validation.php rename to modules/Admin/Language/nn-NO/Validation.php index 21a34148..ed99da37 100644 --- a/modules/Admin/Language/nn-no/Validation.php +++ b/modules/Admin/Language/nn-NO/Validation.php @@ -13,5 +13,6 @@ return [ '{field} er anten ikkje eit bilete, eller er ikkje breitt og høgt nok.', 'is_image_ratio' => '{field} er anten ikkje eit bilete, eller har feil forhold mellom høgd og breidd.', - 'is_json' => '{field} inneheld ugyldig JSON.', + 'validate_url' => + '{field}-feltet må vera ei gyldig nettadresse (td. https://eksempel.no/).', ]; diff --git a/modules/Admin/Language/nn-no/VideoClip.php b/modules/Admin/Language/nn-NO/VideoClip.php similarity index 100% rename from modules/Admin/Language/nn-no/VideoClip.php rename to modules/Admin/Language/nn-NO/VideoClip.php diff --git a/modules/Admin/Language/nn-no/AboutCastopod.php b/modules/Admin/Language/nn-no/AboutCastopod.php deleted file mode 100644 index cdcce825..00000000 --- a/modules/Admin/Language/nn-no/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Om Castopod', - 'host_name' => 'Vertsnamn', - 'version' => 'Castopod-versjon', - 'php_version' => 'PHP-versjon', - 'os' => 'Operativsystem', - 'languages' => 'Språk', - 'update_database' => 'Oppdater databasen', - 'messages' => [ - 'databaseUpdateSuccess' => 'Databasen er oppdatert!', - ], -]; diff --git a/modules/Admin/Language/nn-no/Dashboard.php b/modules/Admin/Language/nn-no/Dashboard.php deleted file mode 100644 index cf1ee11a..00000000 --- a/modules/Admin/Language/nn-no/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Styringspanel', - 'welcome_message' => 'Velkomen til styrarområdet!', - 'podcasts' => [ - 'title' => 'Podkastar', - 'not_found' => 'Ingen publiserte podkastar', - 'last_published' => 'Sist lagt ut {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodar', - 'not_found' => 'Ingen publisert episode', - 'last_published' => 'Sist lagt ut {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Lagring', - 'subtitle' => '{totalUploaded} av {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/nn-no/Notifications.php b/modules/Admin/Language/nn-no/Notifications.php deleted file mode 100644 index 0ff8568b..00000000 --- a/modules/Admin/Language/nn-no/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Varslingar', - 'reply' => '{actor_username} svara på innlegget ditt', - 'favourite' => '{actor_username} merkte innlegget ditt som favoritt', - 'reblog' => '{actor_username} delte innlegget ditt', - 'follow' => '{actor_username} fylgde deg', - 'no_notifications' => 'Ingen varslingar', - 'mark_all_as_read' => 'Merk alle som lesne', -]; diff --git a/modules/Admin/Language/oc/AboutCastopod.php b/modules/Admin/Language/oc/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/oc/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/oc/Breadcrumb.php b/modules/Admin/Language/oc/Breadcrumb.php index 408c9f9f..f3269bfa 100644 --- a/modules/Admin/Language/oc/Breadcrumb.php +++ b/modules/Admin/Language/oc/Breadcrumb.php @@ -19,7 +19,6 @@ return [ 'pages' => 'pages', 'settings' => 'settings', 'theme' => 'theme', - 'about' => 'about', 'add' => 'add', 'new' => 'new', 'edit' => 'edit', @@ -29,19 +28,15 @@ return [ 'publish-date-edit' => 'edit publication date', 'unpublish' => 'unpublish', 'delete' => 'delete', - 'remove' => 'remove', 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'block lists', 'users' => 'users', 'my-account' => 'my account', 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'feed import', 'platforms' => 'platforms', 'social' => 'social networks', 'funding' => 'funding', - 'monetization-other' => 'other monetization', 'analytics' => 'analytics', 'locations' => 'locations', 'webpages' => 'web pages', diff --git a/modules/Admin/Language/oc/Charts.php b/modules/Admin/Language/oc/Charts.php index 6ede2510..4b33530e 100644 --- a/modules/Admin/Language/oc/Charts.php +++ b/modules/Admin/Language/oc/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/oc/Common.php b/modules/Admin/Language/oc/Common.php index 74addcf2..596c8bcd 100644 --- a/modules/Admin/Language/oc/Common.php +++ b/modules/Admin/Language/oc/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Upload a file', 'remote_url' => 'Remote URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Play', diff --git a/modules/Admin/Language/oc/Contributor.php b/modules/Admin/Language/oc/Contributor.php new file mode 100644 index 00000000..d0f3b93d --- /dev/null +++ b/modules/Admin/Language/oc/Contributor.php @@ -0,0 +1,41 @@ + 'Podcast contributors', + 'view' => "{username}'s contribution to {podcastTitle}", + 'add' => 'Add contributor', + 'add_contributor' => 'Add a contributor for {0}', + 'edit_role' => 'Update role for {0}', + 'edit' => 'Edit', + 'remove' => 'Remove', + 'list' => [ + 'username' => 'Username', + 'role' => 'Role', + ], + 'form' => [ + 'user' => 'User', + 'user_placeholder' => 'Select a user…', + 'role' => 'Role', + 'role_placeholder' => 'Select its role…', + 'submit_add' => 'Add contributor', + 'submit_edit' => 'Update role', + ], + 'roles' => [ + 'podcast_admin' => 'Podcast admin', + ], + 'messages' => [ + 'removeOwnerError' => "You can't remove the podcast owner!", + 'removeSuccess' => + 'You have successfully removed {username} from {podcastTitle}', + 'alreadyAddedError' => + "The contributor you're trying to add has already been added!", + ], +]; diff --git a/modules/Admin/Language/oc/Episode.php b/modules/Admin/Language/oc/Episode.php index 4fa846e3..91313a7c 100644 --- a/modules/Admin/Language/oc/Episode.php +++ b/modules/Admin/Language/oc/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'All podcast episodes', 'back_to_podcast' => 'Go back to podcast', 'edit' => 'Edit', - 'preview' => 'Preview', 'publish' => 'Publish', 'publish_edit' => 'Edit publication', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episode', 'visibility' => 'Visibility', - 'downloads' => 'Downloads', 'comments' => 'Comments', 'actions' => 'Actions', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'Chapters', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Admin/Language/oc/Home.php b/modules/Admin/Language/oc/Home.php index 2f0f3570..3ff4c04d 100644 --- a/modules/Admin/Language/oc/Home.php +++ b/modules/Admin/Language/oc/Home.php @@ -9,6 +9,6 @@ declare(strict_types=1); */ return [ - 'all_podcasts' => 'Totes los podcasts', - 'no_podcast' => 'Cap de podcast pas trobat', + 'all_podcasts' => 'All podcasts', + 'no_podcast' => 'No podcast found', ]; diff --git a/modules/Admin/Language/oc/Install.php b/modules/Admin/Language/oc/Install.php index 5a90a8ce..36e373a2 100644 --- a/modules/Admin/Language/oc/Install.php +++ b/modules/Admin/Language/oc/Install.php @@ -9,7 +9,7 @@ declare(strict_types=1); */ return [ - 'manual_config' => 'Configuracion manuala', + 'manual_config' => 'Manual configuration', 'manual_config_subtitle' => 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ @@ -39,12 +39,12 @@ return [ 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', 'cache_handler' => 'Cache handler', 'cacheHandlerOptions' => [ - 'file' => 'Fichièr', + 'file' => 'File', 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'Seguent', - 'submit' => 'Acabar l’installacion', + 'next' => 'Next', + 'submit' => 'Finish install', 'create_superadmin' => 'Create your superadmin account', 'email' => 'Email', 'username' => 'Username', diff --git a/modules/Auth/Language/id/MyAccount.php b/modules/Admin/Language/oc/MyAccount.php similarity index 100% rename from modules/Auth/Language/id/MyAccount.php rename to modules/Admin/Language/oc/MyAccount.php diff --git a/modules/Admin/Language/oc/Navigation.php b/modules/Admin/Language/oc/Navigation.php index f3ffb129..68d4609d 100644 --- a/modules/Admin/Language/oc/Navigation.php +++ b/modules/Admin/Language/oc/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Dashboard', 'admin' => 'Home', 'podcasts' => 'Podcasts', 'podcast-list' => 'All podcasts', 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Import a podcast', 'persons' => 'Persons', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -35,7 +33,6 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Admin/Language/oc/Platforms.php b/modules/Admin/Language/oc/Platforms.php index e161181c..ab17d599 100644 --- a/modules/Admin/Language/oc/Platforms.php +++ b/modules/Admin/Language/oc/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Platforms', 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', 'remove' => 'Remove {platformName}', diff --git a/modules/Admin/Language/oc/Podcast.php b/modules/Admin/Language/oc/Podcast.php index ff0daebc..426b763b 100644 --- a/modules/Admin/Language/oc/Podcast.php +++ b/modules/Admin/Language/oc/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No podcast found!', 'create' => 'Create podcast', 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'New Episode', 'view' => 'View podcast', 'edit' => 'Edit podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Delete podcast', 'see_episodes' => 'See episodes', 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Go to page', 'latest_episodes' => 'Latest episodes', 'see_all_episodes' => 'See all episodes', @@ -50,6 +48,7 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], 'description' => 'Description', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/oc/PodcastImport.php b/modules/Admin/Language/oc/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/oc/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/oc/PodcastNavigation.php b/modules/Admin/Language/oc/PodcastNavigation.php index bb777707..b4d7ddc0 100644 --- a/modules/Admin/Language/oc/PodcastNavigation.php +++ b/modules/Admin/Language/oc/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'Home', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodes', 'episode-list' => 'All episodes', 'episode-create' => 'New episode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/oc/User.php b/modules/Admin/Language/oc/User.php new file mode 100644 index 00000000..585d6799 --- /dev/null +++ b/modules/Admin/Language/oc/User.php @@ -0,0 +1,56 @@ + "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', + 'delete' => 'Delete', + 'create' => 'New user', + 'view' => "{username}'s info", + 'all_users' => 'All users', + 'list' => [ + 'user' => 'User', + 'roles' => 'Roles', + 'banned' => 'Banned?', + ], + 'form' => [ + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', + 'new_password' => 'New Password', + 'roles' => 'Roles', + 'permissions' => 'Permissions', + 'submit_create' => 'Create user', + 'submit_edit' => 'Save', + 'submit_password_change' => 'Change!', + ], + 'roles' => [ + 'superadmin' => 'Super admin', + ], + 'messages' => [ + 'createSuccess' => + 'User created successfully! {username} will be prompted with a password reset upon first authentication.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', + 'editOwnerError' => + '{username} is the instance owner, you cannot edit its roles.', + 'banSuperAdminError' => + '{username} is a superadmin, one does not simply ban a superadmin…', + 'deleteSuperAdminError' => + '{username} is a superadmin, one does not simply delete a superadmin…', + 'deleteSuccess' => '{username} has been deleted.', + ], +]; diff --git a/modules/Admin/Language/oc/Validation.php b/modules/Admin/Language/oc/Validation.php index f76c3163..750b1968 100644 --- a/modules/Admin/Language/oc/Validation.php +++ b/modules/Admin/Language/oc/Validation.php @@ -13,5 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/pl/AboutCastopod.php b/modules/Admin/Language/pl/AboutCastopod.php deleted file mode 100644 index 2a65d0d6..00000000 --- a/modules/Admin/Language/pl/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'O Castopod', - 'host_name' => 'Nazwa hosta', - 'version' => 'Wersja Castopod', - 'php_version' => 'Wersja PHP', - 'os' => 'System operacyjny', - 'languages' => 'Języki', - 'update_database' => 'Aktualizuj bazę danych', - 'messages' => [ - 'databaseUpdateSuccess' => 'Baza danych jest aktualna!', - ], -]; diff --git a/modules/Admin/Language/pl/Breadcrumb.php b/modules/Admin/Language/pl/Breadcrumb.php index 34ba50a6..d472ef10 100644 --- a/modules/Admin/Language/pl/Breadcrumb.php +++ b/modules/Admin/Language/pl/Breadcrumb.php @@ -14,44 +14,39 @@ return [ ->gateway => 'Początek', 'podcasts' => 'podcasty', 'episodes' => 'odcinki', - 'subscriptions' => 'subskrypcja', + 'subscriptions' => 'subscriptions', 'contributors' => 'kontrybutorzy', 'pages' => 'strony', 'settings' => 'ustawienia', 'theme' => 'motyw', - 'about' => 'informacje', 'add' => 'dodaj', 'new' => 'nowy', 'edit' => 'edytuj', 'persons' => 'osoby', 'publish' => 'publikuj', 'publish-edit' => 'edytuj publikację', - 'publish-date-edit' => 'edytuj datę publikacji', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'cofnij publikację', 'delete' => 'usuń', - 'remove' => 'usuń', - 'fediverse' => 'fediwersum', - 'blocked-actors' => 'zablokowani aktorzy', - 'blocked-domains' => 'zablokowane domeny', + 'fediverse' => 'fediverse', + 'block-lists' => 'listy blokowanych', 'users' => 'użytkownicy', 'my-account' => 'moje konto', 'change-password' => 'zmień hasło', - 'imports' => 'importy', - 'sync-feeds' => 'synchronizuj kanały', + 'import' => 'import kanału', 'platforms' => 'platformy', 'social' => 'sieci społecznościowe', 'funding' => 'finansowanie', - 'monetization-other' => 'inna monetyzacja', 'analytics' => 'analityka', 'locations' => 'lokalizacje', 'webpages' => 'strony internetowe', 'unique-listeners' => 'unikalni słuchacze', 'players' => 'odtwarzacze', 'listening-time' => 'czas odsłuchu', - 'time-periods' => 'przedziały czasu', + 'time-periods' => 'okresy czasu', 'soundbites' => 'zajawki', 'video-clips' => 'klipy wideo', 'embed' => 'odtwarzacz do osadzenia', - 'notifications' => 'powiadomienia', - 'suspend' => 'wstrzymaj', + 'notifications' => 'notifications', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/pl/Charts.php b/modules/Admin/Language/pl/Charts.php index ebd13d1d..32eb4e20 100644 --- a/modules/Admin/Language/pl/Charts.php +++ b/modules/Admin/Language/pl/Charts.php @@ -15,8 +15,8 @@ return [ 'by_device_weekly' => 'Pobrania odcinków według urządzenia (dla minionego tygodnia)', 'by_os_weekly' => 'Pobrania odcinków według systemu operacyjnego (dla minionego tygodnia)', 'podcast_by_region' => 'Pobrania odcinków według regionu (dla minionego tygodnia)', - 'unique_daily_listeners' => 'Unikalni słuchacze dziennie', - 'unique_monthly_listeners' => 'Unikalni słuchacze miesięcznie', + 'unique_daily_listeners' => 'Codzienni unikalni słuchacze', + 'unique_monthly_listeners' => 'Comiesięczni unikalni słuchacze', 'by_browser' => 'Wykorzystanie stron internetowych według przeglądarki (dla minionego tygodnia)', 'podcast_by_day' => 'Dzienne pobrania odcinków', 'podcast_by_month' => 'Miesięczne pobrania odcinków', @@ -29,13 +29,12 @@ return [ 'by_domain_weekly' => 'Odwiedziny stron internetowych według źródła (dla minionego tygodnia)', 'by_domain_yearly' => 'Odwiedziny stron internetowych według źródła (dla minionego roku)', 'by_entry_page' => 'Odwiedziny stron internetowych według landing page (dla minionego tygodnia)', - 'podcast_bots' => 'Boty (pająki)', + 'podcast_bots' => 'Boty (robaki)', 'daily_listening_time' => 'Dzienny łączny czas słuchania', 'monthly_listening_time' => 'Miesięczny łączny czas słuchania', 'by_weekday' => 'Według dnia tygodnia (dla minionych 60 dni)', 'by_hour' => 'Według pory dnia (dla minionych 60 dni)', 'podcast_by_bandwidth' => 'Dzienna przepustowość (w MB)', - 'total_storage_by_month' => 'Miesięczne przechowywanie (w MB)', - 'total_bandwidth_by_month' => 'Miesięczne zużycie transferu (w MB)', - 'total_bandwidth_by_month_limit' => 'Ograniczono do {totalBandwidth} miesięcznie', + 'total_storage_by_month' => 'Monthly storage (in MB)', + 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', ]; diff --git a/modules/Admin/Language/pl/Common.php b/modules/Admin/Language/pl/Common.php index 5d3fba6b..183399ee 100644 --- a/modules/Admin/Language/pl/Common.php +++ b/modules/Admin/Language/pl/Common.php @@ -40,13 +40,12 @@ return [ ], 'upload_file' => 'Prześlij plik', 'remote_url' => 'Zdalny URL', - 'save' => 'Zapisz', ], 'play_episode_button' => [ 'play' => 'Odtwarzaj', 'playing' => 'Odtwarzanie', ], 'size_limit' => 'Limit rozmiaru: {0}.', - 'choose_interact' => 'Wybierz sposób interakcji', - 'view' => 'Podgląd', + 'choose_interact' => 'Choose how to interact', + 'view' => 'View', ]; diff --git a/modules/Auth/Language/pl/Contributor.php b/modules/Admin/Language/pl/Contributor.php similarity index 67% rename from modules/Auth/Language/pl/Contributor.php rename to modules/Admin/Language/pl/Contributor.php index 0a5515d1..a00fc8b4 100644 --- a/modules/Auth/Language/pl/Contributor.php +++ b/modules/Admin/Language/pl/Contributor.php @@ -28,20 +28,14 @@ return [ 'submit_add' => 'Dodaj kontrybutora', 'submit_edit' => 'Zaktualizuj rolę', ], - 'delete_form' => [ - 'title' => 'Usuń {contributor}', - 'disclaimer' => - 'Zamierzasz usunąć {contributor} z wspierających. Nie będzie miał już mieć dostępu do "{podcastTitle}".', - 'understand' => 'Rozumiem, chcę usunąć {contributor} z "{podcastTitle}"', - 'submit' => 'Usuń', + 'roles' => [ + 'podcast_admin' => 'Administrator podcastu', ], 'messages' => [ - 'editSuccess' => 'Pomyślnie zmieniono rolę!', - 'editOwnerError' => "Nie możesz edytować właściciela podcastu!", 'removeOwnerError' => "Nie możesz usunąć właściciela podcastu!", 'removeSuccess' => 'Pomyślnie usunąłeś/aś {username} z {podcastTitle}', 'alreadyAddedError' => - "Kontrybutor, którego próbujesz dodać, został już dodany!", + "Kontrybutor, którego próbujesz dodać został już dodany!", ], ]; diff --git a/modules/Admin/Language/pl/Countries.php b/modules/Admin/Language/pl/Countries.php index 53f104a8..78a89f0b 100644 --- a/modules/Admin/Language/pl/Countries.php +++ b/modules/Admin/Language/pl/Countries.php @@ -11,7 +11,7 @@ declare(strict_types=1); */ return [ - 'AD' => 'Andora', + 'AD' => 'Andorra', 'AE' => 'Zjednoczone Emiraty Arabskie', 'AF' => 'Afganistan', 'AG' => 'Antigua i Barbuda', @@ -63,7 +63,7 @@ return [ 'CR' => 'Kostaryka', 'CU' => 'Kuba', 'CV' => 'Republika Zielonego Przylądka', - 'CW' => 'Curacao', + 'CW' => 'Curaçao', 'CX' => 'Wyspa Bożego Narodzenia', 'CY' => 'Cypr', 'CZ' => 'Czechy', @@ -121,7 +121,7 @@ return [ 'IR' => 'Iran', 'IS' => 'Islandia', 'IT' => 'Włochy', - 'JE' => 'Wyspa Jersey', + 'JE' => 'Jersey', 'JM' => 'Jamajka', 'JO' => 'Jordania', 'JP' => 'Japonia', @@ -146,12 +146,12 @@ return [ 'LT' => 'Litwa', 'LU' => 'Luksemburg', 'LV' => 'Łotwa', - 'LY' => 'Libia', + 'LY' => 'Libya', 'MA' => 'Maroko', 'MC' => 'Monako', 'MD' => 'Mołdawia', 'ME' => 'Czarnogóra', - 'MF' => 'Saint-Martin (Francja)', + 'MF' => 'Saint Martin (French part)', 'MG' => 'Madagaskar', 'MH' => 'Wyspy Marshalla', 'MK' => 'Macedonia Północna', @@ -224,7 +224,7 @@ return [ 'SV' => 'Salwador', 'SX' => 'Sint Maarten', 'SY' => 'Syria', - 'SZ' => 'Suazi', + 'SZ' => 'Swaziland', 'TC' => 'Turks i Caicos', 'TD' => 'Czad', 'TF' => 'Francuskie Terytoria Południowe i Antarktyczne', diff --git a/modules/Admin/Language/pl/Dashboard.php b/modules/Admin/Language/pl/Dashboard.php index 26030e1f..881073fd 100644 --- a/modules/Admin/Language/pl/Dashboard.php +++ b/modules/Admin/Language/pl/Dashboard.php @@ -9,20 +9,20 @@ declare(strict_types=1); */ return [ - 'home' => 'Panel administratora', - 'welcome_message' => 'Witamy w panelu administracyjnym!', + 'home' => 'Admin dashboard', + 'welcome_message' => 'Welcome to the admin area!', 'podcasts' => [ - 'title' => 'Podcasty', - 'not_found' => 'Brak opublikowanych podcastów', - 'last_published' => 'Ostatnio opublikowane {lastPublicationDate}', + 'title' => 'Podcasts', + 'not_found' => 'No published podcast', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'episodes' => [ - 'title' => 'Odcinki', - 'not_found' => 'Brak opublikowanych odcinków', - 'last_published' => 'Ostatnio opublikowane {lastPublicationDate}', + 'title' => 'Episodes', + 'not_found' => 'No published episode', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'storage' => [ - 'title' => 'Pamięć', - 'subtitle' => '{totalUploaded} z {totalStorage}', + 'title' => 'Storage', + 'subtitle' => '{totalUploaded} out of {totalStorage}', ], ]; diff --git a/modules/Admin/Language/pl/Episode.php b/modules/Admin/Language/pl/Episode.php index 5c84ab2b..ee45c805 100644 --- a/modules/Admin/Language/pl/Episode.php +++ b/modules/Admin/Language/pl/Episode.php @@ -21,44 +21,41 @@ return [ other {# komentarzy} }', 'all_podcast_episodes' => 'Wszystkie odcinki podcastu', - 'back_to_podcast' => 'Wróć do podcastu', + 'back_to_podcast' => 'Wróć do podkastu', 'edit' => 'Edytuj', - 'preview' => 'Podgląd', 'publish' => 'Publikuj', 'publish_edit' => 'Edytuj publikację', - 'publish_date_edit' => 'Edytuj datę publikacji', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Cofnij publikację', 'publish_error' => 'Odcinek jest już opublikowany.', 'publish_edit_error' => 'Odcinek jest już opublikowany.', 'publish_cancel_error' => 'Odcinek jest już opublikowany.', - 'publish_date_edit_error' => 'Odcinek nie został jeszcze opublikowany, nie możesz edytować daty jego publikacji.', - 'publish_date_edit_future_error' => 'Data publikacji odcinka może być ustawiona tylko na przeszłą datę! Jeśli chcesz ją ponownie zaplanować, należy najpierw cofnąć publikację.', - 'publish_date_edit_success' => 'Data publikacji odcinka została pomyślnie zaktualizowana!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'Odcinek nie jest opublikowany.', 'delete' => 'Usuń', 'go_to_page' => 'Przejdź do strony', 'create' => 'Dodaj odcinek', 'publication_status' => [ 'published' => 'Opublikowany', - 'with_podcast' => 'Opublikowano', + 'with_podcast' => 'Published', 'scheduled' => 'Zaplanowany', 'not_published' => 'Nieopublikowany', ], - 'with_podcast_hint' => 'Opublikowany w tym samym czasie co podcast', + 'with_podcast_hint' => 'To be published at the same time as the podcast', 'list' => [ 'search' => [ - 'placeholder' => 'Szukaj odcinka', - 'clear' => 'Wyczyść wyszukiwanie', - 'submit' => 'Szukaj', + 'placeholder' => 'Search for an episode', + 'clear' => 'Clear search', + 'submit' => 'Search', ], 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# osoba} - few {# osoby} - other {# osób} - }', + one {# episode} + other {# episodes} + }', 'episode' => 'Odcinek', 'visibility' => 'Widoczność', - 'downloads' => 'Pobrane', 'comments' => 'Komentarze', 'actions' => 'Działania', ], @@ -66,31 +63,31 @@ return [ 'createSuccess' => 'Odcinek został pomyślnie utworzony!', 'editSuccess' => 'Odcinek został pomyślnie zaktualizowany!', 'publishSuccess' => '{publication_status, select, - published {Odcinek został pomyślnie opublikowany!} - scheduled {Publikacja odcinka pomyślnie zaplanowana!} - with_podcast {Ten odcinek zostanie opublikowany w tym samym czasie co podcast.} - other {Ten odcinek nie jest opublikowany.} + published {Episode successfully published!} + scheduled {Episode publication successfully scheduled!} + with_podcast {This episode will be published at the same time as the podcast.} + other {This episode is not published.} }', - 'publishCancelSuccess' => 'Publikacja odcinka pomyślnie anulowana!', - 'unpublishBeforeDeleteTip' => 'Musisz cofnąć publikację odcinka przed jego usunięciem.', - 'scheduleDateError' => 'Zaplanowana data musi być ustawiona!', - 'deletePublishedEpisodeError' => 'Musisz cofnąć publikację odcinka przed jego usunięciem.', - 'deleteSuccess' => 'Odcinek pomyślnie usunięty!', - 'deleteError' => 'Nie udało się usunąć {type, select, - transcript {transkrypcji} - chapters {rozdziału} - image {okładki} + 'publishCancelSuccess' => 'Episode publication successfully cancelled!', + 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', + 'scheduleDateError' => 'Schedule date must be set!', + 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', + 'deleteSuccess' => 'Episode successfully deleted!', + 'deleteError' => 'Failed to delete episode {type, select, + transcript {transcript} + chapters {chapters} + image {cover} audio {audio} - other {mediów} - } odcinka.', - 'deleteFileError' => 'Nie można było skasować pliku {type, select, - transcript {transkryptu} - chapters {rozdziałów} - image {okładki} + other {media} + }.', + 'deleteFileError' => 'Failed to delete {type, select, + transcript {transcript} + chapters {chapters} + image {cover} audio {audio} - other {medium} - } {file_key}. Możesz chcieć zrobić to ręcznie.', - 'sameSlugError' => 'Odcinek z wybranym slugiem już istnieje.', + other {media} + } file {file_path}. You may manually remove it from your disk.', + 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ 'file_size_error' => @@ -101,7 +98,7 @@ return [ 'cover' => 'Okładka odcinka', 'cover_hint' => 'Jeśli nie ustawisz okładki, zamiast niej zostanie użyta okładka podcastu.', - 'cover_size_hint' => 'Okładka musi być kwadratowa o szerokości i wysokości co najmniej 1400 pikseli.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'title' => 'Tytuł', 'title_hint' => 'Powinien zawierać jasną i zwięzłą nazwę odcinka. Nie podawaj tutaj numerów odcinków ani sezonów.', @@ -113,37 +110,37 @@ return [ 'full' => 'Pełny', 'full_hint' => 'Pełna zawartość (odcinek)', 'trailer' => 'Zwiastun', - 'trailer_hint' => 'Krótka, promocyjna treść przedstawiająca bieżący program', + 'trailer_hint' => 'Krótka, promocyjna treść przedstawiająca podgląd bieżącego programu', 'bonus' => 'Bonus', 'bonus_hint' => 'Dodatkowa treść do programu (np. informacje zza kulis lub wywiady z obsadą) albo treści promujące inne programy', ], 'premium_title' => 'Premium', - 'premium' => 'Odcinek dostępny wyłącznie dla subskrybentów premium', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Kontrola rodzicielska', 'hint' => 'Czy odcinek zawiera treści dla dorosłych?', - 'undefined' => 'niezdefiniowano', + 'undefined' => 'nieokreślona', 'clean' => 'Czysta', 'explicit' => 'Dla dorosłych', ], 'show_notes_section_title' => 'Notatki programu', 'show_notes_section_subtitle' => - 'Do 4000 znaków, pisz krótko i zwięźle. Notatki programu pomagają potencjalnym słuchaczom w znalezieniu odcinka.', + 'Do 4000 znaków, bądź jasny i zwięźly. Notatki programu pomagają potencjalnym słuchaczom w znalezieniu odcinka.', 'description' => 'Opis', 'description_footer' => 'Stopka opisu', 'description_footer_hint' => 'Ten tekst jest dodawany na końcu każdego opisu odcinka; jest to dobre miejsce do wpisania np. linków społecznościowych.', 'additional_files_section_title' => 'Dodatkowe pliki', 'additional_files_section_subtitle' => - 'Pliki te mogą być używane przez inne platformy, aby zapewnić lepsze wrażenia odbiorcom. Więcej informacji znajdziesz w {podcastNamespaceLink}.', + 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', 'location_section_title' => 'Lokalizacja', 'location_section_subtitle' => 'O jakim miejscu jest ten odcinek?', 'location_name' => 'Nazwa lub adres lokalizacji', 'location_name_hint' => 'Może to być prawdziwa lub fikcyjna lokalizacja', 'transcript' => 'Transkrypcja (napisy / podpisy kodowane)', - 'transcript_hint' => 'Wspierane są tylko .srt lub .vtt.', + 'transcript_hint' => 'Dozwolone tylko .srt.', 'transcript_download' => 'Pobierz transkrypcję', - 'transcript_file' => 'Plik transkrypcji (.srt lub .vtt)', + 'transcript_file' => 'Plik transkrypcji (.srt)', 'transcript_remote_url' => 'Zdalny adres URL dla transkrypcji', 'transcript_file_delete' => 'Usuń plik transkrypcji', 'chapters' => 'Rozdziały', @@ -157,51 +154,51 @@ return [ 'Jeśli potrzebujesz tagów RSS, których Castopod nie obsługuje, ustaw je tutaj.', 'custom_rss' => 'Własne tagi RSS dla odcinka', 'custom_rss_hint' => 'Zostaną wstawione w tagu ❬item❭.', - 'block' => 'Odcinek powinien być ukryty w publicznych katalogach', + 'block' => 'Episode should be hidden from public catalogues', 'block_hint' => - 'Pokazywanie lub ukrywanie odcinka: przełączanie tej funkcji zapobiega pojawieniu się odcinka w Apple Podcasts, Google Podcasts, a także aplikacjach innych firm, które pobierają z tych katalogów. (Niegwarantowane)', + 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'submit_create' => 'Stwórz odcinek', 'submit_edit' => 'Zapisz odcinek', ], 'publish_form' => [ - 'back_to_episode_dashboard' => 'Wróć do panelu odcinka', + 'back_to_episode_dashboard' => 'Wróć do pulpitu odcinka', 'post' => 'Twój wpis ogłoszeniowy', 'post_hint' => - "Napisz wiadomość, aby ogłosić publikację swojego odcinka. Wiadomość zostanie wyemitowana do wszystkich Twoich obserwujących w fediwersum i pojawi się na stronie głównej Twojego podcastu.", + "Napisz wiadomość, aby ogłosić publikację swojego odcinka. Wiadomość zostanie wyemitowana do wszystkich Twoich obserwujących w fediverse i pojawi się na stronie głównej Twojego podcastu.", 'message_placeholder' => 'Napisz swoją wiadomość…', 'publication_date' => 'Data publikacji', 'publication_method' => [ 'now' => 'Teraz', 'schedule' => 'Zaplanuj', - 'with_podcast' => 'Opublikuj razem z podcastem', + 'with_podcast' => 'Publish alongside podcast', ], 'scheduled_publication_date' => 'Planowana data publikacji', 'scheduled_publication_date_clear' => 'Wyczyść datę publikacji', 'scheduled_publication_date_hint' => - 'Możesz zaplanować wydanie odcinka, ustawiając przyszłą datę publikacji. To pole musi być sformatowane jako YYYY-MM-DD HH:mm', + 'Możesz zaplanować wydanie odcinka ustawiając przyszłą datę publikacji. To pole musi być sformatowane jako YYYY-MM-DD HH:mm', 'submit' => 'Opublikuj', 'submit_edit' => 'Edytuj publikację', 'cancel_publication' => 'Anuluj publikację', 'message_warning' => 'Nie napisałeś wiadomości do swojego wpisu ogłoszeniowego!', - 'message_warning_hint' => 'Napisanie wiadomości zwiększa zaangażowanie społeczne, co skutkuje lepszą widocznością Twojego odcinka.', + 'message_warning_hint' => 'Posiadanie wiadomości zwiększa zaangażowanie społeczne, co skutkuje lepszą widocznością Twojego odcinka.', 'message_warning_submit' => 'Opublikuj mimo to', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nowa data publikacji', - 'new_publication_date_hint' => 'Musi być ustawiona przeszła data.', - 'submit' => 'Edytuj datę publikacji', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "Cofnięcie publikacji odcinka spowoduje usunięcie wszystkich powiązanych z nim wpisów i usunięcie go z kanału RSS podcastu.", + "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", 'understand' => 'Rozumiem, chcę cofnąć publikację odcinka', 'submit' => 'Cofnij publikację', ], 'delete_form' => [ 'disclaimer' => - "Usunięcie odcinka spowoduje usunięcie wszystkich plików multimedialnych, komentarzy, klipów wideo i powiązanych z nimi zajawek.", + "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", 'understand' => 'Rozumiem, chcę usunąć odcinek', - 'submit' => 'Usuń', + 'submit' => 'Delete', ], 'embed' => [ 'title' => 'Odtwarzacz osadzalny', @@ -214,14 +211,4 @@ return [ 'light' => 'Jasny', 'light-transparent' => 'Jasny przezroczysty', ], - 'publication_status_banner' => [ - 'draft_mode' => 'tryb szkicu', - 'text' => '{publication_status, select, - published {Ten odcinek jeszcze nie został opublikowany.} - scheduled {Ten odcinek zostanie opublikowany {publication_date}.} - with_podcast {Ten odcinek zostanie opublikowany w tym samym momencie, co podcast.} - other {Ten odcinek jeszcze nie został opublikowany.} - }', - 'preview' => 'Podgląd', - ], ]; diff --git a/modules/Admin/Language/pl/EpisodeNavigation.php b/modules/Admin/Language/pl/EpisodeNavigation.php index 48564e3d..6d71ae7e 100644 --- a/modules/Admin/Language/pl/EpisodeNavigation.php +++ b/modules/Admin/Language/pl/EpisodeNavigation.php @@ -10,11 +10,11 @@ declare(strict_types=1); return [ 'go_to_page' => 'Wyświetl stronę odcinka', - 'dashboard' => 'Panel odcinka', + 'dashboard' => 'Pulpit odcinka', 'episode-view' => 'Początek', 'episode-edit' => 'Edytuj odcinek', 'episode-persons-manage' => 'Zarządzaj osobami', - 'embed-add' => 'Odtwarzacz do osadzania', + 'embed-add' => 'Odtwarzacz do zagnieżdżenia', 'clips' => 'Klipy', 'video-clips-list' => 'Klipy wideo', 'video-clips-create' => 'Nowy klip wideo', diff --git a/modules/Admin/Language/pl/Fediverse.php b/modules/Admin/Language/pl/Fediverse.php index 8c0bda3c..e35653ae 100644 --- a/modules/Admin/Language/pl/Fediverse.php +++ b/modules/Admin/Language/pl/Fediverse.php @@ -10,9 +10,9 @@ declare(strict_types=1); return [ 'messages' => [ - 'actorNotFound' => 'Nie udało się znaleźć użytkownika!', + 'actorNotFound' => 'The account could not be found!', 'blockActorSuccess' => '{actor} został zablokowany!', - 'unblockActorSuccess' => 'Aktor został odblokowany!', + 'unblockActorSuccess' => 'Actor został odblokowany!', 'blockDomainSuccess' => '{domain} została zablokowana!', 'unblockDomainSuccess' => '{domain} została odblokowana!', ], @@ -20,7 +20,7 @@ return [ 'blocked_domains' => 'Zablokowane domeny', 'block_lists_form' => [ 'handle' => 'Uchwyt konta', - 'handle_hint' => 'Wpisz @nazwaużytkownika@domena konta.', + 'handle_hint' => 'Wpisz @nazwęużytkownika@domenę konta.', 'domain' => 'Nazwa domeny', 'submit' => 'Zablokuj!', ], diff --git a/modules/Admin/Language/pl/Install.php b/modules/Admin/Language/pl/Install.php index 28724a3e..bb333f22 100644 --- a/modules/Admin/Language/pl/Install.php +++ b/modules/Admin/Language/pl/Install.php @@ -15,15 +15,15 @@ return [ 'form' => [ 'instance_config' => 'Konfiguracja instancji', 'hostname' => 'Nazwa hosta', - 'media_base_url' => 'Bazowy URL mediów', + 'media_base_url' => 'Bazowy URL multimediów', 'media_base_url_hint' => - 'Jeśli korzystasz z CDNa i/lub zewnętrznej usługi analitycznej, możesz ustawić je tutaj.', - 'admin_gateway' => 'Strona administracyjna', + 'Jeśli korzystasz z CDN i/lub zewnętrznej usługi analitycznej, możesz ustawić je tutaj.', + 'admin_gateway' => 'Brama administracyjna', 'admin_gateway_hint' => - 'Droga dostępu do obszaru administracyjnego (np. https://example.com/cp-admin). Domyślnie jest ustawiona jako cp-admin, ale ze względów bezpieczeństwa zalecamy zmianę tej nazwy.', - 'auth_gateway' => 'Strona uwierzytelniania', + 'Droga dostępu do obszaru administracyjnego (np. https://example.com/cp-admin). Domyślnie jest ustawiona jako cp-admin, ze względów bezpieczeństwa zalecamy jej zmianę.', + 'auth_gateway' => 'Brama uwierzytelniania', 'auth_gateway_hint' => - 'Dostęp do stron uwierzytelniających (np. https://example.com/cp-auth). Domyślnie jest ustawiony jako cp-auth, ale ze względów bezpieczeństwa zalecamy zmianę tej nazwy.', + 'Droga dostępu do stron uwierzytelniających (np. https://example.com/cp-auth). Domyślnie jest ustawiona jako cp-auth, ze względów bezpieczeństwa zalecamy jej zmianę.', 'database_config' => 'Konfiguracja bazy danych', 'database_config_hint' => 'Castopod musi połączyć się z bazą danych MySQL (lub MariaDB). Jeśli nie masz tych wymaganych informacji, skontaktuj się z administratorem serwera.', @@ -33,11 +33,11 @@ return [ 'db_password' => 'Hasło bazy danych', 'db_prefix' => 'Prefiks bazy danych', 'db_prefix_hint' => - "Prefiks nazw tabel Castopod — pozostaw bez zmian, jeśli nie wiesz, co to znaczy.", + "Przedrostek nazw tabel Castopod; pozostaw bez zmian jeśli nie wiesz, co to znaczy.", 'cache_config' => 'Konfiguracja pamięci podręcznej', 'cache_config_hint' => - 'Wybierz preferowany mechanizm pamięci podręcznej. Zostaw domyślną wartość, jeśli nie masz pojęcia, co to znaczy.', - 'cache_handler' => 'Mechanizm pamięci podręcznej', + 'Wybierz preferowaną obsługę pamięci podręcznej (cache). Pozostaw to jako wartość domyślną, jeśli nie masz pojęcia, co to znaczy.', + 'cache_handler' => 'Obsługa pamięci podręcznej', 'cacheHandlerOptions' => [ 'file' => 'Plik', 'redis' => 'Redis', @@ -56,6 +56,6 @@ return [ 'databaseConnectError' => 'Castopod nie mógł połączyć się z Twoją bazą danych. Edytuj konfigurację bazy danych i spróbuj ponownie.', 'writeError' => - "Nie można utworzyć/zapisać pliku `.env`. Musisz go utworzyć ręcznie, postępując zgodnie z szablonem `.env.example` w pakiecie Castopod.", + "Nie można utworzyć/zapisać pliku `.env`. Musisz go utworzyć ręcznie postępując zgodnie z szablonem pliku `.env.example` w pakiecie Castopod.", ], ]; diff --git a/modules/Auth/Language/pl/MyAccount.php b/modules/Admin/Language/pl/MyAccount.php similarity index 100% rename from modules/Auth/Language/pl/MyAccount.php rename to modules/Admin/Language/pl/MyAccount.php diff --git a/modules/Admin/Language/pl/Navigation.php b/modules/Admin/Language/pl/Navigation.php index c7c14989..d4a44104 100644 --- a/modules/Admin/Language/pl/Navigation.php +++ b/modules/Admin/Language/pl/Navigation.php @@ -11,19 +11,17 @@ declare(strict_types=1); return [ 'toggle_sidebar' => 'Przełącz pasek boczny', 'go_to_website' => 'Idź do strony internetowej', - 'go_to_admin' => 'Przejdź do panelu administratora', - 'not-authorized' => 'Brak uprawnień', - 'dashboard' => 'Panel', - 'admin' => 'Strona główna', + 'go_to_admin' => 'Idź do administracji', + 'dashboard' => 'Pulpit', + 'admin' => 'Początek', 'podcasts' => 'Podcasty', 'podcast-list' => 'Wszystkie podcasty', 'podcast-create' => 'Nowy podcast', - 'all-podcast-imports' => 'Wszystkie importy podcastów', - 'podcast-imports-add' => 'Importuj podcast', + 'podcast-import' => 'Importuj podcast', 'persons' => 'Osoby', 'person-list' => 'Wszystkie osoby', 'person-create' => 'Nowa osoba', - 'fediverse' => 'Fediwersum', + 'fediverse' => 'Fediverse', 'fediverse-blocked-actors' => 'Zablokowane konta', 'fediverse-blocked-domains' => 'Zablokowane domeny', 'users' => 'Użytkownicy', @@ -35,7 +33,6 @@ return [ 'settings' => 'Ustawienia', 'settings-general' => 'Ogólne', 'settings-theme' => 'Motyw', - 'admin-about' => 'Informacje', 'account' => [ 'my-account' => 'Moje konto', 'change-password' => 'Zmień hasło', diff --git a/modules/Admin/Language/pl/Notifications.php b/modules/Admin/Language/pl/Notifications.php index 22d4fd6c..2b139d51 100644 --- a/modules/Admin/Language/pl/Notifications.php +++ b/modules/Admin/Language/pl/Notifications.php @@ -9,11 +9,11 @@ declare(strict_types=1); */ return [ - 'title' => 'Powiadomienia', - 'reply' => '{actor_username} odpowiedział na Twój post', - 'favourite' => '{actor_username} polubił Twój post', - 'reblog' => '{actor_username} udostępnił Twój post', - 'follow' => '{actor_username} zaczął Cię obserwować', - 'no_notifications' => 'Brak powiadomień', - 'mark_all_as_read' => 'Oznacz wszystkie jako przeczytane', + 'title' => 'Notifications', + 'reply' => '{actor_username} replied to your post', + 'favourite' => '{actor_username} favourited your post', + 'reblog' => '{actor_username} shared your post', + 'follow' => '{actor_username} started following you', + 'no_notifications' => 'No notifications', + 'mark_all_as_read' => 'Mark all as read', ]; diff --git a/modules/Admin/Language/pl/Person.php b/modules/Admin/Language/pl/Person.php index 0386036c..baf67094 100644 --- a/modules/Admin/Language/pl/Person.php +++ b/modules/Admin/Language/pl/Person.php @@ -24,7 +24,7 @@ return [ 'form' => [ 'avatar' => 'Awatar', 'avatar_size_hint' => - 'Awatar musi być kwadratowy o szerokości i wysokości co najmniej 400 pikseli.', + 'Avatar must be squared and at least 400px wide and tall.', 'full_name' => 'Pełne imię i nazwisko', 'full_name_hint' => 'To jest pełne imię i nazwisko lub pseudonim osoby.', 'unique_name' => 'Unikalna nazwa', @@ -61,5 +61,5 @@ return [ 'submit_add' => 'Dodaj osobę(y)', 'remove' => 'Usuń', ], - 'credits' => 'Autorzy', + 'credits' => 'Kredyty', ]; diff --git a/modules/Admin/Language/pl/Platforms.php b/modules/Admin/Language/pl/Platforms.php index d6a97a84..82bb83e6 100644 --- a/modules/Admin/Language/pl/Platforms.php +++ b/modules/Admin/Language/pl/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Platformy podcastowe', - 'social' => 'Sieci społecznościowe', - 'funding' => 'Linki do finansowania', - ], - 'website' => 'Strona', + 'title' => 'Platformy', 'home_url' => 'Idź do strony {platformName}', - 'register' => 'Zarejestruj', 'submit_url' => 'Prześlij swój podcast na {platformName}', - 'your_link' => 'Twój link', - 'your_id' => [ - 'podcasting' => 'Twoje ID', - 'social' => 'Twoje ID', - 'funding' => 'Twoje CTA', - ], - 'your_cta' => 'Twoje Call To Action', 'visible' => 'Wyświetlać na stronie głównej podcastu?', 'on_embed' => 'Wyświetlać w osadzalnym odtwarzaczu?', 'remove' => 'Usuń {platformName}', diff --git a/modules/Admin/Language/pl/Podcast.php b/modules/Admin/Language/pl/Podcast.php index 7d91fe7f..5aa92ff8 100644 --- a/modules/Admin/Language/pl/Podcast.php +++ b/modules/Admin/Language/pl/Podcast.php @@ -13,58 +13,54 @@ return [ 'no_podcast' => 'Nie znaleziono podcastu!', 'create' => 'Stwórz podcast', 'import' => 'Importuj podcast', - 'all_imports' => 'Importy podcastów', 'new_episode' => 'Nowy Odcinek', 'view' => 'Wyświetl podcast', 'edit' => 'Edytuj podcast', - 'publish' => 'Opublikuj podcast', - 'publish_edit' => 'Edytuj publikację', + 'publish' => 'Publish podcast', + 'publish_edit' => 'Edit publication', 'delete' => 'Usuń podcast', 'see_episodes' => 'Zobacz odcinki', 'see_contributors' => 'Zobacz kontrybutorów', - 'monetization_other' => 'Inna monetyzacja', 'go_to_page' => 'Idź do strony', 'latest_episodes' => 'Najnowsze odcinki', 'see_all_episodes' => 'Zobacz wszystkie odcinki', - 'draft' => 'Wersja robocza', + 'draft' => 'Draft', 'messages' => [ - 'createSuccess' => 'Podcast został pomyślnie utworzony!', + 'createSuccess' => 'Podcast successfully created!', 'editSuccess' => 'Podcast został pomyślnie zaktualizowany!', 'importSuccess' => 'Podcast został pomyślnie zaimportowany!', - 'deleteSuccess' => 'Podcast @{podcast_handle} został pomyślnie usunięty!', - 'deletePodcastMediaError' => 'Nie udało się usunąć {type, select, - cover {okładki} - banner {baneru} - other {mediów} - } podcastu.', - 'deleteEpisodeMediaError' => 'Nie udało się usunąć {episode_slug} {type, select, - transcript {transkrypcji} - chapters {rozdziału} - image {okładki} + 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', + 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, + cover {cover} + banner {banner} + other {media} + }.', + 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, + transcript {transcript} + chapters {chapters} + image {cover} audio {audio} - other {mediów} - } odcinka.', - 'deletePodcastMediaFolderError' => 'Nie udało się usunąć folderu z mediami podcastu {folder_path}. Możesz go ręcznie usunąć ze swojego dysku.', - 'podcastFeedUpdateSuccess' => 'Zaktualizowano pomyślnie: {number_of_new_episodes, plural, - one {# odcinek został dodany} - few {# odcinki zostały dodane} - other {# odcinków zostało dodanych} - } do podcastu!', - 'podcastFeedUpToDate' => 'Podcast jest już aktualny.', - 'publishError' => 'Ten podcast jest już opublikowany lub zaplanowany do publikacji.', - 'publishEditError' => 'Ten podcast nie jest zaplanowany do publikacji.', - 'publishCancelSuccess' => 'Publikacja odcinka pomyślnie anulowana!', - 'scheduleDateError' => 'Zaplanowana data musi być ustawiona!', + other {media} + }.', + 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', + 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, + one {# episode was} + other {# episodes were} + } added to the podcast!', + 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', + 'publishError' => 'This podcast is either already published or scheduled for publication.', + 'publishEditError' => 'This podcast is not scheduled for publication.', + 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', + 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ 'identity_section_title' => 'Tożsamość podcastu', 'identity_section_subtitle' => 'Te pola pozwalają Ci zostać zauważonym.', - 'fediverse_section_title' => 'Tożsamość w Fediwersum', - 'cover' => 'Okładka podcastu', - 'cover_size_hint' => 'Okładka musi być kwadratowa oraz mieć co najmniej 1400px wysokości i szerokości.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Baner podcastu', - 'banner_size_hint' => 'Banner musi mieć proporcje 3:1 oraz mieć co najmniej 1500px szerokości.', + 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', 'banner_delete' => 'Usuń baner podcastu', 'title' => 'Tytuł', 'handle' => 'Uchwyt', @@ -75,17 +71,7 @@ return [ 'episodic' => 'Epizodyczny', 'episodic_hint' => 'Jeśli odcinki mają być pobierane bez określonej kolejności. Najnowsze odcinki zostaną zaprezentowane jako pierwsze.', 'serial' => 'Seryjny', - 'serial_hint' => 'Jeśli odcinki są przeznaczone do wykorzystania w kolejności sekwencyjnej. Odcinki będą wyświetlane w kolejności numerycznej.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium reprezentowane przez tag podcast:medium w RSS. Zmiana tego może mieć wpływ na wygląd w odtwarzaczach podcastów.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Opisuje kanał dla podcastu.', - 'music' => 'Muzyka', - 'music_hint' => 'Kanał muzyki zorganizowany w "album" z każdym elementem jako utwór w albumie.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specyficzne typy audio z jednym elementem na kanał lub gdzie każdy element reprezentuje rozdział książki.', + 'serial_hint' => 'Jeśli odcinki mają być pobierane w kolejności sekwencyjnej. Jako pierwsze zostaną zaprezentowane najstarsze odcinki.', ], 'description' => 'Opis', 'classification_section_title' => 'Klasyfikacja', @@ -110,11 +96,9 @@ return [ 'owner_email' => 'Email właściciela', 'owner_email_hint' => 'Będzie używany przez większość platform do weryfikacji własności podcastu. Widoczne w publicznym kanale RSS.', - 'is_owner_email_removed_from_feed' => 'Usuń email właściciela z publicznego kanału RSS', - 'is_owner_email_removed_from_feed_hint' => 'Może być konieczne tymczasowe odkrycie adresu e-mail, aby katalog mógł zweryfikować właściciela podcastu.', 'publisher' => 'Wydawca', 'publisher_hint' => - 'Grupa odpowiedzialna za stworzenie programu. Często odnosi się do firmy macierzystej lub sieci podcastów. To pole jest czasami oznaczone jako "Autor".', + 'Grupa odpowiedzialna za stworzenie programu. Często odnosi się do firmy macierzystej lub sieci podcastów. To pole jest czasami oznaczone jako ’Autor’.', 'copyright' => 'Prawa autorskie', 'location_section_title' => 'Lokalizacja', 'location_section_subtitle' => 'O jakim miejscu jest ten podcast?', @@ -124,13 +108,8 @@ return [ 'monetization_section_subtitle' => 'Zarabiaj dzięki swoim odbiorcom.', 'premium' => 'Premium', - 'premium_by_default' => 'Odcinki muszą być domyślnie ustawione jako premium', - 'premium_by_default_hint' => 'Odcinki podcastów będą domyślnie oznaczone jako premium. Nadal możesz ustawić niektóre odcinki, zwiastuny lub bonusy jako publiczne.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Odwiedź panel OP3 (link zewnętrzny)', - 'op3_hint' => 'Oceń swoje dane analityczne z OP3, otwartej i zaufanej usługi strony trzeciej. Udostępnij, weryfikuj i porównuj swoje dane analityczne za pomocą ekosystemu otwartego podcastingu.', - 'op3_enable' => 'Włącz usługę analityczną OP3', - 'op3_enable_hint' => 'Ze względów bezpieczeństwa dane analityczne odcinków premium nie będą udostępniane OP3.', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', 'payment_pointer' => 'Wskaźnik płatności do zarabiania w sieci', 'payment_pointer_hint' => 'To tutaj otrzymasz pieniądze dzięki Monetyzacji Internetowej', @@ -138,13 +117,12 @@ return [ 'advanced_section_subtitle' => 'Jeśli potrzebujesz tagów RSS, których Castopod nie obsługuje, ustaw je tutaj.', 'custom_rss' => 'Własne tagi RSS dla podcastu', - 'custom_rss_hint' => 'Zostanie wstawione w tagu ❬channel❭.', - 'verify_txt' => 'Weryfikacja własności TXT', - 'verify_txt_hint' => 'Zamiast polegać na e-mailu, niektóre usługi firm trzecich mogą potwierdzić twoje prawa własności podcastu, prosząc Cię o osadzenie tekstu weryfikacyjnego w twoim kanale.', - 'verify_txt_helper' => 'Ten tekst jest wstrzykiwany do znacznika .', + 'custom_rss_hint' => 'Zostaną wstawione w tagu ❬channel❭.', 'new_feed_url' => 'Nowy adres URL kanału', 'new_feed_url_hint' => 'Użyj tego pola, gdy przenosisz się do innej domeny lub platformy hostingowej podcastu. Domyślnie wartość jest ustawiona na bieżący adres URL RSS, jeśli podcast jest importowany.', - 'old_feed_url' => 'Stary URL kanału', + 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnerstwo', 'partner_id' => 'ID', 'partner_link_url' => 'Adres URL linku', @@ -152,9 +130,10 @@ return [ 'partner_id_hint' => 'Twój własny ID partnera', 'partner_link_url_hint' => 'Ogólny adres linku partnera', 'partner_image_url_hint' => 'Ogólny adres obrazu partnera', - 'block' => 'Odcinek powinien być ukryty w publicznych katalogach', + 'status_section_title' => 'Status', + 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => - 'Pokazywanie lub ukrywanie odcinka: przełączanie tej funkcji zapobiega pojawieniu się odcinka w Apple Podcasts, Google Podcasts, a także w aplikacjach innych firm, które pobierają z tych katalogów. (Niegwarantowane)', + 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', 'complete' => 'Podcast nie będzie miał nowych odcinków', 'lock' => 'Zapobiegaj kopiowaniu podcastu', 'lock_hint' => @@ -263,49 +242,49 @@ return [ 'hockey' => 'Hokej', 'rugby' => 'Rugby', 'running' => 'Bieg', - 'soccer' => 'Piłka nożna', + 'soccer' => 'Soccer', 'swimming' => 'Pływanie', 'tennis' => 'Tenis', 'volleyball' => 'Siatkówka', - 'wilderness' => 'Dzika przyroda', - 'wrestling' => 'Zapasy', - 'after_shows' => 'Po audycji', + 'wilderness' => 'Wilderness', + 'wrestling' => 'Wrestling', + 'after_shows' => 'After Shows', 'film_history' => 'Historia Filmu', 'film_interviews' => 'Wywiady filmowe', 'film_reviews' => 'Recenzje filmów', 'tv_reviews' => 'Recenzje telewizyjne', ], 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Powrót do panelu podcastów', - 'post' => 'Twój wpis ogłoszeniowy', + 'back_to_podcast_dashboard' => 'Back to podcast dashboard', + 'post' => 'Your announcement post', 'post_hint' => - "Napisz wiadomość, aby ogłosić publikację podcastu. Wiadomość będzie wyświetlana na stronie głównej podcastu.", - 'message_placeholder' => 'Napisz swoją wiadomość…', - 'submit' => 'Opublikuj', - 'publication_date' => 'Data publikacji', + "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", + 'message_placeholder' => 'Write your message…', + 'submit' => 'Publish', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Teraz', - 'schedule' => 'Zaplanuj', + 'now' => 'Now', + 'schedule' => 'Schedule', ], - 'scheduled_publication_date' => 'Planowana data publikacji', + 'scheduled_publication_date' => 'Scheduled publication date', 'scheduled_publication_date_hint' => - 'Możesz zaplanować wydanie odcinka, ustawiając przyszłą datę publikacji. To pole musi być sformatowane jako YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edytuj publikację', - 'cancel_publication' => 'Anuluj publikację', - 'message_warning' => 'Nie napisałeś wiadomości do swojego wpisu ogłoszeniowego!', - 'message_warning_hint' => 'Posiadanie wiadomości zwiększa zaangażowanie społeczne, co skutkuje lepszą widocznością Twojego podcastu.', - 'message_warning_submit' => 'Opublikuj mimo to', + 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', + 'message_warning' => 'You did not write a message for your announcement post!', + 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ - 'draft_mode' => 'tryb szkicu', - 'not_published' => 'Ten podcast nie został jeszcze opublikowany.', - 'scheduled' => 'Ten podcast jest zaplanowany do publikacji na {publication_date}.', + 'draft_mode' => 'draft mode', + 'not_published' => 'This podcast is not yet published.', + 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => - "Usunięcie podcastu spowoduje usunięcie wszystkich odcinków, plików multimedialnych, postów i analityk z nim związanych. Ta akcja jest nieodwracalna, nie będziesz w stanie odzyskać tego wszystkiego później.", - 'understand' => 'Rozumiem, chciałbym, aby podcast został trwale usunięty', - 'submit' => 'Usuń', + "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", + 'understand' => 'I understand, I want the podcast to be permanently deleted', + 'submit' => 'Delete', ], 'by' => 'Przez {publisher}', 'season' => 'Sezon {seasonNumber}', @@ -315,14 +294,12 @@ return [ 'no_episode' => 'Nie znaleziono odcinków!', 'follow' => 'Obserwuj', 'followers' => '{numberOfFollowers, plural, - one {# polubienie} - few {# polubienia} - other {# polubień} + one {# follower} + other {# followers} }', 'posts' => '{numberOfPosts, plural, - one {# osoba} - few {# osoby} - other {# osób} + one {# post} + other {# posts} }', 'activity' => 'Aktywność', 'episodes' => 'Odcinki', diff --git a/modules/Admin/Language/pl/PodcastImport.php b/modules/Admin/Language/pl/PodcastImport.php new file mode 100644 index 00000000..a68c6d0a --- /dev/null +++ b/modules/Admin/Language/pl/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'Podcast do zaimportowania', + 'old_podcast_section_subtitle' => + 'Upewnij się, że masz prawa do tego podcastu zanim go zaimportujesz. Kopiowanie i nadawanie podcastu bez odpowiednich praw jest piractwem i podlega ściganiu.', + 'imported_feed_url' => 'Adres URL kanału', + 'imported_feed_url_hint' => 'Kanał musi być w formacie xml lub rss.', + 'new_podcast_section_title' => 'Nowy podcast', + 'advanced_params_section_title' => 'Parametry zaawansowane', + 'advanced_params_section_subtitle' => + 'Zachowaj wartości domyślne jeśli nie masz pojęcia, do czego służą te pola.', + 'slug_field' => 'Pole używane do obliczenia slugu odcinka', + 'description_field' => + 'Pole źródłowe używane do opisu odcinka/notatek programu', + 'force_renumber' => 'Wymuś przenumerowanie odcinków', + 'force_renumber_hint' => + 'Użyj tego, jeśli Twój podcast nie ma numerów odcinków, ale chcesz je ustawić podczas importu.', + 'season_number' => 'Numer sezonu', + 'season_number_hint' => + 'Użyj tego, jeśli Twój podcast nie ma numeru sezonu, ale chcesz go ustawić podczas importu. W przeciwnym razie pozostaw pusty.', + 'max_episodes' => 'Maksymalna liczba odcinków do zaimportowania', + 'max_episodes_hint' => 'Pozostaw puste, aby zaimportować wszystkie odcinki', + 'lock_import' => + 'Ten kanał jest chroniony. Nie możesz go zaimportować. Jeśli jesteś jego właścicielem - usuń ochronę na platformie, z której pochodzi.', + 'submit' => 'Importuj podcast', +]; diff --git a/modules/Admin/Language/pl/PodcastNavigation.php b/modules/Admin/Language/pl/PodcastNavigation.php index ff8066e2..7f3327f1 100644 --- a/modules/Admin/Language/pl/PodcastNavigation.php +++ b/modules/Admin/Language/pl/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Idź do strony podcastu', - 'rss_feed' => 'Kanał RSS', 'dashboard' => 'Pulpit podcastu', 'podcast-view' => 'Początek', 'podcast-edit' => 'Edytuj podcast', 'podcast-persons-manage' => 'Zarządzaj osobami', - 'podcast-imports' => 'Importy podcastów', - 'podcast-imports-sync' => 'Synchronizuj kanały', 'episodes' => 'Odcinki', 'episode-list' => 'Wszystkie odcinki', 'episode-create' => 'Nowy odcinek', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Odtwarzacze', 'podcast-analytics-listening-time' => 'Czas odsłuchu', 'podcast-analytics-time-periods' => 'Okresy czasu', - 'monetization' => 'Monetyzacja', - 'subscription-list' => 'Wszystkie subskrypcje', - 'subscription-create' => 'Dodaj subskrypcję', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', 'contributors' => 'Kontrybutorzy', 'contributor-list' => 'Wszyscy kontrybutorzy', 'contributor-add' => 'Dodaj kontrybutora', - 'broadcast' => 'Transmisja', - 'platforms-podcasting' => 'Aplikacje podcastowe', + 'platforms' => 'Zewnętrzne platformy', + 'platforms-podcasting' => 'Platformy podcastingowe', 'platforms-social' => 'Sieci społecznościowe', - 'platforms-funding' => 'Linki do finansowania', - 'podcast-monetization-other' => 'Inne', + 'platforms-funding' => 'Finansowanie', ]; diff --git a/modules/Admin/Language/pl/Settings.php b/modules/Admin/Language/pl/Settings.php index ef20ebf1..09bcfde0 100644 --- a/modules/Admin/Language/pl/Settings.php +++ b/modules/Admin/Language/pl/Settings.php @@ -15,7 +15,7 @@ return [ 'site_icon' => 'Ikona witryny', 'site_icon_delete' => 'Usuń ikonę witryny', 'site_icon_hint' => 'Ikony witryny są widoczne na kartach przeglądarki, paskach zakładek oraz po dodaniu witryny jako skrótu na urządzeniach mobilnych.', - 'site_icon_helper' => 'Ikona musi być kwadratowa o szerokości i wysokości co najmniej 512 pikseli.', + 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', 'site_name' => 'Nazwa strony', 'site_description' => 'Opis strony', 'submit' => 'Zapisz', @@ -35,8 +35,8 @@ return [ 'reset_counts_helper' => 'Ta opcja zresetuje i ponownie obliczy wszystkie liczniki danych (liczbę obserwujących, wpisów, komentarzy, …).', 'rewrite_media' => 'Przepisz metadane multimediów', 'rewrite_media_helper' => 'Ta opcja usunie wszystkie zbędne pliki multimedialne i odtworzy je (obrazy, pliki audio, transkrypcje, rozdziały, …)', - 'rename_episodes_files' => 'Zmień nazwę plików audio odcinka', - 'rename_episodes_files_hint' => 'Ta opcja zmieni nazwę wszystkich odcinków plików audio na losowy ciąg znaków. Użyj tego, jeśli jeden z Twoich prywatnych odcinków został ujawniony, ponieważ to skutecznie go ukryje.', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', 'clear_cache' => 'Wyczyść całą pamięć podręczną', 'clear_cache_helper' => 'Ta opcja opróżni pamięć podręczną (cache) redis lub zapisywalne/buforowane pliki.', 'run' => 'Przeprowadź porządkowanie', @@ -48,7 +48,7 @@ return [ 'accent_section_subtitle' => 'Wybierz kolor, aby określić wygląd i styl wszystkich stron publicznych.', 'pine' => 'Sosna', 'crimson' => 'Karmazynowy', - 'amber' => 'Bursztyn', + 'amber' => 'bursztynowy', 'lake' => 'Jezioro', 'jacaranda' => 'Jacaranda', 'onyx' => 'Onyks', diff --git a/modules/Admin/Language/pl/Soundbite.php b/modules/Admin/Language/pl/Soundbite.php index 32fbc02b..97544f8d 100644 --- a/modules/Admin/Language/pl/Soundbite.php +++ b/modules/Admin/Language/pl/Soundbite.php @@ -20,7 +20,7 @@ return [ 'form' => [ 'title' => 'Nowa zajawka', 'soundbite_title' => 'Tytuł zajawki', - 'start_time' => 'Rozpocznij od', + 'start_time' => 'Rozpocznij w', 'duration' => 'Długość', 'submit' => 'Stwórz zajawkę', ], diff --git a/modules/Auth/Language/pl/User.php b/modules/Admin/Language/pl/User.php similarity index 74% rename from modules/Auth/Language/pl/User.php rename to modules/Admin/Language/pl/User.php index 69f2d96b..7db87b44 100644 --- a/modules/Auth/Language/pl/User.php +++ b/modules/Admin/Language/pl/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Edytuj role użytkownika {username}", + 'edit_roles' => "Edytuj role użytkownika {username}", + 'forcePassReset' => 'Wymuś resetowanie hasła', 'ban' => 'Zablokuj', 'unban' => 'Odblokuj', 'delete' => 'Usuń', @@ -18,7 +19,7 @@ return [ 'all_users' => 'Wszyscy użytkownicy', 'list' => [ 'user' => 'Użytkownik', - 'role' => 'Rola', + 'roles' => 'Role', 'banned' => 'Zablokowany?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Nazwa użytkownika', 'password' => 'Hasło', 'new_password' => 'Nowe hasło', - 'role' => 'Rola', 'roles' => 'Role', 'permissions' => 'Uprawnienia', 'submit_create' => 'Stwórz użytkownika', 'submit_edit' => 'Zapisz', 'submit_password_change' => 'Zmień!', ], - 'delete_form' => [ - 'title' => 'Usuń użytkownika {user}', - 'disclaimer' => - "Zamierzasz usunąć {user} na stałe. Nie będą już mogli uzyskać dostępu do obszaru administratora.", - 'understand' => 'Rozumiem, chcę trwale usunąć {user}', - 'submit' => 'Usuń', + 'roles' => [ + 'superadmin' => 'Superadministrator', ], 'messages' => [ 'createSuccess' => 'Pomyślnie utworzono użytkownika! {username} zostanie poproszony o zresetowanie hasła przy pierwszym uwierzytelnieniu.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "Role {username} zostały pomyślnie zaktualizowane.", + 'forcePassResetSuccess' => + '{username} zostanie poproszony o zresetowanie hasła przy następnej wizycie.', 'banSuccess' => '{username} został zablokowany.', 'unbanSuccess' => '{username} został odblokowany.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} jest superadministratorem, nie można po prostu zablokować superadministratora…', - 'deleteOwnerError' => - '{username} jest właścicielem instancji, nie można usunąć właściciela…', 'deleteSuperAdminError' => '{username} jest superadministratorem, nie można po prostu usunąć superadministratora…', 'deleteSuccess' => '{username} został usunięty.', diff --git a/modules/Admin/Language/pl/Validation.php b/modules/Admin/Language/pl/Validation.php index 258f7119..a71b5913 100644 --- a/modules/Admin/Language/pl/Validation.php +++ b/modules/Admin/Language/pl/Validation.php @@ -10,8 +10,9 @@ declare(strict_types=1); return [ 'min_dims' => - '{field} nie jest obrazem albo nie jest wystarczająco szeroki lub wysoki.', + '{field} nie jest obrazem, albo nie jest wystarczająco szeroki lub wysoki.', 'is_image_ratio' => - '{field} nie jest obrazem albo nie ma właściwych proporcji.', - 'is_json' => '{field} zawiera nieprawidłowy JSON.', + '{field} nie jest obrazem, albo nie ma właściwych proporcji.', + 'validate_url' => + 'Pole {field} musi być prawidłowym adresem URL (np. https://przyklad.com/).', ]; diff --git a/modules/Admin/Language/pl/VideoClip.php b/modules/Admin/Language/pl/VideoClip.php index 03453b0e..6ff09752 100644 --- a/modules/Admin/Language/pl/VideoClip.php +++ b/modules/Admin/Language/pl/VideoClip.php @@ -17,10 +17,10 @@ return [ 'queued_hint' => 'Klip czeka na przetworzenie.', 'pending' => 'oczekuje', 'pending_hint' => 'Klip zostanie wkrótce wygenerowany.', - 'running' => 'w toku', + 'running' => 'działanie', 'running_hint' => 'Klip jest generowany.', 'failed' => 'niepowodzenie', - 'failed_hint' => 'Nie można było wygenerować klipu: błąd skryptu.', + 'failed_hint' => 'Nie można wygenerować klipu: błąd skryptu.', 'passed' => 'powodzenie', 'passed_hint' => 'Klip został pomyślnie wygenerowany!', ], @@ -35,7 +35,7 @@ return [ 'delete' => 'Usuń klip', 'logs' => 'Dzienniki zadania', 'messages' => [ - 'alreadyExistingError' => 'Klip wideo, który próbujesz utworzyć, już istnieje!', + 'alreadyExistingError' => 'Klip wideo, który próbujesz utworzyć już istnieje!', 'addToQueueSuccess' => 'Klip wideo został dodany do kolejki i oczekuje na utworzenie!', 'deleteSuccess' => 'Klip wideo został pomyślnie usunięty!', ], @@ -51,11 +51,11 @@ return [ 'format' => [ 'label' => 'Wybierz format', 'landscape_hint' => 'W proporcji 16:9, filmy w orientacji poziomej są świetne do PeerTube, Youtube i Vimeo.', - 'portrait_hint' => 'W proporcji 9:16, filmy pionowe świetnie nadają się do TikTok, krótkich filmów na YouTube i Stories na Instagramie.', + 'portrait_hint' => 'W proporcji 9:16, filmy pionowe świetnie nadają się do TikTok, krótkich filmów na YouTube i historii na Instagramie.', 'squared_hint' => 'W proporcji 1:1, kwadratowe filmy są świetne dla Mastodon, Facebooka, Twittera i LinkedIn.', ], 'theme' => 'Wybierz motyw', - 'start_time' => 'Rozpocznij od', + 'start_time' => 'Rozpocznij w', 'duration' => 'Długość', 'trim_start' => 'Przytnij początek', 'trim_end' => 'Przytnij koniec', @@ -63,10 +63,10 @@ return [ ], 'requirements' => [ 'title' => 'Brakujące wymagania', - 'missing' => 'Brakuje wymaganych elementów. Upewnij się, że dodałeś wszystkie wymagane elementy, aby móc tworzyć wideo do tego odcinka!', + 'missing' => 'Brakuje wymagań. Upewnij się, że dodałeś wszystkie wymagane elementy, aby móc tworzyć wideo do tego odcinka!', 'ffmpeg' => 'FFmpeg', 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Biblioteka Freetype dla GD', + 'freetype' => 'Freetype library dla GD', 'transcript' => 'Plik z transkrypcją (.srt)', ], ]; diff --git a/modules/Admin/Language/pt-br/Breadcrumb.php b/modules/Admin/Language/pt-BR/Breadcrumb.php similarity index 75% rename from modules/Admin/Language/pt-br/Breadcrumb.php rename to modules/Admin/Language/pt-BR/Breadcrumb.php index 7ca40d76..028fb11c 100644 --- a/modules/Admin/Language/pt-br/Breadcrumb.php +++ b/modules/Admin/Language/pt-BR/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Início', 'podcasts' => 'podcasts', 'episodes' => 'episódios', - 'subscriptions' => 'assinaturas', + 'subscriptions' => 'subscriptions', 'contributors' => 'contribuidores', 'pages' => 'páginas', 'settings' => 'configurações', 'theme' => 'tema', - 'about' => 'sobre', 'add' => 'adicionar', 'new' => 'novo', 'edit' => 'editar', 'persons' => 'pessoas', 'publish' => 'publicar', 'publish-edit' => 'editar publicação', - 'publish-date-edit' => 'editar data de publicação', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'despublicar', 'delete' => 'excluir', - 'remove' => 'remover', 'fediverse' => 'fediverso', - 'blocked-actors' => 'atores bloqueados', - 'blocked-domains' => 'domínios bloqueados', + 'block-lists' => 'listas de bloqueio', 'users' => 'usuários', 'my-account' => 'minha conta', 'change-password' => 'alterar senha', - 'imports' => 'importações', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'importar feed', 'platforms' => 'plataformas', 'social' => 'redes sociais', 'funding' => 'financiamento', - 'monetization-other' => 'other monetization', 'analytics' => 'estatísticas', 'locations' => 'localizações', 'webpages' => 'páginas da web', @@ -52,6 +47,6 @@ return [ 'soundbites' => 'clipes de áudio', 'video-clips' => 'clipes de vídeo', 'embed' => 'player incorporável', - 'notifications' => 'notificações', - 'suspend' => 'suspender', + 'notifications' => 'notifications', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/pt-br/Charts.php b/modules/Admin/Language/pt-BR/Charts.php similarity index 96% rename from modules/Admin/Language/pt-br/Charts.php rename to modules/Admin/Language/pt-BR/Charts.php index 9a84d031..ff2e91d1 100644 --- a/modules/Admin/Language/pt-br/Charts.php +++ b/modules/Admin/Language/pt-BR/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Largura de banda usada diária (em MB)', 'total_storage_by_month' => 'Armazenamento mensal (em MB)', 'total_bandwidth_by_month' => 'Largura de banda usada mensalmente (em MB)', - 'total_bandwidth_by_month_limit' => 'Limitado a {totalBandwidth} por mês', ]; diff --git a/modules/Admin/Language/pt-br/Common.php b/modules/Admin/Language/pt-BR/Common.php similarity index 98% rename from modules/Admin/Language/pt-br/Common.php rename to modules/Admin/Language/pt-BR/Common.php index f82a5109..c323eef3 100644 --- a/modules/Admin/Language/pt-br/Common.php +++ b/modules/Admin/Language/pt-BR/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Enviar um arquivo', 'remote_url' => 'URL remota', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Reproduzir', diff --git a/modules/Auth/Language/pt-br/Contributor.php b/modules/Admin/Language/pt-BR/Contributor.php similarity index 72% rename from modules/Auth/Language/pt-br/Contributor.php rename to modules/Admin/Language/pt-BR/Contributor.php index 5dc72942..60329ef2 100644 --- a/modules/Auth/Language/pt-br/Contributor.php +++ b/modules/Admin/Language/pt-BR/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Adicionar contribuidor', 'submit_edit' => 'Atualizar cargo', ], - 'delete_form' => [ - 'title' => 'Remover {contributor}', - 'disclaimer' => - 'Você está prestes a remover {contributor} dos colaboradores. Eles não poderão mais acessar "{podcastTitle}".', - 'understand' => 'Eu entendo, eu desejo remover {contributor} de "{podcastTitle}"', - 'submit' => 'Remover', + 'roles' => [ + 'podcast_admin' => 'Administrador do podcast', ], 'messages' => [ - 'editSuccess' => 'Cargo alterado com sucesso!', - 'editOwnerError' => "Você não pode editar o dono do podcast!", 'removeOwnerError' => "Você não pode remover o dono do podcast!", 'removeSuccess' => 'Você removeu {username} com sucesso de {podcastTitle}', diff --git a/modules/Admin/Language/pt-br/Countries.php b/modules/Admin/Language/pt-BR/Countries.php similarity index 100% rename from modules/Admin/Language/pt-br/Countries.php rename to modules/Admin/Language/pt-BR/Countries.php diff --git a/modules/Admin/Language/pt-br/Dashboard.php b/modules/Admin/Language/pt-BR/Dashboard.php similarity index 100% rename from modules/Admin/Language/pt-br/Dashboard.php rename to modules/Admin/Language/pt-BR/Dashboard.php diff --git a/modules/Admin/Language/pt-br/Episode.php b/modules/Admin/Language/pt-BR/Episode.php similarity index 85% rename from modules/Admin/Language/pt-br/Episode.php rename to modules/Admin/Language/pt-BR/Episode.php index 427f9092..b89d4401 100644 --- a/modules/Admin/Language/pt-br/Episode.php +++ b/modules/Admin/Language/pt-BR/Episode.php @@ -22,17 +22,16 @@ return [ 'all_podcast_episodes' => 'Todos os episódios de podcast', 'back_to_podcast' => 'Voltar para o podcast', 'edit' => 'Editar', - 'preview' => 'Pré-visualizar', 'publish' => 'Publicar', 'publish_edit' => 'Editar publicação', - 'publish_date_edit' => 'Editar data de publicação', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Despublicar', 'publish_error' => 'O episódio já está publicado.', 'publish_edit_error' => 'O episódio já está publicado.', 'publish_cancel_error' => 'O episódio já está publicado.', - 'publish_date_edit_error' => 'Episódio ainda não foi publicado, você não pode editar a data de publicação dele.', - 'publish_date_edit_future_error' => 'A data de publicação do episódio só pode ser definida para data passada! Se você deseja reagendá-la, cancele a publicação primeiro.', - 'publish_date_edit_success' => 'A data de publicação do episódio foi atualizada com sucesso!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'O episódio não está publicado.', 'delete' => 'Excluir', 'go_to_page' => 'Ir para a página', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episódio', 'visibility' => 'Visibilidade', - 'downloads' => 'Downloads', 'comments' => 'Comentários', 'actions' => 'Ações', ], @@ -87,7 +85,7 @@ return [ image {capa} audio {áudio} other {mídia} - }arquivo {file_key}. Você pode removê-lo manualmente do seu disco.', + } {file_path}. Você pode removê-lo manualmente do seu disco.', 'sameSlugError' => 'Um episódio com o slug escolhido já existe.', ], 'form' => [ @@ -116,7 +114,7 @@ return [ 'bonus_hint' => 'Conteúdo extra para o podcast (por exemplo, informações nos bastidores ou entrevistas com o elenco) ou conteúdo promocional com outro podcast', ], 'premium_title' => 'Premium', - 'premium' => 'Episódio deve estar acessível apenas para assinantes premium', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ 'label' => 'Aviso aos pais', 'hint' => 'O episódio contém conteúdo explícito?', @@ -139,9 +137,9 @@ return [ 'location_name' => 'Nome ou endereço da localização', 'location_name_hint' => 'Esta pode ser uma localização real ou fictícia', 'transcript' => 'Transcrição (legendas / legendas ocultas)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Somente .srt são permitidos.', 'transcript_download' => 'Baixar transcrição', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Arquivo de transcrição (.srt)', 'transcript_remote_url' => 'URL remoto para transcrição', 'transcript_file_delete' => 'Excluir arquivo de transcrição', 'chapters' => 'Capítulos', @@ -185,13 +183,13 @@ return [ 'message_warning_submit' => 'Publicar mesmo assim', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nova data de publicação', - 'new_publication_date_hint' => 'Deve ser definido como uma data passada.', - 'submit' => 'Editar data de publicação', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "O cancelamento da publicação do episódio excluirá todos os comentários e publicações associados a ele e o removerá do feed RSS do podcast.", + "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", 'understand' => 'Eu entendo, eu quero despublicar o episódio', 'submit' => 'Despublicar', ], @@ -212,14 +210,4 @@ return [ 'light' => 'Claro', 'light-transparent' => 'Claro translúcido', ], - 'publication_status_banner' => [ - 'draft_mode' => 'modo rascunho', - 'text' => '{publication_status, select, - published {Esse episódio ainda não foi publicado.} - scheduled {Esse episódio está agendado para publicação em {publication_date}.} - with_podcast {Esse episódio será publicado ao mesmo tempo que o podcast. .} - other {Esse episódio ainda não foi publicado.} - }', - 'preview' => 'Pré-visualizar', - ], ]; diff --git a/modules/Admin/Language/pt-br/EpisodeNavigation.php b/modules/Admin/Language/pt-BR/EpisodeNavigation.php similarity index 100% rename from modules/Admin/Language/pt-br/EpisodeNavigation.php rename to modules/Admin/Language/pt-BR/EpisodeNavigation.php diff --git a/modules/Admin/Language/pt-br/Fediverse.php b/modules/Admin/Language/pt-BR/Fediverse.php similarity index 100% rename from modules/Admin/Language/pt-br/Fediverse.php rename to modules/Admin/Language/pt-BR/Fediverse.php diff --git a/modules/Admin/Language/pt-br/Home.php b/modules/Admin/Language/pt-BR/Home.php similarity index 100% rename from modules/Admin/Language/pt-br/Home.php rename to modules/Admin/Language/pt-BR/Home.php diff --git a/modules/Admin/Language/pt-br/Install.php b/modules/Admin/Language/pt-BR/Install.php similarity index 100% rename from modules/Admin/Language/pt-br/Install.php rename to modules/Admin/Language/pt-BR/Install.php diff --git a/modules/Auth/Language/pt-br/MyAccount.php b/modules/Admin/Language/pt-BR/MyAccount.php similarity index 100% rename from modules/Auth/Language/pt-br/MyAccount.php rename to modules/Admin/Language/pt-BR/MyAccount.php diff --git a/modules/Admin/Language/pt-br/Navigation.php b/modules/Admin/Language/pt-BR/Navigation.php similarity index 86% rename from modules/Admin/Language/pt-br/Navigation.php rename to modules/Admin/Language/pt-BR/Navigation.php index a5032c7c..c0e86154 100644 --- a/modules/Admin/Language/pt-br/Navigation.php +++ b/modules/Admin/Language/pt-BR/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Ativar/Desativar barra lateral', 'go_to_website' => 'Ir para o site', 'go_to_admin' => 'Ir para admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Painel de controle', 'admin' => 'Início', 'podcasts' => 'Podcasts', 'podcast-list' => 'Todos os podcasts', 'podcast-create' => 'Novo podcast', - 'all-podcast-imports' => 'Todos os importações de Podcast', - 'podcast-imports-add' => 'Importar um podcast', + 'podcast-import' => 'Importar um podcast', 'persons' => 'Pessoas', 'person-list' => 'Todas as pessoas', 'person-create' => 'Nova pessoa', @@ -35,7 +33,6 @@ return [ 'settings' => 'Confirgurações', 'settings-general' => 'Geral', 'settings-theme' => 'Tema', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'Minha conta', 'change-password' => 'Alterar senha', diff --git a/modules/Admin/Language/eu/Notifications.php b/modules/Admin/Language/pt-BR/Notifications.php similarity index 100% rename from modules/Admin/Language/eu/Notifications.php rename to modules/Admin/Language/pt-BR/Notifications.php diff --git a/modules/Admin/Language/pt-br/Page.php b/modules/Admin/Language/pt-BR/Page.php similarity index 100% rename from modules/Admin/Language/pt-br/Page.php rename to modules/Admin/Language/pt-BR/Page.php diff --git a/modules/Admin/Language/pt-br/Pager.php b/modules/Admin/Language/pt-BR/Pager.php similarity index 100% rename from modules/Admin/Language/pt-br/Pager.php rename to modules/Admin/Language/pt-BR/Pager.php diff --git a/modules/Admin/Language/pt-br/Person.php b/modules/Admin/Language/pt-BR/Person.php similarity index 100% rename from modules/Admin/Language/pt-br/Person.php rename to modules/Admin/Language/pt-BR/Person.php diff --git a/modules/Admin/Language/pt-br/Platforms.php b/modules/Admin/Language/pt-BR/Platforms.php similarity index 69% rename from modules/Admin/Language/pt-br/Platforms.php rename to modules/Admin/Language/pt-BR/Platforms.php index 0388f65f..c49bc8a2 100644 --- a/modules/Admin/Language/pt-br/Platforms.php +++ b/modules/Admin/Language/pt-BR/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Plataformas de podcasting', - 'social' => 'Redes sociais', - 'funding' => 'Links de financiamento', - ], - 'website' => 'Site', + 'title' => 'Plataformas', 'home_url' => 'Ir para o site {platformName}', - 'register' => 'Registrar', 'submit_url' => 'Enviar seu podcast para {platformName}', - 'your_link' => 'Seu link', - 'your_id' => [ - 'podcasting' => 'Seu ID', - 'social' => 'Seu ID', - 'funding' => 'Seu CTA', - ], - 'your_cta' => 'Sua chamada para ação', 'visible' => 'Mostrar na página inicial do podcast?', 'on_embed' => 'Mostrar no player incorporável?', 'remove' => 'Remover {platformName}', diff --git a/modules/Admin/Language/pt-br/Podcast.php b/modules/Admin/Language/pt-BR/Podcast.php similarity index 87% rename from modules/Admin/Language/pt-br/Podcast.php rename to modules/Admin/Language/pt-BR/Podcast.php index 2d9e8708..c7e30aa3 100644 --- a/modules/Admin/Language/pt-br/Podcast.php +++ b/modules/Admin/Language/pt-BR/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'Nenhum podcast encontrado!', 'create' => 'Criar podcast', 'import' => 'Importar podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'Novo Episódio', 'view' => 'Ver podcast', 'edit' => 'Editar podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Excluir podcast', 'see_episodes' => 'Ver episódios', 'see_contributors' => 'Ver contribuidores', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Ir para a página', 'latest_episodes' => 'Últimos episódios', 'see_all_episodes' => 'Ver todos os episódios', @@ -50,6 +48,7 @@ return [ other {# episódios foram adicionados} } ao podcast!', 'podcastFeedUpToDate' => 'O Podcast já está atualizado.', + 'podcastNotImported' => 'O Podcast não pôde ser atualizado pois não foi importado.', 'publishError' => 'Este podcast já está publicado ou agendado para publicação.', 'publishEditError' => 'Este podcast não está agendado para publicação.', 'publishCancelSuccess' => 'Publicação do Podcast cancelada com sucesso!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Identidade do podcast', 'identity_section_subtitle' => 'Esses campos permitem que você seja notado.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Capa do podcast', 'cover_size_hint' => 'A capa deve ser quadrada e ter pelo menos 1400px de largura e altura.', 'banner' => 'Banner do podcast', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episódico', 'episodic_hint' => 'Se os episódios são destinados a serem consumidos sem qualquer ordem específica. Os episódios mais recentes serão apresentados primeiro.', 'serial' => 'Serial', - 'serial_hint' => 'Se a intenção é que os episódios sejam consumidos em uma ordem sequencial. Episódios vão ser apresentados em uma ordem numérica.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'Se os episódios são destinados a serem consumidos em ordem sequencial. Os episódios mais antigos serão apresentados primeiro.', ], 'description' => 'Descrição', 'classification_section_title' => 'Classificação', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'E-mail do proprietário', 'owner_email_hint' => 'Será utilizado pela maioria das plataformas para verificar a propriedade do podcast. Visível no feed RSS público.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Editora', 'publisher_hint' => 'O grupo responsável pela criação do podcast. Muitas vezes se refere à empresa-mãe ou rede de um podcast. Este campo é por vezes rotulado como "Autor".', @@ -123,13 +108,8 @@ return [ 'monetization_section_subtitle' => 'Ganhe dinheiro graças à sua audiência.', 'premium' => 'Premium', - 'premium_by_default' => 'Episódios devem ser definidos como premium por padrão', + 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Ativar serviço de análise OP3', - 'op3_enable_hint' => 'Por razões de segurança, os dados de análise dos episódios premium não serão compartilhados com o OP3.', 'payment_pointer' => 'Endereço de pagamento (Payment Pointer) para web monetização', 'payment_pointer_hint' => 'Este é o seu lugar onde você receberá dinheiro graças à web monetização', @@ -138,12 +118,11 @@ return [ 'Se você precisa de tags RSS que Castopod não lida, defina-as aqui.', 'custom_rss' => 'Tags RSS personalizadas para o podcast', 'custom_rss_hint' => 'Isto será injetado dentro da tag ❬channel❭.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'Nova URL de feed', 'new_feed_url_hint' => 'Use este campo ao mover este podcast para outro domínio ou alterar hosts. Por padrão, este campo é preenchido com a URL do feed RSS atual se o podcast for importado.', 'old_feed_url' => 'URL de feed antigo', + 'update_feed' => 'Atualizar feed', + 'update_feed_tip' => 'Importar os últimos episódios deste podcast', 'partnership' => 'Parceria', 'partner_id' => 'ID', 'partner_link_url' => 'URL do link', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Seu próprio ID de parceiro', 'partner_link_url_hint' => 'O endereço genérico de link do parceiro', 'partner_image_url_hint' => 'O endereço genérico da imagem de parceiro', + 'status_section_title' => 'Status', 'block' => 'O podcast deve ser ocultado dos catálogos públicos', 'block_hint' => 'O status do podcast: ativar isso impede que o podcast inteiro apareça em Apple Podcasts, Google Podcasts e qualquer aplicativo de terceiros que extraia programas desses diretórios. (Não garantido)', diff --git a/modules/Admin/Language/pt-BR/PodcastImport.php b/modules/Admin/Language/pt-BR/PodcastImport.php new file mode 100644 index 00000000..97dd95c2 --- /dev/null +++ b/modules/Admin/Language/pt-BR/PodcastImport.php @@ -0,0 +1,37 @@ + + 'Este procedimento pode levar muito tempo. Como a versão atual não mostra nenhum progresso durante a execução, você não verá nada atualizado até que seja finalizado. Em caso de erro de tempo limite, aumente o valor de `max_execution_time`.', + 'old_podcast_section_title' => 'O podcast para importar', + 'old_podcast_section_subtitle' => + 'Certifique-se de possuir os direitos para esse podcast antes de importá-lo. Copiar e transmitir um podcast sem os direitos adequados é uma pirataria e corre o risco de ser processado.', + 'imported_feed_url' => 'URL do feed', + 'imported_feed_url_hint' => 'O feed deve estar no formato xml ou rss.', + 'new_podcast_section_title' => 'O novo podcast', + 'advanced_params_section_title' => 'Parâmetros avançados', + 'advanced_params_section_subtitle' => + 'Mantenha os valores padrão se você não tiver ideia do que os campos servem.', + 'slug_field' => 'Campo a ser usado para calcular o slug do episódio', + 'description_field' => + 'Campo de origem usado para descrição do episódio / mostrar notas', + 'force_renumber' => 'Forçar renumeração de episódios', + 'force_renumber_hint' => + 'Use isto se seu podcast não tem números de episódio, mas deseja configurá-los durante a importação.', + 'season_number' => 'Número da temporada', + 'season_number_hint' => + 'Use isto se o seu podcast não tem um número de temporada, mas deseja definir um durante a importação. Deixe em branco caso contrário.', + 'max_episodes' => 'Número máximo de episódios para importar', + 'max_episodes_hint' => 'Deixe em branco para importar todos os episódios', + 'lock_import' => + 'Este feed está protegido. Você não pode importá-lo. Se você é o proprietário, desproteja-o na plataforma de origem.', + 'submit' => 'Importar podcast', +]; diff --git a/modules/Admin/Language/pt-br/PodcastNavigation.php b/modules/Admin/Language/pt-BR/PodcastNavigation.php similarity index 73% rename from modules/Admin/Language/pt-br/PodcastNavigation.php rename to modules/Admin/Language/pt-BR/PodcastNavigation.php index 873954db..91e41655 100644 --- a/modules/Admin/Language/pt-br/PodcastNavigation.php +++ b/modules/Admin/Language/pt-BR/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Ir para página do podcast', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Painel do podcast', 'podcast-view' => 'Início', 'podcast-edit' => 'Editar podcast', 'podcast-persons-manage' => 'Gerenciar pessoas', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episódios', 'episode-list' => 'Todos os episódios', 'episode-create' => 'Novo episódio', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Tempo de escuta', 'podcast-analytics-time-periods' => 'Períodos de tempo', - 'monetization' => 'Monetization', - 'subscription-list' => 'Todas as assinaturas', - 'subscription-create' => 'Add subscription', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contribuidores', 'contributor-list' => 'Todos os contribuidores', 'contributor-add' => 'Adicionar contribuidor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'Plataformas externas', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Redes sociais', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Financiamento', ]; diff --git a/modules/Admin/Language/pt-br/Settings.php b/modules/Admin/Language/pt-BR/Settings.php similarity index 89% rename from modules/Admin/Language/pt-br/Settings.php rename to modules/Admin/Language/pt-BR/Settings.php index f326a094..84146001 100644 --- a/modules/Admin/Language/pt-br/Settings.php +++ b/modules/Admin/Language/pt-BR/Settings.php @@ -35,8 +35,8 @@ return [ 'reset_counts_helper' => 'Esta opção irá recalcular e redefinir todas as contagens de dados (número de seguidores, publicações, comentários, …).', 'rewrite_media' => 'Reescrever metadados de mídia', 'rewrite_media_helper' => 'Esta opção apagará todos os arquivos de mídia desnecessários e os recriará (imagens, arquivos de áudio, transcrições, capítulos, …)', - 'rename_episodes_files' => 'Renomear os arquivos de áudio de episódios', - 'rename_episodes_files_hint' => 'Esta opção irá renomear todos os episódios de arquivos de áudio para uma sequência aleatória de caracteres. Use isto se o link de seus episódios privados foi vazado, pois isso irá escondê-los efetivamente.', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', 'clear_cache' => 'Limpar todo o cache', 'clear_cache_helper' => 'Esta opção irá liberar o cache do redis ou arquivos graváveis/cache.', 'run' => 'Executar manutenção', diff --git a/modules/Admin/Language/pt-br/Soundbite.php b/modules/Admin/Language/pt-BR/Soundbite.php similarity index 100% rename from modules/Admin/Language/pt-br/Soundbite.php rename to modules/Admin/Language/pt-BR/Soundbite.php diff --git a/modules/Auth/Language/pt-br/User.php b/modules/Admin/Language/pt-BR/User.php similarity index 74% rename from modules/Auth/Language/pt-br/User.php rename to modules/Admin/Language/pt-BR/User.php index 945f8609..d42b9fc6 100644 --- a/modules/Auth/Language/pt-br/User.php +++ b/modules/Admin/Language/pt-BR/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "Edit {username}'s role", + 'edit_roles' => "Editar cargos de {username}", + 'forcePassReset' => 'Forçar redefinição da senha', 'ban' => 'Banir', 'unban' => 'Desbanir', 'delete' => 'Excluir', @@ -18,7 +19,7 @@ return [ 'all_users' => 'Todos os usuários', 'list' => [ 'user' => 'Usuário', - 'role' => 'Role', + 'roles' => 'Cargos', 'banned' => 'Banido?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => 'Nome de usuário', 'password' => 'Senha', 'new_password' => 'Nova Senha', - 'role' => 'Role', 'roles' => 'Cargos', 'permissions' => 'Permissões', 'submit_create' => 'Criar usuário', 'submit_edit' => 'Salvar', 'submit_password_change' => 'Alterar!', ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', + 'roles' => [ + 'superadmin' => 'Super admin', ], 'messages' => [ 'createSuccess' => 'Usuário criado com sucesso! {username} terá que alterar sua senha na primeira autenticação.', - 'roleEditSuccess' => + 'rolesEditSuccess' => "Cargos de {username} foram atualizados com sucesso.", + 'forcePassResetSuccess' => + '{username} precisará alterar sua senha na próxima visita.', 'banSuccess' => '{username} foi banido.', 'unbanSuccess' => '{username} foi desbanido.', 'editOwnerError' => '{username} is the instance owner, you cannot edit its roles.', 'banSuperAdminError' => '{username} é um super admin, não bloqueamos um super admin assim…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', 'deleteSuperAdminError' => '{username} é um super admin, você não exclui um super admin assim…', 'deleteSuccess' => '{username} foi excluído.', diff --git a/modules/Admin/Language/pt-br/Validation.php b/modules/Admin/Language/pt-BR/Validation.php similarity index 77% rename from modules/Admin/Language/pt-br/Validation.php rename to modules/Admin/Language/pt-BR/Validation.php index 1db87454..76ca2ae7 100644 --- a/modules/Admin/Language/pt-br/Validation.php +++ b/modules/Admin/Language/pt-BR/Validation.php @@ -13,5 +13,6 @@ return [ '{field} não é uma imagem ou não é largo ou alto o suficiente.', 'is_image_ratio' => '{field} não é uma imagem ou não tem a proporção correta.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'O campo {field} deve ser uma URL válida (por exemplo, https://examplo.com/).', ]; diff --git a/modules/Admin/Language/pt-br/VideoClip.php b/modules/Admin/Language/pt-BR/VideoClip.php similarity index 100% rename from modules/Admin/Language/pt-br/VideoClip.php rename to modules/Admin/Language/pt-BR/VideoClip.php diff --git a/modules/Admin/Language/pt-br/AboutCastopod.php b/modules/Admin/Language/pt-br/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/pt-br/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/pt-br/Notifications.php b/modules/Admin/Language/pt-br/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/pt-br/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/pt/AboutCastopod.php b/modules/Admin/Language/pt/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/pt/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/pt/Breadcrumb.php b/modules/Admin/Language/pt/Breadcrumb.php index 408c9f9f..f3269bfa 100644 --- a/modules/Admin/Language/pt/Breadcrumb.php +++ b/modules/Admin/Language/pt/Breadcrumb.php @@ -19,7 +19,6 @@ return [ 'pages' => 'pages', 'settings' => 'settings', 'theme' => 'theme', - 'about' => 'about', 'add' => 'add', 'new' => 'new', 'edit' => 'edit', @@ -29,19 +28,15 @@ return [ 'publish-date-edit' => 'edit publication date', 'unpublish' => 'unpublish', 'delete' => 'delete', - 'remove' => 'remove', 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'block lists', 'users' => 'users', 'my-account' => 'my account', 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'feed import', 'platforms' => 'platforms', 'social' => 'social networks', 'funding' => 'funding', - 'monetization-other' => 'other monetization', 'analytics' => 'analytics', 'locations' => 'locations', 'webpages' => 'web pages', diff --git a/modules/Admin/Language/pt/Charts.php b/modules/Admin/Language/pt/Charts.php index 6ede2510..4b33530e 100644 --- a/modules/Admin/Language/pt/Charts.php +++ b/modules/Admin/Language/pt/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/pt/Common.php b/modules/Admin/Language/pt/Common.php index 74addcf2..596c8bcd 100644 --- a/modules/Admin/Language/pt/Common.php +++ b/modules/Admin/Language/pt/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Upload a file', 'remote_url' => 'Remote URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Play', diff --git a/modules/Admin/Language/pt/Contributor.php b/modules/Admin/Language/pt/Contributor.php new file mode 100644 index 00000000..d0f3b93d --- /dev/null +++ b/modules/Admin/Language/pt/Contributor.php @@ -0,0 +1,41 @@ + 'Podcast contributors', + 'view' => "{username}'s contribution to {podcastTitle}", + 'add' => 'Add contributor', + 'add_contributor' => 'Add a contributor for {0}', + 'edit_role' => 'Update role for {0}', + 'edit' => 'Edit', + 'remove' => 'Remove', + 'list' => [ + 'username' => 'Username', + 'role' => 'Role', + ], + 'form' => [ + 'user' => 'User', + 'user_placeholder' => 'Select a user…', + 'role' => 'Role', + 'role_placeholder' => 'Select its role…', + 'submit_add' => 'Add contributor', + 'submit_edit' => 'Update role', + ], + 'roles' => [ + 'podcast_admin' => 'Podcast admin', + ], + 'messages' => [ + 'removeOwnerError' => "You can't remove the podcast owner!", + 'removeSuccess' => + 'You have successfully removed {username} from {podcastTitle}', + 'alreadyAddedError' => + "The contributor you're trying to add has already been added!", + ], +]; diff --git a/modules/Admin/Language/pt/Episode.php b/modules/Admin/Language/pt/Episode.php index 4fa846e3..91313a7c 100644 --- a/modules/Admin/Language/pt/Episode.php +++ b/modules/Admin/Language/pt/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'All podcast episodes', 'back_to_podcast' => 'Go back to podcast', 'edit' => 'Edit', - 'preview' => 'Preview', 'publish' => 'Publish', 'publish_edit' => 'Edit publication', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episode', 'visibility' => 'Visibility', - 'downloads' => 'Downloads', 'comments' => 'Comments', 'actions' => 'Actions', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'Chapters', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/it/MyAccount.php b/modules/Admin/Language/pt/MyAccount.php similarity index 100% rename from modules/Auth/Language/it/MyAccount.php rename to modules/Admin/Language/pt/MyAccount.php diff --git a/modules/Admin/Language/pt/Navigation.php b/modules/Admin/Language/pt/Navigation.php index f3ffb129..68d4609d 100644 --- a/modules/Admin/Language/pt/Navigation.php +++ b/modules/Admin/Language/pt/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Dashboard', 'admin' => 'Home', 'podcasts' => 'Podcasts', 'podcast-list' => 'All podcasts', 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Import a podcast', 'persons' => 'Persons', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -35,7 +33,6 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Admin/Language/pt/Platforms.php b/modules/Admin/Language/pt/Platforms.php index e161181c..ab17d599 100644 --- a/modules/Admin/Language/pt/Platforms.php +++ b/modules/Admin/Language/pt/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Platforms', 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', 'remove' => 'Remove {platformName}', diff --git a/modules/Admin/Language/pt/Podcast.php b/modules/Admin/Language/pt/Podcast.php index ff0daebc..426b763b 100644 --- a/modules/Admin/Language/pt/Podcast.php +++ b/modules/Admin/Language/pt/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No podcast found!', 'create' => 'Create podcast', 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'New Episode', 'view' => 'View podcast', 'edit' => 'Edit podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Delete podcast', 'see_episodes' => 'See episodes', 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Go to page', 'latest_episodes' => 'Latest episodes', 'see_all_episodes' => 'See all episodes', @@ -50,6 +48,7 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], 'description' => 'Description', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/pt/PodcastImport.php b/modules/Admin/Language/pt/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/pt/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/pt/PodcastNavigation.php b/modules/Admin/Language/pt/PodcastNavigation.php index bb777707..b4d7ddc0 100644 --- a/modules/Admin/Language/pt/PodcastNavigation.php +++ b/modules/Admin/Language/pt/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'Home', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodes', 'episode-list' => 'All episodes', 'episode-create' => 'New episode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/pt/User.php b/modules/Admin/Language/pt/User.php new file mode 100644 index 00000000..585d6799 --- /dev/null +++ b/modules/Admin/Language/pt/User.php @@ -0,0 +1,56 @@ + "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', + 'delete' => 'Delete', + 'create' => 'New user', + 'view' => "{username}'s info", + 'all_users' => 'All users', + 'list' => [ + 'user' => 'User', + 'roles' => 'Roles', + 'banned' => 'Banned?', + ], + 'form' => [ + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', + 'new_password' => 'New Password', + 'roles' => 'Roles', + 'permissions' => 'Permissions', + 'submit_create' => 'Create user', + 'submit_edit' => 'Save', + 'submit_password_change' => 'Change!', + ], + 'roles' => [ + 'superadmin' => 'Super admin', + ], + 'messages' => [ + 'createSuccess' => + 'User created successfully! {username} will be prompted with a password reset upon first authentication.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', + 'editOwnerError' => + '{username} is the instance owner, you cannot edit its roles.', + 'banSuperAdminError' => + '{username} is a superadmin, one does not simply ban a superadmin…', + 'deleteSuperAdminError' => + '{username} is a superadmin, one does not simply delete a superadmin…', + 'deleteSuccess' => '{username} has been deleted.', + ], +]; diff --git a/modules/Admin/Language/pt/Validation.php b/modules/Admin/Language/pt/Validation.php index f76c3163..750b1968 100644 --- a/modules/Admin/Language/pt/Validation.php +++ b/modules/Admin/Language/pt/Validation.php @@ -13,5 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/ro/AboutCastopod.php b/modules/Admin/Language/ro/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/ro/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/ro/Breadcrumb.php b/modules/Admin/Language/ro/Breadcrumb.php deleted file mode 100644 index 408c9f9f..00000000 --- a/modules/Admin/Language/ro/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb', - config('Admin') - ->gateway => 'Home', - 'podcasts' => 'podcasts', - 'episodes' => 'episodes', - 'subscriptions' => 'subscriptions', - 'contributors' => 'contributors', - 'pages' => 'pages', - 'settings' => 'settings', - 'theme' => 'theme', - 'about' => 'about', - 'add' => 'add', - 'new' => 'new', - 'edit' => 'edit', - 'persons' => 'persons', - 'publish' => 'publish', - 'publish-edit' => 'edit publication', - 'publish-date-edit' => 'edit publication date', - 'unpublish' => 'unpublish', - 'delete' => 'delete', - 'remove' => 'remove', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'users', - 'my-account' => 'my account', - 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforms', - 'social' => 'social networks', - 'funding' => 'funding', - 'monetization-other' => 'other monetization', - 'analytics' => 'analytics', - 'locations' => 'locations', - 'webpages' => 'web pages', - 'unique-listeners' => 'unique listeners', - 'players' => 'players', - 'listening-time' => 'listening time', - 'time-periods' => 'time periods', - 'soundbites' => 'soundbites', - 'video-clips' => 'video clips', - 'embed' => 'embeddable player', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/ro/Charts.php b/modules/Admin/Language/ro/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/ro/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/ro/Common.php b/modules/Admin/Language/ro/Common.php deleted file mode 100644 index 74addcf2..00000000 --- a/modules/Admin/Language/ro/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Loading…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/ro/Countries.php b/modules/Admin/Language/ro/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/ro/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/ro/Dashboard.php b/modules/Admin/Language/ro/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/ro/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/ro/Episode.php b/modules/Admin/Language/ro/Episode.php deleted file mode 100644 index 4fa846e3..00000000 --- a/modules/Admin/Language/ro/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episode is already published.', - 'publish_cancel_error' => 'Episode is already published.', - 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', - 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', - 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', - 'unpublish_error' => 'Episode is not published.', - 'delete' => 'Delete', - 'go_to_page' => 'Go to page', - 'create' => 'Add an episode', - 'publication_status' => [ - 'published' => 'Published', - 'with_podcast' => 'Published', - 'scheduled' => 'Scheduled', - 'not_published' => 'Not published', - ], - 'with_podcast_hint' => 'To be published at the same time as the podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Search for an episode', - 'clear' => 'Clear search', - 'submit' => 'Search', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episodes} - }', - 'episode' => 'Episode', - 'visibility' => 'Visibility', - 'downloads' => 'Downloads', - 'comments' => 'Comments', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'Episode has been successfully created!', - 'editSuccess' => 'Episode has been successfully updated!', - 'publishSuccess' => '{publication_status, select, - published {Episode successfully published!} - scheduled {Episode publication successfully scheduled!} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not published.} - }', - 'publishCancelSuccess' => 'Episode publication successfully cancelled!', - 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', - 'scheduleDateError' => 'Schedule date must be set!', - 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', - 'deleteSuccess' => 'Episode successfully deleted!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/ro/EpisodeNavigation.php b/modules/Admin/Language/ro/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/ro/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/ro/Fediverse.php b/modules/Admin/Language/ro/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/ro/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/ro/Home.php b/modules/Admin/Language/ro/Home.php deleted file mode 100644 index 3ff4c04d..00000000 --- a/modules/Admin/Language/ro/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found', -]; diff --git a/modules/Admin/Language/ro/Install.php b/modules/Admin/Language/ro/Install.php deleted file mode 100644 index 36e373a2..00000000 --- a/modules/Admin/Language/ro/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/ro/Navigation.php b/modules/Admin/Language/ro/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/ro/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/ro/Notifications.php b/modules/Admin/Language/ro/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/ro/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/ro/Page.php b/modules/Admin/Language/ro/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/ro/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/ro/Pager.php b/modules/Admin/Language/ro/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/ro/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/ro/Person.php b/modules/Admin/Language/ro/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/ro/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/ro/Platforms.php b/modules/Admin/Language/ro/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/ro/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/ro/Podcast.php b/modules/Admin/Language/ro/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/ro/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/ro/PodcastNavigation.php b/modules/Admin/Language/ro/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/ro/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/ro/Settings.php b/modules/Admin/Language/ro/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/ro/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/ro/Soundbite.php b/modules/Admin/Language/ro/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/ro/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/ro/Validation.php b/modules/Admin/Language/ro/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/ro/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/ro/VideoClip.php b/modules/Admin/Language/ro/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/ro/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/ru/AboutCastopod.php b/modules/Admin/Language/ru/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/ru/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/ru/Breadcrumb.php b/modules/Admin/Language/ru/Breadcrumb.php index 635a3806..33432cfd 100644 --- a/modules/Admin/Language/ru/Breadcrumb.php +++ b/modules/Admin/Language/ru/Breadcrumb.php @@ -19,7 +19,6 @@ return [ 'pages' => 'страниц', 'settings' => 'настройки', 'theme' => 'тема', - 'about' => 'about', 'add' => 'добавить', 'new' => 'новая', 'edit' => 'изменить', @@ -29,19 +28,15 @@ return [ 'publish-date-edit' => 'edit publication date', 'unpublish' => 'снять с публикации', 'delete' => 'удалить', - 'remove' => 'remove', 'fediverse' => 'Федивёрс', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', + 'block-lists' => 'список блокируемых', 'users' => 'пользователи', 'my-account' => 'мой аккаунт', 'change-password' => 'сменить пароль', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'импорт ленты', 'platforms' => 'платформы', 'social' => 'социальные сети', 'funding' => 'финансирование', - 'monetization-other' => 'other monetization', 'analytics' => 'аналитика', 'locations' => 'расположение', 'webpages' => 'веб-страницы', diff --git a/modules/Admin/Language/ru/Charts.php b/modules/Admin/Language/ru/Charts.php index 6ede2510..4b33530e 100644 --- a/modules/Admin/Language/ru/Charts.php +++ b/modules/Admin/Language/ru/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', 'total_storage_by_month' => 'Monthly storage (in MB)', 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', ]; diff --git a/modules/Admin/Language/ru/Common.php b/modules/Admin/Language/ru/Common.php index 74addcf2..596c8bcd 100644 --- a/modules/Admin/Language/ru/Common.php +++ b/modules/Admin/Language/ru/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Upload a file', 'remote_url' => 'Remote URL', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => 'Play', diff --git a/modules/Admin/Language/ru/Contributor.php b/modules/Admin/Language/ru/Contributor.php new file mode 100644 index 00000000..d0f3b93d --- /dev/null +++ b/modules/Admin/Language/ru/Contributor.php @@ -0,0 +1,41 @@ + 'Podcast contributors', + 'view' => "{username}'s contribution to {podcastTitle}", + 'add' => 'Add contributor', + 'add_contributor' => 'Add a contributor for {0}', + 'edit_role' => 'Update role for {0}', + 'edit' => 'Edit', + 'remove' => 'Remove', + 'list' => [ + 'username' => 'Username', + 'role' => 'Role', + ], + 'form' => [ + 'user' => 'User', + 'user_placeholder' => 'Select a user…', + 'role' => 'Role', + 'role_placeholder' => 'Select its role…', + 'submit_add' => 'Add contributor', + 'submit_edit' => 'Update role', + ], + 'roles' => [ + 'podcast_admin' => 'Podcast admin', + ], + 'messages' => [ + 'removeOwnerError' => "You can't remove the podcast owner!", + 'removeSuccess' => + 'You have successfully removed {username} from {podcastTitle}', + 'alreadyAddedError' => + "The contributor you're trying to add has already been added!", + ], +]; diff --git a/modules/Admin/Language/ru/Episode.php b/modules/Admin/Language/ru/Episode.php index 4fa846e3..91313a7c 100644 --- a/modules/Admin/Language/ru/Episode.php +++ b/modules/Admin/Language/ru/Episode.php @@ -22,7 +22,6 @@ return [ 'all_podcast_episodes' => 'All podcast episodes', 'back_to_podcast' => 'Go back to podcast', 'edit' => 'Edit', - 'preview' => 'Preview', 'publish' => 'Publish', 'publish_edit' => 'Edit publication', 'publish_date_edit' => 'Edit publication date', @@ -56,7 +55,6 @@ return [ }', 'episode' => 'Episode', 'visibility' => 'Visibility', - 'downloads' => 'Downloads', 'comments' => 'Comments', 'actions' => 'Actions', ], @@ -87,7 +85,7 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', + } file {file_path}. You may manually remove it from your disk.', 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real or fictional location', 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Only .srt are allowed.', 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Transcript file (.srt)', 'transcript_remote_url' => 'Remote url for transcript', 'transcript_file_delete' => 'Delete transcript file', 'chapters' => 'Chapters', @@ -212,14 +210,4 @@ return [ 'light' => 'Light', 'light-transparent' => 'Light transparent', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Auth/Language/ja/MyAccount.php b/modules/Admin/Language/ru/MyAccount.php similarity index 100% rename from modules/Auth/Language/ja/MyAccount.php rename to modules/Admin/Language/ru/MyAccount.php diff --git a/modules/Admin/Language/ru/Navigation.php b/modules/Admin/Language/ru/Navigation.php index f3ffb129..68d4609d 100644 --- a/modules/Admin/Language/ru/Navigation.php +++ b/modules/Admin/Language/ru/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Toggle sidebar', 'go_to_website' => 'Go to website', 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', 'dashboard' => 'Dashboard', 'admin' => 'Home', 'podcasts' => 'Podcasts', 'podcast-list' => 'All podcasts', 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', + 'podcast-import' => 'Import a podcast', 'persons' => 'Persons', 'person-list' => 'All persons', 'person-create' => 'New person', @@ -35,7 +33,6 @@ return [ 'settings' => 'Settings', 'settings-general' => 'General', 'settings-theme' => 'Theme', - 'admin-about' => 'About', 'account' => [ 'my-account' => 'My account', 'change-password' => 'Change password', diff --git a/modules/Admin/Language/ru/Platforms.php b/modules/Admin/Language/ru/Platforms.php index e161181c..ab17d599 100644 --- a/modules/Admin/Language/ru/Platforms.php +++ b/modules/Admin/Language/ru/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => 'Platforms', 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Display in podcast homepage?', 'on_embed' => 'Display on embeddable player?', 'remove' => 'Remove {platformName}', diff --git a/modules/Admin/Language/ru/Podcast.php b/modules/Admin/Language/ru/Podcast.php index ff0daebc..426b763b 100644 --- a/modules/Admin/Language/ru/Podcast.php +++ b/modules/Admin/Language/ru/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => 'No podcast found!', 'create' => 'Create podcast', 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', 'new_episode' => 'New Episode', 'view' => 'View podcast', 'edit' => 'Edit podcast', @@ -22,7 +21,6 @@ return [ 'delete' => 'Delete podcast', 'see_episodes' => 'See episodes', 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', 'go_to_page' => 'Go to page', 'latest_episodes' => 'Latest episodes', 'see_all_episodes' => 'See all episodes', @@ -50,6 +48,7 @@ return [ other {# episodes were} } added to the podcast!', 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => 'Podcast cover', 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', @@ -74,17 +71,7 @@ return [ 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], 'description' => 'Description', 'classification_section_title' => 'Classification', @@ -109,8 +96,6 @@ return [ 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', @@ -125,11 +110,6 @@ return [ 'premium' => 'Premium', 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,12 +118,11 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', 'partnership' => 'Partnership', 'partner_id' => 'ID', 'partner_link_url' => 'Link URL', @@ -151,6 +130,7 @@ return [ 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', diff --git a/modules/Admin/Language/ru/PodcastImport.php b/modules/Admin/Language/ru/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/ru/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/ru/PodcastNavigation.php b/modules/Admin/Language/ru/PodcastNavigation.php index bb777707..b4d7ddc0 100644 --- a/modules/Admin/Language/ru/PodcastNavigation.php +++ b/modules/Admin/Language/ru/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => 'Go to podcast page', - 'rss_feed' => 'RSS feed', 'dashboard' => 'Podcast dashboard', 'podcast-view' => 'Home', 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => 'Episodes', 'episode-list' => 'All episodes', 'episode-create' => 'New episode', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => 'Players', 'podcast-analytics-listening-time' => 'Listening time', 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', + 'premium' => 'Premium', 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', + 'subscription-add' => 'Add subscription', 'contributors' => 'Contributors', 'contributor-list' => 'All contributors', 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/ru/User.php b/modules/Admin/Language/ru/User.php new file mode 100644 index 00000000..585d6799 --- /dev/null +++ b/modules/Admin/Language/ru/User.php @@ -0,0 +1,56 @@ + "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', + 'delete' => 'Delete', + 'create' => 'New user', + 'view' => "{username}'s info", + 'all_users' => 'All users', + 'list' => [ + 'user' => 'User', + 'roles' => 'Roles', + 'banned' => 'Banned?', + ], + 'form' => [ + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', + 'new_password' => 'New Password', + 'roles' => 'Roles', + 'permissions' => 'Permissions', + 'submit_create' => 'Create user', + 'submit_edit' => 'Save', + 'submit_password_change' => 'Change!', + ], + 'roles' => [ + 'superadmin' => 'Super admin', + ], + 'messages' => [ + 'createSuccess' => + 'User created successfully! {username} will be prompted with a password reset upon first authentication.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', + 'editOwnerError' => + '{username} is the instance owner, you cannot edit its roles.', + 'banSuperAdminError' => + '{username} is a superadmin, one does not simply ban a superadmin…', + 'deleteSuperAdminError' => + '{username} is a superadmin, one does not simply delete a superadmin…', + 'deleteSuccess' => '{username} has been deleted.', + ], +]; diff --git a/modules/Admin/Language/ru/Validation.php b/modules/Admin/Language/ru/Validation.php index f76c3163..750b1968 100644 --- a/modules/Admin/Language/ru/Validation.php +++ b/modules/Admin/Language/ru/Validation.php @@ -13,5 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/sk/AboutCastopod.php b/modules/Admin/Language/sk/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/sk/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/sk/Breadcrumb.php b/modules/Admin/Language/sk/Breadcrumb.php index 26cf0b17..3c742281 100644 --- a/modules/Admin/Language/sk/Breadcrumb.php +++ b/modules/Admin/Language/sk/Breadcrumb.php @@ -14,34 +14,29 @@ return [ ->gateway => 'Úvod', 'podcasts' => 'podcasty', 'episodes' => 'časti', - 'subscriptions' => 'odbery', + 'subscriptions' => 'subscriptions', 'contributors' => 'prispievatelia', 'pages' => 'stránky', 'settings' => 'nastavenia', 'theme' => 'vzhľad', - 'about' => 'informácie', 'add' => 'pridať', 'new' => 'pridať', 'edit' => 'upraviť', 'persons' => 'osobnosti', 'publish' => 'zverejniť', 'publish-edit' => 'upraviť zverejnené', - 'publish-date-edit' => 'upraviť dátum publikovania', + 'publish-date-edit' => 'edit publication date', 'unpublish' => 'zrušiť zverejnenie', 'delete' => 'vymazať', - 'remove' => 'odstrániť', 'fediverse' => 'fediverse', - 'blocked-actors' => 'zablokovaní aktéri', - 'blocked-domains' => 'zablokované domény', + 'block-lists' => 'zoznamy blokovaných', 'users' => 'používatelia', 'my-account' => 'môj účet', 'change-password' => 'zmeniť heslo', - 'imports' => 'nahratia', - 'sync-feeds' => 'synchronize feeds', + 'import' => 'import kanála', 'platforms' => 'platformy', 'social' => 'sociálne siete', 'funding' => 'financovanie', - 'monetization-other' => 'other monetization', 'analytics' => 'analytika', 'locations' => 'miesta', 'webpages' => 'web stránky', @@ -53,5 +48,5 @@ return [ 'video-clips' => 'video klipy', 'embed' => 'vnorený', 'notifications' => 'oboznámenia', - 'suspend' => 'pozastaviť', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/sk/Charts.php b/modules/Admin/Language/sk/Charts.php index 17c1187e..8c29dff3 100644 --- a/modules/Admin/Language/sk/Charts.php +++ b/modules/Admin/Language/sk/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => 'Denný prenos údajov (v MB)', 'total_storage_by_month' => 'Mesačné úložisko (v MB)', 'total_bandwidth_by_month' => 'Mesačný prenos údajov (v MB)', - 'total_bandwidth_by_month_limit' => 'Obmedzený na {totalBandwidth} za mesiac', ]; diff --git a/modules/Admin/Language/sk/Common.php b/modules/Admin/Language/sk/Common.php index 584c05bf..9572c953 100644 --- a/modules/Admin/Language/sk/Common.php +++ b/modules/Admin/Language/sk/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => 'Nahrať súbor', 'remote_url' => 'Vzdialená adresa URL', - 'save' => 'Uložiť', ], 'play_episode_button' => [ 'play' => 'Prehrať', diff --git a/modules/Auth/Language/sk/Contributor.php b/modules/Admin/Language/sk/Contributor.php similarity index 73% rename from modules/Auth/Language/sk/Contributor.php rename to modules/Admin/Language/sk/Contributor.php index 2f251c38..3f0991fa 100644 --- a/modules/Auth/Language/sk/Contributor.php +++ b/modules/Admin/Language/sk/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => 'Pridať prispievateľa', 'submit_edit' => 'Aktualizovať rolu', ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', + 'roles' => [ + 'podcast_admin' => 'Správca podcastu', ], 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", 'removeOwnerError' => "Nemôžete odstrániť vlastníka podcastu!", 'removeSuccess' => 'Úspešne ste odstránili používateľa {username} z podcastu {podcastTitle}', diff --git a/modules/Admin/Language/sk/Countries.php b/modules/Admin/Language/sk/Countries.php index 8d5fa7cd..1077917e 100644 --- a/modules/Admin/Language/sk/Countries.php +++ b/modules/Admin/Language/sk/Countries.php @@ -13,7 +13,7 @@ declare(strict_types=1); return [ 'AD' => 'Andorra', 'AE' => 'Spojené Arabské Emiráty', - 'AF' => 'Afganistan', + 'AF' => 'Afghanistan', 'AG' => 'Antigua a Barbuda', 'AI' => 'Anguilla', 'AL' => 'Albánsko', @@ -25,7 +25,7 @@ return [ 'AT' => 'Rakúsko', 'AU' => 'Austrália', 'AW' => 'Aruba', - 'AX' => 'Ålandy', + 'AX' => 'Åland Islands', 'AZ' => 'Azerbajdžan', 'BA' => 'Bosna a Hercegovina', 'BB' => 'Barbados', @@ -33,41 +33,36 @@ return [ 'BE' => 'Belgicko', 'BF' => 'Burkina Faso', 'BG' => 'Bulharsko', - 'BH' => 'Bahrajn', + 'BH' => 'Bahrain', 'BI' => 'Burundi', 'BJ' => 'Benin', - 'BL' => 'Svätý Bartolomej', - 'BM' => 'Bermudy', - 'BN' => 'Brunejsko-Darussalamsky Štát', - 'BO' => 'Bolívia, plurinský štát', - 'BQ' => 'Bonaire, Sint Eustatius a Sabaj', - 'BR' => 'Brazília', - 'BS' => 'Bahamy', - 'BT' => 'Bhután', - 'BV' => 'Bouvetov ostrov', + 'BL' => 'Saint Barthélemy', + 'BM' => 'Bermuda', + 'BN' => 'Brunei Darussalam', + 'BO' => 'Bolivia, Plurinational State of', + 'BQ' => 'Bonaire, Sint Eustatius and Saba', + 'BR' => 'Brazil', + 'BS' => 'Bahamas', + 'BT' => 'Bhutan', + 'BV' => 'Bouvet Island', 'BW' => 'Botswana', - 'BY' => 'Bielorusko', + 'BY' => 'Belarus', 'BZ' => 'Belize', - 'CA' => 'Kanada', - 'CC' => 'Kokosové ostrovy', - 'CD' => ' -Bhután -Bouvetov ostrov -Bielorusko -Kokosové ostrovy -Konžská demokratická republika', - 'CF' => 'Stredoafrická republika', - 'CG' => 'Kongo', - 'CH' => 'Švajčiarsko', - 'CI' => "Pobrežie slonoviny", - 'CK' => 'Cookove ostrovy', - 'CL' => 'Čile', - 'CM' => 'Kamerun', + 'CA' => 'Canada', + 'CC' => 'Cocos (Keeling) Islands', + 'CD' => 'Congo, the Democratic Republic of the', + 'CF' => 'Central African Republic', + 'CG' => 'Congo', + 'CH' => 'Switzerland', + 'CI' => "Côte d'Ivoire", + 'CK' => 'Cook Islands', + 'CL' => 'Chile', + 'CM' => 'Cameroon', 'CN' => 'Čína', 'CO' => 'Kolumbia', 'CR' => 'Kostarika', 'CU' => 'Kuba', - 'CV' => 'Kapverdy', + 'CV' => 'Cape Verde', 'CW' => 'Curaçao', 'CX' => 'Vianočný Ostrov', 'CY' => 'Cyprus', @@ -75,7 +70,7 @@ Konžská demokratická republika', 'DE' => 'Nemecko', 'DJ' => 'Džibutsko', 'DK' => 'Dánsko', - 'DM' => 'Dominika', + 'DM' => 'Dominica', 'DO' => 'Dominikánska republika', 'DZ' => 'Alžírsko', 'EC' => 'Ekvádor', @@ -88,22 +83,22 @@ Konžská demokratická republika', 'FI' => 'Fínsko', 'FJ' => 'Fidži', 'FK' => 'Falklandské ostrovy (Malvíny)', - 'FM' => 'Mikronézia, federatívne štáty', + 'FM' => 'Micronesia, Federated States of', 'FO' => 'Faerské Ostrovy', 'FR' => 'Francúzsko', 'GA' => 'Gabon', 'GB' => 'Spojené Kráľovstvo', 'GD' => 'Grenada', 'GE' => 'Gruzínsko', - 'GF' => 'Francúzska Guayana', + 'GF' => 'French Guiana', 'GG' => 'Guernsey', 'GH' => 'Ghana', - 'GI' => 'Gibraltár', + 'GI' => 'Gibraltar', 'GL' => 'Grónsko', 'GM' => 'Gambia', 'GN' => 'Guinea', 'GP' => 'Guadeloupe', - 'GQ' => 'Rovníková Guinea', + 'GQ' => 'Equatorial Guinea', 'GR' => 'Grécko', 'GS' => 'Južná Georgia a Južné Sandwichove ostrovy', 'GT' => 'Guatemala', @@ -118,7 +113,7 @@ Konžská demokratická republika', 'HU' => 'Maďarsko', 'ID' => 'Indonézia', 'IE' => 'Írsko', - 'IL' => 'Izrael', + 'IL' => 'Israel', 'IM' => 'Ostrov Man', 'IN' => 'India', 'IO' => 'Britské indickooceánske územie', @@ -134,31 +129,18 @@ Konžská demokratická republika', 'KG' => 'Kirgizsko', 'KH' => 'Kambodža', 'KI' => 'Kiribati', - 'KM' => 'Komory', - 'KN' => 'Svätý Krištof a Nevis', - 'KP' => "Kórea, Demokratická ľudová republika", - 'KR' => 'Kórejská Republika', - 'KW' => 'Kuvajt', - 'KY' => 'Kajmanské ostrovy', - 'KZ' => 'Kazachstan', - 'LA' => "_03 slovutny poprad. mp3 -Kapverdy -Dominika -Mikronézia, federatívne štáty -Francúzska Guayana -Rovníková Guinea -Komory -Svätý Krištof a Nevis -Kórea, Demokratická ľudová republika -Kórejská Republika -Kuvajt -Kajmanské ostrovy -Kazachstan -Laoská ľudovodemokratická Republika", + 'KM' => 'Comoros', + 'KN' => 'Saint Kitts and Nevis', + 'KP' => "Korea, Democratic People's Republic of", + 'KR' => 'Korea, Republic of', + 'KW' => 'Kuwait', + 'KY' => 'Cayman Islands', + 'KZ' => 'Kazakhstan', + 'LA' => "Lao People's Democratic Republic", 'LB' => 'Libanon', 'LC' => 'Svätá Lucia', 'LI' => 'Lichtenštajnsko', - 'LK' => 'Srí Lanka', + 'LK' => 'Sri Lanka', 'LR' => 'Libéria', 'LS' => 'Lesotho', 'LT' => 'Litva', @@ -169,30 +151,30 @@ Laoská ľudovodemokratická Republika", 'MC' => 'Monako', 'MD' => 'Moldavská Republika', 'ME' => 'Čierna Hora', - 'MF' => 'Svätý Martin (Francúzska časť)', + 'MF' => 'Saint Martin (French part)', 'MG' => 'Madagaskar', - 'MH' => 'Marshallove ostrovy', + 'MH' => 'Marshall Islands', 'MK' => 'Macedónsko-Bývalá Juhoslovanská Republika', 'ML' => 'Mali', 'MM' => 'Mjanmarsko', 'MN' => 'Mongolsko', 'MO' => 'Macao', - 'MP' => 'Severné Mariány', - 'MQ' => 'Martinik', - 'MR' => 'Mauritánia', + 'MP' => 'Northern Mariana Islands', + 'MQ' => 'Martinique', + 'MR' => 'Mauritania', 'MS' => 'Montserrat', 'MT' => 'Malta', - 'MU' => 'Maurícius', - 'MV' => 'Maledivy', + 'MU' => 'Mauritius', + 'MV' => 'Maldives', 'MW' => 'Malawi', 'MX' => 'Mexiko', 'MY' => 'Malajzia', - 'MZ' => 'Mozambik', + 'MZ' => 'Mozambique', 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namíbia', + 'NA' => 'Namibia', 'NC' => 'Nová Kaledónia', 'NE' => 'Niger', - 'NF' => 'Ostrov Norfolk', + 'NF' => 'Norfolk Island', 'NG' => 'Nigéria', 'NI' => 'Nikaragua', 'NL' => 'Holandsko', @@ -204,64 +186,64 @@ Laoská ľudovodemokratická Republika", 'OM' => 'Omán', 'PA' => 'Panama', 'PE' => 'Peru', - 'PF' => 'Francúzska Polynézia', - 'PG' => 'Papua-Nová Guinea', - 'PH' => 'Filipíny', + 'PF' => 'French Polynesia', + 'PG' => 'Papua New Guinea', + 'PH' => 'Philippines', 'PK' => 'Pakistan', - 'PL' => 'Poľsko', - 'PM' => 'Svätý Peter a Michal', - 'PN' => 'Pitcairnove ostrovy', - 'PR' => 'Portoriko', + 'PL' => 'Poland', + 'PM' => 'Saint Pierre and Miquelon', + 'PN' => 'Pitcairn', + 'PR' => 'Puerto Rico', 'PS' => 'Palestínske okupované územia', 'PT' => 'Portugalsko', 'PW' => 'Palau', - 'PY' => 'Paraguaj', - 'QA' => 'Katar', + 'PY' => 'Paraguay', + 'QA' => 'Qatar', 'RE' => 'Réunion', - 'RO' => 'Rumunsko', - 'RS' => 'Srbsko', + 'RO' => 'Romania', + 'RS' => 'Serbia', 'RU' => 'Ruská Federácia', 'RW' => 'Rwanda', - 'SA' => 'Saudská Arábia', - 'SB' => 'Šalamúnove ostrovy', - 'SC' => 'Seychely', - 'SD' => 'Sudán', - 'SE' => 'Švédsko', - 'SG' => 'Singapur', - 'SH' => 'Svätá Helena, Ascension a Tristan da Cunha', + 'SA' => 'Saudi Arabia', + 'SB' => 'Solomon Islands', + 'SC' => 'Seychelles', + 'SD' => 'Sudan', + 'SE' => 'Sweden', + 'SG' => 'Singapore', + 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', 'SI' => 'Slovinsko', - 'SJ' => 'Špicbergy a Jan Mayen', + 'SJ' => 'Svalbard and Jan Mayen', 'SK' => 'Slovensko', 'SL' => 'Sierra Leone', - 'SM' => 'San Maríno', + 'SM' => 'San Marino', 'SN' => 'Senegal', 'SO' => 'Somálsko', - 'SR' => 'Surinam', + 'SR' => 'Suriname', 'SS' => 'Južný Sudán', - 'ST' => 'Svätý Tomáš a Principov ostrov', + 'ST' => 'Sao Tome and Principe', 'SV' => 'Salvádor', 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Sýrska Arabská Republika', + 'SY' => 'Syrian Arab Republic', 'SZ' => 'Svazijsko', 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Čad', + 'TD' => 'Chad', 'TF' => 'Francúzske južné územia', 'TG' => 'Togo', 'TH' => 'Thajsko', 'TJ' => 'Tadžikistan', 'TK' => 'Tokelau', - 'TL' => 'Východný Timor', + 'TL' => 'Timor-Leste', 'TM' => 'Turkménsko', 'TN' => 'Tunisko', 'TO' => 'Tonga', 'TR' => 'Turecko', - 'TT' => 'Trinidad a Tobago', + 'TT' => 'Trinidad and Tobago', 'TV' => 'Tuvalu', 'TW' => 'Taiwan, provincia Číny', 'TZ' => 'Tanzánia', 'UA' => 'Ukraina', 'UG' => 'Uganda', - 'UM' => 'Menšie Odľahlé Ostrovy Spojených Štátov', + 'UM' => 'United States Minor Outlying Islands', 'US' => 'Spojené Štáty', 'UY' => 'Uruguaj', 'UZ' => 'Uzbekistán', @@ -272,7 +254,7 @@ Laoská ľudovodemokratická Republika", 'VI' => 'Americké Panenské ostrovy', 'VN' => 'Vietnam', 'VU' => 'Vanuatu', - 'WF' => 'Wallis a Futuna', + 'WF' => 'Wallis and Futuna', 'WS' => 'Samoa', 'YE' => 'Jemen', 'YT' => 'Mayotte', diff --git a/modules/Admin/Language/sk/Episode.php b/modules/Admin/Language/sk/Episode.php index ac561290..a731c0e2 100644 --- a/modules/Admin/Language/sk/Episode.php +++ b/modules/Admin/Language/sk/Episode.php @@ -24,17 +24,16 @@ return [ 'all_podcast_episodes' => 'Všetky epizódy podcastu', 'back_to_podcast' => 'Späť na podcast', 'edit' => 'Upraviť', - 'preview' => 'Náhľad', 'publish' => 'Zverejniť', 'publish_edit' => 'Upraviť zverejnenie', - 'publish_date_edit' => 'Upraviť dátum zverejnenia', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => 'Zrušiť zverejnenie', 'publish_error' => 'Epizóda je už zverejnená.', 'publish_edit_error' => 'Epizóda je už zverejnená.', 'publish_cancel_error' => 'Epizóda je už zverejnená.', - 'publish_date_edit_error' => 'Epizóda zatiaľ nie je zverejnená, nie je možné upraviť dátum zverejnenia.', - 'publish_date_edit_future_error' => 'Dátum zverejnenia musí byť v minulosti! Ak si zverejnenie želáte naplánovať v budúcnosti, musíte ho najskôr zrušiť.', - 'publish_date_edit_success' => 'Dátum zverejnenia epizódy bol úspešne aktualizovaný!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => 'Epizóda nie je zverejnená.', 'delete' => 'Vymazať', 'go_to_page' => 'Prejsť na stránku', @@ -60,7 +59,6 @@ return [ }', 'episode' => 'Epizóda', 'visibility' => 'Viditeľnosť', - 'downloads' => 'Stiahnutia', 'comments' => 'Komentáre', 'actions' => 'Úkony', ], @@ -85,56 +83,56 @@ return [ audio {zvuk} other {médiá} }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', + 'deleteFileError' => 'Nepodarilo sa vymazať {type, select, + transcript {prepis} + chapters {kapitoly} + image {obrázok} + audio {zvuk} + other {médiá} + } súbor {file_path}. Môžete ho z disku odstrániť ručne.', 'sameSlugError' => 'Epizóda s takýmto trvalým odkazom už existuje.', ], 'form' => [ 'file_size_error' => - 'Súbor je príliš veľký! Maximálna povolená veľkosť je {0}. V konfigurácii Php zvýšte hodnoty nastavení `memory_limit`, `upload_max_filesize` a `post_max_size` a následne reštartujte web server, aby ste súbor mohli nahrať znovu.', + 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', 'audio_file' => 'Zvukový súbor', 'audio_file_hint' => 'Vyberte zvukový súbor .mp3, alebo .m4a.', 'info_section_title' => 'Informácie o časti', 'cover' => 'Obal k časti', 'cover_hint' => - 'Ak obrázok nepridáte, použije sa obrázok podcastu.', - 'cover_size_hint' => 'Obrázok musí byť štvorcový minimálny rozmer 1400px.', + 'If you do not set a cover, the podcast cover will be used instead.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'title' => 'Názov', 'title_hint' => - 'Má obsahovať jasný a výstižný názov. Nepridávajte čísla sérií a epizód.', + 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', 'permalink' => 'Trvalý odkaz', - 'season_number' => 'Séria', + 'season_number' => 'Season', 'episode_number' => 'Epizóda', 'type' => [ - 'label' => 'Typ', - 'full' => 'Celá epizóda', - 'full_hint' => '´Uplný obsah', - 'trailer' => 'Upútavka', - 'trailer_hint' => 'Krátky promočný úryvok obsahu, ktorý slúži ako ukážka podcastu', + 'label' => 'Type', + 'full' => 'Full', + 'full_hint' => 'Complete content (the episode)', + 'trailer' => 'Trailer', + 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', 'bonus' => 'Bonus', - 'bonus_hint' => 'Doplnkový obsah podcastu (Informácie zo zákulisia alebo rozhovor s účinkujúcimi) alebo upútavka iného podcastu', + 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', ], - 'premium_title' => 'Prémiový obsah', - 'premium' => 'Epizóda je prístupná len pre predplatiteľov prémiového obsahu', + 'premium_title' => 'Premium', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ - 'label' => 'Rodičovská kontrola', - 'hint' => 'Obsahuje epizóda explicitný obsah?', - 'undefined' => 'neuvedené', - 'clean' => 'Čisté', + 'label' => 'Parental advisory', + 'hint' => 'Does the episode contain explicit content?', + 'undefined' => 'undefined', + 'clean' => 'Clean', 'explicit' => 'Chúlostivé', ], - 'show_notes_section_title' => 'Poznámky epizódy', + 'show_notes_section_title' => 'Show notes', 'show_notes_section_subtitle' => - 'Maximálne 4000 znakov, buďte jasní a výstižní.', + 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', 'description' => 'Popis', - 'description_footer' => 'Päta popisu', + 'description_footer' => 'Description footer', 'description_footer_hint' => - 'Tento text je pridaný na koniec popisu každej epizódy, je vhodný napríklad na zverejnenie odkazov na sociálne siete.', + 'This text is added at the end of each episode description, it is a good place to input your social links for example.', 'additional_files_section_title' => 'Dodatočné súbory', 'additional_files_section_subtitle' => 'Tieto súbory sú určené na použitie s inými platformami s cieľom poslucháčom poskytovať bohačšiu skúsenosť. Pre viac informácií si pozrite {podcastNamespaceLink}.', @@ -143,9 +141,9 @@ return [ 'location_name' => 'Názov oblasti alebo adresa', 'location_name_hint' => 'Môže to byť skutočné alebo vymyslené miesto', 'transcript' => 'Prepis (titulky / skryté titulky)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => 'Povolené sú len súbory .srt.', 'transcript_download' => 'Stiahnuť prepis', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => 'Súbor s prepisom (.srt)', 'transcript_remote_url' => 'Vzdialená adresa Url s prepisom', 'transcript_file_delete' => 'Vymazať súbor s prepisom', 'chapters' => 'Kapitoly', @@ -189,13 +187,13 @@ return [ 'message_warning_submit' => 'Napriek tomu zverejniť', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nový dátum zverejnenia', - 'new_publication_date_hint' => 'Musí byť dátum v minulosti.', - 'submit' => 'Upraviť dátum zverejnenia', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "Zrušenie zverejnenia odstráni všetky pridružené príspevky a komentáre a odstráni epizódu z kanála RSS.", + "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", 'understand' => 'Rozumiem, chcem zrušiť zverejnenie epizódy', 'submit' => 'Zrušiť zverejnenie', ], @@ -212,18 +210,8 @@ return [ 'clipboard_iframe' => 'Skopírovať kód prehrávača do schránky', 'clipboard_url' => 'Skopírovať adresu do schránky', 'dark' => 'Tmavý', - 'dark-transparent' => 'Tmavý priehľadný', - 'light' => 'Svetlý', - 'light-transparent' => 'Svetlý priehľadný', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'konceptový režim', - 'text' => '{publication_status, select, - published {Táto epizóda ešte nieje zverejnená.} - scheduled {Táto epizóda je naplánovaná na zverejnenie {publication_date}.} - with_podcast {Táto epizóda bude zverejnená zarovno s podcastom.} - other {Táto epizóda ešte nieje zverejnená.} - }', - 'preview' => 'Náhľad', + 'dark-transparent' => 'Dark transparent', + 'light' => 'Light', + 'light-transparent' => 'Light transparent', ], ]; diff --git a/modules/Admin/Language/sk/EpisodeNavigation.php b/modules/Admin/Language/sk/EpisodeNavigation.php index 8414aebe..d60ef396 100644 --- a/modules/Admin/Language/sk/EpisodeNavigation.php +++ b/modules/Admin/Language/sk/EpisodeNavigation.php @@ -10,14 +10,14 @@ declare(strict_types=1); return [ 'go_to_page' => 'Zobraziť stránku časti', - 'dashboard' => 'Nástenka epizódy', + 'dashboard' => 'Episode dashboard', 'episode-view' => 'Domov', 'episode-edit' => 'Upraviť časť', - 'episode-persons-manage' => 'Spravovať osobnosti', + 'episode-persons-manage' => 'Manage persons', 'embed-add' => 'Vnorený prehrávač', 'clips' => 'Klipy', - 'video-clips-list' => 'Video klipy', - 'video-clips-create' => 'Nový video klip', - 'soundbites-list' => 'Zvukové ukážky', - 'soundbites-create' => 'Nová zvučka', + 'video-clips-list' => 'Video clips', + 'video-clips-create' => 'New video clip', + 'soundbites-list' => 'Soundbites', + 'soundbites-create' => 'New soundbite', ]; diff --git a/modules/Admin/Language/sk/Fediverse.php b/modules/Admin/Language/sk/Fediverse.php index 69cf2fb5..1a5e0a27 100644 --- a/modules/Admin/Language/sk/Fediverse.php +++ b/modules/Admin/Language/sk/Fediverse.php @@ -11,22 +11,22 @@ declare(strict_types=1); return [ 'messages' => [ 'actorNotFound' => 'Účet nieje možné nájsť!', - 'blockActorSuccess' => '{actor} bol/i zablokovaný!', - 'unblockActorSuccess' => 'Aktér bol odblokovaný!', - 'blockDomainSuccess' => '{domain} bola zablokovaná!', - 'unblockDomainSuccess' => '{domain} bola odblokovaná!', + 'blockActorSuccess' => '{actor} has been blocked!', + 'unblockActorSuccess' => 'Actor has been unblocked!', + 'blockDomainSuccess' => '{domain} has been blocked!', + 'unblockDomainSuccess' => '{domain} has been unblocked!', ], - 'blocked_actors' => 'Blokované účty', + 'blocked_actors' => 'Zablokované účty', 'blocked_domains' => 'Zablokované domény', 'block_lists_form' => [ 'handle' => 'Account handle', 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Názov domény', - 'submit' => 'Blokovať!', + 'domain' => 'Domain name', + 'submit' => 'Block!', ], 'list' => [ 'actor' => 'Účet', - 'domain' => 'Názov domény', - 'unblock' => 'Odblokovať', + 'domain' => 'Domain name', + 'unblock' => 'Unblock', ], ]; diff --git a/modules/Admin/Language/sk/Install.php b/modules/Admin/Language/sk/Install.php index c9669cdf..6282e10b 100644 --- a/modules/Admin/Language/sk/Install.php +++ b/modules/Admin/Language/sk/Install.php @@ -13,8 +13,8 @@ return [ 'manual_config_subtitle' => 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ - 'instance_config' => 'Nastavenie inštancie', - 'hostname' => 'Názov hostiteľa', + 'instance_config' => 'Instance configuration', + 'hostname' => 'Hostname', 'media_base_url' => 'Media base URL', 'media_base_url_hint' => 'If you use a CDN and/or an external analytics service, you may set them here.', @@ -24,17 +24,17 @@ return [ 'auth_gateway' => 'Auth gateway', 'auth_gateway_hint' => 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Nastavenie databázy', + 'database_config' => 'Database configuration', 'database_config_hint' => 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Server databázy', - 'db_name' => 'Názov databázy', - 'db_username' => 'Prihlasovacie meno do databázy', - 'db_password' => 'Heslo databázy', - 'db_prefix' => 'Prefix databázy', + 'db_hostname' => 'Database hostname', + 'db_name' => 'Database name', + 'db_username' => 'Database username', + 'db_password' => 'Database password', + 'db_prefix' => 'Database prefix', 'db_prefix_hint' => "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Nastavenie cache', + 'cache_config' => 'Cache configuration', 'cache_config_hint' => 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', 'cache_handler' => 'Obslužný mechanizmus vyrovnávacej pamäte', diff --git a/modules/Auth/Language/sk/MyAccount.php b/modules/Admin/Language/sk/MyAccount.php similarity index 100% rename from modules/Auth/Language/sk/MyAccount.php rename to modules/Admin/Language/sk/MyAccount.php diff --git a/modules/Admin/Language/sk/Navigation.php b/modules/Admin/Language/sk/Navigation.php index 2183aec0..f2c9e53a 100644 --- a/modules/Admin/Language/sk/Navigation.php +++ b/modules/Admin/Language/sk/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => 'Prepnúť postranný panel', 'go_to_website' => 'Prejsť na webstránku', 'go_to_admin' => 'Spravovať', - 'not-authorized' => 'Neautorizovaný', 'dashboard' => 'Nástenka', 'admin' => 'Úvod', 'podcasts' => 'Podcasty', 'podcast-list' => 'Všetky podcasty', 'podcast-create' => 'Nový podcast', - 'all-podcast-imports' => 'Všetky nahrané podcasty', - 'podcast-imports-add' => 'Importovať podcast', + 'podcast-import' => 'Importovať podcast', 'persons' => 'Osobnosti', 'person-list' => 'Všetky osobnosti', 'person-create' => 'Nová osobnosť', @@ -35,7 +33,6 @@ return [ 'settings' => 'Nastavenia', 'settings-general' => 'Všeobecné', 'settings-theme' => 'Vzhľad', - 'admin-about' => 'O aplikácii', 'account' => [ 'my-account' => 'Môj účet', 'change-password' => 'Zmeniť heslo', diff --git a/modules/Admin/Language/sk/Page.php b/modules/Admin/Language/sk/Page.php index 9b2fa2e6..72892ebf 100644 --- a/modules/Admin/Language/sk/Page.php +++ b/modules/Admin/Language/sk/Page.php @@ -15,16 +15,16 @@ return [ 'create' => 'Nová stránka', 'go_to_page' => 'Prejsť na stránku', 'edit' => 'Upraviť stránku', - 'delete' => 'Vymazať stránku', + 'delete' => 'Delete page', 'form' => [ - 'title' => 'Názov', - 'permalink' => 'Trvalý odkaz', - 'content' => 'Obsah', - 'submit_create' => 'Vytvoriť stránku', - 'submit_edit' => 'Uložiť', + 'title' => 'Title', + 'permalink' => 'Permalink', + 'content' => 'Content', + 'submit_create' => 'Create page', + 'submit_edit' => 'Save', ], 'messages' => [ - 'createSuccess' => 'Stránka “{pageTitle}” bola úspešne vytvorená!', - 'editSuccess' => 'Stránka bola úspešne aktualizovaná!', + 'createSuccess' => 'The page “{pageTitle}” was created successfully!', + 'editSuccess' => 'The page was successfully updated!', ], ]; diff --git a/modules/Admin/Language/sk/Pager.php b/modules/Admin/Language/sk/Pager.php index 43b98de4..e25ee638 100644 --- a/modules/Admin/Language/sk/Pager.php +++ b/modules/Admin/Language/sk/Pager.php @@ -9,13 +9,13 @@ declare(strict_types=1); */ return [ - 'pageNavigation' => 'Navigácia stránky', - 'first' => 'Prvá', - 'previous' => 'Predošlá', - 'next' => 'Ďalšia', - 'last' => 'Posledná', - 'older' => 'Staršia', - 'newer' => 'Novšia', + 'pageNavigation' => 'Page navigation', + 'first' => 'First', + 'previous' => 'Previous', + 'next' => 'Next', + 'last' => 'Last', + 'older' => 'Older', + 'newer' => 'Newer', 'invalidTemplate' => '{0} is not a valid Pager template.', 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', ]; diff --git a/modules/Admin/Language/sk/Person.php b/modules/Admin/Language/sk/Person.php index 9c523798..5ce1e02f 100644 --- a/modules/Admin/Language/sk/Person.php +++ b/modules/Admin/Language/sk/Person.php @@ -9,49 +9,49 @@ declare(strict_types=1); */ return [ - 'persons' => 'Osobnosti', - 'all_persons' => 'Všetky osobnosti', - 'no_person' => 'Nikto nenájdený!', - 'create' => 'Vytvoriť osobnosť', - 'view' => 'Ukázať osobnosť', - 'edit' => 'Upraviť osobnosť', - 'delete' => 'Vymazať osobnosť', + 'persons' => 'Persons', + 'all_persons' => 'All persons', + 'no_person' => 'Nobody found!', + 'create' => 'Create a person', + 'view' => 'View person', + 'edit' => 'Edit person', + 'delete' => 'Delete person', 'messages' => [ 'createSuccess' => 'Person has been successfully created!', 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Osobnosť bol/a odstránená!', + 'deleteSuccess' => 'Person has been removed!', ], 'form' => [ 'avatar' => 'Avatar', 'avatar_size_hint' => - 'Obrázok musí byť štvorcový a minimálne 400px široký a vysoký.', - 'full_name' => 'Celé meno', + 'Avatar must be squared and at least 400px wide and tall.', + 'full_name' => 'Full name', 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unikátne meno', - 'unique_name_hint' => 'Použité pre URL odkazy', - 'information_url' => 'Informačná URL adresa', + 'unique_name' => 'Unique name', + 'unique_name_hint' => 'Used for URLs', + 'information_url' => 'Information URL', 'information_url_hint' => 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Vytvoriť osobnosť', - 'submit_edit' => 'Uložiť osobnosť', + 'submit_create' => 'Create person', + 'submit_edit' => 'Save person', ], 'podcast_form' => [ - 'title' => 'Spravovať osobnosti', - 'add_section_title' => 'Pridať osobnosti k tomuto podcastu', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this podcast', 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Osobnosti', + 'persons' => 'Persons', 'persons_hint' => - 'Môžete vybrať jednu, alebo viac osôb s tou istou rolou. Najprv musíte osobnosti vytvoriť.', - 'roles' => 'Úlohy', + 'You may select one or several persons with the same roles. You need to create the persons first.', + 'roles' => 'Roles', 'roles_hint' => - 'Pre osobu môžete vybrať žiadnu, jednu, alebo viac rolí.', - 'submit_add' => 'Pridať osob(y)', - 'remove' => 'Odstrániť', + 'You may select none, one or several roles for a person.', + 'submit_add' => 'Add person(s)', + 'remove' => 'Remove', ], 'episode_form' => [ 'title' => 'Spravovať osobnosti', - 'add_section_title' => 'Pridať osobnosti k tejto epizóde', - 'add_section_subtitle' => 'Môžete vybrať viacero osôb a rolí.', + 'add_section_title' => 'Add persons to this episode', + 'add_section_subtitle' => 'You may pick several persons and roles.', 'persons' => 'Osobnosti', 'persons_hint' => 'Môžete vybrať jednu alebo viac osôb s tou istou rolou. Najprv by ste mali osobnosti vytvoriť.', diff --git a/modules/Admin/Language/sk/Platforms.php b/modules/Admin/Language/sk/Platforms.php index cc0bd289..678bdcbf 100644 --- a/modules/Admin/Language/sk/Platforms.php +++ b/modules/Admin/Language/sk/Platforms.php @@ -9,26 +9,13 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcastové platformy', - 'social' => 'Sociálne siete', - 'funding' => 'Funding links', - ], - 'website' => 'Webová stránka', + 'title' => 'Platformy', 'home_url' => 'Prejsť na stránku {platformName}', - 'register' => 'Registrovať', 'submit_url' => 'Uverejniť podcast na platforme {platformName}', - 'your_link' => 'Váš odkaz', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => 'Zobraziť na úvodnej stránke podcastu?', 'on_embed' => 'Zobraziť na vnorenom prehrávači?', 'remove' => 'Remove {platformName}', - 'submit' => 'Uložiť', + 'submit' => 'Save', 'messages' => [ 'updateSuccess' => 'Platform links have been successfully updated!', 'removeLinkSuccess' => 'The platform link has been removed.', diff --git a/modules/Admin/Language/sk/Podcast.php b/modules/Admin/Language/sk/Podcast.php index 9e630c09..5e65da72 100644 --- a/modules/Admin/Language/sk/Podcast.php +++ b/modules/Admin/Language/sk/Podcast.php @@ -9,26 +9,24 @@ declare(strict_types=1); */ return [ - 'all_podcasts' => 'Všetky podcasty', - 'no_podcast' => 'Žiadny podcast nenájdený!', - 'create' => 'Vytvoriť podcast', - 'import' => 'Importovať podcast', - 'all_imports' => 'Podcast imports', + 'all_podcasts' => 'All podcasts', + 'no_podcast' => 'No podcast found!', + 'create' => 'Create podcast', + 'import' => 'Import podcast', 'new_episode' => 'Nová časť', - 'view' => 'Zobraziť podcast', - 'edit' => 'Upraviť podcast', - 'publish' => 'Zverejniť podcast', - 'publish_edit' => 'Upraviť zverejnené', - 'delete' => 'Vymazať podcast', - 'see_episodes' => 'Ukázať časti', - 'see_contributors' => 'Pozrieť prispievateľov', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Prejsť na stránku', + 'view' => 'View podcast', + 'edit' => 'Edit podcast', + 'publish' => 'Publish podcast', + 'publish_edit' => 'Edit publication', + 'delete' => 'Delete podcast', + 'see_episodes' => 'See episodes', + 'see_contributors' => 'See contributors', + 'go_to_page' => 'Go to page', 'latest_episodes' => 'Posledné časti', 'see_all_episodes' => 'Pozrieť všetky časti', - 'draft' => 'Koncept', + 'draft' => 'Draft', 'messages' => [ - 'createSuccess' => 'Podcast úspešne vytvorený!', + 'createSuccess' => 'Podcast successfully created!', 'editSuccess' => 'Podcast has been successfully updated!', 'importSuccess' => 'Podcast has been successfully imported!', 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', @@ -49,87 +47,69 @@ return [ one {# episode was} other {# episodes were} } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast už je aktualizovaný.', + 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', 'publishError' => 'This podcast is either already published or scheduled for publication.', 'publishEditError' => 'This podcast is not scheduled for publication.', 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ - 'identity_section_title' => 'Identita podcastu', + 'identity_section_title' => 'Podcast identity', 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Identita vo Fediverse', - - 'cover' => 'Obal podcastu', - 'cover_size_hint' => 'Obrázok musí byť štvorcový a minimálne 1400px široký a vysoký.', + 'cover' => 'Podcast cover', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', 'banner_delete' => 'Delete podcast banner', - 'title' => 'Názov', + 'title' => 'Title', 'handle' => 'Handle', 'handle_hint' => 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', 'type' => [ - 'label' => 'Typ', - 'episodic' => 'Epizodický', + 'label' => 'Type', + 'episodic' => 'Episodic', 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Popis', - 'classification_section_title' => 'Zaradenie', + 'description' => 'Description', + 'classification_section_title' => 'Classification', 'classification_section_subtitle' => 'These fields will impact your audience and competition.', - 'language' => 'Jazyk', - 'category' => 'Kategória', - 'category_placeholder' => 'Vybrať kategóriu…', - 'other_categories' => 'Ostatné kategórie', + 'language' => 'Language', + 'category' => 'Category', + 'category_placeholder' => 'Select a category…', + 'other_categories' => 'Other categories', 'parental_advisory' => [ 'label' => 'Parental advisory', - 'hint' => 'Obsahuje explicitný obsah?', - 'undefined' => 'neuvedené', - 'clean' => 'Čistá', - 'explicit' => 'Chúlostivé', + 'hint' => 'Does it contain explicit content?', + 'undefined' => 'undefined', + 'clean' => 'Clean', + 'explicit' => 'Explicit', ], - 'author_section_title' => 'Autor', - 'author_section_subtitle' => 'Kto spravuje tento podcast?', - 'owner_name' => 'Meno vlastníka', + 'author_section_title' => 'Author', + 'author_section_subtitle' => 'Who is managing the podcast?', + 'owner_name' => 'Owner name', 'owner_name_hint' => 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Email vlastníka', + 'owner_email' => 'Owner email', 'owner_email_hint' => 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Vydavateľ', + 'publisher' => 'Publisher', 'publisher_hint' => 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Autorské práva', - 'location_section_title' => 'Umiestnenie', - 'location_section_subtitle' => 'O akom mieste/oblasti je tento podcast?', - 'location_name' => 'Názov oblasti, alebo adresa', + 'copyright' => 'Copyright', + 'location_section_title' => 'Location', + 'location_section_subtitle' => 'What place is this podcast about?', + 'location_name' => 'Location name or address', 'location_name_hint' => 'This can be a real place or fictional', 'monetization_section_title' => 'Monetization', 'monetization_section_subtitle' => 'Earn money thanks to your audience.', - 'premium' => 'Prémiový obsah', - 'premium_by_default' => 'Epizódy musia byť predvolene nastavené ako prémiové', + 'premium' => 'Premium', + 'premium_by_default' => 'Episodes must be set as premium by default', 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => 'This is your where you will receive money thanks to Web Monetization', @@ -138,19 +118,19 @@ return [ 'If you need RSS tags that Castopod does not handle, set them here.', 'custom_rss' => 'Custom RSS tags for the podcast', 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', 'new_feed_url' => 'New feed URL', 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnerstvo', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', + 'partnership' => 'Partnership', 'partner_id' => 'ID', - 'partner_link_url' => 'URL adresa odkazu', - 'partner_image_url' => 'URL adresa obrázka', + 'partner_link_url' => 'Link URL', + 'partner_image_url' => 'Image URL', 'partner_id_hint' => 'Your own partner ID', 'partner_link_url_hint' => 'The generic partner link address', 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', @@ -158,161 +138,161 @@ return [ 'lock' => 'Prevent podcast from being copied', 'lock_hint' => 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Vytvoriť podcast', - 'submit_edit' => 'Uložiť podcast', + 'submit_create' => 'Create podcast', + 'submit_edit' => 'Save podcast', ], 'category_options' => [ - 'uncategorized' => 'nezaradený', - 'arts' => 'Umenia', - 'business' => 'Podnikanie', - 'comedy' => 'Komédia', - 'education' => 'Vzdelanie', - 'fiction' => 'Fikcia', - 'government' => 'Štátna správa', - 'health_and_fitness' => 'Zdravie a fitnes', - 'history' => 'História', + 'uncategorized' => 'uncategorized', + 'arts' => 'Arts', + 'business' => 'Business', + 'comedy' => 'Comedy', + 'education' => 'Education', + 'fiction' => 'Fiction', + 'government' => 'Government', + 'health_and_fitness' => 'Health & Fitness', + 'history' => 'History', 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Voľný čas', - 'music' => 'Hudba', - 'news' => 'Správy', + 'leisure' => 'Leisure', + 'music' => 'Music', + 'news' => 'News', 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Veda', - 'society_and_culture' => 'Spoločnosť a kultúra', - 'sports' => 'Športy', - 'technology' => 'Technológia', - 'true_crime' => 'Skutočné krimi', + 'science' => 'Science', + 'society_and_culture' => 'Society & Culture', + 'sports' => 'Sports', + 'technology' => 'Technology', + 'true_crime' => 'True Crime', 'tv_and_film' => 'TV & Film', - 'books' => 'Knihy', - 'design' => 'Dizajn', + 'books' => 'Books', + 'design' => 'Design', 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Jedlo', - 'performing_arts' => 'Divadelné umenie', - 'visual_arts' => 'Vizuálni umelci', - 'careers' => 'Kariéra', - 'entrepreneurship' => 'Podnikateľský', - 'investing' => 'Investičný', - 'management' => 'Manažment', + 'food' => 'Food', + 'performing_arts' => 'Performing Arts', + 'visual_arts' => 'Visual Arts', + 'careers' => 'Careers', + 'entrepreneurship' => 'Entrepreneurship', + 'investing' => 'Investing', + 'management' => 'Management', 'marketing' => 'Marketing', - 'non_profit' => 'Neziskový', - 'comedy_interviews' => 'Komediálne rozhovory', + 'non_profit' => 'Non-Profit', + 'comedy_interviews' => 'Comedy Interviews', 'improv' => 'Improv', 'stand_up' => 'Stand-Up', - 'courses' => 'Kurzy', - 'how_to' => 'Ako na to', - 'language_learning' => 'Učenie jazykov', - 'self_improvement' => 'Sebazdokonaľovanie', + 'courses' => 'Courses', + 'how_to' => 'How To', + 'language_learning' => 'Language Learning', + 'self_improvement' => 'Self-Improvement', 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Dráma', - 'science_fiction' => 'Vedecko-fantastické', + 'drama' => 'Drama', + 'science_fiction' => 'Science Fiction', 'alternative_health' => 'Alternative Health', 'fitness' => 'Fitness', - 'medicine' => 'Medicínsky', - 'mental_health' => 'Duševné zdravie', + 'medicine' => 'Medicine', + 'mental_health' => 'Mental Health', 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexualita', - 'education_for_kids' => 'Vzdelávanie pre deti', - 'parenting' => 'Rodičovstvo', + 'sexuality' => 'Sexuality', + 'education_for_kids' => 'Education for Kids', + 'parenting' => 'Parenting', 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Príbehy pre deti', + 'stories_for_kids' => 'Stories for Kids', 'animation_and_manga' => 'Animation & Manga', 'automotive' => 'Automotive', 'aviation' => 'Aviation', 'crafts' => 'Crafts', - 'games' => 'Hry', - 'hobbies' => 'Záľuby', + 'games' => 'Games', + 'hobbies' => 'Hobbies', 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Videohry', + 'video_games' => 'Video Games', 'music_commentary' => 'Music Commentary', - 'music_history' => 'Hudobná história', - 'music_interviews' => 'Hudobné rozhovory', + 'music_history' => 'Music History', + 'music_interviews' => 'Music Interviews', 'business_news' => 'Business News', - 'daily_news' => 'Denné správy', + 'daily_news' => 'Daily News', 'entertainment_news' => 'Entertainment News', 'news_commentary' => 'News Commentary', - 'politics' => 'Politika', - 'sports_news' => 'Športové správy', - 'tech_news' => 'Technologické novinky', + 'politics' => 'Politics', + 'sports_news' => 'Sports News', + 'tech_news' => 'Tech News', 'buddhism' => 'Buddhism', - 'christianity' => 'Kresťanstvo', - 'hinduism' => 'Hinduizmus', + 'christianity' => 'Christianity', + 'hinduism' => 'Hinduism', 'islam' => 'Islam', 'judaism' => 'Judaism', - 'religion' => 'Náboženstvo', - 'spirituality' => 'Duchovno', - 'astronomy' => 'Astronómia', - 'chemistry' => 'Chémia', + 'religion' => 'Religion', + 'spirituality' => 'Spirituality', + 'astronomy' => 'Astronomy', + 'chemistry' => 'Chemistry', 'earth_sciences' => 'Earth Sciences', 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Matematické', + 'mathematics' => 'Mathematics', 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Príroda', - 'physics' => 'Fyzika', - 'social_sciences' => 'Sociálne vedy', - 'documentary' => 'Dokumentárny', + 'nature' => 'Nature', + 'physics' => 'Physics', + 'social_sciences' => 'Social Sciences', + 'documentary' => 'Documentary', 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Filozofia', + 'philosophy' => 'Philosophy', 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Vzťahy', - 'baseball' => 'Bejzbal', + 'relationships' => 'Relationships', + 'baseball' => 'Baseball', 'basketball' => 'Basketball', 'cricket' => 'Cricket', 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Futbal', + 'football' => 'Football', 'golf' => 'Golf', 'hockey' => 'Hockey', 'rugby' => 'Rugby', 'running' => 'Running', - 'soccer' => 'Futbal', - 'swimming' => 'Plávanie', - 'tennis' => 'Tenis', - 'volleyball' => 'Volejbal', - 'wilderness' => 'Divočina', - 'wrestling' => 'Zápasnícky', + 'soccer' => 'Soccer', + 'swimming' => 'Swimming', + 'tennis' => 'Tennis', + 'volleyball' => 'Volleyball', + 'wilderness' => 'Wilderness', + 'wrestling' => 'Wrestling', 'after_shows' => 'After Shows', - 'film_history' => 'Filmová história', - 'film_interviews' => 'Filmové rozhovory', - 'film_reviews' => 'Filmové recenzie', - 'tv_reviews' => 'TV recenzie', + 'film_history' => 'Film History', + 'film_interviews' => 'Film Interviews', + 'film_reviews' => 'Film Reviews', + 'tv_reviews' => 'TV Reviews', ], 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Späť na podcastovú nástenku', - 'post' => 'Váš oznamovací príspevok', + 'back_to_podcast_dashboard' => 'Back to podcast dashboard', + 'post' => 'Your announcement post', 'post_hint' => "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Napíšte vašu správu…', - 'submit' => 'Zverejniť', - 'publication_date' => 'Dátum zverejnenia', + 'message_placeholder' => 'Write your message…', + 'submit' => 'Publish', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Hneď teraz', - 'schedule' => 'Naplánovať', + 'now' => 'Now', + 'schedule' => 'Schedule', ], - 'scheduled_publication_date' => 'Dátum plánovaného zverejnenia', + 'scheduled_publication_date' => 'Scheduled publication date', 'scheduled_publication_date_hint' => 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Upraviť zverejnenie', - 'cancel_publication' => 'Zrušiť zverejnenie', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', 'message_warning' => 'You did not write a message for your announcement post!', 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Napriek tomu zverejniť', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ - 'draft_mode' => 'konceptový režim', - 'not_published' => 'Tento podcast ešte nieje zverejnený.', + 'draft_mode' => 'draft mode', + 'not_published' => 'This podcast is not yet published.', 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Vymazať', + 'submit' => 'Delete', ], - 'by' => 'Od {publisher}', + 'by' => 'By {publisher}', 'season' => 'Season {seasonNumber}', 'list_of_episodes_year' => '{year} episodes ({episodeCount})', 'list_of_episodes_season' => 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'Žiadna epizóda nenájdená!', - 'follow' => 'Nasledovať', + 'no_episode' => 'No episode found!', + 'follow' => 'Follow', 'followers' => '{numberOfFollowers, plural, one {# follower} other {# followers} @@ -321,10 +301,10 @@ return [ one {# post} other {# posts} }', - 'activity' => 'Aktivita', - 'episodes' => 'Časti', - 'sponsor' => 'Sponzor', - 'funding_links' => 'Odkazy na financovanie {podcastTitle}', - 'find_on' => 'Nájsť {podcastTitle} na', - 'listen_on' => 'Počúvajte na', + 'activity' => 'Activity', + 'episodes' => 'Episodes', + 'sponsor' => 'Sponsor', + 'funding_links' => 'Funding links for {podcastTitle}', + 'find_on' => 'Find {podcastTitle} on', + 'listen_on' => 'Listen on', ]; diff --git a/modules/Admin/Language/sk/PodcastImport.php b/modules/Admin/Language/sk/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/sk/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/sk/PodcastNavigation.php b/modules/Admin/Language/sk/PodcastNavigation.php index f90c67a2..b4d7ddc0 100644 --- a/modules/Admin/Language/sk/PodcastNavigation.php +++ b/modules/Admin/Language/sk/PodcastNavigation.php @@ -9,34 +9,30 @@ declare(strict_types=1); */ return [ - 'go_to_page' => 'Ísť na stránku podcastu', - 'rss_feed' => 'RSS kanál', + 'go_to_page' => 'Go to podcast page', 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Úvod', - 'podcast-edit' => 'Upraviť podcast', + 'podcast-view' => 'Home', + 'podcast-edit' => 'Edit podcast', 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Nahrané podcasty', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Časti', - 'episode-list' => 'Všetky časti', - 'episode-create' => 'Nová časť', + 'episodes' => 'Episodes', + 'episode-list' => 'All episodes', + 'episode-create' => 'New episode', 'analytics' => 'Analytics', 'podcast-analytics' => 'Audience overview', 'podcast-analytics-webpages' => 'Web pages visits', 'podcast-analytics-locations' => 'Locations', 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Prehrávače', - 'podcast-analytics-listening-time' => 'Čas počúvania', - 'podcast-analytics-time-periods' => 'Časové úseky', - 'monetization' => 'Monetization', - 'subscription-list' => 'Všetky odbery', - 'subscription-create' => 'Pridať odber', - 'contributors' => 'Prispievatelia', - 'contributor-list' => 'Všetci prispievatelia', - 'contributor-add' => 'Pridať prispievateľa', - 'broadcast' => 'Vysielanie', - 'platforms-podcasting' => 'Podcastové aplikácie', - 'platforms-social' => 'Sociálne siete', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'podcast-analytics-players' => 'Players', + 'podcast-analytics-listening-time' => 'Listening time', + 'podcast-analytics-time-periods' => 'Time periods', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', + 'contributors' => 'Contributors', + 'contributor-list' => 'All contributors', + 'contributor-add' => 'Add contributor', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', + 'platforms-social' => 'Social networks', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/sk/Settings.php b/modules/Admin/Language/sk/Settings.php index 63441b6a..4a70dcba 100644 --- a/modules/Admin/Language/sk/Settings.php +++ b/modules/Admin/Language/sk/Settings.php @@ -9,21 +9,21 @@ declare(strict_types=1); */ return [ - 'title' => 'Všeobecné nastavenia', + 'title' => 'General settings', 'instance' => [ - 'title' => 'Inštancia', - 'site_icon' => 'Ikona stránky', - 'site_icon_delete' => 'Odstrániť ikonu stránky', + 'title' => 'Instance', + 'site_icon' => 'Site icon', + 'site_icon_delete' => 'Delete site icon', 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Názov stránky', - 'site_description' => 'Popis stránky', - 'submit' => 'Uložiť', + 'site_name' => 'Site name', + 'site_description' => 'Site description', + 'submit' => 'Save', 'editSuccess' => 'Instance has been updated successfully!', 'deleteIconSuccess' => 'Site icon has been remove successfully!', ], 'images' => [ - 'title' => 'Obrázky', + 'title' => 'Images', 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', 'regenerate' => 'Regenerate images', 'regenerationSuccess' => 'All images have been regenerated successfully!', @@ -43,16 +43,16 @@ return [ 'runSuccess' => 'Housekeeping has been run successfully!', ], 'theme' => [ - 'title' => 'Vzhľad', + 'title' => 'Theme', 'accent_section_title' => 'Accent color', 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', 'pine' => 'Pine', - 'crimson' => 'Karmínová', + 'crimson' => 'Crimson', 'amber' => 'Amber', 'lake' => 'Lake', 'jacaranda' => 'Jacaranda', 'onyx' => 'Onyx', - 'submit' => 'Uložiť', + 'submit' => 'Save', 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', ], ]; diff --git a/modules/Admin/Language/sk/Soundbite.php b/modules/Admin/Language/sk/Soundbite.php index 6b118afb..a3f828fe 100644 --- a/modules/Admin/Language/sk/Soundbite.php +++ b/modules/Admin/Language/sk/Soundbite.php @@ -10,8 +10,8 @@ declare(strict_types=1); return [ 'list' => [ - 'title' => 'Zvukové ukážky', - 'soundbite' => 'Zvuková ukážka', + 'title' => 'Soundbites', + 'soundbite' => 'Soundbite', ], 'messages' => [ 'createSuccess' => 'Soundbite has been successfully created!', @@ -19,13 +19,13 @@ return [ ], 'form' => [ 'title' => 'New soundbite', - 'soundbite_title' => 'Názov zvukovej ukážky', - 'start_time' => 'Začiatok na', - 'duration' => 'Trvanie', - 'submit' => 'Vytvoriť zvukovú ukážku', + 'soundbite_title' => 'Soundbite title', + 'start_time' => 'Start at', + 'duration' => 'Duration', + 'submit' => 'Create soundbite', ], 'play' => 'Play soundbite', 'stop' => 'Stop soundbite', 'create' => 'New soundbite', - 'delete' => 'Vymazať zvukovú ukážku', + 'delete' => 'Delete soundbite', ]; diff --git a/modules/Admin/Language/sk/User.php b/modules/Admin/Language/sk/User.php new file mode 100644 index 00000000..585d6799 --- /dev/null +++ b/modules/Admin/Language/sk/User.php @@ -0,0 +1,56 @@ + "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', + 'delete' => 'Delete', + 'create' => 'New user', + 'view' => "{username}'s info", + 'all_users' => 'All users', + 'list' => [ + 'user' => 'User', + 'roles' => 'Roles', + 'banned' => 'Banned?', + ], + 'form' => [ + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', + 'new_password' => 'New Password', + 'roles' => 'Roles', + 'permissions' => 'Permissions', + 'submit_create' => 'Create user', + 'submit_edit' => 'Save', + 'submit_password_change' => 'Change!', + ], + 'roles' => [ + 'superadmin' => 'Super admin', + ], + 'messages' => [ + 'createSuccess' => + 'User created successfully! {username} will be prompted with a password reset upon first authentication.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', + 'editOwnerError' => + '{username} is the instance owner, you cannot edit its roles.', + 'banSuperAdminError' => + '{username} is a superadmin, one does not simply ban a superadmin…', + 'deleteSuperAdminError' => + '{username} is a superadmin, one does not simply delete a superadmin…', + 'deleteSuccess' => '{username} has been deleted.', + ], +]; diff --git a/modules/Admin/Language/sk/Validation.php b/modules/Admin/Language/sk/Validation.php index f76c3163..750b1968 100644 --- a/modules/Admin/Language/sk/Validation.php +++ b/modules/Admin/Language/sk/Validation.php @@ -13,5 +13,6 @@ return [ '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/sk/VideoClip.php b/modules/Admin/Language/sk/VideoClip.php index cfe35050..638de697 100644 --- a/modules/Admin/Language/sk/VideoClip.php +++ b/modules/Admin/Language/sk/VideoClip.php @@ -12,10 +12,10 @@ return [ 'list' => [ 'title' => 'Video clips', 'status' => [ - 'label' => 'Stav', - 'queued' => 'v poradí', + 'label' => 'Status', + 'queued' => 'queued', 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'čaká', + 'pending' => 'pending', 'pending_hint' => 'Clip will be generated shortly.', 'running' => 'running', 'running_hint' => 'Clip is being generated.', @@ -55,8 +55,8 @@ return [ 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', ], 'theme' => 'Select a theme', - 'start_time' => 'Začiatok na', - 'duration' => 'Trvanie', + 'start_time' => 'Start at', + 'duration' => 'Duration', 'trim_start' => 'Trim start', 'trim_end' => 'Trim end', 'submit' => 'Create video clip', diff --git a/modules/Admin/Language/sr-latn/AboutCastopod.php b/modules/Admin/Language/sr-latn/AboutCastopod.php deleted file mode 100644 index 66ccc2e3..00000000 --- a/modules/Admin/Language/sr-latn/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'O Castopod-u', - 'host_name' => 'Naziv hosta', - 'version' => 'Verzija Castopod-a', - 'php_version' => 'PHP verzija', - 'os' => 'Operativni Sistem', - 'languages' => 'Jezici', - 'update_database' => 'Ažuriraj baze podataka', - 'messages' => [ - 'databaseUpdateSuccess' => 'Baza podataka je ažurirana!', - ], -]; diff --git a/modules/Admin/Language/sr-latn/Breadcrumb.php b/modules/Admin/Language/sr-latn/Breadcrumb.php deleted file mode 100644 index 3376dedd..00000000 --- a/modules/Admin/Language/sr-latn/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb polja', - config('Admin') - ->gateway => 'Početna', - 'podcasts' => 'podkasti', - 'episodes' => 'epizode', - 'subscriptions' => 'pretplate', - 'contributors' => 'saradnici', - 'pages' => 'stranice', - 'settings' => 'podešavanja', - 'theme' => 'tema', - 'about' => 'osnovni podaci', - 'add' => 'dodaj', - 'new' => 'nov', - 'edit' => 'izmeni', - 'persons' => 'osobe', - 'publish' => 'objavi', - 'publish-edit' => 'uredi objavu', - 'publish-date-edit' => 'uredi datum objave', - 'unpublish' => 'ukolni objavu', - 'delete' => 'obriši', - 'remove' => 'ukloni', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blokirani nalozi', - 'blocked-domains' => 'blokirani domeni', - 'users' => 'korisnici', - 'my-account' => 'moj nalog', - 'change-password' => 'promenite lozinku', - 'imports' => 'uvozi', - 'sync-feeds' => 'sinhronizuj snabdevače', - 'platforms' => 'platforme', - 'social' => 'društvene mreže', - 'funding' => 'finansiranje', - 'monetization-other' => 'druga monetizacija', - 'analytics' => 'analitika', - 'locations' => 'lokacije', - 'webpages' => 'veb strane', - 'unique-listeners' => 'jedinstveni slušaoci', - 'players' => 'plejeri', - 'listening-time' => 'ukupno vreme slušanja', - 'time-periods' => 'vremenski periodi', - 'soundbites' => 'zvučni isečci', - 'video-clips' => 'video isečci', - 'embed' => 'embedovan plejer', - 'notifications' => 'obaveštenja', - 'suspend' => 'obustavi', -]; diff --git a/modules/Admin/Language/sr-latn/Charts.php b/modules/Admin/Language/sr-latn/Charts.php deleted file mode 100644 index cb90b13b..00000000 --- a/modules/Admin/Language/sr-latn/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Preuzimanja epizode po servisu (za prošlu nedelju)', - 'by_player_weekly' => 'Preuzimanja epizode po plejeru (za prošlu nedelju)', - 'by_player_yearly' => 'Preuzimanja epizode po plejeru (za prošlu godinu)', - 'by_device_weekly' => 'Preuzimanja epizode po uređaju (za prošlu nedelju)', - 'by_os_weekly' => 'Preuzimanja epizode po operativnom sistemu (za prošlu nedelju)', - 'podcast_by_region' => 'Preuzimanja epizode po regionu (za prošlu nedelju)', - 'unique_daily_listeners' => 'Svakodnevni jedinstveni slušaoci', - 'unique_monthly_listeners' => 'Mesečni jedinstveni slušaoci', - 'by_browser' => 'Korišćenje veb stranica od strane pretraživača (za prošlu nedelju)', - 'podcast_by_day' => 'Dnevno preuzimanje epizoda', - 'podcast_by_month' => 'Mesečno preuzimanje epizoda', - 'episode_by_day' => 'Dnevno preuzimanje epizoda (prvih 60 dana)', - 'episode_by_month' => 'Mesečno preuzimanje epizoda', - 'episodes_by_day' => - 'Preuzimanja poslednjih 5 epizoda (u prvih 60 dana)', - 'by_country_weekly' => 'Preuzimanja epizode po državi (za prošlu nedelju)', - 'by_country_yearly' => 'Preuzimanja epizode po državi (za prošlu godinu)', - 'by_domain_weekly' => 'Posete veb stranicama prema izvoru (za prošlu nedelju)', - 'by_domain_yearly' => 'Posete veb stranicama prema izvoru (za prošlu godinu)', - 'by_entry_page' => 'Posete veb stranicama prema odredišnoj stranici (za prošlu nedelju)', - 'podcast_bots' => 'Botovi (pokretači)', - 'daily_listening_time' => 'Dnevno kumulativno vreme slušanja', - 'monthly_listening_time' => 'Mesečno kumulativno vreme slušanja', - 'by_weekday' => 'Po danu u nedelji (za poslednjih 60 dana)', - 'by_hour' => 'Po dobu dana (za poslednjih 60 dana)', - 'podcast_by_bandwidth' => 'Dnevno korišćen protok (u MB)', - 'total_storage_by_month' => 'Mesečni skladišni prostor (u MB)', - 'total_bandwidth_by_month' => 'Mesečno korišćen protok (u MB)', - 'total_bandwidth_by_month_limit' => 'Ograničeno na {totalBandwidth} mesečno', -]; diff --git a/modules/Admin/Language/sr-latn/Common.php b/modules/Admin/Language/sr-latn/Common.php deleted file mode 100644 index 8fc6f706..00000000 --- a/modules/Admin/Language/sr-latn/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Da', - 'no' => 'Ne', - 'cancel' => 'Otkaži', - 'optional' => 'Opciono', - 'more' => 'Više', - 'no_data' => 'Nema pronađenih podataka!', - 'close' => 'Zatvori', - 'edit' => 'Izmeni', - 'copy' => 'Kopiraj', - 'copied' => 'Kopirano!', - 'home' => 'Početna stranica', - 'explicit' => 'Eksplicitno', - 'powered_by' => 'Pokreće {castopod}', - 'actions' => 'Akcije', - 'pageInfo' => 'Stranica {currentPage} od {pageCount}', - 'go_back' => 'Nazad', - 'forms' => [ - 'editor' => [ - 'write' => 'Piši', - 'preview' => 'Pregled', - 'help' => 'Pokreće markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Pritisni da odabereš', - 'loadingText' => 'Učitavanje…', - 'noResultsText' => 'Nije pronađen nijedan rezultat', - 'noChoicesText' => 'Nema opcija koje je moguće odabrati', - 'maxItemText' => 'Nije moguće dodati više stavki', - ], - 'upload_file' => 'Otpremite datoteku', - 'remote_url' => 'Daljinski URL', - 'save' => 'Sačuvaj', - ], - 'play_episode_button' => [ - 'play' => 'Pusti', - 'playing' => 'Reprodukujem', - ], - 'size_limit' => 'Limit veličine: {0}.', - 'choose_interact' => 'Odaberite način interakcije', - 'view' => 'Pogledaj', -]; diff --git a/modules/Admin/Language/sr-latn/Countries.php b/modules/Admin/Language/sr-latn/Countries.php deleted file mode 100644 index 64b97465..00000000 --- a/modules/Admin/Language/sr-latn/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andora', - 'AE' => 'Ujedinjeni Arapski Emirati', - 'AF' => 'Afganistan', - 'AG' => 'Antiga i Barbuda', - 'AI' => 'Angvila', - 'AL' => 'Albanija', - 'AM' => 'Jermenija', - 'AO' => 'Angola', - 'AQ' => 'Antarktik', - 'AR' => 'Argentina', - 'AS' => 'Američka Samoa', - 'AT' => 'Austrija', - 'AU' => 'Australija', - 'AW' => 'Aruba', - 'AX' => 'Olandska Ostrva', - 'AZ' => 'Azerbejdžan', - 'BA' => 'Bosna i Hercegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladeš', - 'BE' => 'Bеlgija', - 'BF' => 'Burkina Faso', - 'BG' => 'Bugarska', - 'BH' => 'Bahrеin', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Sveti Bartolomej', - 'BM' => 'Bermuda', - 'BN' => 'Bruneji Darusalam', - 'BO' => 'Bolivija, Višenacionalna Država', - 'BQ' => 'Bonеr, Svеti Eustahijе i Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahami', - 'BT' => 'Butan', - 'BV' => 'Ostrvo Buve', - 'BW' => 'Bocvana', - 'BY' => 'Bеlorusija', - 'BZ' => 'Belize', - 'CA' => 'Kanada', - 'CC' => 'Kokosova (Kilingova) Ostrva', - 'CD' => 'Demokratska Republika Kongo', - 'CF' => 'Centralnoafrička Republika', - 'CG' => 'Kongo', - 'CH' => 'Švajcarska', - 'CI' => "Obala Slonovače", - 'CK' => 'Kukova ostrva', - 'CL' => 'Čilе', - 'CM' => 'Kamerun', - 'CN' => 'Kina', - 'CO' => 'Kolumbija', - 'CR' => 'Kostarika', - 'CU' => 'Kuba', - 'CV' => 'Zelenortska Ostrva', - 'CW' => 'Kurasao', - 'CX' => 'Uskršnja ostrva', - 'CY' => 'Kipar', - 'CZ' => 'Češka Republika', - 'DE' => 'Nemačka', - 'DJ' => 'Džibuti', - 'DK' => 'Danska', - 'DM' => 'Dominika', - 'DO' => 'Dominikanska Republika', - 'DZ' => 'Alžir', - 'EC' => 'Ekvador', - 'EE' => 'Estonija', - 'EG' => 'Egipat', - 'EH' => 'Zapadna Sahara', - 'ER' => 'Eritreja', - 'ES' => 'Španija', - 'ET' => 'Etiopija', - 'FI' => 'Finska', - 'FJ' => 'Fidži', - 'FK' => 'Foklandska ostrva (Malvini)', - 'FM' => 'Savezne države Mikronezije', - 'FO' => 'Farska Ostrva', - 'FR' => 'Francuska', - 'GA' => 'Gabon', - 'GB' => 'Ujedinjeno Kraljevstvo', - 'GD' => 'Grenada', - 'GE' => 'Gruzija', - 'GF' => 'Francuska Gvajana', - 'GG' => 'Gernzi', - 'GH' => 'Gana', - 'GI' => 'Gibraltar', - 'GL' => 'Grеnland', - 'GM' => 'Gambija', - 'GN' => 'Gvineja', - 'GP' => 'Gvadelupe', - 'GQ' => 'Ekvatorijalna Gvineja', - 'GR' => 'Grčka', - 'GS' => 'Južna Džordžija i Južna Sendvič Ostrva', - 'GT' => 'Gvatemala', - 'GU' => 'Guam', - 'GW' => 'Gvineja-Bisao', - 'GY' => 'Gvajana', - 'HK' => 'Hong Kong', - 'HM' => 'Ostrva Herd i Makdonald', - 'HN' => 'Honduras', - 'HR' => 'Hrvatska', - 'HT' => 'Haiti', - 'HU' => 'Mađarska', - 'ID' => 'Indonezija', - 'IE' => 'Irska', - 'IL' => 'Izrael', - 'IM' => 'Ostrvo Man', - 'IN' => 'Indija', - 'IO' => 'Britanska Territorija u Indijskom Okeanu', - 'IQ' => 'Irak', - 'IR' => 'Islamska Republika Iran', - 'IS' => 'Island', - 'IT' => 'Italija', - 'JE' => 'Džersi', - 'JM' => 'Jamajka', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenija', - 'KG' => 'Kirgistan', - 'KH' => 'Kambodža', - 'KI' => 'Kiribati', - 'KM' => 'Komorska Ostrva', - 'KN' => 'Sveti Kits i Nevis', - 'KP' => "Demokratska Narodna Republika Koreja", - 'KR' => 'Republika Koreja', - 'KW' => 'Kuvajt', - 'KY' => 'Kajmanska ostrva', - 'KZ' => 'Kazahstan', - 'LA' => "Laos", - 'LB' => 'Liban', - 'LC' => 'Sveta Lucija', - 'LI' => 'Lihtenštajn', - 'LK' => 'Šri Lanka', - 'LR' => 'Liberija', - 'LS' => 'Lesoto', - 'LT' => 'Litvanija', - 'LU' => 'Luksemburg', - 'LV' => 'Letonija', - 'LY' => 'Libija', - 'MA' => 'Maroko', - 'MC' => 'Monako', - 'MD' => 'Republika Moldavija', - 'ME' => 'Crna Gora', - 'MF' => 'Sveti Martin (Francuski deo)', - 'MG' => 'Madagaskar', - 'MH' => 'Maršalska Ostrva', - 'MK' => 'Severna Makedonija', - 'ML' => 'Mali', - 'MM' => 'Mijanmar', - 'MN' => 'Mongolija', - 'MO' => 'Makao', - 'MP' => 'Severna Marijanska Ostrva', - 'MQ' => 'Martinik', - 'MR' => 'Mauritanija', - 'MS' => 'Montserat', - 'MT' => 'Malta', - 'MU' => 'Mauricijus', - 'MV' => 'Maldivi', - 'MW' => 'Malavi', - 'MX' => 'Meksiko', - 'MY' => 'Malezija', - 'MZ' => 'Mozambik', - 'N/A' => 'Nije primenjivo (Lokalna IP…)', - 'NA' => 'Namibija', - 'NC' => 'Nova Kaledonija', - 'NE' => 'Niger', - 'NF' => 'Ostrvo Norfolk', - 'NG' => 'Nigerija', - 'NI' => 'Nikaragva', - 'NL' => 'Holandija', - 'NO' => 'Norveška', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Nijue', - 'NZ' => 'Novi Zeland', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'Francuska Polinezija', - 'PG' => 'Papua Nova Gvinеja', - 'PH' => 'Filipini', - 'PK' => 'Pakistan', - 'PL' => 'Poljska', - 'PM' => 'Sen Pjer i Mikelon', - 'PN' => 'Pitkern', - 'PR' => 'Portoriko', - 'PS' => 'Palestina', - 'PT' => 'Portugalija', - 'PW' => 'Palau', - 'PY' => 'Paragvaj', - 'QA' => 'Katar', - 'RE' => 'Rejunion', - 'RO' => 'Rumunija', - 'RS' => 'Srbija', - 'RU' => 'Ruska Federacija', - 'RW' => 'Ruanda', - 'SA' => 'Saudijska Arabija', - 'SB' => 'Solomonova ostrva', - 'SC' => 'Sejšeli', - 'SD' => 'Sudan', - 'SE' => 'Švedska', - 'SG' => 'Singapur', - 'SH' => 'Sveta Helena, Asension i Tristan da Kunja', - 'SI' => 'Slovеnija', - 'SJ' => 'Svalbard i Jan Majen', - 'SK' => 'Slovačka', - 'SL' => 'Sijera Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalija', - 'SR' => 'Surinam', - 'SS' => 'Južni Sudan', - 'ST' => 'Sao Tomе i Prinsipе', - 'SV' => 'Salvador', - 'SX' => 'Sveti Martin (Holandski deo)', - 'SY' => 'Sirijska Arapska Republika', - 'SZ' => 'Svazilеnd', - 'TC' => 'Tеrks i Kеjkos', - 'TD' => 'Čad', - 'TF' => 'Francuske Južne Teritorije', - 'TG' => 'Togo', - 'TH' => 'Таjland', - 'TJ' => 'Tadžikistan', - 'TK' => 'Tokelau', - 'TL' => 'Istočni Timor', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunis', - 'TO' => 'Tonga', - 'TR' => 'Turska', - 'TT' => 'Trinidad i Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Tajvan, Kineska provincija', - 'TZ' => 'Ujedinjena Republika Tanzanija', - 'UA' => 'Ukrajina', - 'UG' => 'Uganda', - 'UM' => 'Mala spoljna ostrva Sjedinjenih Američkih Država', - 'US' => 'Sjеdinjеnе Državе', - 'UY' => 'Urugvaj', - 'UZ' => 'Uzbekistan', - 'VA' => 'Sveta stolica (Grad-država Vatikan)', - 'VC' => 'Sveti Vinsent i Grenadini', - 'VE' => 'Venecuela', - 'VG' => 'Devičanska ostrva', - 'VI' => 'Devičanska Ostrva, S.A.D.', - 'VN' => 'Vijetnam', - 'VU' => 'Vanuatu', - 'WF' => 'Valis i Futuna', - 'WS' => 'Samoa', - 'YE' => 'Jemen', - 'YT' => 'Majote', - 'ZA' => 'Južna Afrika', - 'ZM' => 'Zambija', - 'ZW' => 'Zimbabve', -]; diff --git a/modules/Admin/Language/sr-latn/Dashboard.php b/modules/Admin/Language/sr-latn/Dashboard.php deleted file mode 100644 index 8761ee1b..00000000 --- a/modules/Admin/Language/sr-latn/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Kontrolna tabla za administratora', - 'welcome_message' => 'Dobrodošli u deo za administratore!', - 'podcasts' => [ - 'title' => 'Podkasti', - 'not_found' => 'Nemate objavljen podkast', - 'last_published' => 'Poslednja objava {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Epizode', - 'not_found' => 'Nemate objavljene epizode', - 'last_published' => 'Poslednja objava {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Prostor', - 'subtitle' => '{totalUploaded} od {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/sr-latn/Episode.php b/modules/Admin/Language/sr-latn/Episode.php deleted file mode 100644 index 9ac56547..00000000 --- a/modules/Admin/Language/sr-latn/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Sezona {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Epizoda {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Sezona {seasonNumber} epizoda {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}:E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# komentar} - other {# komentara} - }', - 'all_podcast_episodes' => 'Sve epizode podkasta', - 'back_to_podcast' => 'Nazad na podkast', - 'edit' => 'Izmeni', - 'preview' => 'Pregled', - 'publish' => 'Objavi', - 'publish_edit' => 'Uredi objavu', - 'publish_date_edit' => 'Uredi datum objave', - 'unpublish' => 'Opozovi objavu', - 'publish_error' => 'Epizoda je već objavljena.', - 'publish_edit_error' => 'Epizoda je već objavljena.', - 'publish_cancel_error' => 'Epizoda je već objavljena.', - 'publish_date_edit_error' => 'Epizoda još uvek nije objavljena, ne možete urediti datum objave.', - 'publish_date_edit_future_error' => 'Datum objavljivanja epizode može se podesiti samo na pređašnji datum. Ukoliko želite da ponovo zakažete objavu epizode u budućnosti, morate prvo opozvati njenu objavu.', - 'publish_date_edit_success' => 'Datum objave epizode je uspešno uređen!', - 'unpublish_error' => 'Epizoda nije objavljena.', - 'delete' => 'Obriši', - 'go_to_page' => 'Idi na stranu', - 'create' => 'Dodaj epizodu', - 'publication_status' => [ - 'published' => 'Objavljeno', - 'with_podcast' => 'Objavljeno', - 'scheduled' => 'Zakazano', - 'not_published' => 'Neobjavljeno', - ], - 'with_podcast_hint' => 'Objaviti u isto vreme kad i podkast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Traži epizodu', - 'clear' => 'Očisti pretragu', - 'submit' => 'Pretraga', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# epizoda} - other {# epizode} - }', - 'episode' => 'Epizoda', - 'visibility' => 'Vidljivost', - 'downloads' => 'Preuzimanja', - 'comments' => 'Komentari', - 'actions' => 'Akcije', - ], - 'messages' => [ - 'createSuccess' => 'Epizoda je uspešno kreirana!', - 'editSuccess' => 'Epizoda je uspešno ažurirana!', - 'publishSuccess' => '{publication_status, select, - published {Epizoda je uspešno objavljena!} - scheduled {Epizoda je uspešno zakazana!} - with_podcast {Ova epizoda će biti objavljena u isto vreme kad i podkast.} - other {Ova epizoda nije objavljena.} - }', - 'publishCancelSuccess' => 'Objavljivanje epizode je uspešno otkazano!', - 'unpublishBeforeDeleteTip' => 'Morate opozvati objavljivanje epizode pre nego što je izbrišete.', - 'scheduleDateError' => 'Morate zakazati datum objave!', - 'deletePublishedEpisodeError' => 'Molimo vas opozovite objavu epizode pre nego što je izbrišete.', - 'deleteSuccess' => 'Epizoda uspešno izbrisana!', - 'deleteError' => 'Neuspešno brisanje {type, select, - transcript {transkripta} - chapters {poglavlja} - image {omota} - audio {zvuka} - other {medija} - }.', - 'deleteFileError' => 'Neuspešno brisanje {type, select, - transcript {transkripta} - chapters {poglavlja} - image {omota} - audio {zvuka} - other {medija} - } datoteke {file_key}. Možete je ukloniti ručno sa vašeg diska.', - 'sameSlugError' => 'Odabrano URL ime (slug) epizode već postoji.', - ], - 'form' => [ - 'file_size_error' => - 'Veličina vaše datoteke je prevelika! Maksimalna veličina je {0}. Povećajte `memory_limit`, `upload_max_filesize` i `post_max_size` vrednosti u vašoj datoteci php konfiguracije, potom ponovo pokrenite veb server da bi ste otpremili datoteku.', - 'audio_file' => 'Zvučna datoteka', - 'audio_file_hint' => 'Odaberite .mp3 ili .m4a zvučnu datoteku.', - 'info_section_title' => 'Informacije o epizodi', - 'cover' => 'Omot epizode', - 'cover_hint' => - 'Ukoliko ne postavite omot epizode, koristiće se omot podkasta.', - 'cover_size_hint' => 'Omot mora biti kvadratnog oblika i minimum 1400px širok i visok.', - 'title' => 'Naslov', - 'title_hint' => - 'Treba sadržati jasan i koncizan naziv epizode. Nemojte upisivati broj sezone ili epizode ovde.', - 'permalink' => 'Trajni link', - 'season_number' => 'Sezona', - 'episode_number' => 'Epizoda', - 'type' => [ - 'label' => 'Vrsta', - 'full' => 'Cela', - 'full_hint' => 'Kompletan sadržaj (epizoda)', - 'trailer' => 'Najava', - 'trailer_hint' => 'Kratak, promotivni deo sadržaja koji predstavlja pregled aktuelne emisije', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Dodatni sadržaj za emisiju (na primer, informacije iza scene ili intervjui sa glumcima) ili unakrsni promotivni sadržaj za drugu emisiju', - ], - 'premium_title' => 'Premium', - 'premium' => 'Epizoda mora biti dostupna samo premium pretplatnicima', - 'parental_advisory' => [ - 'label' => 'Roditeljsko savetovanje', - 'hint' => 'Da li epizoda sadrži eksplicitan sadržaj?', - 'undefined' => 'nedefinisano', - 'clean' => 'Čisto', - 'explicit' => 'Eksplicitno', - ], - 'show_notes_section_title' => 'Prikaži beleške', - 'show_notes_section_subtitle' => - 'Do 4000 znakova, budite jasni i sažeti. Beleške pomažu potencijalnim slušaocima da pronađu epizodu.', - 'description' => 'Opis', - 'description_footer' => 'Podnožje opisa', - 'description_footer_hint' => - 'Ovaj tekst se dodaje na kraj opisa svake epizode, ovo je pravo mesto za vaše linkove ka društvenim mrežama naprimer.', - 'additional_files_section_title' => 'Dodatne datoteke', - 'additional_files_section_subtitle' => - 'Ove datoteke mogu biti korišćene od strane drugih platformi radi boljeg iskustva vaše publike. Pogledajte {podcastNamespaceLink} za više informacija.', - 'location_section_title' => 'Lokacija', - 'location_section_subtitle' => 'O kom mestu je ova epizoda?', - 'location_name' => 'Ime ili adresa lokacije', - 'location_name_hint' => 'Ovo može biti prava ili fiktivna lokacija', - 'transcript' => 'Transkript (titlovi)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Preuzmi transkript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Udaljeni Url za transkript', - 'transcript_file_delete' => 'Obriši datoteku transkripta', - 'chapters' => 'Poglavlja', - 'chapters_hint' => 'Datoteka mora biti u JSON Poglavlja formatu.', - 'chapters_download' => 'Preuzmi poglavlja', - 'chapters_file' => 'Datoteka poglavlja', - 'chapters_remote_url' => 'Udaljeni Url za datoteku poglavlja', - 'chapters_file_delete' => 'Obriši datoteku poglavlja', - 'advanced_section_title' => 'Napredni parametri', - 'advanced_section_subtitle' => - 'Ukoliko su vam potrebni RSS tagovi koje Castopod ne obrađuje, postavite ih ovde.', - 'custom_rss' => 'Posebni RSS tagovi epizode', - 'custom_rss_hint' => 'Ovo će biti ubačeno u ❬item❭ tag.', - 'block' => 'Epizoda treba biti sakriivena u javnim katalozima', - 'block_hint' => - 'Prikazan ili sakriven status epizode: ukoliko uključite ovu opciju onemogućavate prikazivanje vaše epizode na paltformama za slušanje podkasta kao što su Apple Podcasts, Google Podcasts i sličnim direktorijima. (Nije zagarantovano)', - 'submit_create' => 'Kreiraj epizodu', - 'submit_edit' => 'Sačuvaj epizodu', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Nazad na komandnu tablu epizode', - 'post' => 'Najava vaše objave', - 'post_hint' => - "Napišite poruku da najavite objavu vaše epizode. Poruka će biti poslata svim vašim pratiocima u fediversu i istaknuta na stranici vašeg podkasta.", - 'message_placeholder' => 'Napišite poruku…', - 'publication_date' => 'Datum objavljivanja', - 'publication_method' => [ - 'now' => 'Sada', - 'schedule' => 'Raspored', - 'with_podcast' => 'Objavi uz podkast', - ], - 'scheduled_publication_date' => 'Planiran datum objave', - 'scheduled_publication_date_clear' => 'Ukloni datum objave', - 'scheduled_publication_date_hint' => - 'Možete zakazati objavu epizode u budućnosti. Ovo polje mora biti popunjeno u YYYY-MM-DD HH:mm formatu', - 'submit' => 'Objavi', - 'submit_edit' => 'Uredi objavu', - 'cancel_publication' => 'Poništi objavu', - 'message_warning' => 'Niste napisali poruku za najavu objave!', - 'message_warning_hint' => 'Poruka povećava šanse za angažovanjem na društvenim mrežama, rezultirajući u većoj vidljivosti vaše epizode.', - 'message_warning_submit' => 'Objavi svakako', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'Novi datum objavljivanja', - 'new_publication_date_hint' => 'Mora biti podešeno na prošli datum.', - 'submit' => 'Uredi datum objavljivanja', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Opozivanje objavljivanja epizode će obrisati sve komentare i obajve povezane sa eppizodom i ukloniti je i RSS feed-a podkasta.", - 'understand' => 'Razumem, želim da opozovem objavu epizode', - 'submit' => 'Opozovi objavu', - ], - 'delete_form' => [ - 'disclaimer' => - "Brisanje epizode će obrisati sve medijske datoteke, komentare, video i zvučne isečke povezane sa njom.", - 'understand' => 'Razumem, želim da obrišem epizodu', - 'submit' => 'Obriši', - ], - 'embed' => [ - 'title' => 'Embedovan plejer', - 'label' => - 'Odaberite boju teme, kopirajte embedovan plejer i nalepite ga na vaš sajt.', - 'clipboard_iframe' => 'Kopirajte kod embedovanog plejera', - 'clipboard_url' => 'Kopirajte adresu', - 'dark' => 'Tamna', - 'dark-transparent' => 'Tamna providna', - 'light' => 'Svetla', - 'light-transparent' => 'Svetla providna', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'režim nacrta', - 'text' => '{publication_status, select, - published {Ova epizoda još uvek nije objavljena.} - scheduled {Ova epizoda je zakazana za {publication_date}.} - with_podcast {Ova epizoda će biti objavljena kad i podkast.} - other {Ova epizoda još uvek nije objavljena.} - }', - 'preview' => 'Pregled', - ], -]; diff --git a/modules/Admin/Language/sr-latn/EpisodeNavigation.php b/modules/Admin/Language/sr-latn/EpisodeNavigation.php deleted file mode 100644 index 48cf7138..00000000 --- a/modules/Admin/Language/sr-latn/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'Pogledaj stranicu epizode', - 'dashboard' => 'Kontrolna tabla epizode', - 'episode-view' => 'Početna', - 'episode-edit' => 'Uredi epizodu', - 'episode-persons-manage' => 'Uredi osobe', - 'embed-add' => 'Embedovan plejer', - 'clips' => 'Isečci', - 'video-clips-list' => 'Video isečci', - 'video-clips-create' => 'Novi video isečak', - 'soundbites-list' => 'Zvučni isečci', - 'soundbites-create' => 'Novi zvučni isečak', -]; diff --git a/modules/Admin/Language/sr-latn/Fediverse.php b/modules/Admin/Language/sr-latn/Fediverse.php deleted file mode 100644 index 77d2bd18..00000000 --- a/modules/Admin/Language/sr-latn/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'Nalog ne može biti pronađen!', - 'blockActorSuccess' => '{actor} je blokiran!', - 'unblockActorSuccess' => '{actor} je blokiran!', - 'blockDomainSuccess' => '{domain} je blokiran!', - 'unblockDomainSuccess' => '{domain} je odblokiran!', - ], - 'blocked_actors' => 'Blokirani nalozi', - 'blocked_domains' => 'Blokirani domeni', - 'block_lists_form' => [ - 'handle' => 'Kvačica naloga', - 'handle_hint' => 'Unesi @username@domain nalog.', - 'domain' => 'Naziv domena', - 'submit' => 'Blokiraj!', - ], - 'list' => [ - 'actor' => 'Nalog', - 'domain' => 'Naziv domena', - 'unblock' => 'Odblokiraj', - ], -]; diff --git a/modules/Admin/Language/sr-latn/Home.php b/modules/Admin/Language/sr-latn/Home.php deleted file mode 100644 index b116bc70..00000000 --- a/modules/Admin/Language/sr-latn/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'Svi podkasti', - 'no_podcast' => 'Nema pronađenih podkasta', -]; diff --git a/modules/Admin/Language/sr-latn/Install.php b/modules/Admin/Language/sr-latn/Install.php deleted file mode 100644 index 65edca65..00000000 --- a/modules/Admin/Language/sr-latn/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Ručna konfiguracija', - 'manual_config_subtitle' => - 'Napravite `.env` datoteku sa vašim podešavanjima i osvežite stranicu da bi ste nastavili instalaciju.', - 'form' => [ - 'instance_config' => 'Konfiguracija instance', - 'hostname' => 'Ime domaćina', - 'media_base_url' => 'URL medijske baze', - 'media_base_url_hint' => - 'Ako koristite CDN i/ili eksternu uslugu za analitiku, možete ih postaviti ovde.', - 'admin_gateway' => 'Administratorski izlaz', - 'admin_gateway_hint' => - 'Ruta za pristup kontrolnoj tabli administratora (eg. https://example.com/cp-admin).Podrazumevano je podešena na cp-admin, preporučujemo da je promenite iz sigurnosnih razloga.', - 'auth_gateway' => 'Auth izlaz', - 'auth_gateway_hint' => - 'Ruta za pristup stranicama za potvrdu identiteta (eg. https://example.com/cp-auth).Podrazumevano je podešena na cp-auth, preporučujemo da je promenite iz sigurnosnih razloga.', - 'database_config' => 'Konfiguracija baze podataka', - 'database_config_hint' => - 'Castopod mora da se poveže za vašom MySQL (ili MariaDB) bazom. Ukoliko ne posedujete potrebne informacije, molimo vas kontaktirajte administratora vašeg servera.', - 'db_hostname' => 'Ime hosta baze podataka', - 'db_name' => 'Ime baze podataka', - 'db_username' => 'Korisničko ime baze podataka', - 'db_password' => 'Lozinka baze podataka', - 'db_prefix' => 'Prefiks baze', - 'db_prefix_hint' => - "Prefiks imena tabela Castopod-a, ne diraj ako ne znaš šta znači.", - 'cache_config' => 'Konfiguracija keša', - 'cache_config_hint' => - 'Izaberite željeni obrađivač keša. Ostavite je kao podrazumevanu vrednost ako nemate pojma šta to znači.', - 'cache_handler' => 'Obrađivač keša', - 'cacheHandlerOptions' => [ - 'file' => 'Datoteka', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Sledeće', - 'submit' => 'Završi instalaciju', - 'create_superadmin' => 'Kreiraj svoj nalog super administratora', - 'email' => 'E-pošta', - 'username' => 'Korisničko ime', - 'password' => 'Lozinka', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Vaš nalog superadmina je uspešno kreiran. Prijavite se da biste započeli podkasting!', - 'databaseConnectError' => - 'Castopod nije mogao da se poveže sa vašom bazom podataka. Uredite konfiguraciju baze podataka i pokušajte ponovo.', - 'writeError' => - "Nije moguće kreirati/upisati datoteku `.env`. Morate je kreirati ručno prateći šablon datoteke `.env.example` u Castopod-ovom paketu.", - ], -]; diff --git a/modules/Admin/Language/sr-latn/Navigation.php b/modules/Admin/Language/sr-latn/Navigation.php deleted file mode 100644 index bc4c5518..00000000 --- a/modules/Admin/Language/sr-latn/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Uključite bočnu traku', - 'go_to_website' => 'Idi na sajt', - 'go_to_admin' => 'Idi na administratora', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Kontrolna tabla', - 'admin' => 'Početna', - 'podcasts' => 'Podkasti', - 'podcast-list' => 'Svi podkasti', - 'podcast-create' => 'Novi podkast', - 'all-podcast-imports' => 'Uvozi podkasta', - 'podcast-imports-add' => 'Uvezi podkast', - 'persons' => 'Osobe', - 'person-list' => 'Sve osobe', - 'person-create' => 'Nova osoba', - 'fediverse' => 'Fediverzum', - 'fediverse-blocked-actors' => 'Blokirani nalozi', - 'fediverse-blocked-domains' => 'Blokirani domeni', - 'users' => 'Korisnici', - 'user-list' => 'Svi korisnici', - 'user-create' => 'Novi korisnik', - 'pages' => 'Stranice', - 'page-list' => 'Sve stranice', - 'page-create' => 'Nova Stranica', - 'settings' => 'Podešavanja', - 'settings-general' => 'Opšte', - 'settings-theme' => 'Tema', - 'admin-about' => 'Osnovni podaci', - 'account' => [ - 'my-account' => 'Moj nalog', - 'change-password' => 'Promenite lozinku', - 'logout' => 'Odjava', - ], -]; diff --git a/modules/Admin/Language/sr-latn/Notifications.php b/modules/Admin/Language/sr-latn/Notifications.php deleted file mode 100644 index dc79e82a..00000000 --- a/modules/Admin/Language/sr-latn/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Obaveštenja', - 'reply' => '{actor_username} odgovara na tvoju objavu', - 'favourite' => '{actor_username} dodaje tvoju objavu u omiljene', - 'reblog' => '{actor_username} deli tvoju objavu', - 'follow' => '{actor_username} vas sada prati', - 'no_notifications' => 'Nema obaveštenja', - 'mark_all_as_read' => 'Označi svе kao pročitano', -]; diff --git a/modules/Admin/Language/sr-latn/Page.php b/modules/Admin/Language/sr-latn/Page.php deleted file mode 100644 index 224fa82e..00000000 --- a/modules/Admin/Language/sr-latn/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Natrag na početnu', - 'page' => 'Stranica', - 'all_pages' => 'Sve stranice', - 'create' => 'Nova Stranica', - 'go_to_page' => 'Idi na stranicu', - 'edit' => 'Izmeni stranicu', - 'delete' => 'Obriši stranicu', - 'form' => [ - 'title' => 'Naslov', - 'permalink' => 'Trajni link', - 'content' => 'Sadržaj', - 'submit_create' => 'Napravi stranicu', - 'submit_edit' => 'Sačuvaj', - ], - 'messages' => [ - 'createSuccess' => 'Stranica “{pageTitle}” je uspešno napravljena!', - 'editSuccess' => 'Stranica je uspešno ažurirana!', - ], -]; diff --git a/modules/Admin/Language/sr-latn/Pager.php b/modules/Admin/Language/sr-latn/Pager.php deleted file mode 100644 index 421dbe64..00000000 --- a/modules/Admin/Language/sr-latn/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Navigacija po stranicama', - 'first' => 'Prva', - 'previous' => 'Prеthodna', - 'next' => 'Sledeća', - 'last' => 'Poslednja', - 'older' => 'Starije', - 'newer' => 'Novije', - 'invalidTemplate' => '{0} nije važeći šablon za stranice.', - 'invalidPaginationGroup' => '{0} nije važeći šablon za grupu paginacija.', -]; diff --git a/modules/Admin/Language/sr-latn/Person.php b/modules/Admin/Language/sr-latn/Person.php deleted file mode 100644 index e2e40df6..00000000 --- a/modules/Admin/Language/sr-latn/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Osobe', - 'all_persons' => 'Sve osobe', - 'no_person' => 'Niko nije pronađen!', - 'create' => 'Kreiraj novu osobu', - 'view' => 'Pogledaj osobu', - 'edit' => 'Izmeni osobu', - 'delete' => 'Obriši osobu', - 'messages' => [ - 'createSuccess' => 'Osoba je uspešno kreirana!', - 'editSuccess' => 'Osoba je uspešno izmenjena!', - 'deleteSuccess' => 'Osoba je uklonjena!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar mora biti kvadratnog oblika i minimum 400px širok i visok.', - 'full_name' => 'Puno ime', - 'full_name_hint' => 'Ovo je puno ime ili nadimak osobe.', - 'unique_name' => 'Jedinstveno ime', - 'unique_name_hint' => 'Koristi se za URL', - 'information_url' => 'Informacijski URL', - 'information_url_hint' => - 'Url ka relevantnim informacijama o osobi, kao što su naprimer njihova veb stranica ili profil na društvenim mrežama.', - 'submit_create' => 'Kreiraj novu osobu', - 'submit_edit' => 'Sačuvaj osobu', - ], - 'podcast_form' => [ - 'title' => 'Uredi osobe', - 'add_section_title' => 'Dodaj osobe ovom podkastu', - 'add_section_subtitle' => 'Možete odabrati nekoliko osoba i njihovih uloga.', - 'persons' => 'Osobe', - 'persons_hint' => - 'Možete odabrati jednu ili nekoliko osoba sa istim ulogama. Morate prvo kreirati osobe.', - 'roles' => 'Uloge', - 'roles_hint' => - 'Možete odabrati jednu, nekoliko ili nijednu ulogu za osobu.', - 'submit_add' => 'Dodaj osobu(e)', - 'remove' => 'Ukloni', - ], - 'episode_form' => [ - 'title' => 'Upravljaj osobama', - 'add_section_title' => 'Dodaj osobe ovoj epizodi', - 'add_section_subtitle' => 'Možete odabrati nekoliko osoba i njihovih uloga.', - 'persons' => 'Osobe', - 'persons_hint' => - 'Možete odabrati jednu ili nekoliko osoba sa istim ulogama. Morate prvo kreirati osobe.', - 'roles' => 'Uloge', - 'roles_hint' => - 'Možete odabrati jednu, nekoliko ili nijednu ulogu za osobu.', - 'submit_add' => 'Dodaj osobu(e)', - 'remove' => 'Ukloni', - ], - 'credits' => 'Zasluge', -]; diff --git a/modules/Admin/Language/sr-latn/Platforms.php b/modules/Admin/Language/sr-latn/Platforms.php deleted file mode 100644 index 0e895f03..00000000 --- a/modules/Admin/Language/sr-latn/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podkasting platforme', - 'social' => 'Društvene mreže', - 'funding' => 'Podrška', - ], - 'website' => 'Veb stranica', - 'home_url' => 'Idi na {platformName} stranicu', - 'register' => 'Rеgistrujte sе', - 'submit_url' => 'Dodaj svoj podkast na {platformName}', - 'your_link' => 'Vaš link', - 'your_id' => [ - 'podcasting' => 'Tvoj ID', - 'social' => 'Tvoj ID', - 'funding' => 'Tvoj PNA', - ], - 'your_cta' => 'Tvoj poziv na akciju', - 'visible' => 'Prikaži na naslovnoj strani podkasta?', - 'on_embed' => 'Prikaži na embedovanom plejeru?', - 'remove' => 'Ukloni {platformName}', - 'submit' => 'Sačuvaj', - 'messages' => [ - 'updateSuccess' => 'Veze sa platformama su uspešno ažurirane!', - 'removeLinkSuccess' => 'Veza ka platformi je izbrisana.', - 'removeLinkError' => - 'Vezu sa platformom nije moguće ukloniti. Probajte ponovo.', - ], - 'description' => [ - 'podcasting' => 'ID podkasta na ovoj platformi', - 'social' => 'ID naloga podkasta na ovoj platformi', - 'funding' => 'Poruka poziva na akciju', - ], -]; diff --git a/modules/Admin/Language/sr-latn/Podcast.php b/modules/Admin/Language/sr-latn/Podcast.php deleted file mode 100644 index 7926e093..00000000 --- a/modules/Admin/Language/sr-latn/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'Svi podkasti', - 'no_podcast' => 'Nema pronađenih podkasta!', - 'create' => 'Napravi podkast', - 'import' => 'Uvezi podkast', - 'all_imports' => 'Uvozi podkasta', - 'new_episode' => 'Nova epizoda', - 'view' => 'Pogledaj epizodu', - 'edit' => 'Uredi podkast', - 'publish' => 'Objavi podkast', - 'publish_edit' => 'Uredi objavu', - 'delete' => 'Obriši podkast', - 'see_episodes' => 'Pogledaj epizode', - 'see_contributors' => 'Pogledaj saradnike', - 'monetization_other' => 'Druga monetizacija', - 'go_to_page' => 'Idi na stranicu', - 'latest_episodes' => 'Najnovije epizode', - 'see_all_episodes' => 'Prikaži sve epizode', - 'draft' => 'Nacrt', - 'messages' => [ - 'createSuccess' => 'Podkast uspešno kreiran!', - 'editSuccess' => 'Podkast je uspešno ažuriran!', - 'importSuccess' => 'Podkast je uspešno uvezen!', - 'deleteSuccess' => 'Podkast @{podcast_handle} je uspešno obrisan!', - 'deletePodcastMediaError' => 'Neuspešno brisanje podkast {type, select, - cover {omota} - banner {banera} - other {medija} - }.', - 'deleteEpisodeMediaError' => 'Neuspešno brisanje {episode_slug} {type, select, - transcript {transkripta} - chapters {poglavlja} - image {omota} - audio {zvuka} - other {medija} - }.', - 'deletePodcastMediaFolderError' => 'Neuspešno brisanje podkast medija direktorijuma {folder_path}. Možete ga ručno ukloniti sa diska.', - 'podcastFeedUpdateSuccess' => 'Uspešno ažuriranje: {number_of_new_episodes, plural, - one {# epizoda je} - other {# epizode su} - } deo podkasta!', - 'podcastFeedUpToDate' => 'Podkast je već ažuriran.', - 'publishError' => 'Ovaj podkast je ili već objavljen ili zakazan za objavu.', - 'publishEditError' => 'Ovaj podkast nije zakazan za objavu.', - 'publishCancelSuccess' => 'Objavljivanje podkasta je uspešno otkazano!', - 'scheduleDateError' => 'Morate zakazati datum objave!', - ], - 'form' => [ - 'identity_section_title' => 'Identitet podkasta', - 'identity_section_subtitle' => 'Ova polja vam pomažu da budete prepoznati.', - 'fediverse_section_title' => 'Fedivers identitet', - - 'cover' => 'Omot podkasta', - 'cover_size_hint' => 'Omot mora biti kvadratnog oblika i minimum 1400px širok i visok.', - 'banner' => 'Baner podkasta', - 'banner_size_hint' => 'Baner mora imati odnos 3:1 i biti najmanje 1500px širok.', - 'banner_delete' => 'Obriši baner podkasta', - 'title' => 'Naslov', - 'handle' => 'Ručka', - 'handle_hint' => - 'Koristi se radi identifikacije podkasta. Velika slova, mala slova, brojevi i donja crta su prihvatljivi.', - 'type' => [ - 'label' => 'Vrsta', - 'episodic' => 'Epizodno', - 'episodic_hint' => 'Ukoliko su epizode namenjene za konzumiranje bez nekog specifičnog reda. Najnovija epizoda će biti predstavljena prva u redosledu.', - 'serial' => 'Serijski', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Opis', - 'classification_section_title' => 'Klasifikacija', - 'classification_section_subtitle' => - 'Ova polja će uticati na vašu publiku i konkurenciju.', - 'language' => 'Jezik', - 'category' => 'Kategorija', - 'category_placeholder' => 'Izaberite kategoriju…', - 'other_categories' => 'Ostale kategorije', - 'parental_advisory' => [ - 'label' => 'Upozorenje za roditelje', - 'hint' => 'Da li sadrži eksplicitan sadržaj?', - 'undefined' => 'nedefinisano', - 'clean' => 'Čisto', - 'explicit' => 'Eksplicitno', - ], - 'author_section_title' => 'Autor', - 'author_section_subtitle' => 'Ko upravlja podkastom?', - 'owner_name' => 'Ime vlasnika', - 'owner_name_hint' => - 'Za administrativnu upotrebu. Vidljivo u javnom RSS feed-u.', - 'owner_email' => 'Elektronska pošta vlasnika', - 'owner_email_hint' => - 'Koristiće se na većini platforma kako bi se utvrdilo vlasništvo nad podkastom. Vidljivo javno u RSS feed-u.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Izdavač', - 'publisher_hint' => - 'Grupa odgovorna za stvaranje ove emisije. Često se misli na vlasničku kompaniju ili mrežu kojoj pripada podkast. Ovo polje se nekada naziva i \'Autor".', - 'copyright' => 'Autorsko pravo', - 'location_section_title' => 'Lokacija', - 'location_section_subtitle' => 'O kom mestu je ova epizoda?', - 'location_name' => 'Ime ili adresa lokacije', - 'location_name_hint' => 'Ovo može biti stvarno ili izmišljeno mesto', - 'monetization_section_title' => 'Monetizacija', - 'monetization_section_subtitle' => - 'Zaradi novac zahvaljujući svojoj publici.', - 'premium' => 'Premijum', - 'premium_by_default' => 'Epizode ​​se podrazumevano moraju podesiti kao premijum', - 'premium_by_default_hint' => 'Epizode ​​podkasta će podrazumevano biti označene kao premijum. I dalje možete izabrati da neke epizode, trejlere ili bonuse postavite kao javne.', - 'op3' => 'Otvoreni Podkast Prefiks Projekat (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Vrednujte svoje analitičke podatke pomoću OP3, otvorenog koda i pouzdane analitičke usluge treće strane. Delite, potvrdite i uporedite svoje analitičke podatke sa otvorenim podkast ekosistemom.', - 'op3_enable' => 'Omogućite OP3 analitičku uslugu', - 'op3_enable_hint' => 'Iz bezbednosnih razloga, analitika premijum epizoda se neće deliti sa OP3.', - 'payment_pointer' => 'Pokazivač plaćanja za Veb monetizaciju', - 'payment_pointer_hint' => - 'Ovde ćete primati novac zahvaljujući Veb monetizaciji', - 'advanced_section_title' => 'Napredni parametri', - 'advanced_section_subtitle' => - 'Ukoliko su vam potrebni RSS tagovi koje Castopod ne obrađuje, postavite ih ovde.', - 'custom_rss' => 'Posebni RSS tagovi epizode', - 'custom_rss_hint' => 'Ovo će biti ubačeno u ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'Novi URL fid', - 'new_feed_url_hint' => 'Koristite ovo polje kada prelazite na drugi domen ili platformu za hostovanje podkasta. Podrazumevano, vrednost je podešena na trenutni RSS URL ako je podkast uvezen.', - 'old_feed_url' => 'Stari URL fid', - 'partnership' => 'Partnerstvo', - 'partner_id' => 'ID', - 'partner_link_url' => 'URL adresa veze', - 'partner_image_url' => 'URL adresa slike', - 'partner_id_hint' => 'Vaš partnerski ID', - 'partner_link_url_hint' => 'Generička adresa veze partnera', - 'partner_image_url_hint' => 'Generička adresa slike partnera', - 'block' => 'Podkast treba sakriti iz javnih kataloga', - 'block_hint' => - 'Prikazan ili sakriven status podkasta: ukoliko uključite ovu opciju onemogućavate prikazivanje vašeg podkasta na paltformama za slušanje podkasta kao što su Apple Podcasts, Google Podcasts i sličnim direktorijima. (Nije zagarantovano)', - 'complete' => 'Podkast više neće imati novih epizoda', - 'lock' => 'Sprečite kopiranje podkasta', - 'lock_hint' => - 'Cilj ovoga je da komunicira sa drugim podkast platformama i ne dozvoli im da povlače vaš sadržaj. Ukoliko odaberete Da, to znači da će svaki njihov pokušaj da izlistaju vaš sadržaj na svojoj platformi biti odbijen.', - 'submit_create' => 'Napravi podkast', - 'submit_edit' => 'Sačuvaj podkast', - ], - 'category_options' => [ - 'uncategorized' => 'nekategorizovano', - 'arts' => 'Umetnost', - 'business' => 'Posao', - 'comedy' => 'Komedija', - 'education' => 'Obrazovanje', - 'fiction' => 'Fikcija', - 'government' => 'Vlada', - 'health_and_fitness' => 'Zdravlje i Fitnes', - 'history' => 'Istorija', - 'kids_and_family' => 'Deca i Porodica', - 'leisure' => 'Razonoda', - 'music' => 'Muzika', - 'news' => 'Vesti', - 'religion_and_spirituality' => 'Religija i spiritualnost', - 'science' => 'Nauka', - 'society_and_culture' => 'Društvo i Kultura', - 'sports' => 'Sport', - 'technology' => 'Tehnologija', - 'true_crime' => 'Istinski zločini', - 'tv_and_film' => 'Televizija i Film', - 'books' => 'Knjige', - 'design' => 'Dizajn', - 'fashion_and_beauty' => 'Moda i Lepota', - 'food' => 'Hrana', - 'performing_arts' => 'Izvođačka umetnost', - 'visual_arts' => 'Likovna umetnost', - 'careers' => 'Karijera', - 'entrepreneurship' => 'Prednuzetništvo', - 'investing' => 'Investiranje', - 'management' => 'Upravljanje', - 'marketing' => 'Marketing', - 'non_profit' => 'Neprofitna udruženja', - 'comedy_interviews' => 'Komični intervjui', - 'improv' => 'Improvizacija', - 'stand_up' => 'Stendap komedija', - 'courses' => 'Kursevi', - 'how_to' => 'Uradi sam', - 'language_learning' => 'Učenje jezika', - 'self_improvement' => 'Samopoboljšanje', - 'comedy_fiction' => 'Komična fantastika', - 'drama' => 'Drama', - 'science_fiction' => 'Naučna Fantastika', - 'alternative_health' => 'Alternativno zdravlje', - 'fitness' => 'Fitnes', - 'medicine' => 'Medicina', - 'mental_health' => 'Mentalno zdravlje', - 'nutrition' => 'Nutricionizam', - 'sexuality' => 'Seksualnost', - 'education_for_kids' => 'Obrazovanje dece', - 'parenting' => 'Roditeljstvo', - 'pets_and_animals' => 'Ljubimci i životinje', - 'stories_for_kids' => 'Priče za decu', - 'animation_and_manga' => 'Animacija i Manga', - 'automotive' => 'Automobilizam', - 'aviation' => 'Avijacija', - 'crafts' => 'Zanati', - 'games' => 'Igre', - 'hobbies' => 'Hobiji', - 'home_and_garden' => 'Dom i bašta', - 'video_games' => 'Video igre', - 'music_commentary' => 'Komentari muzike', - 'music_history' => 'Istorija muzike', - 'music_interviews' => 'Muzički intervjui', - 'business_news' => 'Vesti iz preduzetništva', - 'daily_news' => 'Dnevne vesti', - 'entertainment_news' => 'Vesti iz zabave', - 'news_commentary' => 'Komentari vesti', - 'politics' => 'Politika', - 'sports_news' => 'Sportske vesti', - 'tech_news' => 'Tehnološke vesti', - 'buddhism' => 'Budizam', - 'christianity' => 'Hrišćanstvo', - 'hinduism' => 'Hinduizam', - 'islam' => 'Islam', - 'judaism' => 'Judeizam', - 'religion' => 'Religija', - 'spirituality' => 'Duhovnost', - 'astronomy' => 'Astronomija', - 'chemistry' => 'Hemija', - 'earth_sciences' => 'Studije zemlje', - 'life_sciences' => 'Studije života', - 'mathematics' => 'Matematika', - 'natural_sciences' => 'Prirodne nauke', - 'nature' => 'Priroda', - 'physics' => 'Fizika', - 'social_sciences' => 'Društvene nauke', - 'documentary' => 'Dokumentarni', - 'personal_journals' => 'Lični dnevnici', - 'philosophy' => 'Filozofija', - 'places_and_travel' => 'Mesta i Putovanje', - 'relationships' => 'Veze', - 'baseball' => 'Bejzbol', - 'basketball' => 'Košarka', - 'cricket' => 'Kriket', - 'fantasy_sports' => 'Fantazi sport', - 'football' => 'Američki fudbal', - 'golf' => 'Golf', - 'hockey' => 'Hokej', - 'rugby' => 'Ragbi', - 'running' => 'Trčanje', - 'soccer' => 'Fudbal', - 'swimming' => 'Plivanje', - 'tennis' => 'Tenis', - 'volleyball' => 'Odbojka', - 'wilderness' => 'Divljina', - 'wrestling' => 'Rvanje', - 'after_shows' => 'Posle emisija', - 'film_history' => 'Filmska istorija', - 'film_interviews' => 'Filmski intervjui', - 'film_reviews' => 'Filmske recenzije', - 'tv_reviews' => 'Televizijske recenzije', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Nazad na komandnu tablu podkasta', - 'post' => 'Najava vaše objave', - 'post_hint' => - "Napišite poruku kako bi ste najavili objavljivanje vašeg podkasta. Ova poruka će biti istaknuta na početnoj stranici vašeg podkasta.", - 'message_placeholder' => 'Napišite poruku…', - 'submit' => 'Objavi', - 'publication_date' => 'Datum objavljivanja', - 'publication_method' => [ - 'now' => 'Sada', - 'schedule' => 'Raspored', - ], - 'scheduled_publication_date' => 'Planiran datum objave', - 'scheduled_publication_date_hint' => - 'Možete zakazati objavu podkasta u budućnosti. Ovo polje mora biti popunjeno u YYYY-MM-DD HH:mm formatu', - 'submit_edit' => 'Uredi objavu', - 'cancel_publication' => 'Poništi objavu', - 'message_warning' => 'Niste napisali poruku za najavu objave!', - 'message_warning_hint' => 'Poruka povećava šanse za angažovanjem na društvenim mrežama, rezultirajući u većoj vidljivosti vašeg podkasta.', - 'message_warning_submit' => 'Objavi svakako', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'režim nacrta', - 'not_published' => 'Ovaj podkast nije još uvek objavljen.', - 'scheduled' => 'Ovaj podkast je zakazan za objavu {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Brisanjem podkasta obrisaće se i sve epizode, medijske datoteke, objave i analitika povezana sa njim. Ova radnja je nepovratna, nakon toga nećete više moći da ih preuzmete ili povratite.", - 'understand' => 'Razumem, želim da trajno obrišem podkast', - 'submit' => 'Obriši', - ], - 'by' => 'Od {publisher}', - 'season' => 'Sezona {seasonNumber}', - 'list_of_episodes_year' => '{year} epizoda ({episodeCount})', - 'list_of_episodes_season' => - 'Sezona {seasonNumber} epizoda ({episodeCount})', - 'no_episode' => 'Nijedna epizode nije pronađena!', - 'follow' => 'Prati', - 'followers' => '{numberOfFollowers, plural, - one {# pratilac} - other {# pratilaca} - }', - 'posts' => '{numberOfPosts, plural, - one {# objava} - other {# objave} - }', - 'activity' => 'Aktivnost', - 'episodes' => 'Epizode', - 'sponsor' => 'Sponzor', - 'funding_links' => 'Linkovi za finansiranje {podcastTitle}', - 'find_on' => 'Pronađi {podcastTitle} na', - 'listen_on' => 'Slušaj na', -]; diff --git a/modules/Admin/Language/sr-latn/PodcastNavigation.php b/modules/Admin/Language/sr-latn/PodcastNavigation.php deleted file mode 100644 index 5958a625..00000000 --- a/modules/Admin/Language/sr-latn/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Idite na stranu podkasta', - 'rss_feed' => 'RSS izvor', - 'dashboard' => 'Kontrolna strana podkasta', - 'podcast-view' => 'Početna stranica', - 'podcast-edit' => 'Uredi podkast', - 'podcast-persons-manage' => 'Upravljaj osobama', - 'podcast-imports' => 'Uvozi podkasta', - 'podcast-imports-sync' => 'Sinhronizuj snabdevače', - 'episodes' => 'Epizode', - 'episode-list' => 'Sve Epizode', - 'episode-create' => 'Nova epizoda', - 'analytics' => 'Analitika', - 'podcast-analytics' => 'Pregled publike', - 'podcast-analytics-webpages' => 'Poseta Veb stranici', - 'podcast-analytics-locations' => 'Lokacije', - 'podcast-analytics-unique-listeners' => 'Jedinstveni slušaoci', - 'podcast-analytics-players' => 'Plejeri', - 'podcast-analytics-listening-time' => 'Ukupno vreme slušanja', - 'podcast-analytics-time-periods' => 'Vremenski periodi', - 'monetization' => 'Monetizacija', - 'subscription-list' => 'Sve pretplate', - 'subscription-create' => 'Dodaj pretplatu', - 'contributors' => 'Saradnici', - 'contributor-list' => 'Svi saradnici', - 'contributor-add' => 'Dodaj saradnika', - 'broadcast' => 'Emitovanje', - 'platforms-podcasting' => 'Podkasting aplikacije', - 'platforms-social' => 'Društvene mreže', - 'platforms-funding' => 'Podrška', - 'podcast-monetization-other' => 'Drugo', -]; diff --git a/modules/Admin/Language/sr-latn/Settings.php b/modules/Admin/Language/sr-latn/Settings.php deleted file mode 100644 index 82554b3c..00000000 --- a/modules/Admin/Language/sr-latn/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'Opšta podešavanja', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Ikonica sajta', - 'site_icon_delete' => 'Obriši ikonicu sajta', - 'site_icon_hint' => 'Ikone sajtova su ono što vidite na karticama pregledača, traci sa obeleživačima i kada dodate veb lokaciju kao prečicu na mobilnim uređajima.', - 'site_icon_helper' => 'Ikona mora biti kvadratnog oblika i minimum 512px široka i visoka.', - 'site_name' => 'Naziv veb strane', - 'site_description' => 'Opis veb strane', - 'submit' => 'Sačuvaj', - 'editSuccess' => 'Instanca je uspešno ažurirana!', - 'deleteIconSuccess' => 'Ikona veb strane je uspešno uklonjena!', - ], - 'images' => [ - 'title' => 'Slike', - 'subtitle' => 'Ovde možete regenerisati sve slike na osnovu originala koji su otpremljeni. Koristi se ako ustanovite da neke slike nedostaju. Ovaj zadatak može potrajati.', - 'regenerate' => 'Regeneriši slike', - 'regenerationSuccess' => 'Sve slike su uspešno regenerisane!', - ], - 'housekeeping' => [ - 'title' => 'Održavanje', - 'subtitle' => 'Obavlja razne poslove u održavanju. Koristite ovu funkciju ako ikada naiđete na probleme sa medijskim datotekama ili integritetom podataka. Ovi zadaci mogu potrajati.', - 'reset_counts' => 'Resetujte brojače', - 'reset_counts_helper' => 'Ova opcija će ponovo izračunati i resetovati sve podatke (broj pratilaca, objava, komentara,…).', - 'rewrite_media' => 'Ponovo upiši medijske metapodatke', - 'rewrite_media_helper' => 'Ova opcija će izbrisati sve suvišne medijske datoteke i ponovo ih kreirati (slike, audio datoteke, transkripte, poglavlja,…)', - 'rename_episodes_files' => 'Preimenuj audio datoteku epizode', - 'rename_episodes_files_hint' => 'Ova opcija će preimenovati sve audio datoteke epizoda u nasumični niz znakova. Koristite ovo ako je neka od vaših privatnih epizoda procurila jer će je to efektivno sakriti.', - 'clear_cache' => 'Obriši sav keš', - 'clear_cache_helper' => 'Ova opcija će isprazniti redis keš ili datoteke za pisanje/keširanje.', - 'run' => 'Pokreni održavanje', - 'runSuccess' => 'Održavanje je uspešno obavljeno!', - ], - 'theme' => [ - 'title' => 'Tema', - 'accent_section_title' => 'Naglašena boja', - 'accent_section_subtitle' => 'Izaberite boju da biste odredili izgled svih javnih stranica.', - 'pine' => 'Bor zelena', - 'crimson' => 'Tamnocrvena', - 'amber' => 'Ćilibar', - 'lake' => 'Jezero plava', - 'jacaranda' => 'Jakaranda ljubičasta', - 'onyx' => 'Oniks crna', - 'submit' => 'Sačuvaj', - 'setInstanceThemeSuccess' => 'Tema je uspešno ažurirana!', - ], -]; diff --git a/modules/Admin/Language/sr-latn/Soundbite.php b/modules/Admin/Language/sr-latn/Soundbite.php deleted file mode 100644 index 306681f9..00000000 --- a/modules/Admin/Language/sr-latn/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Zvučni isečci', - 'soundbite' => 'Zvučni isečak', - ], - 'messages' => [ - 'createSuccess' => 'Zvučni isečak je uspešno kreiran!', - 'deleteSuccess' => 'Zvučni isečak je uspešno uklonjen!', - ], - 'form' => [ - 'title' => 'Novi zvučni isečak', - 'soundbite_title' => 'Naziv zvučnog isečka', - 'start_time' => 'Počni na', - 'duration' => 'Trajanje', - 'submit' => 'Napravi zvučni isečak', - ], - 'play' => 'Reprodukuj zvučni isečak', - 'stop' => 'Zaustavi zvučni isečak', - 'create' => 'Novi zvučni isečak', - 'delete' => 'Obriši zvučni isečak', -]; diff --git a/modules/Admin/Language/sr-latn/Validation.php b/modules/Admin/Language/sr-latn/Validation.php deleted file mode 100644 index d83783d4..00000000 --- a/modules/Admin/Language/sr-latn/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} ili nije slika ili nije dovoljne dužine/visine.', - 'is_image_ratio' => - '{field} ili nije slike ili nije u pravom odnosu veličina.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/sr-latn/VideoClip.php b/modules/Admin/Language/sr-latn/VideoClip.php deleted file mode 100644 index aa0d795b..00000000 --- a/modules/Admin/Language/sr-latn/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video isečci', - 'status' => [ - 'label' => 'Status', - 'queued' => 'čekanje', - 'queued_hint' => 'Video isečak čeka na obradu.', - 'pending' => 'na čekanju', - 'pending_hint' => 'Video isečak će uskoro biti napravljen.', - 'running' => 'u toku', - 'running_hint' => 'Video isečak se pravi.', - 'failed' => 'nije uspеlo', - 'failed_hint' => 'Pravljenje video isečka nije uspelo: greška u skripti.', - 'passed' => 'prošlo', - 'passed_hint' => 'Video isečak je uspešno napravljen!', - ], - 'clip' => 'Isečak', - 'duration' => 'Trajanje posla', - ], - 'title' => 'Video Isečak: {videoClipLabel}', - 'download_clip' => 'Preuzmi isečak', - 'create' => 'Novi video isečak', - 'go_to_page' => 'Idi na stranicu isečka', - 'retry' => 'Ponovo pokušaj da napraviš isečak', - 'delete' => 'Obriši isečak', - 'logs' => 'Katalog poslova', - 'messages' => [ - 'alreadyExistingError' => 'Video isečak koji pokušavate da napravite već postoji!', - 'addToQueueSuccess' => 'Video isečak je dodat u katalog poslova, čeka da bude napravljen!', - 'deleteSuccess' => 'Video isečak je uspešno uklonjen!', - ], - 'format' => [ - 'landscape' => 'Položeno', - 'portrait' => 'Uspravno', - 'squared' => 'Kvadratno', - ], - 'form' => [ - 'title' => 'Novi video isečak', - 'params_section_title' => 'Parametri video isečka', - 'clip_title' => 'Naziv isečka', - 'format' => [ - 'label' => 'Odaberite format', - 'landscape_hint' => 'U 16:9 formatu, položeni video klipovi su odlični za platforme kao što su PeerTube, YouTube i Vimeo.', - 'portrait_hint' => 'U 9:16 formatu, uspravni video isečci su odlični za TikTok, YouTube shorts i Instagram stories.', - 'squared_hint' => 'U 1:1 formatu, kvadratni video isečci su odlični za Mastodon, Facebook, Twitter i LinkedIn.', - ], - 'theme' => 'Odaberite temu', - 'start_time' => 'Počni na', - 'duration' => 'Trajanje', - 'trim_start' => 'Početak isečka', - 'trim_end' => 'Kraj isečka', - 'submit' => 'Napravi video isečak', - ], - 'requirements' => [ - 'title' => 'Nedostaje polje', - 'missing' => 'Niste popunili sva polja. Potrudite se da ubacite sve što je potrebno kako bi ste napravili video za ovu epizodu!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Datoteka transkripta (.srt)', - ], -]; diff --git a/modules/Admin/Language/sv/AboutCastopod.php b/modules/Admin/Language/sv/AboutCastopod.php deleted file mode 100644 index f9707cbe..00000000 --- a/modules/Admin/Language/sv/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'Om Castopod', - 'host_name' => 'Värdnamn', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operativsystem', - 'languages' => 'Språk', - 'update_database' => 'Uppdatera databas', - 'messages' => [ - 'databaseUpdateSuccess' => 'Databasen är uppdaterad!', - ], -]; diff --git a/modules/Admin/Language/sv/Breadcrumb.php b/modules/Admin/Language/sv/Breadcrumb.php index 7acad68e..f3269bfa 100644 --- a/modules/Admin/Language/sv/Breadcrumb.php +++ b/modules/Admin/Language/sv/Breadcrumb.php @@ -11,47 +11,42 @@ declare(strict_types=1); return [ 'label' => 'breadcrumb', config('Admin') - ->gateway => 'Hem', + ->gateway => 'Home', 'podcasts' => 'podcasts', - 'episodes' => 'avsnitt', - 'subscriptions' => 'prenumerationer', - 'contributors' => 'bidragsgivare', - 'pages' => 'sidor', - 'settings' => 'inställningar', - 'theme' => 'tema', - 'about' => 'om', - 'add' => 'lägg till', - 'new' => 'ny', - 'edit' => 'redigera', - 'persons' => 'personer', - 'publish' => 'publicera', - 'publish-edit' => 'redigera publikation', - 'publish-date-edit' => 'redigera publiceringsdatum', - 'unpublish' => 'avpublicera', - 'delete' => 'radera', - 'remove' => 'ta bort', + 'episodes' => 'episodes', + 'subscriptions' => 'subscriptions', + 'contributors' => 'contributors', + 'pages' => 'pages', + 'settings' => 'settings', + 'theme' => 'theme', + 'add' => 'add', + 'new' => 'new', + 'edit' => 'edit', + 'persons' => 'persons', + 'publish' => 'publish', + 'publish-edit' => 'edit publication', + 'publish-date-edit' => 'edit publication date', + 'unpublish' => 'unpublish', + 'delete' => 'delete', 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'användare', - 'my-account' => 'mitt konto', - 'change-password' => 'ändra lösenord', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'plattformar', - 'social' => 'sociala nätverk', - 'funding' => 'finansiering', - 'monetization-other' => 'other monetization', - 'analytics' => 'analys', - 'locations' => 'platser', - 'webpages' => 'webbplatser', - 'unique-listeners' => 'unika lyssnare', - 'players' => 'spelare', - 'listening-time' => 'lyssningstid', - 'time-periods' => 'tidsperiod', - 'soundbites' => 'ljudklipp', - 'video-clips' => 'videoklipp', - 'embed' => 'inbäddad spelare', - 'notifications' => 'aviseringar', - 'suspend' => 'suspendera', + 'block-lists' => 'block lists', + 'users' => 'users', + 'my-account' => 'my account', + 'change-password' => 'change password', + 'import' => 'feed import', + 'platforms' => 'platforms', + 'social' => 'social networks', + 'funding' => 'funding', + 'analytics' => 'analytics', + 'locations' => 'locations', + 'webpages' => 'web pages', + 'unique-listeners' => 'unique listeners', + 'players' => 'players', + 'listening-time' => 'listening time', + 'time-periods' => 'time periods', + 'soundbites' => 'soundbites', + 'video-clips' => 'video clips', + 'embed' => 'embeddable player', + 'notifications' => 'notifications', + 'suspend' => 'suspend', ]; diff --git a/modules/Admin/Language/sv/Charts.php b/modules/Admin/Language/sv/Charts.php index 868b40fd..4b33530e 100644 --- a/modules/Admin/Language/sv/Charts.php +++ b/modules/Admin/Language/sv/Charts.php @@ -9,33 +9,32 @@ declare(strict_types=1); */ return [ - 'by_service_weekly' => 'Avsnitt nedladdningar via tjänst (under den senaste veckan)', - 'by_player_weekly' => 'Nedladdningar av avsnitt via spelare (under den senaste veckan)', - 'by_player_yearly' => 'Nedladdningar av avsnitt via spelare (under det gångna året)', - 'by_device_weekly' => 'Avsnitt nedladdningar per enhet (föregående veckan)', - 'by_os_weekly' => 'Avsnitt nedladdningar av O.S. (för den föregående veckan)', - 'podcast_by_region' => 'Nedladdningar av avsnitt efter region (under den föregående veckan)', - 'unique_daily_listeners' => 'Dagliga unika lyssnare', - 'unique_monthly_listeners' => 'Unika lyssnare varje månad', - 'by_browser' => 'Webbsidor användning av webbläsare (under den föregående veckan)', - 'podcast_by_day' => 'Avsnitt dagliga nedladdningar', - 'podcast_by_month' => 'Månatliga nedladdningar av avsnitt', - 'episode_by_day' => 'Avsnitt dagliga nedladdningar (första 60 dagar)', - 'episode_by_month' => 'Månatliga nedladdningar av avsnitt', + 'by_service_weekly' => 'Episode downloads by service (for the past week)', + 'by_player_weekly' => 'Episode downloads by player (for the past week)', + 'by_player_yearly' => 'Episode downloads by player (for the past year)', + 'by_device_weekly' => 'Episode downloads by device (for the past week)', + 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', + 'podcast_by_region' => 'Episode downloads by region (for the past week)', + 'unique_daily_listeners' => 'Daily unique listeners', + 'unique_monthly_listeners' => 'Monthly unique listeners', + 'by_browser' => 'Web pages usage by browser (for the past week)', + 'podcast_by_day' => 'Episode daily downloads', + 'podcast_by_month' => 'Episode monthly downloads', + 'episode_by_day' => 'Episode daily downloads (first 60 days)', + 'episode_by_month' => 'Episode monthly downloads', 'episodes_by_day' => - '5 senaste avsnitt nedladdningar (under sina första 60 dagar)', - 'by_country_weekly' => 'Nedladdningar av avsnitt per land (under den föregående veckan)', - 'by_country_yearly' => 'Nedladdningar av avsnitt per land (för föregående året)', - 'by_domain_weekly' => 'Webbsidor besök per källa (under föregående veckan)', - 'by_domain_yearly' => 'Webbsidor besök per källa (för det gångna året)', - 'by_entry_page' => 'Webbsidor besök via startsida (under den föregående veckan)', + '5 latest episodes downloads (during their first 60 days)', + 'by_country_weekly' => 'Episode downloads by country (for the past week)', + 'by_country_yearly' => 'Episode downloads by country (for the past year)', + 'by_domain_weekly' => 'Web pages visits by source (for the past week)', + 'by_domain_yearly' => 'Web pages visits by source (for the past year)', + 'by_entry_page' => 'Web pages visits by landing page (for the past week)', 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daglig kumulativ lyssningstid', - 'monthly_listening_time' => 'Månatlig kumulativ lyssningstid', - 'by_weekday' => 'Efter veckodag (för de senaste 60 dagarna)', - 'by_hour' => 'Via tiden på dagen (de senaste 60 dagarna)', - 'podcast_by_bandwidth' => 'Dagligen använd bandbredd (i MB)', - 'total_storage_by_month' => 'Månadslagring (i MB)', - 'total_bandwidth_by_month' => 'Månatlig använd bandbredd (i MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', + 'daily_listening_time' => 'Daily cumulative listening time', + 'monthly_listening_time' => 'Monthly cumulative listening time', + 'by_weekday' => 'By week day (for the past 60 days)', + 'by_hour' => 'By time of day (for the past 60 days)', + 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', + 'total_storage_by_month' => 'Monthly storage (in MB)', + 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', ]; diff --git a/modules/Admin/Language/sv/Common.php b/modules/Admin/Language/sv/Common.php index 465f8c4c..596c8bcd 100644 --- a/modules/Admin/Language/sv/Common.php +++ b/modules/Admin/Language/sv/Common.php @@ -9,44 +9,43 @@ declare(strict_types=1); */ return [ - 'yes' => 'Ja', - 'no' => 'Nej', - 'cancel' => 'Avbryt', - 'optional' => 'Valfritt', - 'more' => 'Mer', - 'no_data' => 'Ingen data hittades!', - 'close' => 'Stäng', - 'edit' => 'Redigera', - 'copy' => 'Kopiera', - 'copied' => 'Kopierad!', - 'home' => 'Hem', - 'explicit' => 'Uteslutande', - 'powered_by' => 'Drivs av {castopod}', - 'actions' => 'Åtgärder', - 'pageInfo' => 'Sida {currentPage} av {pageCount}', - 'go_back' => 'Gå tillbaka', + 'yes' => 'Yes', + 'no' => 'No', + 'cancel' => 'Cancel', + 'optional' => 'Optional', + 'more' => 'More', + 'no_data' => 'No data found!', + 'close' => 'Close', + 'edit' => 'Edit', + 'copy' => 'Copy', + 'copied' => 'Copied!', + 'home' => 'Home', + 'explicit' => 'Explicit', + 'powered_by' => 'Powered by {castopod}', + 'actions' => 'Actions', + 'pageInfo' => 'Page {currentPage} out of {pageCount}', + 'go_back' => 'Go back', 'forms' => [ 'editor' => [ - 'write' => 'Skriv', - 'preview' => 'Förhandsgranska', - 'help' => 'Drivs av markdown', + 'write' => 'Write', + 'preview' => 'Preview', + 'help' => 'Powered by markdown', ], 'multiSelect' => [ - 'selectText' => 'Tryck för att välja', - 'loadingText' => 'Laddar…', - 'noResultsText' => 'Hittade inga resultat', - 'noChoicesText' => 'Inga val att välja mellan', - 'maxItemText' => 'Kan inte lägga till fler objekt', + 'selectText' => 'Press to select', + 'loadingText' => 'Loading…', + 'noResultsText' => 'No results found', + 'noChoicesText' => 'No choices to choose from', + 'maxItemText' => 'Cannot add more items', ], - 'upload_file' => 'Ladda upp en fil', - 'remote_url' => 'Fjärr URL', - 'save' => 'Spara', + 'upload_file' => 'Upload a file', + 'remote_url' => 'Remote URL', ], 'play_episode_button' => [ - 'play' => 'Spela', - 'playing' => 'Spelar', + 'play' => 'Play', + 'playing' => 'Playing', ], - 'size_limit' => 'Storleksgräns: {0}.', - 'choose_interact' => 'Välj hur du vill interagera', - 'view' => 'Visa', + 'size_limit' => 'Size limit: {0}.', + 'choose_interact' => 'Choose how to interact', + 'view' => 'View', ]; diff --git a/modules/Admin/Language/sv/Contributor.php b/modules/Admin/Language/sv/Contributor.php new file mode 100644 index 00000000..d0f3b93d --- /dev/null +++ b/modules/Admin/Language/sv/Contributor.php @@ -0,0 +1,41 @@ + 'Podcast contributors', + 'view' => "{username}'s contribution to {podcastTitle}", + 'add' => 'Add contributor', + 'add_contributor' => 'Add a contributor for {0}', + 'edit_role' => 'Update role for {0}', + 'edit' => 'Edit', + 'remove' => 'Remove', + 'list' => [ + 'username' => 'Username', + 'role' => 'Role', + ], + 'form' => [ + 'user' => 'User', + 'user_placeholder' => 'Select a user…', + 'role' => 'Role', + 'role_placeholder' => 'Select its role…', + 'submit_add' => 'Add contributor', + 'submit_edit' => 'Update role', + ], + 'roles' => [ + 'podcast_admin' => 'Podcast admin', + ], + 'messages' => [ + 'removeOwnerError' => "You can't remove the podcast owner!", + 'removeSuccess' => + 'You have successfully removed {username} from {podcastTitle}', + 'alreadyAddedError' => + "The contributor you're trying to add has already been added!", + ], +]; diff --git a/modules/Admin/Language/sv/Countries.php b/modules/Admin/Language/sv/Countries.php index 1aed3bb0..4cd5d9c8 100644 --- a/modules/Admin/Language/sv/Countries.php +++ b/modules/Admin/Language/sv/Countries.php @@ -12,253 +12,253 @@ declare(strict_types=1); return [ 'AD' => 'Andorra', - 'AE' => 'Förenade Arabemiraten', + 'AE' => 'United Arab Emirates', 'AF' => 'Afghanistan', - 'AG' => 'Antigua och Barbuda', + 'AG' => 'Antigua and Barbuda', 'AI' => 'Anguilla', - 'AL' => 'Albanien', - 'AM' => 'Armenien', + 'AL' => 'Albania', + 'AM' => 'Armenia', 'AO' => 'Angola', - 'AQ' => 'Antarktis', + 'AQ' => 'Antarctica', 'AR' => 'Argentina', - 'AS' => 'Amerikanska Samoaöarna', - 'AT' => 'Österrike', - 'AU' => 'Australien', + 'AS' => 'American Samoa', + 'AT' => 'Austria', + 'AU' => 'Australia', 'AW' => 'Aruba', - 'AX' => 'Åland', - 'AZ' => 'Azerbajdzjan', - 'BA' => 'Bosnien och Hercegovina', + 'AX' => 'Åland Islands', + 'AZ' => 'Azerbaijan', + 'BA' => 'Bosnia and Herzegovina', 'BB' => 'Barbados', 'BD' => 'Bangladesh', - 'BE' => 'Belgien', + 'BE' => 'Belgium', 'BF' => 'Burkina Faso', - 'BG' => 'Bulgarien', + 'BG' => 'Bulgaria', 'BH' => 'Bahrain', 'BI' => 'Burundi', 'BJ' => 'Benin', 'BL' => 'Saint Barthélemy', 'BM' => 'Bermuda', 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia', - 'BQ' => 'Bonaire', - 'BR' => 'Brasilien', + 'BO' => 'Bolivia, Plurinational State of', + 'BQ' => 'Bonaire, Sint Eustatius and Saba', + 'BR' => 'Brazil', 'BS' => 'Bahamas', 'BT' => 'Bhutan', - 'BV' => 'Bouvetön', + 'BV' => 'Bouvet Island', 'BW' => 'Botswana', - 'BY' => 'Vitryssland', + 'BY' => 'Belarus', 'BZ' => 'Belize', - 'CA' => 'Kanada', - 'CC' => 'Kokosöarna', - 'CD' => 'Kongo, Demokratiska republiken Kongo', - 'CF' => 'Centralafrikanska republiken', - 'CG' => 'Kongo', - 'CH' => 'Schweiz', - 'CI' => "Elfenbenskusten", - 'CK' => 'Cooköarna', + 'CA' => 'Canada', + 'CC' => 'Cocos (Keeling) Islands', + 'CD' => 'Congo, the Democratic Republic of the', + 'CF' => 'Central African Republic', + 'CG' => 'Congo', + 'CH' => 'Switzerland', + 'CI' => "Côte d'Ivoire", + 'CK' => 'Cook Islands', 'CL' => 'Chile', - 'CM' => 'Kamerun', - 'CN' => 'Kina', + 'CM' => 'Cameroon', + 'CN' => 'China', 'CO' => 'Colombia', 'CR' => 'Costa Rica', - 'CU' => 'Kuba', - 'CV' => 'Kap Verde', - 'CW' => 'Curacao', - 'CX' => 'Julön', - 'CY' => 'Cypern', - 'CZ' => 'Tjeckien', - 'DE' => 'Tyskland', + 'CU' => 'Cuba', + 'CV' => 'Cape Verde', + 'CW' => 'Curaçao', + 'CX' => 'Christmas Island', + 'CY' => 'Cyprus', + 'CZ' => 'Czech Republic', + 'DE' => 'Germany', 'DJ' => 'Djibouti', - 'DK' => 'Danmark', + 'DK' => 'Denmark', 'DM' => 'Dominica', - 'DO' => 'Dominikanska republiken', - 'DZ' => 'Algeriet', + 'DO' => 'Dominican Republic', + 'DZ' => 'Algeria', 'EC' => 'Ecuador', - 'EE' => 'Estland', - 'EG' => 'Egypten', - 'EH' => 'Västsahara', + 'EE' => 'Estonia', + 'EG' => 'Egypt', + 'EH' => 'Western Sahara', 'ER' => 'Eritrea', - 'ES' => 'Spanien', - 'ET' => 'Etiopien', + 'ES' => 'Spain', + 'ET' => 'Ethiopia', 'FI' => 'Finland', 'FJ' => 'Fiji', - 'FK' => 'Falklandsöarna (Malvinas)', - 'FM' => 'Mikronesien, Federerade Stater', - 'FO' => 'Färöarna', - 'FR' => 'Frankrike', + 'FK' => 'Falkland Islands (Malvinas)', + 'FM' => 'Micronesia, Federated States of', + 'FO' => 'Faroe Islands', + 'FR' => 'France', 'GA' => 'Gabon', - 'GB' => 'Storbritannien', + 'GB' => 'United Kingdom', 'GD' => 'Grenada', - 'GE' => 'Georgien', - 'GF' => 'Franska Guyana', + 'GE' => 'Georgia', + 'GF' => 'French Guiana', 'GG' => 'Guernsey', 'GH' => 'Ghana', 'GI' => 'Gibraltar', - 'GL' => 'Grönland', + 'GL' => 'Greenland', 'GM' => 'Gambia', 'GN' => 'Guinea', 'GP' => 'Guadeloupe', 'GQ' => 'Equatorial Guinea', - 'GR' => 'Grekland', - 'GS' => 'Sydgeorgien och Sydsandwichöarna', + 'GR' => 'Greece', + 'GS' => 'South Georgia and the South Sandwich Islands', 'GT' => 'Guatemala', 'GU' => 'Guam', 'GW' => 'Guinea-Bissau', 'GY' => 'Guyana', - 'HK' => 'Hongkong', - 'HM' => 'Heard Island och McDonaldsöarna', + 'HK' => 'Hong Kong', + 'HM' => 'Heard Island and McDonald Islands', 'HN' => 'Honduras', - 'HR' => 'Kroatien', + 'HR' => 'Croatia', 'HT' => 'Haiti', - 'HU' => 'Ungern', - 'ID' => 'Indonesien', - 'IE' => 'Irland', + 'HU' => 'Hungary', + 'ID' => 'Indonesia', + 'IE' => 'Ireland', 'IL' => 'Israel', 'IM' => 'Isle of Man', - 'IN' => 'Indien', - 'IO' => 'Brittiska territoriet i Indiska oceanen', - 'IQ' => 'Irak', - 'IR' => 'Iran, Islamiska republiken av', - 'IS' => 'Island', - 'IT' => 'Italien', + 'IN' => 'India', + 'IO' => 'British Indian Ocean Territory', + 'IQ' => 'Iraq', + 'IR' => 'Iran, Islamic Republic of', + 'IS' => 'Iceland', + 'IT' => 'Italy', 'JE' => 'Jersey', 'JM' => 'Jamaica', - 'JO' => 'Jordanien', + 'JO' => 'Jordan', 'JP' => 'Japan', 'KE' => 'Kenya', 'KG' => 'Kyrgyzstan', - 'KH' => 'Kambodja', + 'KH' => 'Cambodia', 'KI' => 'Kiribati', - 'KM' => 'Komorerna', - 'KN' => 'Saint Kitts och Nevis', - 'KP' => "Nordkorea", - 'KR' => 'Sydkorea', + 'KM' => 'Comoros', + 'KN' => 'Saint Kitts and Nevis', + 'KP' => "Korea, Democratic People's Republic of", + 'KR' => 'Korea, Republic of', 'KW' => 'Kuwait', - 'KY' => 'Caymanöarna', - 'KZ' => 'Kazakstan', - 'LA' => "Laos", - 'LB' => 'Libanon', - 'LC' => 'Sankt Lucia', + 'KY' => 'Cayman Islands', + 'KZ' => 'Kazakhstan', + 'LA' => "Lao People's Democratic Republic", + 'LB' => 'Lebanon', + 'LC' => 'Saint Lucia', 'LI' => 'Liechtenstein', 'LK' => 'Sri Lanka', - 'LR' => 'Liberien', + 'LR' => 'Liberia', 'LS' => 'Lesotho', - 'LT' => 'Litauen', + 'LT' => 'Lithuania', 'LU' => 'Luxembourg', - 'LV' => 'Lettland', - 'LY' => 'Libyen', - 'MA' => 'Marocko', + 'LV' => 'Latvia', + 'LY' => 'Libya', + 'MA' => 'Morocco', 'MC' => 'Monaco', - 'MD' => 'Moldavien', + 'MD' => 'Moldova, Republic of', 'ME' => 'Montenegro', - 'MF' => 'Saint Martin', - 'MG' => 'Madagaskar', - 'MH' => 'Marshallöarna', - 'MK' => 'Makedonien', + 'MF' => 'Saint Martin (French part)', + 'MG' => 'Madagascar', + 'MH' => 'Marshall Islands', + 'MK' => 'Macedonia, the Former Yugoslav Republic of', 'ML' => 'Mali', 'MM' => 'Myanmar', - 'MN' => 'Mongoliet', + 'MN' => 'Mongolia', 'MO' => 'Macao', - 'MP' => 'Nordmarianerna', + 'MP' => 'Northern Mariana Islands', 'MQ' => 'Martinique', 'MR' => 'Mauritania', 'MS' => 'Montserrat', 'MT' => 'Malta', 'MU' => 'Mauritius', - 'MV' => 'Maldiverna', + 'MV' => 'Maldives', 'MW' => 'Malawi', - 'MX' => 'Mexiko', + 'MX' => 'Mexico', 'MY' => 'Malaysia', - 'MZ' => 'Moçambique', - 'N/A' => 'Ej tillämplig (lokal IP…)', + 'MZ' => 'Mozambique', + 'N/A' => 'Not Applicable (local IP…)', 'NA' => 'Namibia', - 'NC' => 'Nya Kaledonien', + 'NC' => 'New Caledonia', 'NE' => 'Niger', - 'NF' => 'Norfolkön', + 'NF' => 'Norfolk Island', 'NG' => 'Nigeria', 'NI' => 'Nicaragua', - 'NL' => 'Nederländerna', - 'NO' => 'Norge', + 'NL' => 'Netherlands', + 'NO' => 'Norway', 'NP' => 'Nepal', 'NR' => 'Nauru', 'NU' => 'Niue', - 'NZ' => 'Nya Zeeland', + 'NZ' => 'New Zealand', 'OM' => 'Oman', 'PA' => 'Panama', 'PE' => 'Peru', - 'PF' => 'Franska Polynesien', - 'PG' => 'Papua Nya Guinea', - 'PH' => 'Filippinerna', + 'PF' => 'French Polynesia', + 'PG' => 'Papua New Guinea', + 'PH' => 'Philippines', 'PK' => 'Pakistan', - 'PL' => 'Polen', - 'PM' => 'Saint Pierre och Miquelon', + 'PL' => 'Poland', + 'PM' => 'Saint Pierre and Miquelon', 'PN' => 'Pitcairn', 'PR' => 'Puerto Rico', - 'PS' => 'Palestina', + 'PS' => 'Palestine, State of', 'PT' => 'Portugal', 'PW' => 'Palau', 'PY' => 'Paraguay', 'QA' => 'Qatar', 'RE' => 'Réunion', - 'RO' => 'Rumänien', - 'RS' => 'Serbien', - 'RU' => 'Ryssland', + 'RO' => 'Romania', + 'RS' => 'Serbia', + 'RU' => 'Russian Federation', 'RW' => 'Rwanda', - 'SA' => 'Saudiarabien', - 'SB' => 'Salomonöarna', - 'SC' => 'Seychellerna', + 'SA' => 'Saudi Arabia', + 'SB' => 'Solomon Islands', + 'SC' => 'Seychelles', 'SD' => 'Sudan', - 'SE' => 'Sverige', + 'SE' => 'Sweden', 'SG' => 'Singapore', - 'SH' => 'Sankta Helena, Ascension och Tristan da Cunha', - 'SI' => 'Slovenien', - 'SJ' => 'Svalbard', - 'SK' => 'Slovakien', + 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', + 'SI' => 'Slovenia', + 'SJ' => 'Svalbard and Jan Mayen', + 'SK' => 'Slovakia', 'SL' => 'Sierra Leone', 'SM' => 'San Marino', 'SN' => 'Senegal', 'SO' => 'Somalia', - 'SR' => 'Surinam', - 'SS' => 'Sydsudan', - 'ST' => 'Sao Tome och Principe', + 'SR' => 'Suriname', + 'SS' => 'South Sudan', + 'ST' => 'Sao Tome and Principe', 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (nederländska delen)', - 'SY' => 'Syrien', + 'SX' => 'Sint Maarten (Dutch part)', + 'SY' => 'Syrian Arab Republic', 'SZ' => 'Swaziland', - 'TC' => 'Turks- och Caicosöarna', - 'TD' => 'Tchad', - 'TF' => 'Franska sydterritorierna', + 'TC' => 'Turks and Caicos Islands', + 'TD' => 'Chad', + 'TF' => 'French Southern Territories', 'TG' => 'Togo', 'TH' => 'Thailand', 'TJ' => 'Tajikistan', - 'TK' => 'Tokelauöarna', - 'TL' => 'Östtimor', + 'TK' => 'Tokelau', + 'TL' => 'Timor-Leste', 'TM' => 'Turkmenistan', - 'TN' => 'Tunisien', + 'TN' => 'Tunisia', 'TO' => 'Tonga', - 'TR' => 'Turkiet', - 'TT' => 'Trinidad och Tobago', + 'TR' => 'Turkey', + 'TT' => 'Trinidad and Tobago', 'TV' => 'Tuvalu', - 'TW' => 'Taiwan', - 'TZ' => 'Tanzania', - 'UA' => 'Ukraina', + 'TW' => 'Taiwan, Province of China', + 'TZ' => 'Tanzania, United Republic of', + 'UA' => 'Ukraine', 'UG' => 'Uganda', - 'UM' => 'Förenta staternas mindre öar i Oceanien och Västindien', - 'US' => 'USA', + 'UM' => 'United States Minor Outlying Islands', + 'US' => 'United States', 'UY' => 'Uruguay', 'UZ' => 'Uzbekistan', - 'VA' => 'Vatikanstaten', - 'VC' => 'Saint Vincent och Grenadinerna', - 'VE' => 'Venezuela', - 'VG' => 'Brittiska Jungfruöarna', - 'VI' => 'Amerikanska Jungfruöarna.', - 'VN' => 'Vietnam', + 'VA' => 'Holy See (Vatican City State)', + 'VC' => 'Saint Vincent and the Grenadines', + 'VE' => 'Venezuela, Bolivarian Republic of', + 'VG' => 'Virgin Islands, British', + 'VI' => 'Virgin Islands, U.S.', + 'VN' => 'Viet Nam', 'VU' => 'Vanuatu', - 'WF' => 'Wallis- och Futunaöarna', + 'WF' => 'Wallis and Futuna', 'WS' => 'Samoa', - 'YE' => 'Jemen', + 'YE' => 'Yemen', 'YT' => 'Mayotte', - 'ZA' => 'Sydafrika', + 'ZA' => 'South Africa', 'ZM' => 'Zambia', 'ZW' => 'Zimbabwe', ]; diff --git a/modules/Admin/Language/sv/Dashboard.php b/modules/Admin/Language/sv/Dashboard.php index cf127945..881073fd 100644 --- a/modules/Admin/Language/sv/Dashboard.php +++ b/modules/Admin/Language/sv/Dashboard.php @@ -9,20 +9,20 @@ declare(strict_types=1); */ return [ - 'home' => 'Admin kontrollpanel', - 'welcome_message' => 'Välkommen till adminområdet!', + 'home' => 'Admin dashboard', + 'welcome_message' => 'Welcome to the admin area!', 'podcasts' => [ 'title' => 'Podcasts', - 'not_found' => 'Ingen publicerad podcast', - 'last_published' => 'Senast publicerad den {lastPublicationDate}', + 'not_found' => 'No published podcast', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'episodes' => [ - 'title' => 'Avsnitt', - 'not_found' => 'Inga publicerade avsnitt', - 'last_published' => 'Senast publicerad den {lastPublicationDate}', + 'title' => 'Episodes', + 'not_found' => 'No published episode', + 'last_published' => 'Last published on {lastPublicationDate}', ], 'storage' => [ - 'title' => 'Lagring', - 'subtitle' => '{totalUploaded} av {totalStorage}', + 'title' => 'Storage', + 'subtitle' => '{totalUploaded} out of {totalStorage}', ], ]; diff --git a/modules/Admin/Language/sv/Episode.php b/modules/Admin/Language/sv/Episode.php index 38c7b20c..91313a7c 100644 --- a/modules/Admin/Language/sv/Episode.php +++ b/modules/Admin/Language/sv/Episode.php @@ -9,76 +9,74 @@ declare(strict_types=1); */ return [ - 'season' => 'Säsong {seasonNumber}', + 'season' => 'Season {seasonNumber}', 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Avsnitt {episodeNumber}', - 'number_abbr' => 'Av. {episodeNumber}', - 'season_episode' => 'Säsong {seasonNumber} avsnitt {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}A{episodeNumber}', + 'number' => 'Episode {episodeNumber}', + 'number_abbr' => 'Ep. {episodeNumber}', + 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', + 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', 'number_of_comments' => '{numberOfComments, plural, - one {# kommentar} - other {# kommentarer} + one {# comment} + other {# comments} }', - 'all_podcast_episodes' => 'Alla podcast avsnitt', - 'back_to_podcast' => 'Gå tillbaka till podcasten', - 'edit' => 'Redigera', - 'preview' => 'Preview', - 'publish' => 'Publicera', - 'publish_edit' => 'Redigera publikation', - 'publish_date_edit' => 'Redigera publiceringsdatum', - 'unpublish' => 'Avpublicera', - 'publish_error' => 'Avsnittet är redan publicerat.', - 'publish_edit_error' => 'Avsnittet är redan publicerat.', - 'publish_cancel_error' => 'Avsnittet är redan publicerat.', - 'publish_date_edit_error' => 'Avsnittet har inte publicerats ännu, du kan inte redigera dess publiceringsdatum.', - 'publish_date_edit_future_error' => 'Avsnittets publiceringsdatum kan bara ställas in till ett tidigare datum! Om du vill boka om det, avpublicera det först.', - 'publish_date_edit_success' => 'Avsnittets publiceringsdatum har uppdaterats!', - 'unpublish_error' => 'Avsnittet är inte publicerat.', - 'delete' => 'Radera', - 'go_to_page' => 'Gå till sida', - 'create' => 'Lägg till ett avsnitt', + 'all_podcast_episodes' => 'All podcast episodes', + 'back_to_podcast' => 'Go back to podcast', + 'edit' => 'Edit', + 'publish' => 'Publish', + 'publish_edit' => 'Edit publication', + 'publish_date_edit' => 'Edit publication date', + 'unpublish' => 'Unpublish', + 'publish_error' => 'Episode is already published.', + 'publish_edit_error' => 'Episode is already published.', + 'publish_cancel_error' => 'Episode is already published.', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', + 'unpublish_error' => 'Episode is not published.', + 'delete' => 'Delete', + 'go_to_page' => 'Go to page', + 'create' => 'Add an episode', 'publication_status' => [ - 'published' => 'Publicerad', - 'with_podcast' => 'Publicerad', - 'scheduled' => 'Schemalagd', - 'not_published' => 'Ej publicerat', + 'published' => 'Published', + 'with_podcast' => 'Published', + 'scheduled' => 'Scheduled', + 'not_published' => 'Not published', ], - 'with_podcast_hint' => 'Publiceras samtidigt som podcasten', + 'with_podcast_hint' => 'To be published at the same time as the podcast', 'list' => [ 'search' => [ - 'placeholder' => 'Sök efter ett avsnitt', - 'clear' => 'Rensa sökning', - 'submit' => 'Sök', + 'placeholder' => 'Search for an episode', + 'clear' => 'Clear search', + 'submit' => 'Search', ], 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# avsnitt} - other {# avsnitt} + one {# episode} + other {# episodes} }', - 'episode' => 'Avsnitt', - 'visibility' => 'Synlighet', - 'downloads' => 'Downloads', - 'comments' => 'Kommentarer', - 'actions' => 'Åtgärder', + 'episode' => 'Episode', + 'visibility' => 'Visibility', + 'comments' => 'Comments', + 'actions' => 'Actions', ], 'messages' => [ - 'createSuccess' => 'Avsnittet har skapats!', - 'editSuccess' => 'Avsnittet har uppdaterats!', + 'createSuccess' => 'Episode has been successfully created!', + 'editSuccess' => 'Episode has been successfully updated!', 'publishSuccess' => '{publication_status, select, - published {Avsnittet har publicerats!} - scheduled {Avsnittspubliceringen har planerats!} - with_podcast {Detta avsnitt kommer att publiceras samtidigt som podcasten.} - other {Detta avsnitt är inte publicerad.} + published {Episode successfully published!} + scheduled {Episode publication successfully scheduled!} + with_podcast {This episode will be published at the same time as the podcast.} + other {This episode is not published.} }', - 'publishCancelSuccess' => 'Avsnitt publicering har avbrutits!', - 'unpublishBeforeDeleteTip' => 'Du måste avpublicera avsnittet innan du tar bort det.', - 'scheduleDateError' => 'Schemaläggningsdatum måste anges!', - 'deletePublishedEpisodeError' => 'Avpublicera avsnittet innan du tar bort det.', - 'deleteSuccess' => 'Avsnittet har tagits bort!', - 'deleteError' => 'Misslyckades att ta bort avsnitt {type, select, + 'publishCancelSuccess' => 'Episode publication successfully cancelled!', + 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', + 'scheduleDateError' => 'Schedule date must be set!', + 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', + 'deleteSuccess' => 'Episode successfully deleted!', + 'deleteError' => 'Failed to delete episode {type, select, transcript {transcript} - chapters {kapitel} - image {omslag} - audio {ljud} + chapters {chapters} + image {cover} + audio {audio} other {media} }.', 'deleteFileError' => 'Failed to delete {type, select, @@ -87,139 +85,129 @@ return [ image {cover} audio {audio} other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'Ett avsnitt med den valda slug finns redan.', + } file {file_path}. You may manually remove it from your disk.', + 'sameSlugError' => 'An episode with the chosen slug already exists.', ], 'form' => [ 'file_size_error' => - 'Din filstorlek är för stor! Max storlek är {0}. Öka värdena `memory_limit`, `upload_max_filesize` och `post_max_size` i din php-konfigurationsfil och starta sedan om din webbserver för att ladda upp filen.', - 'audio_file' => 'Ljudfil', - 'audio_file_hint' => 'Välj en. mp3 eller . m4a ljudfil.', - 'info_section_title' => 'Avsnitt information', - 'cover' => 'Avsnitt omslag', + 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', + 'audio_file' => 'Audio file', + 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', + 'info_section_title' => 'Episode info', + 'cover' => 'Episode cover', 'cover_hint' => - 'Om du inte sätter ett omslag kommer podcast-omslaget att användas istället.', - 'cover_size_hint' => 'Omslaget måste vara fyrkantigt och minst 1400px brett och högt.', - 'title' => 'Rubrik', + 'If you do not set a cover, the podcast cover will be used instead.', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', + 'title' => 'Title', 'title_hint' => - 'Bör innehålla ett tydligt och koncist avsnittsnamn. Ange inte avsnitt eller säsongsnummer här.', - 'permalink' => 'Permalänk', - 'season_number' => 'Säsong', - 'episode_number' => 'Avsnitt', + 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', + 'permalink' => 'Permalink', + 'season_number' => 'Season', + 'episode_number' => 'Episode', 'type' => [ - 'label' => 'Typ', + 'label' => 'Type', 'full' => 'Full', - 'full_hint' => 'Komplett innehåll (avsnittet)', + 'full_hint' => 'Complete content (the episode)', 'trailer' => 'Trailer', - 'trailer_hint' => 'Kort, PR-del av innehåll som representerar en förhandsvisning av den aktuella serien', + 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra innehåll för showen (till exempel bakom scenens info eller intervjuer med cast) eller korspremiellt innehåll för en annan show', + 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', ], 'premium_title' => 'Premium', - 'premium' => 'Avsnitt måste endast vara tillgängligt för premiumprenumeranter', + 'premium' => 'Episode must be accessible to premium subscribers only', 'parental_advisory' => [ - 'label' => 'Föräldrarådgivande', - 'hint' => 'Innehåller avsnittet olämpligt innehåll?', - 'undefined' => 'odefinierad', - 'clean' => 'Ren', - 'explicit' => 'Uteslutande', + 'label' => 'Parental advisory', + 'hint' => 'Does the episode contain explicit content?', + 'undefined' => 'undefined', + 'clean' => 'Clean', + 'explicit' => 'Explicit', ], - 'show_notes_section_title' => 'Visa anteckningar', + 'show_notes_section_title' => 'Show notes', 'show_notes_section_subtitle' => - 'Upp till 4000 tecken, var tydlig och koncis. Visa anteckningar hjälper potentiella lyssnare att hitta avsnittet.', - 'description' => 'Beskrivning', - 'description_footer' => 'Beskrivning sidfot', + 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', + 'description' => 'Description', + 'description_footer' => 'Description footer', 'description_footer_hint' => - 'Denna text läggs till i slutet av varje avsnitt beskrivning, det är ett bra ställe att skriva in dina sociala länkar till exempel.', - 'additional_files_section_title' => 'Ytterligare filer', + 'This text is added at the end of each episode description, it is a good place to input your social links for example.', + 'additional_files_section_title' => 'Additional files', 'additional_files_section_subtitle' => - 'Dessa filer kan användas av andra plattformar för att ge bättre upplevelse till din publik. Se {podcastNamespaceLink} för mer information.', - 'location_section_title' => 'Plats', - 'location_section_subtitle' => 'Vilken plats handlar detta avsnitt om?', - 'location_name' => 'Platsnamn eller adress', - 'location_name_hint' => 'Detta kan vara en verklig eller fiktiv plats', - 'transcript' => 'Avskrift (undertexter / undertexter)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Ladda ner avskrift', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Fjärr-URL för avskrift', - 'transcript_file_delete' => 'Ta bort avskrift', - 'chapters' => 'Kapitel', - 'chapters_hint' => 'Filen måste vara i JSON Kapitelformat.', - 'chapters_download' => 'Ladda ner kapitel', - 'chapters_file' => 'Kapitel fil', - 'chapters_remote_url' => 'Fjärr-URL för kapitelfil', - 'chapters_file_delete' => 'Ta bort kapitelfil', - 'advanced_section_title' => 'Avancerade parametrar', + 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', + 'location_section_title' => 'Location', + 'location_section_subtitle' => 'What place is this episode about?', + 'location_name' => 'Location name or address', + 'location_name_hint' => 'This can be a real or fictional location', + 'transcript' => 'Transcript (subtitles / closed captions)', + 'transcript_hint' => 'Only .srt are allowed.', + 'transcript_download' => 'Download transcript', + 'transcript_file' => 'Transcript file (.srt)', + 'transcript_remote_url' => 'Remote url for transcript', + 'transcript_file_delete' => 'Delete transcript file', + 'chapters' => 'Chapters', + 'chapters_hint' => 'File must be in JSON Chapters format.', + 'chapters_download' => 'Download chapters', + 'chapters_file' => 'Chapters file', + 'chapters_remote_url' => 'Remote url for chapters file', + 'chapters_file_delete' => 'Delete chapters file', + 'advanced_section_title' => 'Advanced Parameters', 'advanced_section_subtitle' => - 'Om du behöver RSS-taggar som Castopod inte hanterar, ställ in dem här.', - 'custom_rss' => 'Anpassade RSS-taggar för avsnittet', - 'custom_rss_hint' => 'Detta kommer att injiceras inom item taggen.', - 'block' => 'Avsnitt bör döljas från offentliga kataloger', + 'If you need RSS tags that Castopod does not handle, set them here.', + 'custom_rss' => 'Custom RSS tags for the episode', + 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', + 'block' => 'Episode should be hidden from public catalogues', 'block_hint' => - 'Avsnitten visa eller dölja status: växla detta hindrar avsnitten från att visas i Apple Podcasts, Google Podcasts, och alla tredjepartsappar som drar program från dessa kataloger. (Inte garanterat)', - 'submit_create' => 'Skapa avsnitt', - 'submit_edit' => 'Spara avsnitt', + 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', + 'submit_create' => 'Create episode', + 'submit_edit' => 'Save episode', ], 'publish_form' => [ - 'back_to_episode_dashboard' => 'Tillbaka till avsnittets instrumentpanel', - 'post' => 'Ditt meddelande inlägg', + 'back_to_episode_dashboard' => 'Back to episode dashboard', + 'post' => 'Your announcement post', 'post_hint' => - "Skriv ett meddelande för att meddela publiceringen av ditt avsnitt. Meddelandet kommer att sändas till alla dina följare i fediverse och presenteras på din podcasts hemsida.", - 'message_placeholder' => 'Skriv ditt meddelande…', - 'publication_date' => 'Publiceringsdatum', + "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", + 'message_placeholder' => 'Write your message…', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Nu', - 'schedule' => 'Schemalägg', - 'with_podcast' => 'Publicera tillsammans med podcast', + 'now' => 'Now', + 'schedule' => 'Schedule', + 'with_podcast' => 'Publish alongside podcast', ], - 'scheduled_publication_date' => 'Planerat publiceringsdatum', - 'scheduled_publication_date_clear' => 'Rensa publiceringsdatum', + 'scheduled_publication_date' => 'Scheduled publication date', + 'scheduled_publication_date_clear' => 'Clear publication date', 'scheduled_publication_date_hint' => - 'Du kan schemalägga avsnittet genom att ställa in ett framtida publiceringsdatum. Detta fält måste formateras som ÅÅÅ-MM-DD HH:mm', - 'submit' => 'Publicera', - 'submit_edit' => 'Redigera publikation', - 'cancel_publication' => 'Avbryt publicering', - 'message_warning' => 'Du skrev inte ett meddelande för ditt tillkännagivande!', - 'message_warning_hint' => 'Att ha ett meddelande ökar socialt engagemang, vilket resulterar i en bättre synlighet för ditt avsnitt.', - 'message_warning_submit' => 'Publicera ändå', + 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', + 'submit' => 'Publish', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', + 'message_warning' => 'You did not write a message for your announcement post!', + 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', + 'message_warning_submit' => 'Publish anyways', ], 'publish_date_edit_form' => [ - 'new_publication_date' => 'Nytt publiceringsdatum', - 'new_publication_date_hint' => 'Måste vara inställd till ett tidigare datum.', - 'submit' => 'Redigera publiceringsdatum', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "Avpublicera avsnittet kommer att ta bort alla kommentarer och inlägg som är associerade med det och ta bort det från podcastens RSS-flöde.", - 'understand' => 'Jag förstår, jag vill avpublicera avsnittet', - 'submit' => 'Avpublicera', + "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", + 'understand' => 'I understand, I want to unpublish the episode', + 'submit' => 'Unpublish', ], 'delete_form' => [ 'disclaimer' => - "Borttagning av avsnittet kommer att ta bort alla mediefiler, kommentarer, videoklipp och ljudfiler som är associerade med det.", - 'understand' => 'Jag förstår, Jag vill ta bort avsnittet', - 'submit' => 'Radera', + "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", + 'understand' => 'I understand, I want to delete the episode', + 'submit' => 'Delete', ], 'embed' => [ - 'title' => 'Inbäddad spelare', + 'title' => 'Embeddable player', 'label' => - 'Välj ett tema färg, kopiera den inbäddade spelaren till urklipp, sedan klistra in den på din webbplats.', - 'clipboard_iframe' => 'Kopiera inbäddbar spelare till urklipp', - 'clipboard_url' => 'Kopiera adress till urklipp', - 'dark' => 'Mörk', - 'dark-transparent' => 'Mörk transparent', - 'light' => 'Ljust', - 'light-transparent' => 'Ljus transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', + 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', + 'clipboard_iframe' => 'Copy embeddable player to clipboard', + 'clipboard_url' => 'Copy address to clipboard', + 'dark' => 'Dark', + 'dark-transparent' => 'Dark transparent', + 'light' => 'Light', + 'light-transparent' => 'Light transparent', ], ]; diff --git a/modules/Admin/Language/sv/EpisodeNavigation.php b/modules/Admin/Language/sv/EpisodeNavigation.php index 59f92a52..1406e301 100644 --- a/modules/Admin/Language/sv/EpisodeNavigation.php +++ b/modules/Admin/Language/sv/EpisodeNavigation.php @@ -9,15 +9,15 @@ declare(strict_types=1); */ return [ - 'go_to_page' => 'Visa avsnittssida', - 'dashboard' => 'Avsnittets instrumentpanel', - 'episode-view' => 'Hem', - 'episode-edit' => 'Redigera avsnitt', - 'episode-persons-manage' => 'Hantera personer', - 'embed-add' => 'Inbäddad spelare', - 'clips' => 'Klipp', - 'video-clips-list' => 'Videoklipp', - 'video-clips-create' => 'Nytt videoklipp', - 'soundbites-list' => 'Ljudklipp', - 'soundbites-create' => 'Ny ljudbit', + 'go_to_page' => 'View episode page', + 'dashboard' => 'Episode dashboard', + 'episode-view' => 'Home', + 'episode-edit' => 'Edit episode', + 'episode-persons-manage' => 'Manage persons', + 'embed-add' => 'Embeddable player', + 'clips' => 'Clips', + 'video-clips-list' => 'Video clips', + 'video-clips-create' => 'New video clip', + 'soundbites-list' => 'Soundbites', + 'soundbites-create' => 'New soundbite', ]; diff --git a/modules/Admin/Language/sv/Fediverse.php b/modules/Admin/Language/sv/Fediverse.php index 18a1b209..0e4ca66d 100644 --- a/modules/Admin/Language/sv/Fediverse.php +++ b/modules/Admin/Language/sv/Fediverse.php @@ -10,23 +10,23 @@ declare(strict_types=1); return [ 'messages' => [ - 'actorNotFound' => 'Det gick inte att hitta kontot!', - 'blockActorSuccess' => '{actor} har blockerats!', - 'unblockActorSuccess' => 'Aktören har blivit avblockerad!', - 'blockDomainSuccess' => '{domain} har blockerats!', - 'unblockDomainSuccess' => '{domain} har blivit avblockerad!', + 'actorNotFound' => 'The account could not be found!', + 'blockActorSuccess' => '{actor} has been blocked!', + 'unblockActorSuccess' => 'Actor has been unblocked!', + 'blockDomainSuccess' => '{domain} has been blocked!', + 'unblockDomainSuccess' => '{domain} has been unblocked!', ], - 'blocked_actors' => 'Blockerade konton', - 'blocked_domains' => 'Blockerade domäner', + 'blocked_actors' => 'Blocked accounts', + 'blocked_domains' => 'Blocked domains', 'block_lists_form' => [ - 'handle' => 'Hantera konto', - 'handle_hint' => 'Skriv in @användarnamn@domänkonto.', - 'domain' => 'Domännamn', - 'submit' => 'Blockera!', + 'handle' => 'Account handle', + 'handle_hint' => 'Input @username@domain account.', + 'domain' => 'Domain name', + 'submit' => 'Block!', ], 'list' => [ - 'actor' => 'Konto', - 'domain' => 'Domännamn', - 'unblock' => 'Avblockera', + 'actor' => 'Account', + 'domain' => 'Domain name', + 'unblock' => 'Unblock', ], ]; diff --git a/modules/Admin/Language/sv/Home.php b/modules/Admin/Language/sv/Home.php index 493b5d18..3ff4c04d 100644 --- a/modules/Admin/Language/sv/Home.php +++ b/modules/Admin/Language/sv/Home.php @@ -9,6 +9,6 @@ declare(strict_types=1); */ return [ - 'all_podcasts' => 'Alla podcasts', - 'no_podcast' => 'Ingen podcast hittades', + 'all_podcasts' => 'All podcasts', + 'no_podcast' => 'No podcast found', ]; diff --git a/modules/Admin/Language/sv/Install.php b/modules/Admin/Language/sv/Install.php index 9e7de812..36e373a2 100644 --- a/modules/Admin/Language/sv/Install.php +++ b/modules/Admin/Language/sv/Install.php @@ -9,53 +9,53 @@ declare(strict_types=1); */ return [ - 'manual_config' => 'Manuell konfiguration', + 'manual_config' => 'Manual configuration', 'manual_config_subtitle' => - 'Skapa en \'.env\' fil med dina inställningar och uppdatera sidan för att fortsätta installationen.', + 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ - 'instance_config' => 'Konfiguration av instans', - 'hostname' => 'Servernamn', - 'media_base_url' => 'Bas-URL för media', + 'instance_config' => 'Instance configuration', + 'hostname' => 'Hostname', + 'media_base_url' => 'Media base URL', 'media_base_url_hint' => - 'Om du använder en CDN och/eller en extern analystjänst kan du ställa in dem här.', + 'If you use a CDN and/or an external analytics service, you may set them here.', 'admin_gateway' => 'Admin gateway', 'admin_gateway_hint' => - 'Rutten för att komma åt adminområdet (t.ex. https://example.com/cp-admin). Det är som standard inställt som cp-admin, vi rekommenderar att du ändrar det av säkerhetsskäl.', + 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', 'auth_gateway' => 'Auth gateway', 'auth_gateway_hint' => - 'Rutten för att komma åt autentiseringssidorna (t.ex. https://example.com/cp-auth). Den är som standard inställd som cp-auth, vi rekommenderar att du ändrar den av säkerhetsskäl.', - 'database_config' => 'Databas konfiguration', + 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', + 'database_config' => 'Database configuration', 'database_config_hint' => - 'Castopod måste ansluta till din MySQL (eller MariaDB) databas. Om du inte har dessa nödvändiga uppgifter, kontakta din serveradministratör.', - 'db_hostname' => 'Databasens värdnamn', - 'db_name' => 'Databasnamn', - 'db_username' => 'Användarnamn till databasen', - 'db_password' => 'Databasens lösenord', - 'db_prefix' => 'Databas prefix', + 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', + 'db_hostname' => 'Database hostname', + 'db_name' => 'Database name', + 'db_username' => 'Database username', + 'db_password' => 'Database password', + 'db_prefix' => 'Database prefix', 'db_prefix_hint' => - "Prefixet för Castopod tabellnamn, lämna som om du inte vet vad det betyder.", - 'cache_config' => 'Cache-konfiguration', + "The prefix of the Castopod table names, leave as is if you don't know what it means.", + 'cache_config' => 'Cache configuration', 'cache_config_hint' => - 'Välj önskad cachehanterare. Lämna det som standardvärde om du inte har någon aning om vad det innebär.', + 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', 'cache_handler' => 'Cache handler', 'cacheHandlerOptions' => [ - 'file' => 'Fil', + 'file' => 'File', 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'Nästa', - 'submit' => 'Slutför installationen', - 'create_superadmin' => 'Skapa ditt superadministratörskonto', - 'email' => 'Epost', - 'username' => 'Användarnamn', - 'password' => 'Lösenord', + 'next' => 'Next', + 'submit' => 'Finish install', + 'create_superadmin' => 'Create your superadmin account', + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', ], 'messages' => [ 'createSuperAdminSuccess' => - 'Ditt superadministratörskonto har skapats. Logga in för att starta podcasting!', + 'Your superadmin account has been created successfully. Login to start podcasting!', 'databaseConnectError' => - 'Castopod kunde inte ansluta till din databas. Redigera din databaskonfiguration och försök igen.', + 'Castopod could not connect to your database. Edit your database configuration and try again.', 'writeError' => - "Kunde inte skapa/skriva `.env`-filen. Du måste skapa den manuellt genom att följa filmallen `.env.exempel` i Castopod-paketet.", + "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", ], ]; diff --git a/modules/Auth/Language/kk/MyAccount.php b/modules/Admin/Language/sv/MyAccount.php similarity index 100% rename from modules/Auth/Language/kk/MyAccount.php rename to modules/Admin/Language/sv/MyAccount.php diff --git a/modules/Admin/Language/sv/Navigation.php b/modules/Admin/Language/sv/Navigation.php index 4e710a45..68d4609d 100644 --- a/modules/Admin/Language/sv/Navigation.php +++ b/modules/Admin/Language/sv/Navigation.php @@ -9,36 +9,33 @@ declare(strict_types=1); */ return [ - 'toggle_sidebar' => 'Växla sidofält', - 'go_to_website' => 'Gå till webbsidan', - 'go_to_admin' => 'Gå till admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Översiktspanel', - 'admin' => 'Hem', + 'toggle_sidebar' => 'Toggle sidebar', + 'go_to_website' => 'Go to website', + 'go_to_admin' => 'Go to admin', + 'dashboard' => 'Dashboard', + 'admin' => 'Home', 'podcasts' => 'Podcasts', - 'podcast-list' => 'Alla podcasts', - 'podcast-create' => 'Ny podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Personer', - 'person-list' => 'Alla personer', - 'person-create' => 'Ny person', + 'podcast-list' => 'All podcasts', + 'podcast-create' => 'New podcast', + 'podcast-import' => 'Import a podcast', + 'persons' => 'Persons', + 'person-list' => 'All persons', + 'person-create' => 'New person', 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blockerade konton', - 'fediverse-blocked-domains' => 'Blockerade domäner', - 'users' => 'Användare', - 'user-list' => 'Alla användare', - 'user-create' => 'Ny användare', - 'pages' => 'Sidor', - 'page-list' => 'Alla sidor', - 'page-create' => 'Ny sida', - 'settings' => 'Inställningar', - 'settings-general' => 'Allmänt', - 'settings-theme' => 'Tema', - 'admin-about' => 'Om', + 'fediverse-blocked-actors' => 'Blocked accounts', + 'fediverse-blocked-domains' => 'Blocked domains', + 'users' => 'Users', + 'user-list' => 'All users', + 'user-create' => 'New user', + 'pages' => 'Pages', + 'page-list' => 'All pages', + 'page-create' => 'New Page', + 'settings' => 'Settings', + 'settings-general' => 'General', + 'settings-theme' => 'Theme', 'account' => [ - 'my-account' => 'Mitt konto', - 'change-password' => 'Ändra lösenord', - 'logout' => 'Logga ut', + 'my-account' => 'My account', + 'change-password' => 'Change password', + 'logout' => 'Logout', ], ]; diff --git a/modules/Admin/Language/sv/Notifications.php b/modules/Admin/Language/sv/Notifications.php index cacbb79a..2b139d51 100644 --- a/modules/Admin/Language/sv/Notifications.php +++ b/modules/Admin/Language/sv/Notifications.php @@ -9,11 +9,11 @@ declare(strict_types=1); */ return [ - 'title' => 'Aviseringar', - 'reply' => '{actor_username} svarade på ditt inlägg', - 'favourite' => '{actor_username} favoriterade ditt inlägg', - 'reblog' => '{actor_username} delade ditt inlägg', - 'follow' => '{actor_username} började följa dig', - 'no_notifications' => 'Inga aviseringar', - 'mark_all_as_read' => 'Markera alla som lästa', + 'title' => 'Notifications', + 'reply' => '{actor_username} replied to your post', + 'favourite' => '{actor_username} favourited your post', + 'reblog' => '{actor_username} shared your post', + 'follow' => '{actor_username} started following you', + 'no_notifications' => 'No notifications', + 'mark_all_as_read' => 'Mark all as read', ]; diff --git a/modules/Admin/Language/sv/Page.php b/modules/Admin/Language/sv/Page.php index 89f48754..b6f49de5 100644 --- a/modules/Admin/Language/sv/Page.php +++ b/modules/Admin/Language/sv/Page.php @@ -9,22 +9,22 @@ declare(strict_types=1); */ return [ - 'back_to_home' => 'Tillbaka till startsidan', - 'page' => 'Sida', - 'all_pages' => 'Alla sidor', - 'create' => 'Ny sida', - 'go_to_page' => 'Gå till sida', - 'edit' => 'Redigera sida', - 'delete' => 'Ta bort sida', + 'back_to_home' => 'Back to home', + 'page' => 'Page', + 'all_pages' => 'All pages', + 'create' => 'New page', + 'go_to_page' => 'Go to page', + 'edit' => 'Edit page', + 'delete' => 'Delete page', 'form' => [ - 'title' => 'Rubrik', - 'permalink' => 'Permalänk', - 'content' => 'Innehåll', - 'submit_create' => 'Skapa sida', - 'submit_edit' => 'Spara', + 'title' => 'Title', + 'permalink' => 'Permalink', + 'content' => 'Content', + 'submit_create' => 'Create page', + 'submit_edit' => 'Save', ], 'messages' => [ - 'createSuccess' => 'Sidan ”{pageTitle}” skapades framgångsrikt!', - 'editSuccess' => 'Sidan har uppdaterats!', + 'createSuccess' => 'The page “{pageTitle}” was created successfully!', + 'editSuccess' => 'The page was successfully updated!', ], ]; diff --git a/modules/Admin/Language/sv/Pager.php b/modules/Admin/Language/sv/Pager.php index 32a18e90..e25ee638 100644 --- a/modules/Admin/Language/sv/Pager.php +++ b/modules/Admin/Language/sv/Pager.php @@ -9,13 +9,13 @@ declare(strict_types=1); */ return [ - 'pageNavigation' => 'Sidnavigering', - 'first' => 'Första', - 'previous' => 'Föregående', - 'next' => 'Nästa', - 'last' => 'Sista', - 'older' => 'Äldre', - 'newer' => 'Nyare', - 'invalidTemplate' => '{0} är inte en giltig sidmall.', - 'invalidPaginationGroup' => '{0} är inte en giltig sidnumreringsgrupp.', + 'pageNavigation' => 'Page navigation', + 'first' => 'First', + 'previous' => 'Previous', + 'next' => 'Next', + 'last' => 'Last', + 'older' => 'Older', + 'newer' => 'Newer', + 'invalidTemplate' => '{0} is not a valid Pager template.', + 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', ]; diff --git a/modules/Admin/Language/sv/Person.php b/modules/Admin/Language/sv/Person.php index f5007527..a652be9f 100644 --- a/modules/Admin/Language/sv/Person.php +++ b/modules/Admin/Language/sv/Person.php @@ -9,57 +9,57 @@ declare(strict_types=1); */ return [ - 'persons' => 'Personer', - 'all_persons' => 'Alla personer', - 'no_person' => 'Ingen hittades!', - 'create' => 'Skapa en person', - 'view' => 'Visa person', - 'edit' => 'Redigera person', - 'delete' => 'Ta bort person', + 'persons' => 'Persons', + 'all_persons' => 'All persons', + 'no_person' => 'Nobody found!', + 'create' => 'Create a person', + 'view' => 'View person', + 'edit' => 'Edit person', + 'delete' => 'Delete person', 'messages' => [ - 'createSuccess' => 'Person har skapats framgångsrikt!', - 'editSuccess' => 'Person har uppdaterats!', - 'deleteSuccess' => 'Person har tagits bort!', + 'createSuccess' => 'Person has been successfully created!', + 'editSuccess' => 'Person has been successfully updated!', + 'deleteSuccess' => 'Person has been removed!', ], 'form' => [ 'avatar' => 'Avatar', 'avatar_size_hint' => - 'Avatar måste vara kvadratisk och minst 400px bred och hög.', - 'full_name' => 'Fullständigt namn', - 'full_name_hint' => 'Detta är personens fullständiga namn eller alias.', - 'unique_name' => 'Unikt namn', - 'unique_name_hint' => 'Används för URL: er', + 'Avatar must be squared and at least 400px wide and tall.', + 'full_name' => 'Full name', + 'full_name_hint' => 'This is the full name or alias of the person.', + 'unique_name' => 'Unique name', + 'unique_name_hint' => 'Used for URLs', 'information_url' => 'Information URL', 'information_url_hint' => - 'Url till en relevant resurs av information om personen, såsom en hemsida eller en tredje parts profilplattform.', - 'submit_create' => 'Skapa person', - 'submit_edit' => 'Spara person', + 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', + 'submit_create' => 'Create person', + 'submit_edit' => 'Save person', ], 'podcast_form' => [ - 'title' => 'Hantera personer', - 'add_section_title' => 'Lägg till personer till denna podcast', - 'add_section_subtitle' => 'Du kan välja flera personer och roller.', - 'persons' => 'Personer', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this podcast', + 'add_section_subtitle' => 'You may pick several persons and roles.', + 'persons' => 'Persons', 'persons_hint' => - 'Du kan välja en eller flera personer med samma roller. Du måste skapa personerna först.', - 'roles' => 'Roller', + 'You may select one or several persons with the same roles. You need to create the persons first.', + 'roles' => 'Roles', 'roles_hint' => - 'Du kan välja ingen, en eller flera roller för en person.', - 'submit_add' => 'Lägg till person(er)', - 'remove' => 'Ta bort', + 'You may select none, one or several roles for a person.', + 'submit_add' => 'Add person(s)', + 'remove' => 'Remove', ], 'episode_form' => [ - 'title' => 'Hantera personer', - 'add_section_title' => 'Lägg till personer till detta avsnitt', - 'add_section_subtitle' => 'Du kan välja flera personer och roller.', - 'persons' => 'Personer', + 'title' => 'Manage persons', + 'add_section_title' => 'Add persons to this episode', + 'add_section_subtitle' => 'You may pick several persons and roles.', + 'persons' => 'Persons', 'persons_hint' => - 'Du kan välja en eller flera personer med samma roller. Du måste skapa personerna först.', - 'roles' => 'Roller', + 'You may select one or several persons with the same roles. You need to create the persons first.', + 'roles' => 'Roles', 'roles_hint' => - 'Du kan välja ingen, en eller flera roller för en person.', - 'submit_add' => 'Lägg till person(er)', - 'remove' => 'Ta bort', + 'You may select none, one or several roles for a person.', + 'submit_add' => 'Add person(s)', + 'remove' => 'Remove', ], - 'credits' => 'Tack till', + 'credits' => 'Credits', ]; diff --git a/modules/Admin/Language/sv/Platforms.php b/modules/Admin/Language/sv/Platforms.php index 40eab4f8..ab17d599 100644 --- a/modules/Admin/Language/sv/Platforms.php +++ b/modules/Admin/Language/sv/Platforms.php @@ -9,35 +9,22 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Gå till {platformName} webbplats', - 'register' => 'Register', - 'submit_url' => 'Skicka din podcast den {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Visa på podcastens hemsida?', - 'on_embed' => 'Visa på inbäddbar spelare?', - 'remove' => 'Ta bort {platformName}', - 'submit' => 'Spara', + 'title' => 'Platforms', + 'home_url' => 'Go to {platformName} website', + 'submit_url' => 'Submit your podcast on {platformName}', + 'visible' => 'Display in podcast homepage?', + 'on_embed' => 'Display on embeddable player?', + 'remove' => 'Remove {platformName}', + 'submit' => 'Save', 'messages' => [ - 'updateSuccess' => 'Plattformslänkarna har uppdaterats!', - 'removeLinkSuccess' => 'Plattformslänken har tagits bort.', + 'updateSuccess' => 'Platform links have been successfully updated!', + 'removeLinkSuccess' => 'The platform link has been removed.', 'removeLinkError' => - 'Plattformslänken kunde inte tas bort. Försök igen.', + 'The platform link could not be removed. Try again.', ], 'description' => [ - 'podcasting' => 'Podcast ID på denna plattform', - 'social' => 'Den podcast konto ID på denna plattform', - 'funding' => 'Ring till åtgärdsmeddelande', + 'podcasting' => 'The podcast ID on this platform', + 'social' => 'The podcast account ID on this platform', + 'funding' => 'Call to action message', ], ]; diff --git a/modules/Admin/Language/sv/Podcast.php b/modules/Admin/Language/sv/Podcast.php index 7fda701b..426b763b 100644 --- a/modules/Admin/Language/sv/Podcast.php +++ b/modules/Admin/Language/sv/Podcast.php @@ -9,322 +9,302 @@ declare(strict_types=1); */ return [ - 'all_podcasts' => 'Alla podcasts', - 'no_podcast' => 'Ingen podcast hittades!', - 'create' => 'Skapa podcast', - 'import' => 'Importera podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'Nytt avsnitt', - 'view' => 'Visa podcast', - 'edit' => 'Redigera podcast', - 'publish' => 'Publicera podcasten', - 'publish_edit' => 'Redigera publikation', - 'delete' => 'Ta bort podcast', - 'see_episodes' => 'Se avsnitt', - 'see_contributors' => 'Se bidragsgivare', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Gå till sida', - 'latest_episodes' => 'Senaste avsnitt', - 'see_all_episodes' => 'Se alla avsnitt', - 'draft' => 'Utkast', + 'all_podcasts' => 'All podcasts', + 'no_podcast' => 'No podcast found!', + 'create' => 'Create podcast', + 'import' => 'Import podcast', + 'new_episode' => 'New Episode', + 'view' => 'View podcast', + 'edit' => 'Edit podcast', + 'publish' => 'Publish podcast', + 'publish_edit' => 'Edit publication', + 'delete' => 'Delete podcast', + 'see_episodes' => 'See episodes', + 'see_contributors' => 'See contributors', + 'go_to_page' => 'Go to page', + 'latest_episodes' => 'Latest episodes', + 'see_all_episodes' => 'See all episodes', + 'draft' => 'Draft', 'messages' => [ - 'createSuccess' => 'Podcast har skapats!', - 'editSuccess' => 'Podcasten har uppdaterats!', - 'importSuccess' => 'Podcasten har importerats!', - 'deleteSuccess' => 'Podcast @{podcast_handle} har raderats!', - 'deletePodcastMediaError' => 'Kunde inte ta bort podcast {type, select, - cover {omslag} + 'createSuccess' => 'Podcast successfully created!', + 'editSuccess' => 'Podcast has been successfully updated!', + 'importSuccess' => 'Podcast has been successfully imported!', + 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', + 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, + cover {cover} banner {banner} other {media} }.', - 'deleteEpisodeMediaError' => 'Misslyckades att ta bort avsnitt {episode_slug} {type, select, + 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, transcript {transcript} - chapters {kapitel} - image {omslag} - audio {ljud} + chapters {chapters} + image {cover} + audio {audio} other {media} }.', - 'deletePodcastMediaFolderError' => 'Det gick inte att ta bort podcast-mediamappen {folder_path}. Du kan manuellt ta bort den från disken.', - 'podcastFeedUpdateSuccess' => 'Lyckad uppdatering: {number_of_new_episodes, plural, - one {# episoden var} - other {# episoder var} - } lades till i podcasten!', - 'podcastFeedUpToDate' => 'Podcasten är redan uppdaterad.', - 'publishError' => 'Denna podcast är antingen redan publicerad eller schemalagd för publicering.', - 'publishEditError' => 'Denna podcast är inte schemalagd för publicering.', - 'publishCancelSuccess' => 'Podcast publicering avbröts!', - 'scheduleDateError' => 'Schemaläggningsdatum måste anges!', + 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', + 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, + one {# episode was} + other {# episodes were} + } added to the podcast!', + 'podcastFeedUpToDate' => 'Podcast is already up to date.', + 'podcastNotImported' => 'Podcast could not be updated as it was not imported.', + 'publishError' => 'This podcast is either already published or scheduled for publication.', + 'publishEditError' => 'This podcast is not scheduled for publication.', + 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', + 'scheduleDateError' => 'Schedule date must be set!', ], 'form' => [ - 'identity_section_title' => 'Podcast identitet', - 'identity_section_subtitle' => 'Dessa fält gör att du kan bli uppmärksammad.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast omslag', - 'cover_size_hint' => 'Omslaget måste vara fyrkantigt och minst 1400px brett och högt.', + 'identity_section_title' => 'Podcast identity', + 'identity_section_subtitle' => 'These fields allow you to get noticed.', + 'cover' => 'Podcast cover', + 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner måste ha ett 3:1-förhållande och vara minst 1500px bred.', - 'banner_delete' => 'Ta bort podcast banner', - 'title' => 'Rubrik', - 'handle' => 'Hantera', + 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', + 'banner_delete' => 'Delete podcast banner', + 'title' => 'Title', + 'handle' => 'Handle', 'handle_hint' => - 'Används för att identifiera podcasten. Versaler, gemener, siffror och understrykningar accepteras.', + 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', 'type' => [ - 'label' => 'Typ', + 'label' => 'Type', 'episodic' => 'Episodic', - 'episodic_hint' => 'Om avsnitt är avsedda att konsumeras utan någon specifik ordning. Nyaste avsnitt kommer att presenteras först.', - 'serial' => 'Serie', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', + 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', + 'serial' => 'Serial', + 'serial_hint' => 'If episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.', ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Beskrivning', - 'classification_section_title' => 'Klassificering', + 'description' => 'Description', + 'classification_section_title' => 'Classification', 'classification_section_subtitle' => - 'Dessa fält kommer att påverka din publik och konkurrens.', - 'language' => 'Språk', - 'category' => 'Kategori', - 'category_placeholder' => 'Välj en kategori…', - 'other_categories' => 'Andra kategorier', + 'These fields will impact your audience and competition.', + 'language' => 'Language', + 'category' => 'Category', + 'category_placeholder' => 'Select a category…', + 'other_categories' => 'Other categories', 'parental_advisory' => [ - 'label' => 'Föräldrarådgivande', - 'hint' => 'Innehåller det olämpligt innehåll?', - 'undefined' => 'odefinierad', - 'clean' => 'Ren', - 'explicit' => 'Uteslutande', + 'label' => 'Parental advisory', + 'hint' => 'Does it contain explicit content?', + 'undefined' => 'undefined', + 'clean' => 'Clean', + 'explicit' => 'Explicit', ], - 'author_section_title' => 'Författare', - 'author_section_subtitle' => 'Vem hanterar podcasten?', - 'owner_name' => 'Ägarens namn', + 'author_section_title' => 'Author', + 'author_section_subtitle' => 'Who is managing the podcast?', + 'owner_name' => 'Owner name', 'owner_name_hint' => - 'Endast för administrativt bruk. Synlig i det offentliga RSS-flödet.', - 'owner_email' => 'Ägarens e-post', + 'For administrative use only. Visible in the public RSS feed.', + 'owner_email' => 'Owner email', 'owner_email_hint' => - 'Kommer att användas av de flesta plattformar för att verifiera podcast-ägandet. Synlig i det offentliga RSS-flödet.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Utgivare', + 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', + 'publisher' => 'Publisher', 'publisher_hint' => - 'Gruppen som ansvarar för att skapa showen. Ofta hänvisar man till moderbolaget eller nätverket av en podcast. Detta fält är ibland märkt som "Författare".', + 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', 'copyright' => 'Copyright', - 'location_section_title' => 'Plats', - 'location_section_subtitle' => 'Vilken plats handlar denna podcast om?', - 'location_name' => 'Platsnamn eller adress', - 'location_name_hint' => 'Detta kan vara en riktig plats eller fiktiv', - 'monetization_section_title' => 'Inkomster', + 'location_section_title' => 'Location', + 'location_section_subtitle' => 'What place is this podcast about?', + 'location_name' => 'Location name or address', + 'location_name_hint' => 'This can be a real place or fictional', + 'monetization_section_title' => 'Monetization', 'monetization_section_subtitle' => - 'Tjäna pengar tack vare din publik.', + 'Earn money thanks to your audience.', 'premium' => 'Premium', - 'premium_by_default' => 'Avsnitt måste anges som premium som standard', - 'premium_by_default_hint' => 'Podcast avsnitt kommer att markeras som premium som standard. Du kan fortfarande välja att ställa in några avsnitt, trailers eller bonusar som offentliga.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Betalning pekare för Web Monetization', + 'premium_by_default' => 'Episodes must be set as premium by default', + 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', + 'payment_pointer' => 'Payment Pointer for Web Monetization', 'payment_pointer_hint' => - 'Detta är din där du kommer att få pengar tack vare Web Monetization', - 'advanced_section_title' => 'Avancerade parametrar', + 'This is your where you will receive money thanks to Web Monetization', + 'advanced_section_title' => 'Advanced Parameters', 'advanced_section_subtitle' => - 'Om du behöver RSS-taggar som Castopod inte hanterar, ställ in dem här.', - 'custom_rss' => 'Anpassade RSS-taggar för podcasten', - 'custom_rss_hint' => 'Detta kommer att injiceras i kanal taggen.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'Ny flödes-URL', - 'new_feed_url_hint' => 'Använd detta fält när du flyttar till en annan domän eller podcast webbhotell. Som standard är värdet inställt på nuvarande RSS-URL om podcasten importeras.', - 'old_feed_url' => 'Gammal flödes-URL', - 'partnership' => 'Samarbete', + 'If you need RSS tags that Castopod does not handle, set them here.', + 'custom_rss' => 'Custom RSS tags for the podcast', + 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', + 'new_feed_url' => 'New feed URL', + 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', + 'old_feed_url' => 'Old feed URL', + 'update_feed' => 'Update feed', + 'update_feed_tip' => 'Import this podcast\'s latest episodes', + 'partnership' => 'Partnership', 'partner_id' => 'ID', - 'partner_link_url' => 'Länk url', - 'partner_image_url' => 'Bild-URL', - 'partner_id_hint' => 'Din egen partner ID', - 'partner_link_url_hint' => 'Den generiska partnerns länkadress', - 'partner_image_url_hint' => 'Den generiska partnerns bildadress', - 'block' => 'Podcast bör döljas från offentliga kataloger', + 'partner_link_url' => 'Link URL', + 'partner_image_url' => 'Image URL', + 'partner_id_hint' => 'Your own partner ID', + 'partner_link_url_hint' => 'The generic partner link address', + 'partner_image_url_hint' => 'The generic partner image address', + 'status_section_title' => 'Status', + 'block' => 'Podcast should be hidden from public catalogues', 'block_hint' => - 'Podcasten visar eller dölj status: att växla på detta hindrar hela podcasten från att visas i Apple Podcasts, Google Podcasts, och alla tredjepartsappar som drar program från dessa kataloger. (Inte garanterat)', - 'complete' => 'Podcast kommer inte att ha nya avsnitt', - 'lock' => 'Förhindra podcast från att kopieras', + 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', + 'complete' => 'Podcast will not be having new episodes', + 'lock' => 'Prevent podcast from being copied', 'lock_hint' => - 'Syftet är att berätta för andra podcast-plattformar om de får importera detta flöde. Ett värde av ja innebär att varje försök att importera detta flöde till en ny plattform bör avvisas.', - 'submit_create' => 'Skapa podcast', - 'submit_edit' => 'Spara podcast', + 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', + 'submit_create' => 'Create podcast', + 'submit_edit' => 'Save podcast', ], 'category_options' => [ - 'uncategorized' => 'okategoriserad', - 'arts' => 'Konst', - 'business' => 'Företagande', - 'comedy' => 'Komedi', - 'education' => 'Utbildning', - 'fiction' => 'Fiktion', - 'government' => 'Myndighet', - 'health_and_fitness' => 'Hälsa & Träning', - 'history' => 'Historia', - 'kids_and_family' => 'Barn & Familj', - 'leisure' => 'Fritid', - 'music' => 'Musik', - 'news' => 'Nyheter', - 'religion_and_spirituality' => 'Religion & Andlighet', - 'science' => 'Vetenskap', - 'society_and_culture' => 'Samhälle & Kultur', - 'sports' => 'Sport', - 'technology' => 'Teknologi', - 'true_crime' => 'Sann brottslighet', - 'tv_and_film' => 'TV & Film', - 'books' => 'Böcker', + 'uncategorized' => 'uncategorized', + 'arts' => 'Arts', + 'business' => 'Business', + 'comedy' => 'Comedy', + 'education' => 'Education', + 'fiction' => 'Fiction', + 'government' => 'Government', + 'health_and_fitness' => 'Health & Fitness', + 'history' => 'History', + 'kids_and_family' => 'Kids & Family', + 'leisure' => 'Leisure', + 'music' => 'Music', + 'news' => 'News', + 'religion_and_spirituality' => 'Religion & Spirituality', + 'science' => 'Science', + 'society_and_culture' => 'Society & Culture', + 'sports' => 'Sports', + 'technology' => 'Technology', + 'true_crime' => 'True Crime', + 'tv_and_film' => 'TV & Film', + 'books' => 'Books', 'design' => 'Design', - 'fashion_and_beauty' => 'Mode & Skönhet', - 'food' => 'Mat', - 'performing_arts' => 'Scenkonst', - 'visual_arts' => 'Visuell konst', - 'careers' => 'Karriärer', - 'entrepreneurship' => 'Entreprenörskap', - 'investing' => 'Investering', + 'fashion_and_beauty' => 'Fashion & Beauty', + 'food' => 'Food', + 'performing_arts' => 'Performing Arts', + 'visual_arts' => 'Visual Arts', + 'careers' => 'Careers', + 'entrepreneurship' => 'Entrepreneurship', + 'investing' => 'Investing', 'management' => 'Management', - 'marketing' => 'Marknadsföring', - 'non_profit' => 'Ideell organisation', - 'comedy_interviews' => 'Komedi Intervjuer', - 'improv' => 'Förbättra', + 'marketing' => 'Marketing', + 'non_profit' => 'Non-Profit', + 'comedy_interviews' => 'Comedy Interviews', + 'improv' => 'Improv', 'stand_up' => 'Stand-Up', - 'courses' => 'Kurser', - 'how_to' => 'Så funkar det', - 'language_learning' => 'Språkinlärning', - 'self_improvement' => 'Självförbättring', - 'comedy_fiction' => 'Komedi fiktion', + 'courses' => 'Courses', + 'how_to' => 'How To', + 'language_learning' => 'Language Learning', + 'self_improvement' => 'Self-Improvement', + 'comedy_fiction' => 'Comedy Fiction', 'drama' => 'Drama', 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternativ Hälsa', - 'fitness' => 'Träning', - 'medicine' => 'Medicin', - 'mental_health' => 'Mental hälsa', - 'nutrition' => 'Näring', - 'sexuality' => 'Sexualitet', - 'education_for_kids' => 'Utbildning för barn', - 'parenting' => 'Föräldraskap', - 'pets_and_animals' => 'Husdjur & djur', - 'stories_for_kids' => 'Berättelser för barn', - 'animation_and_manga' => 'Animering & Manga', - 'automotive' => 'Fordon', - 'aviation' => 'Luftfart', - 'crafts' => 'Hantverk', - 'games' => 'Spel', - 'hobbies' => 'Fritidsintressen', - 'home_and_garden' => 'Hem och trädgård', - 'video_games' => 'Videospel', - 'music_commentary' => 'Kommentar från musik', - 'music_history' => 'Musikhistorik', - 'music_interviews' => 'Musikintervjuer', - 'business_news' => 'Företagsnyheter', - 'daily_news' => 'Dagliga nyheter', - 'entertainment_news' => 'Underhållningsnyheter', - 'news_commentary' => 'Nyheter Kommentar', - 'politics' => 'Politik', - 'sports_news' => 'Sportnyheter', - 'tech_news' => 'Tekniknyheter', - 'buddhism' => 'Budism', - 'christianity' => 'Kristendom', + 'alternative_health' => 'Alternative Health', + 'fitness' => 'Fitness', + 'medicine' => 'Medicine', + 'mental_health' => 'Mental Health', + 'nutrition' => 'Nutrition', + 'sexuality' => 'Sexuality', + 'education_for_kids' => 'Education for Kids', + 'parenting' => 'Parenting', + 'pets_and_animals' => 'Pets & Animals', + 'stories_for_kids' => 'Stories for Kids', + 'animation_and_manga' => 'Animation & Manga', + 'automotive' => 'Automotive', + 'aviation' => 'Aviation', + 'crafts' => 'Crafts', + 'games' => 'Games', + 'hobbies' => 'Hobbies', + 'home_and_garden' => 'Home & Garden', + 'video_games' => 'Video Games', + 'music_commentary' => 'Music Commentary', + 'music_history' => 'Music History', + 'music_interviews' => 'Music Interviews', + 'business_news' => 'Business News', + 'daily_news' => 'Daily News', + 'entertainment_news' => 'Entertainment News', + 'news_commentary' => 'News Commentary', + 'politics' => 'Politics', + 'sports_news' => 'Sports News', + 'tech_news' => 'Tech News', + 'buddhism' => 'Buddhism', + 'christianity' => 'Christianity', 'hinduism' => 'Hinduism', 'islam' => 'Islam', - 'judaism' => 'Judendom', + 'judaism' => 'Judaism', 'religion' => 'Religion', - 'spirituality' => 'Andlighet', - 'astronomy' => 'Astronomi', - 'chemistry' => 'Kemi', - 'earth_sciences' => 'Jordvetenskap', - 'life_sciences' => 'Livsvetenskaper', - 'mathematics' => 'Matematik', - 'natural_sciences' => 'Naturvetenskap', - 'nature' => 'Natur', - 'physics' => 'Fysik', - 'social_sciences' => 'Samhällsvetenskap', - 'documentary' => 'Dokumentär', - 'personal_journals' => 'Personliga tidsskrifter', - 'philosophy' => 'Filosofi', - 'places_and_travel' => 'Resor & Resmål', - 'relationships' => 'Relationer', + 'spirituality' => 'Spirituality', + 'astronomy' => 'Astronomy', + 'chemistry' => 'Chemistry', + 'earth_sciences' => 'Earth Sciences', + 'life_sciences' => 'Life Sciences', + 'mathematics' => 'Mathematics', + 'natural_sciences' => 'Natural Sciences', + 'nature' => 'Nature', + 'physics' => 'Physics', + 'social_sciences' => 'Social Sciences', + 'documentary' => 'Documentary', + 'personal_journals' => 'Personal Journals', + 'philosophy' => 'Philosophy', + 'places_and_travel' => 'Places & Travel', + 'relationships' => 'Relationships', 'baseball' => 'Baseball', - 'basketball' => 'Basket', - 'cricket' => 'Kricket', - 'fantasy_sports' => 'Fantasy Sport', - 'football' => 'Fotboll', + 'basketball' => 'Basketball', + 'cricket' => 'Cricket', + 'fantasy_sports' => 'Fantasy Sports', + 'football' => 'Football', 'golf' => 'Golf', 'hockey' => 'Hockey', 'rugby' => 'Rugby', - 'running' => 'Löpning', - 'soccer' => 'Fotboll', - 'swimming' => 'Simning', + 'running' => 'Running', + 'soccer' => 'Soccer', + 'swimming' => 'Swimming', 'tennis' => 'Tennis', - 'volleyball' => 'Volleyboll', - 'wilderness' => 'Vildmark', - 'wrestling' => 'Brottning', - 'after_shows' => 'Efter serier', - 'film_history' => 'Film Historik', - 'film_interviews' => 'Filmintervjuer', - 'film_reviews' => 'Filmrecensioner', - 'tv_reviews' => 'TV recensioner', + 'volleyball' => 'Volleyball', + 'wilderness' => 'Wilderness', + 'wrestling' => 'Wrestling', + 'after_shows' => 'After Shows', + 'film_history' => 'Film History', + 'film_interviews' => 'Film Interviews', + 'film_reviews' => 'Film Reviews', + 'tv_reviews' => 'TV Reviews', ], 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Tillbaka till podcast instrumentpanel', - 'post' => 'Ditt meddelande inlägg', + 'back_to_podcast_dashboard' => 'Back to podcast dashboard', + 'post' => 'Your announcement post', 'post_hint' => - "Skriv ett meddelande för att meddela publiceringen av din podcast. Meddelandet kommer att visas på din podcasts hemsida.", - 'message_placeholder' => 'Skriv ditt meddelande…', - 'submit' => 'Publicera', - 'publication_date' => 'Publiceringsdatum', + "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", + 'message_placeholder' => 'Write your message…', + 'submit' => 'Publish', + 'publication_date' => 'Publication date', 'publication_method' => [ - 'now' => 'Nu', - 'schedule' => 'Schemalägg', + 'now' => 'Now', + 'schedule' => 'Schedule', ], - 'scheduled_publication_date' => 'Planerat publiceringsdatum', + 'scheduled_publication_date' => 'Scheduled publication date', 'scheduled_publication_date_hint' => - 'Du kan schemalägga podcast-utgåvan genom att ställa in ett framtida publiceringsdatum. Detta fält måste formateras som YYYY-MM-DD HH:mm', - 'submit_edit' => 'Redigera publikation', - 'cancel_publication' => 'Avbryt publicering', - 'message_warning' => 'Du skrev inte ett meddelande för ditt tillkännagivande!', - 'message_warning_hint' => 'Att ha ett meddelande ökar socialt engagemang, vilket resulterar i en bättre synlighet för din podcast.', - 'message_warning_submit' => 'Publicera ändå', + 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', + 'submit_edit' => 'Edit publication', + 'cancel_publication' => 'Cancel publication', + 'message_warning' => 'You did not write a message for your announcement post!', + 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', + 'message_warning_submit' => 'Publish anyway', ], 'publication_status_banner' => [ - 'draft_mode' => 'utkastläge', - 'not_published' => 'Denna podcast är ännu inte publicerad.', - 'scheduled' => 'Denna podcast är schemalagd för publicering på {publication_date}.', + 'draft_mode' => 'draft mode', + 'not_published' => 'This podcast is not yet published.', + 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', ], 'delete_form' => [ 'disclaimer' => - "Ta bort podcasten kommer att ta bort alla avsnitt, mediefiler, inlägg och analytics i samband med det. Denna åtgärd är oåterkallelig, du kommer inte att kunna hämta dem efteråt.", - 'understand' => 'Jag förstår, jag vill att podcasten ska raderas permanent', - 'submit' => 'Radera', + "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", + 'understand' => 'I understand, I want the podcast to be permanently deleted', + 'submit' => 'Delete', ], - 'by' => 'Av {publisher}', - 'season' => 'Säsong {seasonNumber}', - 'list_of_episodes_year' => '{year} avsnitt ({episodeCount})', + 'by' => 'By {publisher}', + 'season' => 'Season {seasonNumber}', + 'list_of_episodes_year' => '{year} episodes ({episodeCount})', 'list_of_episodes_season' => - 'Säsong {seasonNumber} avsnitt ({episodeCount})', - 'no_episode' => 'Inga avsnitt hittades!', - 'follow' => 'Följ', + 'Season {seasonNumber} episodes ({episodeCount})', + 'no_episode' => 'No episode found!', + 'follow' => 'Follow', 'followers' => '{numberOfFollowers, plural, - one {# följare} - other {# följare} + one {# follower} + other {# followers} }', 'posts' => '{numberOfPosts, plural, - one {# inlägg} - other {# inlägg} + one {# post} + other {# posts} }', - 'activity' => 'Aktivitet', - 'episodes' => 'Avsnitt', + 'activity' => 'Activity', + 'episodes' => 'Episodes', 'sponsor' => 'Sponsor', - 'funding_links' => 'Finansierar länkar för {podcastTitle}', - 'find_on' => 'Hitta {podcastTitle} på', - 'listen_on' => 'Lyssna på', + 'funding_links' => 'Funding links for {podcastTitle}', + 'find_on' => 'Find {podcastTitle} on', + 'listen_on' => 'Listen on', ]; diff --git a/modules/Admin/Language/sv/PodcastImport.php b/modules/Admin/Language/sv/PodcastImport.php new file mode 100644 index 00000000..7c3ef67d --- /dev/null +++ b/modules/Admin/Language/sv/PodcastImport.php @@ -0,0 +1,37 @@ + + 'This procedure may take a long time. As the current version does not show any progress while it runs, you will not see anything updated until it is done. In case of timeout error, increase `max_execution_time` value.', + 'old_podcast_section_title' => 'The podcast to import', + 'old_podcast_section_subtitle' => + 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', + 'imported_feed_url' => 'Feed URL', + 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', + 'new_podcast_section_title' => 'The new podcast', + 'advanced_params_section_title' => 'Advanced parameters', + 'advanced_params_section_subtitle' => + 'Keep the default values if you have no idea of what the fields are for.', + 'slug_field' => 'Field to be used to calculate episode slug', + 'description_field' => + 'Source field used for episode description / show notes', + 'force_renumber' => 'Force episodes renumbering', + 'force_renumber_hint' => + 'Use this if your podcast does not have episode numbers but wish to set them during import.', + 'season_number' => 'Season number', + 'season_number_hint' => + 'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.', + 'max_episodes' => 'Maximum number of episodes to import', + 'max_episodes_hint' => 'Leave blank to import all episodes', + 'lock_import' => + 'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.', + 'submit' => 'Import podcast', +]; diff --git a/modules/Admin/Language/sv/PodcastNavigation.php b/modules/Admin/Language/sv/PodcastNavigation.php index 383f8817..b4d7ddc0 100644 --- a/modules/Admin/Language/sv/PodcastNavigation.php +++ b/modules/Admin/Language/sv/PodcastNavigation.php @@ -9,34 +9,30 @@ declare(strict_types=1); */ return [ - 'go_to_page' => 'Gå till podcast sida', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast instrumentpanel', - 'podcast-view' => 'Hem', - 'podcast-edit' => 'Redigera podcast', - 'podcast-persons-manage' => 'Hantera personer', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Avsnitt', - 'episode-list' => 'Alla avsnitt', - 'episode-create' => 'Nytt avsnitt', - 'analytics' => 'Statistik', - 'podcast-analytics' => 'Lyssnar översikt', - 'podcast-analytics-webpages' => 'Besök på webbsidor', - 'podcast-analytics-locations' => 'Platser', - 'podcast-analytics-unique-listeners' => 'Unika lyssnare', - 'podcast-analytics-players' => 'Spelare', - 'podcast-analytics-listening-time' => 'Lyssningstid', - 'podcast-analytics-time-periods' => 'Tidsperioder', - 'monetization' => 'Monetization', - 'subscription-list' => 'Alla prenumerationer', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Bidragsgivare', - 'contributor-list' => 'Alla bidragsgivare', - 'contributor-add' => 'Lägg till bidragsgivare', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Sociala nätverk', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'go_to_page' => 'Go to podcast page', + 'dashboard' => 'Podcast dashboard', + 'podcast-view' => 'Home', + 'podcast-edit' => 'Edit podcast', + 'podcast-persons-manage' => 'Manage persons', + 'episodes' => 'Episodes', + 'episode-list' => 'All episodes', + 'episode-create' => 'New episode', + 'analytics' => 'Analytics', + 'podcast-analytics' => 'Audience overview', + 'podcast-analytics-webpages' => 'Web pages visits', + 'podcast-analytics-locations' => 'Locations', + 'podcast-analytics-unique-listeners' => 'Unique listeners', + 'podcast-analytics-players' => 'Players', + 'podcast-analytics-listening-time' => 'Listening time', + 'podcast-analytics-time-periods' => 'Time periods', + 'premium' => 'Premium', + 'subscription-list' => 'All subscriptions', + 'subscription-add' => 'Add subscription', + 'contributors' => 'Contributors', + 'contributor-list' => 'All contributors', + 'contributor-add' => 'Add contributor', + 'platforms' => 'External platforms', + 'platforms-podcasting' => 'Podcasting', + 'platforms-social' => 'Social networks', + 'platforms-funding' => 'Funding', ]; diff --git a/modules/Admin/Language/sv/Settings.php b/modules/Admin/Language/sv/Settings.php index 6a595e0a..4a70dcba 100644 --- a/modules/Admin/Language/sv/Settings.php +++ b/modules/Admin/Language/sv/Settings.php @@ -9,50 +9,50 @@ declare(strict_types=1); */ return [ - 'title' => 'Allmänna inställningar', + 'title' => 'General settings', 'instance' => [ - 'title' => 'Instans', - 'site_icon' => 'Ikon för webbplats', - 'site_icon_delete' => 'Ta bort webbplatsikonen', - 'site_icon_hint' => 'Webbplatsikoner är vad du ser på dina webbläsarflikar, bokmärkesfältet och när du lägger till en webbplats som en genväg på mobila enheter.', - 'site_icon_helper' => 'Ikonen måste vara kvadratisk och minst 512px bred och hög.', - 'site_name' => 'Webbplatsens namn', - 'site_description' => 'Webbplatsbeskrivning', - 'submit' => 'Spara', - 'editSuccess' => 'Instansen har uppdaterats!', - 'deleteIconSuccess' => 'Webbplatsikonen har tagits bort!', + 'title' => 'Instance', + 'site_icon' => 'Site icon', + 'site_icon_delete' => 'Delete site icon', + 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', + 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', + 'site_name' => 'Site name', + 'site_description' => 'Site description', + 'submit' => 'Save', + 'editSuccess' => 'Instance has been updated successfully!', + 'deleteIconSuccess' => 'Site icon has been remove successfully!', ], 'images' => [ - 'title' => 'Bilder', - 'subtitle' => 'Här kan du regenerera alla bilder baserat på originalen som laddats upp. Att användas om du upptäcker att vissa bilder saknas. Denna uppgift kan ta ett tag.', - 'regenerate' => 'Regenerera bilder', - 'regenerationSuccess' => 'Alla bilder har återskapats framgångsrikt!', + 'title' => 'Images', + 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', + 'regenerate' => 'Regenerate images', + 'regenerationSuccess' => 'All images have been regenerated successfully!', ], 'housekeeping' => [ - 'title' => 'Städning', - 'subtitle' => 'Kör olika städuppgifter. Använd denna funktion om du någonsin stöter på problem med mediefiler eller dataintegritet. Dessa uppgifter kan ta ett tag.', - 'reset_counts' => 'Återställ räknare', - 'reset_counts_helper' => 'Detta alternativ kommer att räkna om och återställa alla data räknas (antal följare, inlägg, kommentarer, …).', - 'rewrite_media' => 'Skriv om media metadata', - 'rewrite_media_helper' => 'Detta alternativ kommer att ta bort alla överflödiga mediefiler och återskapa dem (bilder, ljudfiler, avskrifter, kapitel, …)', - 'rename_episodes_files' => 'Döp om avsnittets ljudfiler', - 'rename_episodes_files_hint' => 'Detta alternativ kommer att byta namn på alla avsnitt ljudfiler till en slumpmässig sträng av tecken. Använd detta om en av dina privata episoder länk läckte eftersom detta effektivt kommer att dölja det.', - 'clear_cache' => 'Rensa all cache', - 'clear_cache_helper' => 'Det här alternativet kommer att radera redis cache eller skrivbara/cache-filer.', - 'run' => 'Kör städning', - 'runSuccess' => 'Städning har körts framgångsrikt!', + 'title' => 'Housekeeping', + 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', + 'reset_counts' => 'Reset counts', + 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', + 'rewrite_media' => 'Rewrite media metadata', + 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', + 'rename_episodes_files' => 'Rename episode audio files', + 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', + 'clear_cache' => 'Clear all cache', + 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', + 'run' => 'Run housekeeping', + 'runSuccess' => 'Housekeeping has been run successfully!', ], 'theme' => [ - 'title' => 'Tema', - 'accent_section_title' => 'Accentfärg', - 'accent_section_subtitle' => 'Välj färg för att bestämma utseendet och känslan på alla offentliga sidor.', - 'pine' => 'Tall', - 'crimson' => 'Karmosinröd', - 'amber' => 'Bärnsten', - 'lake' => 'Sjö', + 'title' => 'Theme', + 'accent_section_title' => 'Accent color', + 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', + 'pine' => 'Pine', + 'crimson' => 'Crimson', + 'amber' => 'Amber', + 'lake' => 'Lake', 'jacaranda' => 'Jacaranda', 'onyx' => 'Onyx', - 'submit' => 'Spara', - 'setInstanceThemeSuccess' => 'Temat har uppdaterats!', + 'submit' => 'Save', + 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', ], ]; diff --git a/modules/Admin/Language/sv/Soundbite.php b/modules/Admin/Language/sv/Soundbite.php index fd80f828..a3f828fe 100644 --- a/modules/Admin/Language/sv/Soundbite.php +++ b/modules/Admin/Language/sv/Soundbite.php @@ -10,22 +10,22 @@ declare(strict_types=1); return [ 'list' => [ - 'title' => 'Ljudklipp', - 'soundbite' => 'Ljudklipp', + 'title' => 'Soundbites', + 'soundbite' => 'Soundbite', ], 'messages' => [ - 'createSuccess' => 'Ljudklipp har skapats!', - 'deleteSuccess' => 'Ljudklipp har tagits bort!', + 'createSuccess' => 'Soundbite has been successfully created!', + 'deleteSuccess' => 'Soundbite has been successfully removed!', ], 'form' => [ - 'title' => 'Nytt ljudklipp', - 'soundbite_title' => 'Ljudklipp titel', - 'start_time' => 'Starta vid', - 'duration' => 'Längd', - 'submit' => 'Skapa ljudklipp', + 'title' => 'New soundbite', + 'soundbite_title' => 'Soundbite title', + 'start_time' => 'Start at', + 'duration' => 'Duration', + 'submit' => 'Create soundbite', ], - 'play' => 'Spela ljudklipp', - 'stop' => 'Stoppa ljudklipp', - 'create' => 'Nytt ljudklipp', - 'delete' => 'Ta bort ljudklipp', + 'play' => 'Play soundbite', + 'stop' => 'Stop soundbite', + 'create' => 'New soundbite', + 'delete' => 'Delete soundbite', ]; diff --git a/modules/Admin/Language/sv/User.php b/modules/Admin/Language/sv/User.php new file mode 100644 index 00000000..585d6799 --- /dev/null +++ b/modules/Admin/Language/sv/User.php @@ -0,0 +1,56 @@ + "Edit {username}'s roles", + 'forcePassReset' => 'Force pass reset', + 'ban' => 'Ban', + 'unban' => 'Unban', + 'delete' => 'Delete', + 'create' => 'New user', + 'view' => "{username}'s info", + 'all_users' => 'All users', + 'list' => [ + 'user' => 'User', + 'roles' => 'Roles', + 'banned' => 'Banned?', + ], + 'form' => [ + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', + 'new_password' => 'New Password', + 'roles' => 'Roles', + 'permissions' => 'Permissions', + 'submit_create' => 'Create user', + 'submit_edit' => 'Save', + 'submit_password_change' => 'Change!', + ], + 'roles' => [ + 'superadmin' => 'Super admin', + ], + 'messages' => [ + 'createSuccess' => + 'User created successfully! {username} will be prompted with a password reset upon first authentication.', + 'rolesEditSuccess' => + "{username}'s roles have been successfully updated.", + 'forcePassResetSuccess' => + '{username} will be prompted with a password reset upon next visit.', + 'banSuccess' => '{username} has been banned.', + 'unbanSuccess' => '{username} has been unbanned.', + 'editOwnerError' => + '{username} is the instance owner, you cannot edit its roles.', + 'banSuperAdminError' => + '{username} is a superadmin, one does not simply ban a superadmin…', + 'deleteSuperAdminError' => + '{username} is a superadmin, one does not simply delete a superadmin…', + 'deleteSuccess' => '{username} has been deleted.', + ], +]; diff --git a/modules/Admin/Language/sv/Validation.php b/modules/Admin/Language/sv/Validation.php index 8dc9341e..750b1968 100644 --- a/modules/Admin/Language/sv/Validation.php +++ b/modules/Admin/Language/sv/Validation.php @@ -10,8 +10,9 @@ declare(strict_types=1); return [ 'min_dims' => - '{field} är antingen inte en bild, eller så är den inte bred eller tillräckligt hög.', + '{field} is either not an image, or it is not wide or tall enough.', 'is_image_ratio' => - '{field} är antingen inte en bild eller inte av rätt förhållande.', - 'is_json' => '{field} contains invalid JSON.', + '{field} is either not an image or not of the right ratio.', + 'validate_url' => + 'The {field} field must be a valid URL (eg. https://example.com/).', ]; diff --git a/modules/Admin/Language/sv/VideoClip.php b/modules/Admin/Language/sv/VideoClip.php index a94406b9..638de697 100644 --- a/modules/Admin/Language/sv/VideoClip.php +++ b/modules/Admin/Language/sv/VideoClip.php @@ -10,63 +10,63 @@ declare(strict_types=1); return [ 'list' => [ - 'title' => 'Videoklipp', + 'title' => 'Video clips', 'status' => [ 'label' => 'Status', - 'queued' => 'köad', - 'queued_hint' => 'Klipp väntar på att bearbetas.', - 'pending' => 'väntande', - 'pending_hint' => 'Klipp kommer att genereras inom kort.', - 'running' => 'körs', - 'running_hint' => 'Klipp genereras.', - 'failed' => 'misslyckades', - 'failed_hint' => 'Klipp kunde inte genereras: skript misslyckades.', - 'passed' => 'godkänd', - 'passed_hint' => 'Klipp har skapats framgångsrikt!', + 'queued' => 'queued', + 'queued_hint' => 'Clip is waiting to be processed.', + 'pending' => 'pending', + 'pending_hint' => 'Clip will be generated shortly.', + 'running' => 'running', + 'running_hint' => 'Clip is being generated.', + 'failed' => 'failed', + 'failed_hint' => 'Clip could not be generated: script failure.', + 'passed' => 'passed', + 'passed_hint' => 'Clip was generated successfully!', ], - 'clip' => 'Klipp', - 'duration' => 'Varaktighet för jobb', + 'clip' => 'Clip', + 'duration' => 'Job duration', ], - 'title' => 'Videoklipp: {videoClipLabel}', - 'download_clip' => 'Ladda ner klipp', - 'create' => 'Nytt videoklipp', - 'go_to_page' => 'Gå till klippsida', - 'retry' => 'Generering av nytt klipp', - 'delete' => 'Ta bort klipp', + 'title' => 'Video clip: {videoClipLabel}', + 'download_clip' => 'Download clip', + 'create' => 'New video clip', + 'go_to_page' => 'Go to clip page', + 'retry' => 'Retry clip generation', + 'delete' => 'Delete clip', 'logs' => 'Job logs', 'messages' => [ - 'alreadyExistingError' => 'Det videoklipp du försöker skapa finns redan!', - 'addToQueueSuccess' => 'Videoklipp har lagts till i kön, väntar på att skapas!', - 'deleteSuccess' => 'Videoklipp har tagits bort!', + 'alreadyExistingError' => 'The video clip you are trying to create already exists!', + 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', + 'deleteSuccess' => 'Video clip has been successfully removed!', ], 'format' => [ - 'landscape' => 'Liggande', - 'portrait' => 'Stående', - 'squared' => 'Kvadrat', + 'landscape' => 'Landscape', + 'portrait' => 'Portrait', + 'squared' => 'Squared', ], 'form' => [ - 'title' => 'Nytt videoklipp', - 'params_section_title' => 'Parametrar för videoklipp', - 'clip_title' => 'Klipp titel', + 'title' => 'New video clip', + 'params_section_title' => 'Video clip parameters', + 'clip_title' => 'Clip title', 'format' => [ - 'label' => 'Välj ett format', - 'landscape_hint' => 'Med ett 16:9 förhållande, landskapsvideor är bra för PeerTube, Youtube och Vimeo.', - 'portrait_hint' => 'Med 9:16 förhållande, porträttfilmer är bra för TikTok, Youtube shorts och Instagram berättelser.', - 'squared_hint' => 'Med en 1:1 förhållande, fyrkantiga videor är bra för Mastodon, Facebook, Twitter och LinkedIn.', + 'label' => 'Choose a format', + 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', + 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', + 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', ], - 'theme' => 'Välj ett tema', - 'start_time' => 'Starta vid', - 'duration' => 'Längd', - 'trim_start' => 'Trimma start', - 'trim_end' => 'Trimma slut', - 'submit' => 'Skapa videoklipp', + 'theme' => 'Select a theme', + 'start_time' => 'Start at', + 'duration' => 'Duration', + 'trim_start' => 'Trim start', + 'trim_end' => 'Trim end', + 'submit' => 'Create video clip', ], 'requirements' => [ - 'title' => 'Krav ej uppfyllda', - 'missing' => 'Du har saknade krav. Se till att lägga till alla nödvändiga objekt som tillåts att skapa en video för detta avsnitt!', + 'title' => 'Missing requirements', + 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', 'ffmpeg' => 'FFmpeg', - 'gd' => 'Grafik Rita (GD)', - 'freetype' => 'Freetyp bibliotek för GD', - 'transcript' => 'Avskrift fil (.srt)', + 'gd' => 'Graphics Draw (GD)', + 'freetype' => 'Freetype library for GD', + 'transcript' => 'Transcript file (.srt)', ], ]; diff --git a/modules/Admin/Language/uk/AboutCastopod.php b/modules/Admin/Language/uk/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/uk/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/uk/Breadcrumb.php b/modules/Admin/Language/uk/Breadcrumb.php deleted file mode 100644 index 408c9f9f..00000000 --- a/modules/Admin/Language/uk/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb', - config('Admin') - ->gateway => 'Home', - 'podcasts' => 'podcasts', - 'episodes' => 'episodes', - 'subscriptions' => 'subscriptions', - 'contributors' => 'contributors', - 'pages' => 'pages', - 'settings' => 'settings', - 'theme' => 'theme', - 'about' => 'about', - 'add' => 'add', - 'new' => 'new', - 'edit' => 'edit', - 'persons' => 'persons', - 'publish' => 'publish', - 'publish-edit' => 'edit publication', - 'publish-date-edit' => 'edit publication date', - 'unpublish' => 'unpublish', - 'delete' => 'delete', - 'remove' => 'remove', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'users', - 'my-account' => 'my account', - 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforms', - 'social' => 'social networks', - 'funding' => 'funding', - 'monetization-other' => 'other monetization', - 'analytics' => 'analytics', - 'locations' => 'locations', - 'webpages' => 'web pages', - 'unique-listeners' => 'unique listeners', - 'players' => 'players', - 'listening-time' => 'listening time', - 'time-periods' => 'time periods', - 'soundbites' => 'soundbites', - 'video-clips' => 'video clips', - 'embed' => 'embeddable player', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/uk/Charts.php b/modules/Admin/Language/uk/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/uk/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/uk/Common.php b/modules/Admin/Language/uk/Common.php deleted file mode 100644 index 74addcf2..00000000 --- a/modules/Admin/Language/uk/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Loading…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/uk/Countries.php b/modules/Admin/Language/uk/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/uk/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/uk/Dashboard.php b/modules/Admin/Language/uk/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/uk/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/uk/Episode.php b/modules/Admin/Language/uk/Episode.php deleted file mode 100644 index 4fa846e3..00000000 --- a/modules/Admin/Language/uk/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episode is already published.', - 'publish_cancel_error' => 'Episode is already published.', - 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', - 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', - 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', - 'unpublish_error' => 'Episode is not published.', - 'delete' => 'Delete', - 'go_to_page' => 'Go to page', - 'create' => 'Add an episode', - 'publication_status' => [ - 'published' => 'Published', - 'with_podcast' => 'Published', - 'scheduled' => 'Scheduled', - 'not_published' => 'Not published', - ], - 'with_podcast_hint' => 'To be published at the same time as the podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Search for an episode', - 'clear' => 'Clear search', - 'submit' => 'Search', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episodes} - }', - 'episode' => 'Episode', - 'visibility' => 'Visibility', - 'downloads' => 'Downloads', - 'comments' => 'Comments', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'Episode has been successfully created!', - 'editSuccess' => 'Episode has been successfully updated!', - 'publishSuccess' => '{publication_status, select, - published {Episode successfully published!} - scheduled {Episode publication successfully scheduled!} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not published.} - }', - 'publishCancelSuccess' => 'Episode publication successfully cancelled!', - 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', - 'scheduleDateError' => 'Schedule date must be set!', - 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', - 'deleteSuccess' => 'Episode successfully deleted!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/uk/EpisodeNavigation.php b/modules/Admin/Language/uk/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/uk/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/uk/Fediverse.php b/modules/Admin/Language/uk/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/uk/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/uk/Home.php b/modules/Admin/Language/uk/Home.php deleted file mode 100644 index 6249bab1..00000000 --- a/modules/Admin/Language/uk/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'Усі подкасти', - 'no_podcast' => 'Подкастів не знайдено', -]; diff --git a/modules/Admin/Language/uk/Install.php b/modules/Admin/Language/uk/Install.php deleted file mode 100644 index 814cd8c2..00000000 --- a/modules/Admin/Language/uk/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Ручне налаштування', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Ім\'я хоста бази даних', - 'db_name' => 'Назва бази даних', - 'db_username' => 'Ім\'я користувача бази даних', - 'db_password' => 'Пароль бази даних', - 'db_prefix' => 'Префікс бази даних', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Обробник кешу', - 'cacheHandlerOptions' => [ - 'file' => 'Файл', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Далі', - 'submit' => 'Завершити установку', - 'create_superadmin' => 'Створіть свій обліковий запис головного адміністратора', - 'email' => 'Пошта', - 'username' => 'Ім\'я користувача', - 'password' => 'Пароль', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Ваш обліковий запис суперадміністратора було успішно створено. Увійдіть, щоб почати подкасти!', - 'databaseConnectError' => - 'Кастопод не зміг підключитись до бази даних. Змініть конфігурацію бази даних і повторіть спробу.', - 'writeError' => - "Не вдалося створити/записати файл `.env`. Ви повинні створити його вручну, перейшовши шаблон файлу `.env.example` в пакеті Castopode.", - ], -]; diff --git a/modules/Admin/Language/uk/Navigation.php b/modules/Admin/Language/uk/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/uk/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/uk/Notifications.php b/modules/Admin/Language/uk/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/uk/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/uk/Page.php b/modules/Admin/Language/uk/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/uk/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/uk/Pager.php b/modules/Admin/Language/uk/Pager.php deleted file mode 100644 index c940f604..00000000 --- a/modules/Admin/Language/uk/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Навігація між сторінками', - 'first' => 'Перший', - 'previous' => 'Попередній', - 'next' => 'Наступний', - 'last' => 'Останній', - 'older' => 'Старші', - 'newer' => 'Новіші', - 'invalidTemplate' => '{0} не є правильним шаблоном Пейджера.', - 'invalidPaginationGroup' => '{0} - некоректна група нумерацій.', -]; diff --git a/modules/Admin/Language/uk/Person.php b/modules/Admin/Language/uk/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/uk/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/uk/Platforms.php b/modules/Admin/Language/uk/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/uk/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/uk/Podcast.php b/modules/Admin/Language/uk/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/uk/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/uk/PodcastNavigation.php b/modules/Admin/Language/uk/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/uk/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/uk/Settings.php b/modules/Admin/Language/uk/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/uk/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/uk/Soundbite.php b/modules/Admin/Language/uk/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/uk/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/uk/Validation.php b/modules/Admin/Language/uk/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/uk/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/uk/VideoClip.php b/modules/Admin/Language/uk/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/uk/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Admin/Language/zh-hans/Breadcrumb.php b/modules/Admin/Language/zh-Hans/Breadcrumb.php similarity index 81% rename from modules/Admin/Language/zh-hans/Breadcrumb.php rename to modules/Admin/Language/zh-Hans/Breadcrumb.php index db129570..80105ec3 100644 --- a/modules/Admin/Language/zh-hans/Breadcrumb.php +++ b/modules/Admin/Language/zh-Hans/Breadcrumb.php @@ -19,29 +19,24 @@ return [ 'pages' => '页', 'settings' => '设置', 'theme' => '主题', - 'about' => '关于', 'add' => '添加', 'new' => '新建', 'edit' => '编辑', 'persons' => '人', 'publish' => '发布', 'publish-edit' => '编辑发布', - 'publish-date-edit' => '编辑发布日期', + 'publish-date-edit' => 'edit publication date', 'unpublish' => '取消发布', 'delete' => '删除', - 'remove' => '移除', 'fediverse' => '联邦宇宙', - 'blocked-actors' => '已屏蔽演员', - 'blocked-domains' => '已屏蔽域名', + 'block-lists' => '封禁列表', 'users' => '用户', 'my-account' => '我的帐户', 'change-password' => '修改密码', - 'imports' => '导入', - 'sync-feeds' => 'synchronize feeds', + 'import' => '订阅源导入', 'platforms' => '平台', 'social' => '社交网络', 'funding' => '资金支持', - 'monetization-other' => 'other monetization', 'analytics' => '统计数据', 'locations' => '位置', 'webpages' => '网页', diff --git a/modules/Admin/Language/zh-hans/Charts.php b/modules/Admin/Language/zh-Hans/Charts.php similarity index 96% rename from modules/Admin/Language/zh-hans/Charts.php rename to modules/Admin/Language/zh-Hans/Charts.php index e1da7b26..e623691a 100644 --- a/modules/Admin/Language/zh-hans/Charts.php +++ b/modules/Admin/Language/zh-Hans/Charts.php @@ -37,5 +37,4 @@ return [ 'podcast_by_bandwidth' => '每日使用带宽(MB)', 'total_storage_by_month' => '每月存储量 (MB)', 'total_bandwidth_by_month' => '每月使用带宽(MB)', - 'total_bandwidth_by_month_limit' => '每月限制为 {totalBandwidth}', ]; diff --git a/modules/Admin/Language/zh-hans/Common.php b/modules/Admin/Language/zh-Hans/Common.php similarity index 98% rename from modules/Admin/Language/zh-hans/Common.php rename to modules/Admin/Language/zh-Hans/Common.php index 5909a764..1ecaf542 100644 --- a/modules/Admin/Language/zh-hans/Common.php +++ b/modules/Admin/Language/zh-Hans/Common.php @@ -40,7 +40,6 @@ return [ ], 'upload_file' => '上传文件', 'remote_url' => '远程网址', - 'save' => 'Save', ], 'play_episode_button' => [ 'play' => '播放', diff --git a/modules/Auth/Language/zh-hans/Contributor.php b/modules/Admin/Language/zh-Hans/Contributor.php similarity index 71% rename from modules/Auth/Language/zh-hans/Contributor.php rename to modules/Admin/Language/zh-Hans/Contributor.php index 0d28c5ad..d90ef87d 100644 --- a/modules/Auth/Language/zh-hans/Contributor.php +++ b/modules/Admin/Language/zh-Hans/Contributor.php @@ -28,16 +28,10 @@ return [ 'submit_add' => '添加贡献者', 'submit_edit' => '更新角色', ], - 'delete_form' => [ - 'title' => '移除 {contributor}', - 'disclaimer' => - '你将要从贡献者中删除 {contributor},他们将无法再访问“{podcastTitle}”。', - 'understand' => '我明白,我想从“{podcastTitle}”中删除 {contributor}', - 'submit' => '移除', + 'roles' => [ + 'podcast_admin' => '播客管理员', ], 'messages' => [ - 'editSuccess' => '已成功更改角色!', - 'editOwnerError' => "你无法编辑播客所有者!", 'removeOwnerError' => "你无法删除播客所有者!", 'removeSuccess' => '你从 {username} 移除 {podcastTitle}', diff --git a/modules/Admin/Language/zh-hans/Countries.php b/modules/Admin/Language/zh-Hans/Countries.php similarity index 100% rename from modules/Admin/Language/zh-hans/Countries.php rename to modules/Admin/Language/zh-Hans/Countries.php diff --git a/modules/Admin/Language/zh-hans/Dashboard.php b/modules/Admin/Language/zh-Hans/Dashboard.php similarity index 100% rename from modules/Admin/Language/zh-hans/Dashboard.php rename to modules/Admin/Language/zh-Hans/Dashboard.php diff --git a/modules/Admin/Language/zh-hans/Episode.php b/modules/Admin/Language/zh-Hans/Episode.php similarity index 82% rename from modules/Admin/Language/zh-hans/Episode.php rename to modules/Admin/Language/zh-Hans/Episode.php index 49061df4..7a8f335a 100644 --- a/modules/Admin/Language/zh-hans/Episode.php +++ b/modules/Admin/Language/zh-Hans/Episode.php @@ -9,8 +9,8 @@ declare(strict_types=1); */ return [ - 'season' => '第 {seasonNumber} 节', - 'season_abbr' => '第 {seasonNumber} 节', + 'season' => '第 {seasonNumber} 季', + 'season_abbr' => '第 {seasonNumber} 季', 'number' => '第 {episodeNumber} 集', 'number_abbr' => '第 {episodeNumber} 集', 'season_episode' => '第 {seasonNumber} 季第 {episodeNumber} 集', @@ -22,17 +22,16 @@ return [ 'all_podcast_episodes' => '所有播客剧集', 'back_to_podcast' => '返回播客', 'edit' => '编辑', - 'preview' => 'Preview', 'publish' => '发布', 'publish_edit' => '编辑发布', - 'publish_date_edit' => '编辑发布日期', + 'publish_date_edit' => 'Edit publication date', 'unpublish' => '取消发布', 'publish_error' => '剧集已被发布。', 'publish_edit_error' => '剧集已被发布。', 'publish_cancel_error' => '剧集已被发布。', - 'publish_date_edit_error' => '剧集尚未发布,你不能编辑其发布日期。', - 'publish_date_edit_future_error' => '剧集的发布日期只能设置为过去的日期! 如果你想重新安排日期,请先取消发布。', - 'publish_date_edit_success' => '剧集的发布日期已成功更新!', + 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', + 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', + 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', 'unpublish_error' => '剧集尚未发布。', 'delete' => '删除', 'go_to_page' => '转到页面', @@ -56,7 +55,6 @@ return [ }', 'episode' => '剧集', 'visibility' => '可见性', - 'downloads' => '下载', 'comments' => '评论', 'actions' => '操作', ], @@ -81,13 +79,13 @@ return [ audio {音频} other {媒体} }', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', + 'deleteFileError' => '无法删除 {type, select, + transcript {字幕} + chapters {章节} + image {封面} + audio {音频} + other {媒体} + } 文件 {file_path}。您可以手动将其从磁盘删除。', 'sameSlugError' => '选中的剧集已存在。', ], 'form' => [ @@ -139,9 +137,9 @@ return [ 'location_name' => '位置名称或地址', 'location_name_hint' => '真或假位置都可以', 'transcript' => '字幕(字幕/隐藏字幕)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', + 'transcript_hint' => '仅允许使用 .srt。', 'transcript_download' => '下载字幕', - 'transcript_file' => 'Transcript file (.srt or .vtt)', + 'transcript_file' => '字幕文件(.srt)', 'transcript_remote_url' => '用于字幕的网址', 'transcript_file_delete' => '删除字幕文件', 'chapters' => '章节', @@ -152,8 +150,8 @@ return [ 'chapters_file_delete' => '删除章节文件', 'advanced_section_title' => '高级参数', 'advanced_section_subtitle' => - '如果您需要 Castopod 无法处理的 RSS 标签,请在此处设置它们。', - 'custom_rss' => '剧集的自定义 RSS 标签', + '如果你不需要 Castopod 处理某些订阅源标签,请在此处设置。', + 'custom_rss' => '剧集的自定义订阅标签', 'custom_rss_hint' => '这将被注入到 ❬item❭ 标签中。', 'block' => '剧集应该在公共目录中隐藏', 'block_hint' => @@ -185,13 +183,13 @@ return [ 'message_warning_submit' => '仍然发布', ], 'publish_date_edit_form' => [ - 'new_publication_date' => '新发布日期', - 'new_publication_date_hint' => '必须设置为过去的日期。', - 'submit' => '编辑发布日期', + 'new_publication_date' => 'New publication date', + 'new_publication_date_hint' => 'Must be set to a past date.', + 'submit' => 'Edit publication date', ], 'unpublish_form' => [ 'disclaimer' => - "取消发布该剧集将删除相关的所有评论和播文,并将其从播客的 RSS 摘要中删除。", + "取消发布该剧集将删除相关的所有评论和播文,并将其从播客的订阅源中删除。", 'understand' => '我明白,我想取消发布此剧集', 'submit' => '取消发布', ], @@ -212,14 +210,4 @@ return [ 'light' => '亮色', 'light-transparent' => '亮色透明', ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], ]; diff --git a/modules/Admin/Language/zh-hans/EpisodeNavigation.php b/modules/Admin/Language/zh-Hans/EpisodeNavigation.php similarity index 100% rename from modules/Admin/Language/zh-hans/EpisodeNavigation.php rename to modules/Admin/Language/zh-Hans/EpisodeNavigation.php diff --git a/modules/Admin/Language/zh-hans/Fediverse.php b/modules/Admin/Language/zh-Hans/Fediverse.php similarity index 100% rename from modules/Admin/Language/zh-hans/Fediverse.php rename to modules/Admin/Language/zh-Hans/Fediverse.php diff --git a/modules/Admin/Language/zh-hans/Home.php b/modules/Admin/Language/zh-Hans/Home.php similarity index 100% rename from modules/Admin/Language/zh-hans/Home.php rename to modules/Admin/Language/zh-Hans/Home.php diff --git a/modules/Admin/Language/zh-hans/Install.php b/modules/Admin/Language/zh-Hans/Install.php similarity index 100% rename from modules/Admin/Language/zh-hans/Install.php rename to modules/Admin/Language/zh-Hans/Install.php diff --git a/modules/Auth/Language/zh-hans/MyAccount.php b/modules/Admin/Language/zh-Hans/MyAccount.php similarity index 100% rename from modules/Auth/Language/zh-hans/MyAccount.php rename to modules/Admin/Language/zh-Hans/MyAccount.php diff --git a/modules/Admin/Language/zh-hans/Navigation.php b/modules/Admin/Language/zh-Hans/Navigation.php similarity index 87% rename from modules/Admin/Language/zh-hans/Navigation.php rename to modules/Admin/Language/zh-Hans/Navigation.php index 3ed1fccc..9cf34c78 100644 --- a/modules/Admin/Language/zh-hans/Navigation.php +++ b/modules/Admin/Language/zh-Hans/Navigation.php @@ -12,14 +12,12 @@ return [ 'toggle_sidebar' => '切换侧边栏', 'go_to_website' => '访问网站', 'go_to_admin' => '登录到管理员', - 'not-authorized' => 'Not authorized', 'dashboard' => '控制面板', 'admin' => '主页', 'podcasts' => '播客', 'podcast-list' => '全部播客', 'podcast-create' => '新播客', - 'all-podcast-imports' => '全部播客导入', - 'podcast-imports-add' => '导入播客', + 'podcast-import' => '导入播客', 'persons' => '人员', 'person-list' => '所有人', 'person-create' => '新成员', @@ -35,7 +33,6 @@ return [ 'settings' => '设置', 'settings-general' => '通用', 'settings-theme' => '主题', - 'admin-about' => 'About', 'account' => [ 'my-account' => '我的帐户', 'change-password' => '修改密码', diff --git a/modules/Admin/Language/zh-hans/Notifications.php b/modules/Admin/Language/zh-Hans/Notifications.php similarity index 100% rename from modules/Admin/Language/zh-hans/Notifications.php rename to modules/Admin/Language/zh-Hans/Notifications.php diff --git a/modules/Admin/Language/zh-hans/Page.php b/modules/Admin/Language/zh-Hans/Page.php similarity index 100% rename from modules/Admin/Language/zh-hans/Page.php rename to modules/Admin/Language/zh-Hans/Page.php diff --git a/modules/Admin/Language/zh-hans/Pager.php b/modules/Admin/Language/zh-Hans/Pager.php similarity index 100% rename from modules/Admin/Language/zh-hans/Pager.php rename to modules/Admin/Language/zh-Hans/Pager.php diff --git a/modules/Admin/Language/zh-hans/Person.php b/modules/Admin/Language/zh-Hans/Person.php similarity index 100% rename from modules/Admin/Language/zh-hans/Person.php rename to modules/Admin/Language/zh-Hans/Person.php diff --git a/modules/Admin/Language/zh-hans/Platforms.php b/modules/Admin/Language/zh-Hans/Platforms.php similarity index 68% rename from modules/Admin/Language/zh-hans/Platforms.php rename to modules/Admin/Language/zh-Hans/Platforms.php index 2869a4b2..6a71b42a 100644 --- a/modules/Admin/Language/zh-hans/Platforms.php +++ b/modules/Admin/Language/zh-Hans/Platforms.php @@ -9,22 +9,9 @@ declare(strict_types=1); */ return [ - 'title' => [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', + 'title' => '平台', 'home_url' => '转至 {platformName} 网站', - 'register' => 'Register', 'submit_url' => '在 {platformName} 上提交你的播客', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', 'visible' => '在播客主页上显示?', 'on_embed' => '在嵌入式播放器上显示?', 'remove' => '移除 {platformName}', diff --git a/modules/Admin/Language/zh-hans/Podcast.php b/modules/Admin/Language/zh-Hans/Podcast.php similarity index 83% rename from modules/Admin/Language/zh-hans/Podcast.php rename to modules/Admin/Language/zh-Hans/Podcast.php index 1a47c363..1a145c20 100644 --- a/modules/Admin/Language/zh-hans/Podcast.php +++ b/modules/Admin/Language/zh-Hans/Podcast.php @@ -13,7 +13,6 @@ return [ 'no_podcast' => '没有找到播客!', 'create' => '创建播客', 'import' => '导入播客', - 'all_imports' => '播客导入', 'new_episode' => '新剧集', 'view' => '浏览博客', 'edit' => '编辑播客', @@ -22,7 +21,6 @@ return [ 'delete' => '删除播客', 'see_episodes' => '查看剧集', 'see_contributors' => '查看贡献者', - 'monetization_other' => 'Other monetization', 'go_to_page' => '转到页面', 'latest_episodes' => '最新剧集', 'see_all_episodes' => '查看所有剧集', @@ -50,6 +48,7 @@ return [ other {# 剧集} } 添加到播客!', 'podcastFeedUpToDate' => '播客已经是最新状态。', + 'podcastNotImported' => '播客无法更新,因为它没有被导入。', 'publishError' => '此播客已经发布或计划发布。', 'publishEditError' => '此播客未计划发布。', 'publishCancelSuccess' => '取消播客发布!', @@ -58,8 +57,6 @@ return [ 'form' => [ 'identity_section_title' => '播客标识', 'identity_section_subtitle' => '这些字段可能让你脱颖而出。', - 'fediverse_section_title' => 'Fediverse identity', - 'cover' => '播客封面', 'cover_size_hint' => '封面必须是方形,而且至少 1400 px 宽度和高度。', 'banner' => '播客横幅', @@ -74,17 +71,7 @@ return [ 'episodic' => '剧集', 'episodic_hint' => '如果在没有任何特定情况下进行剧集排序。那么最新剧集优先显示。', 'serial' => '系列', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', + 'serial_hint' => '如果指定剧集排序方式。那么最久剧集将优先显示。', ], 'description' => '描述', 'classification_section_title' => '分类', @@ -105,12 +92,10 @@ return [ 'author_section_subtitle' => '谁在管理播客?', 'owner_name' => '所有者名称', 'owner_name_hint' => - '仅供管理使用,在公开 RSS 摘要中可见。', + '仅供管理使用,在公开 RSS 提要中可见。', 'owner_email' => '所有者邮箱', 'owner_email_hint' => - '大多数平台将使用它来验证播客的所有权。 在公开 RSS 摘要中可见。', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', + '大多数平台将使用它来验证播客的所有权。 在公开 RSS 提要中可见。', 'publisher' => '发布者', 'publisher_hint' => '负责制作节目的小组。 通常指播客的母公司或网络。 有时会被标记为“作者”。', @@ -125,25 +110,19 @@ return [ 'premium' => '高级版', 'premium_by_default' => '剧集必须默认设置为付费会员订阅。', 'premium_by_default_hint' => '默认情况下,播客剧集将被标记为高级。 你仍然可以选择将某些剧集、预告片等设置为公开。', - 'op3' => '打开播客前缀项目 (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => '使用 OP3(一项开源且值得信赖的第三方分析服务)来评估您的分析数据。 与开源播客生态系统共享、验证和比较您的分析数据。', - 'op3_enable' => '启用 OP3 分析服务', - 'op3_enable_hint' => '出于安全原因,高级剧集的分析数据将不会与 OP3 共享。', 'payment_pointer' => '网络货币化支付指南', 'payment_pointer_hint' => '借助网络货币化,你可以在此收款', 'advanced_section_title' => '高级参数', 'advanced_section_subtitle' => - '如果您需要 Castopod 无法处理的 RSS 标签,请在此处设置它们。', - 'custom_rss' => '播客的自定义 RSS 标签', - 'custom_rss_hint' => '这将被注入到 ❬channel❭ 标签中。', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => '新摘要网址', - 'new_feed_url_hint' => '当你迁移到另一个域或播客托管平台时,请使用此字段。 默认情况下,播客导入时,该值为当前的 RSS 网址。', - 'old_feed_url' => '旧摘要网址', + '如果你不需要 Castopod 处理某些订阅源标签,请在此处设置。', + 'custom_rss' => '播客的自定义订阅标签', + 'custom_rss_hint' => '这将被注入到❬channel❭标签中。', + 'new_feed_url' => '新订阅源网址', + 'new_feed_url_hint' => '当你迁移到另一个域或播客托管平台时,请使用此字段。 默认情况下,播客导入时,该值为当前的订阅源网址。', + 'old_feed_url' => '旧订阅源网址', + 'update_feed' => '更新订阅源', + 'update_feed_tip' => '导入此播客的最新剧集', 'partnership' => '合作伙伴', 'partner_id' => 'ID', 'partner_link_url' => '链接网址', @@ -151,13 +130,14 @@ return [ 'partner_id_hint' => '你自己的合作伙伴 ID', 'partner_link_url_hint' => '通用合作伙伴链接地址', 'partner_image_url_hint' => '通用合作伙伴图片地址', + 'status_section_title' => '状态', 'block' => '播客应该在公共目录中隐藏', 'block_hint' => '播客显示或隐藏状态:打开此选项可防止整个播客出现在 Apple 播客、Google 播客以及从此目录中提取剧集的任何第三方应用程序中。(不保证)', 'complete' => '播客没有新剧集', 'lock' => '防止播客被盗用', 'lock_hint' => - '目的是告诉其他播客平台是否允许导入此摘要。 值为是表示拒绝将此摘要导入任何平台。', + '目的是告诉其他播客平台是否允许导入此订阅源。 值为是表示拒绝将此订阅源导入任何平台。', 'submit_create' => '创建播客', 'submit_edit' => '保存播客', ], diff --git a/modules/Admin/Language/zh-Hans/PodcastImport.php b/modules/Admin/Language/zh-Hans/PodcastImport.php new file mode 100644 index 00000000..ad5732e6 --- /dev/null +++ b/modules/Admin/Language/zh-Hans/PodcastImport.php @@ -0,0 +1,37 @@ + + '此过程可能需要很长时间。 由于当前版本在运行时未显示任何进度,因此在完成之前您不会看到任何提示。 在超时错误的情况下,增加 `max_execution_time` 值。', + 'old_podcast_section_title' => '要导入的播客', + 'old_podcast_section_subtitle' => + '请确保您在导入之前拥有此播客的权限。 在没有权限的情况下复制和广播播客是盗版行为,可能受到起诉。', + 'imported_feed_url' => '订阅源的 URL', + 'imported_feed_url_hint' => '订阅源必须是 xml 或 rss 格式。', + 'new_podcast_section_title' => '新播客', + 'advanced_params_section_title' => '高级参数', + 'advanced_params_section_subtitle' => + '如果您不知道这些字段的用途,请保留默认值。', + 'slug_field' => '用于计算剧集 Slug 的字段', + 'description_field' => + '用于剧集描述/节目说明的源字段', + 'force_renumber' => '强制剧集重新编号', + 'force_renumber_hint' => + '如果你的播客没有剧集编号但希望在导入时设置,请使用此选项。', + 'season_number' => '季号', + 'season_number_hint' => + '如果您的播客没有季号,但希望在导入时设置,请使用此选项,否则留空。', + 'max_episodes' => '要导入的最大剧集数', + 'max_episodes_hint' => '留空导入所有剧集', + 'lock_import' => + '此订阅源受到保护。你不能导入它。如果你是所有者,请在原平台取消保护。', + 'submit' => '导入播客', +]; diff --git a/modules/Admin/Language/zh-hans/PodcastNavigation.php b/modules/Admin/Language/zh-Hans/PodcastNavigation.php similarity index 74% rename from modules/Admin/Language/zh-hans/PodcastNavigation.php rename to modules/Admin/Language/zh-Hans/PodcastNavigation.php index 0978a9b2..75564b13 100644 --- a/modules/Admin/Language/zh-hans/PodcastNavigation.php +++ b/modules/Admin/Language/zh-Hans/PodcastNavigation.php @@ -10,13 +10,10 @@ declare(strict_types=1); return [ 'go_to_page' => '转到播客页面', - 'rss_feed' => 'RSS feed', 'dashboard' => '播客控制面板', 'podcast-view' => '主页', 'podcast-edit' => '编辑播客', 'podcast-persons-manage' => '管理人员', - 'podcast-imports' => '播客导入', - 'podcast-imports-sync' => 'Sync feeds', 'episodes' => '剧集', 'episode-list' => '所有剧集', 'episode-create' => '新剧集', @@ -28,15 +25,14 @@ return [ 'podcast-analytics-players' => '播放', 'podcast-analytics-listening-time' => '收听时间', 'podcast-analytics-time-periods' => '时间段', - 'monetization' => 'Monetization', + 'premium' => '高级版', 'subscription-list' => '所有订阅', - 'subscription-create' => 'Add subscription', + 'subscription-add' => '添加订阅', 'contributors' => '贡献者', 'contributor-list' => '所有贡献者', 'contributor-add' => '添加贡献者', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', + 'platforms' => '外部平台', + 'platforms-podcasting' => '播客', 'platforms-social' => '社交网络', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', + 'platforms-funding' => '资金支持', ]; diff --git a/modules/Admin/Language/zh-hans/Settings.php b/modules/Admin/Language/zh-Hans/Settings.php similarity index 100% rename from modules/Admin/Language/zh-hans/Settings.php rename to modules/Admin/Language/zh-Hans/Settings.php diff --git a/modules/Admin/Language/zh-hans/Soundbite.php b/modules/Admin/Language/zh-Hans/Soundbite.php similarity index 100% rename from modules/Admin/Language/zh-hans/Soundbite.php rename to modules/Admin/Language/zh-Hans/Soundbite.php diff --git a/modules/Auth/Language/zh-hans/User.php b/modules/Admin/Language/zh-Hans/User.php similarity index 74% rename from modules/Auth/Language/zh-hans/User.php rename to modules/Admin/Language/zh-Hans/User.php index 5440c60a..cb3e0ed6 100644 --- a/modules/Auth/Language/zh-hans/User.php +++ b/modules/Admin/Language/zh-Hans/User.php @@ -9,7 +9,8 @@ declare(strict_types=1); */ return [ - 'edit_role' => "编辑 {username} 的角色", + 'edit_roles' => "编辑 {username} 的角色", + 'forcePassReset' => '强制重置', 'ban' => '封禁', 'unban' => '取消封禁', 'delete' => '删除', @@ -18,7 +19,7 @@ return [ 'all_users' => '所有用户', 'list' => [ 'user' => '用户', - 'role' => '角色', + 'roles' => '角色', 'banned' => '已封禁?', ], 'form' => [ @@ -26,33 +27,28 @@ return [ 'username' => '用户名', 'password' => '密码', 'new_password' => '新密码', - 'role' => '角色', 'roles' => '角色', 'permissions' => '权限', 'submit_create' => '创建用户', 'submit_edit' => '保存', 'submit_password_change' => '修改!', ], - 'delete_form' => [ - 'title' => '删除 {user} ?', - 'disclaimer' => - "你将永久删除 {user},他们将无法再访问管理区域。", - 'understand' => '我明白,我想永久删除 {user}', - 'submit' => '删除', + 'roles' => [ + 'superadmin' => '超级管理员', ], 'messages' => [ 'createSuccess' => '用户创建成功!{username} 将在首次验证时提醒重置密码。', - 'roleEditSuccess' => + 'rolesEditSuccess' => "{username} 的角色已更新。", + 'forcePassResetSuccess' => + '下次访问时 {username} 将被提醒重置密码。', 'banSuccess' => '{username} 已被封禁。', 'unbanSuccess' => '{username} 已解除封禁。', 'editOwnerError' => '{username} 是实例的所有者,你不能编辑他的角色。', 'banSuperAdminError' => '{username} 是超级管理员,不能禁止超级管理员…', - 'deleteOwnerError' => - '{username} 是实例的所有者,不能简单地删除所有者…', 'deleteSuperAdminError' => '{username} 是超级管理员,不能封禁超级管理员…', 'deleteSuccess' => '{username} 已被删除。', diff --git a/modules/Admin/Language/zh-hans/Validation.php b/modules/Admin/Language/zh-Hans/Validation.php similarity index 76% rename from modules/Admin/Language/zh-hans/Validation.php rename to modules/Admin/Language/zh-Hans/Validation.php index 4a447d44..cfdeac6e 100644 --- a/modules/Admin/Language/zh-hans/Validation.php +++ b/modules/Admin/Language/zh-Hans/Validation.php @@ -13,5 +13,6 @@ return [ '{field} 不是一张图片,或者宽或高度不够。', 'is_image_ratio' => '{field} 不是图片或比例不正确。', - 'is_json' => '{field} contains invalid JSON.', + 'validate_url' => + '{field} 字段必须是有效的 URL(例如 https://example.com/)。', ]; diff --git a/modules/Admin/Language/zh-hans/VideoClip.php b/modules/Admin/Language/zh-Hans/VideoClip.php similarity index 100% rename from modules/Admin/Language/zh-hans/VideoClip.php rename to modules/Admin/Language/zh-Hans/VideoClip.php diff --git a/modules/Admin/Language/zh-hans/AboutCastopod.php b/modules/Admin/Language/zh-hans/AboutCastopod.php deleted file mode 100644 index 9817b219..00000000 --- a/modules/Admin/Language/zh-hans/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - '关于 Castopod', - 'host_name' => '主机名', - 'version' => 'Castopod 版本', - 'php_version' => 'PHP 版本', - 'os' => '操作系统', - 'languages' => '语言', - 'update_database' => '更新数据库', - 'messages' => [ - 'databaseUpdateSuccess' => '数据库是最新的!', - ], -]; diff --git a/modules/Admin/Language/zh-hant/AboutCastopod.php b/modules/Admin/Language/zh-hant/AboutCastopod.php deleted file mode 100644 index 3fb62aff..00000000 --- a/modules/Admin/Language/zh-hant/AboutCastopod.php +++ /dev/null @@ -1,22 +0,0 @@ - 'About Castopod', - 'host_name' => 'Host name', - 'version' => 'Castopod version', - 'php_version' => 'PHP version', - 'os' => 'Operating System', - 'languages' => 'Languages', - 'update_database' => 'Update database', - 'messages' => [ - 'databaseUpdateSuccess' => 'Database is up to date!', - ], -]; diff --git a/modules/Admin/Language/zh-hant/Breadcrumb.php b/modules/Admin/Language/zh-hant/Breadcrumb.php deleted file mode 100644 index 408c9f9f..00000000 --- a/modules/Admin/Language/zh-hant/Breadcrumb.php +++ /dev/null @@ -1,57 +0,0 @@ - 'breadcrumb', - config('Admin') - ->gateway => 'Home', - 'podcasts' => 'podcasts', - 'episodes' => 'episodes', - 'subscriptions' => 'subscriptions', - 'contributors' => 'contributors', - 'pages' => 'pages', - 'settings' => 'settings', - 'theme' => 'theme', - 'about' => 'about', - 'add' => 'add', - 'new' => 'new', - 'edit' => 'edit', - 'persons' => 'persons', - 'publish' => 'publish', - 'publish-edit' => 'edit publication', - 'publish-date-edit' => 'edit publication date', - 'unpublish' => 'unpublish', - 'delete' => 'delete', - 'remove' => 'remove', - 'fediverse' => 'fediverse', - 'blocked-actors' => 'blocked actors', - 'blocked-domains' => 'blocked domains', - 'users' => 'users', - 'my-account' => 'my account', - 'change-password' => 'change password', - 'imports' => 'imports', - 'sync-feeds' => 'synchronize feeds', - 'platforms' => 'platforms', - 'social' => 'social networks', - 'funding' => 'funding', - 'monetization-other' => 'other monetization', - 'analytics' => 'analytics', - 'locations' => 'locations', - 'webpages' => 'web pages', - 'unique-listeners' => 'unique listeners', - 'players' => 'players', - 'listening-time' => 'listening time', - 'time-periods' => 'time periods', - 'soundbites' => 'soundbites', - 'video-clips' => 'video clips', - 'embed' => 'embeddable player', - 'notifications' => 'notifications', - 'suspend' => 'suspend', -]; diff --git a/modules/Admin/Language/zh-hant/Charts.php b/modules/Admin/Language/zh-hant/Charts.php deleted file mode 100644 index 6ede2510..00000000 --- a/modules/Admin/Language/zh-hant/Charts.php +++ /dev/null @@ -1,41 +0,0 @@ - 'Episode downloads by service (for the past week)', - 'by_player_weekly' => 'Episode downloads by player (for the past week)', - 'by_player_yearly' => 'Episode downloads by player (for the past year)', - 'by_device_weekly' => 'Episode downloads by device (for the past week)', - 'by_os_weekly' => 'Episode downloads by O.S. (for the past week)', - 'podcast_by_region' => 'Episode downloads by region (for the past week)', - 'unique_daily_listeners' => 'Daily unique listeners', - 'unique_monthly_listeners' => 'Monthly unique listeners', - 'by_browser' => 'Web pages usage by browser (for the past week)', - 'podcast_by_day' => 'Episode daily downloads', - 'podcast_by_month' => 'Episode monthly downloads', - 'episode_by_day' => 'Episode daily downloads (first 60 days)', - 'episode_by_month' => 'Episode monthly downloads', - 'episodes_by_day' => - '5 latest episodes downloads (during their first 60 days)', - 'by_country_weekly' => 'Episode downloads by country (for the past week)', - 'by_country_yearly' => 'Episode downloads by country (for the past year)', - 'by_domain_weekly' => 'Web pages visits by source (for the past week)', - 'by_domain_yearly' => 'Web pages visits by source (for the past year)', - 'by_entry_page' => 'Web pages visits by landing page (for the past week)', - 'podcast_bots' => 'Bots (crawlers)', - 'daily_listening_time' => 'Daily cumulative listening time', - 'monthly_listening_time' => 'Monthly cumulative listening time', - 'by_weekday' => 'By week day (for the past 60 days)', - 'by_hour' => 'By time of day (for the past 60 days)', - 'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)', - 'total_storage_by_month' => 'Monthly storage (in MB)', - 'total_bandwidth_by_month' => 'Monthly used bandwidth (in MB)', - 'total_bandwidth_by_month_limit' => 'Limited to {totalBandwidth} per month', -]; diff --git a/modules/Admin/Language/zh-hant/Common.php b/modules/Admin/Language/zh-hant/Common.php deleted file mode 100644 index 74addcf2..00000000 --- a/modules/Admin/Language/zh-hant/Common.php +++ /dev/null @@ -1,52 +0,0 @@ - 'Yes', - 'no' => 'No', - 'cancel' => 'Cancel', - 'optional' => 'Optional', - 'more' => 'More', - 'no_data' => 'No data found!', - 'close' => 'Close', - 'edit' => 'Edit', - 'copy' => 'Copy', - 'copied' => 'Copied!', - 'home' => 'Home', - 'explicit' => 'Explicit', - 'powered_by' => 'Powered by {castopod}', - 'actions' => 'Actions', - 'pageInfo' => 'Page {currentPage} out of {pageCount}', - 'go_back' => 'Go back', - 'forms' => [ - 'editor' => [ - 'write' => 'Write', - 'preview' => 'Preview', - 'help' => 'Powered by markdown', - ], - 'multiSelect' => [ - 'selectText' => 'Press to select', - 'loadingText' => 'Loading…', - 'noResultsText' => 'No results found', - 'noChoicesText' => 'No choices to choose from', - 'maxItemText' => 'Cannot add more items', - ], - 'upload_file' => 'Upload a file', - 'remote_url' => 'Remote URL', - 'save' => 'Save', - ], - 'play_episode_button' => [ - 'play' => 'Play', - 'playing' => 'Playing', - ], - 'size_limit' => 'Size limit: {0}.', - 'choose_interact' => 'Choose how to interact', - 'view' => 'View', -]; diff --git a/modules/Admin/Language/zh-hant/Countries.php b/modules/Admin/Language/zh-hant/Countries.php deleted file mode 100644 index 4cd5d9c8..00000000 --- a/modules/Admin/Language/zh-hant/Countries.php +++ /dev/null @@ -1,264 +0,0 @@ - 'Andorra', - 'AE' => 'United Arab Emirates', - 'AF' => 'Afghanistan', - 'AG' => 'Antigua and Barbuda', - 'AI' => 'Anguilla', - 'AL' => 'Albania', - 'AM' => 'Armenia', - 'AO' => 'Angola', - 'AQ' => 'Antarctica', - 'AR' => 'Argentina', - 'AS' => 'American Samoa', - 'AT' => 'Austria', - 'AU' => 'Australia', - 'AW' => 'Aruba', - 'AX' => 'Åland Islands', - 'AZ' => 'Azerbaijan', - 'BA' => 'Bosnia and Herzegovina', - 'BB' => 'Barbados', - 'BD' => 'Bangladesh', - 'BE' => 'Belgium', - 'BF' => 'Burkina Faso', - 'BG' => 'Bulgaria', - 'BH' => 'Bahrain', - 'BI' => 'Burundi', - 'BJ' => 'Benin', - 'BL' => 'Saint Barthélemy', - 'BM' => 'Bermuda', - 'BN' => 'Brunei Darussalam', - 'BO' => 'Bolivia, Plurinational State of', - 'BQ' => 'Bonaire, Sint Eustatius and Saba', - 'BR' => 'Brazil', - 'BS' => 'Bahamas', - 'BT' => 'Bhutan', - 'BV' => 'Bouvet Island', - 'BW' => 'Botswana', - 'BY' => 'Belarus', - 'BZ' => 'Belize', - 'CA' => 'Canada', - 'CC' => 'Cocos (Keeling) Islands', - 'CD' => 'Congo, the Democratic Republic of the', - 'CF' => 'Central African Republic', - 'CG' => 'Congo', - 'CH' => 'Switzerland', - 'CI' => "Côte d'Ivoire", - 'CK' => 'Cook Islands', - 'CL' => 'Chile', - 'CM' => 'Cameroon', - 'CN' => 'China', - 'CO' => 'Colombia', - 'CR' => 'Costa Rica', - 'CU' => 'Cuba', - 'CV' => 'Cape Verde', - 'CW' => 'Curaçao', - 'CX' => 'Christmas Island', - 'CY' => 'Cyprus', - 'CZ' => 'Czech Republic', - 'DE' => 'Germany', - 'DJ' => 'Djibouti', - 'DK' => 'Denmark', - 'DM' => 'Dominica', - 'DO' => 'Dominican Republic', - 'DZ' => 'Algeria', - 'EC' => 'Ecuador', - 'EE' => 'Estonia', - 'EG' => 'Egypt', - 'EH' => 'Western Sahara', - 'ER' => 'Eritrea', - 'ES' => 'Spain', - 'ET' => 'Ethiopia', - 'FI' => 'Finland', - 'FJ' => 'Fiji', - 'FK' => 'Falkland Islands (Malvinas)', - 'FM' => 'Micronesia, Federated States of', - 'FO' => 'Faroe Islands', - 'FR' => 'France', - 'GA' => 'Gabon', - 'GB' => 'United Kingdom', - 'GD' => 'Grenada', - 'GE' => 'Georgia', - 'GF' => 'French Guiana', - 'GG' => 'Guernsey', - 'GH' => 'Ghana', - 'GI' => 'Gibraltar', - 'GL' => 'Greenland', - 'GM' => 'Gambia', - 'GN' => 'Guinea', - 'GP' => 'Guadeloupe', - 'GQ' => 'Equatorial Guinea', - 'GR' => 'Greece', - 'GS' => 'South Georgia and the South Sandwich Islands', - 'GT' => 'Guatemala', - 'GU' => 'Guam', - 'GW' => 'Guinea-Bissau', - 'GY' => 'Guyana', - 'HK' => 'Hong Kong', - 'HM' => 'Heard Island and McDonald Islands', - 'HN' => 'Honduras', - 'HR' => 'Croatia', - 'HT' => 'Haiti', - 'HU' => 'Hungary', - 'ID' => 'Indonesia', - 'IE' => 'Ireland', - 'IL' => 'Israel', - 'IM' => 'Isle of Man', - 'IN' => 'India', - 'IO' => 'British Indian Ocean Territory', - 'IQ' => 'Iraq', - 'IR' => 'Iran, Islamic Republic of', - 'IS' => 'Iceland', - 'IT' => 'Italy', - 'JE' => 'Jersey', - 'JM' => 'Jamaica', - 'JO' => 'Jordan', - 'JP' => 'Japan', - 'KE' => 'Kenya', - 'KG' => 'Kyrgyzstan', - 'KH' => 'Cambodia', - 'KI' => 'Kiribati', - 'KM' => 'Comoros', - 'KN' => 'Saint Kitts and Nevis', - 'KP' => "Korea, Democratic People's Republic of", - 'KR' => 'Korea, Republic of', - 'KW' => 'Kuwait', - 'KY' => 'Cayman Islands', - 'KZ' => 'Kazakhstan', - 'LA' => "Lao People's Democratic Republic", - 'LB' => 'Lebanon', - 'LC' => 'Saint Lucia', - 'LI' => 'Liechtenstein', - 'LK' => 'Sri Lanka', - 'LR' => 'Liberia', - 'LS' => 'Lesotho', - 'LT' => 'Lithuania', - 'LU' => 'Luxembourg', - 'LV' => 'Latvia', - 'LY' => 'Libya', - 'MA' => 'Morocco', - 'MC' => 'Monaco', - 'MD' => 'Moldova, Republic of', - 'ME' => 'Montenegro', - 'MF' => 'Saint Martin (French part)', - 'MG' => 'Madagascar', - 'MH' => 'Marshall Islands', - 'MK' => 'Macedonia, the Former Yugoslav Republic of', - 'ML' => 'Mali', - 'MM' => 'Myanmar', - 'MN' => 'Mongolia', - 'MO' => 'Macao', - 'MP' => 'Northern Mariana Islands', - 'MQ' => 'Martinique', - 'MR' => 'Mauritania', - 'MS' => 'Montserrat', - 'MT' => 'Malta', - 'MU' => 'Mauritius', - 'MV' => 'Maldives', - 'MW' => 'Malawi', - 'MX' => 'Mexico', - 'MY' => 'Malaysia', - 'MZ' => 'Mozambique', - 'N/A' => 'Not Applicable (local IP…)', - 'NA' => 'Namibia', - 'NC' => 'New Caledonia', - 'NE' => 'Niger', - 'NF' => 'Norfolk Island', - 'NG' => 'Nigeria', - 'NI' => 'Nicaragua', - 'NL' => 'Netherlands', - 'NO' => 'Norway', - 'NP' => 'Nepal', - 'NR' => 'Nauru', - 'NU' => 'Niue', - 'NZ' => 'New Zealand', - 'OM' => 'Oman', - 'PA' => 'Panama', - 'PE' => 'Peru', - 'PF' => 'French Polynesia', - 'PG' => 'Papua New Guinea', - 'PH' => 'Philippines', - 'PK' => 'Pakistan', - 'PL' => 'Poland', - 'PM' => 'Saint Pierre and Miquelon', - 'PN' => 'Pitcairn', - 'PR' => 'Puerto Rico', - 'PS' => 'Palestine, State of', - 'PT' => 'Portugal', - 'PW' => 'Palau', - 'PY' => 'Paraguay', - 'QA' => 'Qatar', - 'RE' => 'Réunion', - 'RO' => 'Romania', - 'RS' => 'Serbia', - 'RU' => 'Russian Federation', - 'RW' => 'Rwanda', - 'SA' => 'Saudi Arabia', - 'SB' => 'Solomon Islands', - 'SC' => 'Seychelles', - 'SD' => 'Sudan', - 'SE' => 'Sweden', - 'SG' => 'Singapore', - 'SH' => 'Saint Helena, Ascension and Tristan da Cunha', - 'SI' => 'Slovenia', - 'SJ' => 'Svalbard and Jan Mayen', - 'SK' => 'Slovakia', - 'SL' => 'Sierra Leone', - 'SM' => 'San Marino', - 'SN' => 'Senegal', - 'SO' => 'Somalia', - 'SR' => 'Suriname', - 'SS' => 'South Sudan', - 'ST' => 'Sao Tome and Principe', - 'SV' => 'El Salvador', - 'SX' => 'Sint Maarten (Dutch part)', - 'SY' => 'Syrian Arab Republic', - 'SZ' => 'Swaziland', - 'TC' => 'Turks and Caicos Islands', - 'TD' => 'Chad', - 'TF' => 'French Southern Territories', - 'TG' => 'Togo', - 'TH' => 'Thailand', - 'TJ' => 'Tajikistan', - 'TK' => 'Tokelau', - 'TL' => 'Timor-Leste', - 'TM' => 'Turkmenistan', - 'TN' => 'Tunisia', - 'TO' => 'Tonga', - 'TR' => 'Turkey', - 'TT' => 'Trinidad and Tobago', - 'TV' => 'Tuvalu', - 'TW' => 'Taiwan, Province of China', - 'TZ' => 'Tanzania, United Republic of', - 'UA' => 'Ukraine', - 'UG' => 'Uganda', - 'UM' => 'United States Minor Outlying Islands', - 'US' => 'United States', - 'UY' => 'Uruguay', - 'UZ' => 'Uzbekistan', - 'VA' => 'Holy See (Vatican City State)', - 'VC' => 'Saint Vincent and the Grenadines', - 'VE' => 'Venezuela, Bolivarian Republic of', - 'VG' => 'Virgin Islands, British', - 'VI' => 'Virgin Islands, U.S.', - 'VN' => 'Viet Nam', - 'VU' => 'Vanuatu', - 'WF' => 'Wallis and Futuna', - 'WS' => 'Samoa', - 'YE' => 'Yemen', - 'YT' => 'Mayotte', - 'ZA' => 'South Africa', - 'ZM' => 'Zambia', - 'ZW' => 'Zimbabwe', -]; diff --git a/modules/Admin/Language/zh-hant/Dashboard.php b/modules/Admin/Language/zh-hant/Dashboard.php deleted file mode 100644 index 881073fd..00000000 --- a/modules/Admin/Language/zh-hant/Dashboard.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Admin dashboard', - 'welcome_message' => 'Welcome to the admin area!', - 'podcasts' => [ - 'title' => 'Podcasts', - 'not_found' => 'No published podcast', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'episodes' => [ - 'title' => 'Episodes', - 'not_found' => 'No published episode', - 'last_published' => 'Last published on {lastPublicationDate}', - ], - 'storage' => [ - 'title' => 'Storage', - 'subtitle' => '{totalUploaded} out of {totalStorage}', - ], -]; diff --git a/modules/Admin/Language/zh-hant/Episode.php b/modules/Admin/Language/zh-hant/Episode.php deleted file mode 100644 index 4fa846e3..00000000 --- a/modules/Admin/Language/zh-hant/Episode.php +++ /dev/null @@ -1,225 +0,0 @@ - 'Season {seasonNumber}', - 'season_abbr' => 'S{seasonNumber}', - 'number' => 'Episode {episodeNumber}', - 'number_abbr' => 'Ep. {episodeNumber}', - 'season_episode' => 'Season {seasonNumber} episode {episodeNumber}', - 'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}', - 'number_of_comments' => '{numberOfComments, plural, - one {# comment} - other {# comments} - }', - 'all_podcast_episodes' => 'All podcast episodes', - 'back_to_podcast' => 'Go back to podcast', - 'edit' => 'Edit', - 'preview' => 'Preview', - 'publish' => 'Publish', - 'publish_edit' => 'Edit publication', - 'publish_date_edit' => 'Edit publication date', - 'unpublish' => 'Unpublish', - 'publish_error' => 'Episode is already published.', - 'publish_edit_error' => 'Episode is already published.', - 'publish_cancel_error' => 'Episode is already published.', - 'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.', - 'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.', - 'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!', - 'unpublish_error' => 'Episode is not published.', - 'delete' => 'Delete', - 'go_to_page' => 'Go to page', - 'create' => 'Add an episode', - 'publication_status' => [ - 'published' => 'Published', - 'with_podcast' => 'Published', - 'scheduled' => 'Scheduled', - 'not_published' => 'Not published', - ], - 'with_podcast_hint' => 'To be published at the same time as the podcast', - 'list' => [ - 'search' => [ - 'placeholder' => 'Search for an episode', - 'clear' => 'Clear search', - 'submit' => 'Search', - ], - 'number_of_episodes' => '{numberOfEpisodes, plural, - one {# episode} - other {# episodes} - }', - 'episode' => 'Episode', - 'visibility' => 'Visibility', - 'downloads' => 'Downloads', - 'comments' => 'Comments', - 'actions' => 'Actions', - ], - 'messages' => [ - 'createSuccess' => 'Episode has been successfully created!', - 'editSuccess' => 'Episode has been successfully updated!', - 'publishSuccess' => '{publication_status, select, - published {Episode successfully published!} - scheduled {Episode publication successfully scheduled!} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not published.} - }', - 'publishCancelSuccess' => 'Episode publication successfully cancelled!', - 'unpublishBeforeDeleteTip' => 'You must unpublish the episode before deleting it.', - 'scheduleDateError' => 'Schedule date must be set!', - 'deletePublishedEpisodeError' => 'Please unpublish the episode before deleting it.', - 'deleteSuccess' => 'Episode successfully deleted!', - 'deleteError' => 'Failed to delete episode {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deleteFileError' => 'Failed to delete {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - } file {file_key}. You may manually remove it from your disk.', - 'sameSlugError' => 'An episode with the chosen slug already exists.', - ], - 'form' => [ - 'file_size_error' => - 'Your file size is too big! Max size is {0}. Increase the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server to upload your file.', - 'audio_file' => 'Audio file', - 'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.', - 'info_section_title' => 'Episode info', - 'cover' => 'Episode cover', - 'cover_hint' => - 'If you do not set a cover, the podcast cover will be used instead.', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'title' => 'Title', - 'title_hint' => - 'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.', - 'permalink' => 'Permalink', - 'season_number' => 'Season', - 'episode_number' => 'Episode', - 'type' => [ - 'label' => 'Type', - 'full' => 'Full', - 'full_hint' => 'Complete content (the episode)', - 'trailer' => 'Trailer', - 'trailer_hint' => 'Short, promotional piece of content that represents a preview of the current show', - 'bonus' => 'Bonus', - 'bonus_hint' => 'Extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show', - ], - 'premium_title' => 'Premium', - 'premium' => 'Episode must be accessible to premium subscribers only', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does the episode contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'show_notes_section_title' => 'Show notes', - 'show_notes_section_subtitle' => - 'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.', - 'description' => 'Description', - 'description_footer' => 'Description footer', - 'description_footer_hint' => - 'This text is added at the end of each episode description, it is a good place to input your social links for example.', - 'additional_files_section_title' => 'Additional files', - 'additional_files_section_subtitle' => - 'These files may be used by other platforms to provide better experience to your audience. See the {podcastNamespaceLink} for more information.', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this episode about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real or fictional location', - 'transcript' => 'Transcript (subtitles / closed captions)', - 'transcript_hint' => 'Only .srt or .vtt are allowed.', - 'transcript_download' => 'Download transcript', - 'transcript_file' => 'Transcript file (.srt or .vtt)', - 'transcript_remote_url' => 'Remote url for transcript', - 'transcript_file_delete' => 'Delete transcript file', - 'chapters' => 'Chapters', - 'chapters_hint' => 'File must be in JSON Chapters format.', - 'chapters_download' => 'Download chapters', - 'chapters_file' => 'Chapters file', - 'chapters_remote_url' => 'Remote url for chapters file', - 'chapters_file_delete' => 'Delete chapters file', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the episode', - 'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.', - 'block' => 'Episode should be hidden from public catalogues', - 'block_hint' => - 'The episode show or hide status: toggling this on prevents the episode from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'submit_create' => 'Create episode', - 'submit_edit' => 'Save episode', - ], - 'publish_form' => [ - 'back_to_episode_dashboard' => 'Back to episode dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - 'with_podcast' => 'Publish alongside podcast', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_clear' => 'Clear publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit' => 'Publish', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.', - 'message_warning_submit' => 'Publish anyways', - ], - 'publish_date_edit_form' => [ - 'new_publication_date' => 'New publication date', - 'new_publication_date_hint' => 'Must be set to a past date.', - 'submit' => 'Edit publication date', - ], - 'unpublish_form' => [ - 'disclaimer' => - "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.", - 'understand' => 'I understand, I want to unpublish the episode', - 'submit' => 'Unpublish', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the episode will delete all media files, comments, video clips and soundbites associated with it.", - 'understand' => 'I understand, I want to delete the episode', - 'submit' => 'Delete', - ], - 'embed' => [ - 'title' => 'Embeddable player', - 'label' => - 'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.', - 'clipboard_iframe' => 'Copy embeddable player to clipboard', - 'clipboard_url' => 'Copy address to clipboard', - 'dark' => 'Dark', - 'dark-transparent' => 'Dark transparent', - 'light' => 'Light', - 'light-transparent' => 'Light transparent', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'text' => '{publication_status, select, - published {This episode is not yet published.} - scheduled {This episode is scheduled for publication on {publication_date}.} - with_podcast {This episode will be published at the same time as the podcast.} - other {This episode is not yet published.} - }', - 'preview' => 'Preview', - ], -]; diff --git a/modules/Admin/Language/zh-hant/EpisodeNavigation.php b/modules/Admin/Language/zh-hant/EpisodeNavigation.php deleted file mode 100644 index 1406e301..00000000 --- a/modules/Admin/Language/zh-hant/EpisodeNavigation.php +++ /dev/null @@ -1,23 +0,0 @@ - 'View episode page', - 'dashboard' => 'Episode dashboard', - 'episode-view' => 'Home', - 'episode-edit' => 'Edit episode', - 'episode-persons-manage' => 'Manage persons', - 'embed-add' => 'Embeddable player', - 'clips' => 'Clips', - 'video-clips-list' => 'Video clips', - 'video-clips-create' => 'New video clip', - 'soundbites-list' => 'Soundbites', - 'soundbites-create' => 'New soundbite', -]; diff --git a/modules/Admin/Language/zh-hant/Fediverse.php b/modules/Admin/Language/zh-hant/Fediverse.php deleted file mode 100644 index 0e4ca66d..00000000 --- a/modules/Admin/Language/zh-hant/Fediverse.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'actorNotFound' => 'The account could not be found!', - 'blockActorSuccess' => '{actor} has been blocked!', - 'unblockActorSuccess' => 'Actor has been unblocked!', - 'blockDomainSuccess' => '{domain} has been blocked!', - 'unblockDomainSuccess' => '{domain} has been unblocked!', - ], - 'blocked_actors' => 'Blocked accounts', - 'blocked_domains' => 'Blocked domains', - 'block_lists_form' => [ - 'handle' => 'Account handle', - 'handle_hint' => 'Input @username@domain account.', - 'domain' => 'Domain name', - 'submit' => 'Block!', - ], - 'list' => [ - 'actor' => 'Account', - 'domain' => 'Domain name', - 'unblock' => 'Unblock', - ], -]; diff --git a/modules/Admin/Language/zh-hant/Home.php b/modules/Admin/Language/zh-hant/Home.php deleted file mode 100644 index 3ff4c04d..00000000 --- a/modules/Admin/Language/zh-hant/Home.php +++ /dev/null @@ -1,14 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found', -]; diff --git a/modules/Admin/Language/zh-hant/Install.php b/modules/Admin/Language/zh-hant/Install.php deleted file mode 100644 index 36e373a2..00000000 --- a/modules/Admin/Language/zh-hant/Install.php +++ /dev/null @@ -1,61 +0,0 @@ - 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Admin/Language/zh-hant/Navigation.php b/modules/Admin/Language/zh-hant/Navigation.php deleted file mode 100644 index f3ffb129..00000000 --- a/modules/Admin/Language/zh-hant/Navigation.php +++ /dev/null @@ -1,44 +0,0 @@ - 'Toggle sidebar', - 'go_to_website' => 'Go to website', - 'go_to_admin' => 'Go to admin', - 'not-authorized' => 'Not authorized', - 'dashboard' => 'Dashboard', - 'admin' => 'Home', - 'podcasts' => 'Podcasts', - 'podcast-list' => 'All podcasts', - 'podcast-create' => 'New podcast', - 'all-podcast-imports' => 'All Podcast imports', - 'podcast-imports-add' => 'Import a podcast', - 'persons' => 'Persons', - 'person-list' => 'All persons', - 'person-create' => 'New person', - 'fediverse' => 'Fediverse', - 'fediverse-blocked-actors' => 'Blocked accounts', - 'fediverse-blocked-domains' => 'Blocked domains', - 'users' => 'Users', - 'user-list' => 'All users', - 'user-create' => 'New user', - 'pages' => 'Pages', - 'page-list' => 'All pages', - 'page-create' => 'New Page', - 'settings' => 'Settings', - 'settings-general' => 'General', - 'settings-theme' => 'Theme', - 'admin-about' => 'About', - 'account' => [ - 'my-account' => 'My account', - 'change-password' => 'Change password', - 'logout' => 'Logout', - ], -]; diff --git a/modules/Admin/Language/zh-hant/Notifications.php b/modules/Admin/Language/zh-hant/Notifications.php deleted file mode 100644 index 2b139d51..00000000 --- a/modules/Admin/Language/zh-hant/Notifications.php +++ /dev/null @@ -1,19 +0,0 @@ - 'Notifications', - 'reply' => '{actor_username} replied to your post', - 'favourite' => '{actor_username} favourited your post', - 'reblog' => '{actor_username} shared your post', - 'follow' => '{actor_username} started following you', - 'no_notifications' => 'No notifications', - 'mark_all_as_read' => 'Mark all as read', -]; diff --git a/modules/Admin/Language/zh-hant/Page.php b/modules/Admin/Language/zh-hant/Page.php deleted file mode 100644 index b6f49de5..00000000 --- a/modules/Admin/Language/zh-hant/Page.php +++ /dev/null @@ -1,30 +0,0 @@ - 'Back to home', - 'page' => 'Page', - 'all_pages' => 'All pages', - 'create' => 'New page', - 'go_to_page' => 'Go to page', - 'edit' => 'Edit page', - 'delete' => 'Delete page', - 'form' => [ - 'title' => 'Title', - 'permalink' => 'Permalink', - 'content' => 'Content', - 'submit_create' => 'Create page', - 'submit_edit' => 'Save', - ], - 'messages' => [ - 'createSuccess' => 'The page “{pageTitle}” was created successfully!', - 'editSuccess' => 'The page was successfully updated!', - ], -]; diff --git a/modules/Admin/Language/zh-hant/Pager.php b/modules/Admin/Language/zh-hant/Pager.php deleted file mode 100644 index e25ee638..00000000 --- a/modules/Admin/Language/zh-hant/Pager.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Page navigation', - 'first' => 'First', - 'previous' => 'Previous', - 'next' => 'Next', - 'last' => 'Last', - 'older' => 'Older', - 'newer' => 'Newer', - 'invalidTemplate' => '{0} is not a valid Pager template.', - 'invalidPaginationGroup' => '{0} is not a valid Pagination group.', -]; diff --git a/modules/Admin/Language/zh-hant/Person.php b/modules/Admin/Language/zh-hant/Person.php deleted file mode 100644 index a652be9f..00000000 --- a/modules/Admin/Language/zh-hant/Person.php +++ /dev/null @@ -1,65 +0,0 @@ - 'Persons', - 'all_persons' => 'All persons', - 'no_person' => 'Nobody found!', - 'create' => 'Create a person', - 'view' => 'View person', - 'edit' => 'Edit person', - 'delete' => 'Delete person', - 'messages' => [ - 'createSuccess' => 'Person has been successfully created!', - 'editSuccess' => 'Person has been successfully updated!', - 'deleteSuccess' => 'Person has been removed!', - ], - 'form' => [ - 'avatar' => 'Avatar', - 'avatar_size_hint' => - 'Avatar must be squared and at least 400px wide and tall.', - 'full_name' => 'Full name', - 'full_name_hint' => 'This is the full name or alias of the person.', - 'unique_name' => 'Unique name', - 'unique_name_hint' => 'Used for URLs', - 'information_url' => 'Information URL', - 'information_url_hint' => - 'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.', - 'submit_create' => 'Create person', - 'submit_edit' => 'Save person', - ], - 'podcast_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this podcast', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'episode_form' => [ - 'title' => 'Manage persons', - 'add_section_title' => 'Add persons to this episode', - 'add_section_subtitle' => 'You may pick several persons and roles.', - 'persons' => 'Persons', - 'persons_hint' => - 'You may select one or several persons with the same roles. You need to create the persons first.', - 'roles' => 'Roles', - 'roles_hint' => - 'You may select none, one or several roles for a person.', - 'submit_add' => 'Add person(s)', - 'remove' => 'Remove', - ], - 'credits' => 'Credits', -]; diff --git a/modules/Admin/Language/zh-hant/Platforms.php b/modules/Admin/Language/zh-hant/Platforms.php deleted file mode 100644 index e161181c..00000000 --- a/modules/Admin/Language/zh-hant/Platforms.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'podcasting' => 'Podcasting platforms', - 'social' => 'Social networks', - 'funding' => 'Funding links', - ], - 'website' => 'Website', - 'home_url' => 'Go to {platformName} website', - 'register' => 'Register', - 'submit_url' => 'Submit your podcast on {platformName}', - 'your_link' => 'Your link', - 'your_id' => [ - 'podcasting' => 'Your ID', - 'social' => 'Your ID', - 'funding' => 'Your CTA', - ], - 'your_cta' => 'Your call to action', - 'visible' => 'Display in podcast homepage?', - 'on_embed' => 'Display on embeddable player?', - 'remove' => 'Remove {platformName}', - 'submit' => 'Save', - 'messages' => [ - 'updateSuccess' => 'Platform links have been successfully updated!', - 'removeLinkSuccess' => 'The platform link has been removed.', - 'removeLinkError' => - 'The platform link could not be removed. Try again.', - ], - 'description' => [ - 'podcasting' => 'The podcast ID on this platform', - 'social' => 'The podcast account ID on this platform', - 'funding' => 'Call to action message', - ], -]; diff --git a/modules/Admin/Language/zh-hant/Podcast.php b/modules/Admin/Language/zh-hant/Podcast.php deleted file mode 100644 index ff0daebc..00000000 --- a/modules/Admin/Language/zh-hant/Podcast.php +++ /dev/null @@ -1,330 +0,0 @@ - 'All podcasts', - 'no_podcast' => 'No podcast found!', - 'create' => 'Create podcast', - 'import' => 'Import podcast', - 'all_imports' => 'Podcast imports', - 'new_episode' => 'New Episode', - 'view' => 'View podcast', - 'edit' => 'Edit podcast', - 'publish' => 'Publish podcast', - 'publish_edit' => 'Edit publication', - 'delete' => 'Delete podcast', - 'see_episodes' => 'See episodes', - 'see_contributors' => 'See contributors', - 'monetization_other' => 'Other monetization', - 'go_to_page' => 'Go to page', - 'latest_episodes' => 'Latest episodes', - 'see_all_episodes' => 'See all episodes', - 'draft' => 'Draft', - 'messages' => [ - 'createSuccess' => 'Podcast successfully created!', - 'editSuccess' => 'Podcast has been successfully updated!', - 'importSuccess' => 'Podcast has been successfully imported!', - 'deleteSuccess' => 'Podcast @{podcast_handle} successfully deleted!', - 'deletePodcastMediaError' => 'Failed to delete podcast {type, select, - cover {cover} - banner {banner} - other {media} - }.', - 'deleteEpisodeMediaError' => 'Failed to delete podcast episode {episode_slug} {type, select, - transcript {transcript} - chapters {chapters} - image {cover} - audio {audio} - other {media} - }.', - 'deletePodcastMediaFolderError' => 'Failed to delete podcast media folder {folder_path}. You may manually remove it from your disk.', - 'podcastFeedUpdateSuccess' => 'Successful update: {number_of_new_episodes, plural, - one {# episode was} - other {# episodes were} - } added to the podcast!', - 'podcastFeedUpToDate' => 'Podcast is already up to date.', - 'publishError' => 'This podcast is either already published or scheduled for publication.', - 'publishEditError' => 'This podcast is not scheduled for publication.', - 'publishCancelSuccess' => 'Podcast publication successfully cancelled!', - 'scheduleDateError' => 'Schedule date must be set!', - ], - 'form' => [ - 'identity_section_title' => 'Podcast identity', - 'identity_section_subtitle' => 'These fields allow you to get noticed.', - 'fediverse_section_title' => 'Fediverse identity', - - 'cover' => 'Podcast cover', - 'cover_size_hint' => 'Cover must be squared and at least 1400px wide and tall.', - 'banner' => 'Podcast banner', - 'banner_size_hint' => 'Banner must have a 3:1 ratio and be at least 1500px wide.', - 'banner_delete' => 'Delete podcast banner', - 'title' => 'Title', - 'handle' => 'Handle', - 'handle_hint' => - 'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.', - 'type' => [ - 'label' => 'Type', - 'episodic' => 'Episodic', - 'episodic_hint' => 'If episodes are intended to be consumed without any specific order. Newest episodes will be presented first.', - 'serial' => 'Serial', - 'serial_hint' => 'If episodes are intended to be consumed in sequential order. Episodes will be presented in numeric order.', - ], - 'medium' => [ - 'label' => 'Medium', - 'hint' => 'Medium as represented by podcast:medium tag in RSS. Changing this may change how players present your feed.', - 'podcast' => 'Podcast', - 'podcast_hint' => 'Describes a feed for a podcast show.', - 'music' => 'Music', - 'music_hint' => 'A feed of music organized into an "album" with each item a song within the album.', - 'audiobook' => 'Audiobook', - 'audiobook_hint' => 'Specific types of audio with one item per feed, or where items represent chapters within the book.', - ], - 'description' => 'Description', - 'classification_section_title' => 'Classification', - 'classification_section_subtitle' => - 'These fields will impact your audience and competition.', - 'language' => 'Language', - 'category' => 'Category', - 'category_placeholder' => 'Select a category…', - 'other_categories' => 'Other categories', - 'parental_advisory' => [ - 'label' => 'Parental advisory', - 'hint' => 'Does it contain explicit content?', - 'undefined' => 'undefined', - 'clean' => 'Clean', - 'explicit' => 'Explicit', - ], - 'author_section_title' => 'Author', - 'author_section_subtitle' => 'Who is managing the podcast?', - 'owner_name' => 'Owner name', - 'owner_name_hint' => - 'For administrative use only. Visible in the public RSS feed.', - 'owner_email' => 'Owner email', - 'owner_email_hint' => - 'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.', - 'is_owner_email_removed_from_feed' => 'Remove the owner email from the public RSS feed', - 'is_owner_email_removed_from_feed_hint' => 'You may need to temporarily unhide the email so that a directory can verify your podcast ownership.', - 'publisher' => 'Publisher', - 'publisher_hint' => - 'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as ’Author’.', - 'copyright' => 'Copyright', - 'location_section_title' => 'Location', - 'location_section_subtitle' => 'What place is this podcast about?', - 'location_name' => 'Location name or address', - 'location_name_hint' => 'This can be a real place or fictional', - 'monetization_section_title' => 'Monetization', - 'monetization_section_subtitle' => - 'Earn money thanks to your audience.', - 'premium' => 'Premium', - 'premium_by_default' => 'Episodes must be set as premium by default', - 'premium_by_default_hint' => 'Podcast episodes will be marked as premium by default. You can still choose to set some episodes, trailers or bonuses as public.', - 'op3' => 'Open Podcast Prefix Project (OP3)', - 'op3_link' => 'Visit your OP3 dashboard (external link)', - 'op3_hint' => 'Value your analytics data with OP3, an open-source and trusted third party analytics service. Share, validate and compare your analytics data with the open podcasting ecosystem.', - 'op3_enable' => 'Enable OP3 analytics service', - 'op3_enable_hint' => 'For security reasons, premium episodes\' analytics data will not be shared with OP3.', - 'payment_pointer' => 'Payment Pointer for Web Monetization', - 'payment_pointer_hint' => - 'This is your where you will receive money thanks to Web Monetization', - 'advanced_section_title' => 'Advanced Parameters', - 'advanced_section_subtitle' => - 'If you need RSS tags that Castopod does not handle, set them here.', - 'custom_rss' => 'Custom RSS tags for the podcast', - 'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.', - 'verify_txt' => 'Ownership verification TXT', - 'verify_txt_hint' => 'Rather than relying on email, certain third-party services may confirm your podcast ownership by requesting you to embed a verification text within your feed.', - 'verify_txt_helper' => 'This text is injected into a tag.', - 'new_feed_url' => 'New feed URL', - 'new_feed_url_hint' => 'Use this field when you move to another domain or podcast hosting platform. By default, the value is set to the current RSS URL if the podcast is imported.', - 'old_feed_url' => 'Old feed URL', - 'partnership' => 'Partnership', - 'partner_id' => 'ID', - 'partner_link_url' => 'Link URL', - 'partner_image_url' => 'Image URL', - 'partner_id_hint' => 'Your own partner ID', - 'partner_link_url_hint' => 'The generic partner link address', - 'partner_image_url_hint' => 'The generic partner image address', - 'block' => 'Podcast should be hidden from public catalogues', - 'block_hint' => - 'The podcast show or hide status: toggling this on prevents the entire podcast from appearing in Apple Podcasts, Google Podcasts, and any third party apps that pull shows from these directories. (Not guaranteed)', - 'complete' => 'Podcast will not be having new episodes', - 'lock' => 'Prevent podcast from being copied', - 'lock_hint' => - 'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.', - 'submit_create' => 'Create podcast', - 'submit_edit' => 'Save podcast', - ], - 'category_options' => [ - 'uncategorized' => 'uncategorized', - 'arts' => 'Arts', - 'business' => 'Business', - 'comedy' => 'Comedy', - 'education' => 'Education', - 'fiction' => 'Fiction', - 'government' => 'Government', - 'health_and_fitness' => 'Health & Fitness', - 'history' => 'History', - 'kids_and_family' => 'Kids & Family', - 'leisure' => 'Leisure', - 'music' => 'Music', - 'news' => 'News', - 'religion_and_spirituality' => 'Religion & Spirituality', - 'science' => 'Science', - 'society_and_culture' => 'Society & Culture', - 'sports' => 'Sports', - 'technology' => 'Technology', - 'true_crime' => 'True Crime', - 'tv_and_film' => 'TV & Film', - 'books' => 'Books', - 'design' => 'Design', - 'fashion_and_beauty' => 'Fashion & Beauty', - 'food' => 'Food', - 'performing_arts' => 'Performing Arts', - 'visual_arts' => 'Visual Arts', - 'careers' => 'Careers', - 'entrepreneurship' => 'Entrepreneurship', - 'investing' => 'Investing', - 'management' => 'Management', - 'marketing' => 'Marketing', - 'non_profit' => 'Non-Profit', - 'comedy_interviews' => 'Comedy Interviews', - 'improv' => 'Improv', - 'stand_up' => 'Stand-Up', - 'courses' => 'Courses', - 'how_to' => 'How To', - 'language_learning' => 'Language Learning', - 'self_improvement' => 'Self-Improvement', - 'comedy_fiction' => 'Comedy Fiction', - 'drama' => 'Drama', - 'science_fiction' => 'Science Fiction', - 'alternative_health' => 'Alternative Health', - 'fitness' => 'Fitness', - 'medicine' => 'Medicine', - 'mental_health' => 'Mental Health', - 'nutrition' => 'Nutrition', - 'sexuality' => 'Sexuality', - 'education_for_kids' => 'Education for Kids', - 'parenting' => 'Parenting', - 'pets_and_animals' => 'Pets & Animals', - 'stories_for_kids' => 'Stories for Kids', - 'animation_and_manga' => 'Animation & Manga', - 'automotive' => 'Automotive', - 'aviation' => 'Aviation', - 'crafts' => 'Crafts', - 'games' => 'Games', - 'hobbies' => 'Hobbies', - 'home_and_garden' => 'Home & Garden', - 'video_games' => 'Video Games', - 'music_commentary' => 'Music Commentary', - 'music_history' => 'Music History', - 'music_interviews' => 'Music Interviews', - 'business_news' => 'Business News', - 'daily_news' => 'Daily News', - 'entertainment_news' => 'Entertainment News', - 'news_commentary' => 'News Commentary', - 'politics' => 'Politics', - 'sports_news' => 'Sports News', - 'tech_news' => 'Tech News', - 'buddhism' => 'Buddhism', - 'christianity' => 'Christianity', - 'hinduism' => 'Hinduism', - 'islam' => 'Islam', - 'judaism' => 'Judaism', - 'religion' => 'Religion', - 'spirituality' => 'Spirituality', - 'astronomy' => 'Astronomy', - 'chemistry' => 'Chemistry', - 'earth_sciences' => 'Earth Sciences', - 'life_sciences' => 'Life Sciences', - 'mathematics' => 'Mathematics', - 'natural_sciences' => 'Natural Sciences', - 'nature' => 'Nature', - 'physics' => 'Physics', - 'social_sciences' => 'Social Sciences', - 'documentary' => 'Documentary', - 'personal_journals' => 'Personal Journals', - 'philosophy' => 'Philosophy', - 'places_and_travel' => 'Places & Travel', - 'relationships' => 'Relationships', - 'baseball' => 'Baseball', - 'basketball' => 'Basketball', - 'cricket' => 'Cricket', - 'fantasy_sports' => 'Fantasy Sports', - 'football' => 'Football', - 'golf' => 'Golf', - 'hockey' => 'Hockey', - 'rugby' => 'Rugby', - 'running' => 'Running', - 'soccer' => 'Soccer', - 'swimming' => 'Swimming', - 'tennis' => 'Tennis', - 'volleyball' => 'Volleyball', - 'wilderness' => 'Wilderness', - 'wrestling' => 'Wrestling', - 'after_shows' => 'After Shows', - 'film_history' => 'Film History', - 'film_interviews' => 'Film Interviews', - 'film_reviews' => 'Film Reviews', - 'tv_reviews' => 'TV Reviews', - ], - 'publish_form' => [ - 'back_to_podcast_dashboard' => 'Back to podcast dashboard', - 'post' => 'Your announcement post', - 'post_hint' => - "Write a message to announce the publication of your podcast. The message will be featured in your podcast's homepage.", - 'message_placeholder' => 'Write your message…', - 'submit' => 'Publish', - 'publication_date' => 'Publication date', - 'publication_method' => [ - 'now' => 'Now', - 'schedule' => 'Schedule', - ], - 'scheduled_publication_date' => 'Scheduled publication date', - 'scheduled_publication_date_hint' => - 'You can schedule the podcast release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm', - 'submit_edit' => 'Edit publication', - 'cancel_publication' => 'Cancel publication', - 'message_warning' => 'You did not write a message for your announcement post!', - 'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your podcast.', - 'message_warning_submit' => 'Publish anyway', - ], - 'publication_status_banner' => [ - 'draft_mode' => 'draft mode', - 'not_published' => 'This podcast is not yet published.', - 'scheduled' => 'This podcast is scheduled for publication on {publication_date}.', - ], - 'delete_form' => [ - 'disclaimer' => - "Deleting the podcast will delete all episodes, media files, posts and analytics associated with it. This action is irreversible, you will not be able to retrieve them afterwards.", - 'understand' => 'I understand, I want the podcast to be permanently deleted', - 'submit' => 'Delete', - ], - 'by' => 'By {publisher}', - 'season' => 'Season {seasonNumber}', - 'list_of_episodes_year' => '{year} episodes ({episodeCount})', - 'list_of_episodes_season' => - 'Season {seasonNumber} episodes ({episodeCount})', - 'no_episode' => 'No episode found!', - 'follow' => 'Follow', - 'followers' => '{numberOfFollowers, plural, - one {# follower} - other {# followers} - }', - 'posts' => '{numberOfPosts, plural, - one {# post} - other {# posts} - }', - 'activity' => 'Activity', - 'episodes' => 'Episodes', - 'sponsor' => 'Sponsor', - 'funding_links' => 'Funding links for {podcastTitle}', - 'find_on' => 'Find {podcastTitle} on', - 'listen_on' => 'Listen on', -]; diff --git a/modules/Admin/Language/zh-hant/PodcastNavigation.php b/modules/Admin/Language/zh-hant/PodcastNavigation.php deleted file mode 100644 index bb777707..00000000 --- a/modules/Admin/Language/zh-hant/PodcastNavigation.php +++ /dev/null @@ -1,42 +0,0 @@ - 'Go to podcast page', - 'rss_feed' => 'RSS feed', - 'dashboard' => 'Podcast dashboard', - 'podcast-view' => 'Home', - 'podcast-edit' => 'Edit podcast', - 'podcast-persons-manage' => 'Manage persons', - 'podcast-imports' => 'Podcast imports', - 'podcast-imports-sync' => 'Sync feeds', - 'episodes' => 'Episodes', - 'episode-list' => 'All episodes', - 'episode-create' => 'New episode', - 'analytics' => 'Analytics', - 'podcast-analytics' => 'Audience overview', - 'podcast-analytics-webpages' => 'Web pages visits', - 'podcast-analytics-locations' => 'Locations', - 'podcast-analytics-unique-listeners' => 'Unique listeners', - 'podcast-analytics-players' => 'Players', - 'podcast-analytics-listening-time' => 'Listening time', - 'podcast-analytics-time-periods' => 'Time periods', - 'monetization' => 'Monetization', - 'subscription-list' => 'All subscriptions', - 'subscription-create' => 'Add subscription', - 'contributors' => 'Contributors', - 'contributor-list' => 'All contributors', - 'contributor-add' => 'Add contributor', - 'broadcast' => 'Broadcast', - 'platforms-podcasting' => 'Podcasting apps', - 'platforms-social' => 'Social networks', - 'platforms-funding' => 'Funding links', - 'podcast-monetization-other' => 'Other', -]; diff --git a/modules/Admin/Language/zh-hant/Settings.php b/modules/Admin/Language/zh-hant/Settings.php deleted file mode 100644 index 4a70dcba..00000000 --- a/modules/Admin/Language/zh-hant/Settings.php +++ /dev/null @@ -1,58 +0,0 @@ - 'General settings', - 'instance' => [ - 'title' => 'Instance', - 'site_icon' => 'Site icon', - 'site_icon_delete' => 'Delete site icon', - 'site_icon_hint' => 'Site icons are what you see on your browser tabs, bookmarks bar, and when you add a website as a shortcut on mobile devices.', - 'site_icon_helper' => 'Icon must be squared and at least 512px wide and tall.', - 'site_name' => 'Site name', - 'site_description' => 'Site description', - 'submit' => 'Save', - 'editSuccess' => 'Instance has been updated successfully!', - 'deleteIconSuccess' => 'Site icon has been remove successfully!', - ], - 'images' => [ - 'title' => 'Images', - 'subtitle' => 'Here you can regenerate all images based on the originals that were uploaded. To be used if you find that some images are missing. This task may take a while.', - 'regenerate' => 'Regenerate images', - 'regenerationSuccess' => 'All images have been regenerated successfully!', - ], - 'housekeeping' => [ - 'title' => 'Housekeeping', - 'subtitle' => 'Runs various housekeeping tasks. Use this feature if you ever encounter issues with media files or data integrity. These tasks may take a while.', - 'reset_counts' => 'Reset counts', - 'reset_counts_helper' => 'This option will recalculate and reset all data counts (number of followers, posts, comments, …).', - 'rewrite_media' => 'Rewrite media metadata', - 'rewrite_media_helper' => 'This option will delete all superfluous media files and recreate them (images, audio files, transcripts, chapters, …)', - 'rename_episodes_files' => 'Rename episode audio files', - 'rename_episodes_files_hint' => 'This option will rename all episodes audio files to a random string of characters. Use this if one of your private episodes link was leaked as this will effectively hide it.', - 'clear_cache' => 'Clear all cache', - 'clear_cache_helper' => 'This option will flush redis cache or writable/cache files.', - 'run' => 'Run housekeeping', - 'runSuccess' => 'Housekeeping has been run successfully!', - ], - 'theme' => [ - 'title' => 'Theme', - 'accent_section_title' => 'Accent color', - 'accent_section_subtitle' => 'Choose the color to determine the look and feel of all public pages.', - 'pine' => 'Pine', - 'crimson' => 'Crimson', - 'amber' => 'Amber', - 'lake' => 'Lake', - 'jacaranda' => 'Jacaranda', - 'onyx' => 'Onyx', - 'submit' => 'Save', - 'setInstanceThemeSuccess' => 'Theme has been updated successfully!', - ], -]; diff --git a/modules/Admin/Language/zh-hant/Soundbite.php b/modules/Admin/Language/zh-hant/Soundbite.php deleted file mode 100644 index a3f828fe..00000000 --- a/modules/Admin/Language/zh-hant/Soundbite.php +++ /dev/null @@ -1,31 +0,0 @@ - [ - 'title' => 'Soundbites', - 'soundbite' => 'Soundbite', - ], - 'messages' => [ - 'createSuccess' => 'Soundbite has been successfully created!', - 'deleteSuccess' => 'Soundbite has been successfully removed!', - ], - 'form' => [ - 'title' => 'New soundbite', - 'soundbite_title' => 'Soundbite title', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'submit' => 'Create soundbite', - ], - 'play' => 'Play soundbite', - 'stop' => 'Stop soundbite', - 'create' => 'New soundbite', - 'delete' => 'Delete soundbite', -]; diff --git a/modules/Admin/Language/zh-hant/Validation.php b/modules/Admin/Language/zh-hant/Validation.php deleted file mode 100644 index f76c3163..00000000 --- a/modules/Admin/Language/zh-hant/Validation.php +++ /dev/null @@ -1,17 +0,0 @@ - - '{field} is either not an image, or it is not wide or tall enough.', - 'is_image_ratio' => - '{field} is either not an image or not of the right ratio.', - 'is_json' => '{field} contains invalid JSON.', -]; diff --git a/modules/Admin/Language/zh-hant/VideoClip.php b/modules/Admin/Language/zh-hant/VideoClip.php deleted file mode 100644 index 638de697..00000000 --- a/modules/Admin/Language/zh-hant/VideoClip.php +++ /dev/null @@ -1,72 +0,0 @@ - [ - 'title' => 'Video clips', - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Clip is waiting to be processed.', - 'pending' => 'pending', - 'pending_hint' => 'Clip will be generated shortly.', - 'running' => 'running', - 'running_hint' => 'Clip is being generated.', - 'failed' => 'failed', - 'failed_hint' => 'Clip could not be generated: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Clip was generated successfully!', - ], - 'clip' => 'Clip', - 'duration' => 'Job duration', - ], - 'title' => 'Video clip: {videoClipLabel}', - 'download_clip' => 'Download clip', - 'create' => 'New video clip', - 'go_to_page' => 'Go to clip page', - 'retry' => 'Retry clip generation', - 'delete' => 'Delete clip', - 'logs' => 'Job logs', - 'messages' => [ - 'alreadyExistingError' => 'The video clip you are trying to create already exists!', - 'addToQueueSuccess' => 'Video clip has been added to queue, awaiting to be created!', - 'deleteSuccess' => 'Video clip has been successfully removed!', - ], - 'format' => [ - 'landscape' => 'Landscape', - 'portrait' => 'Portrait', - 'squared' => 'Squared', - ], - 'form' => [ - 'title' => 'New video clip', - 'params_section_title' => 'Video clip parameters', - 'clip_title' => 'Clip title', - 'format' => [ - 'label' => 'Choose a format', - 'landscape_hint' => 'With a 16:9 ratio, landscape videos are great for PeerTube, Youtube and Vimeo.', - 'portrait_hint' => 'With a 9:16 ratio, portrait videos are great for TikTok, Youtube shorts and Instagram stories.', - 'squared_hint' => 'With a 1:1 ratio, squared videos are great for Mastodon, Facebook, Twitter and LinkedIn.', - ], - 'theme' => 'Select a theme', - 'start_time' => 'Start at', - 'duration' => 'Duration', - 'trim_start' => 'Trim start', - 'trim_end' => 'Trim end', - 'submit' => 'Create video clip', - ], - 'requirements' => [ - 'title' => 'Missing requirements', - 'missing' => 'You have missing requirements. Make sure to add all the required items to be allowed creating a video for this episode!', - 'ffmpeg' => 'FFmpeg', - 'gd' => 'Graphics Draw (GD)', - 'freetype' => 'Freetype library for GD', - 'transcript' => 'Transcript file (.srt)', - ], -]; diff --git a/modules/Analytics/AnalyticsTrait.php b/modules/Analytics/AnalyticsTrait.php index a345c597..7d1680b4 100644 --- a/modules/Analytics/AnalyticsTrait.php +++ b/modules/Analytics/AnalyticsTrait.php @@ -10,15 +10,12 @@ declare(strict_types=1); namespace Modules\Analytics; +use Config\Services; + trait AnalyticsTrait { protected function registerPodcastWebpageHit(int $podcastId): void { - // Prevent analytics hit when authenticated - if (auth()->loggedIn()) { - return; - } - helper('analytics'); set_user_session_deny_list_ip(); @@ -26,15 +23,18 @@ trait AnalyticsTrait set_user_session_referer(); set_user_session_entry_page(); - $session = service('session'); + $session = Services::session(); + $session->start(); if (! $session->get('denyListIp')) { $db = db_connect(); $referer = $session->get('referer'); $domain = - parse_url((string) $referer, PHP_URL_HOST) ?? '- Direct -'; - parse_str((string) parse_url((string) $referer, PHP_URL_QUERY), $queries); + parse_url($referer, PHP_URL_HOST) === null + ? '- Direct -' + : parse_url($referer, PHP_URL_HOST); + parse_str((string) parse_url($referer, PHP_URL_QUERY), $queries); $keywords = $queries['q'] ?? null; $procedureName = $db->prefixTable('analytics_website'); diff --git a/modules/Analytics/Config/Analytics.php b/modules/Analytics/Config/Analytics.php index fb86c03b..ab263a08 100644 --- a/modules/Analytics/Config/Analytics.php +++ b/modules/Analytics/Config/Analytics.php @@ -20,9 +20,9 @@ class Analytics extends BaseConfig * @var array */ public array $routeFilters = [ - 'analytics-full-data' => 'permission:podcast$1.view', - 'analytics-data' => 'permission:podcast$1.view', - 'analytics-filtered-data' => 'permission:podcast$1.view', + 'analytics-full-data' => 'permission:podcasts-view,podcast-view', + 'analytics-data' => 'permission:podcasts-view,podcast-view', + 'analytics-filtered-data' => 'permission:podcasts-view,podcast-view', ]; /** @@ -37,4 +37,16 @@ class Analytics extends BaseConfig * Z&|qECKBrwgaaD>~;U/tXG1U%tSe_oi5Tzy)h>}5NC2npSrjvM0w_Q>cs=0o=H]* */ public string $salt = ''; + + /** + * get the full audio file url + * + * @param string|string[] $audioPath + */ + public function getAudioUrl(string | array $audioPath): string + { + helper('media'); + + return media_base_url($audioPath); + } } diff --git a/modules/Analytics/Config/Routes.php b/modules/Analytics/Config/Routes.php index 9097151c..5285fbfd 100644 --- a/modules/Analytics/Config/Routes.php +++ b/modules/Analytics/Config/Routes.php @@ -8,7 +8,7 @@ declare(strict_types=1); * @link https://castopod.org/ */ -/** @var \CodeIgniter\Router\RouteCollection $routes */ +$routes = service('routes'); /** * Analytics routes file @@ -27,14 +27,14 @@ $routes->group('', [ ], static function ($routes): void { $routes->group(config('Analytics')->gateway . '/(:num)/(:class)', static function ($routes): void { $routes->get('/', 'AnalyticsController::getData/$1/$2', [ - 'as' => 'analytics-full-data', + 'as' => 'analytics-full-data', 'filter' => config('Analytics') ->routeFilters[ 'analytics-full-data' ], ]); $routes->get('(:filter)', 'AnalyticsController::getData/$1/$2/$3', [ - 'as' => 'analytics-data', + 'as' => 'analytics-data', 'filter' => config('Analytics') ->routeFilters['analytics-data'], ]); @@ -42,7 +42,7 @@ $routes->group('', [ '(:filter)/(:num)', 'AnalyticsController::getData/$1/$2/$3/$4', [ - 'as' => 'analytics-filtered-data', + 'as' => 'analytics-filtered-data', 'filter' => config('Analytics') ->routeFilters[ 'analytics-filtered-data' @@ -53,14 +53,23 @@ $routes->group('', [ $routes->get(config('Analytics')->gateway . '/(:class)/(:filter)', 'AnalyticsController::getData/$1/$2', [ 'as' => 'analytics-data-instance', ]); - - /** - * @deprecated Route for podcast audio file analytics (/audio/pack(podcast_id,episode_id,bytes_threshold,filesize,duration,date)/podcast_folder/filename.mp3) - */ - $routes->head('audio/(:base64)/(:any)', 'EpisodeAnalyticsController::hit/$1/$2'); - $routes->get('audio/(:base64)/(:any)', 'EpisodeAnalyticsController::hit/$1/$2'); + // Route for podcast audio file analytics (/audio/pack(podcast_id,episode_id,bytes_threshold,filesize,duration,date)/podcast_folder/filename.mp3) + $routes->head( + 'audio/(:base64)/(:any)', + 'EpisodeAnalyticsController::hit/$1/$2', + [ + 'as' => 'episode-analytics-hit', + ], + ); + $routes->get( + 'audio/(:base64)/(:any)', + 'EpisodeAnalyticsController::hit/$1/$2', + [ + 'as' => 'episode-analytics-hit', + ], + ); }); // Show the Unknown UserAgents $routes->get('.well-known/unknown-useragents', 'UnknownUserAgentsController'); -$routes->get('.well-known/unknown-useragents/(:num)', 'UnknownUserAgentsController::index/$1'); +$routes->get('.well-known/unknown-useragents/(:num)', 'UnknownUserAgentsController/$1'); diff --git a/modules/Analytics/Controllers/AnalyticsController.php b/modules/Analytics/Controllers/AnalyticsController.php index adf7e3e0..fb0a0315 100644 --- a/modules/Analytics/Controllers/AnalyticsController.php +++ b/modules/Analytics/Controllers/AnalyticsController.php @@ -31,13 +31,11 @@ class AnalyticsController extends Controller } if (! is_numeric($params[0])) { - // @phpstan-ignore-next-line $this->analyticsModel = model('Analytics' . $params[0] . 'Model'); $this->methodName = 'getData' . $params[1]; return $this->{$method}(); } - // @phpstan-ignore-next-line $this->analyticsModel = model('Analytics' . $params[1] . 'Model'); $this->methodName = 'getData' . (count($params) >= 3 ? $params[2] : ''); diff --git a/modules/Analytics/Controllers/EpisodeAnalyticsController.php b/modules/Analytics/Controllers/EpisodeAnalyticsController.php index dfaff0a9..e1244d51 100644 --- a/modules/Analytics/Controllers/EpisodeAnalyticsController.php +++ b/modules/Analytics/Controllers/EpisodeAnalyticsController.php @@ -15,32 +15,107 @@ use App\Models\EpisodeModel; use CodeIgniter\Controller; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; -use Deprecated; +use CodeIgniter\HTTP\RequestInterface; +use CodeIgniter\HTTP\ResponseInterface; +use Config\Services; +use Modules\Analytics\Config\Analytics; +use Modules\PremiumPodcasts\Models\SubscriptionModel; +use Psr\Log\LoggerInterface; class EpisodeAnalyticsController extends Controller { - #[Deprecated(message: 'Replaced by EpisodeAudioController::index method')] - public function hit(string $base64EpisodeData, string ...$audioPath): RedirectResponse + /** + * An array of helpers to be loaded automatically upon class instantiation. These helpers will be available to all + * other controllers that extend Analytics. + * + * @var string[] + */ + protected $helpers = ['analytics']; + + protected Analytics $config; + + /** + * Constructor. + */ + public function initController( + RequestInterface $request, + ResponseInterface $response, + LoggerInterface $logger + ): void { + // Do Not Edit This Line + parent::initController($request, $response, $logger); + + set_user_session_deny_list_ip(); + set_user_session_location(); + set_user_session_player(); + + $this->config = config('Analytics'); + } + + public function hit(string $base64EpisodeData, string ...$audioPath): RedirectResponse|ResponseInterface { + $session = Services::session(); + $session->start(); + + $serviceName = ''; + if ($this->request->getGet('_from')) { + $serviceName = $this->request->getGet('_from'); + } elseif ($session->get('embed_domain') !== null) { + $serviceName = $session->get('embed_domain'); + } elseif ($session->get('referer') !== null && $session->get('referer') !== '- Direct -') { + $serviceName = parse_url($session->get('referer'), PHP_URL_HOST); + } + $episodeData = unpack( 'IpodcastId/IepisodeId/IbytesThreshold/IfileSize/Iduration/IpublicationDate', base64_url_decode($base64EpisodeData), ); - if ($episodeData === false) { + if (! $episodeData) { throw PageNotFoundException::forPageNotFound(); } - $episode = new EpisodeModel() - ->getEpisodeById($episodeData['episodeId']); + // check if episode is premium? + $episode = (new EpisodeModel())->getEpisodeById($episodeData['episodeId']); if (! $episode instanceof Episode) { - throw PageNotFoundException::forPageNotFound(); + return $this->response->setStatusCode(404); } - return redirect()->route( - 'episode-audio', - [$episode->podcast->handle, $episode->slug, $episode->audio->file_extension], + $subscription = null; + + // check if podcast is already unlocked before any token validation + if ($episode->is_premium && ($subscription = service('premium_podcasts')->subscription( + $episode->podcast->handle + )) === null) { + // look for token as GET parameter + if (($token = $this->request->getGet('token')) === null) { + return $this->response->setStatusCode( + 401, + 'Episode is premium, you must provide a token to unlock it.' + ); + } + + // check if there's a valid subscription for the provided token + if (($subscription = (new SubscriptionModel())->validateSubscription( + $episode->podcast->handle, + $token + )) === null) { + return $this->response->setStatusCode(401, 'Invalid token!'); + } + } + + podcast_hit( + $episodeData['podcastId'], + $episodeData['episodeId'], + $episodeData['bytesThreshold'], + $episodeData['fileSize'], + $episodeData['duration'], + $episodeData['publicationDate'], + $serviceName, + $subscription !== null ? $subscription->id : null ); + + return redirect()->to($this->config->getAudioUrl($episode->audio->file_path)); } } diff --git a/modules/Analytics/Database/Migrations/2017-12-01-000000_add_analytics_podcasts.php b/modules/Analytics/Database/Migrations/2017-12-01-000000_add_analytics_podcasts.php index e95fb7a8..f921aa24 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-000000_add_analytics_podcasts.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-000000_add_analytics_podcasts.php @@ -12,17 +12,15 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsPodcasts extends BaseMigration +class AddAnalyticsPodcasts extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ @@ -32,22 +30,22 @@ class AddAnalyticsPodcasts extends BaseMigration // a hit in analytics podcast increments this value when a podcast is listened to in a given date. // Here, the "cumulative listening time" on a podcast per day // cannot surpass 999,999,999,999.999 seconds (~277,777,777 hours) - should be enough. - 'type' => 'DECIMAL(15,3)', + 'type' => 'DECIMAL(15,3)', 'unsigned' => true, ], 'bandwidth' => [ - 'type' => 'BIGINT', + 'type' => 'BIGINT', 'unsigned' => true, ], 'unique_listeners' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); $this->forge->addPrimaryKey(['podcast_id', 'date']); @@ -58,7 +56,6 @@ class AddAnalyticsPodcasts extends BaseMigration $this->forge->createTable('analytics_podcasts'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_podcasts'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-010000_add_analytics_podcasts_by_episode.php b/modules/Analytics/Database/Migrations/2017-12-01-010000_add_analytics_podcasts_by_episode.php index 421d76ca..de03aab9 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-010000_add_analytics_podcasts_by_episode.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-010000_add_analytics_podcasts_by_episode.php @@ -12,35 +12,33 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsPodcastsByEpisode extends BaseMigration +class AddAnalyticsPodcastsByEpisode extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'episode_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'age' => [ - 'type' => 'INT', - 'comment' => 'Days since episode publication date', + 'type' => 'INT', + 'comment' => 'Days since episode publication date', 'unsigned' => true, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); $this->forge->addPrimaryKey(['podcast_id', 'date', 'episode_id']); @@ -51,7 +49,6 @@ class AddAnalyticsPodcastsByEpisode extends BaseMigration $this->forge->createTable('analytics_podcasts_by_episode'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_podcasts_by_episode'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-020000_add_analytics_podcasts_by_hour.php b/modules/Analytics/Database/Migrations/2017-12-01-020000_add_analytics_podcasts_by_hour.php index 3050d0af..d3edf0ce 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-020000_add_analytics_podcasts_by_hour.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-020000_add_analytics_podcasts_by_hour.php @@ -12,30 +12,28 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsPodcastsByHour extends BaseMigration +class AddAnalyticsPodcastsByHour extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'hour' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); $this->forge->addPrimaryKey(['podcast_id', 'date', 'hour']); @@ -46,7 +44,6 @@ class AddAnalyticsPodcastsByHour extends BaseMigration $this->forge->createTable('analytics_podcasts_by_hour'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_podcasts_by_hour'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-030000_add_analytics_podcasts_by_player.php b/modules/Analytics/Database/Migrations/2017-12-01-030000_add_analytics_podcasts_by_player.php index e6b653c1..e12481eb 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-030000_add_analytics_podcasts_by_player.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-030000_add_analytics_podcasts_by_player.php @@ -12,47 +12,45 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsPodcastsByPlayer extends BaseMigration +class AddAnalyticsPodcastsByPlayer extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'service' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 128, ], 'app' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 128, ], 'device' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 32, ], 'os' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 32, ], 'is_bot' => [ - 'type' => 'TINYINT', + 'type' => 'TINYINT', 'constraint' => 1, - 'default' => 0, + 'default' => 0, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); $this->forge->addPrimaryKey(['podcast_id', 'date', 'service', 'app', 'device', 'os', 'is_bot']); @@ -63,7 +61,6 @@ class AddAnalyticsPodcastsByPlayer extends BaseMigration $this->forge->createTable('analytics_podcasts_by_player'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_podcasts_by_player'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-040000_add_analytics_podcasts_by_country.php b/modules/Analytics/Database/Migrations/2017-12-01-040000_add_analytics_podcasts_by_country.php index cd668c0b..2290dd03 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-040000_add_analytics_podcasts_by_country.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-040000_add_analytics_podcasts_by_country.php @@ -12,31 +12,29 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsPodcastsByCountry extends BaseMigration +class AddAnalyticsPodcastsByCountry extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'country_code' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 3, - 'comment' => 'ISO 3166-1 code.', + 'comment' => 'ISO 3166-1 code.', ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); $this->forge->addPrimaryKey(['podcast_id', 'date', 'country_code']); @@ -47,7 +45,6 @@ class AddAnalyticsPodcastsByCountry extends BaseMigration $this->forge->createTable('analytics_podcasts_by_country'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_podcasts_by_country'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-050000_add_analytics_podcasts_by_region.php b/modules/Analytics/Database/Migrations/2017-12-01-050000_add_analytics_podcasts_by_region.php index 3e5ec698..fd9a8bac 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-050000_add_analytics_podcasts_by_region.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-050000_add_analytics_podcasts_by_region.php @@ -12,31 +12,29 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsPodcastsByRegion extends BaseMigration +class AddAnalyticsPodcastsByRegion extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'country_code' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 3, - 'comment' => 'ISO 3166-1 code.', + 'comment' => 'ISO 3166-1 code.', ], 'region_code' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 3, - 'comment' => 'ISO 3166-2 code.', + 'comment' => 'ISO 3166-2 code.', ], 'latitude' => [ 'type' => 'DECIMAL(8,6)', @@ -47,9 +45,9 @@ class AddAnalyticsPodcastsByRegion extends BaseMigration 'null' => true, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); $this->forge->addPrimaryKey(['podcast_id', 'date', 'country_code', 'region_code']); @@ -60,7 +58,6 @@ class AddAnalyticsPodcastsByRegion extends BaseMigration $this->forge->createTable('analytics_podcasts_by_region'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_podcasts_by_region'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-060000_add_analytics_website_by_browser.php b/modules/Analytics/Database/Migrations/2017-12-01-060000_add_analytics_website_by_browser.php index 8e37d154..4f7ecbc7 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-060000_add_analytics_website_by_browser.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-060000_add_analytics_website_by_browser.php @@ -12,30 +12,28 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsWebsiteByBrowser extends BaseMigration +class AddAnalyticsWebsiteByBrowser extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'browser' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 128, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); @@ -47,7 +45,6 @@ class AddAnalyticsWebsiteByBrowser extends BaseMigration $this->forge->createTable('analytics_website_by_browser'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_website_by_browser'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-070000_add_analytics_website_by_referer.php b/modules/Analytics/Database/Migrations/2017-12-01-070000_add_analytics_website_by_referer.php index cfbbd362..6b6b4db6 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-070000_add_analytics_website_by_referer.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-070000_add_analytics_website_by_referer.php @@ -12,41 +12,39 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsWebsiteByReferer extends BaseMigration +class AddAnalyticsWebsiteByReferer extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'referer_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 512, ], 'domain' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 128, - 'null' => true, + 'null' => true, ], 'keywords' => [ 'type' => 'VARCHAR', // length of referer_url (512) - domain (128) = 384 'constraint' => 384, - 'null' => true, + 'null' => true, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); $this->forge->addPrimaryKey(['podcast_id', 'date', 'referer_url']); @@ -57,7 +55,6 @@ class AddAnalyticsWebsiteByReferer extends BaseMigration $this->forge->createTable('analytics_website_by_referer'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_website_by_referer'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-080000_add_analytics_website_by_entry_page.php b/modules/Analytics/Database/Migrations/2017-12-01-080000_add_analytics_website_by_entry_page.php index bdfebcbc..b1576689 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-080000_add_analytics_website_by_entry_page.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-080000_add_analytics_website_by_entry_page.php @@ -12,30 +12,28 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsWebsiteByEntryPage extends BaseMigration +class AddAnalyticsWebsiteByEntryPage extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'entry_page_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 512, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); $this->forge->addPrimaryKey(['podcast_id', 'date', 'entry_page_url']); @@ -46,7 +44,6 @@ class AddAnalyticsWebsiteByEntryPage extends BaseMigration $this->forge->createTable('analytics_website_by_entry_page'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_website_by_entry_page'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-090000_add_analytics_unknown_useragents.php b/modules/Analytics/Database/Migrations/2017-12-01-090000_add_analytics_unknown_useragents.php index 986848c5..ab1f1eb9 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-090000_add_analytics_unknown_useragents.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-090000_add_analytics_unknown_useragents.php @@ -12,29 +12,27 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsUnknownUseragents extends BaseMigration +class AddAnalyticsUnknownUseragents extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'id' => [ - 'type' => 'INT', - 'unsigned' => true, + 'type' => 'INT', + 'unsigned' => true, 'auto_increment' => true, ], 'useragent' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, - 'unique' => true, + 'unique' => true, ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); @@ -47,7 +45,6 @@ class AddAnalyticsUnknownUseragents extends BaseMigration $this->forge->createTable('analytics_unknown_useragents'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_unknown_useragents'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-100000_add_analytics_podcasts_by_subscription.php b/modules/Analytics/Database/Migrations/2017-12-01-100000_add_analytics_podcasts_by_subscription.php index 44ea8c5e..24fd9783 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-100000_add_analytics_podcasts_by_subscription.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-100000_add_analytics_podcasts_by_subscription.php @@ -10,34 +10,32 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsPodcastsBySubscription extends BaseMigration +class AddAnalyticsPodcastsBySubscription extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'episode_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'subscription_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'date' => [ 'type' => 'DATE', ], 'hits' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 1, + 'default' => 1, ], ]); @@ -50,7 +48,6 @@ class AddAnalyticsPodcastsBySubscription extends BaseMigration $this->forge->createTable('analytics_podcasts_by_subscription'); } - #[Override] public function down(): void { $this->forge->dropTable('analytics_podcasts_by_subscription'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_podcasts_procedure.php b/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_podcasts_procedure.php index 9472f0f2..c87a0193 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_podcasts_procedure.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_podcasts_procedure.php @@ -12,12 +12,10 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsPodcastsProcedure extends BaseMigration +class AddAnalyticsPodcastsProcedure extends Migration { - #[Override] public function up(): void { // Creates Procedure for data insertion @@ -87,7 +85,6 @@ class AddAnalyticsPodcastsProcedure extends BaseMigration $this->db->query($createQuery); } - #[Override] public function down(): void { $prefix = $this->db->getPrefix(); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_unknown_useragents_procedure.php b/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_unknown_useragents_procedure.php index af627bf2..13a3003d 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_unknown_useragents_procedure.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_unknown_useragents_procedure.php @@ -12,12 +12,10 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsUnknownUseragentsProcedure extends BaseMigration +class AddAnalyticsUnknownUseragentsProcedure extends Migration { - #[Override] public function up(): void { // Creates Procedure for data insertion @@ -35,7 +33,6 @@ class AddAnalyticsUnknownUseragentsProcedure extends BaseMigration $this->db->query($createQuery); } - #[Override] public function down(): void { $procedureName = $this->db->prefixTable('analytics_unknown_useragents'); diff --git a/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_website_procedure.php b/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_website_procedure.php index dc2b0bd2..c0668ad4 100644 --- a/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_website_procedure.php +++ b/modules/Analytics/Database/Migrations/2017-12-01-210000_add_analytics_website_procedure.php @@ -12,12 +12,10 @@ declare(strict_types=1); namespace Modules\Analytics\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddAnalyticsWebsiteProcedure extends BaseMigration +class AddAnalyticsWebsiteProcedure extends Migration { - #[Override] public function up(): void { // Creates Procedure for data insertion @@ -53,7 +51,6 @@ class AddAnalyticsWebsiteProcedure extends BaseMigration $this->db->query($createQuery); } - #[Override] public function down(): void { $procedureName = $this->db->prefixTable('analytics_website'); diff --git a/modules/Analytics/Entities/AnalyticsPodcasts.php b/modules/Analytics/Entities/AnalyticsPodcasts.php index 45d4b624..5b312210 100644 --- a/modules/Analytics/Entities/AnalyticsPodcasts.php +++ b/modules/Analytics/Entities/AnalyticsPodcasts.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -28,7 +27,7 @@ use CodeIgniter\I18n\Time; class AnalyticsPodcasts extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -36,10 +35,10 @@ class AnalyticsPodcasts extends Entity * @var array */ protected $casts = [ - 'podcast_id' => 'integer', - 'duration' => 'double', - 'bandwidth' => 'integer', + 'podcast_id' => 'integer', + 'duration' => 'double', + 'bandwidth' => 'integer', 'unique_listeners' => 'integer', - 'hits' => 'integer', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Entities/AnalyticsPodcastsByCountry.php b/modules/Analytics/Entities/AnalyticsPodcastsByCountry.php index 59ca02eb..30b9dfb5 100644 --- a/modules/Analytics/Entities/AnalyticsPodcastsByCountry.php +++ b/modules/Analytics/Entities/AnalyticsPodcastsByCountry.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -27,7 +26,7 @@ use CodeIgniter\I18n\Time; class AnalyticsPodcastsByCountry extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -35,11 +34,14 @@ class AnalyticsPodcastsByCountry extends Entity * @var array */ protected $casts = [ - 'podcast_id' => 'integer', + 'podcast_id' => 'integer', 'country_code' => 'string', - 'hits' => 'integer', + 'hits' => 'integer', ]; + /** + * @noRector ReturnTypeDeclarationRector + */ public function getLabels(): string { return lang('Countries.' . $this->attributes['labels']); diff --git a/modules/Analytics/Entities/AnalyticsPodcastsByEpisode.php b/modules/Analytics/Entities/AnalyticsPodcastsByEpisode.php index 1aa5959a..cb461454 100644 --- a/modules/Analytics/Entities/AnalyticsPodcastsByEpisode.php +++ b/modules/Analytics/Entities/AnalyticsPodcastsByEpisode.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -26,7 +25,7 @@ use CodeIgniter\I18n\Time; class AnalyticsPodcastsByEpisode extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -36,6 +35,6 @@ class AnalyticsPodcastsByEpisode extends Entity protected $casts = [ 'podcast_id' => 'integer', 'episode_id' => 'integer', - 'hits' => 'integer', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Entities/AnalyticsPodcastsByHour.php b/modules/Analytics/Entities/AnalyticsPodcastsByHour.php index bfc33b04..091fc720 100644 --- a/modules/Analytics/Entities/AnalyticsPodcastsByHour.php +++ b/modules/Analytics/Entities/AnalyticsPodcastsByHour.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -26,7 +25,7 @@ use CodeIgniter\I18n\Time; class AnalyticsPodcastsByHour extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -35,7 +34,7 @@ class AnalyticsPodcastsByHour extends Entity */ protected $casts = [ 'podcast_id' => 'integer', - 'hour' => 'integer', - 'hits' => 'integer', + 'hour' => 'integer', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Entities/AnalyticsPodcastsByPlayer.php b/modules/Analytics/Entities/AnalyticsPodcastsByPlayer.php index 8fb0acf7..7c7faf15 100644 --- a/modules/Analytics/Entities/AnalyticsPodcastsByPlayer.php +++ b/modules/Analytics/Entities/AnalyticsPodcastsByPlayer.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -29,7 +28,7 @@ use CodeIgniter\I18n\Time; class AnalyticsPodcastsByPlayer extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -38,10 +37,10 @@ class AnalyticsPodcastsByPlayer extends Entity */ protected $casts = [ 'podcast_id' => 'integer', - 'app' => '?string', - 'device' => '?string', - 'os' => '?string', - 'is_bot' => 'boolean', - 'hits' => 'integer', + 'app' => '?string', + 'device' => '?string', + 'os' => '?string', + 'is_bot' => 'boolean', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Entities/AnalyticsPodcastsByRegion.php b/modules/Analytics/Entities/AnalyticsPodcastsByRegion.php index 684667f3..5de71693 100644 --- a/modules/Analytics/Entities/AnalyticsPodcastsByRegion.php +++ b/modules/Analytics/Entities/AnalyticsPodcastsByRegion.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -29,7 +28,7 @@ use CodeIgniter\I18n\Time; class AnalyticsPodcastsByRegion extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -37,14 +36,17 @@ class AnalyticsPodcastsByRegion extends Entity * @var array */ protected $casts = [ - 'podcast_id' => 'integer', + 'podcast_id' => 'integer', 'country_code' => 'string', - 'region_code' => '?string', - 'latitude' => '?double', - 'longitude' => '?double', - 'hits' => 'integer', + 'region_code' => '?string', + 'latitude' => '?double', + 'longitude' => '?double', + 'hits' => 'integer', ]; + /** + * @noRector ReturnTypeDeclarationRector + */ public function getCountryCode(): string { return lang('Countries.' . $this->attributes['country_code']); diff --git a/modules/Analytics/Entities/AnalyticsPodcastsByService.php b/modules/Analytics/Entities/AnalyticsPodcastsByService.php index fb8a0366..51c19f8a 100644 --- a/modules/Analytics/Entities/AnalyticsPodcastsByService.php +++ b/modules/Analytics/Entities/AnalyticsPodcastsByService.php @@ -13,8 +13,7 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; -use Opawg\UserAgentsV2Php\UserAgentsRSS; +use Opawg\UserAgentsPhp\UserAgentsRSS; /** * @property int $podcast_id @@ -31,7 +30,7 @@ use Opawg\UserAgentsV2Php\UserAgentsRSS; class AnalyticsPodcastsByService extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -40,11 +39,11 @@ class AnalyticsPodcastsByService extends Entity */ protected $casts = [ 'podcast_id' => 'integer', - 'app' => '?string', - 'device' => '?string', - 'os' => '?string', - 'is_bot' => 'boolean', - 'hits' => 'integer', + 'app' => '?string', + 'device' => '?string', + 'os' => '?string', + 'is_bot' => 'boolean', + 'hits' => 'integer', ]; public function getLabels(): string diff --git a/modules/Analytics/Entities/AnalyticsPodcastsBySubscription.php b/modules/Analytics/Entities/AnalyticsPodcastsBySubscription.php index 09974b76..c48ba98b 100644 --- a/modules/Analytics/Entities/AnalyticsPodcastsBySubscription.php +++ b/modules/Analytics/Entities/AnalyticsPodcastsBySubscription.php @@ -11,7 +11,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -25,7 +24,7 @@ use CodeIgniter\I18n\Time; class AnalyticsPodcastsBySubscription extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -33,9 +32,9 @@ class AnalyticsPodcastsBySubscription extends Entity * @var array */ protected $casts = [ - 'podcast_id' => 'integer', - 'episode_id' => 'integer', + 'podcast_id' => 'integer', + 'episode_id' => 'integer', 'subscription_id' => 'integer', - 'hits' => 'integer', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Entities/AnalyticsUnknownUserAgent.php b/modules/Analytics/Entities/AnalyticsUnknownUserAgent.php index 016a3d0a..34e85cae 100644 --- a/modules/Analytics/Entities/AnalyticsUnknownUserAgent.php +++ b/modules/Analytics/Entities/AnalyticsUnknownUserAgent.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $id @@ -25,7 +24,7 @@ use CodeIgniter\I18n\Time; class AnalyticsUnknownUserAgent extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['created_at', 'updated_at']; @@ -33,8 +32,8 @@ class AnalyticsUnknownUserAgent extends Entity * @var array */ protected $casts = [ - 'id' => 'integer', + 'id' => 'integer', 'useragent' => 'integer', - 'hits' => 'integer', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Entities/AnalyticsWebsiteByBrowser.php b/modules/Analytics/Entities/AnalyticsWebsiteByBrowser.php index 9d764f7e..48ce16a1 100644 --- a/modules/Analytics/Entities/AnalyticsWebsiteByBrowser.php +++ b/modules/Analytics/Entities/AnalyticsWebsiteByBrowser.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -26,7 +25,7 @@ use CodeIgniter\I18n\Time; class AnalyticsWebsiteByBrowser extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -35,7 +34,7 @@ class AnalyticsWebsiteByBrowser extends Entity */ protected $casts = [ 'podcast_id' => 'integer', - 'browser' => 'string', - 'hits' => 'integer', + 'browser' => 'string', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Entities/AnalyticsWebsiteByEntryPage.php b/modules/Analytics/Entities/AnalyticsWebsiteByEntryPage.php index 7e8294c2..f270c6c2 100644 --- a/modules/Analytics/Entities/AnalyticsWebsiteByEntryPage.php +++ b/modules/Analytics/Entities/AnalyticsWebsiteByEntryPage.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -26,7 +25,7 @@ use CodeIgniter\I18n\Time; class AnalyticsWebsiteByEntryPage extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -34,8 +33,8 @@ class AnalyticsWebsiteByEntryPage extends Entity * @var array */ protected $casts = [ - 'podcast_id' => 'integer', + 'podcast_id' => 'integer', 'entry_page_url' => 'string', - 'hits' => 'integer', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Entities/AnalyticsWebsiteByReferer.php b/modules/Analytics/Entities/AnalyticsWebsiteByReferer.php index c0edf9c8..ef612549 100644 --- a/modules/Analytics/Entities/AnalyticsWebsiteByReferer.php +++ b/modules/Analytics/Entities/AnalyticsWebsiteByReferer.php @@ -13,7 +13,6 @@ declare(strict_types=1); namespace Modules\Analytics\Entities; use CodeIgniter\Entity\Entity; -use CodeIgniter\I18n\Time; /** * @property int $podcast_id @@ -26,7 +25,7 @@ use CodeIgniter\I18n\Time; class AnalyticsWebsiteByReferer extends Entity { /** - * @var list + * @var string[] */ protected $dates = ['date', 'created_at', 'updated_at']; @@ -34,8 +33,8 @@ class AnalyticsWebsiteByReferer extends Entity * @var array */ protected $casts = [ - 'podcast_id' => 'integer', + 'podcast_id' => 'integer', 'referer_url' => 'string', - 'hits' => 'integer', + 'hits' => 'integer', ]; } diff --git a/modules/Analytics/Helpers/analytics_helper.php b/modules/Analytics/Helpers/analytics_helper.php index adf97da4..351c8da7 100644 --- a/modules/Analytics/Helpers/analytics_helper.php +++ b/modules/Analytics/Helpers/analytics_helper.php @@ -9,8 +9,9 @@ declare(strict_types=1); */ use AdAures\Ipcat\IpDb; +use Config\Services; use GeoIp2\Database\Reader; -use Opawg\UserAgentsV2Php\UserAgents; +use Opawg\UserAgentsPhp\UserAgents; use WhichBrowser\Parser; if (! function_exists('base64_url_encode')) { @@ -33,18 +34,42 @@ if (! function_exists('base64_url_decode')) { } } -if (! function_exists('client_ip')) { +if (! function_exists('generate_episode_analytics_url')) { /** - * Get the client IP, depending on available headers + * Builds the episode analytics url that redirects to the audio file url after analytics hit. */ - function client_ip(): string - { - $superglobals = service('superglobals'); - if (! empty($superglobals->server('HTTP_X_FORWARDED_FOR'))) { - return $superglobals->server('HTTP_X_FORWARDED_FOR'); - } - - return $superglobals->server('REMOTE_ADDR'); + function generate_episode_analytics_url( + int $podcastId, + int $episodeId, + string $podcastHandle, + string $episodeSlug, + string $audioExtension, + float $audioDuration, + int $audioFileSize, + int $audioFileHeaderSize, + \CodeIgniter\I18n\Time $publicationDate + ): string { + return url_to( + 'episode-analytics-hit', + base64_url_encode( + pack( + 'I*', + $podcastId, + $episodeId, + // bytes_threshold: number of bytes that must be downloaded for an episode to be counted in download analytics + // - if audio is less than or equal to 60s, then take the audio file_size + // - if audio is more than 60s, then take the audio file_header_size + 60s + $audioDuration <= 60 + ? $audioFileSize + : $audioFileHeaderSize + + floor((($audioFileSize - $audioFileHeaderSize) / $audioDuration) * 60), + $audioFileSize, + $audioDuration, + $publicationDate->getTimestamp(), + ), + ), + $podcastHandle . '/' . $episodeSlug . '.' . $audioExtension, + ); } } @@ -54,10 +79,11 @@ if (! function_exists('set_user_session_deny_list_ip')) { */ function set_user_session_deny_list_ip(): void { - $session = service('session'); + $session = Services::session(); + $session->start(); if (! $session->has('denyListIp')) { - $session->set('denyListIp', IpDb::find(client_ip()) !== null); + $session->set('denyListIp', IpDb::find($_SERVER['REMOTE_ADDR']) !== null); } } } @@ -68,26 +94,31 @@ if (! function_exists('set_user_session_location')) { */ function set_user_session_location(): void { - $session = service('session'); + $session = Services::session(); + $session->start(); $location = [ 'countryCode' => 'N/A', - 'regionCode' => 'N/A', - 'latitude' => null, - 'longitude' => null, + 'regionCode' => 'N/A', + 'latitude' => null, + 'longitude' => null, ]; // Finds location: if (! $session->has('location')) { try { $cityReader = new Reader(WRITEPATH . 'uploads/GeoLite2-City/GeoLite2-City.mmdb'); - $city = $cityReader->city(client_ip()); + $city = $cityReader->city($_SERVER['REMOTE_ADDR']); $location = [ - 'countryCode' => $city->country->isoCode ?? 'N/A', - 'regionCode' => $city->subdivisions[0]->isoCode ?? 'N/A', - 'latitude' => round($city->location->latitude, 3), - 'longitude' => round($city->location->longitude, 3), + 'countryCode' => $city->country->isoCode === null + ? 'N/A' + : $city->country->isoCode, + 'regionCode' => $city->subdivisions[0]->isoCode === null + ? 'N/A' + : $city->subdivisions[0]->isoCode, + 'latitude' => round($city->location->latitude, 3), + 'longitude' => round($city->location->longitude, 3), ]; // If things go wrong the show must go on and the user must be able to download the file } catch (Exception) { @@ -104,12 +135,12 @@ if (! function_exists('set_user_session_player')) { */ function set_user_session_player(): void { - $session = service('session'); + $session = Services::session(); + $session->start(); if (! $session->has('player')) { $playerFound = null; - $userAgent = service('superglobals') - ->server('HTTP_USER_AGENT'); + $userAgent = $_SERVER['HTTP_USER_AGENT']; try { $playerFound = UserAgents::find($userAgent); @@ -121,10 +152,10 @@ if (! function_exists('set_user_session_player')) { $session->set('player', $playerFound); } else { $session->set('player', [ - 'app' => '- unknown -', + 'app' => '- unknown -', 'device' => '', - 'os' => '', - 'bot' => 0, + 'os' => '', + 'bot' => 0, ]); // Add to unknown list try { @@ -147,7 +178,8 @@ if (! function_exists('set_user_session_browser')) { */ function set_user_session_browser(): void { - $session = service('session'); + $session = Services::session(); + $session->start(); if (! $session->has('browser')) { $browserName = '- Other -'; @@ -173,12 +205,14 @@ if (! function_exists('set_user_session_referer')) { */ function set_user_session_referer(): void { - $session = service('session'); + $session = Services::session(); + $session->start(); - $newreferer = service('superglobals') - ->server('HTTP_REFERER') ?? '- Direct -'; + $newreferer = isset($_SERVER['HTTP_REFERER']) + ? $_SERVER['HTTP_REFERER'] + : '- Direct -'; $newreferer = - parse_url((string) $newreferer, PHP_URL_HOST) === + parse_url($newreferer, PHP_URL_HOST) === parse_url(current_url(false), PHP_URL_HOST) ? '- Direct -' : $newreferer; @@ -194,10 +228,10 @@ if (! function_exists('set_user_session_entry_page')) { */ function set_user_session_entry_page(): void { - $session = service('session'); + $session = Services::session(); + $session->start(); - $entryPage = service('superglobals') - ->server('REQUEST_URI'); + $entryPage = $_SERVER['REQUEST_URI']; if (! $session->has('entryPage')) { $session->set('entryPage', $entryPage); } @@ -209,15 +243,12 @@ if (! function_exists('podcast_hit')) { * Counting podcast episode downloads for analytic purposes ✅ No IP address is ever stored on the server. ✅ Only * aggregate data is stored in the database. We follow IAB Podcast Measurement Technical Guidelines Version 2.0: * https://iabtechlab.com/standards/podcast-measurement-guidelines/ - * https://iabtechlab.com/wp-content/uploads/2017/12/Podcast_Measurement_v2-Dec-20-2017.pdf - * ✅ 24-hour window - * ✅ Castopod does not do pre-load - * ✅ IP deny list https://github.com/client9/ipcat - * ✅ User-agent Filtering https://github.com/opawg/user-agents-v2 - * ✅ RSS User-agent https://github.com/opawg/podcast-rss-useragents - * ✅ Ignores 2 bytes range "Range: 0-1" (performed by official Apple iOS Podcast app) - * ✅ In case of partial content, adds up all requests to check >1mn was downloaded - * ✅ Identifying Uniques is done with a combination of IP Address and User Agent + * https://iabtechlab.com/wp-content/uploads/2017/12/Podcast_Measurement_v2-Dec-20-2017.pdf ✅ 24-hour window ✅ + * Castopod does not do pre-load ✅ IP deny list https://github.com/client9/ipcat ✅ User-agent Filtering + * https://github.com/opawg/user-agents ✅ RSS User-agent https://github.com/opawg/podcast-rss-useragents ✅ + * Ignores 2 bytes range "Range: 0-1" (performed by official Apple iOS Podcast app) ✅ In case of partial content, + * adds up all requests to check >1mn was downloaded ✅ Identifying Uniques is done with a combination of IP + * Address and User Agent * * @param integer $podcastId The podcast ID * @param integer $episodeId The Episode ID @@ -237,9 +268,8 @@ if (! function_exists('podcast_hit')) { string $serviceName, ?int $subscriptionId, ): void { - $session = service('session'); - - $clientIp = client_ip(); + $session = Services::session(); + $session->start(); // We try to count (but if things went wrong the show should go on and the user should be able to download the file): try { @@ -248,9 +278,10 @@ if (! function_exists('podcast_hit')) { $session->get('player')['bot'] = true; } - $superglobals = service('superglobals'); //We get the HTTP header field `Range`: - $httpRange = $superglobals->server('HTTP_RANGE') ?? null; + $httpRange = isset($_SERVER['HTTP_RANGE']) + ? $_SERVER['HTTP_RANGE'] + : null; $salt = config('Analytics') ->salt; @@ -259,15 +290,12 @@ if (! function_exists('podcast_hit')) { 'Analytics_Episode_' . sha1( $salt . '_' . date( - 'Y-m-d', - ) . '_' . $clientIp . '_' . $superglobals->server('HTTP_USER_AGENT') . '_' . $episodeId, + 'Y-m-d' + ) . '_' . $_SERVER['REMOTE_ADDR'] . '_' . $_SERVER['HTTP_USER_AGENT'] . '_' . $episodeId ); // The cache expires at midnight: $secondsToMidnight = strtotime('tomorrow') - time(); - - /** @var int|null $downloadedBytes */ $downloadedBytes = cache($episodeListenerHashId); - if ($downloadedBytes === null) { // If it was never downloaded that means that zero bytes were downloaded: $downloadedBytes = 0; @@ -283,12 +311,13 @@ if (! function_exists('podcast_hit')) { // [0-1] bytes range requests are used (by Apple) to check that file exists and that 206 partial content is working. // We don't count these requests. // We calculate how many bytes are being downloaded based on HTTP_RANGE values: - $ranges = explode(',', substr((string) $httpRange, 6)); + $ranges = explode(',', substr($httpRange, 6)); foreach ($ranges as $range) { $parts = explode('-', $range); $downloadedBytes += array_key_exists(1, $parts) ? $fileSize - : (int) $parts[1] - (int) $parts[0]; + : (int) $parts[1] - + (array_key_exists(0, $parts) ? 0 : (int) $parts[0]); } } @@ -308,17 +337,14 @@ if (! function_exists('podcast_hit')) { 'Analytics_Podcast_' . sha1( $salt . '_' . date( - 'Y-m-d', - ) . '_' . $clientIp . '_' . $superglobals->server('HTTP_USER_AGENT') . '_' . $podcastId, + 'Y-m-d' + ) . '_' . $_SERVER['REMOTE_ADDR'] . '_' . $_SERVER['HTTP_USER_AGENT'] . '_' . $podcastId ); $newListener = 1; - // Has this listener already downloaded an episode today: - /** @var int|null $downloadsByUser */ $downloadsByUser = cache($podcastListenerHashId); - // We add one download - if ($downloadsByUser === null) { + if ($downloadsByUser) { $newListener = 0; ++$downloadsByUser; } else { diff --git a/modules/Analytics/Models/AnalyticsPodcastByCountryModel.php b/modules/Analytics/Models/AnalyticsPodcastByCountryModel.php index b79d6de8..cc96c415 100644 --- a/modules/Analytics/Models/AnalyticsPodcastByCountryModel.php +++ b/modules/Analytics/Models/AnalyticsPodcastByCountryModel.php @@ -23,7 +23,7 @@ class AnalyticsPodcastByCountryModel extends Model protected $table = 'analytics_podcasts_by_country'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsPodcastsByCountry::class; @@ -52,7 +52,7 @@ class AnalyticsPodcastByCountryModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => $oneWeekAgo, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') @@ -80,7 +80,7 @@ class AnalyticsPodcastByCountryModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => $oneYearAgo, + 'date >' => $oneYearAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') diff --git a/modules/Analytics/Models/AnalyticsPodcastByEpisodeModel.php b/modules/Analytics/Models/AnalyticsPodcastByEpisodeModel.php index cb4d47a9..fa2e1fd7 100644 --- a/modules/Analytics/Models/AnalyticsPodcastByEpisodeModel.php +++ b/modules/Analytics/Models/AnalyticsPodcastByEpisodeModel.php @@ -23,7 +23,7 @@ class AnalyticsPodcastByEpisodeModel extends Model protected $table = 'analytics_podcasts_by_episode'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsPodcastsByEpisode::class; @@ -50,7 +50,7 @@ class AnalyticsPodcastByEpisodeModel extends Model ->where([ 'episode_id' => $episodeId, 'podcast_id' => $podcastId, - 'age <' => 60, + 'age <' => 60, ]) ->groupBy('labels') ->orderBy('labels', 'ASC') @@ -66,7 +66,7 @@ class AnalyticsPodcastByEpisodeModel extends Model /** * @return AnalyticsPodcastsByEpisode[] */ - public function getDataByMonth(int $podcastId, ?int $episodeId = null): array + public function getDataByMonth(int $podcastId, int $episodeId = null): array { if ( ! ($found = cache("{$podcastId}_{$episodeId}_analytics_podcast_by_episode_by_month")) diff --git a/modules/Analytics/Models/AnalyticsPodcastByHourModel.php b/modules/Analytics/Models/AnalyticsPodcastByHourModel.php index 071df0f9..5e627a75 100644 --- a/modules/Analytics/Models/AnalyticsPodcastByHourModel.php +++ b/modules/Analytics/Models/AnalyticsPodcastByHourModel.php @@ -23,7 +23,7 @@ class AnalyticsPodcastByHourModel extends Model protected $table = 'analytics_podcasts_by_hour'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsPodcastsByHour::class; @@ -49,7 +49,7 @@ class AnalyticsPodcastByHourModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => date('Y-m-d', strtotime('-60 days')), + 'date >' => date('Y-m-d', strtotime('-60 days')), ]) ->groupBy('labels') ->orderBy('labels', 'ASC') diff --git a/modules/Analytics/Models/AnalyticsPodcastByPlayerModel.php b/modules/Analytics/Models/AnalyticsPodcastByPlayerModel.php index 1cc7d74d..d30e3488 100644 --- a/modules/Analytics/Models/AnalyticsPodcastByPlayerModel.php +++ b/modules/Analytics/Models/AnalyticsPodcastByPlayerModel.php @@ -23,7 +23,7 @@ class AnalyticsPodcastByPlayerModel extends Model protected $table = 'analytics_podcasts_by_player'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsPodcastsByPlayer::class; @@ -52,9 +52,9 @@ class AnalyticsPodcastByPlayerModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'app !=' => '', - 'is_bot' => 0, - 'date >' => $oneWeekAgo, + 'app !=' => '', + 'is_bot' => 0, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') @@ -81,9 +81,9 @@ class AnalyticsPodcastByPlayerModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'app !=' => '', - 'is_bot' => 0, - 'date >' => $oneYearAgo, + 'app !=' => '', + 'is_bot' => 0, + 'date >' => $oneYearAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') @@ -110,10 +110,10 @@ class AnalyticsPodcastByPlayerModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'app !=' => '', - 'os !=' => '', - 'is_bot' => 0, - 'date >' => $oneWeekAgo, + 'app !=' => '', + 'os !=' => '', + 'is_bot' => 0, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') @@ -140,9 +140,9 @@ class AnalyticsPodcastByPlayerModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'device !=' => '', - 'is_bot' => 0, - 'date >' => $oneWeekAgo, + 'device !=' => '', + 'is_bot' => 0, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') @@ -169,8 +169,8 @@ class AnalyticsPodcastByPlayerModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'is_bot' => 1, - 'date >' => $oneYearAgo, + 'is_bot' => 1, + 'date >' => $oneYearAgo, ]) ->groupBy('labels') ->orderBy('labels', 'ASC') diff --git a/modules/Analytics/Models/AnalyticsPodcastByRegionModel.php b/modules/Analytics/Models/AnalyticsPodcastByRegionModel.php index 0bba643b..7b04fd8a 100644 --- a/modules/Analytics/Models/AnalyticsPodcastByRegionModel.php +++ b/modules/Analytics/Models/AnalyticsPodcastByRegionModel.php @@ -23,7 +23,7 @@ class AnalyticsPodcastByRegionModel extends Model protected $table = 'analytics_podcasts_by_region'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsPodcastsByRegion::class; @@ -56,7 +56,7 @@ class AnalyticsPodcastByRegionModel extends Model ->groupBy('country_code, region_code') ->where([ 'podcast_id' => $podcastId, - 'date >' => date('Y-m-d', strtotime('-1 week')), + 'date >' => date('Y-m-d', strtotime('-1 week')), ]) ->orderBy('value', 'DESC') ->findAll(); diff --git a/modules/Analytics/Models/AnalyticsPodcastByServiceModel.php b/modules/Analytics/Models/AnalyticsPodcastByServiceModel.php index e7bacc11..2e1e9eda 100644 --- a/modules/Analytics/Models/AnalyticsPodcastByServiceModel.php +++ b/modules/Analytics/Models/AnalyticsPodcastByServiceModel.php @@ -23,7 +23,7 @@ class AnalyticsPodcastByServiceModel extends Model protected $table = 'analytics_podcasts_by_player'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsPodcastsByService::class; @@ -53,8 +53,8 @@ class AnalyticsPodcastByServiceModel extends Model ->where([ 'podcast_id' => $podcastId, 'service !=' => '', - 'is_bot' => 0, - 'date >' => $oneWeekAgo, + 'is_bot' => 0, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') diff --git a/modules/Analytics/Models/AnalyticsPodcastBySubscriptionModel.php b/modules/Analytics/Models/AnalyticsPodcastBySubscriptionModel.php index c629d057..d845a08f 100644 --- a/modules/Analytics/Models/AnalyticsPodcastBySubscriptionModel.php +++ b/modules/Analytics/Models/AnalyticsPodcastBySubscriptionModel.php @@ -21,7 +21,7 @@ class AnalyticsPodcastBySubscriptionModel extends Model protected $table = 'analytics_podcasts_by_subscription'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsPodcastsBySubscription::class; @@ -45,7 +45,7 @@ class AnalyticsPodcastBySubscriptionModel extends Model $found = (int) ($this->builder() ->selectSum('hits', 'total_hits') ->where([ - 'podcast_id' => $podcastId, + 'podcast_id' => $podcastId, 'subscription_id' => $subscriptionId, ]) ->where('`date` >= UTC_TIMESTAMP() - INTERVAL 3 month', null, false) diff --git a/modules/Analytics/Models/AnalyticsPodcastModel.php b/modules/Analytics/Models/AnalyticsPodcastModel.php index 751620e2..fee1ae44 100644 --- a/modules/Analytics/Models/AnalyticsPodcastModel.php +++ b/modules/Analytics/Models/AnalyticsPodcastModel.php @@ -12,9 +12,10 @@ declare(strict_types=1); namespace Modules\Analytics\Models; +use App\Entities\Media\BaseMedia; +use App\Models\MediaModel; use CodeIgniter\Model; use Modules\Analytics\Entities\AnalyticsPodcasts; -use Modules\Media\Models\MediaModel; class AnalyticsPodcastModel extends Model { @@ -24,7 +25,7 @@ class AnalyticsPodcastModel extends Model protected $table = 'analytics_podcasts'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsPodcasts::class; @@ -49,7 +50,7 @@ class AnalyticsPodcastModel extends Model $found = $this->select('date as labels, hits as values') ->where([ 'podcast_id' => $podcastId, - 'date >' => date('Y-m-d', strtotime('-60 days')), + 'date >' => date('Y-m-d', strtotime('-60 days')), ]) ->orderBy('labels', 'ASC') ->findAll(); @@ -73,7 +74,7 @@ class AnalyticsPodcastModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => date('Y-m-d', strtotime('-60 days')), + 'date >' => date('Y-m-d', strtotime('-60 days')), ]) ->groupBy('labels, sort_labels') ->orderBy('sort_labels', 'ASC') @@ -97,7 +98,7 @@ class AnalyticsPodcastModel extends Model $found = $this->select('date as labels, ROUND(bandwidth / 1000000, 2) as `values`') ->where([ 'podcast_id' => $podcastId, - 'date >' => date('Y-m-d', strtotime('-60 days')), + 'date >' => date('Y-m-d', strtotime('-60 days')), ]) ->orderBy('labels', 'ASC') ->findAll(); @@ -146,7 +147,7 @@ class AnalyticsPodcastModel extends Model $found = $this->select('date as labels, unique_listeners as values') ->where([ 'podcast_id' => $podcastId, - 'date >' => date('Y-m-d', strtotime('-60 days')), + 'date >' => date('Y-m-d', strtotime('-60 days')), ]) ->orderBy('labels', 'ASC') ->findAll(); @@ -198,7 +199,7 @@ class AnalyticsPodcastModel extends Model ->selectSum('duration', 'values') ->where([ $this->table . '.podcast_id' => $podcastId, - 'date >' => date('Y-m-d', strtotime('-60 days')), + 'date >' => date('Y-m-d', strtotime('-60 days')), ]) ->groupBy('labels') ->orderBy('labels', 'ASC') @@ -246,7 +247,7 @@ class AnalyticsPodcastModel extends Model { if (! ($found = cache('analytics_total_bandwidth_by_month'))) { $found = $this->select( - 'DATE_FORMAT(updated_at,"%Y-%m") as labels, ROUND(sum(bandwidth) / 1000000, 2) as `values`', + 'DATE_FORMAT(updated_at,"%Y-%m") as labels, ROUND(sum(bandwidth) / 1000000, 2) as `values`' ) ->groupBy('labels') ->orderBy('labels', 'ASC') @@ -262,13 +263,14 @@ class AnalyticsPodcastModel extends Model /** * Get total storage * - * @return AnalyticsPodcasts[] + * @return BaseMedia[] */ public function getDataTotalStorageByMonth(): array { if (! ($found = cache('analytics_total_storage_by_month'))) { - $found = new MediaModel() - ->select('DATE_FORMAT(uploaded_at,"%Y-%m") as labels, ROUND(sum(file_size) / 1000000, 2) as `values`') + $found = (new MediaModel())->select( + 'DATE_FORMAT(uploaded_at,"%Y-%m") as labels, ROUND(sum(file_size) / 1000000, 2) as `values`' + ) ->groupBy('labels') ->orderBy('labels', 'ASC') ->findAll(); diff --git a/modules/Analytics/Models/AnalyticsUnknownUserAgentsModel.php b/modules/Analytics/Models/AnalyticsUnknownUseragentsModel.php similarity index 89% rename from modules/Analytics/Models/AnalyticsUnknownUserAgentsModel.php rename to modules/Analytics/Models/AnalyticsUnknownUseragentsModel.php index 59053466..21cf11d2 100644 --- a/modules/Analytics/Models/AnalyticsUnknownUserAgentsModel.php +++ b/modules/Analytics/Models/AnalyticsUnknownUseragentsModel.php @@ -15,7 +15,7 @@ namespace Modules\Analytics\Models; use CodeIgniter\Model; use Modules\Analytics\Entities\AnalyticsUnknownUserAgent; -class AnalyticsUnknownUserAgentsModel extends Model +class AnalyticsUnknownUserAgentModel extends Model { /** * @var string @@ -23,7 +23,7 @@ class AnalyticsUnknownUserAgentsModel extends Model protected $table = 'analytics_unknown_useragents'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsUnknownUserAgent::class; diff --git a/modules/Analytics/Models/AnalyticsWebsiteByBrowserModel.php b/modules/Analytics/Models/AnalyticsWebsiteByBrowserModel.php index e5398311..ebb446d6 100644 --- a/modules/Analytics/Models/AnalyticsWebsiteByBrowserModel.php +++ b/modules/Analytics/Models/AnalyticsWebsiteByBrowserModel.php @@ -23,7 +23,7 @@ class AnalyticsWebsiteByBrowserModel extends Model protected $table = 'analytics_website_by_browser'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsWebsiteByBrowser::class; @@ -50,7 +50,7 @@ class AnalyticsWebsiteByBrowserModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => $oneWeekAgo, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') diff --git a/modules/Analytics/Models/AnalyticsWebsiteByEntryPageModel.php b/modules/Analytics/Models/AnalyticsWebsiteByEntryPageModel.php index 90bfcfde..0ef9d842 100644 --- a/modules/Analytics/Models/AnalyticsWebsiteByEntryPageModel.php +++ b/modules/Analytics/Models/AnalyticsWebsiteByEntryPageModel.php @@ -23,7 +23,7 @@ class AnalyticsWebsiteByEntryPageModel extends Model protected $table = 'analytics_website_by_entry_page'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsWebsiteByEntryPage::class; @@ -50,7 +50,7 @@ class AnalyticsWebsiteByEntryPageModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => $oneWeekAgo, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') diff --git a/modules/Analytics/Models/AnalyticsWebsiteByRefererModel.php b/modules/Analytics/Models/AnalyticsWebsiteByRefererModel.php index cd8fb2a5..b5973d2c 100644 --- a/modules/Analytics/Models/AnalyticsWebsiteByRefererModel.php +++ b/modules/Analytics/Models/AnalyticsWebsiteByRefererModel.php @@ -23,7 +23,7 @@ class AnalyticsWebsiteByRefererModel extends Model protected $table = 'analytics_website_by_referer'; /** - * @var class-string + * @var string */ protected $returnType = AnalyticsWebsiteByReferer::class; @@ -50,7 +50,7 @@ class AnalyticsWebsiteByRefererModel extends Model ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => $oneWeekAgo, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') @@ -73,11 +73,11 @@ class AnalyticsWebsiteByRefererModel extends Model ! ($found = cache("{$podcastId}_analytics_website_by_domain_weekly")) ) { $oneWeekAgo = date('Y-m-d', strtotime('-1 week')); - $found = $this->select('domain as labels') + $found = $this->select("SUBSTRING_INDEX(domain, '.', -2) as labels") ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => $oneWeekAgo, + 'date >' => $oneWeekAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') @@ -100,11 +100,11 @@ class AnalyticsWebsiteByRefererModel extends Model ! ($found = cache("{$podcastId}_analytics_website_by_domain_yearly")) ) { $oneYearAgo = date('Y-m-d', strtotime('-1 year')); - $found = $this->select('domain as labels') + $found = $this->select("SUBSTRING_INDEX(domain, '.', -2) as labels") ->selectSum('hits', 'values') ->where([ 'podcast_id' => $podcastId, - 'date >' => $oneYearAgo, + 'date >' => $oneYearAgo, ]) ->groupBy('labels') ->orderBy('values', 'DESC') diff --git a/modules/Api/Rest/V1/Config/Registrar.php b/modules/Api/Rest/V1/Config/Registrar.php deleted file mode 100644 index 43814934..00000000 --- a/modules/Api/Rest/V1/Config/Registrar.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ - public static function Filters(): array - { - return [ - 'aliases' => [ - 'rest-api' => ApiFilter::class, - ], - ]; - } -} diff --git a/modules/Api/Rest/V1/Config/RestApi.php b/modules/Api/Rest/V1/Config/RestApi.php index 836a8fb2..d32a6cb9 100644 --- a/modules/Api/Rest/V1/Config/RestApi.php +++ b/modules/Api/Rest/V1/Config/RestApi.php @@ -15,17 +15,6 @@ class RestApi extends BaseConfig */ public bool $enabled = false; - public bool $basicAuth = false; - - public ?string $basicAuthUsername = null; - - public ?string $basicAuthPassword = null; - - /** - * Default results limit. - */ - public int $limit = 10; - /** * -------------------------------------------------------------------------- * Rest API gateway diff --git a/modules/Api/Rest/V1/Config/Routes.php b/modules/Api/Rest/V1/Config/Routes.php index 5f717129..0fe530ba 100644 --- a/modules/Api/Rest/V1/Config/Routes.php +++ b/modules/Api/Rest/V1/Config/Routes.php @@ -4,36 +4,18 @@ declare(strict_types=1); namespace Modules\Api\Rest\V1\Config; -use CodeIgniter\Router\RouteCollection; - -/** @var RouteCollection $routes */ +$routes = service('routes'); $routes->group( config('RestApi') ->gateway . 'podcasts', [ 'namespace' => 'Modules\Api\Rest\V1\Controllers', - 'filter' => 'rest-api', + 'filter' => 'rest-api', ], static function ($routes): void { $routes->get('/', 'PodcastController::list'); $routes->get('(:num)', 'PodcastController::view/$1'); $routes->get('(:any)', 'ExceptionController::notFound'); - }, -); - -$routes->group( - config('RestApi') - ->gateway . 'episodes', - [ - 'namespace' => 'Modules\Api\Rest\V1\Controllers', - 'filter' => 'rest-api', - ], - static function ($routes): void { - $routes->get('/', 'EpisodeController::list'); - $routes->post('/', 'EpisodeController::attemptCreate'); - $routes->post('(:num)/publish', 'EpisodeController::attemptPublish/$1'); - $routes->get('(:num)', 'EpisodeController::view/$1'); - $routes->get('(:any)', 'ExceptionController::notFound'); - }, + } ); diff --git a/modules/Api/Rest/V1/Config/Services.php b/modules/Api/Rest/V1/Config/Services.php index 40806e82..c4a3d72c 100644 --- a/modules/Api/Rest/V1/Config/Services.php +++ b/modules/Api/Rest/V1/Config/Services.php @@ -5,16 +5,16 @@ declare(strict_types=1); namespace Modules\Api\Rest\V1\Config; use CodeIgniter\Config\BaseService; -use Modules\Api\Rest\V1\Core\RestApiExceptions; +use Modules\Api\Rest\V1\Core\Exceptions; class Services extends BaseService { - public static function restApiExceptions(bool $getShared = true): RestApiExceptions + public static function restApiExceptions(bool $getShared = true) { if ($getShared) { return static::getSharedInstance('restApiExceptions'); } - return new RestApiExceptions(config('Exceptions')); + return new Exceptions(config('Exceptions'), static::request(), static::response()); } } diff --git a/modules/Api/Rest/V1/Controllers/BaseApiController.php b/modules/Api/Rest/V1/Controllers/BaseApiController.php deleted file mode 100644 index ba114089..00000000 --- a/modules/Api/Rest/V1/Controllers/BaseApiController.php +++ /dev/null @@ -1,22 +0,0 @@ -initialize(); - } - - public function list(): ResponseInterface - { - $query = $this->request->getGet('query'); - $order = $this->request->getGet('order') ?? 'newest'; - $podcastIds = $this->request->getGet('podcastIds'); - - $builder = (new EpisodeModel()); - - if ($podcastIds !== null) { - $builder->whereIn('podcast_id', explode(',', (string) $podcastIds)); - } - - if ($query !== null) { - $builder->fullTextSearch($query); - - if ($order === 'search') { - $builder->orderBy('(episodes_score + podcasts_score)', 'desc'); - } - } - - if ($order === 'newest') { - $builder->orderBy('episodes.created_at', 'desc'); - } - - /** @var array $data */ - $data = $builder->findAll( - (int) ($this->request->getGet('limit') ?? config('RestApi')->limit), - (int) $this->request->getGet('offset'), - ); - - array_map(static function (Episode $episode): void { - self::mapEpisode($episode); - }, $data); - - return $this->respond($data); - } - - public function view(int $id): ResponseInterface - { - $episode = new EpisodeModel() - ->getEpisodeById($id); - - if (! $episode instanceof Episode) { - return $this->failNotFound('Episode not found'); - } - - // @phpstan-ignore-next-line - return $this->respond(static::mapEpisode($episode)); - } - - public function attemptCreate(): ResponseInterface - { - $rules = [ - 'created_by' => 'required|is_natural_no_zero', - 'updated_by' => 'required|is_natural_no_zero', - 'title' => 'required', - 'slug' => 'required|max_length[128]', - 'podcast_id' => 'required|is_natural_no_zero', - 'audio_file' => 'uploaded[audio_file]|ext_in[audio_file,mp3,m4a]', - 'cover' => 'permit_empty|is_image[cover]|ext_in[cover,jpg,jpeg,png]|min_dims[cover,1400,1400]|is_image_ratio[cover,1,1]', - 'transcript_file' => 'permit_empty|ext_in[transcript_file,srt,vtt]', - 'chapters_file' => 'permit_empty|ext_in[chapters_file,json]|is_json[chapters_file]', - 'transcript-choice' => 'permit_empty|in_list[upload-file,remote-url]', - 'chapters-choice' => 'permit_empty|in_list[upload-file,remote-url]', - ]; - - if (! $this->validate($rules)) { - return $this->failValidationErrors(array_values($this->validator->getErrors())); - } - - $podcastId = (int) $this->request->getPost('podcast_id'); - - $podcast = new PodcastModel() - ->getPodcastById($podcastId); - - if (! $podcast instanceof Podcast) { - return $this->failNotFound('Podcast not found'); - } - - $createdByUserId = (int) $this->request->getPost('created_by'); - - $userModel = new UserModel(); - $createdByUser = $userModel->find($createdByUserId); - - if (! $createdByUser) { - return $this->failNotFound('User not found'); - } - - $updatedByUserId = (int) $this->request->getPost('updated_by'); - - $updatedByUser = $userModel->find($updatedByUserId); - - if (! $updatedByUser) { - return $this->failNotFound('Updated by user not found'); - } - - if ($podcast->type === 'serial' && $this->request->getPost('type') === 'full') { - $rules['episode_number'] = 'required'; - } - - if (! $this->validate($rules)) { - return $this->failValidationErrors(array_values($this->validator->getErrors())); - } - - $validData = $this->validator->getValidated(); - - if (new EpisodeModel() - ->where([ - 'slug' => $validData['slug'], - 'podcast_id' => $podcast->id, - ]) - ->first() instanceof Episode) { - return $this->fail('An episode with the same slug already exists in this podcast.', 409); - } - - $newEpisode = new Episode([ - 'created_by' => $createdByUserId, - 'updated_by' => $updatedByUserId, - 'podcast_id' => $podcast->id, - 'title' => $validData['title'], - 'slug' => $validData['slug'], - 'guid' => null, - 'audio' => $this->request->getFile('audio_file'), - 'cover' => $this->request->getFile('cover'), - 'description_markdown' => $this->request->getPost('description'), - 'location' => in_array($this->request->getPost('location_name'), ['', null], true) - ? null - : new Location($this->request->getPost('location_name')), - 'parental_advisory' => $this->request->getPost('parental_advisory') !== 'undefined' - ? $this->request->getPost('parental_advisory') - : null, - 'number' => $this->request->getPost('episode_number') ? (int) $this->request->getPost( - 'episode_number', - ) : null, - 'season_number' => $this->request->getPost('season_number') ? (int) $this->request->getPost( - 'season_number', - ) : null, - 'type' => $this->request->getPost('type'), - 'is_blocked' => $this->request->getPost('block') === 'yes', - 'custom_rss_string' => $this->request->getPost('custom_rss'), - 'is_premium' => $this->request->getPost('premium') === 'yes', - 'published_at' => null, - ]); - - $transcriptChoice = $this->request->getPost('transcript-choice'); - if ($transcriptChoice === 'upload-file') { - $newEpisode->setTranscript($this->request->getFile('transcript_file')); - } elseif ($transcriptChoice === 'remote-url') { - $newEpisode->transcript_remote_url = $this->request->getPost( - 'transcript_remote_url', - ) === '' ? null : $this->request->getPost('transcript_remote_url'); - } - - $chaptersChoice = $this->request->getPost('chapters-choice'); - if ($chaptersChoice === 'upload-file') { - $newEpisode->setChapters($this->request->getFile('chapters_file')); - } elseif ($chaptersChoice === 'remote-url') { - $newEpisode->chapters_remote_url = $this->request->getPost( - 'chapters_remote_url', - ) === '' ? null : $this->request->getPost('chapters_remote_url'); - } - - $episodeModel = new EpisodeModel(); - if (($newEpisodeId = (int) $episodeModel->insert($newEpisode, true)) === 0) { - return $this->fail(array_values($episodeModel->errors()), 400); - } - - $episode = $episodeModel->find($newEpisodeId) - ->toRawArray(); - - return $this->respond($episode); - } - - public function attemptPublish(int $id): ResponseInterface - { - $episodeModel = new EpisodeModel(); - $episode = $episodeModel->getEpisodeById($id); - - if (! $episode instanceof Episode) { - return $this->failNotFound('Episode not found'); - } - - if ($episode->publication_status !== 'not_published') { - return $this->fail('Episode is already published or scheduled for publication', 409); - } - - $rules = [ - 'publication_method' => 'required', - 'created_by' => 'required|is_natural_no_zero', - ]; - - if (! $this->validate($rules)) { - return $this->failValidationErrors(array_values($this->validator->getErrors())); - } - - if ($this->request->getPost('publication_method') === 'schedule') { - $rules['scheduled_publication_date'] = 'required|valid_date[Y-m-d H:i]'; - } - - if (! $this->validate($rules)) { - return $this->failValidationErrors(array_values($this->validator->getErrors())); - } - - $createdByUserId = (int) $this->request->getPost('created_by'); - - $userModel = new UserModel(); - $createdByUser = $userModel->find($createdByUserId); - - if (! $createdByUser) { - return $this->failNotFound('User not found'); - } - - $validData = $this->validator->getValidated(); - - $db = db_connect(); - $db->transStart(); - - $newPost = new Post([ - 'actor_id' => $episode->podcast->actor_id, - 'episode_id' => $episode->id, - 'message' => $this->request->getPost('message') ?? '', - 'created_by' => $createdByUserId, - ]); - - $clientTimezone = $this->request->getPost('client_timezone') ?? app_timezone(); - - if ($episode->podcast->publication_status === 'published') { - $publishMethod = $validData['publication_method']; - if ($publishMethod === 'schedule') { - $scheduledPublicationDate = $validData['scheduled_publication_date'] ?? null; - if ($scheduledPublicationDate) { - $episode->published_at = Time::createFromFormat( - 'Y-m-d H:i', - $scheduledPublicationDate, - $clientTimezone, - )->setTimezone(app_timezone()); - } else { - $db->transRollback(); - return $this->fail('Scheduled publication date is required', 400); - } - } else { - $episode->published_at = Time::now(); - } - } elseif ($episode->podcast->publication_status === 'scheduled') { - // podcast publication date has already been set - $episode->published_at = $episode->podcast->published_at->addSeconds(1); - } else { - $episode->published_at = Time::now(); - } - - $newPost->published_at = $episode->published_at; - - $postModel = new PostModel(); - if (! $postModel->addPost($newPost)) { - $db->transRollback(); - return $this->fail(array_values($postModel->errors()), 400); - } - - if (! $episodeModel->update($episode->id, $episode)) { - $db->transRollback(); - return $this->fail(array_values($episodeModel->errors()), 400); - } - - $db->transComplete(); - - // @phpstan-ignore-next-line - return $this->respond(self::mapEpisode($episode)); - } - - protected static function mapEpisode(Episode $episode): Episode - { - $episode->cover_url = $episode->getCover() - ->file_url; - $episode->duration = round($episode->audio->duration); - - return $episode; - } -} diff --git a/modules/Api/Rest/V1/Controllers/ExceptionController.php b/modules/Api/Rest/V1/Controllers/ExceptionController.php index 3f1cd7f0..50dd7863 100644 --- a/modules/Api/Rest/V1/Controllers/ExceptionController.php +++ b/modules/Api/Rest/V1/Controllers/ExceptionController.php @@ -4,11 +4,15 @@ declare(strict_types=1); namespace Modules\Api\Rest\V1\Controllers; -use CodeIgniter\HTTP\ResponseInterface; +use CodeIgniter\API\ResponseTrait; +use CodeIgniter\Controller; +use CodeIgniter\HTTP\Response; -class ExceptionController extends BaseApiController +class ExceptionController extends Controller { - public function notFound(): ResponseInterface + use ResponseTrait; + + public function notFound(): Response { return $this->failNotFound('Podcast not found'); } diff --git a/modules/Api/Rest/V1/Controllers/PodcastController.php b/modules/Api/Rest/V1/Controllers/PodcastController.php index 8daf7c33..3cbe3cd8 100644 --- a/modules/Api/Rest/V1/Controllers/PodcastController.php +++ b/modules/Api/Rest/V1/Controllers/PodcastController.php @@ -6,54 +6,37 @@ namespace Modules\Api\Rest\V1\Controllers; use App\Entities\Podcast; use App\Models\PodcastModel; -use CodeIgniter\HTTP\ResponseInterface; +use CodeIgniter\API\ResponseTrait; +use CodeIgniter\Controller; +use CodeIgniter\HTTP\Response; +use Modules\Api\Rest\V1\Config\Services; -class PodcastController extends BaseApiController +class PodcastController extends Controller { + use ResponseTrait; + public function __construct() { - service('restApiExceptions')->initialize(); + Services::restApiExceptions()->initialize(); } - public function list(): ResponseInterface + public function list(): Response { - /** @var array $data */ - $data = new PodcastModel() - ->findAll(); - array_map(static function (Podcast $podcast): void { - self::mapPodcast($podcast); + $data = (new PodcastModel())->findAll(); + array_map(static function ($podcast): void { + $podcast->feed_url = $podcast->getFeedUrl(); }, $data); return $this->respond($data); } - public function view(int $id): ResponseInterface + public function view(int $id): Response { - $podcast = new PodcastModel() - ->getPodcastById($id); - if (! $podcast instanceof Podcast) { + $data = (new PodcastModel())->getPodcastById($id); + if (! $data instanceof Podcast) { return $this->failNotFound('Podcast not found'); } - // @phpstan-ignore-next-line - return $this->respond(self::mapPodcast($podcast)); - } - - protected static function mapPodcast(Podcast $podcast): Podcast - { - $podcast->feed_url = $podcast->getFeedUrl(); - $podcast->actor_display_name = $podcast->getActor() - ->display_name; - $podcast->cover_url = $podcast->getCover() - ->file_url; - - $categories = [$podcast->getCategory(), ...$podcast->getOtherCategories()]; - - foreach ($categories as $category) { - $category->translated = lang('Podcast.category_options.' . $category->code); - } - - $podcast->categories = $categories; - - return $podcast; + $data->feed_url = $data->getFeedUrl(); + return $this->respond($data); } } diff --git a/modules/Api/Rest/V1/Core/RestApiExceptions.php b/modules/Api/Rest/V1/Core/Exceptions.php similarity index 62% rename from modules/Api/Rest/V1/Core/RestApiExceptions.php rename to modules/Api/Rest/V1/Core/Exceptions.php index 7d132aea..4dae50e5 100644 --- a/modules/Api/Rest/V1/Core/RestApiExceptions.php +++ b/modules/Api/Rest/V1/Core/Exceptions.php @@ -4,19 +4,16 @@ declare(strict_types=1); namespace Modules\Api\Rest\V1\Core; -use CodeIgniter\Debug\Exceptions; -use Override; use Throwable; -class RestApiExceptions extends Exceptions +class Exceptions extends \CodeIgniter\Debug\Exceptions { - #[Override] protected function render(Throwable $exception, int $statusCode): void { header('Content-Type: application/json'); $data = [ - 'status' => $statusCode, - 'error' => $statusCode, + 'status' => $statusCode, + 'error' => $statusCode, 'messages' => [ 'error' => 'Unexpected error', ], @@ -24,9 +21,9 @@ class RestApiExceptions extends Exceptions if (ENVIRONMENT === 'development') { $data['messages'] = array_merge($data['messages'], [ 'message' => $exception->getMessage(), - 'file' => $exception->getFile(), - 'line' => $exception->getLine(), - 'trace' => $exception->getTrace(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + 'trace' => $exception->getTrace(), ]); } diff --git a/modules/Api/Rest/V1/Filters/ApiFilter.php b/modules/Api/Rest/V1/Filters/ApiFilter.php index 8bb25935..d6e6b32a 100644 --- a/modules/Api/Rest/V1/Filters/ApiFilter.php +++ b/modules/Api/Rest/V1/Filters/ApiFilter.php @@ -6,75 +6,20 @@ namespace Modules\Api\Rest\V1\Filters; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\Filters\FilterInterface; -use CodeIgniter\HTTP\Request; use CodeIgniter\HTTP\RequestInterface; -use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface; -use Modules\Api\Rest\V1\Config\RestApi; -use Override; class ApiFilter implements FilterInterface { - /** - * @param Request $request - * - * @return RequestInterface|ResponseInterface|string|null - */ - #[Override] - public function before(RequestInterface $request, $arguments = null) + public function before(RequestInterface $request, $arguments = null): void { - /** @var RestApi $restApiConfig */ - $restApiConfig = config('RestApi'); - - if (! $restApiConfig->enabled) { + if (! config('RestApi')->enabled) { throw PageNotFoundException::forPageNotFound(); } - - if ($request->getMethod() === 'POST' && ! $restApiConfig->basicAuth) { - /** @var Response $response */ - $response = service('response'); - $response->setStatusCode(401); - return $response; - } - - if ($restApiConfig->basicAuth) { - /** @var Response $response */ - $response = service('response'); - if (! $request->hasHeader('Authorization')) { - $response->setStatusCode(401); - - return $response; - } - - $authHeader = $request->getHeaderLine('Authorization'); - if (! str_starts_with($authHeader, 'Basic ')) { - $response->setStatusCode(401); - - return $response; - } - - $auth_token = base64_decode(substr($authHeader, 6), true); - - [$username, $password] = explode(':', (string) $auth_token); - - if (! ($username === $restApiConfig->basicAuthUsername && $password === $restApiConfig->basicAuthPassword)) { - $response->setStatusCode(401); - - return $response; - } - } - - return null; } - /** - * @param string[]|null $arguments - * - * @return ResponseInterface|null - */ - #[Override] - public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void { - return null; + // Do something here } } diff --git a/modules/Api/Rest/V1/podcast.json b/modules/Api/Rest/V1/podcast.json new file mode 100644 index 00000000..4fe37fde --- /dev/null +++ b/modules/Api/Rest/V1/podcast.json @@ -0,0 +1,328 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.0.0", + "title": "Castopod podcasts" + }, + "paths": { + "/api/rest/v1/podcasts": { + "get": { + "summary": "List all podcasts", + "responses": { + "200": { + "description": "Object of podcasts", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Podcasts" + } + } + } + }, + "default": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/rest/v1/podcasts/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The id of the podcast to retrieve", + "schema": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maxLength": 10 + } + } + ], + "get": { + "summary": "Info for a specific podcast", + "responses": { + "200": { + "description": "Expected response to a valid request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Podcast" + } + } + } + }, + "default": { + "description": "unexpected error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Podcast": { + "type": "object", + "required": [ + "id", + "guid", + "actor_id", + "handle", + "title", + "description_markdown", + "description_html", + "cover_id", + "language_code", + "category_id", + "owner_name", + "owner_email", + "type", + "is_blocked", + "is_completed", + "is_locked", + "is_published_on_hubs", + "created_by", + "updated_by", + "created_at", + "updated_at", + "feed_url" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maxLength": 10 + }, + "guid": { + "type": "string", + "maxLength": 36 + }, + "actor_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maxLength": 10 + }, + "handle": { + "type": "string", + "maxLength": 32 + }, + "title": { + "type": "string", + "maxLength": 128 + }, + "description_markdown": { + "type": "string" + }, + "description_html": { + "type": "string" + }, + "cover_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maxLength": 10 + }, + "banner_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maxLength": 10 + }, + "language_code": { + "type": "string", + "maxLength": 2 + }, + "category_id": { + "type": "integer", + "format": "int64", + "minimum": 1 + }, + "parental_advisory": { + "type": "string", + "enum": ["clean", "explicit"] + }, + "owner_name": { + "type": "string", + "maxLength": 128 + }, + "owner_email": { + "type": "string", + "maxLength": 255 + }, + "publisher": { + "type": "string", + "maxLength": 128 + }, + "type": { + "type": "string", + "enum": ["episodic", "serial"] + }, + "copyright": { + "type": "string", + "maxLength": 128 + }, + "episode_description_footer_markdown": { + "type": "string" + }, + "episode_description_footer_html": { + "type": "string" + }, + "is_blocked": { + "type": "integer", + "format": "int32", + "enum": [0, 1], + "minLength": 1 + }, + "is_completed": { + "type": "integer", + "format": "int32", + "enum": [0, 1], + "minLength": 1 + }, + "is_locked": { + "type": "integer", + "format": "int32", + "enum": [0, 1], + "minLength": 1 + }, + "imported_feed_url": { + "type": "string", + "maxLength": 512 + }, + "new_feed_url": { + "type": "string", + "maxLength": 512 + }, + "payment_pointer": { + "type": "string", + "maxLength": 128 + }, + "location_name": { + "type": "string", + "maxLength": 128 + }, + "location_geo": { + "type": "string", + "maxLength": 32 + }, + "location_osm": { + "type": "string", + "maxLength": 12 + }, + "custom_rss": { + "type": "string" + }, + "is_published_on_hubs": { + "type": "integer", + "format": "int32", + "enum": [0, 1], + "minLength": 1 + }, + "partner_id": { + "type": "string", + "maxLength": 32 + }, + "partner_link_url": { + "type": "string", + "maxLength": 512 + }, + "partner_image_url": { + "type": "string", + "maxLength": 512 + }, + "created_by": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maxLength": 10 + }, + "updated_by": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maxLength": 10 + }, + "created_at": { + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date-time" + }, + "timezone_type": { + "type": "integer", + "format": "int32" + }, + "timezone": { + "type": "string" + } + } + }, + "updated_at": { + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date-time" + }, + "timezone_type": { + "type": "integer", + "format": "int32" + }, + "timezone": { + "type": "string" + } + } + }, + "feed_url": { + "type": "string" + } + } + }, + "Podcasts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Podcast" + } + }, + "Error": { + "type": "object", + "properties": { + "status": { + "type": "integer", + "format": "int32" + }, + "error": { + "type": "integer", + "format": "int32" + }, + "messages": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } +} diff --git a/modules/Api/Rest/V1/schema.yaml b/modules/Api/Rest/V1/schema.yaml deleted file mode 100644 index 9c7a0220..00000000 --- a/modules/Api/Rest/V1/schema.yaml +++ /dev/null @@ -1,530 +0,0 @@ -openapi: 3.1.0 -info: - version: 1.0.0 - title: Castopod API - description: |- - The Castopod API offers you a programmatic way to integrate your Podcasts and - Episodes in your apps and help you automate creation and publishing. - - ⚠️ **The API is disabled by default.** - - You may add the following feature flag in your `.env` to activate it: - - ```ini - restapi.enabled=true - ``` - - Operations to add or publish episodes require you to setup basic authentication - in your `.env`: - - ```ini - restapi.basicAuth=true - restapi.basicAuthUsername="YOUR_BASIC_AUTH_USERNAME" - restapi.basicAuthPassword="YOUR_BASIC_AUTH_PASSWORD" - ``` - - With BasicAuth enabled, your requests must include the `Authorization` header - with the username and password you have set previously: - - ``` - "Authorization": "Basic username:password" - ``` - - license: - name: AGPL v3 - url: https://code.castopod.org/adaures/castopod/-/blob/develop/LICENSE.md -paths: - /podcasts: - get: - summary: Get all podcasts - operationId: get-all-podcasts - responses: - "200": - description: Successful operation - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/Podcast" - default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - /podcasts/{podcastId}: - parameters: - - name: podcastId - in: path - description: The id of the podcast to retrieve - required: true - schema: - type: integer - format: int64 - get: - summary: Get podcast by ID - description: Returns a single podcast - operationId: get-podcast-by-id - responses: - "200": - description: Successful operation - content: - application/json: - schema: - $ref: "#/components/schemas/Podcast" - default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - /episodes: - get: - summary: Get all episodes - operationId: get-all-episodes - responses: - "200": - description: Object of episodes - content: - application/json: - schema: - type: "array" - items: - $ref: "#/components/schemas/Episode" - default: - description: Unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - post: - summary: Add a new episode - operationId: add-episode - requestBody: - description: Episode object that needs to be added - required: true - content: - multipart/form-data: - schema: - $ref: "#/components/schemas/EpisodeCreateRequest" - responses: - "201": - description: Episode created successfully - content: - application/json: - schema: - $ref: "#/components/schemas/Episode" - default: - description: Unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - /episodes/{episodeId}: - parameters: - - name: episodeId - in: path - description: The id of the episode to retrieve - required: true - schema: - type: integer - format: int64 - get: - summary: Get episode by ID - description: Returns a single episode - operationId: get-episode-by-id - responses: - "200": - description: Expected response to a valid request - content: - application/json: - schema: - $ref: "#/components/schemas/Episode" - default: - description: Unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" - /episodes/{episodeId}/publish: - post: - summary: Publish an episode - operationId: publish-episode - parameters: - - name: episodeId - in: path - description: The id of the episode to publish - required: true - schema: - type: integer - format: int64 - requestBody: - description: Publish parameters - required: true - content: - multipart/form-data: - schema: - $ref: "#/components/schemas/EpisodePublishRequest" - responses: - "200": - description: Successful operation - content: - application/json: - schema: - $ref: "#/components/schemas/Episode" - default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" -components: - schemas: - Podcast: - type: object - required: - - id - - guid - - actor_id - - handle - - title - - description_markdown - - description_html - - cover_id - - language_code - - category_id - - owner_name - - owner_email - - type - - is_blocked - - is_completed - - is_locked - - is_published_on_hubs - - created_by - - updated_by - - created_at - - updated_at - - feed_url - properties: - id: - type: integer - format: int64 - guid: - type: string - maxLength: 36 - actor_id: - type: integer - format: int64 - handle: - type: string - maxLength: 32 - title: - type: string - maxLength: 128 - description_markdown: - type: string - description_html: - type: string - cover_id: - type: integer - format: int64 - banner_id: - type: integer - format: int64 - language_code: - type: string - maxLength: 2 - category_id: - type: integer - format: int64 - minimum: 1 - parental_advisory: - type: string - enum: - - clean - - explicit - owner_name: - type: string - maxLength: 128 - owner_email: - type: string - maxLength: 255 - publisher: - type: string - maxLength: 128 - type: - type: string - enum: - - episodic - - serial - copyright: - type: string - maxLength: 128 - episode_description_footer_markdown: - type: string - episode_description_footer_html: - type: string - is_blocked: - type: integer - format: int32 - enum: - - 0 - - 1 - is_completed: - type: integer - format: int32 - enum: - - 0 - - 1 - is_locked: - type: integer - format: int32 - enum: - - 0 - - 1 - imported_feed_url: - type: string - maxLength: 512 - new_feed_url: - type: string - maxLength: 512 - location_name: - type: string - maxLength: 128 - location_geo: - type: string - maxLength: 32 - location_osm: - type: string - maxLength: 12 - custom_rss: - type: string - is_published_on_hubs: - type: integer - format: int32 - enum: - - 0 - - 1 - partner_id: - type: string - maxLength: 32 - partner_link_url: - type: string - maxLength: 512 - partner_image_url: - type: string - maxLength: 512 - created_by: - type: integer - format: int64 - updated_by: - type: integer - format: int64 - created_at: - type: object - properties: - date: - type: string - format: date-time - timezone_type: - type: integer - format: int32 - timezone: - type: string - updated_at: - type: object - properties: - date: - type: string - format: date-time - timezone_type: - type: integer - format: int32 - timezone: - type: string - feed_url: - type: string - Episode: - type: object - required: - - id - - title - - slug - - podcast_id - - created_by - - updated_by - - created_at - - updated_at - properties: - id: - type: integer - format: int64 - title: - type: string - slug: - type: string - podcast_id: - type: integer - format: int64 - description_markdown: - type: string - description_html: - type: string - audio_url: - type: string - format: uri - cover_url: - type: string - format: uri - duration: - type: integer - format: int32 - published_at: - type: string - format: date-time - created_by: - type: integer - format: int64 - updated_by: - type: integer - format: int64 - EpisodeCreateRequest: - type: object - required: - - user_id - - updated_by - - title - - slug - - podcast_id - - audio_file - properties: - user_id: - type: integer - format: int64 - description: ID of the user creating the episode - updated_by: - type: integer - format: int64 - description: ID of the user updating the episode - title: - type: string - description: Title of the episode - slug: - type: string - description: URL-friendly slug of the episode - podcast_id: - type: integer - format: int64 - description: ID of the podcast the episode belongs to - audio_file: - type: string - format: binary - description: Audio file for the episode - cover: - type: string - format: binary - description: Cover image for the episode - description: - type: string - description: Description of the episode - location_name: - type: string - description: Location associated with the episode - parental_advisory: - type: string - enum: - - clean - - explicit - description: Parental advisory rating - episode_number: - type: integer - format: int32 - description: Episode number (for serial podcasts) - season_number: - type: integer - format: int32 - description: Season number (for serial podcasts) - type: - type: string - enum: - - full - - trailer - - bonus - description: Type of episode - block: - type: string - enum: - - "yes" - - "no" - description: Block episode from being published - custom_rss: - type: string - description: Custom RSS content - premium: - type: string - enum: - - "yes" - - "no" - description: Mark episode as premium content - transcript-choice: - type: string - enum: - - upload-file - - remote-url - description: Transcript source choice - transcript_file: - type: string - format: binary - description: Transcript file - transcript_remote_url: - type: string - format: uri - description: Remote URL for transcript - chapters-choice: - type: string - enum: - - upload-file - - remote-url - description: Chapters source choice - chapters_file: - type: string - format: binary - description: Chapters file - chapters_remote_url: - type: string - format: uri - description: Remote URL for chapters - EpisodePublishRequest: - type: object - required: - - publication_method - properties: - publication_method: - type: string - enum: - - now - - schedule - - with_podcast - description: Method of publication - scheduled_publication_date: - type: string - format: date-time - description: Scheduled date and time for publication - client_timezone: - type: string - description: Timezone of the client - Error: - type: object - properties: - status: - type: integer - format: int32 - error: - type: integer - format: int32 - messages: - type: object - properties: - error: - type: string diff --git a/modules/Auth/Auth.php b/modules/Auth/Auth.php deleted file mode 100644 index 83403106..00000000 --- a/modules/Auth/Auth.php +++ /dev/null @@ -1,46 +0,0 @@ -routes($routes); - * - auth()->routes($routes, ['except' => ['login', 'register']]) - * - * @param array{except?:list} $config - */ - #[Override] - public function routes(RouteCollection &$routes, array $config = []): void - { - $authRoutes = config('AuthRoutes') - ->routes; - - $routes->group(config('Auth')->gateway, [ - 'namespace' => 'Modules\Auth\Controllers', - ], static function (RouteCollection $routes) use ($authRoutes, $config): void { - foreach ($authRoutes as $name => $row) { - if (! isset($config['except']) || ! in_array($name, $config['except'], true)) { - foreach ($row as $params) { - $options = isset($params[3]) - ? [ - 'as' => $params[3], - ] - : null; - $routes->{$params[0]}($params[1], $params[2], $options); - } - } - } - }); - } -} diff --git a/modules/Auth/Authorization/FlatAuthorization.php b/modules/Auth/Authorization/FlatAuthorization.php new file mode 100644 index 00000000..933a2728 --- /dev/null +++ b/modules/Auth/Authorization/FlatAuthorization.php @@ -0,0 +1,54 @@ +getPermissionID($permission); + + if (! is_numeric($permissionId)) { + return false; + } + + return $this->permissionModel->doesGroupHavePermission($groupId, $permissionId); + } + + /** + * Makes user part of given groups. + * + * @param array $groups Either collection of ID or names + */ + public function setUserGroups(int $userId, array $groups = []): bool + { + // remove user from all groups before resetting it in new groups + $this->groupModel->removeUserFromAllGroups($userId); + + if ($groups === []) { + return true; + } + + foreach ($groups as $group) { + $this->addUserToGroup($userId, $group); + } + + return true; + } +} diff --git a/modules/Auth/Authorization/GroupModel.php b/modules/Auth/Authorization/GroupModel.php new file mode 100644 index 00000000..74618542 --- /dev/null +++ b/modules/Auth/Authorization/GroupModel.php @@ -0,0 +1,30 @@ +select('auth_groups.*') + ->like('name', 'podcast_', 'after') + ->findAll(); + } + + /** + * @return mixed[] + */ + public function getUserRoles(): array + { + return $this->select('auth_groups.*') + ->notLike('name', 'podcast_', 'after') + ->findAll(); + } +} diff --git a/modules/Auth/Authorization/PermissionModel.php b/modules/Auth/Authorization/PermissionModel.php new file mode 100644 index 00000000..01106c10 --- /dev/null +++ b/modules/Auth/Authorization/PermissionModel.php @@ -0,0 +1,53 @@ +getPermissionsForGroup($groupId); + + return count($groupPerms) && + array_key_exists($permissionId, $groupPerms); + } + + /** + * Gets all permissions for a group in a way that can be easily used to check against: + * + * [ id => name, id => name ] + * + * @return array + */ + public function getPermissionsForGroup(int $groupId): array + { + $cacheName = "group{$groupId}_permissions"; + if (! ($found = cache($cacheName))) { + $groupPermissions = $this->db + ->table('auth_groups_permissions') + ->select('id, auth_permissions.name') + ->join('auth_permissions', 'auth_permissions.id = permission_id', 'inner') + ->where('group_id', $groupId) + ->get() + ->getResultObject(); + + $found = []; + foreach ($groupPermissions as $row) { + $found[$row->id] = strtolower($row->name); + } + + cache() + ->save($cacheName, $found, 300); + } + + return $found; + } +} diff --git a/modules/Auth/Commands/RolesDoc.php b/modules/Auth/Commands/RolesDoc.php deleted file mode 100644 index 84d7b941..00000000 --- a/modules/Auth/Commands/RolesDoc.php +++ /dev/null @@ -1,196 +0,0 @@ - - */ - private const array COMMENT_BLOCK_IDS = [ - 'instance_roles' => 'AUTH-INSTANCE-ROLES-LIST', - 'instance_permissions' => 'AUTH-INSTANCE-PERMISSIONS-LIST', - 'podcast_roles' => 'AUTH-PODCAST-ROLES-LIST', - 'podcast_permissions' => 'AUTH-PODCAST-PERMISSIONS-LIST', - ]; - - /** - * @var string - */ - protected $group = 'auth'; - - /** - * @var string - */ - protected $name = 'auth:generate-doc'; - - /** - * @var string - */ - protected $description = 'Generates the html table references for roles and permissions in the docs.'; - - #[Override] - public function run(array $params): void - { - // loop over all files in path - $files = glob(ROOTPATH . 'docs/src/content/docs/**/getting-started/auth.mdx'); - - if (! $files) { - $files = []; - } - - CLI::write(implode(PHP_EOL, $files)); - - if ($files === []) { - return; - } - - foreach ($files as $file) { - $locale = $this->detectLocaleFromPath($file); - service('language') - ->setLocale($locale); - - $authGroups = new AuthGroups(); - - $fileContents = file_get_contents($file); - - foreach (self::COMMENT_BLOCK_IDS as $key => $block_id) { - $pattern = '/(\{\/\*\s' . $block_id . ':START.*\*\/\})[\S\s]*(\{\/\*\s' . $block_id . ':END.*\*\/\})/'; - - $handleInjectMethod = 'handle' . str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $key))); - - $fileContents = $this->{$handleInjectMethod}($authGroups, $fileContents, $pattern); - } - - // Write the contents back to the file - file_put_contents($file, $fileContents); - } - } - - protected function handleInstanceRoles(AuthGroups $authGroups, string $fileContents, string $pattern): string - { - $instanceMatrix = $authGroups->matrix; - return $this->renderCommentBlock( - $fileContents, - $pattern, - ['role', 'description', 'permissions'], - $authGroups->instanceGroups, - static function ($table, $key, array $value) use ($instanceMatrix): void { - $table->addRow($value['title'], $value['description'], implode(', ', $instanceMatrix[$key])); - }, - ); - } - - protected function handleInstancePermissions(AuthGroups $authGroups, string $fileContents, string $pattern): string - { - return $this->renderCommentBlock( - $fileContents, - $pattern, - ['permission', 'description'], - $authGroups->instancePermissions, - static function ($table, $key, $value): void { - $table->addRow($key, $value); - }, - ); - } - - protected function handlePodcastRoles(AuthGroups $authGroups, string $fileContents, string $pattern): string - { - $podcastMatrix = $authGroups->podcastMatrix; - return $this->renderCommentBlock( - $fileContents, - $pattern, - ['role', 'description', 'permissions'], - $authGroups->podcastGroups, - static function ($table, $key, array $value) use ($podcastMatrix): void { - $table->addRow($value['title'], $value['description'], implode(', ', $podcastMatrix[$key])); - }, - ); - } - - protected function handlePodcastPermissions(AuthGroups $authGroups, string $fileContents, string $pattern): string - { - return $this->renderCommentBlock( - $fileContents, - $pattern, - ['permission', 'description'], - $authGroups->podcastPermissions, - static function ($table, $key, $value): void { - $table->addRow($key, $value); - }, - ); - } - - /** - * @param array $tableHeading - * @param array|array> $data - */ - private function renderCommentBlock( - string $fileContents, - string $pattern, - array $tableHeading, - array $data, - Closure $callback, - ): string { - // check if it has the start and end comments to insert roles table - // looking for and - - $hasInstanceInsertComments = preg_match($pattern, $fileContents); - - if (! $hasInstanceInsertComments) { - return $fileContents; - } - - // prepare role table - $table = new Table(); - $table->setHeading($tableHeading); - - foreach ($data as $key => $value) { - $callback($table, $key, $value); - } - - $converter = new HtmlConverter(); - $converter->getEnvironment() - ->addConverter(new TableConverter()); - $markdownTable = str_replace(['{', '}'], ['\{', '\}'], $converter->convert($table->generate())); - - // insert table between block comments - $newFileContents = preg_replace( - $pattern, - '${1}' . PHP_EOL . PHP_EOL . $markdownTable . PHP_EOL . PHP_EOL . '${2}', - $fileContents, - ); - - if ($newFileContents === null) { - return $fileContents; - } - - return $newFileContents; - } - - private function detectLocaleFromPath(string $fileKey): string - { - preg_match( - '~docs\/src\/content\/docs\/(?:([a-z]{2}(?:-[A-Za-z]{2,})?)\/)getting-started\/auth\.mdx~', - $fileKey, - $match, - ); - - if ($match === []) { - return 'en'; - } - - return $match[1]; - } -} diff --git a/modules/Auth/Config/Auth.php b/modules/Auth/Config/Auth.php index f5fc2c68..11ffea8a 100644 --- a/modules/Auth/Config/Auth.php +++ b/modules/Auth/Config/Auth.php @@ -4,114 +4,46 @@ declare(strict_types=1); namespace Modules\Auth\Config; -use CodeIgniter\Shield\Authentication\Actions\ActionInterface; -use CodeIgniter\Shield\Authentication\Actions\Email2FA; -use CodeIgniter\Shield\Authentication\AuthenticatorInterface; -use CodeIgniter\Shield\Config\Auth as ShieldAuth; -use CodeIgniter\Shield\Entities\User; -use Modules\Auth\Models\UserModel; -use Override; +use Myth\Auth\Config\Auth as MythAuthConfig; -class Auth extends ShieldAuth +class Auth extends MythAuthConfig { /** - * ////////////////// AUTHENTICATION ////////////////// + * -------------------------------------------------------------------------- + * Views used by Auth Controllers + * -------------------------------------------------------------------------- * * @var array */ - public array $views = [ - 'login' => 'login', - 'register' => 'register', - 'layout' => '_layout', - 'action_email_2fa' => 'email_2fa_show', - 'action_email_2fa_verify' => 'email_2fa_verify', - 'action_email_2fa_email' => 'emails/email_2fa_email', - 'action_email_activate_show' => 'email_activate_show', - 'action_email_activate_email' => 'emails/email_activate_email', - 'magic-link-login' => 'magic_link_form', - 'magic-link-message' => 'magic_link_message', - 'magic-link-email' => 'emails/magic_link_email', - 'magic-link-set-password' => 'magic_link_set_password', - 'welcome-email' => 'emails/welcome_email', + public $views = [ + 'login' => 'login', + 'register' => 'register', + 'forgot' => 'forgot', + 'reset' => 'reset', + 'emailForgot' => 'emails/forgot', + 'emailActivation' => 'emails/activation', ]; /** - * -------------------------------------------------------------------- - * Redirect urLs - * -------------------------------------------------------------------- - * The default URL that a user will be redirected to after - * various auth actions. If you need more flexibility you can - * override the `getUrl()` method to apply any logic you may need. + * -------------------------------------------------------------------------- + * Layout for the views to extend + * -------------------------------------------------------------------------- * - * @var array + * @var string */ - public array $redirects = [ - 'register' => '/', - 'login' => '/', - 'logout' => 'login', - 'force_reset' => '/', - 'permission_denied' => '/', - 'group_denied' => '/', - ]; + public $viewLayout = '_layout'; /** - * -------------------------------------------------------------------- - * Authentication Actions - * -------------------------------------------------------------------- - * Specifies the class that represents an action to take after - * the user logs in or registers a new account at the site. + * -------------------------------------------------------------------------- + * Allow User Registration + * -------------------------------------------------------------------------- + * When enabled (default) any unregistered user may apply for a new + * account. If you disable registration you may need to ensure your + * controllers and views know not to offer registration. * - * You must register actions in the order of the actions to be performed. - * - * Available actions with Shield: - * - register: 'CodeIgniter\Shield\Authentication\Actions\EmailActivator' - * - login: 'CodeIgniter\Shield\Authentication\Actions\Email2FA' - * - * @var array|null> + * @var bool */ - public array $actions = [ - 'register' => null, - 'login' => null, - ]; - - /** - * -------------------------------------------------------------------- - * Allow Registration - * -------------------------------------------------------------------- - * Determines whether users can register for the site. - */ - public bool $allowRegistration = false; - - /** - * -------------------------------------------------------------------- - * Allow Two-Factor Authentication - * -------------------------------------------------------------------- - * Determines whether email 2FA is enabled. - */ - public bool $enable2FA = false; - - /** - * -------------------------------------------------------------------- - * Welcome Link Lifetime - * -------------------------------------------------------------------- - * Specifies the amount of time, in seconds, that a welcome link is valid. - * You can use Time Constants or any desired number. - */ - public int $welcomeLinkLifetime = 48 * HOUR; - - /** - * -------------------------------------------------------------------- - * User Provider - * -------------------------------------------------------------------- - * The name of the class that handles user persistence. - * By default, this is the included UserModel, which - * works with any of the database engines supported by CodeIgniter. - * You can change it as long as they adhere to the - * CodeIgniter\Shield\Models\UserModel. - * - * @var class-string - */ - public string $userProvider = UserModel::class; + public $allowRegistration = false; /** * -------------------------------------------------------------------------- @@ -120,57 +52,4 @@ class Auth extends ShieldAuth * Defines a base route for all authentication related pages */ public string $gateway = 'cp-auth'; - - public function __construct() - { - parent::__construct(); - - $adminGateway = config('Admin') - ->gateway; - - $this->redirects = [ - 'register' => $adminGateway, - 'login' => $adminGateway, - 'logout' => $adminGateway, - 'force_reset' => $adminGateway, - 'permission_denied' => $adminGateway, - 'group_denied' => $adminGateway, - ]; - - // FIXME: enable2FA config can only be updated in the .env - // Using the settings service to have it set in the db causes infinite loop. - if ($this->enable2FA) { - $this->actions['login'] = Email2FA::class; - } - } - - /** - * Returns the URL that a user should be redirected to after a successful login. - * - * Redirects to the set-password form if magicLogin - */ - #[Override] - public function loginRedirect(): string - { - if (! session('magicLogin')) { - return $this->getUrl(setting('Auth.redirects')['login']); - } - - // activate user upon magic-link login as it is done via email - if (! auth()->user()->active) { - /** @var AuthenticatorInterface $authenticator */ - $authenticator = auth('session') - ->getAuthenticator(); - - $user = $authenticator->getUser(); - - if ($user instanceof User) { - // Set the user active now - $user->activate(); - } - } - - // prompt user to change their password - return $this->getUrl(route_to('magic-link-set-password')); - } } diff --git a/modules/Auth/Config/AuthGroups.php b/modules/Auth/Config/AuthGroups.php deleted file mode 100644 index 5bb64b88..00000000 --- a/modules/Auth/Config/AuthGroups.php +++ /dev/null @@ -1,290 +0,0 @@ -attempt($credentials); - * - * @var array> - */ - public array $groups = []; - - /** - * -------------------------------------------------------------------- - * Permissions - * -------------------------------------------------------------------- - * The available permissions in the system. Each system is defined - * where the key is the - * - * If a permission is not listed here it cannot be used. - * - * @var array - */ - public array $permissions = []; - - /** - * -------------------------------------------------------------------- - * Permissions Matrix - * -------------------------------------------------------------------- - * Maps permissions to groups. - * @var array> - */ - public array $matrix = []; - - /** - * @var array> - */ - public array $instanceGroups = []; - - /** - * @var array - */ - public array $instancePermissions = []; - - /** - * @var array> - */ - public array $podcastGroups = []; - - /** - * @var array - */ - public array $podcastPermissions = []; - - /** - * @var string[] - */ - public array $instanceBaseGroups = ['superadmin', 'manager', 'podcaster']; - - /** - * @var string[] - */ - public array $instanceBasePermissions = [ - 'admin.access', - 'admin.settings', - 'plugins.manage', - 'users.manage', - 'persons.manage', - 'pages.manage', - 'podcasts.view', - 'podcasts.create', - 'podcasts.import', - 'fediverse.manage-blocks', - ]; - - /** - * @var array> - */ - public array $instanceMatrix = [ - 'superadmin' => [ - 'admin.*', - 'plugins.*', - 'podcasts.*', - 'users.manage', - 'persons.manage', - 'pages.manage', - 'fediverse.manage-blocks', - ], - 'manager' => ['podcasts.create', 'podcasts.import', 'persons.manage', 'pages.manage'], - 'podcaster' => ['admin.access'], - ]; - - /** - * @var string[] - */ - public array $podcastBaseGroups = ['admin', 'editor', 'author', 'guest']; - - /** - * @var string[] - */ - public array $podcastBasePermissions = [ - 'view', - 'edit', - 'delete', - 'manage-import', - 'manage-persons', - 'manage-subscriptions', - 'manage-contributors', - 'manage-platforms', - 'manage-publications', - 'manage-notifications', - 'interact-as', - 'episodes.view', - 'episodes.create', - 'episodes.edit', - 'episodes.delete', - 'episodes.manage-persons', - 'episodes.manage-clips', - 'episodes.manage-publications', - 'episodes.manage-comments', - ]; - - /** - * @var array - */ - public array $podcastMatrix = [ - 'admin' => ['*'], - 'editor' => [ - 'view', - 'edit', - 'manage-import', - 'manage-persons', - 'manage-platforms', - 'manage-publications', - 'manage-notifications', - 'interact-as', - 'episodes.view', - 'episodes.create', - 'episodes.edit', - 'episodes.delete', - 'episodes.manage-persons', - 'episodes.manage-clips', - 'episodes.manage-publications', - 'episodes.manage-comments', - ], - 'author' => [ - 'view', - 'manage-persons', - 'episodes.view', - 'episodes.create', - 'episodes.edit', - 'episodes.manage-persons', - 'episodes.manage-clips', - ], - 'guest' => ['view', 'episodes.view'], - ]; - - /** - * Fill groups, permissions and matrix based on - */ - public function __construct() - { - parent::__construct(); - - foreach ($this->instanceBaseGroups as $group) { - $this->instanceGroups[$group] = [ - 'title' => lang("Auth.instance_groups.{$group}.title"), - 'description' => lang("Auth.instance_groups.{$group}.description"), - ]; - } - - $this->groups = $this->instanceGroups; - - foreach ($this->instanceBasePermissions as $permission) { - $this->instancePermissions[$permission] = lang("Auth.instance_permissions.{$permission}"); - $this->permissions[$permission] = lang("Auth.instance_permissions.{$permission}"); - } - - $this->matrix = $this->instanceMatrix; - - $this->generateBasePodcastAuthorizations(); - - /** - * For each podcast, include podcast groups, permissions, and matrix into $groups, $permissions, and $matrix - * attributes. - */ - $podcasts = new PodcastModel() - ->findAll(); - foreach ($podcasts as $podcast) { - $this->generatePodcastAuthorizations($podcast->id); - } - } - - public function generateBasePodcastAuthorizations(): void - { - foreach ($this->podcastBaseGroups as $group) { - $this->podcastGroups[$group] = [ - 'title' => lang("Auth.podcast_groups.{$group}.title", [ - 'id' => '{id}', - ]), - 'description' => lang("Auth.podcast_groups.{$group}.description", [ - 'id' => '{id}', - ]), - ]; - } - - foreach ($this->podcastBasePermissions as $permission) { - $this->podcastPermissions[$permission] = lang("Auth.podcast_permissions.{$permission}", [ - 'id' => '{id}', - ]); - $this->permissions[$permission] = lang("Auth.podcast_permissions.{$permission}", [ - 'id' => '{id}', - ]); - } - } - - public function generatePodcastAuthorizations(int $podcastId): void - { - foreach ($this->podcastBaseGroups as $group) { - $podcastGroup = 'podcast#' . $podcastId . '-' . $group; - $this->groups[$podcastGroup] = [ - 'title' => lang("Auth.podcast_groups.{$group}.title", [ - 'id' => $podcastId, - ]), - 'description' => lang("Auth.podcast_groups.{$group}.description", [ - 'id' => $podcastId, - ]), - ]; - } - - foreach ($this->podcastBasePermissions as $permission) { - $podcastPermission = 'podcast#' . $podcastId . '.' . $permission; - $this->permissions[$podcastPermission] = lang("Auth.podcast_permissions.{$permission}", [ - 'id' => $podcastId, - ]); - } - - foreach ($this->podcastMatrix as $group => $permissionWildcards) { - $podcastGroup = 'podcast#' . $podcastId . '-' . $group; - foreach ($permissionWildcards as $permissionWildcard) { - $podcastPermissionWildcard = 'podcast#' . $podcastId . '.' . $permissionWildcard; - $this->matrix[$podcastGroup][] = $podcastPermissionWildcard; - } - } - } -} diff --git a/modules/Auth/Config/AuthRoutes.php b/modules/Auth/Config/AuthRoutes.php deleted file mode 100644 index 8e7540a2..00000000 --- a/modules/Auth/Config/AuthRoutes.php +++ /dev/null @@ -1,45 +0,0 @@ ->> - */ - public array $routes = [ - 'register' => [ - ['get', 'register', 'RegisterController::registerView', 'register'], - ['post', 'register', 'RegisterController::registerAction'], - ], - 'login' => [ - ['get', 'login', 'LoginController::loginView', 'login'], - ['post', 'login', 'LoginController::loginAction'], - ], - 'magic-link' => [ - [ - 'get', - 'login/magic-link', - 'MagicLinkController::loginView', - 'magic-link', // Route name - ], - ['post', 'login/magic-link', 'MagicLinkController::loginAction'], - [ - 'get', - 'login/verify-magic-link', - 'MagicLinkController::verify', - 'verify-magic-link', // Route name - ], - ], - 'logout' => [['get', 'logout', 'LoginController::logoutAction', 'logout']], - 'auth-actions' => [ - ['get', 'auth/a/show', 'ActionController::show', 'auth-action-show'], - ['post', 'auth/a/handle', 'ActionController::handle', 'auth-action-handle'], - ['post', 'auth/a/verify', 'ActionController::verify', 'auth-action-verify'], - ], - ]; -} diff --git a/modules/Auth/Config/AuthToken.php b/modules/Auth/Config/AuthToken.php deleted file mode 100644 index 4f56dc76..00000000 --- a/modules/Auth/Config/AuthToken.php +++ /dev/null @@ -1,123 +0,0 @@ - - */ - public array $authenticatorHeader = [ - 'tokens' => 'Authorization', - 'hmac' => 'Authorization', - ]; - - /** - * -------------------------------------------------------------------- - * Unused Token Lifetime - * -------------------------------------------------------------------- - * Determines the amount of time, in seconds, that an unused token can - * be used. - */ - public int $unusedTokenLifetime = YEAR; - - /** - * -------------------------------------------------------------------- - * HMAC secret key byte size - * -------------------------------------------------------------------- - * Specify in integer the desired byte size of the - * HMAC SHA256 byte size - */ - public int $hmacSecretKeyByteSize = 32; - - /** - * -------------------------------------------------------------------- - * HMAC encryption Keys - * -------------------------------------------------------------------- - * This sets the key to be used when encrypting a user's HMAC Secret Key. - * - * 'keys' is an array of keys which will facilitate key rotation. Valid - * keyTitles must include only [a-zA-Z0-9_] and should be kept to a - * max of 8 characters. - * - * Each keyTitle is an associative array containing the required 'key' - * value, and the optional 'driver' and 'digest' values. If the - * 'driver' and 'digest' values are not specified, the default 'driver' - * and 'digest' values will be used. - * - * Old keys will are used to decrypt existing Secret Keys. It is encouraged - * to run 'php spark shield:hmac reencrypt' to update existing Secret - * Key encryptions. - * - * @see https://codeigniter.com/user_guide/libraries/encryption.html - * - * @var array|string - * - * NOTE: The value becomes temporarily a string when setting value as JSON - * from environment variable. - * - * [key_name => ['key' => key_value]] - * or [key_name => ['key' => key_value, 'driver' => driver, 'digest' => digest]] - */ - public $hmacEncryptionKeys = [ - 'k1' => [ - 'key' => '', - ], - ]; - - /** - * -------------------------------------------------------------------- - * HMAC Current Encryption Key Selector - * -------------------------------------------------------------------- - * This specifies which of the encryption keys should be used. - */ - public string $hmacEncryptionCurrentKey = 'k1'; - - /** - * -------------------------------------------------------------------- - * HMAC Encryption Key Driver - * -------------------------------------------------------------------- - * This specifies which of the encryption drivers should be used. - * - * Available drivers: - * - OpenSSL - * - Sodium - */ - public string $hmacEncryptionDefaultDriver = 'OpenSSL'; - - /** - * -------------------------------------------------------------------- - * HMAC Encryption Key Driver - * -------------------------------------------------------------------- - * THis specifies the type of encryption to be used. - * e.g. 'SHA512' or 'SHA256'. - */ - public string $hmacEncryptionDefaultDigest = 'SHA512'; -} diff --git a/modules/Auth/Config/Events.php b/modules/Auth/Config/Events.php deleted file mode 100644 index 36b0cf2a..00000000 --- a/modules/Auth/Config/Events.php +++ /dev/null @@ -1,14 +0,0 @@ -routes($routes); - -// Admin routes for users and podcast contributors +/** + * Overwriting Myth:auth routes file + */ $routes->group( - config('Admin') + config('Auth') ->gateway, [ 'namespace' => 'Modules\Auth\Controllers', ], static function ($routes): void { - $routes->get('magic-link-set-password', 'MagicLinkController::setPasswordView', [ - 'as' => 'magic-link-set-password', + // Login/out + $routes->get('login', 'AuthController::login', [ + 'as' => 'login', ]); - $routes->post('magic-link-set-password', 'MagicLinkController::setPasswordAction'); - - $routes->post('interact-as-actor', 'InteractController::interactAsActorAction', [ + $routes->post('login', 'AuthController::attemptLogin'); + $routes->get('logout', 'AuthController::logout', [ + 'as' => 'logout', + ]); + // Registration + $routes->get('register', 'AuthController::register', [ + 'as' => 'register', + ]); + $routes->post('register', 'AuthController::attemptRegister'); + // Activation + $routes->get('activate-account', 'AuthController::activateAccount', [ + 'as' => 'activate-account', + ]); + $routes->get( + 'resend-activate-account', + 'AuthController::resendActivateAccount', + [ + 'as' => 'resend-activate-account', + ], + ); + // Forgot/Resets + $routes->get('forgot', 'AuthController::forgotPassword', [ + 'as' => 'forgot', + ]); + $routes->post('forgot', 'AuthController::attemptForgot'); + $routes->get('reset-password', 'AuthController::resetPassword', [ + 'as' => 'reset-password', + ]); + $routes->post('reset-password', 'AuthController::attemptReset'); + // interacting as an actor + $routes->post('interact-as-actor', 'AuthController::attemptInteractAsActor', [ 'as' => 'interact-as-actor', ]); - - // Users - $routes->group('users', static function ($routes): void { - $routes->get('/', 'UserController::list', [ - 'as' => 'user-list', - 'filter' => 'permission:users.manage', - ]); - $routes->get('new', 'UserController::createView', [ - 'as' => 'user-create', - 'filter' => 'permission:users.manage', - ]); - $routes->post('new', 'UserController::createAction', [ - 'filter' => 'permission:users.manage', - ]); - // User - $routes->group('(:num)', static function ($routes): void { - $routes->get('/', 'UserController::view/$1', [ - 'as' => 'user-view', - 'filter' => 'permission:users.manage', - ]); - $routes->get('edit', 'UserController::editView/$1', [ - 'as' => 'user-edit', - 'filter' => 'permission:users.manage', - ]); - $routes->post('edit', 'UserController::editAction/$1', [ - 'filter' => 'permission:users.manage', - ]); - $routes->get('delete', 'UserController::delete/$1', [ - 'as' => 'user-delete', - 'filter' => 'permission:users.manage', - ]); - $routes->post('delete', 'UserController::deleteAction/$1', [ - 'as' => 'user-delete', - 'filter' => 'permission:users.manage', - ]); - }); - }); - // My account - $routes->group('my-account', static function ($routes): void { - $routes->get('/', 'MyAccountController', [ - 'as' => 'my-account', - ]); - $routes->get('change-password', 'MyAccountController::changePassword', [ - 'as' => 'change-password', - ],); - $routes->post('change-password', 'MyAccountController::changeAction'); - }); - - // Podcast contributors - $routes->group('podcasts/(:num)/contributors', static function ($routes): void { - $routes->get('/', 'ContributorController::list/$1', [ - 'as' => 'contributor-list', - 'filter' => 'permission:podcast$1.manage-contributors', - ]); - $routes->get('add', 'ContributorController::createView/$1', [ - 'as' => 'contributor-add', - 'filter' => 'permission:podcast$1.manage-contributors', - ]); - $routes->post( - 'add', - 'ContributorController::createAction/$1', - [ - 'filter' => 'permission:podcast$1.manage-contributors', - ], - ); - // Contributor - $routes->group('(:num)', static function ($routes): void { - $routes->get('/', 'ContributorController::view/$1/$2', [ - 'as' => 'contributor-view', - 'filter' => 'permission:podcast$1.manage-contributors', - ]); - $routes->get( - 'edit', - 'ContributorController::editView/$1/$2', - [ - 'as' => 'contributor-edit', - 'filter' => 'permission:podcast$1.manage-contributors', - ], - ); - $routes->post( - 'edit', - 'ContributorController::editAction/$1/$2', - [ - 'filter' => 'permission:podcast$1.manage-contributors', - ], - ); - $routes->get( - 'remove', - 'ContributorController::removeView/$1/$2', - [ - 'as' => 'contributor-remove', - 'filter' => 'permission:podcast$1.manage-contributors', - ], - ); - $routes->post( - 'remove', - 'ContributorController::removeAction/$1/$2', - [ - 'filter' => 'permission:podcast$1.manage-contributors', - ], - ); - }); - }); - }, + } ); diff --git a/modules/Auth/Config/Services.php b/modules/Auth/Config/Services.php index 1ef66bae..71b8129c 100644 --- a/modules/Auth/Config/Services.php +++ b/modules/Auth/Config/Services.php @@ -4,23 +4,87 @@ declare(strict_types=1); namespace Modules\Auth\Config; -use Config\Services as BaseService; -use Modules\Auth\Auth; +use App\Models\UserModel; +use CodeIgniter\Config\BaseService; +use CodeIgniter\Model; +use Modules\Auth\Authorization\FlatAuthorization; +use Modules\Auth\Authorization\GroupModel; +use Modules\Auth\Authorization\PermissionModel; +use Myth\Auth\Models\LoginModel; +/** + * Services Configuration file. + * + * Services are simply other classes/libraries that the system uses to do its job. This is used by CodeIgniter to allow + * the core of the framework to be swapped out easily without affecting the usage within the rest of your application. + * + * This file holds any application-specific services, or service overrides that you might need. An example has been + * included with the general method format you should use for your service methods. For more examples, see the core + * Services file at system/Config/Services.php. + */ class Services extends BaseService { /** - * The base auth class + * @return mixed */ - public static function auth(bool $getShared = true): Auth - { + public static function authentication( + string $lib = 'local', + Model $userModel = null, + Model $loginModel = null, + bool $getShared = true + ) { if ($getShared) { - /** @var Auth */ - return self::getSharedInstance('auth'); + return self::getSharedInstance('authentication', $lib, $userModel, $loginModel); } + // config() checks first in app/Config $config = config('Auth'); - return new Auth($config); + $class = $config->authenticationLibs[$lib]; + + $instance = new $class($config); + + if ($userModel === null) { + $userModel = new UserModel(); + } + + if ($loginModel === null) { + $loginModel = new LoginModel(); + } + + return $instance->setUserModel($userModel) + ->setLoginModel($loginModel); + } + + /** + * @return mixed|$this + */ + public static function authorization( + Model $groupModel = null, + Model $permissionModel = null, + Model $userModel = null, + bool $getShared = true + ) { + if ($getShared) { + return self::getSharedInstance('authorization', $groupModel, $permissionModel, $userModel); + } + + if ($groupModel === null) { + $groupModel = new GroupModel(); + } + + if ($permissionModel === null) { + $permissionModel = new PermissionModel(); + } + + /* @phpstan-ignore-next-line */ + $instance = new FlatAuthorization($groupModel, $permissionModel); + + if ($userModel === null) { + $userModel = new UserModel(); + } + + /* @phpstan-ignore-next-line */ + return $instance->setUserModel($userModel); } } diff --git a/modules/Auth/Controllers/ActionController.php b/modules/Auth/Controllers/ActionController.php deleted file mode 100644 index 649005ee..00000000 --- a/modules/Auth/Controllers/ActionController.php +++ /dev/null @@ -1,29 +0,0 @@ -config->allowRegistration) { + return redirect() + ->back() + ->withInput() + ->with('error', lang('Auth.registerDisabled')); + } + + $users = model('UserModel'); + + // Validate here first, since some things, + // like the password, can only be validated properly here. + $rules = [ + 'username' => + 'required|alpha_numeric_space|min_length[3]|is_unique[users.username]', + 'email' => 'required|valid_email|is_unique[users.email]', + 'password' => 'required|strong_password', + ]; + + if (! $this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', service('validation')->getErrors()); + } + + // Save the user + $allowedPostFields = array_merge(['password'], $this->config->validFields, $this->config->personalFields); + $user = new User($this->request->getPost($allowedPostFields)); + + $this->config->requireActivation === null + ? $user->activate() + : $user->generateActivateHash(); + + // Ensure default group gets assigned if set + if ($this->config->defaultUserGroup !== null) { + $users = $users->withGroup($this->config->defaultUserGroup); + } + + if (! $users->save($user)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $users->errors()); + } + + if ($this->config->requireActivation !== null) { + $activator = service('activator'); + $sent = $activator->send($user); + + if (! $sent) { + return redirect() + ->back() + ->withInput() + ->with('error', $activator->error() ?? lang('Auth.unknownError')); + } + + // Success! + return redirect() + ->route('login') + ->with('message', lang('Auth.activationSuccess')); + } + + // Success! + return redirect() + ->route('login') + ->with('message', lang('Auth.registerSuccess')); + } + + /** + * Verifies the code with the email and saves the new password, if they all pass validation. + */ + public function attemptReset(): RedirectResponse + { + if ($this->config->activeResetter === null) { + return redirect() + ->route('login') + ->with('error', lang('Auth.forgotDisabled')); + } + + $users = model('UserModel'); + + // First things first - log the reset attempt. + $users->logResetAttempt( + $this->request->getPost('email'), + $this->request->getPost('token'), + $this->request->getIPAddress(), + (string) $this->request->getUserAgent(), + ); + + $rules = [ + 'token' => 'required', + 'email' => 'required|valid_email', + 'password' => 'required|strong_password', + ]; + + if (! $this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', $users->errors()); + } + + $user = $users + ->where('email', $this->request->getPost('email')) + ->where('reset_hash', $this->request->getPost('token')) + ->first(); + + if ($user === null) { + return redirect() + ->back() + ->with('error', lang('Auth.forgotNoUser')); + } + + // Reset token still valid? + if ( + $user->reset_expires !== null && + time() > $user->reset_expires->getTimestamp() + ) { + return redirect() + ->back() + ->withInput() + ->with('error', lang('Auth.resetTokenExpired')); + } + + // Success! Save the new password, and cleanup the reset hash. + $user->password = $this->request->getPost('password'); + $user->reset_hash = null; + $user->reset_at = date('Y-m-d H:i:s'); + $user->reset_expires = null; + $user->force_pass_reset = false; + $users->save($user); + + helper('auth'); + + // set interact_as_actor_id value + $userPodcasts = $user->podcasts; + if ($userPodcasts = $user->podcasts) { + set_interact_as_actor($userPodcasts[0]->actor_id); + } + + return redirect() + ->route('login') + ->with('message', lang('Auth.resetSuccess')); + } + + public function attemptInteractAsActor(): RedirectResponse + { + $rules = [ + 'actor_id' => 'required|numeric', + ]; + + if (! $this->validate($rules)) { + return redirect() + ->back() + ->withInput() + ->with('errors', service('validation')->getErrors()); + } + + helper('auth'); + + set_interact_as_actor((int) $this->request->getPost('actor_id')); + + return redirect()->back(); + } +} diff --git a/modules/Auth/Controllers/ContributorController.php b/modules/Auth/Controllers/ContributorController.php deleted file mode 100644 index 119703bf..00000000 --- a/modules/Auth/Controllers/ContributorController.php +++ /dev/null @@ -1,266 +0,0 @@ -getPodcastById((int) $params[0])) instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - $this->podcast = $podcast; - - if (count($params) <= 1) { - return $this->{$method}(); - } - - if (($this->contributor = new UserModel()->getPodcastContributor( - (int) $params[1], - (int) $params[0], - )) instanceof User) { - return $this->{$method}(); - } - - throw PageNotFoundException::forPageNotFound(); - } - - public function list(): string - { - $data = [ - 'podcast' => $this->podcast, - ]; - - $this->setHtmlHead(lang('Contributor.podcast_contributors')); - replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, - ]); - return view('contributor/list', $data); - } - - public function view(): string - { - $data = [ - 'podcast' => $this->podcast, - 'contributor' => new UserModel() - ->getPodcastContributor($this->contributor->id, $this->podcast->id), - ]; - - $this->setHtmlHead(lang('Contributor.view', [ - 'username' => esc($this->contributor->username), - 'podcastTitle' => esc($this->podcast->title), - ])); - replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, - 1 => $this->contributor->username, - ]); - return view('contributor/view', $data); - } - - public function createView(): string - { - helper('form'); - - $users = new UserModel() - ->findAll(); - $contributorOptions = array_reduce( - $users, - static function (array $result, User $user): array { - $result[] = [ - 'value' => $user->id, - 'label' => $user->username, - ]; - return $result; - }, - [], - ); - - $roles = setting('AuthGroups.podcastBaseGroups'); - $roleOptions = []; - array_walk( - $roles, - static function (string $role, $key) use (&$roleOptions): array { - $roleOptions[] = [ - 'value' => $role, - 'label' => lang('Auth.podcast_groups.' . $role . '.title'), - ]; - return $roleOptions; - }, - [], - ); - - $data = [ - 'podcast' => $this->podcast, - 'contributorOptions' => $contributorOptions, - 'roleOptions' => $roleOptions, - ]; - - $this->setHtmlHead(lang('Contributor.add_contributor', [esc($this->podcast->title)])); - replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, - ]); - return view('contributor/create', $data); - } - - public function createAction(): RedirectResponse - { - /** @var User $user */ - $user = new UserModel() - ->find((int) $this->request->getPost('user')); - - if (get_podcast_group($user, $this->podcast->id)) { - return redirect() - ->back() - ->withInput() - ->with('errors', [lang('Contributor.messages.alreadyAddedError')]); - } - - add_podcast_group($user, $this->podcast->id, $this->request->getPost('role')); - - return redirect()->route('contributor-list', [$this->podcast->id]); - } - - public function editView(): string|RedirectResponse - { - helper('form'); - - $roles = setting('AuthGroups.podcastBaseGroups'); - $roleOptions = []; - array_walk( - $roles, - static function (string $role) use (&$roleOptions): array { - $roleOptions[] = [ - 'value' => $role, - 'label' => lang('Auth.podcast_groups.' . $role . '.title'), - ]; - return $roleOptions; - }, - [], - ); - - $contributorGroup = get_podcast_group($this->contributor, $this->podcast->id); - - if ($contributorGroup === null) { - return redirect() - ->back() - ->withInput() - ->with('errors', [lang('Contributor.messages.notAddedError')]); - } - - $data = [ - 'podcast' => $this->podcast, - 'contributor' => $this->contributor, - 'contributorGroup' => $contributorGroup, - 'roleOptions' => $roleOptions, - ]; - - $this->setHtmlHead(lang('Contributor.edit_role', [esc($this->contributor->username)])); - replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, - 1 => $this->contributor->username, - ]); - return view('contributor/edit', $data); - } - - public function editAction(): RedirectResponse - { - // forbid updating a podcast owner - if ($this->podcast->created_by === $this->contributor->id) { - return redirect() - ->back() - ->with('errors', [lang('Contributor.messages.editOwnerError')]); - } - - $group = $this->request->getPost('role'); - - set_podcast_group($this->contributor, $this->podcast->id, $group); - - cache() - ->delete("podcast#{$this->podcast->id}_contributors"); - - return redirect()->route('contributor-list', [$this->podcast->id])->with( - 'message', - lang('Contributor.messages.editSuccess'), - ); - } - - public function removeView(): string - { - helper('form'); - - $data = [ - 'podcast' => $this->podcast, - 'contributor' => $this->contributor, - ]; - - $this->setHtmlHead(lang('Contributor.delete_form.title', [ - 'contributor' => $this->contributor->username, - ])); - replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, - 1 => $this->contributor->username, - ]); - return view('contributor/remove', $data); - } - - public function removeAction(): RedirectResponse - { - if ($this->podcast->created_by === $this->contributor->id) { - return redirect() - ->back() - ->with('errors', [lang('Contributor.messages.removeOwnerError')]); - } - - $rules = [ - 'understand' => 'required', - ]; - - if (! $this->validate($rules)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $this->validator->getErrors()); - } - - cache() - ->delete("podcast#{$this->podcast->id}_contributors"); - - // remove contributor from podcast group - $this->contributor->removeGroup(get_podcast_group($this->contributor, $this->podcast->id, false)); - - return redirect() - ->route('contributor-list', [$this->podcast->id]) - ->with( - 'message', - lang('Contributor.messages.removeSuccess', [ - 'username' => $this->contributor->username, - 'podcastTitle' => $this->podcast->title, - ]), - ); - } -} diff --git a/modules/Auth/Controllers/InteractController.php b/modules/Auth/Controllers/InteractController.php deleted file mode 100644 index d8281b62..00000000 --- a/modules/Auth/Controllers/InteractController.php +++ /dev/null @@ -1,36 +0,0 @@ - 'required|numeric', - ]; - - if (! $this->validate($rules)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $this->validator->getErrors()); - } - - $validData = $this->validator->getValidated(); - - helper('auth'); - - set_interact_as_actor((int) $validData['actor_id']); - - return redirect()->back(); - } -} diff --git a/modules/Auth/Controllers/LoginController.php b/modules/Auth/Controllers/LoginController.php deleted file mode 100644 index d4d7386e..00000000 --- a/modules/Auth/Controllers/LoginController.php +++ /dev/null @@ -1,26 +0,0 @@ -to(config('Auth')->loginRedirect()); - } - - return view(setting('Auth.views')['magic-link-set-password']); - } - - public function setPasswordAction(): RedirectResponse - { - $rules = [ - 'new_password' => 'required|strong_password', - ]; - - if (! $this->validate($rules)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $this->validator->getErrors()); - } - - $validData = $this->validator->getValidated(); - - $user = auth() - ->user(); - - if ($user instanceof User) { - // set new password to user - $user->password = $validData['new_password']; - - $userModel = auth() - ->getProvider(); - $userModel->save($user); - } - - // remove magic login session to reinstate normal check - if (session('magicLogin')) { - session()->removeTempdata('magicLogin'); - } - - // Success! - return redirect()->to(config('Auth')->loginRedirect()) - ->with('message', lang('MyAccount.messages.passwordChangeSuccess')); - } -} diff --git a/modules/Auth/Controllers/RegisterController.php b/modules/Auth/Controllers/RegisterController.php deleted file mode 100644 index 4a093f95..00000000 --- a/modules/Auth/Controllers/RegisterController.php +++ /dev/null @@ -1,29 +0,0 @@ -{$method}(); - } - - if (($this->user = new UserModel()->find($params[0])) instanceof User) { - return $this->{$method}(); - } - - throw PageNotFoundException::forPageNotFound(); - } - - public function list(): string - { - $data = [ - 'users' => new UserModel() - ->findAll(), - ]; - - $this->setHtmlHead(lang('User.all_users')); - return view('user/list', $data); - } - - public function view(): string - { - $data = [ - 'user' => $this->user, - ]; - - $this->setHtmlHead(lang('User.view', [ - 'username' => esc($this->user->username), - ])); - replace_breadcrumb_params([ - 0 => $this->user->username, - ]); - return view('user/view', $data); - } - - public function createView(): string - { - helper('form'); - - $roles = setting('AuthGroups.instanceGroups'); - $roleOptions = []; - array_walk( - $roles, - static function (array $role, $key) use (&$roleOptions): array { - $roleOptions[] = [ - 'value' => $key, - 'label' => $role['title'], - ]; - return $roleOptions; - }, - [], - ); - - $data = [ - 'roleOptions' => $roleOptions, - ]; - - $this->setHtmlHead(lang('User.create')); - return view('user/create', $data); - } - - /** - * Create the user with the provided username and email. The password is set as a random string and a magic link is - * sent to the user to allow them setting their password. - */ - public function createAction(): RedirectResponse - { - helper(['text', 'email']); - - $db = db_connect(); - $db->transStart(); - - $userModel = new UserModel(); - - // Save the user - $email = $this->request->getPost('email'); - $user = new User([ - 'username' => $this->request->getPost('username'), - 'email' => $email, - // set a random password - // user will be prompted to change it on first magic link login. - 'password' => random_string('alnum', 32), - ]); - try { - $userModel->save($user); - } catch (ValidationException) { - return redirect()->back() - ->withInput() - ->with('errors', $userModel->errors()); - } - - $user = $userModel->findById($userModel->getInsertID()); - $user->addGroup($this->request->getPost('role')); - - // **** SEND WELCOME LINK FOR FIRST LOGIN **** - - $identityModel = model('UserIdentityModel'); - - // Delete any previous magic-link identities - $identityModel->deleteIdentitiesByType($user, Session::ID_TYPE_MAGIC_LINK); - - // Generate the code and save it as an identity - $token = random_string('crypto', 20); - - $identityModel->insert([ - 'user_id' => $user->id, - 'type' => Session::ID_TYPE_MAGIC_LINK, - 'secret' => $token, - 'expires' => Time::now()->addSeconds(setting('Auth.welcomeLinkLifetime'))->format('Y-m-d H:i:s'), - ]); - - // Send the user an email with the code - $email = emailer() - ->setFrom(setting('Email.fromEmail'), setting('Email.fromName') ?? ''); - $email->setTo($user->email); - $email->setSubject(lang('Auth.welcomeSubject', [ - 'siteName' => setting('App.siteName'), - ])); - $email->setMessage(view(setting('Auth.views')['welcome-email'], [ - 'token' => $token, - ], [ - 'theme' => 'auth', - ])); - - if (! $email->send(false)) { - log_message('error', $email->printDebugger(['headers'])); - - return redirect()->back() - ->with('error', lang('Auth.unableSendEmailToUser', [$user->email])); - } - - // Clear the email - $email->clear(); - - $db->transComplete(); - - // Success! - return redirect() - ->route('user-list') - ->with('message', lang('User.messages.createSuccess', [ - 'username' => $user->username, - ])); - } - - public function editView(): string - { - helper('form'); - - $roles = setting('AuthGroups.instanceGroups'); - $roleOptions = []; - array_walk( - $roles, - static function (array $role, $key) use (&$roleOptions): array { - $roleOptions[] = [ - 'value' => $key, - 'label' => $role['title'], - ]; - return $roleOptions; - }, - [], - ); - - $data = [ - 'user' => $this->user, - 'roleOptions' => $roleOptions, - ]; - - $this->setHtmlHead(lang('User.edit_role', [ - 'username' => esc($this->user->username), - ])); - replace_breadcrumb_params([ - 0 => $this->user->username, - ]); - return view('user/edit', $data); - } - - public function editAction(): RedirectResponse - { - // The instance owner is a superadmin and the only user that cannot be demoted. - if ((bool) $this->user->is_owner) { - return redirect() - ->back() - ->with('errors', [ - lang('User.messages.editOwnerError', [ - 'username' => $this->user->username, - ]), - ]); - } - - $group = $this->request->getPost('role'); - - set_instance_group($this->user, $group); - - // Success! - return redirect() - ->route('user-list') - ->with('message', lang('User.messages.roleEditSuccess', [ - 'username' => $this->user->username, - ])); - } - - public function deleteView(): string - { - helper(['form']); - - $data = [ - 'user' => $this->user, - ]; - - $this->setHtmlHead(lang('User.delete_form.title', [ - 'user' => $this->user->username, - ])); - replace_breadcrumb_params([ - 0 => $this->user->username, - ]); - return view('user/delete', $data); - } - - public function deleteAction(): RedirectResponse - { - // You cannot delete the instance owner. - if ((bool) $this->user->is_owner) { - return redirect() - ->back() - ->with('errors', [ - lang('User.messages.deleteOwnerError', [ - 'username' => $this->user->username, - ]), - ]); - } - - // You cannot delete a superadmin - // superadmin has to be demoted before being deleted - if ($this->user->inGroup(setting('AuthGroups.mostPowerfulPodcastGroup'))) { - return redirect() - ->back() - ->with('errors', [ - lang('User.messages.deleteSuperAdminError', [ - 'username' => $this->user->username, - ]), - ]); - } - - $rules = [ - 'understand' => 'required', - ]; - - if (! $this->validate($rules)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $this->validator->getErrors()); - } - - new UserModel() - ->delete($this->user->id, true); - - return redirect() - ->route('user-list') - ->with('message', lang('User.messages.deleteSuccess', [ - 'username' => $this->user->username, - ])); - } -} diff --git a/modules/Auth/Database/Migrations/2020-07-03-191500_add_podcasts_users.php b/modules/Auth/Database/Migrations/2020-07-03-191500_add_podcasts_users.php new file mode 100644 index 00000000..b6535c4a --- /dev/null +++ b/modules/Auth/Database/Migrations/2020-07-03-191500_add_podcasts_users.php @@ -0,0 +1,46 @@ +forge->addField([ + 'podcast_id' => [ + 'type' => 'INT', + 'unsigned' => true, + ], + 'user_id' => [ + 'type' => 'INT', + 'unsigned' => true, + ], + 'group_id' => [ + 'type' => 'INT', + 'unsigned' => true, + ], + ]); + $this->forge->addPrimaryKey(['user_id', 'podcast_id']); + $this->forge->addForeignKey('user_id', 'users', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('podcast_id', 'podcasts', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('group_id', 'auth_groups', 'id', '', 'CASCADE'); + $this->forge->createTable('podcasts_users'); + } + + public function down(): void + { + $this->forge->dropTable('podcasts_users'); + } +} diff --git a/modules/Auth/Database/Migrations/2020-12-29-100000_add_is_owner_to_users.php b/modules/Auth/Database/Migrations/2020-12-29-100000_add_is_owner_to_users.php deleted file mode 100644 index 7f0badee..00000000 --- a/modules/Auth/Database/Migrations/2020-12-29-100000_add_is_owner_to_users.php +++ /dev/null @@ -1,32 +0,0 @@ - [ - 'type' => 'TINYINT', - 'constraint' => 1, - 'default' => 0, - 'null' => false, - ], - ]; - - $this->forge->addColumn('users', $fields); - } - - #[Override] - public function down(): void - { - $fields = ['is_owner']; - $this->forge->dropColumn('users', $fields); - } -} diff --git a/plugins/.gitkeep b/modules/Auth/Database/Seeds/.gitkeep similarity index 100% rename from plugins/.gitkeep rename to modules/Auth/Database/Seeds/.gitkeep diff --git a/modules/Auth/Database/Seeds/AuthSeeder.php b/modules/Auth/Database/Seeds/AuthSeeder.php new file mode 100644 index 00000000..976c904b --- /dev/null +++ b/modules/Auth/Database/Seeds/AuthSeeder.php @@ -0,0 +1,302 @@ +[] + */ + protected array $groups = [ + [ + 'name' => 'superadmin', + 'description' => + 'Somebody who has access to all the castopod instance features', + ], + [ + 'name' => 'podcast_admin', + 'description' => + 'Somebody who has access to all the features within a given podcast', + ], + ]; + + /** + * Build permissions array as a list of: + * + * ``` context => [ [action, description], [action, description], ... ] ``` + * + * @var array[]> + */ + protected array $permissions = [ + 'users' => [ + [ + 'name' => 'create', + 'description' => 'Create a user', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'list', + 'description' => 'List all users', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'view', + 'description' => 'View any user info', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'manage_authorizations', + 'description' => 'Add or remove roles/permissions to a user', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'manage_bans', + 'description' => 'Ban / unban a user', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'force_pass_reset', + 'description' => + 'Force a user to update his password upon next login', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'delete', + 'description' => + 'Delete user without removing him from database', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'delete_permanently', + 'description' => + 'Delete all occurrences of a user from the database', + 'has_permission' => ['superadmin'], + ], + ], + 'pages' => [ + [ + 'name' => 'manage', + 'description' => 'List / create / edit / delete pages', + 'has_permission' => ['superadmin'], + ], + ], + 'podcasts' => [ + [ + 'name' => 'create', + 'description' => 'Add a new podcast', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'import', + 'description' => 'Import a new podcast from an external feed', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'list', + 'description' => 'List all podcasts and their episodes', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'view', + 'description' => 'View any podcast and their contributors list', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'delete', + 'description' => 'Delete any podcast from the database', + 'has_permission' => ['superadmin'], + ], + ], + 'episodes' => [ + [ + 'name' => 'list', + 'description' => 'List all episodes of any podcast', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'view', + 'description' => 'View any episode of any podcast', + 'has_permission' => ['superadmin'], + ], + ], + 'podcast' => [ + [ + 'name' => 'view', + 'description' => 'View a podcast', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'edit', + 'description' => 'Edit a podcast', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'manage_contributors', + 'description' => + 'Add / remove contributors to a podcast and edit their roles', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'manage_platforms', + 'description' => 'Set / remove platform links of a podcast', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'manage_publications', + 'description' => + 'Publish / unpublish episodes & posts of a podcast', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'interact_as', + 'description' => + 'Interact as the podcast to favourite / share or reply to posts.', + 'has_permission' => ['podcast_admin'], + ], + ], + 'podcast_episodes' => [ + [ + 'name' => 'list', + 'description' => 'List all episodes of a podcast', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'view', + 'description' => 'View any episode of a podcast', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'create', + 'description' => 'Add new episodes for a podcast', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'edit', + 'description' => 'Edit an episode of a podcast', + 'has_permission' => ['podcast_admin'], + ], + [ + 'name' => 'delete', + 'description' => + 'Delete all occurrences of an episode of a podcast from the database', + 'has_permission' => ['podcast_admin'], + ], + ], + 'person' => [ + [ + 'name' => 'create', + 'description' => 'Add a new person', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'list', + 'description' => 'List all persons', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'view', + 'description' => 'View any person', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'edit', + 'description' => 'Edit a person', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'delete', + 'description' => + 'Delete permanently any person from the database', + 'has_permission' => ['superadmin'], + ], + ], + 'fediverse' => [ + [ + 'name' => 'block_actors', + 'description' => + 'Block fediverse actors from interacting with the instance.', + 'has_permission' => ['superadmin'], + ], + [ + 'name' => 'block_domains', + 'description' => + 'Block fediverse domains from interacting with the instance.', + 'has_permission' => ['superadmin'], + ], + ], + ]; + + public function run(): void + { + $groupId = 0; + $dataGroups = []; + foreach ($this->groups as $group) { + $dataGroups[] = [ + 'id' => ++$groupId, + 'name' => $group['name'], + 'description' => $group['description'], + ]; + } + + // Map permissions to a format the `auth_permissions` table expects + $dataPermissions = []; + $dataGroupsPermissions = []; + $permissionId = 0; + foreach ($this->permissions as $context => $actions) { + foreach ($actions as $action) { + $dataPermissions[] = [ + 'id' => ++$permissionId, + 'name' => $context . '-' . $action['name'], + 'description' => $action['description'], + ]; + + foreach ($action['has_permission'] as $role) { + // link permission to specified groups + $dataGroupsPermissions[] = [ + 'group_id' => $this->getGroupIdByName($role, $dataGroups), + 'permission_id' => $permissionId, + ]; + } + } + } + + $this->db + ->table('auth_permissions') + ->ignore(true) + ->insertBatch($dataPermissions); + $this->db + ->table('auth_groups') + ->ignore(true) + ->insertBatch($dataGroups); + $this->db + ->table('auth_groups_permissions') + ->ignore(true) + ->insertBatch($dataGroupsPermissions); + } + + /** + * @param array[] $dataGroups + */ + public static function getGroupIdByName(string $name, array $dataGroups): ?int + { + foreach ($dataGroups as $group) { + if ($group['name'] === $name) { + return $group['id']; + } + } + + return null; + } +} diff --git a/modules/Auth/Entities/User.php b/modules/Auth/Entities/User.php new file mode 100644 index 00000000..312bde68 --- /dev/null +++ b/modules/Auth/Entities/User.php @@ -0,0 +1,109 @@ + + */ + protected $casts = [ + 'id' => 'integer', + 'active' => 'boolean', + 'force_pass_reset' => 'boolean', + 'podcast_id' => '?integer', + 'podcast_role' => '?string', + ]; + + public function getIsOwner(): bool + { + $firstUser = (new UserModel())->first(); + + if (! $firstUser instanceof self) { + return false; + } + + return $this->username === $firstUser->username; + } + + /** + * Returns the podcasts the user is contributing to + * + * @return Podcast[] + */ + public function getPodcasts(): array + { + if ($this->id === null) { + throw new RuntimeException('Users must be created before getting podcasts.'); + } + + if ($this->podcasts === null) { + $this->podcasts = (new PodcastModel())->getUserPodcasts($this->id); + } + + return $this->podcasts; + } + + /** + * Returns the ids of the user's actors that have unread notifications + * + * @return int[] + */ + public function getActorIdsWithUnreadNotifications(): array + { + if ($this->getPodcasts() === []) { + return []; + } + + $unreadNotifications = (new NotificationModel())->whereIn( + 'target_actor_id', + array_column($this->getPodcasts(), 'actor_id') + ) + ->where('read_at', null) + ->findAll(); + + return array_column($unreadNotifications, 'target_actor_id'); + } +} diff --git a/modules/Auth/Filters/PermissionFilter.php b/modules/Auth/Filters/PermissionFilter.php index 982e9f64..19824798 100644 --- a/modules/Auth/Filters/PermissionFilter.php +++ b/modules/Auth/Filters/PermissionFilter.php @@ -4,105 +4,96 @@ declare(strict_types=1); namespace Modules\Auth\Filters; -use App\Entities\Podcast; use App\Models\PodcastModel; use CodeIgniter\Filters\FilterInterface; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; -use Override; -use RuntimeException; +use Config\Services; +use Myth\Auth\Exceptions\PermissionException; -/** - * Permission Authorization Filter. - */ class PermissionFilter implements FilterInterface { /** - * @param string[]|null $arguments + * Do whatever processing this filter needs to do. By default it should not return anything during normal execution. + * However, when an abnormal state is found, it should return an instance of CodeIgniter\HTTP\Response. If it does, + * script execution will end and that Response will be sent back to the client, allowing for error pages, redirects, + * etc. * - * @return RequestInterface|ResponseInterface|string|null + * @param string[]|null $params + * @return void|mixed */ - #[Override] - public function before(RequestInterface $request, $arguments = null) + public function before(RequestInterface $request, $params = null) { - if ($arguments === null || $arguments === []) { - return null; + helper('auth'); + + if ($params === null) { + return; } - if (! auth()->loggedIn()) { - return redirect()->route('login'); + $authenticate = Services::authentication(); + + // if no user is logged in then send to the login form + if (! $authenticate->check()) { + session()->set('redirect_url', current_url()); + return redirect('login'); } - if ($this->isAuthorized($arguments)) { - return null; + helper('misc'); + $authorize = Services::authorization(); + $router = Services::router(); + $routerParams = $router->params(); + $result = false; + + // Check if user has at least one of the permissions + foreach ($params as $permission) { + // check if permission is for a specific podcast + if ( + (str_starts_with($permission, 'podcast-') || + str_starts_with($permission, 'podcast_episodes-')) && + $routerParams !== [] + ) { + if ( + ($groupId = (new PodcastModel())->getContributorGroupId( + $authenticate->id(), + $routerParams[0], + )) && + $authorize->groupHasPermission($permission, $groupId) + ) { + $result = true; + break; + } + } elseif ( + $authorize->hasPermission($permission, $authenticate->id()) + ) { + $result = true; + break; + } } - throw new RuntimeException(lang('Auth.notEnoughPrivilege'), 403); - } - - /** - * @param string[]|null $arguments - * - * @return ResponseInterface|null - */ - #[Override] - public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) - { - return null; - } - - /** - * Ensures the user is logged in and has one or more - * of the permissions as specified in the filter. - * - * @param string[] $arguments - */ - protected function isAuthorized(array $arguments): bool - { - $result = true; - - foreach ($arguments as $permission) { - // is permission specific to a podcast? - if (str_contains($permission, '$')) { - $router = service('router'); - $routerParams = $router->params(); - - if (! preg_match('/\$(\d+)\./', $permission, $match)) { - throw new RuntimeException(sprintf( - 'Could not get podcast identifier from permission %s', - $permission, - ), 1); - } - - $paramKey = ((int) $match[1]) - 1; - if (! array_key_exists($paramKey, $routerParams)) { - throw new RuntimeException(sprintf('Router param does not exist at key %s', $match[1]), 1); - } - - $podcastParam = $routerParams[$paramKey]; - - // get podcast id - $podcastId = null; - if (is_numeric($podcastParam)) { - $podcastId = (int) $podcastParam; - } else { - $podcast = new PodcastModel() - ->getPodcastByHandle($podcastParam); - if ($podcast instanceof Podcast) { - $podcastId = $podcast->id; - } - } - - if ($podcastId !== null) { - $permission = str_replace('$' . $match[1], '#' . $podcastId, $permission); - } + if (! $result) { + if ($authenticate->silent()) { + $redirectURL = session('redirect_url') ?? '/'; + unset($_SESSION['redirect_url']); + return redirect() + ->to($redirectURL) + ->with('error', lang('Auth.notEnoughPrivilege')); } - $result = $result && auth() - ->user() - ->can($permission); + throw new PermissionException(lang('Auth.notEnoughPrivilege')); } - - return $result; } + + //-------------------------------------------------------------------- + + /** + * Allows After filters to inspect and modify the response object as needed. This method does not allow any way to + * stop execution of other after filters, short of throwing an Exception or Error. + * + * @param string[]|null $arguments + */ + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void + { + } + + //-------------------------------------------------------------------- } diff --git a/modules/Auth/Helpers/auth_helper.php b/modules/Auth/Helpers/auth_helper.php deleted file mode 100644 index 36b6a075..00000000 --- a/modules/Auth/Helpers/auth_helper.php +++ /dev/null @@ -1,305 +0,0 @@ -setAuthenticator($alias); - } -} - -if (! function_exists('set_interact_as_actor')) { - /** - * Sets the actor id of which the user is acting as - */ - function set_interact_as_actor(int $actorId): void - { - if (auth()->loggedIn()) { - session() - ->set('interact_as_actor_id', $actorId); - } - } -} - -if (! function_exists('remove_interact_as_actor')) { - /** - * Removes the actor id of which the user is acting as - */ - function remove_interact_as_actor(): void - { - session()->remove('interact_as_actor_id'); - } -} - -if (! function_exists('interact_as_actor_id')) { - /** - * Sets the podcast id of which the user is acting as - */ - function interact_as_actor_id(): ?int - { - return session()->get('interact_as_actor_id'); - } -} - -if (! function_exists('interact_as_actor')) { - /** - * Get the actor the user is currently interacting as - */ - function interact_as_actor(): ?Actor - { - if (! auth()->loggedIn()) { - return null; - } - - $session = session(); - if (! $session->has('interact_as_actor_id')) { - return null; - } - - return model(ActorModel::class, false)->getActorById($session->get('interact_as_actor_id')); - } -} - -if (! function_exists('can_user_interact')) { - function can_user_interact(): bool - { - return (bool) interact_as_actor(); - } -} - -if (! function_exists('add_podcast_group')) { - function add_podcast_group(User $user, int $podcastId, string $group): User - { - $podcastGroup = 'podcast#' . $podcastId . '-' . $group; - - return $user->addGroup($podcastGroup); - } -} - -if (! function_exists('get_instance_group')) { - function get_instance_group(User $user): ?string - { - $instanceGroups = array_filter( - $user->getGroups() ?? [], - static fn ($group): bool => ! str_starts_with((string) $group, 'podcast#'), - ); - - if ($instanceGroups === []) { - return null; - } - - $instanceGroup = array_shift($instanceGroups); - - // Verify that a user belongs to one group only! - if ($instanceGroups !== []) { - // remove any other group the user belongs to - $user->removeGroup(...$instanceGroups); - } - - return $instanceGroup; - } -} - -if (! function_exists('set_instance_group')) { - function set_instance_group(User $user, string $group): User - { - // remove old instance group - if (get_instance_group($user)) { - $user->removeGroup(get_instance_group($user)); - } - - // set new group - return $user->addGroup($group); - } -} - -if (! function_exists('get_podcast_group')) { - function get_podcast_group(User $user, int $podcastId, bool $removePrefix = true): ?string - { - $podcastGroups = array_filter( - $user->getGroups() ?? [], - static fn ($group): bool => str_starts_with((string) $group, "podcast#{$podcastId}-"), - ); - - if ($podcastGroups === []) { - return null; - } - - $podcastGroup = array_shift($podcastGroups); - - // Verify that a user belongs to one group only! - if ($podcastGroups !== []) { - // remove any other group the user belongs to - $user->removeGroup(...$podcastGroups); - } - - if ($removePrefix) { - // strip the `podcast#{id}-` prefix when returning group - return substr((string) $podcastGroup, strlen('podcast#' . $podcastId . '-')); - } - - return $podcastGroup; - } -} - -if (! function_exists('set_podcast_group')) { - function set_podcast_group(User $user, int $podcastId, string $group): User - { - // remove old instance group - $user->removeGroup("podcast#{$podcastId}-" . get_podcast_group($user, $podcastId)); - - // set new group - return add_podcast_group($user, $podcastId, $group); - } -} - -if (! function_exists('get_podcast_groups')) { - /** - * @return string[] - */ - function get_user_podcast_ids(User $user): array - { - $podcastGroups = array_filter( - $user->getGroups() ?? [], - static fn ($group): bool => str_starts_with((string) $group, 'podcast#'), - ); - - $userPodcastIds = []; - // extract all podcast ids from groups - foreach ($podcastGroups as $podcastGroup) { - // extract podcast id from group and add it to the list of ids - preg_match('~podcast#(\d+)-[a-z]+~', (string) $podcastGroup, $matches); - $userPodcastIds[] = $matches[1]; - } - - return $userPodcastIds; - } -} - -if (! function_exists('can_podcast')) { - function can_podcast(User $user, int $podcastId, string $permission): bool - { - return $user->can('podcast#' . $podcastId . '.' . $permission); - } -} - -if (! function_exists('get_user_podcasts')) { - /** - * Returns the podcasts the user is contributing to - * - * @return Podcast[] - */ - function get_user_podcasts(User $user): array - { - return new PodcastModel() - ->getUserPodcasts($user->id, get_user_podcast_ids($user)); - } -} - -if (! function_exists('get_podcasts_user_can_interact_with')) { - /** - * @return Podcast[] - */ - function get_podcasts_user_can_interact_with(User $user): array - { - $userPodcasts = new PodcastModel() - ->getUserPodcasts($user->id, get_user_podcast_ids($user)); - - $hasInteractAsPrivilege = interact_as_actor_id() === null; - - if ($userPodcasts === []) { - if ($hasInteractAsPrivilege) { - remove_interact_as_actor(); - } - - return []; - } - - $isInteractAsPrivilegeLost = true; - $podcastsUserCanInteractWith = []; - foreach ($userPodcasts as $userPodcast) { - if (can_podcast($user, $userPodcast->id, 'interact-as')) { - if (interact_as_actor_id() === $userPodcast->actor_id) { - $isInteractAsPrivilegeLost = false; - } - - $podcastsUserCanInteractWith[] = $userPodcast; - } - } - - if ($podcastsUserCanInteractWith === []) { - if (interact_as_actor_id() !== null) { - remove_interact_as_actor(); - } - - return []; - } - - // check if user has lost the interact as privilege for current podcast actor. - // --> Remove interact as if there's no podcast actor to interact as - // or set the first podcast actor the user can interact as - if ($isInteractAsPrivilegeLost) { - set_interact_as_actor($podcastsUserCanInteractWith[0]->actor_id); - } - - return $podcastsUserCanInteractWith; - } -} - -if (! function_exists('get_actor_ids_with_unread_notifications')) { - /** - * Returns the ids of the user's actors that have unread notifications - * - * @return int[] - */ - function get_actor_ids_with_unread_notifications(User $user): array - { - if (($userPodcasts = get_user_podcasts($user)) === []) { - return []; - } - - $unreadNotifications = new NotificationModel() - ->whereIn('target_actor_id', array_column($userPodcasts, 'actor_id')) - ->where('read_at') - ->findAll(); - - return array_column($unreadNotifications, 'target_actor_id'); - } -} - -if (! function_exists('get_group_title')) { - /** - * @return array<'title'|'description', string> - */ - function get_group_info(string $group, ?int $podcastId = null): array - { - if ($podcastId === null) { - return setting('AuthGroups.instanceGroups')[$group]; - } - - return setting('AuthGroups.podcastGroups')[$group]; - } -} diff --git a/modules/Auth/Language/ar/Auth.php b/modules/Auth/Language/ar/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/ar/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/br/Auth.php b/modules/Auth/Language/br/Auth.php deleted file mode 100644 index 9730b849..00000000 --- a/modules/Auth/Language/br/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Perc\'henn·ez an istañs', - 'description' => 'Perc\'henn·ez Castopod.', - ], - 'superadmin' => [ - 'title' => 'Dreistmerour·ez', - 'description' => 'Ur c\'hontroll klok en deus war Castopod.', - ], - 'manager' => [ - 'title' => 'Merour·ez', - 'description' => 'Merañ a ra endalc\'had Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podkaster', - 'description' => 'Implijerien·ezed kustum Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Gallout a ra gwelet taolenn-stur Castopod.', - 'admin.settings' => 'Gallout a ra gwelet arventennoù Castopod.', - 'users.manage' => 'Gallout a ra ober war-dro implijerien·ezed Castopod.', - 'persons.manage' => 'Gallout a ra merañ an emellerien·ezed.', - 'pages.manage' => 'Gallout a ra merañ ar pajennoù.', - 'podcasts.view' => 'Gallout a ra gwelet an holl bodkastoù.', - 'podcasts.create' => 'Gallout a ra krouiñ podkastoù nevez.', - 'podcasts.import' => 'Gallout a ra enporzhiañ podkastoù.', - 'fediverse.manage-blocks' => 'Gallout a ra mirout aktourien·ezed pe domanioù ar Fediverse ouzh kaout darempredoù gant Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Perc\'henn·ez ar podkast', - 'description' => 'Perc\'henn·ez ar podkast.', - ], - 'admin' => [ - 'title' => 'Merour·ez', - 'description' => 'Ur c\'hontroll klok en deus war ar podkast #{id}.', - ], - 'editor' => [ - 'title' => 'Embanner', - 'description' => 'Merañ a ra endalc\'had hag embannadurioù ar podkast #{id}.', - ], - 'author' => [ - 'title' => 'Aozer·ez', - 'description' => 'Merañ a ra endalc\'had ar podkast #{id} met ne c\'hall ket embann anezho.', - ], - 'guest' => [ - 'title' => 'Kouviad·ez', - 'description' => 'Perzhiad·ez eus ar podkast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Gallout a ra gwelet taolenn-stur ha muzulioù heklev ar podkast #{id}.', - 'edit' => 'Gallout a ra kemmañ ar podkast #{id}.', - 'delete' => 'Gallout a ra lemel ar podkast #{id}.', - 'manage-import' => 'Gallout a ra sinkronekaat ar podkast enporzhiet #{id}.', - 'manage-persons' => 'Gallout a ra merañ koumanantoù ar podkast #{id}.', - 'manage-subscriptions' => 'Gallout a ra merañ koumanantoù ar podkast #{id}.', - 'manage-contributors' => 'Gallout a ra merañ perzhidi ha perzhiadezed ar podkast #{id}.', - 'manage-platforms' => 'Gallout a ra ouzhpennañ pe lemel liammoù etrezek savennoù diavaez evit ar podkast #{id}.', - 'manage-publications' => 'Gallout a ra embann ar podkast #{id}.', - 'manage-notifications' => 'Gallout a ra gwelet kemennoù ar podkast #{id} ha lakaat anezho evel lennet.', - 'interact-as' => 'Gallout a ra ober traoù gant identelezh ar podkast #{id}: ouzhpennañ ur gemennadenn d\'ar re garetañ, rannañ anezhi pe respont dezhi.', - 'episodes' => [ - 'view' => 'Gallout a ra gwelet taolennoù-stur ha muzulioù heklev rannoù ar podkast #{id}.', - 'create' => 'Gallout a ra krouiñ rannoù evit podkast #{id}.', - 'edit' => 'Gallout a ra kemmañ rannoù ar podkast #{id}.', - 'delete' => 'Gallout a ra lemel rannoù ar podkast #{id}.', - 'manage-persons' => 'Gallout a ra merañ emellerien·ezed ar podkast #{id}.', - 'manage-clips' => 'Gallout a ra merañ klipoù video pe tennadoù son ar podkast #{id}.', - 'manage-publications' => 'Gallout a ra embann pe diembann rannoù ha kemennadennoù ar podkast #{id}.', - 'manage-comments' => 'Gallout a ra krouiñ/lemel evezhiadennoù evit rannoù ar podkast #{id}.', - ], - ], - - // missing keys - 'code' => 'Ho kod 6 sifr dezhañ', - - 'set_password' => 'Skrivit ho ker-tremen', - - // Welcome email - 'welcomeSubject' => 'Pedet oc\'h bet da vont war {siteName}', - 'emailWelcomeMailBody' => 'Krouet ez eus bet ur gont deoc\'h war {domain}. Klikit war al liamm amañ-dindan evit choaz ur ger-tremen. Bev e vo al liamm betek {numberOfHours} eur goude m\'eo bet kaset ar postel-mañ.', -]; diff --git a/modules/Auth/Language/ca/Auth.php b/modules/Auth/Language/ca/Auth.php deleted file mode 100644 index 3478f697..00000000 --- a/modules/Auth/Language/ca/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Propietari de la instància', - 'description' => 'Propietari del Castopod.', - ], - 'superadmin' => [ - 'title' => 'Super administrador', - 'description' => 'Té control complet sobre Castopod.', - ], - 'manager' => [ - 'title' => 'Administrador', - 'description' => 'Administra el contingut de Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Usos generals de Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Pot accedir a l\'àrea d\'administració de Castopod.', - 'admin.settings' => 'Pot accedir a la configuració de Castopod.', - 'users.manage' => 'Pot administrar els usuaris de Castopod.', - 'persons.manage' => 'Pot administrar persones.', - 'pages.manage' => 'Pot administrar pàgines.', - 'podcasts.view' => 'Pot veure els pòdcasts.', - 'podcasts.create' => 'Pot crear nous pòdcasts.', - 'podcasts.import' => 'Pot importar pòdcasts.', - 'fediverse.manage-blocks' => 'Pot evitar que actors/dominis del fedivers interactuen amb Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Propietari del pòdcast', - 'description' => 'El propietari del pòdcast.', - ], - 'admin' => [ - 'title' => 'Administrador', - 'description' => 'Té control complet del pòdcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Administra els continguts i la publicació del pòdcast #{id}.', - ], - 'author' => [ - 'title' => 'Autor', - 'description' => 'Administra el contingut del podcast #{id} però no el pot publicar.', - ], - 'guest' => [ - 'title' => 'Convidat', - 'description' => 'Col·laborador general del podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Pot veure el tauler i les estadístiques del podcast #{id}.', - 'edit' => 'Pot editar el podcast #{id}.', - 'delete' => 'Pot suprimir el podcast #{id}.', - 'manage-import' => 'Pot sincronitzar el podcast importat #{id}.', - 'manage-persons' => 'Pot gestionar les subscripcions del podcast #{id}.', - 'manage-subscriptions' => 'Pot gestionar les subscripcions del podcast #{id}.', - 'manage-contributors' => 'Pot gestionar els col·laboradors del podcast #{id}.', - 'manage-platforms' => 'Pot establir/eliminar enllaços de plataforma del podcast #{id}.', - 'manage-publications' => 'Pot publicar el podcast #{id}.', - 'manage-notifications' => 'Pot veure i marcar les notificacions com a llegides per al podcast #{id}.', - 'interact-as' => 'Pot interactuar en nom del podcast #{id} per marcar les publicacions com a preferides, compartir-les o respondre-hi.', - 'episodes' => [ - 'view' => 'Pot veure taulers i estadístiques dels episodis del podcast #{id}.', - 'create' => 'Pot crear episodis per al podcast #{id}.', - 'edit' => 'Pot editar episodis del podcast #{id}.', - 'delete' => 'Pot suprimir episodis del podcast #{id}.', - 'manage-persons' => 'Pot gestionar persones d\'episodi del podcast #{id}.', - 'manage-clips' => 'Pot gestionar clips de vídeo o fragments de so del pòdcast #{id}.', - 'manage-publications' => 'Pot publicar/anul·lar la publicació d\'episodis i publicacions del pòdcast #{id}.', - 'manage-comments' => 'Pot crear/eliminar comentaris d\'episodi del pòdcast #{id}.', - ], - ], - - // missing keys - 'code' => 'El teu codi de 6 dígits', - - 'set_password' => 'Estableix la teva contrasenya', - - // Welcome email - 'welcomeSubject' => 'Has estat convidat a {siteName}', - 'emailWelcomeMailBody' => 'S\'ha creat un compte per a tu a {domain}, fes clic a l\'enllaç d\'inici de sessió següent per configurar la teva contrasenya. L\'enllaç és vàlid durant {numberOfHours} hores després de l\'hora d\'enviament d\'aquest correu electrònic.', -]; diff --git a/modules/Auth/Language/da/Auth.php b/modules/Auth/Language/da/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/da/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/da/Contributor.php b/modules/Auth/Language/da/Contributor.php deleted file mode 100644 index f2685498..00000000 --- a/modules/Auth/Language/da/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast bidragsydere', - 'view' => "{username}s bidrag til {podcastTitle}", - 'add' => 'Tilføj bidragyder', - 'add_contributor' => 'Tilføj bidragyder til {0}', - 'edit_role' => 'Opdatér rolle for {0}', - 'edit' => 'Redigér', - 'remove' => 'Fjern', - 'list' => [ - 'username' => 'Brugernavn', - 'role' => 'Rolle', - ], - 'form' => [ - 'user' => 'Bruger', - 'user_placeholder' => 'Vælg en bruger…', - 'role' => 'Rolle', - 'role_placeholder' => 'Vælg dens rolle…', - 'submit_add' => 'Tilføj bidragyder', - 'submit_edit' => 'Opdatér rolle', - ], - 'delete_form' => [ - 'title' => 'Fjern {contributor}', - 'disclaimer' => - 'Du er ved at fjerne {contributor} fra bidragydere. De vil ikke længere kunne få adgang til "{podcastTitle}".', - 'understand' => 'Jeg forstår, jeg vil fjerne {contributor} fra "{podcastTitle}"', - 'submit' => 'Fjern', - ], - 'messages' => [ - 'editSuccess' => 'Rolle ændret!', - 'editOwnerError' => "Du kan ikke redigere podcast-ejeren!", - 'removeOwnerError' => "Du kan ikke fjerne podcast-ejeren!", - 'removeSuccess' => - 'Du har fjernet {username} fra {podcastTitle}', - 'alreadyAddedError' => - "Den bidragsyder, du forsøger at tilføje, er allerede blevet tilføjet!", - ], -]; diff --git a/modules/Auth/Language/da/User.php b/modules/Auth/Language/da/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/da/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/de/Auth.php b/modules/Auth/Language/de/Auth.php deleted file mode 100644 index e35619ca..00000000 --- a/modules/Auth/Language/de/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instanzbesitzer', - 'description' => 'Der Castopod-Besitzer.', - ], - 'superadmin' => [ - 'title' => 'Super-Administrator', - 'description' => 'Hat die vollständige Kontrolle über Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Verwaltet Castopods Inhalte.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Allgemeine Benutzer von Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Kann auf den Admin-Bereich von Castopod zugreifen.', - 'admin.settings' => 'Kann auf die Einstellungen von Castopod zugreifen.', - 'users.manage' => 'Kann Castopod-Benutzer verwalten.', - 'persons.manage' => 'Kann Mitwirkende verwalten.', - 'pages.manage' => 'Kann Seiten verwalten.', - 'podcasts.view' => 'Kann alle Podcasts einsehen.', - 'podcasts.create' => 'Kann neue Podcasts erstellen.', - 'podcasts.import' => 'Kann Podcasts importieren.', - 'fediverse.manage-blocks' => 'Kann föderierte Nutzer/Domains davon abhalten, mit Castopod zu interagieren.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast-Besitzer', - 'description' => 'Der Podcast-Besitzer.', - ], - 'admin' => [ - 'title' => 'Administrator', - 'description' => 'Hat die vollständige Kontrolle über Podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Verwaltet Inhalte und Veröffentlichungen von Podcast #{id}.', - ], - 'author' => [ - 'title' => 'Autor', - 'description' => 'Verwaltet Inhalte von Podcast #{id}, kann diese aber nicht veröffentlichen.', - ], - 'guest' => [ - 'title' => 'Gast', - 'description' => 'Allgemeiner Mitwirkender des Podcasts #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Kann das Dashboard und Analysen des Podcasts #{id} einsehen.', - 'edit' => 'Kann Podcast #{id} bearbeiten.', - 'delete' => 'Kann Podcast #{id} löschen.', - 'manage-import' => 'Kann den importierten Podcast #{id} synchronisieren.', - 'manage-persons' => 'Kann Abonnements des Podcasts #{id} verwalten.', - 'manage-subscriptions' => 'Kann Abonnements des Podcasts #{id} verwalten.', - 'manage-contributors' => 'Kann Mitwirkende des Podcasts #{id} verwalten.', - 'manage-platforms' => 'Kann Plattform-Links des Podcasts #{id} verwalten.', - 'manage-publications' => 'Kann Podcast #{id} veröffentlichen.', - 'manage-notifications' => 'Kann Benachrichtigungen des Podcasts #{id} einsehen und als gelesen markieren.', - 'interact-as' => 'Kann als Podcast #{id} interagieren, um Beiträge zu favorisieren, zu teilen oder diese zu beantworten.', - 'episodes' => [ - 'view' => 'Kann Dashboards und Analysen von Episoden des Podcasts #{id} einsehen.', - 'create' => 'Kann Folgen für Podcast #{id} erstellen.', - 'edit' => 'Kann Folgen von Podcast #{id} bearbeiten.', - 'delete' => 'Kann Folgen von Podcast #{id} löschen.', - 'manage-persons' => 'Kann Personen von Episoden des Podcasts #{id} verwalten.', - 'manage-clips' => 'Kann Videoclips und Soundbites des Podcasts #{id} verwalten.', - 'manage-publications' => 'Kann Episoden und Posts von Podcast #{id} veröffentlichen/zurückziehen.', - 'manage-comments' => 'Kann Kommentare von Folgen des Podcasts #{id} erstellen und löschen.', - ], - ], - - // missing keys - 'code' => 'Ihr 6-stelliger Code', - - 'set_password' => 'Legen Sie Ihr Passwort fest', - - // Welcome email - 'welcomeSubject' => 'Sie wurden zu {siteName} eingeladen', - 'emailWelcomeMailBody' => 'Ein Account auf {domain} wurde für Sie angelegt, klicken Sie auf den unten stehenden Login-Link, um Ihr Passwort festzulegen. Der Link ist mit Versand der Mail für {numberOfHours} gültig.', -]; diff --git a/modules/Auth/Language/el/Auth.php b/modules/Auth/Language/el/Auth.php deleted file mode 100644 index 1ba3c9ae..00000000 --- a/modules/Auth/Language/el/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Ιδιοκτήτης Διακομιστή', - 'description' => 'Ο ιδιοκτήτης του Castopod.', - ], - 'superadmin' => [ - 'title' => 'Υπερδιαχειριστής', - 'description' => 'Έχει πλήρη έλεγχο του Castopod.', - ], - 'manager' => [ - 'title' => 'Διαχειριστής', - 'description' => 'Διαχείριση περιεχομένου του Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Γενικοί χρήστες του Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Μπορεί να έχει πρόσβαση στην περιοχή διαχείρισης Castopod.', - 'admin.settings' => 'Μπορεί να έχει πρόσβαση στις ρυθμίσεις Castopod.', - 'users.manage' => 'Μπορεί να διαχειριστεί τους χρήστες Castopod.', - 'persons.manage' => 'Μπορεί να διαχειριστεί τα άτομα.', - 'pages.manage' => 'Μπορεί να διαχειριστεί τις σελίδες.', - 'podcasts.view' => 'Μπορεί να δει όλα τα podcasts.', - 'podcasts.create' => 'Μπορεί να δημιουργήσει νέα podcasts.', - 'podcasts.import' => 'Μπορεί να εισάγει podcasts.', - 'fediverse.manage-blocks' => 'Μπορεί να εμποδίσει τους ψευτογενείς ηθοποιούς/τομείς να αλληλεπιδρούν με το Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Ιδιοκτήτης Podcast', - 'description' => 'Ο ιδιοκτήτης του podcast.', - ], - 'admin' => [ - 'title' => 'Διαχειριστής', - 'description' => 'Έχει πλήρη έλεγχο του podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Εκδότης', - 'description' => 'Διαχειρίζεται περιεχόμενο και δημοσιεύσεις του podcast #{id}.', - ], - 'author' => [ - 'title' => 'Συντάκτης', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Επισκέπτης', - 'description' => 'Γενικός συντελεστής του podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/el/User.php b/modules/Auth/Language/el/User.php deleted file mode 100644 index 05bc0e1d..00000000 --- a/modules/Auth/Language/el/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Επεξεργασία ρόλων {username}", - 'ban' => 'Αποκλεισμός', - 'unban' => 'Κατάργηση αποκλεισμού', - 'delete' => 'Διαγραφή', - 'create' => 'Νέος χρήστης', - 'view' => "πληροφορίες του {username}", - 'all_users' => 'Όλοι οι χρήστες', - 'list' => [ - 'user' => 'Χρήστης', - 'role' => 'Ρόλος', - 'banned' => 'Αποκλεισμένος;', - ], - 'form' => [ - 'email' => 'Ηλεκτρονικό ταχυδρομείο', - 'username' => 'Όνομα Χρήστη', - 'password' => 'Κωδικόs πρόσβασης', - 'new_password' => 'Νέος Κωδικός Πρόσβασης', - 'role' => 'Ρόλος', - 'roles' => 'Ρόλοι', - 'permissions' => 'Δικαιώματα', - 'submit_create' => 'Δημιουργία χρήστη', - 'submit_edit' => 'Αποθήκευση', - 'submit_password_change' => 'Αλλαγή!', - ], - 'delete_form' => [ - 'title' => 'Διαγραφή {user}', - 'disclaimer' => - "Πρόκειται να διαγράψετε το {user} οριστικά. Δεν θα μπορούν πλέον να έχουν πρόσβαση στην περιοχή διαχείρισης.", - 'understand' => 'Καταλαβαίνω, θέλω να διαγράψω {user} μόνιμα', - 'submit' => 'Διαγραφή', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "οι ρόλοι του {username} έχουν ενημερωθεί με επιτυχία.", - 'banSuccess' => 'Ο/Η {username} έχει αποκλειστεί.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, you cannot edit its roles.', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/en/Auth.php b/modules/Auth/Language/en/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/en/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/en/User.php b/modules/Auth/Language/en/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/en/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/es/Auth.php b/modules/Auth/Language/es/Auth.php deleted file mode 100644 index 9f82a3cc..00000000 --- a/modules/Auth/Language/es/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Propietario de Instancia', - 'description' => 'Propietario de Castopod.', - ], - 'superadmin' => [ - 'title' => 'Super administrador', - 'description' => 'Tiene control completo sobre Castopod.', - ], - 'manager' => [ - 'title' => 'Administrador', - 'description' => 'Administrar contenido de Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Usuarios generales de Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Puedes acceder al área de administración de Castopod.', - 'admin.settings' => 'Puede acceder a la configuración de Castopod.', - 'users.manage' => 'Puede administrar usuarios de Castopod.', - 'persons.manage' => 'Puede administrar personas.', - 'pages.manage' => 'Puede administrar páginas.', - 'podcasts.view' => 'Puede ver todos los podcasts.', - 'podcasts.create' => 'Puede crear nuevos podcasts.', - 'podcasts.import' => 'Puede importar podcasts.', - 'fediverse.manage-blocks' => 'Puedes bloquear la interacción de actores/dominios del fediverso con Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Propietario de Podcast', - 'description' => 'El propietario del podcast.', - ], - 'admin' => [ - 'title' => 'Administrador', - 'description' => 'Tiene el control completo del podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Gestiona el contenido y las publicaciones del podcast #{id}.', - ], - 'author' => [ - 'title' => 'Autor', - 'description' => 'Gestiona el contenido del podcast #{id} pero no puede publicarlo.', - ], - 'guest' => [ - 'title' => 'Invitado', - 'description' => 'Colaborador general del podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Puede ver el panel de control y analíticas del episodio #{id}.', - 'edit' => 'Puede editar el podcast #{id}.', - 'delete' => 'Puede borrar el podcast #{id}.', - 'manage-import' => 'Puede sincronizar el podcast importado #{id}.', - 'manage-persons' => 'Puede administrar las suscripciones del podcast #{id}.', - 'manage-subscriptions' => 'Puede administrar las suscripciones del podcast #{id}.', - 'manage-contributors' => 'Puede administrar colaboradores del podcast #{id}.', - 'manage-platforms' => 'Puede establecer/eliminar enlaces a la plataforma del podcast #{id}.', - 'manage-publications' => 'Puede publicar el podcast #{id}.', - 'manage-notifications' => 'Puede ver y marcar las notificaciones como leídas para podcast #{id}.', - 'interact-as' => 'Puede interactuar como el podcast #{id} para marcar como favarito, compartir o responder a las publicaciones.', - 'episodes' => [ - 'view' => 'Puede ver el panel de control y analíticas del episodio #{id}.', - 'create' => 'Puede crear episodios para el podcast #{id}.', - 'edit' => 'Puede editar episodios del podcast #{id}.', - 'delete' => 'Puede borrar episodios del podcast #{id}.', - 'manage-persons' => 'Puede administrar las personas de los episodios del podcast #{id}.', - 'manage-clips' => 'Puedes administrar video clips o sonidos del podcast #{id}.', - 'manage-publications' => 'Puede publicar/despublicar episodios y publicaciones del podcast #{id}.', - 'manage-comments' => 'Puede crear/eliminar los comentarios de episodio del podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Introduce un código de 6 dígitos', - - 'set_password' => 'Establece tu contraseña', - - // Welcome email - 'welcomeSubject' => 'Has sido invitado a {siteName}', - 'emailWelcomeMailBody' => 'Una cuenta fue creada para usted en {domain}, haga clic en el enlace de inicio de sesión de abajo para establecer su contraseña. El enlace es válido durante {numberOfHours} horas después de enviar este correo electrónico.', -]; diff --git a/modules/Auth/Language/eu/Auth.php b/modules/Auth/Language/eu/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/eu/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/eu/User.php b/modules/Auth/Language/eu/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/eu/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/fa/Auth.php b/modules/Auth/Language/fa/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/fa/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/fa/User.php b/modules/Auth/Language/fa/User.php deleted file mode 100644 index b9804342..00000000 --- a/modules/Auth/Language/fa/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "ویراش نقش {username}", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'حذف', - 'create' => 'کاربر جدید', - 'view' => "اطّلاعات {username}", - 'all_users' => 'تمامی کاربران', - 'list' => [ - 'user' => 'کاربر', - 'role' => 'نقش', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'رایانامه', - 'username' => 'نام‌کاربری', - 'password' => 'گذرواژه', - 'new_password' => 'گذرواژه‌ٔ جدید', - 'role' => 'نقش', - 'roles' => 'نقش‌ها', - 'permissions' => 'اجازه‌ها', - 'submit_create' => 'ایجاد کاربر', - 'submit_edit' => 'ذخیره', - 'submit_password_change' => 'تغییر!', - ], - 'delete_form' => [ - 'title' => 'حذف {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'حذف', - ], - 'messages' => [ - 'createSuccess' => - 'کاربر با موفّقیت ساخته شد! رایانامهٔ خوش‌آمدی به همراه پیوند ورود برای {username} فرستاده شد. در نخستین ورودش اعلانی برای بازنشانی گذرواژه دریافت خواهد کرد.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} مالک نمونه است. کسی به سادگی مالک را تغییر نمی‌دهد…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/fr-ca/Auth.php b/modules/Auth/Language/fr-ca/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/fr-ca/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/fr-ca/User.php b/modules/Auth/Language/fr-ca/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/fr-ca/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/fr/Auth.php b/modules/Auth/Language/fr/Auth.php deleted file mode 100644 index 4afdf596..00000000 --- a/modules/Auth/Language/fr/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Propriétaire de l\'instance', - 'description' => 'Le propriétaire du Castopod.', - ], - 'superadmin' => [ - 'title' => 'Super administrat·rice·eur', - 'description' => 'A un contrôle complet sur Castopod.', - ], - 'manager' => [ - 'title' => 'Gestionnaire', - 'description' => 'Gère le contenu de Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podcast·rice·eur', - 'description' => 'Utilisateurs généraux de Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Peut accéder à la zone d\'administration Castopod.', - 'admin.settings' => 'Peut accéder aux paramètres de Castopod.', - 'users.manage' => 'Peut gérer les utilisateurs de Castopod.', - 'persons.manage' => 'Permet de gérer les personnes.', - 'pages.manage' => 'Permet de gérer les pages.', - 'podcasts.view' => 'Peut voir tous les podcasts.', - 'podcasts.create' => 'Peut créer de nouveaux podcasts.', - 'podcasts.import' => 'Peut importer des podcasts.', - 'fediverse.manage-blocks' => 'Peut empêcher des act·rice·eur·s/domaines d\'interagir avec Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Propriétaire du Podcast', - 'description' => 'Le/la propriétaire du podcast.', - ], - 'admin' => [ - 'title' => 'Administrateur', - 'description' => 'A un contrôle total sur le podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Éditeur', - 'description' => 'Gère le contenu et les publications du podcast #{id}.', - ], - 'author' => [ - 'title' => 'Auteur / Autrice', - 'description' => 'Gère le contenu du podcast #{id} , mais ne peut pas le publier.', - ], - 'guest' => [ - 'title' => 'Invité', - 'description' => 'Contributeur général du podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Peut voir le tableau de bord et les analyses du podcast #{id}.', - 'edit' => 'Peut éditer le podcast #{id}.', - 'delete' => 'Peut supprimer le podcast #{id}.', - 'manage-import' => 'Peut synchroniser le podcast importé #{id}.', - 'manage-persons' => 'Permet de gérer les abonnements au podcast #{id}.', - 'manage-subscriptions' => 'Permet de gérer les abonnements au podcast #{id}.', - 'manage-contributors' => 'Permet de gérer les contributeurs du podcast #{id}.', - 'manage-platforms' => 'Peut configurer/supprimer les liens de la plateforme du podcast #{id}.', - 'manage-publications' => 'Peut publier le podcast #{id}.', - 'manage-notifications' => 'Peut afficher et marquer les notifications comme lues pour le podcast #{id}.', - 'interact-as' => 'Peut interagir en tant que podcast #{id} pour mettre en favori, partager ou répondre aux messages.', - 'episodes' => [ - 'view' => 'Peut voir le tableau de bord et les statistiques du podcast #{id}.', - 'create' => 'Peut créer des épisodes pour le podcast #{id}.', - 'edit' => 'Peut modifier les épisodes du podcast #{id}.', - 'delete' => 'Peut supprimer les épisodes du podcast #{id}.', - 'manage-persons' => 'Peut gérer les intervenants des épisodes du podcast #{id}.', - 'manage-clips' => 'Permet de gérer les clips vidéo ou les parties sonores du podcast #{id}.', - 'manage-publications' => 'Peut publier/dépublier des épisodes et des messages de podcast #{id}.', - 'manage-comments' => 'Peut créer/supprimer les commentaires de l\'épisode du podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Votre code à 6 chiffres', - - 'set_password' => 'Choisis ton mot de passe', - - // Welcome email - 'welcomeSubject' => 'Vous avez été invité·e à rejoindre {siteName}', - 'emailWelcomeMailBody' => 'Un compte a été créé pour vous sur {domain}, cliquez sur le lien de connexion ci-dessous pour définir votre mot de passe. Le lien est valide pendant {numberOfHours} heures après l\'envoi de cet e-mail.', -]; diff --git a/modules/Auth/Language/fr2/Auth.php b/modules/Auth/Language/fr2/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/fr2/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/fr2/Contributor.php b/modules/Auth/Language/fr2/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/fr2/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/fr2/User.php b/modules/Auth/Language/fr2/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/fr2/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/gd/Auth.php b/modules/Auth/Language/gd/Auth.php deleted file mode 100644 index 2ff1f7d8..00000000 --- a/modules/Auth/Language/gd/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Sealbhadair an ionstans', - 'description' => 'Cò leis a tha an Castopod seo.', - ], - 'superadmin' => [ - 'title' => 'Sàr-rianaire', - 'description' => 'Smachd gu lèir air Castopod.', - ], - 'manager' => [ - 'title' => 'Manaidsear', - 'description' => 'Stiùireadh susbaint Chastopod.', - ], - 'podcaster' => [ - 'title' => 'Pod-chraoladair', - 'description' => 'Luchd-cleachdaidh coitcheann Chastopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => '’S urrainn dhaibh raon rianachd Chastopod inntrigeadh.', - 'admin.settings' => '’S urrainn dhaibh roghainnean Chastopod inntrigeadh.', - 'users.manage' => '’S urrainn dhaibh luchdc-leachdaidh Chastopod a stiùireadh.', - 'persons.manage' => '’S urrainn dhaibh daoine a stiùireadh.', - 'pages.manage' => '’S urrainn dhaibh duilleagan a stiùireadh.', - 'podcasts.view' => 'Chì iad a h-uile pod-chraoladh.', - 'podcasts.create' => '’S urrainn dhaibh pod-chraolaidhean ùra a chruthachadh.', - 'podcasts.import' => '’S urrainn dhaibh pod-chraolaidhean ion-phortadh.', - 'fediverse.manage-blocks' => '’S urrainn dhaibh actairean/àrainnean a cho-shaoghail a bhacadh o eadar-ghabhail le Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Seilbheadair a’ phod-chraolaidh', - 'description' => 'Cò leis a tha am pod-chraoladh.', - ], - 'admin' => [ - 'title' => 'Rianaire', - 'description' => 'Smachd gu lèir air air a’ phod-chraoladh #{id}.', - ], - 'editor' => [ - 'title' => 'Deasaiche', - 'description' => 'A’ stiùireadh susbaint is foillseachaidhean a’ phod-chraoladh #{id}.', - ], - 'author' => [ - 'title' => 'Ùghdar', - 'description' => 'A’ stiùireadh susbaint a’ phod-chraolaidh #{id} ach gun chomas foillseachaidh.', - ], - 'guest' => [ - 'title' => 'Aoigh', - 'description' => 'Neach-cuideachaidh a’ phod-chraolaidh #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Cead an deas-bhòrd agus anailiseachd a’ phod-chraolaidh #{id} a shealltainn.', - 'edit' => '’S urrainn dhaibh am pod-chraoladh #{id} a dheasachadh.', - 'delete' => '’S urrainn dhaibh am pod-chraoladh #{id} a sguabadh às.', - 'manage-import' => '’S urrainn dhaibh am pod-chraoladh #{id} air ion-phortadh a shioncronachadh.', - 'manage-persons' => '’S urrainn dhaibh na fo-sgrìobhaidhean air a’ phod-chraoladh #{id} a stiùireadh.', - 'manage-subscriptions' => '’S urrainn dhaibh na fo-sgrìobhaidhean air a’ phod-chraoladh #{id} a stiùireadh.', - 'manage-contributors' => '’S urrainn dhaibh an luchd-cuideachaidh aig a’ phod-chraoladh #{id} a stiùireadh.', - 'manage-platforms' => '’S urrainn dhaibh ceanglaichean-ùrlair a’ phod-chraolaidh #{id} a shuidheachadh/a thoirt air falbh.', - 'manage-publications' => '’S urrainn dhaibh am pod-chraoladh #{id} fhoillseachadh.', - 'manage-notifications' => 'Chì iad brathan a’ phod-chraolaidh #{id} agus ’s urrainn dhaibh comharra a chur gun deach an leughadh.', - 'interact-as' => '’S urrainn dhaibh eadar-ghabhail ’na phod-chraoladh #{id} airson annsachdan, co-roinneadh is freagairtean do phostaichean.', - 'episodes' => [ - 'view' => 'Chì iad deas-bhùird is anailiseachd do dh’eapasodan a’ phod-chraolaidh #{id}.', - 'create' => '’S urrainn dhaibh eapasodan a chruthachadh dhan phod-chraoladh #{id}.', - 'edit' => '’S urrainn dhaibh eapasodan a’ phod-chraolaidh #{id} a dheasachadh.', - 'delete' => '’S urrainn dhaibh eapasodan a’ phod-chraolaidh #{id} a sguabadh às.', - 'manage-persons' => '’S urrainn dhaibh daoine nan eapasodan aig a’ phod-chraoladh #{id} a stiùireadh.', - 'manage-clips' => '’S urrainn dhaibh cliopaichean video no blasan-fuaime aig a’ phod-chraoladh #{id} a stiùireadh.', - 'manage-publications' => '’S urrainn dhaibh eapasodan is postaichean a’ phod-chraolaidh #{id} fhoillseachadh/neo-fhoillseachadh.', - 'manage-comments' => '’S urrainn dhaibh beachdan air eapasod a’ phod-chraolaidh #{id} a chruthachadh/a thoirt air falbh.', - ], - ], - - // missing keys - 'code' => 'An còd 6-àireamhach agad', - - 'set_password' => 'Suidhich am facal-faire agad', - - // Welcome email - 'welcomeSubject' => 'Fhuair thu cuireadh gu {siteName}', - 'emailWelcomeMailBody' => 'Chaidh cunntas a chruthachadh dhut air {domain}, briog air ceangal a’ chlàraidh a-steach gu h-ìosal airson am facal-faire agad a shuidheachadh. Bidh an ceangal dligheach fad {numberOfHours} uair a thìde às dèidh cur a’ phuist-d seo.', -]; diff --git a/modules/Auth/Language/gd/Contributor.php b/modules/Auth/Language/gd/Contributor.php deleted file mode 100644 index a6154a55..00000000 --- a/modules/Auth/Language/gd/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Luchd-cuideachaidh a’ phod-chraolaidh', - 'view' => "Na chuir {username} ri {podcastTitle}", - 'add' => 'Cuir neach-cuideachaidh ris', - 'add_contributor' => 'Cuir neach-cuideachaidh ris airson {0}', - 'edit_role' => 'Ùraich an dreuchd airson {0}', - 'edit' => 'Deasaich', - 'remove' => 'Thoir air falbh', - 'list' => [ - 'username' => 'Ainm-cleachdaiche', - 'role' => 'Dreuchd', - ], - 'form' => [ - 'user' => 'Cleachdaiche', - 'user_placeholder' => 'Tagh cleachdaiche…', - 'role' => 'Dreuchd', - 'role_placeholder' => 'Tagh dreuchd dhaibh…', - 'submit_add' => 'Cuir neach-cuideachaidh ris', - 'submit_edit' => 'Ùraich an dreuchd', - ], - 'delete_form' => [ - 'title' => 'Thoir {contributor} air falbh', - 'disclaimer' => - 'Tha thu an impis {contributor} a toirt air falbh on luchd-cuideachaidh. Chan urrainn dhaibh “{podcastTitle}” inntrigeadh tuilleadh an uairsin.', - 'understand' => 'Tha mi agaibh, tha mi airson {contributor} a thoirt air falbh o “{podcastTitle}”', - 'submit' => 'Thoir air falbh', - ], - 'messages' => [ - 'editSuccess' => 'Chaidh an dreuchd atharrachadh!', - 'editOwnerError' => "Chan urrainn dhut sealbhadair a’ phod-chraolaidh a dheasachadh!", - 'removeOwnerError' => "Chan urrainn dhut sealbhadair a’ phod-chraolaidh a thoirt air falbh!", - 'removeSuccess' => - 'Thug thu {username} air falbh o {podcastTitle}', - 'alreadyAddedError' => - "Chaidh an neach-cuideachaidh a tha thu airson cur ris a chur ris mu thràth!", - ], -]; diff --git a/modules/Auth/Language/gd/MyAccount.php b/modules/Auth/Language/gd/MyAccount.php deleted file mode 100644 index 1a9f8fe1..00000000 --- a/modules/Auth/Language/gd/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'Fiosrachadh a’ chunntais agam', - 'changePassword' => 'Atharraich am facal-faire agam', - 'messages' => [ - 'wrongPasswordError' => "Chuir thu a-steach am facal-faire ceàrr, feuch ris a-rithist.", - 'passwordChangeSuccess' => 'Chaidh am facal-faire atharrachadh!', - ], -]; diff --git a/modules/Auth/Language/gd/User.php b/modules/Auth/Language/gd/User.php deleted file mode 100644 index 33a1d513..00000000 --- a/modules/Auth/Language/gd/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Deasaich an dreuchd aig {username}", - 'ban' => 'Toirmisg', - 'unban' => 'Dì-thoirmisg', - 'delete' => 'Sguab às', - 'create' => 'Cleachdaiche ùr', - 'view' => "Am fiosrachadh aig {username}", - 'all_users' => 'A h-uile cleachdaiche', - 'list' => [ - 'user' => 'Cleachdaiche', - 'role' => 'Dreuchd', - 'banned' => 'Air a thoirmeasg?', - ], - 'form' => [ - 'email' => 'Post-d', - 'username' => 'Ainm-cleachdaiche', - 'password' => 'Facal-faire', - 'new_password' => 'Am facal-faire ùr', - 'role' => 'Dreuchd', - 'roles' => 'Dreuchdan', - 'permissions' => 'Ceadan', - 'submit_create' => 'Cruthaich cleachdaiche', - 'submit_edit' => 'Sàbhail', - 'submit_password_change' => 'Atharraich!', - ], - 'delete_form' => [ - 'title' => 'Sguab às {user}', - 'disclaimer' => - "Tha thu an impis {user} a sguabadh às gu buan. Chan urrainn dhaibh raon na rianachd inntrigeadh tuilleadh an uairsin.", - 'understand' => 'Tha mi agaibh, tha mi airson {user} a sguabadh às gu buan', - 'submit' => 'Sguab às', - ], - 'messages' => [ - 'createSuccess' => - 'Chaidh an cleachdaiche a chruthachadh! Chaidh post-d fàilteachaidh a chur gu {username} le ceangal clàraidh a-steach, thèid iarraidh orra gun ath-shuidhich iad am facal-faire aca a’ chiad turas a nì iad dearbhadh.', - 'roleEditSuccess' => - "Chaidh na dreuchdan aig {username} ùrachadh.", - 'banSuccess' => 'Chaidh {username} a thoirmeasg.', - 'unbanSuccess' => 'Chaidh {username} a dhì-thoirmeasg.', - 'editOwnerError' => - 'Is {username} sealbhadair an ionstans, na bean ris an t-sealbhadair…', - 'banSuperAdminError' => - 'Tha {username} ’na shàr-rianaire, na toirmisg sàr-rianaire…', - 'deleteOwnerError' => - 'Is {username} sealbhadair an ionstans, na sguab às an sealbhadair…', - 'deleteSuperAdminError' => - 'Tha {username} ’na shàr-rianaire, na sguab às sàr-rianaire…', - 'deleteSuccess' => 'Chaidh {username} a sguabadh às.', - ], -]; diff --git a/modules/Auth/Language/gl/Auth.php b/modules/Auth/Language/gl/Auth.php deleted file mode 100644 index 15902033..00000000 --- a/modules/Auth/Language/gl/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Propietaria da instancia', - 'description' => 'Propietaria de Castopod.', - ], - 'superadmin' => [ - 'title' => 'Super Admin', - 'description' => 'Ten control completo sobre Castopod.', - ], - 'manager' => [ - 'title' => 'Xestora', - 'description' => 'Quen xestiona o contido de Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Usuaria común de Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Pode acceder á área de administración.', - 'admin.settings' => 'Pode acceder aos axustes de Castopod.', - 'users.manage' => 'Pode xestionar as usuarias de Castopod.', - 'persons.manage' => 'Pode xestionar persoas.', - 'pages.manage' => 'Pode xestionar páxinas.', - 'podcasts.view' => 'Pode ver tódolos podcast.', - 'podcasts.create' => 'Pode crear novos podcast.', - 'podcasts.import' => 'Pode importar podcasts.', - 'fediverse.manage-blocks' => 'Pode bloquear actores/dominios do fediverso evitando interactuar con Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Dona do Podcast', - 'description' => 'A propietaria do podcast.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Ten control total sobre o podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editora', - 'description' => 'Persoa que xestiona o contido e publicacións do podcast #{id}.', - ], - 'author' => [ - 'title' => 'Autora', - 'description' => 'Persoa que xestiona o contido do podcast #{id} pero non pode publicalo.', - ], - 'guest' => [ - 'title' => 'Convidada', - 'description' => 'Contribuínte básico ao podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Pode ver o taboleiro e estatísticas do podcast #{id}.', - 'edit' => 'Pode editar o podcast #{id}.', - 'delete' => 'Pode eliminar o podcast #{id}.', - 'manage-import' => 'Pode sincronizar o podcast importado #{id}.', - 'manage-persons' => 'Pode xestionar as subscricións do podcast #{id}.', - 'manage-subscriptions' => 'Pode xestionar as subscricións do podcast #{id}.', - 'manage-contributors' => 'Pode xestionar as contribucións ao podcast #{id}.', - 'manage-platforms' => 'Pode establecer/eliminar ligazóns a plataformas do podcast #{id}.', - 'manage-publications' => 'Pode publicar o podcast #{id}.', - 'manage-notifications' => 'Pode ver e marcar as notificacións como lidas no podcast #{id}.', - 'interact-as' => 'Pode actuar como o podcast #{id} para compartir, favorecer ou responder a publicacións.', - 'episodes' => [ - 'view' => 'Pode ver os taboleiros e estatísticas dos episodios do podcast #{id}.', - 'create' => 'Pode crear episodios para o podcast #{id}.', - 'edit' => 'Pode editar os episodios do podcast #{id}.', - 'delete' => 'Pode eliminar episodios do podcast #{id}.', - 'manage-persons' => 'Pode xestionar as persoas do episodio do podcast #{id}.', - 'manage-clips' => 'Pode xestionar os clips de vídeo e extractos de audio do podcast #{id}.', - 'manage-publications' => 'Pode publicar/retirar episodios e publicacións do podcast #{id}.', - 'manage-comments' => 'Pode crear/eliminar comentarios dos episodios do podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Código de 6 díxitos', - - 'set_password' => 'Establece un contrasinal', - - // Welcome email - 'welcomeSubject' => 'Recibiches un convite para {siteName}', - 'emailWelcomeMailBody' => 'Creouse unha conta para ti en {domain}, preme na ligazón inferior de acceso para establecer un contrasinal. A ligazón é válida durante {numberOfHours} horas desde que se enviou este email.', -]; diff --git a/modules/Auth/Language/id/Auth.php b/modules/Auth/Language/id/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/id/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/id/Contributor.php b/modules/Auth/Language/id/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/id/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/it/Auth.php b/modules/Auth/Language/it/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/it/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/ja/Auth.php b/modules/Auth/Language/ja/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/ja/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/ja/Contributor.php b/modules/Auth/Language/ja/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/ja/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/ja/User.php b/modules/Auth/Language/ja/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/ja/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/kk/Auth.php b/modules/Auth/Language/kk/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/kk/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/kk/Contributor.php b/modules/Auth/Language/kk/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/kk/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/kk/User.php b/modules/Auth/Language/kk/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/kk/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/ko/Auth.php b/modules/Auth/Language/ko/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/ko/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/ko/Contributor.php b/modules/Auth/Language/ko/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/ko/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/ko/MyAccount.php b/modules/Auth/Language/ko/MyAccount.php deleted file mode 100644 index 6ebbb30e..00000000 --- a/modules/Auth/Language/ko/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'My account info', - 'changePassword' => 'Change my password', - 'messages' => [ - 'wrongPasswordError' => "You've entered the wrong password, try again.", - 'passwordChangeSuccess' => 'Password has been successfully changed!', - ], -]; diff --git a/modules/Auth/Language/ko/User.php b/modules/Auth/Language/ko/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/ko/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/nl/Auth.php b/modules/Auth/Language/nl/Auth.php deleted file mode 100644 index 31521984..00000000 --- a/modules/Auth/Language/nl/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance eigenaar', - 'description' => 'De Castopod eigenaar.', - ], - 'superadmin' => [ - 'title' => 'Super beheerder', - 'description' => 'Heeft de volledige controle over Castopod.', - ], - 'manager' => [ - 'title' => 'Beheerder', - 'description' => 'Beheert de inhoud van Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Algemene gebruikers van Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Kan toegang krijgen tot de beheeromgeving van Castopod.', - 'admin.settings' => 'Kan toegang krijgen tot de instellingen van Castopod.', - 'users.manage' => 'Kan Castopod-gebruikers beheren.', - 'persons.manage' => 'Kan personen beheren.', - 'pages.manage' => 'Kan pagina\'s beheren.', - 'podcasts.view' => 'Kan alle podcasts bekijken.', - 'podcasts.create' => 'Kan nieuwe podcast aanmaken.', - 'podcasts.import' => 'Kan podcasts importeren.', - 'fediverse.manage-blocks' => 'Kan fediverse actors/domains blokkeren voor interactie met Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Eigenaar', - 'description' => 'De eigenaar van de podcast.', - ], - 'admin' => [ - 'title' => 'Beheerder', - 'description' => 'Heeft de volledige controle over podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Redacteur', - 'description' => 'Beheert inhoud en publicaties van podcast #{id}.', - ], - 'author' => [ - 'title' => 'Auteur', - 'description' => 'Beheert de inhoud van podcast #{id} maar kan deze niet publiceren.', - ], - 'guest' => [ - 'title' => 'Gast', - 'description' => 'Algemene bijdrager van podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Kan dashboard en analyses van podcast #{id} zien.', - 'edit' => 'Kan podcast #{id} wijzigen.', - 'delete' => 'Kan podcast #{id} verwijderen.', - 'manage-import' => 'Kan de geïmporteerde podcast #{id} synchroniseren.', - 'manage-persons' => 'Kan abonnementen van podcast #{id} beheren.', - 'manage-subscriptions' => 'Kan abonnementen van podcast #{id} beheren.', - 'manage-contributors' => 'Kan bijdragers van podcast #{id} beheren.', - 'manage-platforms' => 'Kan platform links van podcast #{id} instellen of verwijderen.', - 'manage-publications' => 'Kan podcast #{id} publiceren.', - 'manage-notifications' => 'Kan meldingen bekijken en markeren als gelezen voor podcast #{id}.', - 'interact-as' => 'Kan als podcast #{id} handelen om te favorieten, te delen of te reageren op berichten.', - 'episodes' => [ - 'view' => 'Kan dashboard en analyses van de afleveringen van podcast #{id} zien.', - 'create' => 'Kan afleveringen voor podcast #{id} aanmaken.', - 'edit' => 'Kan afleveringen van podcast #{id} wijzigen.', - 'delete' => 'Kan afleveringen van podcast #{id} verwijderen.', - 'manage-persons' => 'Kan aflevering personen van podcast #{id} beheren.', - 'manage-clips' => 'Kan videoclips of soundbites van podcast #{id} beheren.', - 'manage-publications' => 'Kan afleveringen en berichten van podcast #{id} publiceren/depubliceren.', - 'manage-comments' => 'Kan opmerkingen van aflevering van podcast van #{id} maken of verwijderen.', - ], - ], - - // missing keys - 'code' => 'Jouw 6-cijferige code', - - 'set_password' => 'Stel je wachtwoord in', - - // Welcome email - 'welcomeSubject' => 'Je bent uitgenodigd voor {siteName}', - 'emailWelcomeMailBody' => 'Er is een account voor u aangemaakt op {domain}, klik op onderstaande inloglink om uw wachtwoord in te stellen. De link is geldig tot {numberOfHours} uur nadat deze e-mail is verzonden.', -]; diff --git a/modules/Auth/Language/nl/MyAccount.php b/modules/Auth/Language/nl/MyAccount.php deleted file mode 100644 index c7a5d5cf..00000000 --- a/modules/Auth/Language/nl/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'Mijn accountgegevens', - 'changePassword' => 'Wijzig mijn wachtwoord', - 'messages' => [ - 'wrongPasswordError' => "Je hebt een verkeerd wachtwoord ingevoerd, probeer het opnieuw.", - 'passwordChangeSuccess' => 'Wachtwoord is succesvol gewijzigd!', - ], -]; diff --git a/modules/Auth/Language/nl/User.php b/modules/Auth/Language/nl/User.php deleted file mode 100644 index ee321721..00000000 --- a/modules/Auth/Language/nl/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Rol van {username} wijzigen", - 'ban' => 'Blokkeren', - 'unban' => 'Deblokkeren', - 'delete' => 'Verwijderen', - 'create' => 'Nieuwe gebruiker', - 'view' => "Info van {username}", - 'all_users' => 'Alle gebruikers', - 'list' => [ - 'user' => 'Gebruiker', - 'role' => 'Rol', - 'banned' => 'Geblokkeerd?', - ], - 'form' => [ - 'email' => 'E-mail', - 'username' => 'Gebruikersnaam', - 'password' => 'Wachtwoord', - 'new_password' => 'Nieuw Wachtwoord', - 'role' => 'Rol', - 'roles' => 'Rollen', - 'permissions' => 'Rechten', - 'submit_create' => 'Gebruiker aanmaken', - 'submit_edit' => 'Opslaan', - 'submit_password_change' => 'Wijzigen!', - ], - 'delete_form' => [ - 'title' => 'Verwijder {user}', - 'disclaimer' => - "Je staat op het punt {user} permanent te verwijderen. Deze zal geen toegang meer hebben tot de beheerdersomgeving.", - 'understand' => 'Ik begrijp het, ik wil {user} permanent verwijderen', - 'submit' => 'Verwijderen', - ], - 'messages' => [ - 'createSuccess' => - 'Gebruiker succesvol aangemaakt! Een welkomsmail is naar {username} verzonden met een inloglink, bij de eerste authenticatie zal er om een wachtwoordreset gevraagd worden.', - 'roleEditSuccess' => - "De rollen van {username} zijn succesvol bijgewerkt.", - 'banSuccess' => '{username} is geblokkeerd.', - 'unbanSuccess' => '{username} is gedeblokkeerd.', - 'editOwnerError' => - '{username} is de instance eigenaar, men raakt niet zomaar de eigenaar aan…', - 'banSuperAdminError' => - '{username} is een super beheerder, men raakt niet zomaar een super beheerder aan…', - 'deleteOwnerError' => - '{username} is de instance eigenaar, men verwijderd niet zomaar de eigenaar…', - 'deleteSuperAdminError' => - '{username} is een superadmin, men verwijderd niet zomaar een superadmin…', - 'deleteSuccess' => '{username} is verwijderd.', - ], -]; diff --git a/modules/Auth/Language/nn-no/Auth.php b/modules/Auth/Language/nn-no/Auth.php deleted file mode 100644 index ba1c57f9..00000000 --- a/modules/Auth/Language/nn-no/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Nettstadeigar', - 'description' => 'Castopod-eigaren.', - ], - 'superadmin' => [ - 'title' => 'Superstyrar', - 'description' => 'Har full kontroll over Castopod.', - ], - 'manager' => [ - 'title' => 'Leiar', - 'description' => 'Styrer innhaldet på Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podkastar', - 'description' => 'Vanlege Castopod-brukarar.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Kan bruka styringspanelet for Castopod.', - 'admin.settings' => 'Kan få tilgang til innstillingane for Castopod.', - 'users.manage' => 'Kan handtera Castopod-brukarar.', - 'persons.manage' => 'Kan handtera folk.', - 'pages.manage' => 'Kan handtera sider.', - 'podcasts.view' => 'Kan sjå alle podkastane.', - 'podcasts.create' => 'Kan laga nye podkastar.', - 'podcasts.import' => 'Kan importera podkastar.', - 'fediverse.manage-blocks' => 'Kan blokkera folk og domene på allheimen frå å samhandla med Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podkasteigar', - 'description' => 'Podkasteigaren.', - ], - 'admin' => [ - 'title' => 'Administrator', - 'description' => 'Har full kontroll over podkasten #{id}.', - ], - 'editor' => [ - 'title' => 'Redaktør', - 'description' => 'Styrer innhald og publisering for podkasten #{id}.', - ], - 'author' => [ - 'title' => 'Skapar', - 'description' => 'Styrer innhald for podkasten #{id}, men kan ikkje publisera dei.', - ], - 'guest' => [ - 'title' => 'Gjest', - 'description' => 'Vanleg bidragsytar til podkasten #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Kan sjå styringspanelet og analysedata for podkasten #{id}.', - 'edit' => 'Kan redigera podkasten #{id}.', - 'delete' => 'Kan sletta podkasten #{id}.', - 'manage-import' => 'Kan synkronisera den importerte podkasten #{id}.', - 'manage-persons' => 'Kan handtera abonnement for podkasten #{id}.', - 'manage-subscriptions' => 'Kan handtera abonnement for podkasten #{id}.', - 'manage-contributors' => 'Kan handtera bidragsytarar for podkasten #{id}.', - 'manage-platforms' => 'Kan oppretta og fjerna plattformlenkjer for podkasten #{id}.', - 'manage-publications' => 'Kan publisera podkasten #{id}.', - 'manage-notifications' => 'Kan lesa og merka varsel som lesne for podkasten #{id}.', - 'interact-as' => 'Kan merka podkasten #{id} som favoritt, dela og svara på innlegg.', - 'episodes' => [ - 'view' => 'Kan sjå styringspanelet og analysedata for episodane av podkasten #{id}.', - 'create' => 'Kan laga epoisodar for podkasten #{id}.', - 'edit' => 'Kan redigera episodane av podkasten #{id}.', - 'delete' => 'Kan sletta episodar av podkasten #{id}.', - 'manage-persons' => 'Kan handtera bidragsytarar til episodar av podkasten #{id}.', - 'manage-clips' => 'Kan handtera film- og lydklypp av podkasten #{id}.', - 'manage-publications' => 'Kan publisera og avpublisera episodar og innlegg for podkasten #{id}.', - 'manage-comments' => 'Kan skriva og sletta kommentarar til episodane av podkasten #{id}.', - ], - ], - - // missing keys - 'code' => 'Den sekssifra koden din', - - 'set_password' => 'Lag eit passord', - - // Welcome email - 'welcomeSubject' => 'Du er invitert til {siteName}', - 'emailWelcomeMailBody' => 'Me har laga ein konto til deg på {domain}. Klikk på lenka under for å laga eit passord. Lenka er gyldig i {numberOfHours} timar etter eposten vart send.', -]; diff --git a/modules/Auth/Language/oc/Auth.php b/modules/Auth/Language/oc/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/oc/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/oc/Contributor.php b/modules/Auth/Language/oc/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/oc/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/oc/MyAccount.php b/modules/Auth/Language/oc/MyAccount.php deleted file mode 100644 index 6ebbb30e..00000000 --- a/modules/Auth/Language/oc/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'My account info', - 'changePassword' => 'Change my password', - 'messages' => [ - 'wrongPasswordError' => "You've entered the wrong password, try again.", - 'passwordChangeSuccess' => 'Password has been successfully changed!', - ], -]; diff --git a/modules/Auth/Language/pl/Auth.php b/modules/Auth/Language/pl/Auth.php deleted file mode 100644 index bbc42f95..00000000 --- a/modules/Auth/Language/pl/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Właściciel instancji', - 'description' => 'Właściciel Castopoda.', - ], - 'superadmin' => [ - 'title' => 'Superadministrator', - 'description' => 'Ma pełną kontrolę nad Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Zarządza zawartością Castopoda.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Zwykli użytkownicy Castopoda.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Ma dostęp do panelu administracyjnego Castopoda.', - 'admin.settings' => 'Ma dostęp do ustawień Castopoda.', - 'users.manage' => 'Może zarządzać użytkownikami Castopoda.', - 'persons.manage' => 'Może zarządzać osobami.', - 'pages.manage' => 'Może zarządzać stronami.', - 'podcasts.view' => 'Może wyświetlać wszystkie podcasty.', - 'podcasts.create' => 'Może tworzyć nowe podcasty.', - 'podcasts.import' => 'Może importować podcasty.', - 'fediverse.manage-blocks' => 'Można blokować aktorów/domeny z fediwersum przed interakcjami z Castopodem.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Właściciel Podcastu', - 'description' => 'Właściciel podcastu.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Ma pełną kontrolę nad podcastem #{id}.', - ], - 'editor' => [ - 'title' => 'Edytor', - 'description' => 'Zarządza treścią i publikacjami podcastu #{id}.', - ], - 'author' => [ - 'title' => 'Autor', - 'description' => 'Zarządza zawartością podcastu #{id}, ale nie może jej opublikować.', - ], - 'guest' => [ - 'title' => 'Gość', - 'description' => 'Główny współtwórca podcastu #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Może wyświetlań panel zarządzania oraz analitykę podcastu #{id}.', - 'edit' => 'Może edytować podcast #{id}.', - 'delete' => 'Może usunąć podcast #{id}.', - 'manage-import' => 'Może synchronizować importowany podcast #{id}.', - 'manage-persons' => 'Może zarządzać subskrypcjami podcastu #{id}.', - 'manage-subscriptions' => 'Może zarządzać subskrypcjami podcastu #{id}.', - 'manage-contributors' => 'Może zarządzać współtwórcami podcastu #{id}.', - 'manage-platforms' => 'Można ustawić/usunąć linki platformy podcastu #{id}.', - 'manage-publications' => 'Może publikować podcast #{id}.', - 'manage-notifications' => 'Może wyświetlać i oznaczać powiadomienia jako przeczytane dla podcastu #{id}.', - 'interact-as' => 'Może jako podcast #{id} dodawać do ulubionych, udostępniać lub odpowiadać na posty.', - 'episodes' => [ - 'view' => 'Może wyświetlać panel zarządzania oraz analitykę odcinków podcastu #{id}.', - 'create' => 'Może tworzyć odcinki dla podcastu #{id}.', - 'edit' => 'Może edytować odcinki podcastu #{id}.', - 'delete' => 'Można usuwać odcinki podcastu #{id}.', - 'manage-persons' => 'Może zarządzać osobami w odcinkach podcastu #{id}.', - 'manage-clips' => 'Może zarządzać klipami wideo lub zajawkami podcastu #{id}.', - 'manage-publications' => 'Może publikować/cofać publikowanie odcinków i postów podcastu #{id}.', - 'manage-comments' => 'Może tworzyć/usuwać komentarze odcinka podcastu #{id}.', - ], - ], - - // missing keys - 'code' => 'Twój 6-cyfrowy kod', - - 'set_password' => 'Ustaw swoje hasło', - - // Welcome email - 'welcomeSubject' => 'Zostałeś zaproszony do {siteName}', - 'emailWelcomeMailBody' => 'Na {domain} zostało utworzone dla Ciebie konto, kliknij poniższy link logowania, aby ustawić hasło. Link jest ważny przez {numberOfHours} godzin po wysłaniu tego e-maila.', -]; diff --git a/modules/Auth/Language/pt-br/Auth.php b/modules/Auth/Language/pt-br/Auth.php deleted file mode 100644 index 2637625b..00000000 --- a/modules/Auth/Language/pt-br/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instância proprietário', - 'description' => 'O proprietário do Castopod.', - ], - 'superadmin' => [ - 'title' => 'Super administrador', - 'description' => 'Tem controle completo sobre Castopod.', - ], - 'manager' => [ - 'title' => 'Gerente', - 'description' => 'Gerencia o conteúdo de Castopod.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Usuários gerais do Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Pode acessar a área de administração do Castopod.', - 'admin.settings' => 'Pode acessar as configurações de Castopod.', - 'users.manage' => 'Pode gerenciar usuários do Castopod.', - 'persons.manage' => 'Pode gerenciar pessoas.', - 'pages.manage' => 'Pode gerenciar páginas.', - 'podcasts.view' => 'Pode ver todos os podcasts.', - 'podcasts.create' => 'Pode criar novos podcasts.', - 'podcasts.import' => 'Pode importar podcasts.', - 'fediverse.manage-blocks' => 'Pode bloquear ator/domínios distintos de interagir com Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Dono do Podcast', - 'description' => 'O proprietário do podcast.', - ], - 'admin' => [ - 'title' => 'Administrador', - 'description' => 'Tem controle completo do podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Gerencia o conteúdo e as publicações do podcast #{id}.', - ], - 'author' => [ - 'title' => 'Autor', - 'description' => 'Gerencia o conteúdo do podcast #{id} mas não pode publicá-los.', - ], - 'guest' => [ - 'title' => 'Convidado', - 'description' => 'Contribuidor geral do podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Pode visualizar o painel de controle e análises do podcast #{id}.', - 'edit' => 'Pode editar o podcast #{id}.', - 'delete' => 'Pode deletar episódios do podcast #{id}.', - 'manage-import' => 'Pode sincronizar o podcast importado #{id}.', - 'manage-persons' => 'Pode gerenciar assinaturas do podcast #{id}.', - 'manage-subscriptions' => 'Pode gerenciar assinaturas do podcast #{id}.', - 'manage-contributors' => 'Pode gerenciar contribuidores do podcast #{id}.', - 'manage-platforms' => 'Pode definir/remover links de plataforma do podcast #{id}.', - 'manage-publications' => 'Pode publicar podcast #{id}.', - 'manage-notifications' => 'Pode ver e marcar notificações como lidas para o podcast #{id}.', - 'interact-as' => 'Pode interagir com o podcast #{id} para favorito, compartilhar ou responder às publicações.', - 'episodes' => [ - 'view' => 'Pode ver painéis e análises de episódios de podcast #{id}.', - 'create' => 'Pode criar episódios para o podcast #{id}.', - 'edit' => 'Pode editar episódios de podcast #{id}.', - 'delete' => 'Pode excluir episódios do podcast #{id}.', - 'manage-persons' => 'Pode gerenciar pessoas de episódios do podcast #{id}.', - 'manage-clips' => 'Pode gerenciar clipes de vídeo ou sons de episódios do podcast #{id}.', - 'manage-publications' => 'Pode publicar/remover a publicação de episódios e postagens de podcast #{id}.', - 'manage-comments' => 'Pode criar/remover comentários de episódio do podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Seu código de 6 dígitos', - - 'set_password' => 'Defina sua senha', - - // Welcome email - 'welcomeSubject' => 'Você foi convidado(a) para o {siteName}', - 'emailWelcomeMailBody' => 'Uma conta foi criada para você no {domain}, clique no link de login abaixo para definir sua senha. O link é válido por {numberOfHours} horas após o envio deste e-mail.', -]; diff --git a/modules/Auth/Language/pt/Auth.php b/modules/Auth/Language/pt/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/pt/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/pt/Contributor.php b/modules/Auth/Language/pt/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/pt/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/pt/MyAccount.php b/modules/Auth/Language/pt/MyAccount.php deleted file mode 100644 index 6ebbb30e..00000000 --- a/modules/Auth/Language/pt/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'My account info', - 'changePassword' => 'Change my password', - 'messages' => [ - 'wrongPasswordError' => "You've entered the wrong password, try again.", - 'passwordChangeSuccess' => 'Password has been successfully changed!', - ], -]; diff --git a/modules/Auth/Language/ro/Auth.php b/modules/Auth/Language/ro/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/ro/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/ro/Contributor.php b/modules/Auth/Language/ro/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/ro/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/ro/MyAccount.php b/modules/Auth/Language/ro/MyAccount.php deleted file mode 100644 index 6ebbb30e..00000000 --- a/modules/Auth/Language/ro/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'My account info', - 'changePassword' => 'Change my password', - 'messages' => [ - 'wrongPasswordError' => "You've entered the wrong password, try again.", - 'passwordChangeSuccess' => 'Password has been successfully changed!', - ], -]; diff --git a/modules/Auth/Language/ro/User.php b/modules/Auth/Language/ro/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/ro/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/ru/Auth.php b/modules/Auth/Language/ru/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/ru/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/ru/Contributor.php b/modules/Auth/Language/ru/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/ru/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/ru/MyAccount.php b/modules/Auth/Language/ru/MyAccount.php deleted file mode 100644 index 6ebbb30e..00000000 --- a/modules/Auth/Language/ru/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'My account info', - 'changePassword' => 'Change my password', - 'messages' => [ - 'wrongPasswordError' => "You've entered the wrong password, try again.", - 'passwordChangeSuccess' => 'Password has been successfully changed!', - ], -]; diff --git a/modules/Auth/Language/ru/User.php b/modules/Auth/Language/ru/User.php deleted file mode 100644 index e7908f5b..00000000 --- a/modules/Auth/Language/ru/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, you cannot edit its roles.', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/sk/Auth.php b/modules/Auth/Language/sk/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/sk/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/sk/User.php b/modules/Auth/Language/sk/User.php deleted file mode 100644 index e7908f5b..00000000 --- a/modules/Auth/Language/sk/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, you cannot edit its roles.', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/sr-latn/Auth.php b/modules/Auth/Language/sr-latn/Auth.php deleted file mode 100644 index 82d4174f..00000000 --- a/modules/Auth/Language/sr-latn/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Vlasnik instance', - 'description' => 'Vlasnik Castopoda.', - ], - 'superadmin' => [ - 'title' => 'Super administrator', - 'description' => 'Ima kompletnu kontrolu nad Castopod-om.', - ], - 'manager' => [ - 'title' => 'Menadžer', - 'description' => 'Upravlja sadržajem na Castopod-u.', - ], - 'podcaster' => [ - 'title' => 'Podkaster', - 'description' => 'Opšti korisnici Castopod-a.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Može pristupiti administratorskom delu Castopod-a.', - 'admin.settings' => 'Može pristupiti podešavanjima Castopod-a.', - 'users.manage' => 'Može upravljati korisnicima Castopod-a.', - 'persons.manage' => 'Može upravljati osobama.', - 'pages.manage' => 'Može upravljati stranicama.', - 'podcasts.view' => 'Može videti sve podkaste.', - 'podcasts.create' => 'Može napraviti nove podkaste.', - 'podcasts.import' => 'Može uvesti nove podkaste.', - 'fediverse.manage-blocks' => 'Može blokirati interakciju Castopoda i fedivers naloga/domena.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Vlasnik podkasta', - 'description' => 'Vlasnik podkasta.', - ], - 'admin' => [ - 'title' => 'Administrator', - 'description' => 'Ima kompletnu kontrolu nad podkastom #{id}.', - ], - 'editor' => [ - 'title' => 'Urednik', - 'description' => 'Upravlja sadržajem i objavama podkasta #{id}.', - ], - 'author' => [ - 'title' => 'Autor', - 'description' => 'Upravlja sadržajem podkasta #{id} ali ne može da ga objavi.', - ], - 'guest' => [ - 'title' => 'Gost', - 'description' => 'Saradnik na podkastu #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Može videti upravljačku tablu i analitiku podkasta #{id}.', - 'edit' => 'Može uređivati podkast #{id}.', - 'delete' => 'Može obrisati podkast #{id}.', - 'manage-import' => 'Može sinhronizovati uvezen podkast #{id}.', - 'manage-persons' => 'Može upravljati pretplatama na podkast #{id}.', - 'manage-subscriptions' => 'Može upravljati pretplatama na podkast #{id}.', - 'manage-contributors' => 'Može upravljati saradnicima na podkastu #{id}.', - 'manage-platforms' => 'Može ubaciti/izbaciti veze ka platformama podkasta #{id}.', - 'manage-publications' => 'Može objaviti podkast #{id}.', - 'manage-notifications' => 'Može videti obaveštenja i označiti ih kao pročitana za podkast #{id}.', - 'interact-as' => 'Može da komunicira kao podkast #{id} i deli, odgovara na i stavlja u omiljene postove.', - 'episodes' => [ - 'view' => 'Može videti upravljačku tablu i analitiku epizoda podkasta #{id}.', - 'create' => 'Može napraviti epizode podkasta #{id}.', - 'edit' => 'Može uređivati epizode podkasta #{id}.', - 'delete' => 'Može obrisati epizode podkasta #{id}.', - 'manage-persons' => 'Može upravljati osobama na epizodama podkasta #{id}.', - 'manage-clips' => 'Može upravljati video klipovima i zvučnim isečcima podkasta #{id}.', - 'manage-publications' => 'Može da objavi/poništi objavljivanje epizoda i postova podkasta #{id}.', - 'manage-comments' => 'Može dodati/obrisati komentar na epizodi podkasta #{id}.', - ], - ], - - // missing keys - 'code' => 'Vaša šestocifrena šifra', - - 'set_password' => 'Podesi lozinku', - - // Welcome email - 'welcomeSubject' => 'Pozvani ste na {siteName}', - 'emailWelcomeMailBody' => 'Za vas je napravljen nalog na {domain}, kliknite na link za prijavu ispod da biste postavili lozinku. Veza je važeća {numberOfHours} sati nakon slanja ove e-pošte.', -]; diff --git a/modules/Auth/Language/sr-latn/Contributor.php b/modules/Auth/Language/sr-latn/Contributor.php deleted file mode 100644 index 39bcbdb9..00000000 --- a/modules/Auth/Language/sr-latn/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Saradnici podkasta', - 'view' => "{username} doprinos {podcastTitle}", - 'add' => 'Dodaj saradnika', - 'add_contributor' => 'Dodaj saradnike za {0}', - 'edit_role' => 'Uredi ulogu za {0}', - 'edit' => 'Izmeni', - 'remove' => 'Ukloni', - 'list' => [ - 'username' => 'Korisničko ime', - 'role' => 'Uloga', - ], - 'form' => [ - 'user' => 'Korisnik', - 'user_placeholder' => 'Izaberi korisnika…', - 'role' => 'Uloga', - 'role_placeholder' => 'Dodaj ulogu…', - 'submit_add' => 'Dodaj saradnika', - 'submit_edit' => 'Ažuriraj ulogu', - ], - 'delete_form' => [ - 'title' => 'Ukloni {contributor}', - 'disclaimer' => - 'Obrisaćete {contributor} iz saradnika. Oni neće moći više da pristupe "{podcastTitle}".', - 'understand' => 'Razumem, želim da uklonim {contributor} iz "{podcastTitle}"', - 'submit' => 'Ukloni', - ], - 'messages' => [ - 'editSuccess' => 'Uloga uspešno promenjena!', - 'editOwnerError' => "Ne možete urediti vlasnika podkasta!", - 'removeOwnerError' => "Ne možete ukloniti vlasnika podkasta!", - 'removeSuccess' => - 'Uspešno ste uklonili {username} iz {podcastTitle}', - 'alreadyAddedError' => - "Saradnik kojeg pokušavate dodati je već dodat!", - ], -]; diff --git a/modules/Auth/Language/sr-latn/MyAccount.php b/modules/Auth/Language/sr-latn/MyAccount.php deleted file mode 100644 index 5fa13d74..00000000 --- a/modules/Auth/Language/sr-latn/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'Infromacije o mom nalogu', - 'changePassword' => 'Promeni moju lozinku', - 'messages' => [ - 'wrongPasswordError' => "Uneli ste pogrešnu lozinku, probajte ponovo.", - 'passwordChangeSuccess' => 'Lozinka je uspešno promenjena!', - ], -]; diff --git a/modules/Auth/Language/sr-latn/User.php b/modules/Auth/Language/sr-latn/User.php deleted file mode 100644 index 5e128ed8..00000000 --- a/modules/Auth/Language/sr-latn/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Uredi {username} uloge", - 'ban' => 'Zabrani', - 'unban' => 'Ukini zabranu', - 'delete' => 'Obriši', - 'create' => 'Novi korisnik', - 'view' => "Informacije o korisniku {username}", - 'all_users' => 'Svi korisnici', - 'list' => [ - 'user' => 'Korisnik', - 'role' => 'Uloga', - 'banned' => 'Zabranjen?', - ], - 'form' => [ - 'email' => 'E-pošta', - 'username' => 'Korisničko ime', - 'password' => 'Lozinka', - 'new_password' => 'Nova lozinka', - 'role' => 'Uloga', - 'roles' => 'Uloge', - 'permissions' => 'Dozvole', - 'submit_create' => 'Kreiraj korisnika', - 'submit_edit' => 'Sačuvaj', - 'submit_password_change' => 'Promeni!', - ], - 'delete_form' => [ - 'title' => 'Ukloni korisnika {user}', - 'disclaimer' => - "Spremate se da trajno uklonite korisnika {user}. Korisnik neće moći više da pristupi administratorskoj zoni.", - 'understand' => 'Shvatam, želim da trajno uklonim korisnika {user}', - 'submit' => 'Obriši', - ], - 'messages' => [ - 'createSuccess' => - 'Korisnik je uspešno kreiran! Poruka dobrodošlice je poslata E-poštom korisniku {username}. Ona sadrži vezu za prijavu a od njih će biti zatraženo resetovanje lozinke nakon prve autentifikacije.', - 'roleEditSuccess' => - "Uloge korisnika {username} su uspešno ažurirane.", - 'banSuccess' => 'Korisnik {username} je zabranjen.', - 'unbanSuccess' => 'Korisniku {username} je skinuta zabrana.', - 'editOwnerError' => - 'Korisnik {username} je vlasnik instance, prosto ne možete dirati vlasnika…', - 'banSuperAdminError' => - 'Korisnik {username} je super administrator, prosto ne možete zabraniti super administratora…', - 'deleteOwnerError' => - 'Korisnik {username} je vlasnik instance, prosto ne možete obrisati vlasnika…', - 'deleteSuperAdminError' => - 'Korisnik {username} je super administrator, prosto ne možete obrisati super administratora…', - 'deleteSuccess' => 'Korisnik {username} je obrisan.', - ], -]; diff --git a/modules/Auth/Language/sv/Auth.php b/modules/Auth/Language/sv/Auth.php deleted file mode 100644 index 386853fe..00000000 --- a/modules/Auth/Language/sv/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instans Ägare', - 'description' => 'Castopod ägaren.', - ], - 'superadmin' => [ - 'title' => 'Super administratör', - 'description' => 'Har fullständig kontroll över Castopod.', - ], - 'manager' => [ - 'title' => 'Hanterare', - 'description' => 'Hanterar Castopods innehåll.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'Generella användare av Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Kan komma åt Castopod admin-området.', - 'admin.settings' => 'Kan komma åt Castopod-inställningarna.', - 'users.manage' => 'Kan hantera Castopod-användare.', - 'persons.manage' => 'Kan hantera personer.', - 'pages.manage' => 'Kan hantera sidor.', - 'podcasts.view' => 'Kan se alla podcasts.', - 'podcasts.create' => 'Kan skapa nya podcasts.', - 'podcasts.import' => 'Kan importera podcasts.', - 'fediverse.manage-blocks' => 'Kan blockera fediverse skådespelare/domäner från att interagera med Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast ägare', - 'description' => 'Podcast ägaren.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Har fullständig kontroll över podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Redigerare', - 'description' => 'Hanterar innehåll och publikationer i podcast #{id}.', - ], - 'author' => [ - 'title' => 'Författare', - 'description' => 'Hanterar innehåll i podcast #{id} men kan inte publicera dem.', - ], - 'guest' => [ - 'title' => 'Gäst', - 'description' => 'Generell bidragsgivare till podcasten #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Kan visa instrumentpanelen och analysen av podcast #{id}.', - 'edit' => 'Kan redigera podcast #{id}.', - 'delete' => 'Kan ta bort podcast #{id}.', - 'manage-import' => 'Kan synkronisera importerad podcast #{id}.', - 'manage-persons' => 'Kan hantera prenumerationer på podcast #{id}.', - 'manage-subscriptions' => 'Kan hantera prenumerationer på podcast #{id}.', - 'manage-contributors' => 'Kan hantera bidragsgivare för podcast #{id}.', - 'manage-platforms' => 'Kan sätta/ta bort plattformslänkar för podcast #{id}.', - 'manage-publications' => 'Kan publicera podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Kan interagera som podcasten #{id} för att favorita, dela eller svara på inlägg.', - 'episodes' => [ - 'view' => 'Kan visa instrumentpaneler och analyser av podcast #{id}s avsnitt.', - 'create' => 'Kan skapa avsnitt för podcast #{id}.', - 'edit' => 'Kan redigera avsnitt av podcast #{id}.', - 'delete' => 'Kan ta bort avsnitt av podcast #{id}.', - 'manage-persons' => 'Kan hantera avsnittpersoner i podcast #{id}.', - 'manage-clips' => 'Kan hantera videoklipp eller ljudklipp från podcasten #{id}.', - 'manage-publications' => 'Kan publicera/avpublicera avsnitt och inlägg i podcast #{id}.', - 'manage-comments' => 'Kan skapa/ta bort avsnitt kommentarer från podcasten #{id}.', - ], - ], - - // missing keys - 'code' => 'Din 6-siffriga kod', - - 'set_password' => 'Välj ett lösenord', - - // Welcome email - 'welcomeSubject' => 'Du har blivit inbjuden till {siteName}', - 'emailWelcomeMailBody' => 'Ett konto skapades för dig på {domain}, klicka på inloggningslänken nedan för att ange ditt lösenord. Länken är giltig i {numberOfHours} timmar efter att detta e-postmeddelande skickats.', -]; diff --git a/modules/Auth/Language/sv/Contributor.php b/modules/Auth/Language/sv/Contributor.php deleted file mode 100644 index 572b91ad..00000000 --- a/modules/Auth/Language/sv/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Redigera', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Användarnamn', - 'role' => 'Roll', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Roll', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Uppdatera roll', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/sv/MyAccount.php b/modules/Auth/Language/sv/MyAccount.php deleted file mode 100644 index 78a66902..00000000 --- a/modules/Auth/Language/sv/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'My account info', - 'changePassword' => 'Ändra mitt lösenord', - 'messages' => [ - 'wrongPasswordError' => "You've entered the wrong password, try again.", - 'passwordChangeSuccess' => 'Password has been successfully changed!', - ], -]; diff --git a/modules/Auth/Language/sv/User.php b/modules/Auth/Language/sv/User.php deleted file mode 100644 index d5a57d48..00000000 --- a/modules/Auth/Language/sv/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Radera', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Användarnamn', - 'password' => 'Lösenord', - 'new_password' => 'Nytt lösenord', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! {username} will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, you cannot edit its roles.', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/uk/Auth.php b/modules/Auth/Language/uk/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/uk/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/uk/Contributor.php b/modules/Auth/Language/uk/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/uk/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/uk/MyAccount.php b/modules/Auth/Language/uk/MyAccount.php deleted file mode 100644 index 0b511d51..00000000 --- a/modules/Auth/Language/uk/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'Інформація про аккаунт', - 'changePassword' => 'Змінити мій пароль', - 'messages' => [ - 'wrongPasswordError' => "Ви ввели неправильний пароль, спробуйте ще раз.", - 'passwordChangeSuccess' => 'Ваш пароль успішно змінено.', - ], -]; diff --git a/modules/Auth/Language/uk/User.php b/modules/Auth/Language/uk/User.php deleted file mode 100644 index a9383f65..00000000 --- a/modules/Auth/Language/uk/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Змінити роль «%{name}»", - 'ban' => 'Забанити', - 'unban' => 'Розбанити', - 'delete' => 'Видалити', - 'create' => 'Новий користувач', - 'view' => "{username}інформація", - 'all_users' => 'Усі користувачі', - 'list' => [ - 'user' => 'Користувач', - 'role' => 'Роль', - 'banned' => 'Забанені?', - ], - 'form' => [ - 'email' => 'Пошта', - 'username' => 'Ім\'я користувача', - 'password' => 'Пароль', - 'new_password' => 'Новий пароль', - 'role' => 'Роль', - 'roles' => 'Ролі', - 'permissions' => 'Дозволи', - 'submit_create' => 'Створити користувача', - 'submit_edit' => 'Зберегти', - 'submit_password_change' => 'Змінити', - ], - 'delete_form' => [ - 'title' => 'Видалити користувача?', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Language/zh-hans/Auth.php b/modules/Auth/Language/zh-hans/Auth.php deleted file mode 100644 index b3d371e5..00000000 --- a/modules/Auth/Language/zh-hans/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => '实例所有者', - 'description' => 'Castopod 所有者', - ], - 'superadmin' => [ - 'title' => '超级管理员', - 'description' => '拥有对 Castopod 的完全控制。', - ], - 'manager' => [ - 'title' => '管理', - 'description' => '管理 Castopod 的内容。', - ], - 'podcaster' => [ - 'title' => '播客', - 'description' => 'Castopod 的普通用户。', - ], - ], - 'instance_permissions' => [ - 'admin.access' => '可以访问 Castopod 管理区域。', - 'admin.settings' => '可以访问 Castopod 设置。', - 'users.manage' => '可以管理 Castopod 用户。', - 'persons.manage' => '可以管理人员。', - 'pages.manage' => '可以管理页面。', - 'podcasts.view' => '可以查看所有播客。', - 'podcasts.create' => '可以创建新播客。', - 'podcasts.import' => '可以导入播客。', - 'fediverse.manage-blocks' => '可以阻止联邦宇宙参与者/域与 Castopod 交互。', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => '播客封面', - 'description' => '播客所有者。', - ], - 'admin' => [ - 'title' => '管理员', - 'description' => '完全控制播客 #{id}。', - ], - 'editor' => [ - 'title' => '编辑', - 'description' => '管理播客 #{id} 的内容和出版物。', - ], - 'author' => [ - 'title' => '作者', - 'description' => '管理播客 #{id} 的内容,但不能发布。', - ], - 'guest' => [ - 'title' => '访客', - 'description' => '播客 #{id} 的普通贡献者。', - ], - ], - 'podcast_permissions' => [ - 'view' => '可以查看播客 #{id} 的仪表板和分析。', - 'edit' => '可以编辑播客 #{id}。', - 'delete' => '可以删除播客 #{id}。', - 'manage-import' => '可以同步导入的播客 #{id}。', - 'manage-persons' => '可以管理播客 #{id} 的订阅。', - 'manage-subscriptions' => '可以管理播客 #{id} 的订阅。', - 'manage-contributors' => '可以管理播客 #{id} 的贡献者。', - 'manage-platforms' => '可以设置/删除播客 #{id} 的平台链接。', - 'manage-publications' => '可以发布播客 #{id}。', - 'manage-notifications' => '可以查看播客 #{id} 的通知并将其标记为已读。', - 'interact-as' => '可以在播客 #{id} 进行互动,以收藏、分享或回复帖子。', - 'episodes' => [ - 'view' => '可以查看播客 #{id} 的仪表板和分析。', - 'create' => '可以为播客 #{id} 创建剧集。', - 'edit' => '可以编辑播客 #{id} 的剧集。', - 'delete' => '可以删除播客 #{id} 的剧集。', - 'manage-persons' => '可以管理播客 #{id} 的剧集人。', - 'manage-clips' => '可以管理播客 #{id} 的视频剪辑或声音片段。', - 'manage-publications' => '可以发布/取消发布播客 #{id} 的剧集和帖子。', - 'manage-comments' => '可以创建/删除播客 #{id} 的剧集评论。', - ], - ], - - // missing keys - 'code' => '你的6位验证码', - - 'set_password' => '设置你的密码', - - // Welcome email - 'welcomeSubject' => '你已受邀加入 {siteName}', - 'emailWelcomeMailBody' => '在 {domain} 上为你创建了一个帐户,单击下面的登录链接设置您的密码。 该链接在发送此电子邮件后的 {numberOfHours} 小时内有效。', -]; diff --git a/modules/Auth/Language/zh-hant/Auth.php b/modules/Auth/Language/zh-hant/Auth.php deleted file mode 100644 index b366563a..00000000 --- a/modules/Auth/Language/zh-hant/Auth.php +++ /dev/null @@ -1,95 +0,0 @@ - [ - 'owner' => [ - 'title' => 'Instance Owner', - 'description' => 'The Castopod owner.', - ], - 'superadmin' => [ - 'title' => 'Super admin', - 'description' => 'Has complete control over Castopod.', - ], - 'manager' => [ - 'title' => 'Manager', - 'description' => 'Manages Castopod\'s content.', - ], - 'podcaster' => [ - 'title' => 'Podcaster', - 'description' => 'General users of Castopod.', - ], - ], - 'instance_permissions' => [ - 'admin.access' => 'Can access the Castopod admin area.', - 'admin.settings' => 'Can access the Castopod settings.', - 'users.manage' => 'Can manage Castopod users.', - 'persons.manage' => 'Can manage persons.', - 'pages.manage' => 'Can manage pages.', - 'podcasts.view' => 'Can view all podcasts.', - 'podcasts.create' => 'Can create new podcasts.', - 'podcasts.import' => 'Can import podcasts.', - 'fediverse.manage-blocks' => 'Can block fediverse actors/domains from interacting with Castopod.', - ], - 'podcast_groups' => [ - 'owner' => [ - 'title' => 'Podcast Owner', - 'description' => 'The podcast owner.', - ], - 'admin' => [ - 'title' => 'Admin', - 'description' => 'Has complete control of podcast #{id}.', - ], - 'editor' => [ - 'title' => 'Editor', - 'description' => 'Manages content and publications of podcast #{id}.', - ], - 'author' => [ - 'title' => 'Author', - 'description' => 'Manages content of podcast #{id} but cannot publish them.', - ], - 'guest' => [ - 'title' => 'Guest', - 'description' => 'General contributor of the podcast #{id}.', - ], - ], - 'podcast_permissions' => [ - 'view' => 'Can view dashboard and analytics of podcast #{id}.', - 'edit' => 'Can edit podcast #{id}.', - 'delete' => 'Can delete podcast #{id}.', - 'manage-import' => 'Can synchronize imported podcast #{id}.', - 'manage-persons' => 'Can manage subscriptions of podcast #{id}.', - 'manage-subscriptions' => 'Can manage subscriptions of podcast #{id}.', - 'manage-contributors' => 'Can manage contributors of podcast #{id}.', - 'manage-platforms' => 'Can set/remove platform links of podcast #{id}.', - 'manage-publications' => 'Can publish podcast #{id}.', - 'manage-notifications' => 'Can view and mark notifications as read for podcast #{id}.', - 'interact-as' => 'Can interact as the podcast #{id} to favourite, share or reply to posts.', - 'episodes' => [ - 'view' => 'Can view dashboards and analytics of podcast #{id}\'s episodes.', - 'create' => 'Can create episodes for podcast #{id}.', - 'edit' => 'Can edit episodes of podcast #{id}.', - 'delete' => 'Can delete episodes of podcast #{id}.', - 'manage-persons' => 'Can manage episode persons of podcast #{id}.', - 'manage-clips' => 'Can manage video clips or soundbites of podcast #{id}.', - 'manage-publications' => 'Can publish/unpublish episodes and posts of podcast #{id}.', - 'manage-comments' => 'Can create/remove episode comments of podcast #{id}.', - ], - ], - - // missing keys - 'code' => 'Your 6-digit code', - - 'set_password' => 'Set your password', - - // Welcome email - 'welcomeSubject' => 'You\'ve been invited to {siteName}', - 'emailWelcomeMailBody' => 'An account was created for you on {domain}, click on the login link below to set your password. The link is valid for {numberOfHours} hours after this email was sent.', -]; diff --git a/modules/Auth/Language/zh-hant/Contributor.php b/modules/Auth/Language/zh-hant/Contributor.php deleted file mode 100644 index c70badc0..00000000 --- a/modules/Auth/Language/zh-hant/Contributor.php +++ /dev/null @@ -1,47 +0,0 @@ - 'Podcast contributors', - 'view' => "{username}'s contribution to {podcastTitle}", - 'add' => 'Add contributor', - 'add_contributor' => 'Add a contributor for {0}', - 'edit_role' => 'Update role for {0}', - 'edit' => 'Edit', - 'remove' => 'Remove', - 'list' => [ - 'username' => 'Username', - 'role' => 'Role', - ], - 'form' => [ - 'user' => 'User', - 'user_placeholder' => 'Select a user…', - 'role' => 'Role', - 'role_placeholder' => 'Select its role…', - 'submit_add' => 'Add contributor', - 'submit_edit' => 'Update role', - ], - 'delete_form' => [ - 'title' => 'Remove {contributor}', - 'disclaimer' => - 'You are about to remove {contributor} from contributors. They will not be able to access "{podcastTitle}" anymore.', - 'understand' => 'I understand, I want to remove {contributor} from "{podcastTitle}"', - 'submit' => 'Remove', - ], - 'messages' => [ - 'editSuccess' => 'Role successfully changed!', - 'editOwnerError' => "You can't edit the podcast owner!", - 'removeOwnerError' => "You can't remove the podcast owner!", - 'removeSuccess' => - 'You have successfully removed {username} from {podcastTitle}', - 'alreadyAddedError' => - "The contributor you're trying to add has already been added!", - ], -]; diff --git a/modules/Auth/Language/zh-hant/MyAccount.php b/modules/Auth/Language/zh-hant/MyAccount.php deleted file mode 100644 index 6ebbb30e..00000000 --- a/modules/Auth/Language/zh-hant/MyAccount.php +++ /dev/null @@ -1,18 +0,0 @@ - 'My account info', - 'changePassword' => 'Change my password', - 'messages' => [ - 'wrongPasswordError' => "You've entered the wrong password, try again.", - 'passwordChangeSuccess' => 'Password has been successfully changed!', - ], -]; diff --git a/modules/Auth/Language/zh-hant/User.php b/modules/Auth/Language/zh-hant/User.php deleted file mode 100644 index 32ec560c..00000000 --- a/modules/Auth/Language/zh-hant/User.php +++ /dev/null @@ -1,60 +0,0 @@ - "Edit {username}'s role", - 'ban' => 'Ban', - 'unban' => 'Unban', - 'delete' => 'Delete', - 'create' => 'New user', - 'view' => "{username}'s info", - 'all_users' => 'All users', - 'list' => [ - 'user' => 'User', - 'role' => 'Role', - 'banned' => 'Banned?', - ], - 'form' => [ - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - 'new_password' => 'New Password', - 'role' => 'Role', - 'roles' => 'Roles', - 'permissions' => 'Permissions', - 'submit_create' => 'Create user', - 'submit_edit' => 'Save', - 'submit_password_change' => 'Change!', - ], - 'delete_form' => [ - 'title' => 'Delete {user}', - 'disclaimer' => - "You are about to delete {user} permanently. They will not be able to access the admin area anymore.", - 'understand' => 'I understand, I want to delete {user} permanently', - 'submit' => 'Delete', - ], - 'messages' => [ - 'createSuccess' => - 'User created successfully! A welcome email was sent to {username} with a login link, they will be prompted with a password reset upon first authentication.', - 'roleEditSuccess' => - "{username}'s roles have been successfully updated.", - 'banSuccess' => '{username} has been banned.', - 'unbanSuccess' => '{username} has been unbanned.', - 'editOwnerError' => - '{username} is the instance owner, one does not simply touch the owner…', - 'banSuperAdminError' => - '{username} is a superadmin, one does not simply ban a superadmin…', - 'deleteOwnerError' => - '{username} is the instance owner, one does not simply delete the owner…', - 'deleteSuperAdminError' => - '{username} is a superadmin, one does not simply delete a superadmin…', - 'deleteSuccess' => '{username} has been deleted.', - ], -]; diff --git a/modules/Auth/Models/UserModel.php b/modules/Auth/Models/UserModel.php deleted file mode 100644 index 16ac112a..00000000 --- a/modules/Auth/Models/UserModel.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ - protected $allowedFields = [ - 'username', - 'status', - 'status_message', - 'active', - 'is_owner', - 'last_active', - 'deleted_at', - ]; - - /** - * @return User[] - */ - public function getPodcastContributors(int $podcastId): array - { - return $this->select('users.*') - ->join('auth_groups_users', 'users.id = auth_groups_users.user_id') - ->like('auth_groups_users.group', "podcast#{$podcastId}-") - ->findAll(); - } - - public function getPodcastContributor(int $contributorId, int $podcastId): ?User - { - return $this->select('users.*') - ->join('auth_groups_users', 'users.id = auth_groups_users.user_id') - ->where('users.id', $contributorId) - ->like('auth_groups_users.group', "podcast#{$podcastId}-") - ->first(); - } -} diff --git a/modules/Fediverse/ActivityRequest.php b/modules/Fediverse/ActivityRequest.php index f5b56a29..cfd268ab 100644 --- a/modules/Fediverse/ActivityRequest.php +++ b/modules/Fediverse/ActivityRequest.php @@ -14,6 +14,7 @@ use CodeIgniter\HTTP\CURLRequest; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\URI; use CodeIgniter\I18n\Time; +use Config\Services; use Modules\Fediverse\Core\Activity; use phpseclib\Crypt\RSA; @@ -32,7 +33,7 @@ class ActivityRequest public function __construct(string $uri, ?string $activityPayload = null) { - $this->request = service('curlrequest'); + $this->request = Services::curlrequest(); if ($activityPayload !== null) { $this->request->setBody($activityPayload); @@ -41,8 +42,8 @@ class ActivityRequest $this->options = [ 'headers' => [ 'Content-Type' => 'application/activity+json', - 'Accept' => 'application/activity+json', - 'User-Agent' => 'Castopod/' . CP_VERSION . '; +' . base_url('', 'https'), + 'Accept' => 'application/activity+json', + 'User-Agent' => 'Castopod/' . CP_VERSION . '; +' . base_url('', 'https'), // TODO: outgoing and incoming requests ], ]; @@ -81,7 +82,7 @@ class ActivityRequest $date = Time::now('GMT')->format('D, d M Y H:i:s T'); $digest = 'SHA-256=' . base64_encode($this->getBodyDigest()); $contentType = $this->options['headers']['Content-Type']; - $contentLength = (string) strlen((string) $this->request->getBody()); + $contentLength = (string) strlen($this->request->getBody()); $userAgent = 'Castopod/' . CP_VERSION . '; +' . base_url('', 'https'); $plainText = "(request-target): post {$path}\nhost: {$host}\ndate: {$date}\ndigest: {$digest}\ncontent-type: {$contentType}\ncontent-length: {$contentLength}\nuser-agent: {$userAgent}"; @@ -97,20 +98,20 @@ class ActivityRequest $this->options = [ 'headers' => [ - 'Content-Type' => $contentType, + 'Content-Type' => $contentType, 'Content-Length' => $contentLength, - 'Authorization' => "Signature {$signatureHeader}", - 'Signature' => $signatureHeader, - 'Host' => $host, - 'Date' => $date, - 'User-Agent' => $userAgent, - 'Digest' => $digest, + 'Authorization' => "Signature {$signatureHeader}", + 'Signature' => $signatureHeader, + 'Host' => $host, + 'Date' => $date, + 'User-Agent' => $userAgent, + 'Digest' => $digest, ], ]; } protected function getBodyDigest(): string { - return hash('sha256', (string) $this->request->getBody(), true); + return hash('sha256', $this->request->getBody(), true); } } diff --git a/modules/Fediverse/Commands/Broadcast.php b/modules/Fediverse/Commands/Broadcast.php deleted file mode 100644 index 3e096946..00000000 --- a/modules/Fediverse/Commands/Broadcast.php +++ /dev/null @@ -1,71 +0,0 @@ -getScheduledActivities(10); - - foreach ($scheduledActivities as $scheduledActivity) { - // set activity post to processing - model('ActivityModel', false) - ->update($scheduledActivity->id, [ - 'status' => 'processing', - ]); - } - - // Send activity to all followers - foreach ($scheduledActivities as $scheduledActivity) { - try { - if ($scheduledActivity->target_actor_id !== null) { - if ($scheduledActivity->actor_id !== $scheduledActivity->target_actor_id) { - // send activity to targeted actor - send_activity_to_actor( - $scheduledActivity->actor, - $scheduledActivity->targetActor, - json_encode($scheduledActivity->payload, JSON_THROW_ON_ERROR), - ); - } - } else { - // send activity to all actor followers - send_activity_to_followers( - $scheduledActivity->actor, - json_encode($scheduledActivity->payload, JSON_THROW_ON_ERROR), - ); - } - - // set activity post to delivered - model('ActivityModel', false) - ->update($scheduledActivity->id, [ - 'status' => 'delivered', - ]); - - } catch (Exception) { - // set activity post to delivered - model('ActivityModel', false) - ->update($scheduledActivity->id, [ - 'status' => 'failed', - ]); - } - } - } -} diff --git a/modules/Fediverse/Config/Fediverse.php b/modules/Fediverse/Config/Fediverse.php index a35e88dd..382153a8 100644 --- a/modules/Fediverse/Config/Fediverse.php +++ b/modules/Fediverse/Config/Fediverse.php @@ -10,9 +10,9 @@ declare(strict_types=1); namespace Modules\Fediverse\Config; -use App\Libraries\NoteObject; use CodeIgniter\Config\BaseConfig; use Modules\Fediverse\Objects\ActorObject; +use Modules\Fediverse\Objects\NoteObject; class Fediverse extends BaseConfig { @@ -23,7 +23,6 @@ class Fediverse extends BaseConfig */ public string $actorObject = ActorObject::class; - // FIXME: hotfix applied to have episodes show up in posts public string $noteObject = NoteObject::class; /** @@ -31,14 +30,16 @@ class Fediverse extends BaseConfig * Default avatar and cover images * -------------------------------------------------------------------- */ - public string $defaultAvatarImagePath = 'avatar-default.jpg'; + public string $defaultAvatarImagePath = 'media/avatar-default.jpg'; public string $defaultAvatarImageMimetype = 'image/jpeg'; - public string $defaultCoverImagePath = 'banner-default.jpg'; + public string $defaultCoverImagePath = 'media/banner-default.jpg'; public string $defaultCoverImageMimetype = 'image/jpeg'; + public string $tablesPrefix = 'fediverse_'; + /** * -------------------------------------------------------------------- * Cache options diff --git a/modules/Fediverse/Config/Registrar.php b/modules/Fediverse/Config/Registrar.php deleted file mode 100644 index 3c28460f..00000000 --- a/modules/Fediverse/Config/Registrar.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ - public static function Filters(): array - { - return [ - 'aliases' => [ - 'fediverse' => FediverseFilter::class, - ], - ]; - } -} diff --git a/modules/Fediverse/Config/Routes.php b/modules/Fediverse/Config/Routes.php index 1fb7fe0c..06fa16de 100644 --- a/modules/Fediverse/Config/Routes.php +++ b/modules/Fediverse/Config/Routes.php @@ -2,15 +2,13 @@ declare(strict_types=1); -use CodeIgniter\Router\RouteCollection; - /** * @copyright 2021 Ad Aures * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 * @link https://castopod.org/ */ -/** @var RouteCollection $routes */ +$routes = service('routes'); $routes->addPlaceholder('actorUsername', '[a-zA-Z0-9\_]{1,32}'); $routes->addPlaceholder( @@ -37,22 +35,23 @@ $routes->group('', [ // Actor $routes->group('@(:actorUsername)', static function ($routes): void { // Actor - $routes->get('/', 'ActorController::index/$1', [ + $routes->get('/', 'ActorController/$1', [ 'as' => 'actor', ]); $routes->post('inbox', 'ActorController::inbox/$1', [ - 'as' => 'inbox', - 'filter' => 'fediverse:verify-activitystream,verify-blocks,verify-signature', + 'as' => 'inbox', + 'filter' => + 'fediverse:verify-activitystream,verify-blocks,verify-signature', ]); $routes->get('outbox', 'ActorController::outbox/$1', [ - 'as' => 'outbox', + 'as' => 'outbox', 'filter' => 'fediverse:verify-activitystream', ]); $routes->get('followers', 'ActorController::followers/$1', [ - 'as' => 'followers', + 'as' => 'followers', 'filter' => 'fediverse::activity-stream', ]); - $routes->post('follow', 'ActorController::followAction/$1', [ + $routes->post('follow', 'ActorController::attemptFollow/$1', [ 'as' => 'attempt-follow', ]); $routes->get('activities/(:uuid)', 'ActorController::activity/$1/$2', [ @@ -60,18 +59,18 @@ $routes->group('', [ ]); }); // Post - $routes->post('posts/create', 'PostController::createAction/$1', [ + $routes->post('posts/new', 'PostController::attemptCreate/$1', [ 'as' => 'post-attempt-create', ]); - $routes->get('posts/(:uuid)', 'PostController::index/$1', [ + $routes->get('posts/(:uuid)', 'PostController/$1', [ 'as' => 'post', ]); - $routes->get('posts/(:uuid)/replies', 'PostController::index/$1', [ + $routes->get('posts/(:uuid)/replies', 'PostController/$1', [ 'as' => 'post-replies', ]); $routes->post( 'posts/(:uuid)/remote/(:postAction)', - 'PostController::remoteActionAction/$1/$2/$3', + 'PostController::attemptRemoteAction/$1/$2/$3', [ 'as' => 'post-attempt-remote-action', ], @@ -79,28 +78,28 @@ $routes->group('', [ // Blocking actors and domains $routes->post( 'fediverse-block-actor', - 'BlockController::blockActorAction', + 'BlockController::attemptBlockActor', [ 'as' => 'fediverse-attempt-block-actor', ], ); $routes->post( 'fediverse-block-domain', - 'BlockController::blockDomainAction', + 'BlockController::attemptBlockDomain', [ 'as' => 'fediverse-attempt-block-domain', ], ); $routes->post( 'fediverse-unblock-actor', - 'BlockController::unblockActorAction', + 'BlockController::attemptUnblockActor', [ 'as' => 'fediverse-attempt-unblock-actor', ], ); $routes->post( 'fediverse-unblock-domain', - 'BlockController::unblockDomainAction', + 'BlockController::attemptUnblockDomain', [ 'as' => 'fediverse-attempt-unblock-domain', ], diff --git a/modules/Fediverse/Controllers/ActivityPubController.php b/modules/Fediverse/Controllers/ActivityPubController.php index bceee417..fe94c9a1 100644 --- a/modules/Fediverse/Controllers/ActivityPubController.php +++ b/modules/Fediverse/Controllers/ActivityPubController.php @@ -11,11 +11,14 @@ declare(strict_types=1); namespace Modules\Fediverse\Controllers; use CodeIgniter\Controller; -use CodeIgniter\HTTP\ResponseInterface; +use CodeIgniter\HTTP\Response; class ActivityPubController extends Controller { - public function preflight(): ResponseInterface + /** + * @noRector ReturnTypeDeclarationRector + */ + public function preflight(): Response { return $this->response->setHeader('Access-Control-Allow-Origin', '*') // for allowing any domain, insecure ->setHeader('Access-Control-Allow-Headers', '*') // for allowing any headers, insecure diff --git a/modules/Fediverse/Controllers/ActorController.php b/modules/Fediverse/Controllers/ActorController.php index a567436b..44b0dc3a 100644 --- a/modules/Fediverse/Controllers/ActorController.php +++ b/modules/Fediverse/Controllers/ActorController.php @@ -17,18 +17,15 @@ use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\I18n\Time; use Exception; use Modules\Fediverse\Config\Fediverse; -use Modules\Fediverse\Entities\Activity; use Modules\Fediverse\Entities\Actor; use Modules\Fediverse\Entities\Post; -use Modules\Fediverse\Models\ActivityModel; -use Modules\Fediverse\Models\ActorModel; use Modules\Fediverse\Objects\OrderedCollectionObject; use Modules\Fediverse\Objects\OrderedCollectionPage; class ActorController extends Controller { /** - * @var list + * @var string[] */ protected $helpers = ['fediverse']; @@ -48,7 +45,7 @@ class ActorController extends Controller } if ( - ! ($actor = model('ActorModel', false)->getActorByUsername($params[0])) instanceof Actor + ($actor = model('ActorModel', false)->getActorByUsername($params[0])) === null ) { throw PageNotFoundException::forPageNotFound(); } @@ -59,6 +56,9 @@ class ActorController extends Controller return $this->{$method}(...$params); } + /** + * @noRector ReturnTypeDeclarationRector + */ public function index(): ResponseInterface { $actorObjectClass = $this->config->actorObject; @@ -71,6 +71,8 @@ class ActorController extends Controller /** * Handles incoming requests from fediverse servers + * + * @noRector ReturnTypeDeclarationRector */ public function inbox(): ResponseInterface { @@ -91,6 +93,7 @@ class ActorController extends Controller ); // switch/case on activity type + /** @phpstan-ignore-next-line */ switch ($payload->type) { case 'Create': if ($payload->object->type === 'Note') { @@ -103,22 +106,21 @@ class ActorController extends Controller ->getPostByUri($payload->object->inReplyTo); $reply = null; - if ($replyToPost instanceof Post) { + if ($replyToPost !== null) { // TODO: strip content from html to retrieve message // remove all html tags and reconstruct message with mentions? $message = get_message_from_object($payload->object); $reply = new Post([ - 'uri' => $payload->object->id, - 'actor_id' => $payloadActor->id, + 'uri' => $payload->object->id, + 'actor_id' => $payloadActor->id, 'in_reply_to_id' => $replyToPost->id, - 'message' => $message, - 'is_private' => ! is_note_public($payload->object), - 'published_at' => Time::parse($payload->object->published), + 'message' => $message, + 'published_at' => Time::parse($payload->object->published), ]); } - if ($reply instanceof Post) { + if ($reply !== null) { $postId = model('PostModel', false) ->addReply($reply, true, false); @@ -137,9 +139,9 @@ class ActorController extends Controller ->setJSON([]); case 'Delete': $postToDelete = model('PostModel', false) - ->getPostByUri($payload->object); + ->getPostByUri($payload->object->id); - if ($postToDelete instanceof Post) { + if ($postToDelete !== null) { model('PostModel', false) ->removePost($postToDelete, false); } @@ -163,7 +165,7 @@ class ActorController extends Controller $post = model('PostModel', false) ->getPostByUri($payload->object); - if ($post instanceof Post) { + if ($post !== null) { // Like side-effect model('FavouriteModel', false) ->addFavourite($payloadActor, $post, false); @@ -180,7 +182,7 @@ class ActorController extends Controller $post = model('PostModel', false) ->getPostByUri($payload->object); - if ($post instanceof Post) { + if ($post !== null) { model('ActivityModel', false) ->update($activityId, [ 'post_id' => $post->id, @@ -194,6 +196,7 @@ class ActorController extends Controller ->setJSON([]); case 'Undo': // switch/case on the type of activity to undo + /** @phpstan-ignore-next-line */ switch ($payload->object->type) { case 'Follow': // revert side-effect by removing follow from database @@ -207,7 +210,7 @@ class ActorController extends Controller $post = model('PostModel', false) ->getPostByUri($payload->object->object); - if ($post instanceof Post) { + if ($post !== null) { // revert side-effect by removing favourite from database model('FavouriteModel', false) ->removeFavourite($payloadActor, $post, false); @@ -225,10 +228,10 @@ class ActorController extends Controller ->getPostByUri($payload->object->object); $reblogPost = null; - if ($post instanceof Post) { + if ($post !== null) { $reblogPost = model('PostModel', false) ->where([ - 'actor_id' => $payloadActor->id, + 'actor_id' => $payloadActor->id, 'reblog_of_id' => service('uuid') ->fromString($post->id) ->getBytes(), @@ -236,7 +239,7 @@ class ActorController extends Controller ->first(); } - if ($reblogPost instanceof \App\Entities\Post) { + if ($reblogPost !== null) { model('PostModel', false) ->undoReblog($reblogPost, false); @@ -261,10 +264,12 @@ class ActorController extends Controller } } + /** + * @noRector ReturnTypeDeclarationRector + */ public function outbox(): ResponseInterface { // get published activities by publication date - /** @var ActivityModel $actorActivity */ $actorActivity = model('ActivityModel', false) ->where('actor_id', $this->actor->id) ->where('`created_at` <= UTC_TIMESTAMP()', null, false) @@ -277,7 +282,6 @@ class ActorController extends Controller $pager = $actorActivity->pager; $collection = new OrderedCollectionObject(null, $pager); } else { - /** @var Activity[] $paginatedActivity */ $paginatedActivity = $actorActivity->paginate(12, 'default', $pageNumber); $pager = $actorActivity->pager; $orderedItems = []; @@ -293,14 +297,19 @@ class ActorController extends Controller ->setBody($collection->toJSON()); } + /** + * @noRector ReturnTypeDeclarationRector + */ public function followers(): ResponseInterface { + $tablesPrefix = config('Fediverse') + ->tablesPrefix; + // get followers for a specific actor - /** @var ActorModel $followers */ $followers = model('ActorModel', false) - ->join('fediverse_follows', 'fediverse_follows.actor_id = id', 'inner') - ->where('fediverse_follows.target_actor_id', $this->actor->id) - ->orderBy('fediverse_follows.created_at', 'DESC'); + ->join($tablesPrefix . 'follows', $tablesPrefix . 'follows.actor_id = id', 'inner') + ->where($tablesPrefix . 'follows.target_actor_id', $this->actor->id) + ->orderBy($tablesPrefix . 'follows.created_at', 'DESC'); $pageNumber = (int) $this->request->getGet('page'); @@ -309,7 +318,6 @@ class ActorController extends Controller $pager = $followers->pager; $followersCollection = new OrderedCollectionObject(null, $pager); } else { - /** @var Actor[] $paginatedFollowers */ $paginatedFollowers = $followers->paginate(12, 'default', $pageNumber); $pager = $followers->pager; @@ -326,10 +334,11 @@ class ActorController extends Controller ->setBody($followersCollection->toJSON()); } - public function followAction(): RedirectResponse + public function attemptFollow(): RedirectResponse | ResponseInterface { $rules = [ - 'handle' => 'regex_match[/^@?(?P[\w\.\-]+)@(?P[\w\.\-]+)(?P:[\d]+)?$/]', + 'handle' => + 'regex_match[/^@?(?P[\w\.\-]+)@(?P[\w\.\-]+)(?P:[\d]+)?$/]', ]; if (! $this->validate($rules)) { @@ -339,15 +348,13 @@ class ActorController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - helper('text'); // get webfinger data from actor // parse actor id to get actor and domain // check if actor and domain exist - $handle = $validData['handle']; + $handle = $this->request->getPost('handle'); $parts = split_handle($handle); try { @@ -375,14 +382,17 @@ class ActorController extends Controller } return redirect()->to( - str_replace('{uri}', urlencode($this->actor->uri), (string) $data->links[$ostatusKey]->template), + str_replace('{uri}', urlencode($this->actor->uri), $data->links[$ostatusKey]->template), ); } + /** + * @noRector ReturnTypeDeclarationRector + */ public function activity(string $activityId): ResponseInterface { if ( - ! ($activity = model('ActivityModel', false)->getActivityById($activityId)) instanceof Activity + ! ($activity = model('ActivityModel', false)->getActivityById($activityId)) ) { throw PageNotFoundException::forPageNotFound(); } diff --git a/modules/Fediverse/Controllers/BlockController.php b/modules/Fediverse/Controllers/BlockController.php index e5304b0b..abf6a7c4 100644 --- a/modules/Fediverse/Controllers/BlockController.php +++ b/modules/Fediverse/Controllers/BlockController.php @@ -17,11 +17,11 @@ use Exception; class BlockController extends Controller { /** - * @var list + * @var string[] */ protected $helpers = ['fediverse']; - public function blockActorAction(): RedirectResponse + public function attemptBlockActor(): RedirectResponse { $rules = [ 'handle' => 'required|regex_match[/^@?([\w\.\-]+)@([\w\.\-]+)(:[\d]+)?$/]', @@ -34,9 +34,7 @@ class BlockController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - $handle = $validData['handle']; + $handle = $this->request->getPost('handle'); if ($parts = split_handle($handle)) { try { @@ -58,7 +56,7 @@ class BlockController extends Controller ])); } - public function unblockActorAction(): RedirectResponse + public function attemptUnblockActor(): RedirectResponse { $rules = [ 'actor_id' => 'required', @@ -71,16 +69,14 @@ class BlockController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - model('ActorModel', false) - ->unblockActor((int) $validData['actor_id']); + ->unblockActor((int) $this->request->getPost('actor_id')); return redirect()->back() ->with('message', lang('Fediverse.messages.unblockActorSuccess')); } - public function blockDomainAction(): RedirectResponse + public function attemptBlockDomain(): RedirectResponse { $rules = [ 'domain' => 'required|regex_match[/^[\w\-\.]+[\w]+(:[\d]+)?/]', @@ -93,9 +89,7 @@ class BlockController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - $domain = $validData['domain']; + $domain = $this->request->getPost('domain'); model('BlockedDomainModel', false) ->blockDomain($domain); @@ -105,7 +99,7 @@ class BlockController extends Controller ])); } - public function unblockDomainAction(): RedirectResponse + public function attemptUnblockDomain(): RedirectResponse { $rules = [ 'domain' => 'required', @@ -118,9 +112,7 @@ class BlockController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - $domain = $validData['domain']; + $domain = $this->request->getPost('domain'); model('BlockedDomainModel', false) ->unblockDomain($domain); diff --git a/modules/Fediverse/Controllers/NodeInfo2Controller.php b/modules/Fediverse/Controllers/NodeInfo2Controller.php index 4457c600..60ef6cb2 100644 --- a/modules/Fediverse/Controllers/NodeInfo2Controller.php +++ b/modules/Fediverse/Controllers/NodeInfo2Controller.php @@ -28,19 +28,19 @@ class NodeInfo2Controller extends Controller $nodeInfo2 = [ 'version' => '1.0', - 'server' => [ - 'baseUrl' => base_url(), - 'name' => esc(service('settings') ->get('App.siteName')), + 'server' => [ + 'baseUrl' => base_url(), + 'name' => esc(service('settings') ->get('App.siteName')), 'software' => 'Castopod', - 'version' => CP_VERSION, + 'version' => CP_VERSION, ], - 'protocols' => ['activitypub'], + 'protocols' => ['activitypub'], 'openRegistrations' => config('Auth') ->allowRegistration, 'usage' => [ 'users' => [ - 'total' => $totalUsers, - 'activeMonth' => $activeMonth, + 'total' => $totalUsers, + 'activeMonth' => $activeMonth, 'activeHalfyear' => $activeHalfyear, ], 'localPosts' => $totalPosts, diff --git a/modules/Fediverse/Controllers/PostController.php b/modules/Fediverse/Controllers/PostController.php index 8fdd4548..7eb5f47e 100644 --- a/modules/Fediverse/Controllers/PostController.php +++ b/modules/Fediverse/Controllers/PostController.php @@ -12,8 +12,8 @@ namespace Modules\Fediverse\Controllers; use CodeIgniter\Controller; use CodeIgniter\Exceptions\PageNotFoundException; -use CodeIgniter\HTTP\IncomingRequest; use CodeIgniter\HTTP\RedirectResponse; +use CodeIgniter\HTTP\Response; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\I18n\Time; use Modules\Fediverse\Config\Fediverse; @@ -24,14 +24,7 @@ use Modules\Fediverse\Objects\OrderedCollectionPage; class PostController extends Controller { /** - * Instance of the main Request object. - * - * @var IncomingRequest - */ - protected $request; - - /** - * @var list + * @var string[] */ protected $helpers = ['fediverse']; @@ -49,11 +42,7 @@ class PostController extends Controller public function _remap(string $method, string ...$params): mixed { - if ($params === []) { - throw PageNotFoundException::forPageNotFound(); - } - - if (! ($post = model('PostModel', false)->getPostById($params[0])) instanceof Post) { + if (($post = model('PostModel', false)->getPostById($params[0])) === null) { throw PageNotFoundException::forPageNotFound(); } @@ -64,7 +53,10 @@ class PostController extends Controller return $this->{$method}(...$params); } - public function index(): ResponseInterface + /** + * @noRector ReturnTypeDeclarationRector + */ + public function index(): Response { $noteObjectClass = $this->config->noteObject; $noteObject = new $noteObjectClass($this->post); @@ -74,7 +66,10 @@ class PostController extends Controller ->setBody($noteObject->toJSON()); } - public function replies(): ResponseInterface + /** + * @noRector ReturnTypeDeclarationRector + */ + public function replies(): Response { /** * get post replies @@ -97,9 +92,11 @@ class PostController extends Controller $orderedItems = []; $noteObjectClass = $this->config->noteObject; - foreach ($paginatedReplies as $reply) { - $replyObject = new $noteObjectClass($reply); - $orderedItems[] = $replyObject->toArray(); + if ($paginatedReplies !== null) { + foreach ($paginatedReplies as $reply) { + $replyObject = new $noteObjectClass($reply); + $orderedItems[] = $replyObject->toArray(); + } } $collection = new OrderedCollectionPage($pager, $orderedItems); @@ -110,11 +107,11 @@ class PostController extends Controller ->setBody($collection->toJSON()); } - public function createAction(): RedirectResponse + public function attemptCreate(): RedirectResponse { $rules = [ 'actor_id' => 'required|is_natural_no_zero', - 'message' => 'required|max_length[500]', + 'message' => 'required|max_length[500]', ]; if (! $this->validate($rules)) { @@ -124,11 +121,9 @@ class PostController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - $newPost = new Post([ - 'actor_id' => $validData['actor_id'], - 'message' => $validData['message'], + 'actor_id' => $this->request->getPost('actor_id'), + 'message' => $this->request->getPost('message'), 'published_at' => Time::now(), ]); @@ -145,7 +140,7 @@ class PostController extends Controller return redirect()->back(); } - public function favouriteAction(): RedirectResponse + public function attemptFavourite(): RedirectResponse { $rules = [ 'actor_id' => 'required|is_natural_no_zero', @@ -158,18 +153,16 @@ class PostController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - $actor = model('ActorModel', false) - ->getActorById($validData['actor_id']); + ->getActorById($this->request->getPost('actor_id')); model('FavouriteModel', false) - ->toggleFavourite($actor, $this->post); + ->toggleFavourite($actor, $this->post->id); return redirect()->back(); } - public function reblogAction(): RedirectResponse + public function attemptReblog(): RedirectResponse { $rules = [ 'actor_id' => 'required|is_natural_no_zero', @@ -182,10 +175,8 @@ class PostController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - $actor = model('ActorModel', false) - ->getActorById($validData['actor_id']); + ->getActorById($this->request->getPost('actor_id')); model('PostModel', false) ->toggleReblog($actor, $this->post); @@ -193,11 +184,11 @@ class PostController extends Controller return redirect()->back(); } - public function replyAction(): RedirectResponse + public function attemptReply(): RedirectResponse { $rules = [ 'actor_id' => 'required|is_natural_no_zero', - 'message' => 'required|max_length[500]', + 'message' => 'required|max_length[500]', ]; if (! $this->validate($rules)) { @@ -207,13 +198,11 @@ class PostController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - $newReplyPost = new Post([ - 'actor_id' => $validData['actor_id'], + 'actor_id' => $this->request->getPost('actor_id'), 'in_reply_to_id' => $this->post->id, - 'message' => $validData['message'], - 'published_at' => Time::now(), + 'message' => $this->request->getPost('message'), + 'published_at' => Time::now(), ]); if (! model('PostModel', false)->addReply($newReplyPost)) { @@ -228,10 +217,11 @@ class PostController extends Controller return redirect()->back(); } - public function remoteActionAction(string $action): RedirectResponse | ResponseInterface + public function attemptRemoteAction(string $action): RedirectResponse | ResponseInterface { $rules = [ - 'handle' => 'regex_match[/^@?(?P[\w\.\-]+)@(?P[\w\.\-]+)(?P:[\d]+)?$/]', + 'handle' => + 'regex_match[/^@?(?P[\w\.\-]+)@(?P[\w\.\-]+)(?P:[\d]+)?$/]', ]; if (! $this->validate($rules)) { @@ -241,15 +231,13 @@ class PostController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - helper('text'); // get webfinger data from actor // parse actor id to get actor and domain // check if actor and domain exist if ( - ! ($parts = split_handle($validData['handle'])) || + ! ($parts = split_handle($this->request->getPost('handle'))) || ! ($data = get_webfinger_data($parts['username'], $parts['domain'])) ) { return redirect() @@ -271,25 +259,25 @@ class PostController extends Controller } return redirect()->to( - str_replace('{uri}', urlencode($this->post->uri), (string) $data->links[$ostatusKey]->template), + str_replace('{uri}', urlencode($this->post->uri), $data->links[$ostatusKey]->template), ); } - public function blockActorAction(): RedirectResponse + public function attemptBlockActor(): RedirectResponse { model('ActorModel', false)->blockActor($this->post->actor->id); return redirect()->back(); } - public function blockDomainAction(): RedirectResponse + public function attemptBlockDomain(): RedirectResponse { model('BlockedDomainModel', false)->blockDomain($this->post->actor->domain); return redirect()->back(); } - public function deleteAction(): RedirectResponse + public function attemptDelete(): RedirectResponse { model('PostModel', false)->removePost($this->post); diff --git a/modules/Fediverse/Controllers/SchedulerController.php b/modules/Fediverse/Controllers/SchedulerController.php new file mode 100644 index 00000000..15a02c0b --- /dev/null +++ b/modules/Fediverse/Controllers/SchedulerController.php @@ -0,0 +1,54 @@ +getScheduledActivities(); + + // Send activity to all followers + foreach ($scheduledActivities as $scheduledActivity) { + if ($scheduledActivity->target_actor_id !== null) { + if ($scheduledActivity->actor_id !== $scheduledActivity->target_actor_id) { + // send activity to targeted actor + send_activity_to_actor( + $scheduledActivity->actor, + $scheduledActivity->targetActor, + json_encode($scheduledActivity->payload, JSON_THROW_ON_ERROR) + ); + } + } else { + // send activity to all actor followers + send_activity_to_followers( + $scheduledActivity->actor, + json_encode($scheduledActivity->payload, JSON_THROW_ON_ERROR), + ); + } + + // set activity post to delivered + model('ActivityModel', false) + ->update($scheduledActivity->id, [ + 'status' => 'delivered', + ]); + } + } +} diff --git a/modules/Fediverse/Core/AbstractObject.php b/modules/Fediverse/Core/AbstractObject.php index 81a21b05..85a837c5 100644 --- a/modules/Fediverse/Core/AbstractObject.php +++ b/modules/Fediverse/Core/AbstractObject.php @@ -24,7 +24,7 @@ abstract class AbstractObject } /** - * @return array + * @return array */ public function toArray(): array { @@ -42,11 +42,13 @@ abstract class AbstractObject } // removes all NULL, FALSE and Empty Strings but leaves 0 (zero) values - return array_filter($array, static fn ($value): bool => ! in_array($value, [null, false, ''], true)); + return array_filter($array, static function ($value): bool { + return $value !== null && $value !== false && $value !== ''; + }); } - public function toJSON(): string + public function toJSON(): string | bool { - return (string) json_encode($this->toArray(), JSON_UNESCAPED_UNICODE); + return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-010000_add_actors.php b/modules/Fediverse/Database/Migrations/2018-01-01-010000_add_actors.php index dc323b9d..0293c1b9 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-010000_add_actors.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-010000_add_actors.php @@ -12,30 +12,28 @@ declare(strict_types=1); namespace Modules\Fediverse\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddActors extends BaseMigration +class AddActors extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'id' => [ - 'type' => 'INT', - 'unsigned' => true, + 'type' => 'INT', + 'unsigned' => true, 'auto_increment' => true, ], 'uri' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'username' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 32, ], 'domain' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'private_key' => [ @@ -47,7 +45,7 @@ class AddActors extends BaseMigration 'null' => true, ], 'display_name' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 128, ], 'summary' => [ @@ -55,55 +53,55 @@ class AddActors extends BaseMigration 'null' => true, ], 'avatar_image_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, - 'null' => true, + 'null' => true, ], // constraint is 13 because the longest safe mimetype for images is image/svg+xml, // see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#image_types 'avatar_image_mimetype' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 13, - 'null' => true, + 'null' => true, ], 'cover_image_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, - 'null' => true, + 'null' => true, ], 'cover_image_mimetype' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 13, - 'null' => true, + 'null' => true, ], 'inbox_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'outbox_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, - 'null' => true, + 'null' => true, ], 'followers_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, - 'null' => true, + 'null' => true, ], 'followers_count' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 0, + 'default' => 0, ], 'posts_count' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 0, + 'default' => 0, ], 'is_blocked' => [ - 'type' => 'TINYINT', + 'type' => 'TINYINT', 'constraint' => 1, - 'default' => 0, + 'default' => 0, ], 'created_at' => [ 'type' => 'DATETIME', @@ -115,12 +113,11 @@ class AddActors extends BaseMigration $this->forge->addPrimaryKey('id'); $this->forge->addUniqueKey('uri'); $this->forge->addUniqueKey(['username', 'domain']); - $this->forge->createTable('fediverse_actors'); + $this->forge->createTable(config('Fediverse')->tablesPrefix . 'actors'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_actors'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'actors'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-020000_add_posts.php b/modules/Fediverse/Database/Migrations/2018-01-01-020000_add_posts.php index c6bffce5..e69e6bfa 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-020000_add_posts.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-020000_add_posts.php @@ -12,61 +12,59 @@ declare(strict_types=1); namespace Modules\Fediverse\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddPosts extends BaseMigration +class AddPosts extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, ], 'uri' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'actor_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'in_reply_to_id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, - 'null' => true, + 'null' => true, ], 'reblog_of_id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, - 'null' => true, + 'null' => true, ], 'message' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 500, - 'null' => true, + 'null' => true, ], 'message_html' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 600, - 'null' => true, + 'null' => true, ], 'favourites_count' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 0, + 'default' => 0, ], 'reblogs_count' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 0, + 'default' => 0, ], 'replies_count' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'default' => 0, + 'default' => 0, ], 'published_at' => [ 'type' => 'DATETIME', @@ -77,19 +75,21 @@ class AddPosts extends BaseMigration ], ]); + $tablesPrefix = config('Fediverse') + ->tablesPrefix; + $this->forge->addPrimaryKey('id'); $this->forge->addUniqueKey('uri'); // FIXME: an actor must reblog a post only once // $this->forge->addUniqueKey(['actor_id', 'reblog_of_id']); - $this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('in_reply_to_id', 'fediverse_posts', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('reblog_of_id', 'fediverse_posts', 'id', '', 'CASCADE'); - $this->forge->createTable('fediverse_posts'); + $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('in_reply_to_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('reblog_of_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE'); + $this->forge->createTable($tablesPrefix . 'posts'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_posts'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'posts'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_activities.php b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_activities.php index b497009b..eccc8026 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_activities.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_activities.php @@ -12,44 +12,42 @@ declare(strict_types=1); namespace Modules\Fediverse\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddActivities extends BaseMigration +class AddActivities extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, ], 'actor_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'target_actor_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'null' => true, + 'null' => true, ], 'post_id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, - 'null' => true, + 'null' => true, ], 'type' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 100, ], 'payload' => [ 'type' => 'JSON', ], 'status' => [ - 'type' => 'ENUM', + 'type' => 'ENUM', 'constraint' => ['queued', 'delivered'], - 'null' => true, + 'null' => true, ], 'scheduled_at' => [ 'type' => 'DATETIME', @@ -60,16 +58,18 @@ class AddActivities extends BaseMigration ], ]); + $tablesPrefix = config('Fediverse') + ->tablesPrefix; + $this->forge->addPrimaryKey('id'); - $this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('target_actor_id', 'fediverse_actors', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('post_id', 'fediverse_posts', 'id', '', 'CASCADE'); - $this->forge->createTable('fediverse_activities'); + $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('target_actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE'); + $this->forge->createTable($tablesPrefix . 'activities'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_activities'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'activities'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_favourites.php b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_favourites.php index be9b5755..23554047 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_favourites.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_favourites.php @@ -12,35 +12,35 @@ declare(strict_types=1); namespace Modules\Fediverse\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddFavourites extends BaseMigration +class AddFavourites extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'actor_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'post_id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, ], ]); + $tablesPrefix = config('Fediverse') + ->tablesPrefix; + $this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()'); $this->forge->addPrimaryKey(['actor_id', 'post_id']); - $this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('post_id', 'fediverse_posts', 'id', '', 'CASCADE'); - $this->forge->createTable('fediverse_favourites'); + $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE'); + $this->forge->createTable($tablesPrefix . 'favourites'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_favourites'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'favourites'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_follows.php b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_follows.php index 945933f4..8f7c6f2d 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_follows.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_follows.php @@ -12,37 +12,37 @@ declare(strict_types=1); namespace Modules\Fediverse\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddFollowers extends BaseMigration +class AddFollowers extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'actor_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'comment' => 'Actor that is following', + 'comment' => 'Actor that is following', ], 'target_actor_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, - 'comment' => 'Actor that is followed', + 'comment' => 'Actor that is followed', ], ]); + $tablesPrefix = config('Fediverse') + ->tablesPrefix; + $this->forge->addField('`created_at` timestamp NOT NULL DEFAULT current_timestamp()'); $this->forge->addPrimaryKey(['actor_id', 'target_actor_id']); - $this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('target_actor_id', 'fediverse_actors', 'id', '', 'CASCADE'); - $this->forge->createTable('fediverse_follows'); + $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('target_actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE'); + $this->forge->createTable($tablesPrefix . 'follows'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_follows'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'follows'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_preview_cards.php b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_preview_cards.php index 479d7102..a2b1d51d 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_preview_cards.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-100000_add_preview_cards.php @@ -12,56 +12,54 @@ declare(strict_types=1); namespace Modules\Fediverse\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddPreviewCards extends BaseMigration +class AddPreviewCards extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'id' => [ - 'type' => 'INT', - 'unsigned' => true, + 'type' => 'INT', + 'unsigned' => true, 'auto_increment' => true, ], 'url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 512, ], 'title' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 128, ], 'description' => [ 'type' => 'TEXT', ], 'type' => [ - 'type' => 'ENUM', + 'type' => 'ENUM', 'constraint' => ['link', 'video', 'image', 'rich'], - 'default' => 'link', + 'default' => 'link', ], 'author_name' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 64, - 'null' => true, + 'null' => true, ], 'author_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, - 'null' => true, + 'null' => true, ], 'provider_name' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'provider_url' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'image' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'html' => [ @@ -77,12 +75,11 @@ class AddPreviewCards extends BaseMigration $this->forge->addPrimaryKey('id'); $this->forge->addUniqueKey('url'); - $this->forge->createTable('fediverse_preview_cards'); + $this->forge->createTable(config('Fediverse')->tablesPrefix . 'preview_cards'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_preview_cards'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'preview_cards'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-110000_add_posts_preview_cards.php b/modules/Fediverse/Database/Migrations/2018-01-01-110000_add_posts_preview_cards.php index 3d8d4d70..df0eab8d 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-110000_add_posts_preview_cards.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-110000_add_posts_preview_cards.php @@ -12,34 +12,34 @@ declare(strict_types=1); namespace Modules\Fediverse\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddPostsPreviewCards extends BaseMigration +class AddPostsPreviewCards extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'post_id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, ], 'preview_card_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], ]); + $tablesPrefix = config('Fediverse') + ->tablesPrefix; + $this->forge->addPrimaryKey(['post_id', 'preview_card_id']); - $this->forge->addForeignKey('post_id', 'fediverse_posts', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('preview_card_id', 'fediverse_preview_cards', 'id', '', 'CASCADE'); - $this->forge->createTable('fediverse_posts_preview_cards'); + $this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('preview_card_id', $tablesPrefix . 'preview_cards', 'id', '', 'CASCADE'); + $this->forge->createTable($tablesPrefix . 'posts_preview_cards'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_posts_preview_cards'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'posts_preview_cards'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-120000_add_blocked_domains.php b/modules/Fediverse/Database/Migrations/2018-01-01-120000_add_blocked_domains.php index d17079a1..6906866f 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-120000_add_blocked_domains.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-120000_add_blocked_domains.php @@ -12,17 +12,15 @@ declare(strict_types=1); namespace Modules\Fediverse\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddBlockedDomains extends BaseMigration +class AddBlockedDomains extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'name' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'created_at' => [ @@ -30,12 +28,11 @@ class AddBlockedDomains extends BaseMigration ], ]); $this->forge->addPrimaryKey('name'); - $this->forge->createTable('fediverse_blocked_domains'); + $this->forge->createTable(config('Fediverse')->tablesPrefix . 'blocked_domains'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_blocked_domains'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'blocked_domains'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-01-130000_add_notifications.php b/modules/Fediverse/Database/Migrations/2018-01-01-130000_add_notifications.php index a1764482..7fa59da2 100644 --- a/modules/Fediverse/Database/Migrations/2018-01-01-130000_add_notifications.php +++ b/modules/Fediverse/Database/Migrations/2018-01-01-130000_add_notifications.php @@ -12,38 +12,37 @@ declare(strict_types=1); namespace App\Database\Migrations; -use Override; +use CodeIgniter\Database\Migration; -class AddNotifications extends BaseMigration +class AddNotifications extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'id' => [ - 'type' => 'INT', - 'unsigned' => true, + 'type' => 'INT', + 'unsigned' => true, 'auto_increment' => true, ], 'actor_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'target_actor_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'post_id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, - 'null' => true, + 'null' => true, ], 'activity_id' => [ - 'type' => 'BINARY', + 'type' => 'BINARY', 'constraint' => 16, ], 'type' => [ - 'type' => 'ENUM', + 'type' => 'ENUM', 'constraint' => ['like', 'follow', 'share', 'reply'], ], 'read_at' => [ @@ -58,17 +57,19 @@ class AddNotifications extends BaseMigration ], ]); + $tablesPrefix = config('Fediverse') + ->tablesPrefix; + $this->forge->addPrimaryKey('id'); - $this->forge->addForeignKey('actor_id', 'fediverse_actors', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('target_actor_id', 'fediverse_actors', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('post_id', 'fediverse_posts', 'id', '', 'CASCADE'); - $this->forge->addForeignKey('activity_id', 'fediverse_activities', 'id', '', 'CASCADE'); - $this->forge->createTable('fediverse_notifications'); + $this->forge->addForeignKey('actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('target_actor_id', $tablesPrefix . 'actors', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('post_id', $tablesPrefix . 'posts', 'id', '', 'CASCADE'); + $this->forge->addForeignKey('activity_id', $tablesPrefix . 'activities', 'id', '', 'CASCADE'); + $this->forge->createTable($tablesPrefix . 'notifications'); } - #[Override] public function down(): void { - $this->forge->dropTable('fediverse_notifications'); + $this->forge->dropTable(config('Fediverse')->tablesPrefix . 'notifications'); } } diff --git a/modules/Fediverse/Database/Migrations/2018-01-02-120000_update_activities_status.php b/modules/Fediverse/Database/Migrations/2018-01-02-120000_update_activities_status.php deleted file mode 100644 index 2d7adac0..00000000 --- a/modules/Fediverse/Database/Migrations/2018-01-02-120000_update_activities_status.php +++ /dev/null @@ -1,44 +0,0 @@ - [ - 'type' => 'ENUM', - 'constraint' => ['queued', 'processing', 'delivered', 'failed'], - 'null' => true, - ], - ]; - - $this->forge->modifyColumn('fediverse_activities', $fields); - } - - public function down(): void - { - $fields = [ - 'status' => [ - 'type' => 'ENUM', - 'constraint' => ['queued', 'delivered'], - 'null' => true, - ], - ]; - - $this->forge->modifyColumn('fediverse_activities', $fields); - } -} diff --git a/modules/Fediverse/Database/Migrations/2025-07-31-120000_add_is_private_to_posts.php b/modules/Fediverse/Database/Migrations/2025-07-31-120000_add_is_private_to_posts.php deleted file mode 100644 index d1ac9327..00000000 --- a/modules/Fediverse/Database/Migrations/2025-07-31-120000_add_is_private_to_posts.php +++ /dev/null @@ -1,35 +0,0 @@ - [ - 'type' => 'TINYINT', - 'constraint' => 1, - 'default' => 0, - 'after' => 'message_html', - ], - ]; - - $this->forge->addColumn('fediverse_posts', $fields); - } - - public function down(): void - { - $this->forge->dropColumn('fediverse_posts', 'is_private'); - } -} diff --git a/modules/Fediverse/Entities/Activity.php b/modules/Fediverse/Entities/Activity.php index 34d34cec..3e2107f7 100644 --- a/modules/Fediverse/Entities/Activity.php +++ b/modules/Fediverse/Entities/Activity.php @@ -10,18 +10,17 @@ declare(strict_types=1); namespace Modules\Fediverse\Entities; -use CodeIgniter\I18n\Time; use Michalsn\Uuid\UuidEntity; use RuntimeException; /** * @property string $id * @property int $actor_id - * @property ?Actor $actor + * @property Actor $actor * @property int|null $target_actor_id - * @property ?Actor $target_actor + * @property Actor $target_actor * @property string|null $post_id - * @property ?Post $post + * @property Post $post * @property string $type * @property object $payload * @property string|null $status @@ -42,7 +41,7 @@ class Activity extends UuidEntity protected $uuids = ['id', 'post_id']; /** - * @var list + * @var string[] */ protected $dates = ['scheduled_at', 'created_at']; @@ -50,18 +49,22 @@ class Activity extends UuidEntity * @var array */ protected $casts = [ - 'id' => 'string', - 'actor_id' => 'integer', + 'id' => 'string', + 'actor_id' => 'integer', 'target_actor_id' => '?integer', - 'post_id' => '?string', - 'type' => 'string', - 'payload' => 'json', - 'status' => '?string', + 'post_id' => '?string', + 'type' => 'string', + 'payload' => 'json', + 'status' => '?string', ]; public function getActor(): Actor { - if (! $this->actor instanceof Actor) { + if ($this->actor_id === null) { + throw new RuntimeException('Activity must have an actor_id before getting the actor.'); + } + + if ($this->actor === null) { $this->actor = model('ActorModel', false) ->getActorById($this->actor_id); } @@ -75,7 +78,7 @@ class Activity extends UuidEntity throw new RuntimeException('Activity must have a target_actor_id before getting the target actor.'); } - if (! $this->target_actor instanceof Actor) { + if ($this->target_actor === null) { $this->target_actor = model('ActorModel', false) ->getActorById($this->target_actor_id); } @@ -89,7 +92,7 @@ class Activity extends UuidEntity throw new RuntimeException('Activity must have a post_id before getting post.'); } - if (! $this->post instanceof Post) { + if ($this->post === null) { $this->post = model('PostModel', false) ->getPostById($this->post_id); } diff --git a/modules/Fediverse/Entities/Actor.php b/modules/Fediverse/Entities/Actor.php index 9b6bdb42..d7a5ba64 100644 --- a/modules/Fediverse/Entities/Actor.php +++ b/modules/Fediverse/Entities/Actor.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace Modules\Fediverse\Entities; use CodeIgniter\Entity\Entity; +use RuntimeException; /** * @property int $id @@ -41,7 +42,7 @@ class Actor extends Entity protected string $public_key_id; /** - * @var Actor[]|null + * @var \Modules\Fediverse\Entities\Actor[]|null */ protected ?array $followers = null; @@ -51,24 +52,24 @@ class Actor extends Entity * @var array */ protected $casts = [ - 'id' => 'integer', - 'uri' => 'string', - 'username' => 'string', - 'domain' => 'string', - 'display_name' => 'string', - 'summary' => '?string', - 'private_key' => '?string', - 'public_key' => '?string', - 'avatar_image_url' => '?string', + 'id' => 'integer', + 'uri' => 'string', + 'username' => 'string', + 'domain' => 'string', + 'display_name' => 'string', + 'summary' => '?string', + 'private_key' => '?string', + 'public_key' => '?string', + 'avatar_image_url' => '?string', 'avatar_image_mimetype' => '?string', - 'cover_image_url' => '?string', - 'cover_image_mimetype' => '?string', - 'inbox_url' => 'string', - 'outbox_url' => '?string', - 'followers_url' => '?string', - 'followers_count' => 'integer', - 'posts_count' => 'integer', - 'is_blocked' => 'boolean', + 'cover_image_url' => '?string', + 'cover_image_mimetype' => '?string', + 'inbox_url' => 'string', + 'outbox_url' => '?string', + 'followers_url' => '?string', + 'followers_count' => 'integer', + 'posts_count' => 'integer', + 'is_blocked' => 'boolean', ]; public function getPublicKeyId(): string @@ -95,8 +96,12 @@ class Actor extends Entity */ public function getFollowers(): array { + if ($this->id === null) { + throw new RuntimeException('Actor must be created before getting followers.'); + } + if ($this->followers === null) { - $this->followers = model('ActorModel', false) + $this->followers = (array) model('ActorModel', false) ->getFollowers($this->id); } diff --git a/modules/Fediverse/Entities/Favourite.php b/modules/Fediverse/Entities/Favourite.php index 1811d8f5..2625e6cb 100644 --- a/modules/Fediverse/Entities/Favourite.php +++ b/modules/Fediverse/Entities/Favourite.php @@ -28,6 +28,6 @@ class Favourite extends UuidEntity */ protected $casts = [ 'actor_id' => 'integer', - 'post_id' => 'string', + 'post_id' => 'string', ]; } diff --git a/modules/Fediverse/Entities/Follow.php b/modules/Fediverse/Entities/Follow.php index 49736eea..2a415e89 100644 --- a/modules/Fediverse/Entities/Follow.php +++ b/modules/Fediverse/Entities/Follow.php @@ -22,7 +22,7 @@ class Follow extends Entity * @var array */ protected $casts = [ - 'actor_id' => 'integer', + 'actor_id' => 'integer', 'target_actor_id' => 'integer', ]; } diff --git a/modules/Fediverse/Entities/Notification.php b/modules/Fediverse/Entities/Notification.php index 0815c273..cfd74184 100644 --- a/modules/Fediverse/Entities/Notification.php +++ b/modules/Fediverse/Entities/Notification.php @@ -10,7 +10,6 @@ declare(strict_types=1); namespace Modules\Fediverse\Entities; -use CodeIgniter\I18n\Time; use Michalsn\Uuid\UuidEntity; use Modules\Fediverse\Models\ActorModel; use Modules\Fediverse\Models\PostModel; @@ -19,11 +18,11 @@ use RuntimeException; /** * @property int $id * @property int $actor_id - * @property ?Actor $actor + * @property Actor $actor * @property int $target_actor_id - * @property ?Actor $target_actor + * @property Actor $target_actor * @property string|null $post_id - * @property ?Post $post + * @property Post $post * @property string $activity_id * @property Activity $activity * @property 'like'|'follow'|'share'|'reply' $type @@ -47,7 +46,7 @@ class Notification extends UuidEntity protected $uuids = ['post_id', 'activity_id']; /** - * @var list + * @var string[] */ protected $dates = ['read_at', 'created_at', 'updated_at']; @@ -55,19 +54,22 @@ class Notification extends UuidEntity * @var array */ protected $casts = [ - 'id' => 'integer', - 'actor_id' => 'integer', + 'id' => 'integer', + 'actor_id' => 'integer', 'target_actor_id' => 'integer', - 'post_id' => '?string', - 'activity_id' => 'string', - 'type' => 'string', + 'post_id' => '?string', + 'activity_id' => 'string', + 'type' => 'string', ]; public function getActor(): ?Actor { + if ($this->actor_id === null) { + throw new RuntimeException('Notification must have an actor_id before getting actor.'); + } + if (! $this->actor instanceof Actor) { - $this->actor = new ActorModel() - ->getActorById($this->actor_id); + $this->actor = (new ActorModel())->getActorById($this->actor_id); } return $this->actor; @@ -75,9 +77,12 @@ class Notification extends UuidEntity public function getTargetActor(): ?Actor { + if ($this->target_actor_id === null) { + throw new RuntimeException('Notification must have a target_actor_id before getting target actor.'); + } + if (! $this->target_actor instanceof Actor) { - $this->target_actor = new ActorModel() - ->getActorById($this->target_actor_id); + $this->target_actor = (new ActorModel())->getActorById($this->target_actor_id); } return $this->target_actor; @@ -90,8 +95,7 @@ class Notification extends UuidEntity } if (! $this->post instanceof Post) { - $this->post = new PostModel() - ->getPostById($this->post_id); + $this->post = (new PostModel())->getPostById($this->post_id); } return $this->post; diff --git a/modules/Fediverse/Entities/Post.php b/modules/Fediverse/Entities/Post.php index 10d41a2a..45aab89e 100644 --- a/modules/Fediverse/Entities/Post.php +++ b/modules/Fediverse/Entities/Post.php @@ -18,19 +18,16 @@ use RuntimeException; * @property string $id * @property string $uri * @property int $actor_id - * @property ?Actor $actor + * @property Actor $actor * @property string|null $in_reply_to_id * @property Post|null $reply_to_post * @property string|null $reblog_of_id * @property Post|null $reblog_of_post * @property string $message * @property string $message_html - * @property bool $is_private - * * @property int $favourites_count * @property int $reblogs_count * @property int $replies_count - * * @property Time $published_at * @property Time $created_at * @@ -68,7 +65,7 @@ class Post extends UuidEntity protected $uuids = ['id', 'in_reply_to_id', 'reblog_of_id']; /** - * @var list + * @var string[] */ protected $dates = ['published_at', 'created_at']; @@ -76,17 +73,16 @@ class Post extends UuidEntity * @var array */ protected $casts = [ - 'id' => 'string', - 'uri' => 'string', - 'actor_id' => 'integer', - 'in_reply_to_id' => '?string', - 'reblog_of_id' => '?string', - 'message' => 'string', - 'message_html' => 'string', - 'is_private' => 'boolean', + 'id' => 'string', + 'uri' => 'string', + 'actor_id' => 'integer', + 'in_reply_to_id' => '?string', + 'reblog_of_id' => '?string', + 'message' => 'string', + 'message_html' => 'string', 'favourites_count' => 'integer', - 'reblogs_count' => 'integer', - 'replies_count' => 'integer', + 'reblogs_count' => 'integer', + 'replies_count' => 'integer', ]; /** @@ -94,7 +90,11 @@ class Post extends UuidEntity */ public function getActor(): Actor { - if (! $this->actor instanceof Actor) { + if ($this->actor_id === null) { + throw new RuntimeException('Post must have an actor_id before getting actor.'); + } + + if ($this->actor === null) { $this->actor = model('ActorModel', false) ->getActorById($this->actor_id); } @@ -104,7 +104,11 @@ class Post extends UuidEntity public function getPreviewCard(): ?PreviewCard { - if (! $this->preview_card instanceof PreviewCard) { + if ($this->id === null) { + throw new RuntimeException('Post must be created before getting preview_card.'); + } + + if ($this->preview_card === null) { $this->preview_card = model('PreviewCardModel', false) ->getPostPreviewCard($this->id); } @@ -117,8 +121,12 @@ class Post extends UuidEntity */ public function getReplies(): array { + if ($this->id === null) { + throw new RuntimeException('Post must be created before getting replies.'); + } + if ($this->replies === null) { - $this->replies = model('PostModel', false) + $this->replies = (array) model('PostModel', false) ->getPostReplies($this->id); } @@ -136,7 +144,7 @@ class Post extends UuidEntity throw new RuntimeException('Post is not a reply.'); } - if (! $this->reply_to_post instanceof self) { + if ($this->reply_to_post === null) { $this->reply_to_post = model('PostModel', false) ->getPostById($this->in_reply_to_id); } @@ -149,8 +157,12 @@ class Post extends UuidEntity */ public function getReblogs(): array { + if ($this->id === null) { + throw new RuntimeException('Post must be created before getting reblogs.'); + } + if ($this->reblogs === null) { - $this->reblogs = model('PostModel', false) + $this->reblogs = (array) model('PostModel', false) ->getPostReblogs($this->id); } @@ -163,7 +175,7 @@ class Post extends UuidEntity throw new RuntimeException('Post is not a reblog.'); } - if (! $this->reblog_of_post instanceof self) { + if ($this->reblog_of_post === null) { $this->reblog_of_post = model('PostModel', false) ->getPostById($this->reblog_of_id); } diff --git a/modules/Fediverse/Entities/PreviewCard.php b/modules/Fediverse/Entities/PreviewCard.php index 2271aca4..ba8d8b88 100644 --- a/modules/Fediverse/Entities/PreviewCard.php +++ b/modules/Fediverse/Entities/PreviewCard.php @@ -32,17 +32,17 @@ class PreviewCard extends Entity * @var array */ protected $casts = [ - 'id' => 'integer', - 'post_id' => 'string', - 'url' => 'string', - 'title' => 'string', - 'description' => 'string', - 'type' => 'string', - 'author_name' => '?string', - 'author_url' => '?string', + 'id' => 'integer', + 'post_id' => 'string', + 'url' => 'string', + 'title' => 'string', + 'description' => 'string', + 'type' => 'string', + 'author_name' => '?string', + 'author_url' => '?string', 'provider_name' => '?string', - 'provider_url' => '?string', - 'image' => '?string', - 'html' => '?string', + 'provider_url' => '?string', + 'image' => '?string', + 'html' => '?string', ]; } diff --git a/app/Filters/AllowCorsFilter.php b/modules/Fediverse/Filters/AllowCorsFilter.php similarity index 52% rename from app/Filters/AllowCorsFilter.php rename to modules/Fediverse/Filters/AllowCorsFilter.php index 578263fe..3ed0f948 100644 --- a/app/Filters/AllowCorsFilter.php +++ b/modules/Fediverse/Filters/AllowCorsFilter.php @@ -2,43 +2,26 @@ declare(strict_types=1); -namespace App\Filters; +namespace Modules\Fediverse\Filters; use CodeIgniter\Filters\FilterInterface; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; -use Override; class AllowCorsFilter implements FilterInterface { - /** - * @param list|null $arguments - * - * @return RequestInterface|ResponseInterface|string|null - */ - #[Override] - public function before(RequestInterface $request, $arguments = null) + public function before(RequestInterface $request, $arguments = null): void { - return null; + // Do something here } - /** - * @param list|null $arguments - * - * @return ResponseInterface|null - */ - #[Override] - public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void { - if (! $response->hasHeader('Cache-Control')) { - $response->setHeader('Cache-Control', 'public, max-age=86400'); - } - $response->setHeader('Access-Control-Allow-Origin', '*') // for allowing any domain, insecure ->setHeader('Access-Control-Allow-Headers', '*') // for allowing any headers, insecure ->setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS') // allows GET and OPTIONS methods only - ->setHeader('Access-Control-Max-Age', '86400'); - - return $response; + ->setHeader('Access-Control-Max-Age', '86400') + ->setHeader('Cache-Control', 'public, max-age=86400') + ->setStatusCode(200); } } diff --git a/modules/Fediverse/Filters/FediverseFilter.php b/modules/Fediverse/Filters/FediverseFilter.php index 2e9b32ba..ddac50de 100644 --- a/modules/Fediverse/Filters/FediverseFilter.php +++ b/modules/Fediverse/Filters/FediverseFilter.php @@ -9,26 +9,29 @@ use CodeIgniter\Filters\FilterInterface; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\URI; +use Config\Services; use Exception; use Modules\Fediverse\HttpSignature; -use Override; class FediverseFilter implements FilterInterface { /** - * @param string[]|null $params + * Do whatever processing this filter needs to do. By default it should not return anything during normal execution. + * However, when an abnormal state is found, it should return an instance of CodeIgniter\HTTP\Response. If it does, + * script execution will end and that Response will be sent back to the client, allowing for error pages, redirects, + * etc. * - * @return RequestInterface|ResponseInterface|string|null + * @param string[]|null $params + * @return void|mixed */ - #[Override] public function before(RequestInterface $request, $params = null) { if ($params === null) { - return null; + return; } if (in_array('verify-activitystream', $params, true)) { - $negotiate = service('negotiator'); + $negotiate = Services::negotiator(); $allowedContentTypes = [ 'application/ld+json; profile="https://www.w3.org/ns/activitystreams', @@ -41,12 +44,10 @@ class FediverseFilter implements FilterInterface } if (in_array('verify-blocks', $params, true)) { - // @phpstan-ignore-next-line $payload = $request->getJSON(); $actorUri = $payload->actor; - $domain = new URI($actorUri) - ->getHost(); + $domain = (new URI($actorUri))->getHost(); // check first if domain is blocked if (model('BlockedDomainModel', false)->isDomainBlocked($domain)) { @@ -59,31 +60,29 @@ class FediverseFilter implements FilterInterface } } - log_message('critical', 'ITS HEEEEEEEEEEEERE'); - if (in_array('verify-signature', $params, true)) { try { // securityCheck: check activity signature before handling it - new HttpSignature() - ->verify(); + (new HttpSignature())->verify(); } catch (Exception) { // Invalid HttpSignature (401 = unauthorized) // TODO: show error message? return service('response')->setStatusCode(401); } } - - return null; } + //-------------------------------------------------------------------- + /** - * @param string[]|null $arguments + * Allows After filters to inspect and modify the response object as needed. This method does not allow any way to + * stop execution of other after filters, short of throwing an Exception or Error. * - * @return ResponseInterface|null + * @param string[]|null $arguments */ - #[Override] - public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void { - return null; } + + //-------------------------------------------------------------------- } diff --git a/modules/Fediverse/Helpers/fediverse_helper.php b/modules/Fediverse/Helpers/fediverse_helper.php index 391842a8..f4500585 100644 --- a/modules/Fediverse/Helpers/fediverse_helper.php +++ b/modules/Fediverse/Helpers/fediverse_helper.php @@ -10,11 +10,10 @@ declare(strict_types=1); use CodeIgniter\HTTP\Exceptions\HTTPException; use CodeIgniter\HTTP\URI; -use Config\Mimes; -use Embera\Embera; +use Config\Database; +use Essence\Essence; use Modules\Fediverse\Activities\AcceptActivity; use Modules\Fediverse\ActivityRequest; -use Modules\Fediverse\Core\ObjectType; use Modules\Fediverse\Entities\Actor; use Modules\Fediverse\Entities\PreviewCard; @@ -33,7 +32,7 @@ if (! function_exists('get_webfinger_data')) { $webfingerRequest = new ActivityRequest((string) $webfingerUri); $webfingerResponse = $webfingerRequest->get(); - return json_decode((string) $webfingerResponse->getBody(), false, 512, JSON_THROW_ON_ERROR); + return json_decode($webfingerResponse->getBody(), false, 512, JSON_THROW_ON_ERROR); } } @@ -41,7 +40,7 @@ if (! function_exists('split_handle')) { /** * Splits handle into its parts (username, host and port) * - * @return array{0:string,username:non-empty-string,1:non-empty-string,domain:non-empty-string,2:non-empty-string,port?:non-falsy-string,3?:non-falsy-string} + * @return array|false */ function split_handle(string $handle): array | false { @@ -65,15 +64,8 @@ if (! function_exists('accept_follow')) { function accept_follow(Actor $actor, Actor $targetActor, string $objectId): void { $acceptActivity = new AcceptActivity(); - - $object = new ObjectType(); - $object->set('id', $objectId); - $object->set('type', 'Follow'); - $object->set('actor', $targetActor->uri); - $object->set('object', $actor->uri); - $acceptActivity->set('actor', $actor->uri) - ->set('object', $object); + ->set('object', $objectId); $db = db_connect(); $db->transStart(); @@ -131,7 +123,6 @@ if (! function_exists('send_activity_to_followers')) { */ function send_activity_to_followers(Actor $actor, string $activityPayload): void { - // TODO: send activities in parallel with https://www.php.net/manual/en/function.curl-multi-init.php foreach ($actor->followers as $follower) { send_activity_to_actor($actor, $follower, $activityPayload); } @@ -158,33 +149,38 @@ if (! function_exists('create_preview_card_from_url')) { */ function create_preview_card_from_url(URI $url): ?PreviewCard { - $embera = new Embera(); - $mediaData = $embera->getUrlData((string) $url); + $essence = new Essence([ + 'filters' => [ + 'OEmbedProvider' => '//', + 'OpenGraphProvider' => '//', + 'TwitterCardsProvider' => '//', + ], + ]); + $media = $essence->extract((string) $url); - if ($mediaData !== []) { - $mediaUrl = array_key_first($mediaData); - $media = array_first($mediaData); + if ($media) { + $typeMapping = [ + 'photo' => 'image', + 'video' => 'video', + 'website' => 'link', + 'rich' => 'rich', + ]; - if (array_key_exists('title', $media)) { - $typeMapping = [ - 'photo' => 'image', - 'video' => 'video', - 'website' => 'link', - 'rich' => 'rich', - ]; - - // Check that, at least, the url and title are set + // Check that, at least, the url and title are set + if ($media->url && $media->title) { $newPreviewCard = new PreviewCard([ - 'url' => $mediaUrl, - 'title' => $media['title'] ?? '', - 'description' => $media['description'] ?? '', - 'type' => $typeMapping[$media['type']] ?? 'link', - 'author_name' => $media['author_name'] ?? null, - 'author_url' => $media['author_url'] ?? null, - 'provider_name' => $media['provider_name'] ?? '', - 'provider_url' => $media['provider_url'] ?? '', - 'image' => $media['thumbnail_url'] ?? '', - 'html' => $media['html'] ?? '', + 'url' => (string) $url, + 'title' => $media->title, + 'description' => $media->description, + 'type' => isset($typeMapping[$media->type]) + ? $typeMapping[$media->type] + : 'link', + 'author_name' => $media->authorName, + 'author_url' => $media->authorUrl, + 'provider_name' => $media->providerName, + 'provider_url' => $media->providerUrl, + 'image' => $media->thumbnailUrl, + 'html' => $media->html, ]); if ( @@ -210,8 +206,8 @@ if (! function_exists('get_or_create_preview_card_from_url')) { { // check if preview card has already been generated if ( - ($previewCard = model('PreviewCardModel', false) - ->getPreviewCardFromUrl((string) $url)) instanceof PreviewCard + $previewCard = model('PreviewCardModel', false) + ->getPreviewCardFromUrl((string) $url) ) { return $previewCard; } @@ -229,7 +225,7 @@ if (! function_exists('get_or_create_actor_from_uri')) { function get_or_create_actor_from_uri(string $actorUri): ?Actor { // check if actor exists in database already and return it - if (($actor = model('ActorModel', false)->getActorByUri($actorUri)) instanceof Actor) { + if ($actor = model('ActorModel', false)->getActorByUri($actorUri)) { return $actor; } @@ -247,8 +243,8 @@ if (! function_exists('get_or_create_actor')) { { // check if actor exists in database already and return it if ( - ($actor = model('ActorModel', false) - ->getActorByUsername($username, $domain)) instanceof Actor + $actor = model('ActorModel', false) + ->getActorByUsername($username, $domain) ) { return $actor; } @@ -269,7 +265,7 @@ if (! function_exists('create_actor_from_uri')) { { $activityRequest = new ActivityRequest($actorUri); $actorResponse = $activityRequest->get(); - $actorPayload = json_decode((string) $actorResponse->getBody(), false, 512, JSON_THROW_ON_ERROR); + $actorPayload = json_decode($actorResponse->getBody(), false, 512, JSON_THROW_ON_ERROR); $newActor = new Actor(); $newActor->uri = $actorUri; @@ -281,26 +277,12 @@ if (! function_exists('create_actor_from_uri')) { $newActor->summary = property_exists($actorPayload, 'summary') ? $actorPayload->summary : null; if (property_exists($actorPayload, 'icon')) { $newActor->avatar_image_url = $actorPayload->icon->url; - - if (property_exists($actorPayload->icon, 'mediaType')) { - $newActor->avatar_image_mimetype = $actorPayload->icon->mediaType; - } else { - $iconExtension = pathinfo((string) $actorPayload->icon->url, PATHINFO_EXTENSION); - - $newActor->avatar_image_mimetype = (string) Mimes::guessTypeFromExtension($iconExtension); - } + $newActor->avatar_image_mimetype = $actorPayload->icon->mediaType; } if (property_exists($actorPayload, 'image')) { $newActor->cover_image_url = $actorPayload->image->url; - - if (property_exists($actorPayload->image, 'mediaType')) { - $newActor->cover_image_mimetype = $actorPayload->image->mediaType; - } else { - $coverExtension = pathinfo((string) $actorPayload->image->url, PATHINFO_EXTENSION); - - $newActor->cover_image_mimetype = (string) Mimes::guessTypeFromExtension($coverExtension); - } + $newActor->cover_image_mimetype = $actorPayload->image->mediaType; } $newActor->inbox_url = $actorPayload->inbox; @@ -345,7 +327,7 @@ if (! function_exists('get_message_from_object')) { */ function get_message_from_object(stdClass $object): string | false { - if (property_exists($object, 'content') && is_string($object->content)) { + if (property_exists($object, 'content')) { extract_text_from_html($object->content); return $object->content; } @@ -365,29 +347,6 @@ if (! function_exists('get_message_from_object')) { } } -if (! function_exists('is_note_public')) { - /** - * Check whether note is public or not - */ - function is_note_public(stdClass $object): bool - { - $isPublic = false; - if (property_exists($object, 'to') && is_array($object->to)) { - $isPublic = in_array('https://www.w3.org/ns/activitystreams#Public', $object->to, true); - } - - if ($isPublic) { - return true; - } - - if (property_exists($object, 'cc') && is_array($object->cc)) { - return in_array('https://www.w3.org/ns/activitystreams#Public', $object->cc, true); - } - - return $isPublic; - } -} - if (! function_exists('linkify')) { /** * Turn all link elements in clickable links. Transforms urls and handles @@ -403,7 +362,7 @@ if (! function_exists('linkify')) { $text = match ($protocol) { 'http', 'https' => preg_replace_callback( '~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(? '_blank', - 'rel' => 'noopener noreferrer', + 'rel' => 'noopener noreferrer', ], ), ) . '>'; }, - (string) $text, + $text, ), 'handle' => preg_replace_callback( '~(?\w++)(?:@(?(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]))?~', - static function (array $match) use (&$links): string { + static function ($match) use (&$links) { // check if host is set and look for actor in database - if (isset($match['domain'])) { + if (isset($match['host'])) { if ( - ($actor = model( + $actor = model( 'ActorModel', - )->getActorByUsername($match['username'], $match['domain'])) instanceof Actor + )->getActorByUsername($match['username'], $match['domain']) ) { // TODO: check that host is local to remove target blank? return '<' . @@ -443,7 +402,7 @@ if (! function_exists('linkify')) { $links, anchor($actor->uri, $match[0], [ 'target' => '_blank', - 'rel' => 'noopener noreferrer', + 'rel' => 'noopener noreferrer', ]), ) . '>'; @@ -456,7 +415,7 @@ if (! function_exists('linkify')) { $links, anchor($actor->uri, $match[0], [ 'target' => '_blank', - 'rel' => 'noopener noreferrer', + 'rel' => 'noopener noreferrer', ]), ) . '>'; @@ -468,8 +427,8 @@ if (! function_exists('linkify')) { } } else { if ( - ($actor = model('ActorModel', false) - ->getActorByUsername($match['username'])) instanceof Actor + $actor = model('ActorModel', false) + ->getActorByUsername($match['username']) ) { return '<' . array_push($links, anchor($actor->uri, $match[0])) . @@ -481,13 +440,13 @@ if (! function_exists('linkify')) { '>'; } }, - (string) $text, + $text, ), default => preg_replace_callback( '~' . preg_quote($protocol, '~') . '://([^\s<]+?)(? '_blank', - 'rel' => 'noopener noreferrer', + 'rel' => 'noopener noreferrer', ], ), ) . '>'; }, - (string) $text, + $text, ), }; } @@ -510,10 +469,10 @@ if (! function_exists('linkify')) { // Insert all links return preg_replace_callback( '~<(\d+)>~', - static function (array $match) use (&$links): string { - return $links[(int) $match[1] - 1]; + static function ($match) use (&$links) { + return $links[$match[1] - 1]; }, - (string) $text, + $text, ); } } diff --git a/modules/Fediverse/HttpSignature.php b/modules/Fediverse/HttpSignature.php index 145f0848..f5d08e43 100644 --- a/modules/Fediverse/HttpSignature.php +++ b/modules/Fediverse/HttpSignature.php @@ -16,6 +16,7 @@ namespace Modules\Fediverse; use CodeIgniter\HTTP\IncomingRequest; use CodeIgniter\I18n\Time; +use Config\Services; use Exception; use phpseclib\Crypt\RSA; @@ -24,7 +25,10 @@ use phpseclib\Crypt\RSA; */ class HttpSignature { - private const string SIGNATURE_PATTERN = '/ + /** + * @var string + */ + private const SIGNATURE_PATTERN = '/ (?=.*(keyId="(?Phttps?:\/\/[\w\-\.]+[\w]+(:[\d]+)?[\w\-\.#\/@]+)")) (?=.*(signature="(?P[\w+\/]+={0,2})")) (?=.*(headers="\(request-target\)(?P[\w\\-\s]+)"))? @@ -33,10 +37,10 @@ class HttpSignature protected IncomingRequest $request; - public function __construct(?IncomingRequest $request = null) + public function __construct(IncomingRequest $request = null) { - if (! $request instanceof IncomingRequest) { - $request = service('request'); + if ($request === null) { + $request = Services::request(); } $this->request = $request; @@ -69,7 +73,7 @@ class HttpSignature } // compute body digest and compare with header digest - $bodyDigest = hash('sha256', (string) $this->request->getBody(), true); + $bodyDigest = hash('sha256', $this->request->getBody(), true); $digest = 'SHA-256=' . base64_encode($bodyDigest); if ($digest !== $digestHeader->getValue()) { throw new Exception('Request digest is incorrect.'); @@ -95,7 +99,7 @@ class HttpSignature // Fetch the public key linked from keyId $actorRequest = new ActivityRequest($keyId); $actorResponse = $actorRequest->get(); - $actor = json_decode((string) $actorResponse->getBody(), false, 512, JSON_THROW_ON_ERROR); + $actor = json_decode($actorResponse->getBody(), false, 512, JSON_THROW_ON_ERROR); $publicKeyPem = (string) $actor->publicKey->publicKeyPem; @@ -112,7 +116,7 @@ class HttpSignature * * @return array|false */ - private function splitSignature(string $signature): bool|array + private function splitSignature(string $signature): array | false { if (! preg_match(self::SIGNATURE_PATTERN, $signature, $matches, PREG_UNMATCHED_AS_NULL)) { // Signature pattern failed @@ -138,10 +142,9 @@ class HttpSignature $strings[] = sprintf( '(request-target): %s %s%s', $this->request->getMethod(), - '/' . $this->request->getUri()->getPath(), - $this->request->getUri() - ->getQuery() !== '' - ? '?' . $this->request->getUri()->getQuery() + '/' . $this->request->uri->getPath(), + $this->request->uri->getQuery() !== '' + ? '?' . $this->request->uri->getQuery() : '', ); @@ -161,7 +164,7 @@ class HttpSignature string $publicKeyPem, string $data, string $signature, - string $algorithm = 'rsa-sha256', + string $algorithm = 'rsa-sha256' ): bool { if ($algorithm === 'rsa-sha512' || $algorithm === 'rsa-sha256') { $hash = substr($algorithm, strpos($algorithm, '-') + 1); diff --git a/modules/Fediverse/Models/ActivityModel.php b/modules/Fediverse/Models/ActivityModel.php index 21cd5538..dcb1f0ad 100644 --- a/modules/Fediverse/Models/ActivityModel.php +++ b/modules/Fediverse/Models/ActivityModel.php @@ -13,15 +13,14 @@ namespace Modules\Fediverse\Models; use CodeIgniter\Database\BaseResult; use CodeIgniter\I18n\Time; use DateTimeInterface; -use Michalsn\Uuid\UuidModel; use Modules\Fediverse\Entities\Activity; -class ActivityModel extends UuidModel +class ActivityModel extends BaseUuidModel { /** * @var string */ - protected $table = 'fediverse_activities'; + protected $table = 'activities'; /** * @var string @@ -34,17 +33,17 @@ class ActivityModel extends UuidModel protected $uuidFields = ['id', 'post_id']; /** - * @var list + * @var string[] */ protected $afterInsert = ['notify']; /** - * @var list + * @var string[] */ protected $afterUpdate = ['notify']; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -58,7 +57,7 @@ class ActivityModel extends UuidModel ]; /** - * @var class-string + * @var string */ protected $returnType = Activity::class; @@ -72,7 +71,7 @@ class ActivityModel extends UuidModel */ protected $useTimestamps = true; - protected $updatedField = ''; + protected $updatedField; public function getActivityById(string $activityId): ?Activity { @@ -100,21 +99,18 @@ class ActivityModel extends UuidModel ?int $targetActorId, ?string $postId, string $payload, - ?DateTimeInterface $scheduledAt = null, - ?string $taskStatus = null, + DateTimeInterface $scheduledAt = null, + ?string $taskStatus = null ): BaseResult | int | string | false { return $this->insert( [ - 'actor_id' => $actorId, + 'actor_id' => $actorId, 'target_actor_id' => $targetActorId, - 'post_id' => $postId, - 'type' => $type === 'Undo' ? $type . '_' . (json_decode( - $payload, - true, - ))['object']['type'] : $type, - 'payload' => $payload, + 'post_id' => $postId, + 'type' => $type === 'Undo' ? $type . '_' . (json_decode($payload, true))['object']['type'] : $type, + 'payload' => $payload, 'scheduled_at' => $scheduledAt, - 'status' => $taskStatus, + 'status' => $taskStatus, ], true, ); @@ -123,24 +119,21 @@ class ActivityModel extends UuidModel /** * @return Activity[] */ - public function getScheduledActivities(int $limit = 10): array + public function getScheduledActivities(): array { return $this->where('`scheduled_at` <= UTC_TIMESTAMP()', null, false) ->where('status', 'queued') ->orderBy('scheduled_at', 'ASC') - ->limit($limit) ->findAll(); } /** - * @param array $data + * @param array> $data * @return array> */ protected function notify(array $data): array { - /** @var ?Activity $activity */ - $activity = new self() - ->find(is_array($data['id']) ? $data['id'][0] : $data['id']); + $activity = (new self())->getActivityById(is_array($data['id']) ? $data['id'][0] : $data['id']); if (! $activity instanceof Activity) { return $data; @@ -156,47 +149,43 @@ class ActivityModel extends UuidModel } if ($activity->type === 'Follow') { - new NotificationModel() - ->insert([ - 'actor_id' => $activity->actor_id, - 'target_actor_id' => $activity->target_actor_id, - 'activity_id' => $activity->id, - 'type' => 'follow', - 'created_at' => $activity->created_at, - ]); + (new NotificationModel())->insert([ + 'actor_id' => $activity->actor_id, + 'target_actor_id' => $activity->target_actor_id, + 'activity_id' => $activity->id, + 'type' => 'follow', + 'created_at' => $activity->created_at, + ]); } elseif ($activity->type === 'Undo_Follow') { - new NotificationModel() - ->builder() + (new NotificationModel())->builder() ->delete([ - 'actor_id' => $activity->actor_id, + 'actor_id' => $activity->actor_id, 'target_actor_id' => $activity->target_actor_id, - 'type' => 'follow', + 'type' => 'follow', ]); } elseif (in_array($activity->type, ['Create', 'Like', 'Announce'], true) && $activity->post_id !== null) { - new NotificationModel() - ->insert([ - 'actor_id' => $activity->actor_id, - 'target_actor_id' => $activity->target_actor_id, - 'post_id' => $activity->post_id, - 'activity_id' => $activity->id, - 'type' => match ($activity->type) { - 'Create' => 'reply', - 'Like' => 'like', - 'Announce' => 'share', - }, - 'created_at' => $activity->created_at, - ]); + (new NotificationModel())->insert([ + 'actor_id' => $activity->actor_id, + 'target_actor_id' => $activity->target_actor_id, + 'post_id' => $activity->post_id, + 'activity_id' => $activity->id, + 'type' => match ($activity->type) { + 'Create' => 'reply', + 'Like' => 'like', + 'Announce' => 'share', + }, + 'created_at' => $activity->created_at, + ]); } elseif (in_array($activity->type, ['Undo_Like', 'Undo_Announce'], true) && $activity->post_id !== null) { - new NotificationModel() - ->builder() + (new NotificationModel())->builder() ->delete([ - 'actor_id' => $activity->actor_id, + 'actor_id' => $activity->actor_id, 'target_actor_id' => $activity->target_actor_id, - 'post_id' => service('uuid') + 'post_id' => service('uuid') ->fromString($activity->post_id) ->getBytes(), 'type' => match ($activity->type) { - 'Undo_Like' => 'like', + 'Undo_Like' => 'like', 'Undo_Announce' => 'share', }, ]); diff --git a/modules/Fediverse/Models/ActorModel.php b/modules/Fediverse/Models/ActorModel.php index c061e11d..3c550ddc 100644 --- a/modules/Fediverse/Models/ActorModel.php +++ b/modules/Fediverse/Models/ActorModel.php @@ -11,18 +11,17 @@ declare(strict_types=1); namespace Modules\Fediverse\Models; use CodeIgniter\Events\Events; -use CodeIgniter\Model; use Modules\Fediverse\Entities\Actor; -class ActorModel extends Model +class ActorModel extends BaseModel { /** * @var string */ - protected $table = 'fediverse_actors'; + protected $table = 'actors'; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -46,7 +45,7 @@ class ActorModel extends Model ]; /** - * @var class-string + * @var string */ protected $returnType = Actor::class; @@ -62,7 +61,16 @@ class ActorModel extends Model public function getActorById(int $id): ?Actor { - return $this->find($id); + $cacheName = config('Fediverse') + ->cachePrefix . "actor#{$id}"; + if (! ($found = cache($cacheName))) { + $found = $this->find($id); + + cache() + ->save($cacheName, $found, DECADE); + } + + return $found; } /** @@ -84,7 +92,7 @@ class ActorModel extends Model if (! ($found = cache($cacheName))) { $found = $this->where([ 'username' => $username, - 'domain' => $domain, + 'domain' => $domain, ])->first(); cache() @@ -120,8 +128,10 @@ class ActorModel extends Model config('Fediverse') ->cachePrefix . "actor#{$actorId}_followers"; if (! ($found = cache($cacheName))) { - $found = $this->join('fediverse_follows', 'fediverse_follows.actor_id = id', 'inner') - ->where('fediverse_follows.target_actor_id', $actorId) + $tablesPrefix = config('Fediverse') + ->tablesPrefix; + $found = $this->join($tablesPrefix . 'follows', $tablesPrefix . 'follows.actor_id = id', 'inner') + ->where($tablesPrefix . 'follows.target_actor_id', $actorId) ->findAll(); cache() @@ -136,7 +146,7 @@ class ActorModel extends Model */ public function isActorBlocked(string $actorUri): bool { - if (($actor = $this->getActorByUri($actorUri)) instanceof Actor) { + if (($actor = $this->getActorByUri($actorUri)) !== null) { return $actor->is_blocked; } @@ -202,8 +212,7 @@ class ActorModel extends Model $cacheName = config('Fediverse') ->cachePrefix . 'blocked_actors'; if (! ($found = cache($cacheName))) { - $result = $this->builder() - ->select('COUNT(*) as total_local_actors') + $result = $this->select('COUNT(*) as total_local_actors') ->where('domain', get_current_domain()) ->get() ->getResultArray(); @@ -225,30 +234,30 @@ class ActorModel extends Model ->cachePrefix . 'blocked_actors'; if (! ($found = cache($cacheName))) { $tablePrefix = config('Database') - ->default['DBPrefix']; - $result = $this->builder() - ->select('COUNT(DISTINCT `' . $tablePrefix . 'fediverse_actors`.`id`) as `total_active_actors`', false) + ->default['DBPrefix'] . config('Fediverse') + ->tablesPrefix; + $result = $this->select('COUNT(DISTINCT `cp_fediverse_actors`.`id`) as `total_active_actors`', false) ->join( - $tablePrefix . 'fediverse_posts', - $tablePrefix . 'fediverse_actors.id = ' . $tablePrefix . 'fediverse_posts.actor_id', - 'left outer', + $tablePrefix . 'posts', + $tablePrefix . 'actors.id = ' . $tablePrefix . 'posts.actor_id', + 'left outer' ) ->join( - $tablePrefix . 'fediverse_favourites', - $tablePrefix . 'fediverse_actors.id = ' . $tablePrefix . 'fediverse_favourites.actor_id', - 'left outer', + $tablePrefix . 'favourites', + $tablePrefix . 'actors.id = ' . $tablePrefix . 'favourites.actor_id', + 'left outer' ) - ->where($tablePrefix . 'fediverse_actors.domain', get_current_domain()) + ->where($tablePrefix . 'actors.domain', get_current_domain()) ->groupStart() ->where( - "`{$tablePrefix}fediverse_posts`.`created_at` >= UTC_TIMESTAMP() - INTERVAL {$lastNumberOfMonths} month", + "`{$tablePrefix}posts`.`created_at` >= UTC_TIMESTAMP() - INTERVAL {$lastNumberOfMonths} month", null, - false, + false ) ->orWhere( - "`{$tablePrefix}fediverse_favourites`.`created_at` >= UTC_TIMESTAMP() - INTERVAL {$lastNumberOfMonths} month", + "`{$tablePrefix}favourites`.`created_at` >= UTC_TIMESTAMP() - INTERVAL {$lastNumberOfMonths} month", null, - false, + false ) ->groupEnd() ->get() @@ -265,8 +274,12 @@ class ActorModel extends Model public function resetFollowersCount(): int | false { - $actorsFollowersCount = $this->db->table('fediverse_follows') - ->select('target_actor_id as id, COUNT(*) as `followers_count`') + $tablePrefix = config('Fediverse') + ->tablesPrefix; + + $actorsFollowersCount = $this->db->table($tablePrefix . 'follows')->select( + 'target_actor_id as id, COUNT(*) as `followers_count`' + ) ->groupBy('id') ->get() ->getResultArray(); @@ -280,8 +293,12 @@ class ActorModel extends Model public function resetPostsCount(): int | false { - $actorsFollowersCount = $this->db->table('fediverse_posts') - ->select('actor_id as id, COUNT(*) as `posts_count`') + $tablePrefix = config('Fediverse') + ->tablesPrefix; + + $actorsFollowersCount = $this->db->table($tablePrefix . 'posts')->select( + 'actor_id as id, COUNT(*) as `posts_count`' + ) ->where([ 'in_reply_to_id' => null, ]) diff --git a/modules/Fediverse/Models/BaseModel.php b/modules/Fediverse/Models/BaseModel.php new file mode 100644 index 00000000..685f1776 --- /dev/null +++ b/modules/Fediverse/Models/BaseModel.php @@ -0,0 +1,26 @@ +table = config('Fediverse') + ->tablesPrefix . $this->table; + } +} diff --git a/modules/Fediverse/Models/BaseUuidModel.php b/modules/Fediverse/Models/BaseUuidModel.php new file mode 100644 index 00000000..e2f80ea9 --- /dev/null +++ b/modules/Fediverse/Models/BaseUuidModel.php @@ -0,0 +1,20 @@ +table = config('Fediverse') + ->tablesPrefix . $this->table; + } +} diff --git a/modules/Fediverse/Models/BlockedDomainModel.php b/modules/Fediverse/Models/BlockedDomainModel.php index 3b8acf3f..933f6e52 100644 --- a/modules/Fediverse/Models/BlockedDomainModel.php +++ b/modules/Fediverse/Models/BlockedDomainModel.php @@ -12,15 +12,14 @@ namespace Modules\Fediverse\Models; use CodeIgniter\Database\BaseResult; use CodeIgniter\Events\Events; -use CodeIgniter\Model; use Modules\Fediverse\Entities\BlockedDomain; -class BlockedDomainModel extends Model +class BlockedDomainModel extends BaseModel { /** * @var string */ - protected $table = 'fediverse_blocked_domains'; + protected $table = 'blocked_domains'; /** * @var string @@ -28,12 +27,12 @@ class BlockedDomainModel extends Model protected $primaryKey = 'name'; /** - * @var list + * @var string[] */ protected $allowedFields = ['name']; /** - * @var class-string + * @var string */ protected $returnType = BlockedDomain::class; @@ -47,7 +46,7 @@ class BlockedDomainModel extends Model */ protected $useTimestamps = true; - protected $updatedField = ''; + protected $updatedField; /** * Retrieves instance or podcast domain blocks depending on whether or not $podcastId param is set. diff --git a/modules/Fediverse/Models/FavouriteModel.php b/modules/Fediverse/Models/FavouriteModel.php index 0c1dfc6f..3ca5aa62 100644 --- a/modules/Fediverse/Models/FavouriteModel.php +++ b/modules/Fediverse/Models/FavouriteModel.php @@ -11,19 +11,18 @@ declare(strict_types=1); namespace Modules\Fediverse\Models; use CodeIgniter\Events\Events; -use Michalsn\Uuid\UuidModel; use Modules\Fediverse\Activities\LikeActivity; use Modules\Fediverse\Activities\UndoActivity; use Modules\Fediverse\Entities\Actor; use Modules\Fediverse\Entities\Favourite; use Modules\Fediverse\Entities\Post; -class FavouriteModel extends UuidModel +class FavouriteModel extends BaseUuidModel { /** * @var string */ - protected $table = 'fediverse_favourites'; + protected $table = 'favourites'; /** * @var string[] @@ -31,12 +30,12 @@ class FavouriteModel extends UuidModel protected $uuidFields = ['post_id']; /** - * @var list + * @var string[] */ protected $allowedFields = ['actor_id', 'post_id']; /** - * @var class-string + * @var string */ protected $returnType = Favourite::class; @@ -45,7 +44,7 @@ class FavouriteModel extends UuidModel */ protected $useTimestamps = true; - protected $updatedField = ''; + protected $updatedField; public function addFavourite(Actor $actor, Post $post, bool $registerActivity = true): void { @@ -53,11 +52,10 @@ class FavouriteModel extends UuidModel $this->insert([ 'actor_id' => $actor->id, - 'post_id' => $post->id, + 'post_id' => $post->id, ]); model('PostModel', false) - ->builder() ->where('id', service('uuid') ->fromString($post->id) ->getBytes()) ->increment('favourites_count'); @@ -98,13 +96,12 @@ class FavouriteModel extends UuidModel $this->db->transStart(); model('PostModel', false) - ->builder() ->where('id', service('uuid') ->fromString($post->id) ->getBytes()) ->decrement('favourites_count'); $this->where([ 'actor_id' => $actor->id, - 'post_id' => service('uuid') + 'post_id' => service('uuid') ->fromString($post->id) ->getBytes(), ]) @@ -115,9 +112,9 @@ class FavouriteModel extends UuidModel // get like activity $activity = model('ActivityModel', false) ->where([ - 'type' => 'Like', + 'type' => 'Like', 'actor_id' => $actor->id, - 'post_id' => service('uuid') + 'post_id' => service('uuid') ->fromString($post->id) ->getBytes(), ]) @@ -168,10 +165,10 @@ class FavouriteModel extends UuidModel if ( $this->where([ 'actor_id' => $actor->id, - 'post_id' => service('uuid') + 'post_id' => service('uuid') ->fromString($post->id) ->getBytes(), - ])->first() instanceof Favourite + ])->first() ) { $this->removeFavourite($actor, $post); } else { diff --git a/modules/Fediverse/Models/FollowModel.php b/modules/Fediverse/Models/FollowModel.php index 9541625a..5a49b0a8 100644 --- a/modules/Fediverse/Models/FollowModel.php +++ b/modules/Fediverse/Models/FollowModel.php @@ -12,27 +12,26 @@ namespace Modules\Fediverse\Models; use CodeIgniter\Events\Events; use CodeIgniter\I18n\Time; -use CodeIgniter\Model; use Exception; use Modules\Fediverse\Activities\FollowActivity; use Modules\Fediverse\Activities\UndoActivity; use Modules\Fediverse\Entities\Actor; use Modules\Fediverse\Entities\Follow; -class FollowModel extends Model +class FollowModel extends BaseModel { /** * @var string */ - protected $table = 'fediverse_follows'; + protected $table = 'follows'; /** - * @var list + * @var string[] */ protected $allowedFields = ['actor_id', 'target_actor_id']; /** - * @var class-string + * @var string */ protected $returnType = Follow::class; @@ -41,7 +40,7 @@ class FollowModel extends Model */ protected $useTimestamps = true; - protected $updatedField = ''; + protected $updatedField; /** * @param Actor $actor Actor that is following @@ -53,13 +52,12 @@ class FollowModel extends Model $this->db->transStart(); $this->insert([ - 'actor_id' => $actor->id, + 'actor_id' => $actor->id, 'target_actor_id' => $targetActor->id, ]); // increment followers_count for target actor model('ActorModel', false) - ->builder() ->where('id', $targetActor->id) ->increment('followers_count'); @@ -109,13 +107,12 @@ class FollowModel extends Model $this->db->transStart(); $this->where([ - 'actor_id' => $actor->id, + 'actor_id' => $actor->id, 'target_actor_id' => $targetActor->id, ])->delete(); // decrement followers_count for target actor model('ActorModel', false) - ->builder() ->where('id', $targetActor->id) ->decrement('followers_count'); @@ -124,8 +121,8 @@ class FollowModel extends Model // get follow activity from database $followActivity = model('ActivityModel', false) ->where([ - 'type' => 'Follow', - 'actor_id' => $actor->id, + 'type' => 'Follow', + 'actor_id' => $actor->id, 'target_actor_id' => $targetActor->id, ]) ->first(); diff --git a/modules/Fediverse/Models/NotificationModel.php b/modules/Fediverse/Models/NotificationModel.php index b0993d6e..24732d7d 100644 --- a/modules/Fediverse/Models/NotificationModel.php +++ b/modules/Fediverse/Models/NotificationModel.php @@ -10,15 +10,14 @@ declare(strict_types=1); namespace Modules\Fediverse\Models; -use Michalsn\Uuid\UuidModel; use Modules\Fediverse\Entities\Notification; -class NotificationModel extends UuidModel +class NotificationModel extends BaseUuidModel { /** * @var string */ - protected $table = 'fediverse_notifications'; + protected $table = 'notifications'; /** * @var string @@ -26,7 +25,7 @@ class NotificationModel extends UuidModel protected $primaryKey = 'id'; /** - * @var class-string + * @var string */ protected $returnType = Notification::class; @@ -41,7 +40,7 @@ class NotificationModel extends UuidModel protected $uuidFields = ['post_id', 'activity_id']; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'actor_id', diff --git a/modules/Fediverse/Models/PostModel.php b/modules/Fediverse/Models/PostModel.php index e24000cc..94f2130c 100644 --- a/modules/Fediverse/Models/PostModel.php +++ b/modules/Fediverse/Models/PostModel.php @@ -11,11 +11,11 @@ declare(strict_types=1); namespace Modules\Fediverse\Models; use CodeIgniter\Database\BaseResult; +use CodeIgniter\Database\Query; use CodeIgniter\Events\Events; use CodeIgniter\HTTP\URI; use CodeIgniter\I18n\Time; use Exception; -use Michalsn\Uuid\UuidModel; use Modules\Fediverse\Activities\AnnounceActivity; use Modules\Fediverse\Activities\CreateActivity; use Modules\Fediverse\Activities\DeleteActivity; @@ -24,12 +24,12 @@ use Modules\Fediverse\Entities\Actor; use Modules\Fediverse\Entities\Post; use Modules\Fediverse\Objects\TombstoneObject; -class PostModel extends UuidModel +class PostModel extends BaseUuidModel { /** * @var string */ - protected $table = 'fediverse_posts'; + protected $table = 'posts'; /** * @var string @@ -42,7 +42,7 @@ class PostModel extends UuidModel protected $uuidFields = ['id', 'in_reply_to_id', 'reblog_of_id']; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -52,7 +52,6 @@ class PostModel extends UuidModel 'reblog_of_id', 'message', 'message_html', - 'is_private', 'favourites_count', 'reblogs_count', 'replies_count', @@ -60,7 +59,7 @@ class PostModel extends UuidModel ]; /** - * @var class-string + * @var string */ protected $returnType = Post::class; @@ -74,24 +73,33 @@ class PostModel extends UuidModel */ protected $useTimestamps = true; - protected $updatedField = ''; + protected $updatedField; /** * @var array */ protected $validationRules = [ - 'actor_id' => 'required', + 'actor_id' => 'required', 'message_html' => 'max_length[500]', ]; /** - * @var list + * @var string[] */ protected $beforeInsert = ['setPostId']; public function getPostById(string $postId): ?Post { - return $this->find($postId); + $cacheName = config('Fediverse') + ->cachePrefix . "post#{$postId}"; + if (! ($found = cache($cacheName))) { + $found = $this->find($postId); + + cache() + ->save($cacheName, $found, DECADE); + } + + return $found; } public function getPostByUri(string $postUri): ?Post @@ -124,7 +132,7 @@ class PostModel extends UuidModel "actor#{$actorId}_published_posts"; if (! ($found = cache($cacheName))) { $found = $this->where([ - 'actor_id' => $actorId, + 'actor_id' => $actorId, 'in_reply_to_id' => null, ]) ->where('`published_at` <= UTC_TIMESTAMP()', null, false) @@ -134,7 +142,7 @@ class PostModel extends UuidModel $secondsToNextUnpublishedPost = $this->getSecondsToNextUnpublishedPosts($actorId); cache() - ->save($cacheName, $found, $secondsToNextUnpublishedPost ?: DECADE); + ->save($cacheName, $found, $secondsToNextUnpublishedPost ? $secondsToNextUnpublishedPost : DECADE); } return $found; @@ -146,8 +154,7 @@ class PostModel extends UuidModel */ public function getSecondsToNextUnpublishedPosts(int $actorId): int | false { - $result = $this->builder() - ->select('TIMESTAMPDIFF(SECOND, UTC_TIMESTAMP(), `published_at`) as timestamp_diff') + $result = $this->select('TIMESTAMPDIFF(SECOND, UTC_TIMESTAMP(), `published_at`) as timestamp_diff') ->where([ 'actor_id' => $actorId, ]) @@ -175,21 +182,21 @@ class PostModel extends UuidModel ($withBlocked ? '_withBlocked' : ''); if (! ($found = cache($cacheName))) { + $tablesPrefix = config('Fediverse') + ->tablesPrefix; if (! $withBlocked) { - $this->select('fediverse_posts.*') - ->join('fediverse_actors', 'fediverse_actors.id = fediverse_posts.actor_id', 'inner') - ->where('fediverse_actors.is_blocked', 0); + $this->select($tablesPrefix . 'posts.*') + ->join( + $tablesPrefix . 'actors', + $tablesPrefix . 'actors.id = ' . $tablesPrefix . 'posts.actor_id', + 'inner' + ) + ->where($tablesPrefix . 'actors.is_blocked', 0); } $this->where('in_reply_to_id', $this->uuid->fromString($postId) ->getBytes()) ->where('`published_at` <= UTC_TIMESTAMP()', null, false) ->orderBy('published_at', 'ASC'); - - // do not get private replies if public - if (! can_user_interact()) { - $this->where('is_private', false); - } - $found = $this->findAll(); cache() @@ -223,9 +230,9 @@ class PostModel extends UuidModel return $found; } - public function addPreviewCard(string $postId, int $previewCardId): bool + public function addPreviewCard(string $postId, int $previewCardId): Query | bool { - return $this->db->table('fediverse_posts_preview_cards') + return $this->db->table(config('Fediverse')->tablesPrefix . 'posts_preview_cards') ->insert([ 'post_id' => $this->uuid->fromString($postId) ->getBytes(), @@ -241,8 +248,8 @@ class PostModel extends UuidModel public function addPost( Post $post, bool $createPreviewCard = true, - bool $registerActivity = true, - ): bool|int|object|string { + bool $registerActivity = true + ): string | false { helper('fediverse'); $this->db->transStart(); @@ -272,7 +279,6 @@ class PostModel extends UuidModel if ($post->in_reply_to_id === null) { // post is not a reply model('ActorModel', false) - ->builder() ->where('id', $post->actor_id) ->increment('posts_count'); @@ -291,10 +297,6 @@ class PostModel extends UuidModel ->set('actor', $post->actor->uri) ->set('object', new $noteObjectClass($post)); - if ($post->in_reply_to_id !== null && $post->is_private) { - $createActivity->set('to', [$post->reply_to_post->actor->uri]); - } - $activityId = model('ActivityModel', false) ->newActivity( 'Create', @@ -328,7 +330,7 @@ class PostModel extends UuidModel // update post create activity schedule in database $scheduledActivity = model('ActivityModel', false) ->where([ - 'type' => 'Create', + 'type' => 'Create', 'post_id' => $this->uuid ->fromString($updatedPost->id) ->getBytes(), @@ -338,10 +340,9 @@ class PostModel extends UuidModel // update published date in payload $newPayload = $scheduledActivity->payload; $newPayload->object->published = $updatedPost->published_at->format(DATE_W3C); - model('ActivityModel', false) ->update($scheduledActivity->id, [ - 'payload' => json_encode($newPayload, JSON_THROW_ON_ERROR), + 'payload' => json_encode($newPayload, JSON_THROW_ON_ERROR), 'scheduled_at' => $updatedPost->published_at, ]); @@ -379,7 +380,7 @@ class PostModel extends UuidModel if ( $post->preview_card && $this->db - ->table('fediverse_posts_preview_cards') + ->table(config('Fediverse')->tablesPrefix . 'posts_preview_cards') ->where('preview_card_id', $post->preview_card->id) ->countAll() <= 1 ) { @@ -415,19 +416,15 @@ class PostModel extends UuidModel if ($post->in_reply_to_id === null && $post->reblog_of_id === null) { model('ActorModel', false) - ->builder() ->where('id', $post->actor_id) ->decrement('posts_count'); Events::trigger('on_post_remove', $post); } elseif ($post->in_reply_to_id !== null) { - if (! $post->is_private) { - // Post to remove is a reply - model('PostModel', false) - ->builder() - ->where('id', $this->uuid->fromString($post->in_reply_to_id) ->getBytes()) - ->decrement('replies_count'); - } + // Post to remove is a reply + model('PostModel', false) + ->where('id', $this->uuid->fromString($post->in_reply_to_id) ->getBytes()) + ->decrement('replies_count'); Events::trigger('on_reply_remove', $post); } @@ -445,7 +442,7 @@ class PostModel extends UuidModel public function addReply( Post $reply, bool $createPreviewCard = true, - bool $registerActivity = true, + bool $registerActivity = true ): string | false { if (! $reply->in_reply_to_id) { throw new Exception('Passed post is not a reply!'); @@ -455,12 +452,9 @@ class PostModel extends UuidModel $postId = $this->addPost($reply, $createPreviewCard, $registerActivity); - if (! $reply->is_private) { - model('PostModel', false) - ->builder() - ->where('id', $this->uuid->fromString($reply->in_reply_to_id) ->getBytes()) - ->increment('replies_count'); - } + model('PostModel', false) + ->where('id', $this->uuid->fromString($reply->in_reply_to_id) ->getBytes()) + ->increment('replies_count'); Events::trigger('on_post_reply', $reply); @@ -473,11 +467,6 @@ class PostModel extends UuidModel public function reblog(Actor $actor, Post $post, bool $registerActivity = true): string | false { - // cannot reblog a private post - if ($post->is_private) { - return false; - } - $this->db->transStart(); $userId = null; @@ -486,22 +475,20 @@ class PostModel extends UuidModel } $reblog = new Post([ - 'actor_id' => $actor->id, + 'actor_id' => $actor->id, 'reblog_of_id' => $post->id, 'published_at' => Time::now(), - 'created_by' => $userId, + 'created_by' => $userId, ]); // add reblog $reblogId = $this->insert($reblog); model('ActorModel', false) - ->builder() ->where('id', $actor->id) ->increment('posts_count'); model('PostModel', false) - ->builder() ->where('id', $this->uuid->fromString($post->id)->getBytes()) ->increment('reblogs_count'); @@ -541,12 +528,10 @@ class PostModel extends UuidModel $this->db->transStart(); model('ActorModel', false) - ->builder() ->where('id', $reblogPost->actor_id) ->decrement('posts_count'); model('PostModel', false) - ->builder() ->where('id', $this->uuid->fromString($reblogPost->reblog_of_id) ->getBytes()) ->decrement('reblogs_count'); @@ -555,16 +540,16 @@ class PostModel extends UuidModel // get like activity $activity = model('ActivityModel', false) ->where([ - 'type' => 'Announce', + 'type' => 'Announce', 'actor_id' => $reblogPost->actor_id, - 'post_id' => $this->uuid + 'post_id' => $this->uuid ->fromString($reblogPost->reblog_of_id) ->getBytes(), ]) ->first(); $announceActivity = new AnnounceActivity($reblogPost); - $announceActivity->set('id', url_to('activity', $reblogPost->actor->username, $activity->id)); + $announceActivity->set('id', url_to('activity', $reblogPost->actor->username, $activity->id),); $undoActivity ->set('actor', $reblogPost->actor->uri) @@ -605,11 +590,11 @@ class PostModel extends UuidModel { if ( ! ($reblogPost = $this->where([ - 'actor_id' => $actor->id, + 'actor_id' => $actor->id, 'reblog_of_id' => $this->uuid ->fromString($post->id) ->getBytes(), - ])->first()) instanceof Post + ])->first()) ) { $this->reblog($actor, $post); } else { @@ -624,10 +609,11 @@ class PostModel extends UuidModel $cacheName = config('Fediverse') ->cachePrefix . 'blocked_actors'; if (! ($found = cache($cacheName))) { - $result = $this->builder() - ->select('COUNT(*) as total_local_posts') - ->join('fediverse_actors', 'fediverse_actors.id = fediverse_posts.actor_id') - ->where('fediverse_actors.domain', get_current_domain()) + $tablePrefix = config('Fediverse') + ->tablesPrefix; + $result = $this->select('COUNT(*) as total_local_posts') + ->join($tablePrefix . 'actors', $tablePrefix . 'actors.id = ' . $tablePrefix . 'posts.actor_id') + ->where($tablePrefix . 'actors.domain', get_current_domain()) ->where('`published_at` <= UTC_TIMESTAMP()', null, false) ->get() ->getResultArray(); @@ -643,8 +629,12 @@ class PostModel extends UuidModel public function resetFavouritesCount(): int | false { - $postsFavouritesCount = $this->db->table('fediverse_favourites') - ->select('post_id as id, COUNT(*) as `favourites_count`') + $tablePrefix = config('Fediverse') + ->tablesPrefix; + + $postsFavouritesCount = $this->db->table($tablePrefix . 'favourites')->select( + 'post_id as id, COUNT(*) as `favourites_count`' + ) ->groupBy('id') ->get() ->getResultArray(); @@ -659,10 +649,12 @@ class PostModel extends UuidModel public function resetReblogsCount(): int | false { - $postsReblogsCount = $this->builder() - ->select('fediverse_posts.id, COUNT(*) as `replies_count`') - ->join('fediverse_posts as p2', 'fediverse_posts.id = p2.reblog_of_id') - ->groupBy('fediverse_posts.id') + $tablePrefix = config('Fediverse') + ->tablesPrefix; + + $postsReblogsCount = $this->select($tablePrefix . 'posts.id, COUNT(*) as `replies_count`') + ->join($tablePrefix . 'posts as p2', $tablePrefix . 'posts.id = p2.reblog_of_id') + ->groupBy($tablePrefix . 'posts.id') ->get() ->getResultArray(); @@ -676,10 +668,12 @@ class PostModel extends UuidModel public function resetRepliesCount(): int | false { - $postsRepliesCount = $this->builder() - ->select('fediverse_posts.id, COUNT(*) as `replies_count`') - ->join('fediverse_posts as p2', 'fediverse_posts.id = p2.in_reply_to_id') - ->groupBy('fediverse_posts.id') + $tablePrefix = config('Fediverse') + ->tablesPrefix; + + $postsRepliesCount = $this->select($tablePrefix . 'posts.id, COUNT(*) as `replies_count`') + ->join($tablePrefix . 'posts as p2', $tablePrefix . 'posts.id = p2.in_reply_to_id') + ->groupBy($tablePrefix . 'posts.id') ->get() ->getResultArray(); diff --git a/modules/Fediverse/Models/PreviewCardModel.php b/modules/Fediverse/Models/PreviewCardModel.php index b0e64c96..fb9c028e 100644 --- a/modules/Fediverse/Models/PreviewCardModel.php +++ b/modules/Fediverse/Models/PreviewCardModel.php @@ -11,18 +11,17 @@ declare(strict_types=1); namespace Modules\Fediverse\Models; use CodeIgniter\Database\BaseResult; -use CodeIgniter\Model; use Modules\Fediverse\Entities\PreviewCard; -class PreviewCardModel extends Model +class PreviewCardModel extends BaseModel { /** * @var string */ - protected $table = 'fediverse_preview_cards'; + protected $table = 'preview_cards'; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -39,7 +38,7 @@ class PreviewCardModel extends Model ]; /** - * @var class-string + * @var string */ protected $returnType = PreviewCard::class; @@ -76,9 +75,11 @@ class PreviewCardModel extends Model config('Fediverse') ->cachePrefix . "post#{$postId}_preview_card"; if (! ($found = cache($cacheName))) { + $tablesPrefix = config('Fediverse') + ->tablesPrefix; $found = $this->join( - 'fediverse_posts_preview_cards', - 'fediverse_posts_preview_cards.preview_card_id = id', + $tablesPrefix . 'posts_preview_cards', + $tablesPrefix . 'posts_preview_cards.preview_card_id = id', 'inner', ) ->where('post_id', service('uuid') ->fromString($postId) ->getBytes()) diff --git a/modules/Fediverse/Objects/ActorObject.php b/modules/Fediverse/Objects/ActorObject.php index d00ccb84..99f84f5e 100644 --- a/modules/Fediverse/Objects/ActorObject.php +++ b/modules/Fediverse/Objects/ActorObject.php @@ -68,21 +68,21 @@ class ActorObject extends ObjectType $this->followers = $actor->followers_url; $this->image = [ - 'type' => 'Image', + 'type' => 'Image', 'mediaType' => $actor->cover_image_mimetype, - 'url' => $actor->cover_image_url, + 'url' => $actor->cover_image_url, ]; $this->icon = [ - 'type' => 'Image', + 'type' => 'Image', 'mediaType' => $actor->avatar_image_mimetype, - 'url' => $actor->avatar_image_url, + 'url' => $actor->avatar_image_url, ]; if ($actor->public_key !== null) { $this->publicKey = [ - 'id' => $actor->public_key_id, - 'owner' => $actor->uri, + 'id' => $actor->public_key_id, + 'owner' => $actor->uri, 'publicKeyPem' => $actor->public_key, ]; } diff --git a/modules/Fediverse/Objects/NoteObject.php b/modules/Fediverse/Objects/NoteObject.php index 73af27a3..561ce89b 100644 --- a/modules/Fediverse/Objects/NoteObject.php +++ b/modules/Fediverse/Objects/NoteObject.php @@ -39,19 +39,13 @@ class NoteObject extends ObjectType $this->attributedTo = $post->actor->uri; if ($post->in_reply_to_id !== null) { - if ($post->is_private) { - $this->to = [$post->reply_to_post->actor->uri]; - } else { - $this->to[] = $post->reply_to_post->actor->uri; - } + $this->to[] = $post->reply_to_post->actor->uri; $this->inReplyTo = $post->reply_to_post->uri; } $this->replies = url_to('post-replies', esc($post->actor->username), $post->id); - if (! $post->is_private) { - $this->cc = [$post->actor->followers_url]; - } + $this->cc = [$post->actor->followers_url]; } } diff --git a/modules/Fediverse/Objects/OrderedCollectionObject.php b/modules/Fediverse/Objects/OrderedCollectionObject.php index 339ffb03..8012d226 100644 --- a/modules/Fediverse/Objects/OrderedCollectionObject.php +++ b/modules/Fediverse/Objects/OrderedCollectionObject.php @@ -28,15 +28,15 @@ class OrderedCollectionObject extends ObjectType protected ?string $last = null; /** - * @param ObjectType[]|list|null $orderedItems + * @param ObjectType[]|null $orderedItems */ public function __construct( protected ?array $orderedItems = null, - ?Pager $pager = null, + ?Pager $pager = null ) { $this->id = current_url(); - if ($pager instanceof Pager) { + if ($pager !== null) { $totalItems = $pager->getTotal(); $this->totalItems = $totalItems; diff --git a/modules/Fediverse/WebFinger.php b/modules/Fediverse/WebFinger.php index e07f5115..82e0472f 100644 --- a/modules/Fediverse/WebFinger.php +++ b/modules/Fediverse/WebFinger.php @@ -11,11 +11,13 @@ declare(strict_types=1); namespace Modules\Fediverse; use Exception; -use Modules\Fediverse\Entities\Actor; class WebFinger { - private const string RESOURCE_PATTERN = '/^acct:(?P([\w_]+))@(?P([\w\-\.]+[\w]+)(:[\d]+)?)$/x'; + /** + * @var string + */ + private const RESOURCE_PATTERN = '/^acct:(?P([\w_]+))@(?P([\w\-\.]+[\w]+)(:[\d]+)?)$/x'; protected string $username; @@ -36,7 +38,7 @@ class WebFinger protected array $links = []; public function __construct( - protected string $subject, + protected string $subject ) { // Split resource into its parts (username, domain) $parts = $this->splitResource($subject); @@ -60,20 +62,20 @@ class WebFinger } if ( - ! ($actor = model('ActorModel', false)->getActorByUsername($username, $domain)) instanceof Actor + ! ($actor = model('ActorModel', false)->getActorByUsername($username, $domain)) ) { throw new Exception('Could not find actor'); } - $this->aliases = [$actor->uri]; + $this->aliases = [$actor->id]; $this->links = [ [ - 'rel' => 'self', + 'rel' => 'self', 'type' => 'application/activity+json', 'href' => $actor->uri, ], [ - 'rel' => 'http://webfinger.net/rel/profile-page', + 'rel' => 'http://webfinger.net/rel/profile-page', 'type' => 'text/html', 'href' => $actor->uri, # TODO: should there be 2 values? @actorUsername @@ -91,16 +93,16 @@ class WebFinger return [ 'subject' => $this->subject, 'aliases' => $this->aliases, - 'links' => $this->links, + 'links' => $this->links, ]; } /** * Split resource into its parts (username, domain) * - * @return array{0:string,username:non-empty-string,1:non-empty-string,2:non-empty-string,domain:non-falsy-string,3:non-falsy-string,4:non-falsy-string,5?:non-falsy-string} + * @return array|false */ - private function splitResource(string $resource): bool|array + private function splitResource(string $resource): array | false { if (! preg_match(self::RESOURCE_PATTERN, $resource, $matches)) { // Resource pattern failed diff --git a/modules/Install/Commands/CreateSuperadmin.php b/modules/Install/Commands/CreateSuperadmin.php deleted file mode 100644 index 0dfdad71..00000000 --- a/modules/Install/Commands/CreateSuperadmin.php +++ /dev/null @@ -1,145 +0,0 @@ -> - */ - private array $validationRules = []; - - #[Override] - public function run(array $params): void - { - // first, check that super admin does not exist - $userModel = model('UserModel'); - $isSuperAdminCreated = $userModel->where('is_owner', true) - ->countAllResults(); - - if ($isSuperAdminCreated > 0) { - $this->write('Super admin was already created!', 'red'); - - exit(EXIT_ERROR); - } - - $this->setValidationRules(); - - $username = $params['n'] ?? null; - $email = $params['e'] ?? null; - - $data = [ - 'is_owner' => true, - ]; - - if ($username === null) { - $username = $this->prompt('Username', null, $this->validationRules['username']['rules']); - } - - $data['username'] = $username; - - if ($email === null) { - $email = $this->prompt('Email', null, $this->validationRules['email']['rules']); - } - - $data['email'] = $email; - - $password = $this->prompt('Password', null, $this->validationRules['password']['rules']); - $passwordConfirm = $this->prompt( - 'Password confirmation', - null, - $this->validationRules['password']['rules'], - ); - - if ($password !== $passwordConfirm) { - throw new BadInputException("The passwords don't match"); - } - - $data['password'] = $password; - - // Run validation if the user has passed username and/or email via command line - $validation = service('validation'); - $validation->setRules($this->validationRules); - - if (! $validation->run($data)) { - foreach ($validation->getErrors() as $message) { - $this->write($message, 'red'); - } - - throw new CancelException('Super admin creation aborted'); - } - - $userModel = model('UserModel'); - - $user = new User($data); - $userModel->save($user); - - $user = $userModel->findById($userModel->getInsertID()); - - // set newly created user as most powerful instance group (superadmin) - $user->addGroup(setting('AuthGroups.mostPowerfulGroup')); - - $this->write('Super admin "' . $username . '" created', 'green'); - } - - private function setValidationRules(): void - { - $validationRules = new ValidationRules(); - - $rules = $validationRules->getRegistrationRules(); - - // Remove `strong_password` because it only supports use cases - // to check the user's own password. - $passwordRules = $rules['password']['rules']; - if (is_string($passwordRules)) { - $passwordRules = explode('|', $passwordRules); - } - - if (($key = array_search('strong_password[]', $passwordRules, true)) !== false) { - unset($passwordRules[$key]); - } - - if (($key = array_search('strong_password', $passwordRules, true)) !== false) { - unset($passwordRules[$key]); - } - - $config = config('Auth'); - - // Add `min_length` - $passwordRules[] = 'min_length[' . $config->minimumPasswordLength . ']'; - - $rules['password']['rules'] = $passwordRules; - - $this->validationRules = [ - 'username' => $rules['username'], - 'email' => $rules['email'], - 'password' => $rules['password'], - ]; - } -} diff --git a/modules/Install/Commands/InitDatabase.php b/modules/Install/Commands/InitDatabase.php deleted file mode 100644 index 67d8f61b..00000000 --- a/modules/Install/Commands/InitDatabase.php +++ /dev/null @@ -1,40 +0,0 @@ -setNamespace(null) - ->latest(); - - // Seed database - $seeder = Database::seeder(); - $seeder->call('AppSeeder'); - } -} diff --git a/modules/Install/Config/Routes.php b/modules/Install/Config/Routes.php index 481d01fd..94a289c5 100644 --- a/modules/Install/Config/Routes.php +++ b/modules/Install/Config/Routes.php @@ -4,9 +4,7 @@ declare(strict_types=1); namespace Modules\Install\Config; -use CodeIgniter\Router\RouteCollection; - -/** @var RouteCollection $routes */ +$routes = service('routes'); // Install Wizard routes $routes->group( @@ -19,21 +17,21 @@ $routes->group( $routes->get('/', 'InstallController', [ 'as' => 'install', ]); - $routes->post('instance-config', 'InstallController::instanceConfigAction', [ + $routes->post('instance-config', 'InstallController::attemptInstanceConfig', [ 'as' => 'instance-config', ]); - $routes->post('database-config', 'InstallController::databaseConfigAction', [ + $routes->post('database-config', 'InstallController::attemptDatabaseConfig', [ 'as' => 'database-config', ]); - $routes->post('cache-config', 'InstallController::cacheConfigAction', [ + $routes->post('cache-config', 'InstallController::attemptCacheConfig', [ 'as' => 'cache-config', ]); $routes->post( 'create-superadmin', - 'InstallController::createSuperAdminAction', + 'InstallController::attemptCreateSuperAdmin', [ 'as' => 'create-superadmin', ], ); - }, + } ); diff --git a/modules/Install/Controllers/InstallController.php b/modules/Install/Controllers/InstallController.php index f6f875af..0f80f081 100644 --- a/modules/Install/Controllers/InstallController.php +++ b/modules/Install/Controllers/InstallController.php @@ -10,19 +10,18 @@ declare(strict_types=1); namespace Modules\Install\Controllers; +use App\Models\UserModel; use CodeIgniter\Controller; use CodeIgniter\Database\Exceptions\DatabaseException; use CodeIgniter\Exceptions\PageNotFoundException; use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; -use CodeIgniter\Shield\Entities\User; -use CodeIgniter\Shield\Exceptions\ValidationException as ShieldValidationException; use Config\Database; +use Config\Services; use Dotenv\Dotenv; use Dotenv\Exception\ValidationException; -use Modules\Auth\Models\UserModel; -use Override; +use Modules\Auth\Entities\User; use Psr\Log\LoggerInterface; use Throwable; use ViewThemes\Theme; @@ -30,15 +29,17 @@ use ViewThemes\Theme; class InstallController extends Controller { /** - * @var list + * @var string[] */ - protected $helpers = ['form', 'components', 'svg', 'misc', 'setting']; + protected $helpers = ['form', 'components', 'svg', 'misc']; - #[Override] + /** + * Constructor. + */ public function initController( RequestInterface $request, ResponseInterface $response, - LoggerInterface $logger, + LoggerInterface $logger ): void { // Do Not Edit This Line parent::initController($request, $response, $logger); @@ -74,7 +75,7 @@ class InstallController extends Controller $dotenv->required(['app.baseURL', 'analytics.salt', 'admin.gateway', 'auth.gateway']); } catch (ValidationException) { // form to input instance configuration - return $this->instanceConfigView(); + return $this->instanceConfig(); } try { @@ -86,13 +87,13 @@ class InstallController extends Controller 'database.default.DBPrefix', ]); } catch (ValidationException) { - return $this->databaseConfigView(); + return $this->databaseConfig(); } try { $dotenv->required('cache.handler'); } catch (ValidationException) { - return $this->cacheConfigView(); + return $this->cacheConfig(); } } else { try { @@ -116,20 +117,23 @@ class InstallController extends Controller try { $db = db_connect(); - // Check if instance owner has been created, meaning install was completed - if ($db->tableExists('users') && new UserModel()->where('is_owner', true) - ->first() instanceof User - ) { + // Check if superadmin has been created, meaning migrations and seeds have passed + if ( + $db->tableExists('users') && + (new UserModel())->countAll() > 0 + ) { // if so, show a 404 page throw PageNotFoundException::forPageNotFound(); } + + /** @noRector */ } catch (DatabaseException) { // Could not connect to the database // show database config view to fix value session() ->setFlashdata('error', lang('Install.messages.databaseConnectError')); - return $this->databaseConfigView(); + return $this->databaseConfig(); } // migrate if no user has been created @@ -138,40 +142,39 @@ class InstallController extends Controller // Check if all seeds have succeeded $this->seed(); - return $this->createSuperAdminView(); + return $this->createSuperAdmin(); } - public function instanceConfigView(): string + public function instanceConfig(): string { return view('instance_config'); } - public function instanceConfigAction(): RedirectResponse + public function attemptInstanceConfig(): RedirectResponse { $rules = [ - 'hostname' => 'required|valid_url_strict', - 'media_base_url' => 'permit_empty|valid_url_strict', - 'admin_gateway' => 'required', - 'auth_gateway' => 'required|differs[admin_gateway]', + 'hostname' => 'required|validate_url', + 'media_base_url' => 'permit_empty|validate_url', + 'admin_gateway' => 'required', + 'auth_gateway' => 'required|differs[admin_gateway]', ]; if (! $this->validate($rules)) { return redirect() - ->to((host_url() ?? config('App') ->baseURL) . config('Install')->gateway) + ->to((host_url() === null ? config('App') ->baseURL : host_url()) . config('Install')->gateway) ->withInput() ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - $baseUrl = $validData['hostname']; - $mediaBaseUrl = $validData['media_base_url']; + $baseUrl = $this->request->getPost('hostname'); + $mediaBaseUrl = $this->request->getPost('media_base_url'); self::writeEnv([ - 'app.baseURL' => $baseUrl, - 'media.baseURL' => $mediaBaseUrl === '' ? $baseUrl : $mediaBaseUrl, + 'app.baseURL' => $baseUrl, + 'app.mediaBaseURL' => + $mediaBaseUrl === '' ? $baseUrl : $mediaBaseUrl, 'analytics.salt' => generate_random_salt(64), - 'admin.gateway' => $validData['admin_gateway'], - 'auth.gateway' => $validData['auth_gateway'], + 'admin.gateway' => $this->request->getPost('admin_gateway'), + 'auth.gateway' => $this->request->getPost('auth_gateway'), ]); helper('text'); @@ -180,16 +183,16 @@ class InstallController extends Controller return redirect()->to(reduce_double_slashes($baseUrl . '/' . config('Install')->gateway)); } - public function databaseConfigView(): string + public function databaseConfig(): string { return view('database_config'); } - public function databaseConfigAction(): RedirectResponse + public function attemptDatabaseConfig(): RedirectResponse { $rules = [ 'db_hostname' => 'required', - 'db_name' => 'required', + 'db_name' => 'required', 'db_username' => 'required', 'db_password' => 'required', ]; @@ -201,25 +204,23 @@ class InstallController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - self::writeEnv([ - 'database.default.hostname' => $validData['db_hostname'], - 'database.default.database' => $validData['db_name'], - 'database.default.username' => $validData['db_username'], - 'database.default.password' => $validData['db_password'], + 'database.default.hostname' => $this->request->getPost('db_hostname'), + 'database.default.database' => $this->request->getPost('db_name'), + 'database.default.username' => $this->request->getPost('db_username'), + 'database.default.password' => $this->request->getPost('db_password'), 'database.default.DBPrefix' => $this->request->getPost('db_prefix'), ]); return redirect()->back(); } - public function cacheConfigView(): string + public function cacheConfig(): string { return view('cache_config'); } - public function cacheConfigAction(): RedirectResponse + public function attemptCacheConfig(): RedirectResponse { $rules = [ 'cache_handler' => 'required', @@ -232,10 +233,8 @@ class InstallController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - self::writeEnv([ - 'cache.handler' => $validData['cache_handler'], + 'cache.handler' => $this->request->getPost('cache_handler'), ]); return redirect()->back(); @@ -246,9 +245,23 @@ class InstallController extends Controller */ public function migrate(): void { - $migrate = service('migrations'); + $migrations = Services::migrations(); - $migrate->setNamespace(null) + $migrations->setNamespace('CodeIgniter\Settings') + ->latest(); + $migrations->setNamespace('Myth\Auth') + ->latest(); + $migrations->setNamespace('Modules\Fediverse') + ->latest(); + $migrations->setNamespace(APP_NAMESPACE) + ->latest(); + $migrations->setNamespace('Modules\WebSub') + ->latest(); + $migrations->setNamespace('Modules\Auth') + ->latest(); + $migrations->setNamespace('Modules\PremiumPodcasts') + ->latest(); + $migrations->setNamespace('Modules\Analytics') ->latest(); } @@ -266,7 +279,7 @@ class InstallController extends Controller /** * Returns the form to create a the first superadmin user for the instance. */ - public function createSuperAdminView(): string + public function createSuperAdmin(): string { return view('create_superadmin'); } @@ -276,14 +289,21 @@ class InstallController extends Controller * * After creation, user is redirected to login page to input its credentials. */ - public function createSuperAdminAction(): RedirectResponse + public function attemptCreateSuperAdmin(): RedirectResponse { - // validate user password - $rules = [ - 'username' => 'required', - 'email' => 'required', - 'password' => 'required|strong_password', - ]; + $userModel = new UserModel(); + + // Validate here first, since some things, + // like the password, can only be validated properly here. + $rules = array_merge( + $userModel->getValidationRules([ + 'only' => ['username'], + ]), + [ + 'email' => 'required|valid_email|is_unique[users.email]', + 'password' => 'required|strong_password', + ], + ); if (! $this->validate($rules)) { return redirect() @@ -292,29 +312,29 @@ class InstallController extends Controller ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - // Save the user - $user = new User([ - 'username' => $validData['username'], - 'email' => $validData['email'], - 'password' => $validData['password'], - 'is_owner' => true, - ]); + $user = new User($this->request->getPost()); - $userModel = new UserModel(); - try { - $userModel->save($user); - } catch (ShieldValidationException) { - return redirect()->back() + // Activate user + $user->activate(); + + $db = db_connect(); + + $db->transStart(); + if (! ($userId = $userModel->insert($user, true))) { + $db->transRollback(); + + return redirect() + ->back() ->withInput() ->with('errors', $userModel->errors()); } - $user = $userModel->findById($userModel->getInsertID()); + // add newly created user to superadmin group + $authorization = Services::authorization(); + $authorization->addUserToGroup($userId, 'superadmin'); - // set newly created user as most powerful instance group (superadmin) - $user->addGroup(setting('AuthGroups.mostPowerfulGroup')); + $db->transComplete(); // Success! // set redirect_url session as admin area to go to after login @@ -322,7 +342,7 @@ class InstallController extends Controller ->set('redirect_url', route_to('admin')); return redirect() - ->route('admin') + ->route('login') ->with('message', lang('Install.messages.createSuperAdminSuccess')); } @@ -347,7 +367,7 @@ class InstallController extends Controller return $line; }, - $envData, + $envData ); if (! $replaced) { diff --git a/modules/Install/Language/.rsync-filter b/modules/Install/Language/.rsync-filter index b802a93d..2a742b26 100644 --- a/modules/Install/Language/.rsync-filter +++ b/modules/Install/Language/.rsync-filter @@ -2,11 +2,9 @@ + fr/*** + pl/*** + de/*** -+ pt-br/*** -+ nn-no/*** ++ pt-BR/*** ++ nn-NO/*** + es/*** -+ zh-hans/*** ++ zh-Hans/*** + ca/*** -+ br/*** -+ sr-latn/*** - ** diff --git a/modules/Install/Language/br/Install.php b/modules/Install/Language/br/Install.php index c29b77e2..926c45f9 100644 --- a/modules/Install/Language/br/Install.php +++ b/modules/Install/Language/br/Install.php @@ -9,10 +9,10 @@ declare(strict_types=1); */ return [ - 'title' => 'Stalier Castopod', + 'title' => 'Castopod installer', 'manual_config' => 'Kefluniañ dre zorn', 'manual_config_subtitle' => - 'Krouit ur restr `.env` gant hoc’h arventennoù ha nevesait ar bajenn evit kenderc\'hel gant ar staliañ.', + 'Krouit ur restr `.env` gant hoc’h arventennoù ha hizivait ar bajenn evit kenderc\'hel gant ar staliañ.', 'form' => [ 'instance_config' => 'Arventennoù an istañs', 'hostname' => 'Anv an ostiz', diff --git a/modules/Install/Language/da/Install.php b/modules/Install/Language/da/Install.php deleted file mode 100644 index 16bbbd54..00000000 --- a/modules/Install/Language/da/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installationsprogram', - 'manual_config' => 'Manuel konfiguration', - 'manual_config_subtitle' => - 'Opret en `.env` fil med dine indstillinger og opdater siden for at fortsætte installationen.', - 'form' => [ - 'instance_config' => 'Instanskonfiguration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Medie base URL', - 'media_base_url_hint' => - 'Hvis du bruger en CDN og/eller en ekstern analysetjeneste, kan du indstille dem her.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod skal oprette forbindelse til din MySQL (eller MariaDB) database. Hvis du ikke har disse nødvendige oplysninger, bedes du kontakte din serveradministrator.', - 'db_hostname' => 'Database host navn', - 'db_name' => 'Databasenavn', - 'db_username' => 'Database brugernavn', - 'db_password' => 'Database adgangskode', - 'db_prefix' => 'Database præfiks', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Næste', - 'submit' => 'Afslut installation', - 'create_superadmin' => 'Opret din Super Admin konto', - 'email' => 'Email', - 'username' => 'Brugernavn', - 'password' => 'Adgangskode', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Din superadmin konto er blevet oprettet. Log ind for at starte podcasting!', - 'databaseConnectError' => - 'Castopod kunne ikke oprette forbindelse til din database. Rediger din database konfiguration og prøv igen.', - 'writeError' => - "Kunne ikke oprette/skrive `.env` filen. Du skal oprette den manuelt ved at følge `.env.example` filskabelon i Castopod-pakken.", - ], -]; diff --git a/modules/Install/Language/de/Install.php b/modules/Install/Language/de/Install.php index ecebbfa7..b3269fdb 100644 --- a/modules/Install/Language/de/Install.php +++ b/modules/Install/Language/de/Install.php @@ -21,10 +21,10 @@ return [ 'Wenn du einen CDN und/oder einen externen Analysedienst verwendest, kannst du diesen hier festlegen.', 'admin_gateway' => 'Admin-Gateway', 'admin_gateway_hint' => - 'Der Pfad zum Zugriff auf den Admin-Bereich (z.B. https://example.com/cp-admin), wird standardmäßig als "cp-admin" festgelegt. Wir empfehlen, sie aus Sicherheitsgründen zu ändern.', + 'Die Route zum Zugriff auf den Admin-Bereich (z.B. https://example.com/cp-admin), wird standardmäßig als "cp-admin" festgelegt. Wir empfehlen, sie aus Sicherheitsgründen zu ändern.', 'auth_gateway' => 'Auth-Gateway', 'auth_gateway_hint' => - 'Der Pfad zum Zugriff auf die Authentifizierungsseiten (z. B. https://example.com/cp-auth), wird standardmäßig als "cp-auth" gesetzt. Wir empfehlen, sie aus Sicherheitsgründen zu ändern.', + 'Die Route zum Zugriff auf die Authentifizierungsseiten (z. B. https://example.com/cp-auth), wird standardmäßig als "cp-auth" gesetzt. Wir empfehlen, sie aus Sicherheitsgründen zu ändern.', 'database_config' => 'Datenbankkonfiguration', 'database_config_hint' => 'Castopod muss sich mit der MySQL-Datenbank (oder MariaDB) verbinden. Wenn diese erforderlichen Informationen nicht verfügbar sind, wende dich bitte an deinen Serveradministrator.', diff --git a/modules/Install/Language/en/Install.php b/modules/Install/Language/en/Install.php index 45d26085..1f66ef11 100644 --- a/modules/Install/Language/en/Install.php +++ b/modules/Install/Language/en/Install.php @@ -46,7 +46,7 @@ return [ ], 'next' => 'Next', 'submit' => 'Finish install', - 'create_superadmin' => 'Create your Super Admin account', + 'create_superadmin' => 'Create your superadmin account', 'email' => 'Email', 'username' => 'Username', 'password' => 'Password', diff --git a/modules/Install/Language/eu/Install.php b/modules/Install/Language/eu/Install.php deleted file mode 100644 index 45d26085..00000000 --- a/modules/Install/Language/eu/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installer', - 'manual_config' => 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your Super Admin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Install/Language/fa/Install.php b/modules/Install/Language/fa/Install.php index 0164c3f8..1f66ef11 100644 --- a/modules/Install/Language/fa/Install.php +++ b/modules/Install/Language/fa/Install.php @@ -9,13 +9,13 @@ declare(strict_types=1); */ return [ - 'title' => 'نصب کنندهٔ کستوپاد', - 'manual_config' => 'پیکربندی دستی', + 'title' => 'Castopod installer', + 'manual_config' => 'Manual configuration', 'manual_config_subtitle' => 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ - 'instance_config' => 'پیکربندی نمونه', - 'hostname' => 'نام میزبان', + 'instance_config' => 'Instance configuration', + 'hostname' => 'Hostname', 'media_base_url' => 'Media base URL', 'media_base_url_hint' => 'If you use a CDN and/or an external analytics service, you may set them here.', @@ -28,28 +28,28 @@ return [ 'database_config' => 'Database configuration', 'database_config_hint' => 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'نام میزبان پایگاه داده', - 'db_name' => 'نام پایگاه‌داده', - 'db_username' => 'نام کاربری پایگاه‌داده', - 'db_password' => 'گذرواژهٔ پایگاه‌داده', - 'db_prefix' => 'پيشوند پايگاه‌داده', + 'db_hostname' => 'Database hostname', + 'db_name' => 'Database name', + 'db_username' => 'Database username', + 'db_password' => 'Database password', + 'db_prefix' => 'Database prefix', 'db_prefix_hint' => "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'پیکربندی انباره', + 'cache_config' => 'Cache configuration', 'cache_config_hint' => 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', 'cache_handler' => 'Cache handler', 'cacheHandlerOptions' => [ - 'file' => 'پرونده', - 'redis' => 'ردیس', + 'file' => 'File', + 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'بعدی', - 'submit' => 'پایان نصب', - 'create_superadmin' => 'ایجاد ابرحساب مدیریتان', - 'email' => 'رایانامه', - 'username' => 'نام‌کاربری', - 'password' => 'گذرواژه', + 'next' => 'Next', + 'submit' => 'Finish install', + 'create_superadmin' => 'Create your superadmin account', + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', ], 'messages' => [ 'createSuperAdminSuccess' => diff --git a/modules/Install/Language/fr-ca/Install.php b/modules/Install/Language/fr-ca/Install.php deleted file mode 100644 index 45d26085..00000000 --- a/modules/Install/Language/fr-ca/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installer', - 'manual_config' => 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your Super Admin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Install/Language/fr2/Install.php b/modules/Install/Language/fr2/Install.php deleted file mode 100644 index 45d26085..00000000 --- a/modules/Install/Language/fr2/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installer', - 'manual_config' => 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your Super Admin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Install/Language/gd/Install.php b/modules/Install/Language/gd/Install.php index 2c39010f..1f66ef11 100644 --- a/modules/Install/Language/gd/Install.php +++ b/modules/Install/Language/gd/Install.php @@ -9,54 +9,54 @@ declare(strict_types=1); */ return [ - 'title' => 'Inneal-stàlaidh Chastopod', - 'manual_config' => 'Rèiteachadh a làimh', + 'title' => 'Castopod installer', + 'manual_config' => 'Manual configuration', 'manual_config_subtitle' => - 'Cruthaich faidhle `.env` leis na roghainnean agad agus ath-nuadhaich an duilleag a leantainn air adhart leis an stàladh.', + 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ - 'instance_config' => 'Rèiteachadh an ionstans', - 'hostname' => 'Ainm an òstair', - 'media_base_url' => 'URL bunaiteach nam meadhanan', + 'instance_config' => 'Instance configuration', + 'hostname' => 'Hostname', + 'media_base_url' => 'Media base URL', 'media_base_url_hint' => - 'Ma tha thu a’ cleachdadh CDN agus/no seirbheis anailiseachd air an taobh a-muigh, faodaidh tu an suidheachadh an-seo.', - 'admin_gateway' => 'Balach na rianachd', + 'If you use a CDN and/or an external analytics service, you may set them here.', + 'admin_gateway' => 'Admin gateway', 'admin_gateway_hint' => - 'Seo an t-slighe airson raon na rianachd inntrigeadh (m.e. https://ball-eisimpleir.com/cp-admin). Thèid seo a shuidheachadh air cp-admin a ghnàth ach mholamaid gun atharraich thu seo air adhbhar tèarainteachd.', - 'auth_gateway' => 'Bealach an dearbhaidh', + 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', + 'auth_gateway' => 'Auth gateway', 'auth_gateway_hint' => - 'Seo an t-slighe airson duilleagan an dearbhaidh inntrigeadh (m.e. https://ball-eisimpleir.com/cp-auth). Thèid seo a shuidheachadh air cp-auth a ghnàth ach mholamaid gun atharraich thu seo air adhbhar tèarainteachd.', - 'database_config' => 'Rèiteachadh an stòir-dhàta', + 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', + 'database_config' => 'Database configuration', 'database_config_hint' => - 'Feumaidh Castopod ceangal ris an stòr-dàta MySQL (no MariaDB) agad. Mur eil am fiosrachadh riatanach seo agad, cuir fios tu rianaire an fhrithealaiche agad.', - 'db_hostname' => 'Ainm òstair an stòir-dhàta', - 'db_name' => 'Ainm an stòir-dhàta', - 'db_username' => 'Ainm-cleachdaiche an stòir-dhàta', - 'db_password' => 'Facal-faire an stòir-dhàta', - 'db_prefix' => 'Ro-leasachan an stòir-dhàta', + 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', + 'db_hostname' => 'Database hostname', + 'db_name' => 'Database name', + 'db_username' => 'Database username', + 'db_password' => 'Database password', + 'db_prefix' => 'Database prefix', 'db_prefix_hint' => - "Seo ro-leasachan do dh’ainmean clàran Chastopod, fàg e mar a tha e mur eil thu a’ tuigsinn dè as ciall dha.", - 'cache_config' => 'Rèiteachadh an tasgadain', + "The prefix of the Castopod table names, leave as is if you don't know what it means.", + 'cache_config' => 'Cache configuration', 'cache_config_hint' => - 'Tagh an làimhsichear as fheàrr leat dhan tasgadan. Fàg air an luach bhunaiteach e mur eil thu a’ tuigsinn dè as ciall dha.', - 'cache_handler' => 'Làimhsichear an tasgadain', + 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', + 'cache_handler' => 'Cache handler', 'cacheHandlerOptions' => [ - 'file' => 'Faidhle', + 'file' => 'File', 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'Air adhart', - 'submit' => 'Cuir crìoch air an stàladh', - 'create_superadmin' => 'Cruthaich an cunntas sàr-rianaire agad', - 'email' => 'Post-d', - 'username' => 'Ainm-cleachdaiche', - 'password' => 'Facal-faire', + 'next' => 'Next', + 'submit' => 'Finish install', + 'create_superadmin' => 'Create your superadmin account', + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', ], 'messages' => [ 'createSuperAdminSuccess' => - 'Chaidh an cunntas sàr-rianaire agad a chruthachadh. Clàraich a-steach a thòiseachadh leis a’ phod-chraoladh!', + 'Your superadmin account has been created successfully. Login to start podcasting!', 'databaseConnectError' => - 'Cha b’ urrainn do Chastopod ceangal ris an stòr-dàta agad. Deasaich rèiteachadh an stòir-dhàta agad is feuch ris a-rithist.', + 'Castopod could not connect to your database. Edit your database configuration and try again.', 'writeError' => - "Cha b’ urrainn dhuinn am faidhle `.env` a chruthachadh/sgrìobhadh thuige. Feumaidh tu a chruthachadh a làimh a leantainn ris an fhaidhle-teamplaid `.env.example` sa phacaid Castopod.", + "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", ], ]; diff --git a/modules/Install/Language/ja/Install.php b/modules/Install/Language/ja/Install.php deleted file mode 100644 index 45d26085..00000000 --- a/modules/Install/Language/ja/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installer', - 'manual_config' => 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your Super Admin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Install/Language/kk/Install.php b/modules/Install/Language/kk/Install.php deleted file mode 100644 index 45d26085..00000000 --- a/modules/Install/Language/kk/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installer', - 'manual_config' => 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your Super Admin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Install/Language/ko/Install.php b/modules/Install/Language/ko/Install.php deleted file mode 100644 index 1f66ef11..00000000 --- a/modules/Install/Language/ko/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installer', - 'manual_config' => 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Install/Language/nl/Install.php b/modules/Install/Language/nl/Install.php index e5cc6d4a..1f66ef11 100644 --- a/modules/Install/Language/nl/Install.php +++ b/modules/Install/Language/nl/Install.php @@ -9,54 +9,54 @@ declare(strict_types=1); */ return [ - 'title' => 'Castopod installatie', - 'manual_config' => 'Handmatige configuratie', + 'title' => 'Castopod installer', + 'manual_config' => 'Manual configuration', 'manual_config_subtitle' => - 'Maak een `.env` bestand aan met je instellingen en vernieuw de pagina om door te gaan met de installatie.', + 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ - 'instance_config' => 'Instantie configuratie', - 'hostname' => 'Hostnaam', - 'media_base_url' => 'Media basis-URL', + 'instance_config' => 'Instance configuration', + 'hostname' => 'Hostname', + 'media_base_url' => 'Media base URL', 'media_base_url_hint' => - 'Als u een CDN en/of een externe statistiekenservice gebruikt, kunt u ze hier instellen.', - 'admin_gateway' => 'Admin pad', + 'If you use a CDN and/or an external analytics service, you may set them here.', + 'admin_gateway' => 'Admin gateway', 'admin_gateway_hint' => - 'De route naar toegang tot de admin omgeving (bijv. https://example.com/cp-admin). Het is standaard ingesteld als cp-admin, we raden je aan om het te wijzigen om veiligheidsredenen.', - 'auth_gateway' => 'Authenticatie pad', + 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', + 'auth_gateway' => 'Auth gateway', 'auth_gateway_hint' => - 'De route voor toegang tot de authenticatiepagina\'s (bijv. https://example.com/cp-auth). Deze is standaard ingesteld als cp-auth, wij raden u aan deze om veiligheidsredenen te wijzigen.', - 'database_config' => 'Databaseconfiguratie', + 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', + 'database_config' => 'Database configuration', 'database_config_hint' => - 'Castopod moet verbinding maken met uw MySQL (of MariaDB) database. Als u niet over de benodigde informatie beschikt, neem dan contact op met uw serverbeheerder.', - 'db_hostname' => 'Database hostnaam', - 'db_name' => 'Databasenaam', - 'db_username' => 'Database gebruikersnaam', - 'db_password' => 'Database wachtwoord', - 'db_prefix' => 'Database voorvoegsel', + 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', + 'db_hostname' => 'Database hostname', + 'db_name' => 'Database name', + 'db_username' => 'Database username', + 'db_password' => 'Database password', + 'db_prefix' => 'Database prefix', 'db_prefix_hint' => - "Het voorvoegsel van de Castopod tabelnamen. Laat leeg indien je niet weet wat dit betekent.", - 'cache_config' => 'Cache-configuratie', + "The prefix of the Castopod table names, leave as is if you don't know what it means.", + 'cache_config' => 'Cache configuration', 'cache_config_hint' => - 'Kies je gewenste cache-handler. Laat deze standaard waarde achter als je geen idee hebt wat het betekent.', + 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', 'cache_handler' => 'Cache handler', 'cacheHandlerOptions' => [ - 'file' => 'Bestandsysteem', + 'file' => 'File', 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'Volgende', - 'submit' => 'Installatie voltooien', - 'create_superadmin' => 'Maak uw Super Admin account aan', - 'email' => 'E-mail', - 'username' => 'Gebruikersnaam', - 'password' => 'Wachtwoord', + 'next' => 'Next', + 'submit' => 'Finish install', + 'create_superadmin' => 'Create your superadmin account', + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', ], 'messages' => [ 'createSuperAdminSuccess' => - 'Uw superadmin account is aangemaakt. Log in om met podcasten te starten!', + 'Your superadmin account has been created successfully. Login to start podcasting!', 'databaseConnectError' => - 'Castopod kon geen verbinding maken met uw database. Bewerk uw databaseconfiguratie en probeer het opnieuw.', + 'Castopod could not connect to your database. Edit your database configuration and try again.', 'writeError' => - "Kon het `.env` bestand niet maken/schrijven. Je moet het handmatig aanmaken door het meegeleverde voorbeeld `.env.example` bestand te kopiëren en aan te passen.", + "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", ], ]; diff --git a/modules/Install/Language/nn-no/Install.php b/modules/Install/Language/nn-NO/Install.php similarity index 100% rename from modules/Install/Language/nn-no/Install.php rename to modules/Install/Language/nn-NO/Install.php diff --git a/modules/Install/Language/pl/Install.php b/modules/Install/Language/pl/Install.php index aa214368..f08df622 100644 --- a/modules/Install/Language/pl/Install.php +++ b/modules/Install/Language/pl/Install.php @@ -16,15 +16,15 @@ return [ 'form' => [ 'instance_config' => 'Konfiguracja instancji', 'hostname' => 'Nazwa hosta', - 'media_base_url' => 'Bazowy URL mediów', + 'media_base_url' => 'Bazowy URL multimediów', 'media_base_url_hint' => - 'Jeśli korzystasz z CDNa i/lub zewnętrznej usługi analitycznej, możesz ustawić je tutaj.', - 'admin_gateway' => 'Strona administracyjna', + 'Jeśli korzystasz z CDN i/lub zewnętrznej usługi analitycznej, możesz ustawić je tutaj.', + 'admin_gateway' => 'Brama administracyjna', 'admin_gateway_hint' => - 'Dostęp do obszaru administracyjnego (np. https://example.com/cp-admin). Domyślnie jest ustawiony jako cp-admin, ale ze względów bezpieczeństwa zalecamy zmianę tej nazwy.', - 'auth_gateway' => 'Strona uwierzytelniania', + 'Droga dostępu do obszaru administracyjnego (np. https://example.com/cp-admin). Domyślnie jest ustawiona jako cp-admin, ze względów bezpieczeństwa zalecamy jej zmianę.', + 'auth_gateway' => 'Brama uwierzytelniania', 'auth_gateway_hint' => - 'Dostęp do stron uwierzytelniających (np. https://example.com/cp-auth). Domyślnie jest ustawiony jako cp-auth, ale ze względów bezpieczeństwa zalecamy zmianę tej nazwy.', + 'Droga dostępu do stron uwierzytelniających (np. https://example.com/cp-auth). Domyślnie jest ustawiona jako cp-auth, ze względów bezpieczeństwa zalecamy jej zmianę.', 'database_config' => 'Konfiguracja bazy danych', 'database_config_hint' => 'Castopod musi połączyć się z bazą danych MySQL (lub MariaDB). Jeśli nie masz tych wymaganych informacji, skontaktuj się z administratorem serwera.', @@ -34,11 +34,11 @@ return [ 'db_password' => 'Hasło bazy danych', 'db_prefix' => 'Prefiks bazy danych', 'db_prefix_hint' => - "Prefiks nazw tabel Castopod — pozostaw bez zmian, jeśli nie wiesz, co to znaczy.", + "Przedrostek nazw tabel Castopod; pozostaw bez zmian jeśli nie wiesz, co to znaczy.", 'cache_config' => 'Konfiguracja pamięci podręcznej', 'cache_config_hint' => - 'Wybierz preferowany mechanizm pamięci podręcznej. Zostaw domyślną wartość, jeśli nie masz pojęcia, co to znaczy.', - 'cache_handler' => 'Mechanizm pamięci podręcznej', + 'Wybierz preferowaną obsługę pamięci podręcznej (cache). Pozostaw to jako wartość domyślną, jeśli nie masz pojęcia, co to znaczy.', + 'cache_handler' => 'Obsługa pamięci podręcznej', 'cacheHandlerOptions' => [ 'file' => 'Plik', 'redis' => 'Redis', @@ -55,8 +55,8 @@ return [ 'createSuperAdminSuccess' => 'Twoje konto superadministratora zostało pomyślnie utworzone. Zaloguj się, aby rozpocząć podcastowanie!', 'databaseConnectError' => - 'Castopod nie mógł się połączyć z Twoją bazą danych. Edytuj konfigurację bazy danych i spróbuj ponownie.', + 'Castopod nie mógł połączyć się z Twoją bazą danych. Edytuj konfigurację bazy danych i spróbuj ponownie.', 'writeError' => - "Nie można utworzyć/zapisać pliku `.env`. Musisz go utworzyć ręcznie, postępując zgodnie z szablonem `.env.example` w pakiecie Castopod.", + "Nie można utworzyć/zapisać pliku `.env`. Musisz go utworzyć ręcznie postępując zgodnie z szablonem pliku `.env.example` w pakiecie Castopod.", ], ]; diff --git a/modules/Install/Language/pt-br/Install.php b/modules/Install/Language/pt-BR/Install.php similarity index 100% rename from modules/Install/Language/pt-br/Install.php rename to modules/Install/Language/pt-BR/Install.php diff --git a/modules/Install/Language/ro/Install.php b/modules/Install/Language/ro/Install.php deleted file mode 100644 index 45d26085..00000000 --- a/modules/Install/Language/ro/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installer', - 'manual_config' => 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your Super Admin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Install/Language/sk/Install.php b/modules/Install/Language/sk/Install.php index d6eaaf2d..1f66ef11 100644 --- a/modules/Install/Language/sk/Install.php +++ b/modules/Install/Language/sk/Install.php @@ -25,14 +25,14 @@ return [ 'auth_gateway' => 'Auth gateway', 'auth_gateway_hint' => 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Nastavenie databázy', + 'database_config' => 'Database configuration', 'database_config_hint' => 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', 'db_hostname' => 'Database hostname', - 'db_name' => 'Názov databázy', - 'db_username' => 'Prihlasovacie meno do databázy', - 'db_password' => 'Heslo k databáze', - 'db_prefix' => 'Prefix databázy', + 'db_name' => 'Database name', + 'db_username' => 'Database username', + 'db_password' => 'Database password', + 'db_prefix' => 'Database prefix', 'db_prefix_hint' => "The prefix of the Castopod table names, leave as is if you don't know what it means.", 'cache_config' => 'Cache configuration', @@ -44,18 +44,18 @@ return [ 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'Ďalej', - 'submit' => 'Dokončiť inštaláciu', + 'next' => 'Next', + 'submit' => 'Finish install', 'create_superadmin' => 'Create your superadmin account', 'email' => 'Email', - 'username' => 'Používateľské meno', - 'password' => 'Heslo', + 'username' => 'Username', + 'password' => 'Password', ], 'messages' => [ 'createSuperAdminSuccess' => 'Your superadmin account has been created successfully. Login to start podcasting!', 'databaseConnectError' => - 'Castopod sa nemohol pripojiť k vašej databáze. Upravte konfiguráciu svojej databázy a skúste to znovu.', + 'Castopod could not connect to your database. Edit your database configuration and try again.', 'writeError' => "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", ], diff --git a/modules/Install/Language/sr-latn/Install.php b/modules/Install/Language/sr-latn/Install.php deleted file mode 100644 index d12ba554..00000000 --- a/modules/Install/Language/sr-latn/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Instalator Castopoda', - 'manual_config' => 'Ručna konfiguracija', - 'manual_config_subtitle' => - 'Napravite `.env` datoteku sa vašim podešavanjima i osvežite stranicu da bi ste nastavili instalaciju.', - 'form' => [ - 'instance_config' => 'Konfiguracija instance', - 'hostname' => 'Ime domaćina', - 'media_base_url' => 'URL medijske baze', - 'media_base_url_hint' => - 'Ako koristite CDN i/ili eksternu uslugu za analitiku, možete ih postaviti ovde.', - 'admin_gateway' => 'Administratorski izlaz', - 'admin_gateway_hint' => - 'Ruta za pristup kontrolnoj tabli administratora (eg. https://example.com/cp-admin).Podrazumevano je podešena na cp-admin, preporučujemo da je promenite iz sigurnosnih razloga.', - 'auth_gateway' => 'Auth izlaz', - 'auth_gateway_hint' => - 'Ruta za pristup stranicama za potvrdu identiteta (eg. https://example.com/cp-auth).Podrazumevano je podešena na cp-auth, preporučujemo da je promenite iz sigurnosnih razloga.', - 'database_config' => 'Konfiguracija baze podataka', - 'database_config_hint' => - 'Castopod mora da se poveže za vašom MySQL (ili MariaDB) bazom. Ukoliko ne posedujete potrebne informacije, molimo vas kontaktirajte administratora vašeg servera.', - 'db_hostname' => 'Ime hosta baze podataka', - 'db_name' => 'Ime baze podataka', - 'db_username' => 'Korisničko ime baze podataka', - 'db_password' => 'Lozinka baze podataka', - 'db_prefix' => 'Prefiks baze', - 'db_prefix_hint' => - "Prefiks imena tabela Castopod-a, ne diraj ako ne znaš šta znači.", - 'cache_config' => 'Konfiguracija keša', - 'cache_config_hint' => - 'Izaberite željeni obrađivač keša. Ostavite je kao podrazumevanu vrednost ako nemate pojma šta to znači.', - 'cache_handler' => 'Obrađivač keša', - 'cacheHandlerOptions' => [ - 'file' => 'Datoteka', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Sledeće', - 'submit' => 'Završi instalaciju', - 'create_superadmin' => 'Kreiraj svoj nalog super administratora', - 'email' => 'E-pošta', - 'username' => 'Korisničko ime', - 'password' => 'Lozinka', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Vaš nalog superadmina je uspešno kreiran. Prijavite se da biste započeli podkasting!', - 'databaseConnectError' => - 'Castopod nije mogao da se poveže sa vašom bazom podataka. Uredite konfiguraciju baze podataka i pokušajte ponovo.', - 'writeError' => - "Nije moguće kreirati/upisati datoteku `.env`. Morate je kreirati ručno prateći šablon datoteke `.env.example` u Castopod-ovom paketu.", - ], -]; diff --git a/modules/Install/Language/sv/Install.php b/modules/Install/Language/sv/Install.php index f2bc70b5..1f66ef11 100644 --- a/modules/Install/Language/sv/Install.php +++ b/modules/Install/Language/sv/Install.php @@ -9,54 +9,54 @@ declare(strict_types=1); */ return [ - 'title' => 'Installationsprogrammet för Castopod', - 'manual_config' => 'Manuell konfiguration', + 'title' => 'Castopod installer', + 'manual_config' => 'Manual configuration', 'manual_config_subtitle' => - 'Skapa en \'.env\' fil med dina inställningar och uppdatera sidan för att fortsätta installationen.', + 'Create a `.env` file with your settings and refresh the page to continue installation.', 'form' => [ - 'instance_config' => 'Konfiguration av instans', - 'hostname' => 'Servernamn', - 'media_base_url' => 'Bas-URL för media', + 'instance_config' => 'Instance configuration', + 'hostname' => 'Hostname', + 'media_base_url' => 'Media base URL', 'media_base_url_hint' => - 'Om du använder en CDN och/eller en extern analystjänst kan du ställa in dem här.', + 'If you use a CDN and/or an external analytics service, you may set them here.', 'admin_gateway' => 'Admin gateway', 'admin_gateway_hint' => - 'Rutten för att komma åt adminområdet (t.ex. https://example.com/cp-admin). Det är som standard inställt som cp-admin, vi rekommenderar att du ändrar det av säkerhetsskäl.', + 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', 'auth_gateway' => 'Auth gateway', 'auth_gateway_hint' => - 'Rutten för att komma åt autentiseringssidorna (t.ex. https://example.com/cp-auth). Den är som standard inställd som cp-auth, vi rekommenderar att du ändrar den av säkerhetsskäl.', - 'database_config' => 'Databas konfiguration', + 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', + 'database_config' => 'Database configuration', 'database_config_hint' => - 'Castopod måste ansluta till din MySQL (eller MariaDB) databas. Om du inte har dessa nödvändiga uppgifter, kontakta din serveradministratör.', - 'db_hostname' => 'Databasens värdnamn', - 'db_name' => 'Databasnamn', - 'db_username' => 'Användarnamn till databasen', - 'db_password' => 'Databasens lösenord', - 'db_prefix' => 'Databas prefix', + 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', + 'db_hostname' => 'Database hostname', + 'db_name' => 'Database name', + 'db_username' => 'Database username', + 'db_password' => 'Database password', + 'db_prefix' => 'Database prefix', 'db_prefix_hint' => - "Prefixet för Castopod tabellnamn, lämna som om du inte vet vad det betyder.", - 'cache_config' => 'Cache-konfiguration', + "The prefix of the Castopod table names, leave as is if you don't know what it means.", + 'cache_config' => 'Cache configuration', 'cache_config_hint' => - 'Välj önskad cachehanterare. Lämna det som standardvärde om du inte har någon aning om vad det innebär.', + 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', 'cache_handler' => 'Cache handler', 'cacheHandlerOptions' => [ - 'file' => 'Fil', + 'file' => 'File', 'redis' => 'Redis', 'predis' => 'Predis', ], - 'next' => 'Nästa', - 'submit' => 'Slutför installationen', + 'next' => 'Next', + 'submit' => 'Finish install', 'create_superadmin' => 'Create your superadmin account', - 'email' => 'Epost', - 'username' => 'Användarnamn', - 'password' => 'Lösenord', + 'email' => 'Email', + 'username' => 'Username', + 'password' => 'Password', ], 'messages' => [ 'createSuperAdminSuccess' => - 'Ditt superadministratörskonto har skapats. Logga in för att starta podcasting!', + 'Your superadmin account has been created successfully. Login to start podcasting!', 'databaseConnectError' => - 'Castopod kunde inte ansluta till din databas. Redigera din databaskonfiguration och försök igen.', + 'Castopod could not connect to your database. Edit your database configuration and try again.', 'writeError' => - "Kunde inte skapa/skriva `.env`-filen. Du måste skapa den manuellt genom att följa filmallen `.env.exempel` i Castopod-paketet.", + "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", ], ]; diff --git a/modules/Install/Language/uk/Install.php b/modules/Install/Language/uk/Install.php deleted file mode 100644 index a06569bb..00000000 --- a/modules/Install/Language/uk/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Кастопод інсталятор', - 'manual_config' => 'Ручне налаштування', - 'manual_config_subtitle' => - 'Створіть файл `.env` з налаштуваннями та перезавантажте сторінку, щоб продовжити встановлення.', - 'form' => [ - 'instance_config' => 'Конфігурація екземпляру', - 'hostname' => 'Ім\'я хоста', - 'media_base_url' => 'URL-адреса бази даних медіа', - 'media_base_url_hint' => - 'Якщо ви використовуєте CDN та/або зовнішній аналітичний сервіс, ви можете встановити їх тут.', - 'admin_gateway' => 'Шлюз Адміністратора', - 'admin_gateway_hint' => - 'Шлях до сторінки аутентифікації (наприклад https://example.com/cp-admin). Встановлений за замовчуванням cp-auth, Ми рекомендуємо вам змінити його з міркувань безпеки.', - 'auth_gateway' => 'Шлюз авторизації', - 'auth_gateway_hint' => - 'Шлях до сторінки аутентифікації (наприклад https://example.com/cp-auth). Встановлений за замовчуванням cp-auth, Ми рекомендуємо вам змінити його з міркувань безпеки.', - 'database_config' => 'Налаштування бази даних', - 'database_config_hint' => - 'Кастопод потребує підключення до бази даних MySQL (або MariaDB) для відновлення. Якщо у вас немає такої необхідної інформації, будь ласка, зверніться до адміністратора вашого сервера.', - 'db_hostname' => 'Ім\'я хоста бази даних', - 'db_name' => 'Назва бази даних', - 'db_username' => 'Ім\'я користувача бази даних', - 'db_password' => 'Пароль бази даних', - 'db_prefix' => 'Префікс бази даних', - 'db_prefix_hint' => - "Залишайте префікс імен таблиць Castopod, якщо ви не знаєте що це значить.", - 'cache_config' => 'Конфігурація кешу', - 'cache_config_hint' => - 'Виберіть бажаний обробник кешу або залиште без змін, як стандартне значення, якщо ви не знаєте, що це означає.', - 'cache_handler' => 'Обробник кешу', - 'cacheHandlerOptions' => [ - 'file' => 'Файл', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Далі', - 'submit' => 'Завершити установку', - 'create_superadmin' => 'Створіть свій обліковий запис головного адміністратора', - 'email' => 'Пошта', - 'username' => 'Ім\'я користувача', - 'password' => 'Пароль', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Ваш обліковий запис головного адміністратора було успішно створено. Увійдіть, щоб почати подкасти!', - 'databaseConnectError' => - 'Castopod не зміг під\'єднатися до вашої бази даних. Перевірте конфігурацію бази даних і повторіть спробу.', - 'writeError' => - "Не вдалося створити/записати файл `.env`. Ви повинні створити його вручну, перейшовши шаблон файлу `.env.example` в пакеті Castopode.", - ], -]; diff --git a/modules/Install/Language/zh-hans/Install.php b/modules/Install/Language/zh-Hans/Install.php similarity index 100% rename from modules/Install/Language/zh-hans/Install.php rename to modules/Install/Language/zh-Hans/Install.php diff --git a/modules/Install/Language/zh-hant/Install.php b/modules/Install/Language/zh-hant/Install.php deleted file mode 100644 index 45d26085..00000000 --- a/modules/Install/Language/zh-hant/Install.php +++ /dev/null @@ -1,62 +0,0 @@ - 'Castopod installer', - 'manual_config' => 'Manual configuration', - 'manual_config_subtitle' => - 'Create a `.env` file with your settings and refresh the page to continue installation.', - 'form' => [ - 'instance_config' => 'Instance configuration', - 'hostname' => 'Hostname', - 'media_base_url' => 'Media base URL', - 'media_base_url_hint' => - 'If you use a CDN and/or an external analytics service, you may set them here.', - 'admin_gateway' => 'Admin gateway', - 'admin_gateway_hint' => - 'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.', - 'auth_gateway' => 'Auth gateway', - 'auth_gateway_hint' => - 'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.', - 'database_config' => 'Database configuration', - 'database_config_hint' => - 'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.', - 'db_hostname' => 'Database hostname', - 'db_name' => 'Database name', - 'db_username' => 'Database username', - 'db_password' => 'Database password', - 'db_prefix' => 'Database prefix', - 'db_prefix_hint' => - "The prefix of the Castopod table names, leave as is if you don't know what it means.", - 'cache_config' => 'Cache configuration', - 'cache_config_hint' => - 'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.', - 'cache_handler' => 'Cache handler', - 'cacheHandlerOptions' => [ - 'file' => 'File', - 'redis' => 'Redis', - 'predis' => 'Predis', - ], - 'next' => 'Next', - 'submit' => 'Finish install', - 'create_superadmin' => 'Create your Super Admin account', - 'email' => 'Email', - 'username' => 'Username', - 'password' => 'Password', - ], - 'messages' => [ - 'createSuperAdminSuccess' => - 'Your superadmin account has been created successfully. Login to start podcasting!', - 'databaseConnectError' => - 'Castopod could not connect to your database. Edit your database configuration and try again.', - 'writeError' => - "Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.", - ], -]; diff --git a/modules/Media/Config/Media.php b/modules/Media/Config/Media.php deleted file mode 100644 index 987847c4..00000000 --- a/modules/Media/Config/Media.php +++ /dev/null @@ -1,73 +0,0 @@ - - */ - public array $fileManagers = [ - 'fs' => FS::class, - 's3' => S3::class, - ]; - - /** - * @var array - */ - public array $s3 = [ - 'bucket' => 'castopod', - 'key' => '', - 'secret' => '', - 'region' => '', - 'protocol' => '', - 'endpoint' => '', - 'debug' => false, - 'pathStyleEndpoint' => false, - 'keyPrefix' => '', - ]; - - /** - * -------------------------------------------------------------------------- - * Media Base URL - * -------------------------------------------------------------------------- - * - * URL to your media root. Typically this will be your base URL, - * WITH a trailing slash: - * - * http://cdn.example.com/ - */ - public string $baseURL = 'http://localhost:8080/'; - - /** - * -------------------------------------------------------------------------- - * Media root folder - * -------------------------------------------------------------------------- - * Defines the root folder for media files storage - */ - public string $root = 'media'; - - /** - * -------------------------------------------------------------------------- - * Media storage folder - * -------------------------------------------------------------------------- - * Defines the folder used to store the media root folder - */ - public string $storage = ROOTPATH . 'public'; - - /** - * @var array - */ - public array $folders = [ - 'podcasts' => 'podcasts', - 'persons' => 'persons', - ]; -} diff --git a/modules/Media/Database/Migrations/2022-30-12-180000_rename_media_file_path.php b/modules/Media/Database/Migrations/2022-30-12-180000_rename_media_file_path.php deleted file mode 100644 index 14b54394..00000000 --- a/modules/Media/Database/Migrations/2022-30-12-180000_rename_media_file_path.php +++ /dev/null @@ -1,43 +0,0 @@ - [ - 'name' => 'file_key', - 'type' => 'VARCHAR', - 'constraint' => 255, - ], - ]; - $this->forge->modifyColumn('media', $fields); - } - - #[Override] - public function down(): void - { - $fields = [ - 'file_key' => [ - 'name' => 'file_path', - 'type' => 'VARCHAR', - 'constraint' => 255, - ], - ]; - $this->forge->modifyColumn('media', $fields); - } -} diff --git a/modules/Media/Entities/BaseMedia.php b/modules/Media/Entities/BaseMedia.php deleted file mode 100644 index 5eb1b118..00000000 --- a/modules/Media/Entities/BaseMedia.php +++ /dev/null @@ -1,140 +0,0 @@ -|null $file_metadata - * @property 'image'|'audio'|'video'|'document' $type - * @property string|null $description - * @property string|null $language_code - * @property int $uploaded_by - * @property int $updated_by - */ -class BaseMedia extends Entity -{ - protected File $file; - - /** - * @var list - */ - protected $dates = ['uploaded_at', 'updated_at']; - - /** - * @var array - */ - protected $casts = [ - 'id' => 'integer', - 'file_key' => 'string', - 'file_size' => 'int', - 'file_mimetype' => 'string', - 'file_metadata' => '?json-array', - 'type' => 'string', - 'description' => '?string', - 'language_code' => '?string', - 'uploaded_by' => 'integer', - 'updated_by' => 'integer', - ]; - - /** - * @param array $data - */ - #[Override] - public function injectRawData(array $data): static - { - parent::injectRawData($data); - - $this->initFileProperties(); - - return $this; - } - - public function initFileProperties(): void - { - $pathInfo = pathinfo($this->file_key) + [ - 'filename' => '', - 'dirname' => '', - 'extension' => '', - ]; - - $this->file_url = service('file_manager') - ->getUrl($this->file_key); - $this->file_name = $pathInfo['filename']; - $this->file_directory = $pathInfo['dirname']; - $this->file_extension = $pathInfo['extension']; - } - - public function setFile(File $file): self - { - $this->attributes['type'] = $this->type; - $this->attributes['file_mimetype'] = $file->getMimeType(); - $this->attributes['file_metadata'] = json_encode(lstat((string) $file), JSON_INVALID_UTF8_IGNORE); - - if ($filesize = $file->getSize()) { - $this->attributes['file_size'] = $filesize; - } - - $this->attributes['file'] = $file; - - return $this; - } - - public function saveFile(): void - { - if (! $this->attributes['file'] || ! $this->file_key) { - throw new RuntimeException("'file' and 'file_key' attributes must be set before saving a file."); - } - - $this->attributes['file_key'] = service('file_manager')->save($this->attributes['file'], $this->file_key); - } - - public function deleteFile(): bool - { - return service('file_manager')->delete($this->file_key); - } - - public function rename(): bool - { - $newFileKey = $this->file_directory . '/' . new File('')->getRandomName() . '.' . $this->file_extension; - - $db = db_connect(); - $db->transStart(); - - if (! new MediaModel()->update($this->id, [ - 'file_key' => $newFileKey, - ])) { - return false; - } - - if (! service('file_manager')->rename($this->file_key, $newFileKey)) { - $db->transRollback(); - - return false; - } - - $db->transComplete(); - - return true; - } -} diff --git a/modules/Media/Entities/Chapters.php b/modules/Media/Entities/Chapters.php deleted file mode 100644 index 44cbfc54..00000000 --- a/modules/Media/Entities/Chapters.php +++ /dev/null @@ -1,65 +0,0 @@ -file_metadata !== null && array_key_exists('chapter_count', $this->file_metadata)) { - helper('media'); - - $this->chapter_count = $this->file_metadata['chapter_count']; - } - } - - #[Override] - public function setFile(File $file): self - { - parent::setFile($file); - - $metadata = lstat((string) $file); - - if (! $metadata) { - $metadata = []; - } - - helper('filesystem'); - - $metadata['chapter_count'] = $this->countChaptersInJson($file); - - $this->attributes['file_metadata'] = json_encode($metadata, JSON_INVALID_UTF8_IGNORE); - - $this->file = $file; - - return $this; - } - - private function countChaptersInJson(File $file): Int - { - $chapterContent = file_get_contents($file->getRealPath()); - - if ($chapterContent === false) { - throw new Exception('Could not read chapter file at ' . $this->file->getRealPath()); - } - - return substr_count($chapterContent, 'startTime'); - } -} diff --git a/modules/Media/Entities/Image.php b/modules/Media/Entities/Image.php deleted file mode 100644 index 02319af1..00000000 --- a/modules/Media/Entities/Image.php +++ /dev/null @@ -1,183 +0,0 @@ -> $sizes - */ -class Image extends BaseMedia -{ - protected string $type = 'image'; - - /** - * @var array> - */ - protected array $sizes = []; - - #[Override] - public function initFileProperties(): void - { - parent::initFileProperties(); - - if ($this->file_metadata && array_key_exists('sizes', $this->file_metadata)) { - $this->sizes = $this->file_metadata['sizes']; - $this->initSizeProperties(); - } - } - - public function initSizeProperties(): bool - { - helper('filesystem'); - - foreach ($this->sizes as $name => $size) { - $extension = array_key_exists('extension', $size) ? $size['extension'] : $this->file_extension; - $mimetype = array_key_exists('mimetype', $size) ? $size['mimetype'] : $this->file_mimetype; - $width = array_key_exists('width', $size) ? $size['width'] : 0; - $height = array_key_exists('height', $size) ? $size['height'] : 0; - - $this->{$name . '_key'} = change_file_path($this->file_key, '_' . $name, $extension); - $this->{$name . '_url'} = service('file_manager')->getUrl($this->{$name . '_key'}); - $this->{$name . '_mimetype'} = $mimetype; - $this->{$name . '_width'} = $width; - $this->{$name . '_height'} = $height; - } - - return true; - } - - /** - * @param array $data - */ - #[Override] - public function injectRawData(array $data): static - { - parent::injectRawData($data); - - if ($this->attributes === []) { - return $this; - } - - if ($this->file_metadata !== [] && array_key_exists('sizes', $this->file_metadata)) { - $this->sizes = $this->file_metadata['sizes']; - $this->attributes['sizes'] = $this->file_metadata['sizes']; - $this->initFileProperties(); - $this->initSizeProperties(); - } - - return $this; - } - - #[Override] - public function setFile(File $file): self - { - parent::setFile($file); - - if ($this->file_mimetype === 'image/jpeg' && $metadata = @exif_read_data( - $file->getRealPath(), - null, - true, - )) { - $metadata['sizes'] = $this->attributes['sizes']; - $this->attributes['file_size'] = $metadata['FILE']['FileSize']; - } else { - $metadata = [ - 'sizes' => $this->attributes['sizes'], - ]; - } - - $this->attributes['file_metadata'] = json_encode($metadata, JSON_INVALID_UTF8_IGNORE); - - return $this; - } - - #[Override] - public function saveFile(): void - { - if ($this->attributes['sizes'] !== []) { - $this->initFileProperties(); - $this->saveSizes(); - } - - parent::saveFile(); - } - - #[Override] - public function deleteFile(): bool - { - if (parent::deleteFile()) { - return $this->deleteSizes(); - } - - return false; - } - - public function saveSizes(): void - { - $tempImagePath = ''; - if (! array_key_exists('file', $this->attributes) && $this->file_key) { - // no original file instance set to save sizes from - - // download image temporarily to generate sizes from - $tempImagePath = (string) tempnam(WRITEPATH . 'temp', 'img_'); - $imageContent = (string) service('file_manager') - ->getFileContents($this->file_key); - file_put_contents($tempImagePath, $imageContent); - - $this->attributes['file'] = new File($tempImagePath, true); - } - - // save derived sizes - $imageService = service('image'); - - foreach ($this->sizes as $name => $size) { - $tempFilePath = tempnam(WRITEPATH . 'temp', 'img_'); - $resizedImage = $imageService - ->withFile($this->attributes['file']->getRealPath()) - ->resize($size['width'], $size['height']); - - /** @var GdImage $resizedImageResource */ - $resizedImageResource = $resizedImage->getResource(); - - // set resolution to 72 by 72 for all sizes - // Apple Podcasts requires images to be 72 dpi - imageresolution($resizedImageResource, 72, 72); - - $resizedImage->save($tempFilePath); - - $newImage = new File($tempFilePath, true); - - service('file_manager') - ->save($newImage, $this->{$name . '_key'}); - } - - if ($tempImagePath !== '') { - unlink($tempImagePath); - } - } - - private function deleteSizes(): bool - { - // delete all derived sizes - foreach (array_keys($this->sizes) as $name) { - $pathProperty = $name . '_key'; - - if (! service('file_manager')->delete($this->{$pathProperty})) { - return false; - } - } - - return true; - } -} diff --git a/modules/Media/Entities/Transcript.php b/modules/Media/Entities/Transcript.php deleted file mode 100644 index 160d9551..00000000 --- a/modules/Media/Entities/Transcript.php +++ /dev/null @@ -1,112 +0,0 @@ -file_metadata !== null && array_key_exists('json_key', $this->file_metadata)) { - helper('media'); - - $this->json_key = $this->file_metadata['json_key']; - $this->json_url = service('file_manager') - ->getUrl($this->json_key); - } - } - - #[Override] - public function setFile(File $file): self - { - parent::setFile($file); - - $metadata = lstat((string) $file); - - if (! $metadata) { - $metadata = []; - } - - helper('filesystem'); - - // set metadata (generated json file path) - $this->json_key = change_file_path($this->file_key, '', 'json'); - $metadata['json_key'] = $this->json_key; - - $this->attributes['file_metadata'] = json_encode($metadata, JSON_INVALID_UTF8_IGNORE); - - $this->file = $file; - - return $this; - } - - #[Override] - public function saveFile(): void - { - $this->saveJsonTranscript(); - - parent::saveFile(); - } - - #[Override] - public function deleteFile(): bool - { - if (! parent::deleteFile()) { - return false; - } - - if ($this->json_key) { - return service('file_manager')->delete($this->json_key); - } - - return true; - } - - private function saveJsonTranscript(): void - { - $transcriptContent = file_get_contents($this->file->getRealPath()); - - $transcriptParser = new TranscriptParser(); - - if ($transcriptContent === false) { - throw new Exception('Could not read transcript file at ' . $this->file->getRealPath()); - } - - $transcript_format = $this->file->getExtension(); - $transcriptJson = match ($transcript_format) { - 'vtt' => $transcriptParser->loadString($transcriptContent) - ->parseVtt(), - default => $transcriptParser->loadString($transcriptContent) - ->parseSrt(), - }; - - $tempFilePath = WRITEPATH . 'uploads/' . $this->file->getRandomName(); - file_put_contents($tempFilePath, $transcriptJson); - - $newTranscriptJson = new File($tempFilePath, true); - - service('file_manager') - ->save($newTranscriptJson, $this->json_key); - } -} diff --git a/modules/Media/FileManagers/FS.php b/modules/Media/FileManagers/FS.php deleted file mode 100644 index 8fbb918e..00000000 --- a/modules/Media/FileManagers/FS.php +++ /dev/null @@ -1,159 +0,0 @@ -media_path_absolute($key); - - if (! file_exists(dirname($path))) { - mkdir(dirname($path), 0777, true); - } - - if (! file_exists(dirname($path) . '/index.html')) { - touch(dirname($path) . '/index.html'); - } - - // copy to media folder, overwrite file if already existing - $isCopySuccessful = copy($file->getRealPath(), $path); - - if (! $isCopySuccessful) { - throw new Exception("Could not save file {$key} to {$path}"); - } - - // delete temporary file after copy - unlink($file->getRealPath()); - - return $key; - } - - #[Override] - public function delete(string $key): bool - { - helper('media'); - - return @unlink($this->media_path_absolute($key)); - } - - #[Override] - public function getUrl(string $key): string - { - return media_url($this->config->root . '/' . $key); - } - - #[Override] - public function rename(string $oldKey, string $newKey): bool - { - helper('media'); - - return rename($this->media_path_absolute($oldKey), $this->media_path_absolute($newKey)); - } - - #[Override] - public function getFileContents(string $key): string|false - { - helper('media'); - - return file_get_contents($this->media_path_absolute($key)); - } - - #[Override] - public function getFileInput(string $key): string - { - helper('media'); - - return $this->media_path_absolute($key); - } - - #[Override] - public function deletePodcastImageSizes(string $podcastHandle): bool - { - foreach (['jpg', 'jpeg', 'png', 'webp'] as $ext) { - $this->deleteAll("podcasts/{$podcastHandle}", "*_*{$ext}"); - } - - return true; - } - - #[Override] - public function deletePersonImagesSizes(): bool - { - foreach (['jpg', 'jpeg', 'png', 'webp'] as $ext) { - $this->deleteAll('persons', "*_*{$ext}"); - } - - return true; - } - - #[Override] - public function deleteAll(string $prefix, string $pattern = '*'): bool - { - helper('media'); - - // delete all in folder? - if ($pattern === '*') { - helper('filesystem'); - - return delete_files($this->media_path_absolute($prefix), true); - } - - $prefix = rtrim($prefix, '/') . '/'; - - $imagePaths = glob($this->media_path_absolute($prefix . $pattern)); - - if (! $imagePaths) { - return true; - } - - foreach ($imagePaths as $imagePath) { - @unlink($imagePath); - } - - return true; - } - - #[Override] - public function isHealthy(): bool - { - helper('media'); - - return is_really_writable($this->media_path_absolute()); - } - - /** - * Prefixes the absolute storage directory to the media path of a given uri - * - * @param string|string[] $uri URI string or array of URI segments - */ - private function media_path_absolute(string | array $uri = ''): string - { - // convert segment array to string - if (is_array($uri)) { - $uri = implode('/', $uri); - } - - $uri = trim($uri, '/'); - - return config('Media')->storage . '/' . config('Media')->root . '/' . $uri; - } -} diff --git a/modules/Media/FileManagers/FileManagerInterface.php b/modules/Media/FileManagers/FileManagerInterface.php deleted file mode 100644 index d711230d..00000000 --- a/modules/Media/FileManagers/FileManagerInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -s3 = new S3Client([ - 'version' => 'latest', - 'region' => $config->s3['region'], - 'endpoint' => $config->s3['endpoint'], - 'credentials' => new Credentials((string) $config->s3['key'], (string) $config->s3['secret']), - 'debug' => $config->s3['debug'], - 'use_path_style_endpoint' => $config->s3['pathStyleEndpoint'], - ]); - } - - #[Override] - public function save(File $file, string $key): string - { - $this->s3->putObject([ - 'Bucket' => $this->config->s3['bucket'], - 'Key' => $this->prefixKey($key), - 'SourceFile' => $file, - 'ContentType' => $file->getMimeType(), - 'CacheControl' => 'max-age=' . YEAR, - 'ACL' => 'public-read', - ]); - - // delete file after storage in s3 - unlink($file->getRealPath()); - - return $key; - } - - #[Override] - public function delete(string $key): bool - { - try { - $this->s3->deleteObject([ - 'Bucket' => $this->config->s3['bucket'], - 'Key' => $this->prefixKey($key), - ]); - } catch (Exception) { - return false; - } - - return true; - } - - #[Override] - public function getUrl(string $key): string - { - return media_url($this->prefixKey($key)); - } - - #[Override] - public function rename(string $oldKey, string $newKey): bool - { - try { - // copy old object with new key - $this->s3->copyObject([ - 'Bucket' => $this->config->s3['bucket'], - 'CopySource' => $this->config->s3['bucket'] . '/' . $this->prefixKey($oldKey), - 'Key' => $this->prefixKey($newKey), - 'ACL' => 'public-read', - ]); - } catch (Exception) { - return false; - } - - // delete old object - return $this->delete($oldKey); - } - - #[Override] - public function getFileContents(string $key): string|false - { - try { - $result = $this->s3->getObject([ - 'Bucket' => $this->config->s3['bucket'], - 'Key' => $this->prefixKey($key), - ]); - } catch (Exception) { - return false; - } - - return (string) $result->get('Body'); - } - - #[Override] - public function getFileInput(string $key): string - { - return $this->getUrl($key); - } - - #[Override] - public function deletePodcastImageSizes(string $podcastHandle): bool - { - foreach (['jpg', 'jpeg', 'png', 'webp'] as $ext) { - $this->deleteAll('podcasts/' . $podcastHandle, "*_*{$ext}"); - } - - return true; - } - - #[Override] - public function deletePersonImagesSizes(): bool - { - foreach (['jpg', 'jpeg', 'png', 'webp'] as $ext) { - $this->deleteAll('persons', "*_*{$ext}"); - } - - return true; - } - - #[Override] - public function deleteAll(string $prefix, ?string $pattern = '*'): bool - { - $prefix = rtrim($this->prefixKey($prefix), '/') . '/'; // make sure that there is a trailing slash - $pattern = $prefix . $pattern; - - $results = $this->s3->getPaginator('ListObjectsV2', [ - 'Bucket' => $this->config->s3['bucket'], - 'prefix' => $prefix, - ]); - - $objectsToDelete = []; - foreach ($results as $result) { - if ($result['Contents'] === null) { - continue; - } - - foreach ($result['Contents'] as $object) { - if (fnmatch($pattern, $object['Key'])) { - $objectsToDelete[] = [ - 'Key' => $object['Key'], - ]; - } - } - } - - if ($objectsToDelete === []) { - return true; - } - - try { - $this->s3->deleteObjects([ - 'Bucket' => $this->config->s3['bucket'], - 'Delete' => [ - 'Objects' => $objectsToDelete, - ], - ]); - } catch (Exception) { - return false; - } - - return true; - } - - #[Override] - public function isHealthy(): bool - { - // check that bucket exists - if (! $this->s3->doesBucketExist((string) $this->config->s3['bucket'])) { - return false; - } - - try { - // ok if bucket exists and you have permission to access it - $this->s3->headBucket([ - 'Bucket' => $this->config->s3['bucket'], - ]); - } catch (Exception) { - return false; - } - - return true; - } - - private function prefixKey(string $key): string - { - if ($this->config->s3['keyPrefix'] === '') { - return $key; - } - - $keyPrefix = rtrim((string) $this->config->s3['keyPrefix']); - - return $keyPrefix . '/' . $key; - } -} diff --git a/modules/Media/Helpers/filesystem_helper.php b/modules/Media/Helpers/filesystem_helper.php deleted file mode 100644 index 9a6d00c8..00000000 --- a/modules/Media/Helpers/filesystem_helper.php +++ /dev/null @@ -1,20 +0,0 @@ -|string $relativePath URI string or array of URI segments - */ - function media_url(array|string $relativePath = '', ?string $scheme = null): string - { - // Convert array of segments to a string - if (is_array($relativePath)) { - $relativePath = implode('/', $relativePath); - } - - $uri = new URI(rtrim(config('Media')->baseURL, '/') . '/' . ltrim($relativePath)); - - return URI::createURIString( - $scheme ?? $uri->getScheme(), - $uri->getAuthority(), - $uri->getPath(), - $uri->getQuery(), - $uri->getFragment(), - ); - } -} diff --git a/modules/Media/TranscriptParser.php b/modules/Media/TranscriptParser.php deleted file mode 100644 index 67ebba2f..00000000 --- a/modules/Media/TranscriptParser.php +++ /dev/null @@ -1,232 +0,0 @@ -transcriptContent = $content; - - return $this; - } - - /** - * Adapted from: https://stackoverflow.com/a/11659306 - * - * @return string Returns the json encoded string - */ - public function parseSrt(): string - { - if (! defined('SRT_STATE_SUBNUMBER')) { - define('SRT_STATE_SUBNUMBER', 0); - } - - if (! defined('SRT_STATE_TIME')) { - define('SRT_STATE_TIME', 1); - } - - if (! defined('SRT_STATE_TEXT')) { - define('SRT_STATE_TEXT', 2); - } - - if (! defined('SRT_STATE_BLANK')) { - define('SRT_STATE_BLANK', 3); - } - - $subs = []; - $state = SRT_STATE_SUBNUMBER; - $subNum = 0; - $subText = ''; - $subTime = ''; - - $lines = explode(PHP_EOL, $this->transcriptContent); - foreach ($lines as $line) { - switch ($state) { - case SRT_STATE_SUBNUMBER: - $subNum = trim($line); - $state = SRT_STATE_TIME; - break; - - case SRT_STATE_TIME: - $subTime = trim($line); - $state = SRT_STATE_TEXT; - break; - - case SRT_STATE_TEXT: - if (trim($line) === '') { - $sub = new stdClass(); - $sub->number = (int) $subNum; - [$startTime, $endTime] = explode(' --> ', $subTime); - $sub->startTime = $this->getSecondsFromTimeString($startTime); - $sub->endTime = $this->getSecondsFromTimeString($endTime); - $sub->text = trim($subText); - $subText = ''; - $state = SRT_STATE_SUBNUMBER; - $subs[] = $sub; - } elseif ($subText !== '') { - $subText .= PHP_EOL . $line; - } else { - $subText .= $line; - } - - break; - } - } - - if ($state === SRT_STATE_TEXT) { - // if file was missing the trailing newlines, we'll be in this - // state here. Append the last read text and add the last sub. - // @phpstan-ignore-next-line - $sub->text = $subText; - // @phpstan-ignore-next-line - $subs[] = $sub; - } - - $jsonString = json_encode($subs, JSON_PRETTY_PRINT); - - if (! $jsonString) { - throw new Exception('Failed to parse SRT to JSON.'); - } - - return $jsonString; - } - - public function parseVtt(): string - { - if (! defined('VTT_STATE_HEADER')) { - define('VTT_STATE_HEADER', 0); - } - - if (! defined('VTT_STATE_BLANK')) { - define('VTT_STATE_BLANK', 1); - } - - if (! defined('VTT_STATE_TIME')) { - define('VTT_STATE_TIME', 2); - } - - if (! defined('VTT_STATE_TEXT')) { - define('VTT_STATE_TEXT', 3); - } - - $subs = []; - $state = VTT_STATE_HEADER; - $subNum = 0; - $subText = ''; - $subTime = ''; - - $lines = explode(PHP_EOL, $this->transcriptContent); - // add a newline as last item, if it isn't already a newline - if (array_last($lines) !== '') { - $lines[] = PHP_EOL; - } - - foreach ($lines as $line) { - switch ($state) { - case VTT_STATE_HEADER: - $state = VTT_STATE_BLANK; - break; - - case VTT_STATE_BLANK: - $speakercount = 0; - $state = VTT_STATE_TIME; - break; - - case VTT_STATE_TIME: - $subTime = trim($line); - $state = VTT_STATE_TEXT; - break; - - case VTT_STATE_TEXT: - if (trim($line) === '') { - $state = VTT_STATE_TIME; - // @phpstan-ignore-next-line - } elseif ($subText !== '') { - $subText .= PHP_EOL . $line; - } else { - /** VTT includes a lot of information on the spoken line - * An example may look like this: - * So this is it - * We need to break this down into it's components, namely: - * 1. The actual words for the caption - * 2. Who is speaking - * 3. Any styling cues encoded in the VTT (which we dump) - * More information: https://www.w3.org/TR/webvtt1/ - * - * If there is more than one speaker in a cue, we also need - * to handle this, to repeat the start and end times for - * the second cue. - * */ - - $vtt_speaker_pattern = '/^<.*>/U'; - $removethese = ['', '<', '>']; - preg_match($vtt_speaker_pattern, $line, $matches); - if (isset($matches[0])) { - $subVoiceCue = str_replace($removethese, '', $matches[0]); - $subSpeaker = substr($subVoiceCue, strpos($subVoiceCue, ' ')); - } else { - $subSpeaker = ''; - } - - $subText .= preg_replace($vtt_speaker_pattern, '', $line); - $sub = new stdClass(); - $sub->number = $subNum; - [$startTime, $endTime] = explode(' --> ', $subTime); - $sub->startTime = $this->getSecondsFromVTTTimeString($startTime); - $sub->endTime = $this->getSecondsFromVTTTimeString($endTime); - $sub->text = trim($subText); - if ($subSpeaker !== '') { - $sub->speaker = trim($subSpeaker); - } - - $subText = ''; - $subs[] = $sub; - ++$subNum; - } - - break; - } - } - - $jsonString = json_encode($subs, JSON_PRETTY_PRINT); - - if (! $jsonString) { - throw new Exception('Failed to parse VTT to JSON.'); - } - - return $jsonString; - } - - private function getSecondsFromTimeString(string $timeString): float - { - $timeString = explode(',', $timeString); - return (strtotime($timeString[0]) - strtotime('TODAY')) + (float) "0.{$timeString[1]}"; - } - - private function getSecondsFromVTTTimeString(string $timeString): float - { - $timeString = explode('.', $timeString); - if (substr_count($timeString[0], ':') === 1) { - // add hours if only MM:SS.mmm format - $timeString[0] = '00:' . $timeString[0]; - } - - return (strtotime($timeString[0]) - strtotime('TODAY')) + (float) "0.{$timeString[1]}"; - } -} diff --git a/modules/MediaClipper/Config/MediaClipper.php b/modules/MediaClipper/Config/MediaClipper.php deleted file mode 100644 index 933ed886..00000000 --- a/modules/MediaClipper/Config/MediaClipper.php +++ /dev/null @@ -1,346 +0,0 @@ ->> - */ - public array $formats = [ - 'landscape' => [ - 'width' => 1920, - 'height' => 1080, - 'cover' => [ - 'width' => 480, - 'height' => 480, - 'radius' => 24, - 'x' => 150, - 'y' => 120, - ], - 'quotes' => [ - 'width' => 192, - 'height' => 192, - 'x' => 810, - 'y' => 210, - ], - 'podcastTitle' => [ - 'fontsize' => 20, - 'x' => 150, - 'y' => 620, - 'lineWidth' => 510, - ], - 'episodeTitle' => [ - 'fontsize' => 32, - 'x' => 150, - 'y' => 660, - 'lines' => 3, - 'lineWidth' => 510, - 'lineHeight' => 1.5, - ], - 'episodeNumbering' => [ - 'fontsize' => 18, - 'paddingX' => 10, - 'paddingY' => 5, - 'marginRight' => 10, - ], - 'timestamp' => [ - 'fontsize' => 32, - 'padding' => 10, - 'x' => 1620, - 'y' => 985, - ], - 'watermark' => [ - 'width' => 90, - 'height' => 72, - 'x' => 140, - 'y' => 960, - ], - 'progressbar' => [ - 'height' => 10, - ], - 'soundwaves' => [ - 'width' => 192, - 'height' => 108, - 'rescaleWidth' => 1920, - 'rescaleHeight' => 540, - 'x' => 0, - 'y' => 810, - 'mask' => ROOTPATH . 'modules/MediaClipper/Resources/soundwaves-mask-landscape.png', - ], - 'subtitles' => [ - 'fontsize' => 18, - 'marginL' => 180, - 'marginR' => 20, - 'marginV' => 85, - ], - ], - 'portrait' => [ - 'width' => 1080, - 'height' => 1920, - 'cover' => [ - 'width' => 280, - 'height' => 280, - 'radius' => 16, - 'x' => 50, - 'y' => 50, - ], - 'quotes' => [ - 'width' => 256, - 'height' => 256, - 'x' => 40, - 'y' => 520, - ], - 'podcastTitle' => [ - 'fontsize' => 32, - 'x' => 360, - 'y' => 55, - 'lineWidth' => 670, - ], - 'episodeTitle' => [ - 'fontsize' => 42, - 'x' => 360, - 'y' => 110, - 'lines' => 3, - 'lineWidth' => 670, - 'lineHeight' => 1.5, - ], - 'episodeNumbering' => [ - 'fontsize' => 28, - 'paddingX' => 10, - 'paddingY' => 10, - 'marginRight' => 10, - ], - 'timestamp' => [ - 'fontsize' => 48, - 'padding' => 14, - 'x' => 734, - 'y' => 1800, - ], - 'watermark' => [ - 'width' => 120, - 'height' => 96, - 'x' => 130, - 'y' => 1770, - ], - 'progressbar' => [ - 'height' => 10, - ], - 'soundwaves' => [ - 'width' => 54, - 'height' => 96, - 'rescaleWidth' => 1080, - 'rescaleHeight' => 1920, - 'x' => 0, - 'y' => 960, - 'mask' => ROOTPATH . 'modules/MediaClipper/Resources/soundwaves-mask-portrait.png', - ], - 'subtitles' => [ - 'fontsize' => 16, - 'marginL' => 40, - 'marginR' => 25, - 'marginV' => 97, - ], - ], - 'squared' => [ - 'width' => 1200, - 'height' => 1200, - 'cover' => [ - 'width' => 200, - 'height' => 200, - 'radius' => 16, - 'x' => 40, - 'y' => 40, - ], - 'quotes' => [ - 'width' => 200, - 'height' => 200, - 'x' => 85, - 'y' => 320, - ], - 'podcastTitle' => [ - 'fontsize' => 28, - 'x' => 260, - 'y' => 50, - 'lines' => 1, - 'lineWidth' => 800, - ], - 'episodeTitle' => [ - 'fontsize' => 36, - 'x' => 260, - 'y' => 90, - 'lines' => 2, - 'lineWidth' => 850, - 'lineHeight' => 1.5, - ], - 'episodeNumbering' => [ - 'fontsize' => 24, - 'paddingX' => 10, - 'paddingY' => 5, - 'marginRight' => 10, - ], - 'timestamp' => [ - 'fontsize' => 48, - 'padding' => 10, - 'x' => 855, - 'y' => 1070, - ], - 'watermark' => [ - 'width' => 120, - 'height' => 96, - 'x' => 130, - 'y' => 1040, - ], - 'progressbar' => [ - 'height' => 10, - ], - 'soundwaves' => [ - 'width' => 60, - 'height' => 60, - 'rescaleWidth' => 1200, - 'rescaleHeight' => 1200, - 'x' => 0, - 'y' => 600, - 'mask' => ROOTPATH . 'modules/MediaClipper/Resources/soundwaves-mask-squared.png', - ], - 'subtitles' => [ - 'fontsize' => 20, - 'marginL' => 60, - 'marginR' => 20, - 'marginV' => 98, - ], - ], - ]; - - /** - * @var array> - */ - public array $themes = [ - 'pine' => [ - // Previews must be a HSL colorscheme string - 'preview' => '174 100% 29%', - 'preview-background' => '172 100% 17%', - // arrays are rgb - 'background' => [0, 86, 74], - 'text' => [255, 255, 255], - // subtitle hex color is BGR (Blue, Green, Red), - 'subtitles' => 'FFFFFF', - // quotes image MUST BE black - 'quotes' => [0, 148, 134], - 'episodeNumberingBg' => [0, 61, 11], - 'episodeNumberingText' => [255, 255, 255], - 'progressbar' => '009486', - 'timestampBg' => '00564A', - 'timestampText' => 'FFFFFF', - 'watermarkBg' => '00564A', - 'soundwaves' => [231, 249, 228], - ], - 'crimson' => [ - // Preview must be a HSL colorscheme string - 'preview' => '350 87% 61%', - 'preview-background' => '348 75% 40%', - // arrays are rgb - 'background' => [179, 31, 57], - 'text' => [255, 255, 255], - // subtitle hex color is BGR (Blue, Green, Red), - 'subtitles' => 'FFFFFF', - // quotes image MUST BE black - 'quotes' => [242, 70, 100], - 'episodeNumberingBg' => [152, 16, 43], - 'episodeNumberingText' => [255, 255, 255], - 'progressbar' => 'F24664', - 'timestampBg' => 'B31F39', - 'timestampText' => 'FFFFFF', - 'watermarkBg' => 'B31F39', - 'soundwaves' => [253, 206, 215], - ], - 'lake' => [ - // Preview must be a HSL colorscheme string - 'preview' => '194 100% 44%', - 'preview-background' => '194 100% 22%', - // arrays are rgb - 'background' => [0, 86, 113], - 'text' => [255, 255, 255], - // subtitle hex color is BGR (Blue, Green, Red), - 'subtitles' => 'FFFFFF', - // quotes image MUST BE black - 'quotes' => [0, 171, 225], - 'episodeNumberingBg' => [0, 43, 57], - 'episodeNumberingText' => [255, 255, 255], - 'progressbar' => '00ABE1', - 'timestampBg' => '005671', - 'timestampText' => 'FFFFFF', - 'watermarkBg' => '005671', - 'soundwaves' => [214, 245, 255], - ], - 'amber' => [ - // Preview must be a HSL colorscheme string - 'preview' => '17 100% 57%', - 'preview-background' => '17 100% 35%', - // arrays are rgb - 'background' => [177, 50, 0], - 'text' => [255, 255, 255], - // subtitle hex color is BGR (Blue, Green, Red), - 'subtitles' => 'FFFFFF', - // quotes image MUST BE black - 'quotes' => [255, 96, 34], - 'episodeNumberingBg' => [121, 34, 0], - 'episodeNumberingText' => [255, 255, 255], - 'progressbar' => 'FF6022', - 'timestampBg' => 'B13200', - 'timestampText' => 'FFFFFF', - 'watermarkBg' => 'B13200', - 'soundwaves' => [255, 213, 197], - ], - 'jacaranda' => [ - // Preview must be a HSL colorscheme string - 'preview' => '254 72% 52%', - 'preview-background' => '254 73% 30%', - // arrays are rgb - 'background' => [47, 21, 132], - 'text' => [255, 255, 255], - // subtitle hex color is BGR (Blue, Green, Red), - 'subtitles' => 'FFFFFF', - // quotes image MUST BE black - 'quotes' => [86, 45, 221], - 'episodeNumberingBg' => [30, 14, 84], - 'episodeNumberingText' => [255, 255, 255], - 'progressbar' => '562DDD', - 'timestampBg' => '2F1584', - 'timestampText' => 'FFFFFF', - 'watermarkBg' => '2F1584', - 'soundwaves' => [199, 185, 244], - ], - 'onyx' => [ - // Preview must be a HSL colorscheme string - 'preview' => '240 17% 2%', - 'preview-background' => '240 17% 2%', - // arrays are rgb - 'background' => [5, 5, 7], - 'text' => [255, 255, 255], - // subtitle hex color is BGR (Blue, Green, Red), - 'subtitles' => 'FFFFFF', - // quotes image MUST BE black - 'quotes' => [38, 38, 49], - 'episodeNumberingBg' => [0, 0, 0], - 'episodeNumberingText' => [255, 255, 255], - 'progressbar' => 'D5D5E1', - 'timestampBg' => '050507', - 'timestampText' => 'FFFFFF', - 'watermarkBg' => '050507', - 'soundwaves' => [213, 213, 225], - ], - ]; -} diff --git a/modules/Platforms/Config/Routes.php b/modules/Platforms/Config/Routes.php deleted file mode 100644 index 06284656..00000000 --- a/modules/Platforms/Config/Routes.php +++ /dev/null @@ -1,64 +0,0 @@ -addPlaceholder('platformType', '\bpodcasting|\bsocial|\bfunding'); - -// Admin routes for subscriptions -$routes->group( - config('Admin') - ->gateway, - [ - 'namespace' => 'Modules\Platforms\Controllers', - ], - static function ($routes): void { - $routes->group('podcasts/(:num)/platforms', static function ($routes): void { - $routes->get( - '/', - 'PlatformController::list/$1/podcasting', - [ - 'as' => 'platforms-podcasting', - 'filter' => 'permission:podcast$1.manage-platforms', - ], - ); - $routes->get( - 'social', - 'PlatformController::list/$1/social', - [ - 'as' => 'platforms-social', - 'filter' => 'permission:podcast$1.manage-platforms', - ], - ); - $routes->get( - 'funding', - 'PlatformController::list/$1/funding', - [ - 'as' => 'platforms-funding', - 'filter' => 'permission:podcast$1.manage-platforms', - ], - ); - $routes->post( - 'save/(:platformType)', - 'PlatformController::updateAction/$1/$2', - [ - 'as' => 'platforms-save', - 'filter' => 'permission:podcast$1.manage-platforms', - ], - ); - $routes->get( - '(:platformType)/(:slug)/podcast-platform-remove', - 'PlatformController::removeAction/$1/$2/$3', - [ - 'as' => 'podcast-platform-remove', - 'filter' => 'permission:podcast$1.manage-platforms', - ], - ); - }); - }, -); diff --git a/modules/Platforms/Config/Services.php b/modules/Platforms/Config/Services.php deleted file mode 100644 index c9912c0c..00000000 --- a/modules/Platforms/Config/Services.php +++ /dev/null @@ -1,20 +0,0 @@ -{$method}(); - } - - if ( - ! ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast - ) { - throw PageNotFoundException::forPageNotFound(); - } - - $this->podcast = $podcast; - - unset($params[0]); - return $this->{$method}(...$params); - } - - public function index(): string - { - return view('podcast/platforms/dashboard'); - } - - public function list(string $platformType): string - { - helper('form'); - - $data = [ - 'podcast' => $this->podcast, - 'platformType' => $platformType, - 'platforms' => new PlatformModel() - ->getPlatformsWithData($this->podcast->id, $platformType), - ]; - - $this->setHtmlHead(lang("Platforms.title.{$platformType}")); - replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, - ]); - return view('podcast/platforms', $data); - } - - public function updateAction(string $platformType): RedirectResponse - { - $platformModel = new PlatformModel(); - $validation = service('validation'); - - $platformsData = []; - foreach ( - $this->request->getPost('platforms') as $platformSlug => $podcastPlatform - ) { - $podcastPlatformUrl = trim((string) $podcastPlatform['url']); - if ($podcastPlatformUrl === '') { - continue; - } - - if (! $validation->check(htmlentities($podcastPlatformUrl), 'valid_url_strict')) { - continue; - } - - $podcastPlatformAccountId = trim((string) $podcastPlatform['account_id']); - $platformsData[] = [ - 'podcast_id' => $this->podcast->id, - 'type' => $platformType, - 'slug' => $platformSlug, - 'link_url' => $podcastPlatformUrl, - 'account_id' => $podcastPlatformAccountId === '' ? null : $podcastPlatformAccountId, - 'is_visible' => array_key_exists('visible', $podcastPlatform) && - $podcastPlatform['visible'] === 'yes', - ]; - } - - $platformModel->savePlatforms($this->podcast->id, $platformType, $platformsData); - - return redirect() - ->back() - ->with('message', lang('Platforms.messages.updateSuccess')); - } - - public function removeAction(string $platformType, string $platformSlug): RedirectResponse - { - new PlatformModel() - ->removePlatform($this->podcast->id, $platformType, $platformSlug); - - return redirect() - ->back() - ->with('message', lang('Platforms.messages.removeLinkSuccess')); - } -} diff --git a/modules/Platforms/Models/PlatformModel.php b/modules/Platforms/Models/PlatformModel.php deleted file mode 100644 index 8ba8c89a..00000000 --- a/modules/Platforms/Models/PlatformModel.php +++ /dev/null @@ -1,179 +0,0 @@ - - */ - protected $allowedFields = ['podcast_id', 'type', 'slug', 'link_url', 'account_id', 'is_visible']; - - /** - * @var class-string - */ - protected $returnType = Platform::class; - - /** - * @var bool - */ - protected $useSoftDeletes = false; - - /** - * @var bool - */ - protected $useTimestamps = false; - - /** - * @return Platform[] - */ - public function getPlatformsWithData(int $podcastId, string $platformType): array - { - $cacheName = "podcast#{$podcastId}_platforms_{$platformType}_withData"; - if (! ($found = cache($cacheName))) { - $platforms = service('platforms'); - - $found = $this->getPlatforms($podcastId, $platformType); - $platformsData = $platforms->getPlatformsByType($platformType); - - $knownSlugs = []; - foreach ($found as $podcastPlatform) { - $knownSlugs[] = $podcastPlatform->slug; - } - - foreach ($platformsData as $slug => $platform) { - if (! in_array($slug, $knownSlugs, true)) { - $found[] = new Platform([ - 'podcast_id' => $podcastId, - 'slug' => $slug, - 'type' => $platformType, - 'label' => $platform['label'], - 'home_url' => $platform['home_url'], - 'submit_url' => $platform['submit_url'], - 'link_url' => '', - 'account_id' => null, - 'is_visible' => false, - ]); - } - } - - cache() - ->save($cacheName, $found, DECADE); - } - - return $found; - } - - /** - * @return Platform[] - */ - public function getPlatforms(int $podcastId, string $platformType): array - { - $cacheName = "podcast#{$podcastId}_platforms_{$platformType}"; - if (! ($found = cache($cacheName))) { - $platforms = service('platforms'); - - /** @var Platform[] $found */ - $found = $this - ->where('podcast_id', $podcastId) - ->where('type', $platformType) - ->orderBy('slug') - ->findAll(); - - foreach ($found as $platform) { - $platformData = $platforms->findPlatformBySlug($platformType, $platform->slug); - - if ($platformData === null) { - // delete platform, it does not correspond to any existing one - $this->delete($platform->id); - - continue; - } - - $platform->type = $platformType; - $platform->label = $platformData['label']; - $platform->home_url = $platformData['home_url']; - $platform->submit_url = $platformData['submit_url']; - } - - cache() - ->save($cacheName, $found, DECADE); - } - - return $found; - } - - /** - * @param array> $data - * - * @return int|false Number of rows inserted or FALSE on failure - */ - public function savePlatforms(int $podcastId, string $platformType, array $data): int | false - { - $this->clearCache($podcastId); - - $platforms = service('platforms'); - - $platformsData = $platforms->getPlatformsByType($platformType); - - $this->builder() - ->whereIn('slug', array_keys($platformsData)) - ->delete(); - - if ($data === []) { - // no rows inserted - return 0; - } - - return $this->insertBatch($data); - } - - public function removePlatform(int $podcastId, string $platformType, string $platformSlug): bool | string - { - $this->clearCache($podcastId); - - return $this->builder() - ->delete([ - 'podcast_id' => $podcastId, - 'type' => $platformType, - 'slug' => $platformSlug, - ]); - } - - public function clearCache(int $podcastId): void - { - cache()->deleteMatching("podcast#{$podcastId}_platforms_*"); - - // delete localized podcast page cache - cache() - ->deleteMatching("page_podcast#{$podcastId}*"); - // delete post and episode comments pages cache - cache() - ->deleteMatching('page_post*'); - cache() - ->deleteMatching('page_episode#*'); - } -} diff --git a/modules/Platforms/Platforms.php b/modules/Platforms/Platforms.php deleted file mode 100644 index 13cf436c..00000000 --- a/modules/Platforms/Platforms.php +++ /dev/null @@ -1,478 +0,0 @@ -> - */ - public const DATA = [ - 'podcasting' => [ - 'amazon' => [ - 'label' => 'Amazon Music', - 'home_url' => 'https://music.amazon.com/', - 'submit_url' => 'https://podcasters.amazon.com/', - ], - 'antennapod' => [ - 'label' => 'AntennaPod', - 'home_url' => 'https://antennapod.org/', - 'submit_url' => 'https://antennapod.org/documentation/podcasters-hosters/add-on-antennapod', - ], - 'anytime' => [ - 'label' => 'Anytime Podcast Player', - 'home_url' => 'https://anytimeplayer.app/', - 'submit_url' => null, - ], - 'apple' => [ - 'label' => 'Apple Podcasts', - 'home_url' => 'https://www.apple.com/itunes/podcasts/', - 'submit_url' => 'https://podcastsconnect.apple.com/my-podcasts/new-feed', - ], - 'blubrry' => [ - 'label' => 'Blubrry', - 'home_url' => 'https://www.blubrry.com/', - 'submit_url' => 'https://www.blubrry.com/addpodcast.php', - ], - 'breez' => [ - 'label' => 'Breez', - 'home_url' => 'https://breez.technology/', - 'submit_url' => null, - ], - 'castamatic' => [ - 'label' => 'Castamatic', - 'home_url' => 'https://castamatic.com/', - 'submit_url' => null, - ], - 'castbox' => [ - 'label' => 'Castbox', - 'home_url' => 'https://castbox.fm/', - 'submit_url' => 'https://helpcenter.castbox.fm/portal/kb/articles/submit-my-podcast', - ], - 'castopod' => [ - 'label' => 'Castopod', - 'home_url' => 'https://castopod.org/', - 'submit_url' => 'https://castopod.org/instances', - ], - 'castro' => [ - 'label' => 'Castro', - 'home_url' => 'http://castro.fm/', - 'submit_url' => 'https://castro.fm/support/link-to-your-podcast-in-castro', - ], - 'curiocaster' => [ - 'label' => 'CurioCaster', - 'home_url' => 'https://curiocaster.com/', - 'submit_url' => null, - ], - 'deezer' => [ - 'label' => 'Deezer', - 'home_url' => 'https://www.deezer.com/', - 'submit_url' => 'https://podcasters.deezer.com/submission', - ], - 'episodes-fm' => [ - 'label' => 'Episodes.fm', - 'home_url' => 'https://episodes.fm/', - 'submit_url' => 'https://podcastindex.org/add', - ], - 'fountain' => [ - 'label' => 'Fountain', - 'home_url' => 'https://www.fountain.fm/', - 'submit_url' => 'https://support.fountain.fm/article/56-how-to-claim-your-show-on-fountain', - ], - 'fyyd' => [ - 'label' => 'fyyd', - 'home_url' => 'https://fyyd.de/', - 'submit_url' => 'https://fyyd.de/add-feed', - ], - 'gpodder' => [ - 'label' => 'gPodder', - 'home_url' => 'https://gpodder.org/', - 'submit_url' => null, - ], - 'ivoox' => [ - 'label' => 'Ivoox', - 'home_url' => 'https://www.ivoox.com/', - 'submit_url' => null, - ], - 'listennotes' => [ - 'label' => 'ListenNotes', - 'home_url' => 'https://www.listennotes.com/', - 'submit_url' => 'https://www.listennotes.com/submit/', - ], - 'overcast' => [ - 'label' => 'Overcast', - 'home_url' => 'https://overcast.fm/', - 'submit_url' => 'https://overcast.fm/podcasterinfo', - ], - 'playerfm' => [ - 'label' => 'Player.Fm', - 'home_url' => 'https://player.fm/', - 'submit_url' => 'https://player.fm/importer/feed', - ], - 'pocketcasts' => [ - 'label' => 'Pocketcasts', - 'home_url' => 'https://www.pocketcasts.com/', - 'submit_url' => 'https://www.pocketcasts.com/submit/', - ], - 'podbean' => [ - 'label' => 'Podbean', - 'home_url' => 'https://www.podbean.com/', - 'submit_url' => 'https://www.podbean.com/site/submitPodcast', - ], - 'podcastaddict' => [ - 'label' => 'Podcast Addict', - 'home_url' => 'https://podcastaddict.com/', - 'submit_url' => 'https://podcastaddict.com/submit', - ], - 'podcastindex' => [ - 'label' => 'Podcast Index', - 'home_url' => 'https://podcastindex.org/', - 'submit_url' => 'https://podcastindex.org/add', - ], - 'podchaser' => [ - 'label' => 'Podchaser', - 'home_url' => 'https://www.podchaser.com/', - 'submit_url' => 'https://www.podchaser.com/add', - ], - 'podcloud' => [ - 'label' => 'podCloud', - 'home_url' => 'https://podcloud.fr/', - 'submit_url' => 'https://podcloud.fr/studio/podcasts/new', - ], - 'podlink' => [ - 'label' => 'pod.link', - 'home_url' => 'https://pod.link/', - 'submit_url' => null, - ], - 'podtail' => [ - 'label' => 'Podtail', - 'home_url' => 'https://podtail.com/', - 'submit_url' => 'https://podtail.com/about/faq/', - ], - 'podfriend' => [ - 'label' => 'Podfriend', - 'home_url' => 'https://www.podfriend.com/', - 'submit_url' => 'https://podcastindex.org/add', - ], - 'podverse' => [ - 'label' => 'Podverse', - 'home_url' => 'https://podverse.fm/', - 'submit_url' => 'https://docs.google.com/forms/d/e/1FAIpQLSdewKP-YrE8zGjDPrkmoJEwCxPl_gizEkmzAlTYsiWAuAk1Ng/viewform', - ], - 'radiopublic' => [ - 'label' => 'RadioPublic', - 'home_url' => 'https://radiopublic.com/', - 'submit_url' => 'https://podcasters.radiopublic.com/signup', - ], - 'spotify' => [ - 'label' => 'Spotify', - 'home_url' => 'https://www.spotify.com/', - 'submit_url' => 'https://podcasters.spotify.com/dash/submit', - ], - 'spreaker' => [ - 'label' => 'Spreaker', - 'home_url' => 'https://www.spreaker.com/', - 'submit_url' => 'https://www.spreaker.com/cms/shows/rss-import', - ], - 'tunein' => [ - 'label' => 'TuneIn', - 'home_url' => 'https://tunein.com/', - 'submit_url' => 'https://help.tunein.com/contact/add-podcast-S19TR3Sdf', - ], - 'hypercatcher' => [ - 'label' => 'HyperCatcher', - 'home_url' => 'https://hypercatcher.com/', - 'submit_url' => null, - ], - 'ivyfm' => [ - 'label' => 'Ivy.fm', - 'home_url' => 'https://ivy.fm/', - 'submit_url' => null, - ], - 'jumplink' => [ - 'label' => 'JumpLink', - 'home_url' => 'https://jump.link/', - 'submit_url' => 'https://jump.link/a/accounts/signup/', - ], - 'kasts' => [ - 'label' => 'Kasts', - 'home_url' => 'https://apps.kde.org/kasts/', - 'submit_url' => null, - ], - 'playapod' => [ - 'label' => 'Playapod', - 'home_url' => 'https://playapod.com/', - 'submit_url' => null, - ], - 'plink' => [ - 'label' => 'Plink', - 'home_url' => 'https://plinkhq.com/', - 'submit_url' => null, - ], - 'podcastchapters' => [ - 'label' => 'Podcast Chapters', - 'home_url' => 'https://chaptersapp.com/', - 'submit_url' => null, - ], - 'podcastguru' => [ - 'label' => 'Podcast Guru', - 'home_url' => 'https://podcastguru.io/', - 'submit_url' => 'https://podcastguru.io/promote-your-podcast/', - ], - 'podlp' => [ - 'label' => 'PodLP', - 'home_url' => 'https://podlp.com/', - 'submit_url' => 'https://podlp.com/submit.html', - ], - 'podnews' => [ - 'label' => 'Podnews', - 'home_url' => 'https://podnews.net/', - 'submit_url' => 'https://podnews.net/podcast/subscribe-pages', - ], - 'podstation' => [ - 'label' => 'podStation', - 'home_url' => 'https://podstation.github.io/', - 'submit_url' => null, - ], - 'sphinxchat' => [ - 'label' => 'Sphinx', - 'home_url' => 'https://sphinx.chat/', - 'submit_url' => null, - ], - 'truefans' => [ - 'label' => 'Truefans', - 'home_url' => 'https://truefans.fm/', - 'submit_url' => 'https://podcastindex.org/add', - ], - 'tsacdop' => [ - 'label' => 'Tsacdop', - 'home_url' => 'https://www.tsacdop.app/', - 'submit_url' => null, - ], - 'youtube-music' => [ - 'label' => 'YouTube Music', - 'home_url' => 'https://www.youtube.com/creators/podcasts/', - 'submit_url' => 'https://studio.youtube.com/channel/content/podcasts', - ], - ], - 'social' => [ - 'bluesky' => [ - 'label' => 'Bluesky', - 'home_url' => 'https://bsky.app/', - 'submit_url' => 'https://bsky.app/', - ], - 'discord' => [ - 'label' => 'Discord', - 'home_url' => 'https://discord.com/', - 'submit_url' => 'https://discord.com/register', - ], - 'discourse' => [ - 'label' => 'Discourse', - 'home_url' => 'https://www.discourse.org/', - 'submit_url' => null, - ], - 'facebook' => [ - 'label' => 'Facebook', - 'home_url' => 'https://www.facebook.com/', - 'submit_url' => 'https://www.facebook.com/pages/creation/', - ], - 'funkwhale' => [ - 'label' => 'Funkwhale', - 'home_url' => 'https://funkwhale.audio/', - 'submit_url' => 'https://network.funkwhale.audio/dashboards/', - ], - 'instagram' => [ - 'label' => 'Instagram', - 'home_url' => 'https://www.instagram.com/', - 'submit_url' => 'https://www.instagram.com/accounts/emailsignup/', - ], - 'linkedin' => [ - 'label' => 'LinkedIn', - 'home_url' => 'https://www.linkedin.com/', - 'submit_url' => 'https://www.linkedin.com/company/setup/new/', - ], - 'mastodon' => [ - 'label' => 'Mastodon', - 'home_url' => 'https://joinmastodon.org/', - 'submit_url' => 'https://joinmastodon.org/communities', - ], - 'matrix' => [ - 'label' => 'Matrix', - 'home_url' => 'https://matrix.org/', - 'submit_url' => 'https://matrix.org/try-matrix/', - ], - 'misskey' => [ - 'label' => 'Misskey', - 'home_url' => 'https://join.misskey.page/', - 'submit_url' => 'https://join.misskey.page/en-US/instances', - ], - 'mobilizon' => [ - 'label' => 'Mobilizon', - 'home_url' => 'https://joinmobilizon.org/', - 'submit_url' => 'https://instances.joinmobilizon.org/instances', - ], - 'peertube' => [ - 'label' => 'PeerTube', - 'home_url' => 'https://joinpeertube.org/', - 'submit_url' => 'https://joinpeertube.org/instances', - ], - 'pixelfed' => [ - 'label' => 'Pixelfed', - 'home_url' => 'https://pixelfed.org/', - 'submit_url' => 'https://beta.joinpixelfed.org/', - ], - 'pleroma' => [ - 'label' => 'Pleroma', - 'home_url' => 'https://pleroma.social/', - 'submit_url' => 'https://pleroma.social/#featured-instances', - ], - 'plume' => [ - 'label' => 'Plume', - 'home_url' => 'https://joinplu.me/', - 'submit_url' => 'https://joinplu.me/#instances', - ], - 'slack' => [ - 'label' => 'Slack', - 'home_url' => 'https://slack.com/', - 'submit_url' => 'https://slack.com/get-started#/create', - ], - 'telegram' => [ - 'label' => 'Telegram', - 'home_url' => 'https://www.telegram.org/', - 'submit_url' => null, - ], - 'threads' => [ - 'label' => 'Threads', - 'home_url' => 'https://www.threads.net/', - 'submit_url' => 'https://www.threads.net/login', - ], - 'tiktok' => [ - 'label' => 'TikTok', - 'home_url' => 'https://www.tiktok.com/', - 'submit_url' => 'https://www.tiktok.com/signup', - ], - 'twitch' => [ - 'label' => 'Twitch', - 'home_url' => 'https://www.twitch.tv/', - 'submit_url' => 'https://www.twitch.tv/signup', - ], - 'writefreely' => [ - 'label' => 'WriteFreely', - 'home_url' => 'https://writefreely.org/', - 'submit_url' => 'https://writefreely.org/instances', - ], - 'youtube' => [ - 'label' => 'YouTube', - 'home_url' => 'https://www.youtube.com/', - 'submit_url' => 'https://studio.youtube.com/', - ], - 'x' => [ - 'label' => 'Twitter / X', - 'home_url' => 'https://x.com/', - 'submit_url' => 'https://x.com/i/flow/signup', - ], - ], - 'funding' => [ - 'buymeacoffee' => [ - 'label' => 'Buy Me a Coffee', - 'home_url' => 'https://www.buymeacoffee.com/', - 'submit_url' => 'https://www.buymeacoffee.com/signup', - ], - 'paypal' => [ - 'label' => 'PayPal', - 'home_url' => 'https://www.paypal.com/', - 'submit_url' => 'https://www.paypal.com/paypalme/my/grab', - ], - 'fosspay' => [ - 'label' => 'fosspay', - 'home_url' => 'https://git.sr.ht/~sircmpwn/fosspay', - 'submit_url' => null, - ], - 'gofundme' => [ - 'label' => 'GoFundMe', - 'home_url' => 'https://www.gofundme.com/', - 'submit_url' => 'https://www.gofundme.com/sign-up', - ], - 'helloasso' => [ - 'label' => 'HelloAsso', - 'home_url' => 'https://www.helloasso.com/', - 'submit_url' => 'https://auth.helloasso.com/inscription', - ], - 'indiegogo' => [ - 'label' => 'Indiegogo', - 'home_url' => 'https://www.indiegogo.com/', - 'submit_url' => 'https://www.indiegogo.com/start-a-campaign#/', - ], - 'kickstarter' => [ - 'label' => 'Kickstarter', - 'home_url' => 'https://www.kickstarter.com/', - 'submit_url' => 'https://www.kickstarter.com/learn', - ], - 'kisskissbankbank' => [ - 'label' => 'KissKissBankBank', - 'home_url' => 'https://www.kisskissbankbank.com/', - 'submit_url' => 'https://www.kisskissbankbank.com/en/financer-mon-projet', - ], - 'kofi' => [ - 'label' => 'Ko-fi', - 'home_url' => 'https://ko-fi.com/', - 'submit_url' => 'https://ko-fi.com/account/register', - ], - 'liberapay' => [ - 'label' => 'Liberapay', - 'home_url' => 'https://liberapay.com/', - 'submit_url' => 'https://liberapay.com/sign-up', - ], - 'patreon' => [ - 'label' => 'Patreon', - 'home_url' => 'https://www.patreon.com/', - 'submit_url' => 'https://www.patreon.com/create', - ], - 'tipeee' => [ - 'label' => 'Tipeee', - 'home_url' => 'https://tipeee.com/', - 'submit_url' => 'https://tipeee.com/register/', - ], - 'ulule' => [ - 'label' => 'Ulule', - 'home_url' => 'https://www.ulule.com/', - 'submit_url' => 'https://www.ulule.com/projects/create/#/', - ], - 'donorbox' => [ - 'label' => 'Donorbox', - 'home_url' => 'https://donorbox.org/', - 'submit_url' => 'https://donorbox.org/orgs/new', - ], - ], - ]; - - /** - * @return array - */ - public function getPlatformsByType(string $type): array - { - return self::DATA[$type] ?? []; - } - - /** - * @return null|array{label:string,home_url:string,submit_url:?string} - */ - public function findPlatformBySlug(string $type, string $slug): ?array - { - $data = self::DATA[$type] ?? []; - - if (! array_key_exists($slug, $data)) { - return null; - } - - return $data[$slug]; - } -} diff --git a/modules/Plugins/Commands/Add.php b/modules/Plugins/Commands/Add.php deleted file mode 100644 index 97e8aa28..00000000 --- a/modules/Plugins/Commands/Add.php +++ /dev/null @@ -1,81 +0,0 @@ - - */ - protected $arguments = [ - 'plugin' => 'The pluginKey and an optional version separated by an @. If version is not provided, the latest will be added by default.', - ]; - - /** - * Actually execute a command. - * - * @param array $params - */ - #[Override] - public function run(array $params): void - { - parent::run($params); - - $plugins = $this->parsePluginsParams($params); - - /** @var PluginsManager $cpm */ - $cpm = service('cpm'); - - $cpm->install($plugins); - } - - /** - * @param array $params - * @return array - */ - private function parsePluginsParams(array $params): array - { - $plugins = []; - foreach ($params as $param) { - preg_match( - '/^(?[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9]([_.-]?[a-z0-9]+)*)(@(?\S+))?\s*$/', - $param, - $matches, - ); - - if (array_key_exists('pluginKey', $matches)) { - $plugins[$matches['pluginKey']] = $matches['version'] ?? null; - } - } - - return $plugins; - } -} diff --git a/modules/Plugins/Commands/BaseCommand.php b/modules/Plugins/Commands/BaseCommand.php deleted file mode 100644 index 7cc27b01..00000000 --- a/modules/Plugins/Commands/BaseCommand.php +++ /dev/null @@ -1,46 +0,0 @@ - - */ - protected $options = [ - '--debug' => 'Get log trace to follow what is happening under the hood.', - ]; - - /** - * Actually execute a command. - * - * @param array $params - * - * @return int|void - */ - public function run(array $params) - { - if (CLI::getOption('debug')) { - PluginsManagerLogger::$formatter = CpmFormatterDebug::class; - } else { - PluginsManagerLogger::$formatter = CpmFormatter::class; - } - - return 0; - } -} diff --git a/modules/Plugins/Commands/CpmFormatter.php b/modules/Plugins/Commands/CpmFormatter.php deleted file mode 100644 index e312824c..00000000 --- a/modules/Plugins/Commands/CpmFormatter.php +++ /dev/null @@ -1,60 +0,0 @@ - CLI::write( - sprintf('• adding plugin %s%s', CLI::color( - $log['context']['pluginKey'], - 'white', - ), $log['context']['constraint'] === null ? '' : '@' . CLI::color( - $log['context']['constraint'], - 'light_yellow', - )), - ), - 'add.end' => CLI::write( - sprintf('+ %s@%s added%s', $log['context']['pluginKey'], $log['context']['version'], PHP_EOL), - 'light_green', - ), - 'update.start' => CLI::write(sprintf('• updating plugin %s…', $log['context']['pluginKey'])), - 'update.end' => CLI::write( - '✔ ' . sprintf( - '%s updated to version %s%s', - $log['context']['pluginKey'], - $log['context']['version'], - PHP_EOL, - ), - 'light_green', - ), - 'remove.start' => CLI::write(sprintf('• removing plugin %s…', $log['context']['pluginKey'])), - 'remove.end' => CLI::write( - '- ' . sprintf('%s was removed%s', $log['context']['pluginKey'], PHP_EOL), - 'light_red', - ), - default => null, - }; - - if ($level === LogLevel::Warning) { - CLI::write('⚠️ ' . $log['message'], 'light_yellow'); - } - - if ($level === LogLevel::Error) { - CLI::newLine(); - CLI::write(' error ', 'white', 'red'); - CLI::error($log['message']); - CLI::newLine(); - - exit(1); // exit with error, something wrong happened - } - } -} diff --git a/modules/Plugins/Commands/CpmFormatterDebug.php b/modules/Plugins/Commands/CpmFormatterDebug.php deleted file mode 100644 index 417576b1..00000000 --- a/modules/Plugins/Commands/CpmFormatterDebug.php +++ /dev/null @@ -1,42 +0,0 @@ - CLI::write( - sprintf('%s %s', CLI::color($level->name, 'white', 'green'), json_encode( - $log, - JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT, - )), - ), - LogLevel::Warning => CLI::write( - sprintf('%s %s', CLI::color($level->name, 'white', 'yellow'), json_encode( - $log, - JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT, - )), - ), - LogLevel::Error => CLI::write( - sprintf('%s %s', CLI::color($level->name, 'white', 'red'), json_encode( - $log, - JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT, - )), - ), - default => CLI::write( - sprintf('%s %s', CLI::color($level->name, 'white', 'blue'), json_encode( - $log, - JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT, - )), - ), - }; - } -} diff --git a/modules/Plugins/Commands/CreatePlugin.php b/modules/Plugins/Commands/CreatePlugin.php deleted file mode 100644 index c0bcafa0..00000000 --- a/modules/Plugins/Commands/CreatePlugin.php +++ /dev/null @@ -1,153 +0,0 @@ - ['use App\Entities\Podcast;'], - 'rssAfterChannel' => ['use App\Entities\Podcast;', 'use App\Libraries\RssFeed;'], - 'rssBeforeItem' => ['use App\Entities\Episode;'], - 'rssAfterItem' => ['use App\Entities\Episode;', 'use App\Libraries\RssFeed;'], - 'siteHead' => ['use use App\Libraries\HtmlHead'], - ]; - - protected const HOOKS_METHODS = [ - 'rssBeforeChannel' => ' public function rssBeforeChannel(Podcast $podcast): void - { - // YOUR CODE HERE - }', - 'rssAfterChannel' => ' public function rssAfterChannel(Podcast $podcast, RssFeed $channel): void - { - // YOUR CODE HERE - }', - 'rssBeforeItem' => ' public function rssBeforeItem(Episode $episode): void - { - // YOUR CODE HERE - }', - 'rssAfterItem' => ' public function rssAfterItem(Episode $episode, RssFeed $item): void - { - // YOUR CODE HERE - }', - 'siteHead' => ' public function siteHead(HtmlHead $head): void - { - // YOUR CODE HERE - }', - ]; - - /** - * @var string - */ - protected $name = 'plugins:create'; - - /** - * @var string - */ - protected $description = 'Generates a new plugin folder based on a template.'; - - /** - * Actually execute a command. - * - * @param list $params - */ - #[Override] - public function run(array $params): void - { - $pluginName = CLI::prompt( - 'Plugin name (/)', - 'acme/hello-world', - Manifest::$validation_rules['name'], - ); - CLI::newLine(); - $description = CLI::prompt('Description', '', Manifest::$validation_rules['description']); - CLI::newLine(); - $license = CLI::prompt('License', 'UNLICENSED', Manifest::$validation_rules['license']); - CLI::newLine(); - $hooks = CLI::promptByMultipleKeys('Which hooks do you want to implement?', Plugins::HOOKS); - - $nameParts = explode('/', $pluginName); - $vendor = $nameParts[0]; - $name = $nameParts[1]; - - /** @var PluginsConfig $pluginsConfig */ - $pluginsConfig = config('Plugins'); - - // 1. create plugin directory if not existent - $pluginDirectory = $pluginsConfig->folder . $vendor . DIRECTORY_SEPARATOR . $name; - if (! file_exists($pluginDirectory)) { - mkdir($pluginDirectory, 0755, true); - } - - // 2. get contents of templates - $manifestTemplate = file_get_contents(__DIR__ . '/plugin-template/manifest.tpl.json'); - - if (! $manifestTemplate) { - throw new Exception('Failed to get manifest template.'); - } - - $pluginClassTemplate = file_get_contents(__DIR__ . '/plugin-template/Plugin.tpl.php'); - - if (! $pluginClassTemplate) { - throw new Exception('Failed to get Plugin class template.'); - } - - // 3. edit templates' contents - $manifestContents = str_replace('"name": ""', '"name": "' . $pluginName . '"', $manifestTemplate); - $manifestContents = str_replace( - '"description": ""', - '"description": "' . $description . '"', - $manifestContents, - ); - $manifestContents = str_replace('"license": ""', '"license": "' . $license . '"', $manifestContents); - $manifestContents = str_replace( - '"hooks": []', - '"hooks": ["' . implode('", "', $hooks) . '"]', - $manifestContents, - ); - - $pluginClassName = str_replace( - ' ', - '', - ucwords(str_replace(['-', '_', '.'], ' ', $vendor . ' ' . $name)) . 'Plugin', - ); - $pluginClassContents = str_replace('class Plugin', 'class ' . $pluginClassName, $pluginClassTemplate); - - $allImports = []; - $allMethods = []; - foreach ($hooks as $hook) { - $allImports = [...$allImports, ...self::HOOKS_IMPORTS[$hook]]; - $allMethods = [...$allMethods, self::HOOKS_METHODS[$hook]]; - } - - $imports = implode(PHP_EOL, array_unique($allImports)); - $methods = implode(PHP_EOL . PHP_EOL, $allMethods); - $pluginClassContents = str_replace('// IMPORTS_HERE', $imports, $pluginClassContents); - $pluginClassContents = str_replace(' // HOOKS_HERE', $methods, $pluginClassContents); - - $manifest = $pluginDirectory . '/manifest.json'; - $pluginClass = $pluginDirectory . '/Plugin.php'; - - if (! file_put_contents($manifest, $manifestContents)) { - throw new Exception('Failed to create manifest.json file.'); - } - - if (! file_put_contents($pluginClass, $pluginClassContents)) { - throw new Exception('Failed to create Plugin class file.'); - } - - CLI::newLine(1); - CLI::write( - sprintf('Plugin %s created in %s', CLI::color($pluginName, 'white'), CLI::color($pluginDirectory, 'white')), - 'green', - ); - } -} diff --git a/modules/Plugins/Commands/Install.php b/modules/Plugins/Commands/Install.php deleted file mode 100644 index 11c80a03..00000000 --- a/modules/Plugins/Commands/Install.php +++ /dev/null @@ -1,48 +0,0 @@ - $params - */ - #[Override] - public function run(array $params): void - { - parent::run($params); - - /** @var PluginsManager $cpm */ - $cpm = service('cpm'); - - $cpm->installFromPluginsTxt(); - } -} diff --git a/modules/Plugins/Commands/Remove.php b/modules/Plugins/Commands/Remove.php deleted file mode 100644 index 6f54212f..00000000 --- a/modules/Plugins/Commands/Remove.php +++ /dev/null @@ -1,85 +0,0 @@ - - */ - protected $arguments = [ - 'plugins' => 'One or more plugins as vendor/plugin', - ]; - - /** - * @param list $params - */ - #[Override] - public function run(array $params): int - { - parent::run($params); - - /** @var Plugins $plugins */ - $plugins = service('plugins'); - - /** @var PluginsManager $cpm */ - $cpm = service('cpm'); - - /** @var list $errors */ - $errors = []; - foreach ($params as $pluginKey) { - $plugin = $plugins->getPluginByKey($pluginKey); - - if ($plugin === null) { - $errors[] = sprintf('Plugin %s was not found.', $pluginKey); - continue; - } - - if (! $plugins->uninstall($plugin)) { - $errors[] = sprintf('Something happened when removing %s', $pluginKey); - break; - } - - // delete plugin folder - $cpm->remove($pluginKey); - } - - foreach ($errors as $error) { - CLI::write(' error ', 'white', 'red'); - CLI::error($error); - CLI::newLine(); - } - - return $errors === [] ? 0 : 1; - } -} diff --git a/modules/Plugins/Commands/Update.php b/modules/Plugins/Commands/Update.php deleted file mode 100644 index 08836bfe..00000000 --- a/modules/Plugins/Commands/Update.php +++ /dev/null @@ -1,65 +0,0 @@ - - */ - protected $arguments = [ - 'plugin' => 'The pluginKey and an optional version separated by an @. If version is not provided, the latest will be added by default.', - ]; - - /** - * Actually execute a command. - * - * @param array $params - * - * @return int|void - */ - #[Override] - public function run(array $params) - { - parent::run($params); - - if ($params === []) { - CLI::error('Missing pluginKey argument.'); - return 1; - } - - /** @var PluginsManager $cpm */ - $cpm = service('cpm'); - - $cpm->update($params[0]); - } -} diff --git a/modules/Plugins/Commands/plugin-template/Plugin.tpl.php b/modules/Plugins/Commands/plugin-template/Plugin.tpl.php deleted file mode 100644 index edf615e5..00000000 --- a/modules/Plugins/Commands/plugin-template/Plugin.tpl.php +++ /dev/null @@ -1,11 +0,0 @@ -group( - config('Admin') - ->gateway, - [ - 'namespace' => 'Modules\Plugins\Controllers', - ], - static function ($routes): void { - $routes->group('plugins', static function ($routes): void { - $routes->get('/', 'PluginController::installed', [ - 'as' => 'plugins-installed', - 'filter' => 'permission:plugins.manage', - ]); - $routes->get('(:segment)', 'PluginController::vendor/$1', [ - 'as' => 'plugins-vendor', - 'filter' => 'permission:plugins.manage', - ]); - $routes->group('(:segment)/(:segment)', static function ($routes): void { - $routes->get('/', 'PluginController::view/$1/$2', [ - 'as' => 'plugins-view', - 'filter' => 'permission:plugins.manage', - ]); - $routes->get('settings', 'PluginController::settingsView/$1/$2', [ - 'as' => 'plugins-settings-general', - 'filter' => 'permission:plugins.manage', - ]); - $routes->post('settings', 'PluginController::settingsAction/$1/$2', [ - 'as' => 'plugins-settings-general-action', - 'filter' => 'permission:plugins.manage', - ]); - $routes->get('(:num)', 'PluginController::settingsView/$1/$2/$3', [ - 'as' => 'plugins-settings-podcast', - 'filter' => 'permission:podcast$3.edit', - ]); - $routes->post('(:num)', 'PluginController::settingsAction/$1/$2/$3', [ - 'as' => 'plugins-settings-podcast-action', - 'filter' => 'permission:podcast$3.edit', - ]); - $routes->get('(:num)/(:num)', 'PluginController::settingsView/$1/$2/$3/$4', [ - 'as' => 'plugins-settings-episode', - 'filter' => 'permission:podcast$3.episodes.edit', - ]); - $routes->post('(:num)/(:num)', 'PluginController::settingsAction/$1/$2/$3/$4', [ - 'as' => 'plugins-settings-episode-action', - 'filter' => 'permission:podcast$3.episodes.edit', - ]); - $routes->post('activate', 'PluginController::activate/$1/$2', [ - 'as' => 'plugins-activate', - 'filter' => 'permission:plugins.manage', - ]); - $routes->post('deactivate', 'PluginController::deactivate/$1/$2', [ - 'as' => 'plugins-deactivate', - 'filter' => 'permission:plugins.manage', - ]); - $routes->get('uninstall', 'PluginController::uninstall/$1/$2', [ - 'as' => 'plugins-uninstall', - 'filter' => 'permission:plugins.manage', - ]); - }); - }); - }, -); diff --git a/modules/Plugins/Config/Services.php b/modules/Plugins/Config/Services.php deleted file mode 100644 index ea91b4d7..00000000 --- a/modules/Plugins/Config/Services.php +++ /dev/null @@ -1,37 +0,0 @@ -repositoryUrl, WRITEPATH, $config->folder, WRITEPATH . 'temp'); - } -} diff --git a/modules/Plugins/Controllers/PluginController.php b/modules/Plugins/Controllers/PluginController.php deleted file mode 100644 index 2028cdec..00000000 --- a/modules/Plugins/Controllers/PluginController.php +++ /dev/null @@ -1,362 +0,0 @@ -plugins = service('plugins'); - } - - public function installed(): string - { - $pager = service('pager'); - - $page = (int) ($this->request->getGet('page') ?? 1); - $perPage = 10; - $total = $this->plugins->getInstalledCount(); - - $pager_links = $pager->makeLinks($page, $perPage, $total); - - $this->setHtmlHead(lang('Plugins.installed')); - return view('plugins/installed', [ - 'total' => $total, - 'plugins' => $this->plugins->getPlugins($page, $perPage), - 'pager_links' => $pager_links, - ]); - } - - public function vendor(string $vendor): string - { - $vendorPlugins = $this->plugins->getVendorPlugins($vendor); - - $this->setHtmlHead(lang('Plugins.installed')); - replace_breadcrumb_params([ - $vendor => $vendor, - ]); - return view('plugins/installed', [ - 'total' => count($vendorPlugins), - 'plugins' => $vendorPlugins, - 'pager_links' => '', - ]); - } - - public function view(string $vendor, string $package): string - { - - $plugin = $this->plugins->getPlugin($vendor, $package); - - if (! $plugin instanceof BasePlugin) { - throw PageNotFoundException::forPageNotFound(); - } - - $this->setHtmlHead($plugin->getTitle()); - replace_breadcrumb_params([ - $vendor => $vendor, - $package => $package, - ]); - return view('plugins/view', [ - 'plugin' => $plugin, - ]); - } - - public function settingsView( - string $vendor, - string $package, - ?string $podcastId = null, - ?string $episodeId = null, - ): string { - - $plugin = $this->plugins->getPlugin($vendor, $package); - - if (! $plugin instanceof BasePlugin) { - throw PageNotFoundException::forPageNotFound(); - } - - $type = 'general'; - $context = null; - $breadcrumbReplacements = [ - $vendor => $vendor, - $package => $package, - ]; - $data = [ - 'plugin' => $plugin, - ]; - - if ($podcastId !== null) { - $podcast = new PodcastModel() - ->getPodcastById((int) $podcastId); - - if (! $podcast instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - $type = 'podcast'; - $context = ['podcast', (int) $podcastId]; - $breadcrumbReplacements[0] = $podcast->handle; - $data['podcast'] = $podcast; - } - - if ($episodeId !== null) { - $episode = new EpisodeModel() - ->getEpisodeById((int) $episodeId); - - if (! $episode instanceof Episode) { - throw PageNotFoundException::forPageNotFound(); - } - - $type = 'episode'; - $context = ['episode', (int) $episodeId]; - $breadcrumbReplacements[1] = $episode->title; - $data['episode'] = $episode; - } - - $fields = $plugin->getSettingsFields($type); - - if ($fields === []) { - throw PageNotFoundException::forPageNotFound(); - } - - $data['type'] = $type; - $data['context'] = $context; - $data['fields'] = $fields; - - helper('form'); - $this->setHtmlHead(lang('Plugins.settingsTitle', [ - 'pluginTitle' => $plugin->getTitle(), - 'type' => $type, - ])); - replace_breadcrumb_params($breadcrumbReplacements); - return view('plugins/settings', $data); - } - - public function settingsAction( - string $vendor, - string $package, - ?string $podcastId = null, - ?string $episodeId = null, - ): RedirectResponse { - $plugin = $this->plugins->getPlugin($vendor, $package); - - if (! $plugin instanceof BasePlugin) { - throw PageNotFoundException::forPageNotFound(); - } - - $type = 'general'; - $context = null; - if ($podcastId !== null) { - $type = 'podcast'; - $context = ['podcast', (int) $podcastId]; - } - - if ($episodeId !== null) { - $type = 'episode'; - $context = ['episode', (int) $episodeId]; - } - - // construct validation rules first - $rules = []; - foreach ($plugin->getSettingsFields($type) as $field) { - $typeRules = $this->plugins::FIELDS_VALIDATIONS[$field->type]; - if (! in_array('permit_empty', $typeRules, true)) { - $typeRules[] = $field->optional ? 'permit_empty' : 'required'; - } - - if ($field->multiple) { - if ($field instanceof Group) { - foreach ($field->fields as $subField) { - $typeRules = $this->plugins::FIELDS_VALIDATIONS[$subField->type]; - if (! in_array('permit_empty', $typeRules, true)) { - $typeRules[] = $subField->optional ? 'permit_empty' : 'required'; - } - - $rules[sprintf('%s.*.%s', $field->key, $subField->key)] = [ - ...$typeRules, - ...$subField->validationRules, - ]; - } - } else { - $rules[$field->key . '.*'] = [...$typeRules, ...$field->validationRules]; - } - } elseif ($field instanceof Group) { - foreach ($field->fields as $subField) { - $typeRules = $this->plugins::FIELDS_VALIDATIONS[$subField->type]; - if (! in_array('permit_empty', $typeRules, true)) { - $typeRules[] = $subField->optional ? 'permit_empty' : 'required'; - } - - $rules[sprintf('%s.%s', $field->key, $subField->key)] = [ - ...$typeRules, - ...$subField->validationRules, - ]; - } - } else { - $rules[$field->key] = [...$typeRules, ...$field->validationRules]; - } - } - - if (! $this->validate($rules)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $this->validator->getErrors()); - } - - $validatedData = $this->validator->getValidated(); - - foreach ($plugin->getSettingsFields($type) as $field) { - $fieldValue = $validatedData[$field->key] ?? null; - - $this->plugins->setOption($plugin, $field->key, $this->castFieldValue($field, $fieldValue), $context); - } - - // clear cache after setting options - $plugin->clearCache(); - - return redirect()->back() - ->with('message', lang('Plugins.messages.saveSettingsSuccess', [ - 'pluginTitle' => $plugin->getTitle(), - ])); - } - - public function activate(string $vendor, string $package): RedirectResponse - { - - $plugin = $this->plugins->getPlugin($vendor, $package); - - if (! $plugin instanceof BasePlugin) { - throw PageNotFoundException::forPageNotFound(); - } - - $this->plugins->activate($plugin); - - // clear cache after activation - $plugin->clearCache(); - - return redirect()->back(); - } - - public function deactivate(string $vendor, string $package): RedirectResponse - { - - $plugin = $this->plugins->getPlugin($vendor, $package); - - if (! $plugin instanceof BasePlugin) { - throw PageNotFoundException::forPageNotFound(); - } - - $this->plugins->deactivate($plugin); - - // clear cache after deactivation - $plugin->clearCache(); - - return redirect()->back(); - } - - public function uninstall(string $vendor, string $package): RedirectResponse - { - - $plugin = $this->plugins->getPlugin($vendor, $package); - - if (! $plugin instanceof BasePlugin) { - throw PageNotFoundException::forPageNotFound(); - } - - $this->plugins->uninstall($plugin); - - return redirect()->back(); - } - - private function castFieldValue(Field $field, mixed $fieldValue): mixed - { - if ($fieldValue === '' || $fieldValue === null) { - return null; - } - - $value = null; - if ($field->multiple) { - $value = []; - foreach ($fieldValue as $key => $val) { - if ($val === '') { - continue; - } - - if ($field instanceof Group) { - foreach ($val as $subKey => $subVal) { - /** @var Field|false $subField */ - $subField = array_column($field->fields, null, 'key')[$subKey] ?? false; - if (! $subField) { - continue; - } - - $v = $this->castValue($subVal, $subField->type); - if ($v) { - $value[$key][$subKey] = $v; - } - } - } else { - $value[$key] = $this->castValue($val, $field->type); - } - } - } elseif ($field instanceof Group) { - foreach ($fieldValue as $subKey => $subVal) { - /** @var Field|false $subField */ - $subField = array_column($field->fields, null, 'key')[$subKey] ?? false; - if (! $subField) { - continue; - } - - $v = $this->castValue($subVal, $subField->type); - if ($v) { - $value[$subKey] = $v; - } - } - } else { - $value = $this->castValue($fieldValue, $field->type); - } - - return $value === [] ? null : $value; - } - - private function castValue(mixed $value, string $type): mixed - { - if ($value === '' || $value === null) { - return null; - } - - return match ($this->plugins::FIELDS_CASTS[$type] ?? 'text') { - 'bool' => $value === 'yes', - 'int' => (int) $value, - 'uri' => new URI($value), - 'datetime' => Time::createFromFormat( - 'Y-m-d H:i', - $value, - $this->request->getPost('client_timezone'), - )->setTimezone(app_timezone()), - 'markdown' => new Markdown($value), - 'rss' => new RSS($value), - default => $value, - }; - } -} diff --git a/modules/Plugins/Core/BasePlugin.php b/modules/Plugins/Core/BasePlugin.php deleted file mode 100644 index 995fa272..00000000 --- a/modules/Plugins/Core/BasePlugin.php +++ /dev/null @@ -1,389 +0,0 @@ -key = sprintf('%s/%s', $vendor, $package); - - // TODO: cache manifest data - $manifestPath = $directory . '/manifest.json'; - - $this->manifest = new Manifest($this->key); - $this->manifest->loadFromFile($manifestPath); - - // check compatibility with Castopod version - if ($this->manifest->minCastopodVersion !== null && version_compare( - CP_VERSION, - $this->manifest->minCastopodVersion, - '<', - )) { - $this->status = PluginStatus::INCOMPATIBLE; - } else { - $this->status = get_plugin_setting($this->key, 'active') ? PluginStatus::ACTIVE : PluginStatus::INACTIVE; - } - - $this->iconSrc = $this->loadIcon($directory . '/icon.svg'); - - $this->readmeHTML = $this->loadMarkdownAsHTML($directory . '/README.md'); - - $this->licenseHTML = $this->loadMarkdownAsHTML($directory . '/LICENSE.md'); - } - - /** - * @param list|string $value - */ - public function __set(string $name, array|string $value): void - { - $this->{$name} = $value; - } - - #[Override] - public function rssBeforeChannel(Podcast $podcast): void - { - } - - #[Override] - public function rssAfterChannel(Podcast $podcast, RssFeed $channel): void - { - } - - #[Override] - public function rssBeforeItem(Episode $episode): void - { - } - - #[Override] - public function rssAfterItem(Episode $episode, RssFeed $item): void - { - } - - #[Override] - public function siteHead(HtmlHead $head): void - { - } - - final public function getGeneralSetting(string $key): mixed - { - return get_plugin_setting($this->key, $key); - } - - final public function getPodcastSetting(int $podcastId, string $key): mixed - { - return get_plugin_setting($this->key, $key, ['podcast', $podcastId]); - } - - final public function getEpisodeSetting(int $episodeId, string $key): mixed - { - return get_plugin_setting($this->key, $key, ['episode', $episodeId]); - } - - final public function clearCache(): void - { - foreach ($this->getHooks() as $hook) { - foreach (Plugins::CACHE_MAP[$hook] ?? [] as $cacheGlob) { - cache()->deleteMatching($cacheGlob); - } - } - } - - /** - * @return bool true on success, false on failure - */ - final public function activate(): bool - { - if ($this->status === PluginStatus::ACTIVE) { - return false; - } - - $this->setStatus(PluginStatus::ACTIVE); - - if ($this->status === PluginStatus::INACTIVE) { - return false; - } - - set_plugin_setting($this->key, 'active', true); - return true; - } - - final public function deactivate(): bool - { - if ($this->status !== PluginStatus::ACTIVE) { - return false; - } - - $this->setStatus(PluginStatus::INACTIVE); - set_plugin_setting($this->key, 'active', false); - - return true; - } - - final public function getStatus(): PluginStatus - { - return $this->status; - } - - final public function getDirectory(): string - { - return $this->directory; - } - - /** - * @return array - */ - final public function getManifestErrors(): array - { - return Manifest::getPluginErrors($this->key); - } - - final public function isHookDeclared(string $name): bool - { - return in_array($name, $this->manifest->hooks, true); - } - - final public function getVersion(): string - { - return $this->manifest->version; - } - - final public function getHomepage(): ?URI - { - return $this->manifest->homepage; - } - - final public function getRepository(): ?Repository - { - return $this->manifest->repository; - } - - /** - * @return list - */ - final public function getKeywords(): array - { - return $this->manifest->keywords; - } - - /** - * @return Person[] - */ - final public function getAuthors(): array - { - return $this->manifest->authors; - } - - final public function getIconSrc(): string - { - return $this->iconSrc; - } - - /** - * @return Field[] - */ - final public function getSettingsFields(string $type): array - { - $settings = $this->manifest->settings; - if (! $settings instanceof Settings) { - return []; - } - - return $settings->{$type}; - } - - final public function getMinCastopodVersion(): string - { - return $this->manifest->minCastopodVersion ?? ''; - } - - /** - * @return list - */ - final public function getHooks(): array - { - return $this->manifest->hooks; - } - - final public function getKey(): string - { - return $this->key; - } - - final public function getVendor(): string - { - return $this->vendor; - } - - final public function getPackage(): string - { - return $this->package; - } - - final public function getTitle(): string - { - $key = sprintf('Plugin.%s.title', $this->key); - /** @var string $title */ - $title = lang($key); - - if ($title === $key) { - return $this->manifest->name; - } - - return $title; - } - - final public function getDescription(): string - { - $key = sprintf('Plugin.%s.description', $this->key); - - /** @var string $description */ - $description = lang($key); - - if ($description === $key) { - return esc($this->manifest->description); - } - - return $description; - } - - final public function getReadmeHTML(): ?string - { - return $this->readmeHTML; - } - - final public function getLicense(): string - { - return $this->manifest->license ?? 'UNLICENSED'; - } - - final public function getLicenseHTML(): ?string - { - return $this->licenseHTML; - } - - /** - * @param PluginStatus::ACTIVE|PluginStatus::INACTIVE $value - */ - final protected function setStatus(PluginStatus $value): self - { - if ($this->getManifestErrors() !== []) { - $this->status = PluginStatus::INVALID; - - return $this; - } - - $this->status = $value; - - return $this; - } - - final protected function getOption(string $option): mixed - { - return get_plugin_setting($this->key, $option); - } - - final protected function setOption(string $option, mixed $value = null): void - { - set_plugin_setting($this->key, $option, $value); - } - - private function loadIcon(string $path): string - { - // TODO: cache icon - $svgIcon = @file_get_contents($path); - - if (! $svgIcon) { - return "data:image/svg+xml;utf8,%3Csvg xmlns='http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' viewBox='0 0 64 64'%3E%3Cpath fill='%2300564A' d='M0 0h64v64H0z'%2F%3E%3Cpath fill='%23E7F9E4' d='M25.3 18.7a5 5 0 1 1 9.7 1.6h7c1 0 1.7.8 1.7 1.7v7a5 5 0 1 1 0 9.4v7c0 .9-.8 1.6-1.7 1.6H18.7c-1 0-1.7-.7-1.7-1.7V22c0-1 .7-1.7 1.7-1.7h7a5 5 0 0 1-.4-1.6Z'%2F%3E%3C%2Fsvg%3E"; - } - - $encodedIcon = rawurlencode(str_replace(["\r", "\n"], ' ', $svgIcon)); - return 'data:image/svg+xml;utf8,' . str_replace( - ['%20', '%22', '%27', '%3D'], - [' ', "'", "'", '='], - $encodedIcon, - ); - } - - private function loadMarkdownAsHTML(string $path): ?string - { - // TODO: cache readme - $readmeMD = @file_get_contents($path); - - if (! $readmeMD) { - return null; - } - - $environment = new Environment([ - 'html_input' => 'escape', - 'allow_unsafe_links' => false, - 'host' => new URI(base_url()) - ->getHost(), - ]); - $environment->addExtension(new CommonMarkCoreExtension()); - - $environment->addExtension(new GithubFlavoredMarkdownExtension()); - $environment->addExtension(new SmartPunctExtension()); - - $environment->addEventListener( - DocumentParsedEvent::class, - static function (DocumentParsedEvent $event): void { - new ExternalLinkProcessor() - ->onDocumentParsed($event); - }, - ); - $environment->addEventListener( - DocumentParsedEvent::class, - static function (DocumentParsedEvent $event): void { - new ExternalImageProcessor() - ->onDocumentParsed($event); - }, - ); - - $converter = new MarkdownConverter($environment); - - return $converter->convert($readmeMD) - ->getContent(); - } -} diff --git a/modules/Plugins/Core/Markdown.php b/modules/Plugins/Core/Markdown.php deleted file mode 100644 index 2e6b1af7..00000000 --- a/modules/Plugins/Core/Markdown.php +++ /dev/null @@ -1,46 +0,0 @@ -markdown; - } - - public function renderHTML(): string - { - $config = [ - 'html_input' => 'escape', - 'allow_unsafe_links' => false, - ]; - - $environment = new Environment($config); - $environment->addExtension(new CommonMarkCoreExtension()); - $environment->addExtension(new AutolinkExtension()); - $environment->addExtension(new SmartPunctExtension()); - $environment->addExtension(new DisallowedRawHtmlExtension()); - - $converter = new MarkdownConverter($environment); - - return (string) $converter->convert($this->markdown); - } -} diff --git a/modules/Plugins/Core/PluginInterface.php b/modules/Plugins/Core/PluginInterface.php deleted file mode 100644 index bd30aad5..00000000 --- a/modules/Plugins/Core/PluginInterface.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ - public const HOOKS = ['rssBeforeChannel', 'rssAfterChannel', 'rssBeforeItem', 'rssAfterItem', 'siteHead']; - - public const CACHE_MAP = [ - 'rssBeforeChannel' => ['podcast*feed*'], - 'rssAfterChannel' => ['podcast*feed*'], - 'rssBeforeItem' => ['podcast*feed*'], - 'rssAfterItem' => ['podcast*feed*'], - 'siteHead' => ['page*'], - ]; - - public const FIELDS_VALIDATIONS = [ - 'checkbox' => ['permit_empty'], - 'datetime' => ['valid_date[Y-m-d H:i]'], - 'email' => ['valid_email'], - 'group' => ['permit_empty', 'is_list'], - 'html' => ['string'], - 'markdown' => ['string'], - 'number' => ['integer'], - 'radio-group' => ['string'], - 'rss' => ['string'], - 'select' => ['string'], - 'select-multiple' => ['permit_empty', 'is_list'], - 'text' => ['string'], - 'textarea' => ['string'], - 'toggler' => ['permit_empty'], - 'url' => ['valid_url_strict'], - ]; - - public const FIELDS_CASTS = [ - 'checkbox' => 'bool', - 'datetime' => 'datetime', - 'markdown' => 'markdown', - 'number' => 'int', - 'rss' => 'rss', - 'toggler' => 'bool', - 'url' => 'uri', - ]; - - /** - * @var array - */ - protected static array $plugins = []; - - /** - * @var array - */ - protected static array $pluginsByVendor = []; - - protected static int $installedCount = 0; - - protected static int $activeCount = 0; - - public function __construct( - protected PluginsConfig $config, - ) { - helper('plugins'); - - $this->registerPlugins(); - } - - /** - * @param value-of $name - * @param array $arguments - */ - public function __call(string $name, array $arguments): void - { - if (! in_array($name, static::HOOKS, true)) { - return; - } - - $this->runHook($name, $arguments); - } - - /** - * @return array - */ - public function getPlugins(int $page = 1, int $perPage = 12): array - { - return array_slice(static::$plugins, (($page - 1) * $perPage), $perPage); - } - - /** - * @return array - */ - public function getAllPlugins(): array - { - return static::$plugins; - } - - /** - * @return array - */ - public function getActivePlugins(): array - { - $activePlugins = []; - foreach (static::$plugins as $plugin) { - if ($plugin->getStatus() === PluginStatus::ACTIVE) { - $activePlugins[] = $plugin; - } - } - - return $activePlugins; - } - - /** - * @return array - */ - public function getPluginsWithPodcastSettings(): array - { - $pluginsWithPodcastSettings = []; - foreach (static::$plugins as $plugin) { - if ($plugin->getStatus() !== PluginStatus::ACTIVE) { - continue; - } - - if ($plugin->getSettingsFields('podcast') === []) { - continue; - } - - $pluginsWithPodcastSettings[] = $plugin; - } - - return $pluginsWithPodcastSettings; - } - - /** - * @return array - */ - public function getPluginsWithEpisodeSettings(): array - { - $pluginsWithEpisodeSettings = []; - foreach (static::$plugins as $plugin) { - if ($plugin->getStatus() !== PluginStatus::ACTIVE) { - continue; - } - - if ($plugin->getSettingsFields('episode') === []) { - continue; - } - - $pluginsWithEpisodeSettings[] = $plugin; - } - - return $pluginsWithEpisodeSettings; - } - - /** - * @return array - */ - public function getVendorPlugins(string $vendor): array - { - return static::$pluginsByVendor[$vendor] ?? []; - } - - public function getPlugin(string $vendor, string $package): ?BasePlugin - { - foreach ($this->getVendorPlugins($vendor) as $plugin) { - if ($plugin->getPackage() === $package) { - return $plugin; - } - } - - return null; - } - - public function getPluginByKey(string $key): ?BasePlugin - { - if (! str_contains($key, '/')) { - return null; - } - - $keyArray = explode('/', $key); - return $this->getPlugin($keyArray[0], $keyArray[1]); - } - - /** - * @param value-of $name - * @param array $arguments - */ - public function runHook(string $name, array $arguments): void - { - foreach (static::$plugins as $plugin) { - // only run hook on active plugins - if ($plugin->getStatus() !== PluginStatus::ACTIVE) { - continue; - } - - if (! $plugin->isHookDeclared($name)) { - continue; - } - - $plugin->{$name}(...$arguments); - } - } - - public function activate(BasePlugin $plugin): void - { - if ($plugin->activate()) { - ++self::$activeCount; - } - } - - public function deactivate(BasePlugin $plugin): void - { - if ($plugin->deactivate()) { - --self::$activeCount; - } - } - - /** - * @param ?array{'podcast'|'episode',int} $additionalContext - */ - public function setOption(BasePlugin $plugin, string $name, mixed $value, ?array $additionalContext = null): void - { - set_plugin_setting($plugin->getKey(), $name, $value, $additionalContext); - } - - public function getInstalledCount(): int - { - return static::$installedCount; - } - - public function getActiveCount(): int - { - return static::$activeCount; - } - - public function uninstall(BasePlugin $plugin): bool - { - // remove all settings data - $db = Database::connect(); - $builder = $db->table('settings'); - - $db->transStart(); - $builder->where('class', self::class); - $builder->like('context', sprintf('plugin:%s', $plugin->getKey() . '%')); - - if (! $builder->delete()) { - $db->transRollback(); - return false; - } - - return $db->transCommit(); - } - - protected function registerPlugins(): void - { - // search for plugins in plugins folder - $pluginsDirectories = glob($this->config->folder . '*/*', GLOB_ONLYDIR); - - if ($pluginsDirectories === false || $pluginsDirectories === []) { - return; - } - - foreach ($pluginsDirectories as $pluginDirectory) { - $vendor = basename(dirname($pluginDirectory)); - $package = basename($pluginDirectory); - - if (preg_match('~' . PLUGINS_KEY_PATTERN . '~', $vendor . '/' . $package) === false) { - continue; - } - - $className = str_replace( - ' ', - '', - ucwords(str_replace(['-', '_', '.'], ' ', $vendor . ' ' . $package)) . 'Plugin', - ); - - $pluginFile = $pluginDirectory . DIRECTORY_SEPARATOR . 'Plugin.php'; - spl_autoload_register(static function ($class) use (&$className, &$pluginFile): void { - if ($class !== $className) { - return; - } - - if (! file_exists($pluginFile)) { - return; - } - - include_once $pluginFile; - }, true); - - if (! class_exists($className)) { - continue; - } - - $plugin = new $className($vendor, $package, $pluginDirectory); - if (! $plugin instanceof BasePlugin) { - continue; - } - - static::$plugins[] = $plugin; - static::$pluginsByVendor[$vendor][] = $plugin; - ++static::$installedCount; - - if ($plugin->getStatus() === PluginStatus::ACTIVE) { - ++static::$activeCount; - } - } - } -} diff --git a/modules/Plugins/Core/RSS.php b/modules/Plugins/Core/RSS.php deleted file mode 100644 index 36a96fe7..00000000 --- a/modules/Plugins/Core/RSS.php +++ /dev/null @@ -1,43 +0,0 @@ -rss; - } - - /** - * @return ?RssFeed[] - */ - public function toSimpleRSS(): ?array - { - try { - $rssFeed = new RssFeed("{$this->rss}"); - } catch (Exception) { - return null; - } - - return [ - ...$rssFeed->children(), - ...$rssFeed->children(RssFeed::ATOM_NS, true), - ...$rssFeed->children(RssFeed::ITUNES_NS, true), - ...$rssFeed->children(RssFeed::PODCAST_NS, true), - ]; - } -} diff --git a/modules/Plugins/ExternalImageProcessor.php b/modules/Plugins/ExternalImageProcessor.php deleted file mode 100644 index f5947aa3..00000000 --- a/modules/Plugins/ExternalImageProcessor.php +++ /dev/null @@ -1,45 +0,0 @@ -getDocument(); - $walker = $document->walker(); - while ($event = $walker->next()) { - $node = $event->getNode(); - - // Only stop at Link nodes when we first encounter them - if (! ($node instanceof Image) || ! $event->isEntering()) { - continue; - } - - $url = $node->getUrl(); - if ($this->isUrlExternal($url)) { - $node->detach(); - } - } - } - - private function isUrlExternal(string $url): bool - { - // Only look at http and https URLs - if (! preg_match('/^https?:\/\//', $url)) { - return false; - } - - $host = parse_url($url, PHP_URL_HOST); - - // TODO: load from environment's config - return $host !== new URI(base_url()) - ->getHost(); - } -} diff --git a/modules/Plugins/ExternalLinkProcessor.php b/modules/Plugins/ExternalLinkProcessor.php deleted file mode 100644 index 0297609c..00000000 --- a/modules/Plugins/ExternalLinkProcessor.php +++ /dev/null @@ -1,46 +0,0 @@ -getDocument(); - $walker = $document->walker(); - while ($event = $walker->next()) { - $node = $event->getNode(); - - // Only stop at Link nodes when we first encounter them - if (! ($node instanceof Link) || ! $event->isEntering()) { - continue; - } - - $url = $node->getUrl(); - if ($this->isUrlExternal($url)) { - $node->data->append('attributes/target', '_blank'); - $node->data->append('attributes/rel', 'noopener noreferrer'); - } - } - } - - private function isUrlExternal(string $url): bool - { - // Only look at http and https URLs - if (! preg_match('/^https?:\/\//', $url)) { - return false; - } - - $host = parse_url($url, PHP_URL_HOST); - - // TODO: load from environment's config - return $host !== new URI(base_url()) - ->getHost(); - } -} diff --git a/modules/Plugins/Helpers/plugins_helper.php b/modules/Plugins/Helpers/plugins_helper.php deleted file mode 100644 index 3a2c926d..00000000 --- a/modules/Plugins/Helpers/plugins_helper.php +++ /dev/null @@ -1,83 +0,0 @@ -get($key, $context); - } -} - -if (! function_exists('set_plugin_setting')) { - /** - * @param ?array{'podcast'|'episode',int} $additionalContext - */ - function set_plugin_setting( - string $pluginKey, - string $option, - mixed $value = null, - ?array $additionalContext = null, - ): void { - $key = sprintf('Plugins.%s', $option); - $context = sprintf('plugin:%s', $pluginKey); - - if ($additionalContext !== null) { - $context .= sprintf('+%s:%d', ...$additionalContext); - } - - setting() - ->set($key, $value, $context); - } -} - -if (! function_exists('load_plugins_translations')) { - /** - * @return array - */ - function load_plugins_translations(string $locale): array - { - $allPlugins = plugins() - ->getAllPlugins(); - - $translations = []; - foreach ($allPlugins as $plugin) { - $file = $plugin->getDirectory() . DIRECTORY_SEPARATOR . 'i18n' . DIRECTORY_SEPARATOR . $locale . '.json'; - - $jsonContents = @file_get_contents($file); - - if (! $jsonContents) { - continue; - } - - $contents = json_decode($jsonContents, true); - - if (! $contents) { - continue; - } - - $translations[$plugin->getKey()] = $contents; - } - - return $translations; - } -} diff --git a/modules/Plugins/Language/br/Plugin.php b/modules/Plugins/Language/br/Plugin.php deleted file mode 100644 index 36a992fa..00000000 --- a/modules/Plugins/Language/br/Plugin.php +++ /dev/null @@ -1,8 +0,0 @@ - 'Plugins installed', - 'about' => 'About', - 'website' => 'Website', - 'repository' => 'Code repository', - 'authors' => 'Authors', - 'author_email' => 'Email {authorName}', - 'author_homepage' => '{authorName} homepage', - 'declaredHooks' => 'Declared hooks', - 'settings' => 'Settings', - 'settingsTitle' => '{type, select, - podcast {{pluginTitle} podcast settings} - episode {{pluginTitle} episode settings} - other {{pluginTitle} general settings} - }', - 'view' => 'View', - 'activate' => 'Activate', - 'deactivate' => 'Deactivate', - 'active' => 'Active', - 'inactive' => 'Inactive', - 'invalid' => 'Invalid', - 'incompatible' => 'Incompatible', - 'incompatible_hint' => 'Plugin requires Castopod v{minCastopodVersion} minimum.', - 'uninstall' => 'Uninstall', - 'keywords' => [ - 'podcasting20' => 'Podcasting 2.0', - 'seo' => 'SEO', - 'analytics' => 'Analytics', - 'accessibility' => 'Accessibility', - ], - 'noDescription' => 'No description', - 'noReadme' => 'No README file found.', - 'messages' => [ - 'saveSettingsSuccess' => '{pluginTitle} settings were successfully saved!', - ], - 'errors' => [ - 'manifestError' => 'Plugin manifest has errors', - 'manifestMissing' => 'Plugin manifest "{manifestPath}" is missing.', - 'manifestJsonInvalid' => 'Plugin manifest "{manifestPath}" is not a valid JSON.', - ], -]; diff --git a/modules/Plugins/Language/es/Plugin.php b/modules/Plugins/Language/es/Plugin.php deleted file mode 100644 index 36a992fa..00000000 --- a/modules/Plugins/Language/es/Plugin.php +++ /dev/null @@ -1,8 +0,0 @@ - 'permit_empty|in_list[checkbox,datetime,email,group,html,markdown,number,radio-group,rss,select-multiple,select,text,textarea,toggler,url]', - 'key' => 'required|alpha_dash', - 'label' => 'required|string', - 'hint' => 'permit_empty|string', - 'helper' => 'permit_empty|string', - 'validationRules' => 'permit_empty|is_string_or_list', - 'optional' => 'permit_empty|is_boolean', - 'multiple' => 'permit_empty|is_boolean', - ]; - - protected string $type = 'text'; - - protected string $key; - - protected string $label; - - protected string $hint = ''; - - protected string $helper = ''; - - /** - * @var string[] - */ - protected array $validationRules = []; - - protected bool $optional = false; - - protected bool $multiple = false; - - public function getLabel(): string - { - return $this->getTranslated('label'); - } - - public function getHint(): string - { - return $this->getTranslated('hint'); - } - - public function getHelper(): string - { - return $this->getTranslated('helper'); - } - - /** - * @param string|list $values - */ - public function setValidationRules(string|array $values): void - { - $validationRules = []; - if (is_string($values)) { - $validationRules = explode('|', $values); - } - - $allowedRules = [ - 'alpha', - 'alpha_dash', - 'alpha_numeric', - 'alpha_numeric_punct', - 'alpha_numeric_space', - 'alpha_space', - 'decimal', - 'differs', - 'exact_length', - 'greater_than', - 'greater_than_equal_to', - 'hex', - 'in_list', - 'integer', - 'is_natural', - 'is_natural_no_zero', - 'less_than', - 'less_than_equal_to', - 'max_length', - 'min_length', - 'not_in_list', - 'regex_match', - 'valid_base64', - 'valid_date', - ]; - foreach ($validationRules as $rule) { - foreach ($allowedRules as $allowedRule) { - if (str_starts_with($rule, $allowedRule)) { - $this->validationRules[] = $rule; - } - } - } - } - - public function render(string $name, mixed $value, string $class = ''): string - { - throw new RuntimeException('Render function not defined in parent Field class'); - } - - private function getTranslated(string $property): string - { - $key = sprintf('Plugin.%s.settings.%s.%s.%s', $this->pluginKey, $this->type, $this->key, $property); - - /** @var string $i18nField */ - $i18nField = lang($key); - - if ($this->{$property} === '' || $i18nField === $key) { - return esc($this->{$property}); - } - - return esc($i18nField); - } -} diff --git a/modules/Plugins/Manifest/FieldInterface.php b/modules/Plugins/Manifest/FieldInterface.php deleted file mode 100644 index 2fcbaa23..00000000 --- a/modules/Plugins/Manifest/FieldInterface.php +++ /dev/null @@ -1,10 +0,0 @@ - 'permit_empty|is_boolean', - ]; - - protected bool $defaultValue = false; - - public function render(string $name, mixed $value, string $class = ''): string - { - $value = $value ? 'yes' : ''; - return <<{$this->label} - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Datetime.php b/modules/Plugins/Manifest/Fields/Datetime.php deleted file mode 100644 index d7a5826f..00000000 --- a/modules/Plugins/Manifest/Fields/Datetime.php +++ /dev/null @@ -1,37 +0,0 @@ - 'permit_empty|valid_date', - ]; - - protected string $defaultValue = ''; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Email.php b/modules/Plugins/Manifest/Fields/Email.php deleted file mode 100644 index 50f215f0..00000000 --- a/modules/Plugins/Manifest/Fields/Email.php +++ /dev/null @@ -1,38 +0,0 @@ - 'permit_empty|valid_email', - ]; - - protected string $defaultValue = ''; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Group.php b/modules/Plugins/Manifest/Fields/Group.php deleted file mode 100644 index 2cb89f7d..00000000 --- a/modules/Plugins/Manifest/Fields/Group.php +++ /dev/null @@ -1,36 +0,0 @@ -injectRules(); - - parent::__construct($pluginKey); - } - - #[Override] - public function loadData(array $data): void - { - $data = $this->transformData($data); - - parent::loadData($data); - } - - public function render(string $name, mixed $value, string $class = ''): string - { - // TODO: render group, depending on multiple - throw new RuntimeException('Render function not defined in Group Field class'); - } -} diff --git a/modules/Plugins/Manifest/Fields/Html.php b/modules/Plugins/Manifest/Fields/Html.php deleted file mode 100644 index f5f112cd..00000000 --- a/modules/Plugins/Manifest/Fields/Html.php +++ /dev/null @@ -1,39 +0,0 @@ - 'permit_empty|string', - ]; - - protected string $defaultValue = ''; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - $value = htmlspecialchars($value ?? ''); - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Markdown.php b/modules/Plugins/Manifest/Fields/Markdown.php deleted file mode 100644 index 4105a628..00000000 --- a/modules/Plugins/Manifest/Fields/Markdown.php +++ /dev/null @@ -1,37 +0,0 @@ - 'permit_empty|string', - ]; - - protected string $defaultValue = ''; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Number.php b/modules/Plugins/Manifest/Fields/Number.php deleted file mode 100644 index 949eea5a..00000000 --- a/modules/Plugins/Manifest/Fields/Number.php +++ /dev/null @@ -1,38 +0,0 @@ - 'permit_empty|numeric', - ]; - - protected ?int $defaultValue = null; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/RadioGroup.php b/modules/Plugins/Manifest/Fields/RadioGroup.php deleted file mode 100644 index d7b38229..00000000 --- a/modules/Plugins/Manifest/Fields/RadioGroup.php +++ /dev/null @@ -1,57 +0,0 @@ - 'permit_empty|string', - ]; - - protected string $defaultValue = ''; - - public function __construct(string $pluginKey) - { - $this->injectRules(); - - parent::__construct($pluginKey); - } - - #[Override] - public function loadData(array $data): void - { - $data = $this->transformData($data); - - parent::loadData($data); - } - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - $options = esc(json_encode($this->getOptionsArray())); - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Rss.php b/modules/Plugins/Manifest/Fields/Rss.php deleted file mode 100644 index 3e085317..00000000 --- a/modules/Plugins/Manifest/Fields/Rss.php +++ /dev/null @@ -1,40 +0,0 @@ - 'permit_empty|string', - ]; - - protected string $defaultValue = ''; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - $value = htmlspecialchars((string) $value); - $defaultValue = esc($this->defaultValue); - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Select.php b/modules/Plugins/Manifest/Fields/Select.php deleted file mode 100644 index 7fa8f9d2..00000000 --- a/modules/Plugins/Manifest/Fields/Select.php +++ /dev/null @@ -1,64 +0,0 @@ - 'permit_empty|string', - 'options' => 'is_list', - ]; - - protected array $casts = [ - 'options' => [Option::class], - ]; - - protected string $defaultValue = ''; - - public function __construct(string $pluginKey) - { - $this->injectRules(); - - parent::__construct($pluginKey); - } - - #[Override] - public function loadData(array $data): void - { - $data = $this->transformData($data); - - parent::loadData($data); - } - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - $options = esc(json_encode($this->getOptionsArray())); - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/SelectMultiple.php b/modules/Plugins/Manifest/Fields/SelectMultiple.php deleted file mode 100644 index 7a2e6e7f..00000000 --- a/modules/Plugins/Manifest/Fields/SelectMultiple.php +++ /dev/null @@ -1,63 +0,0 @@ - $defaultValue - */ -class SelectMultiple extends Field -{ - use WithOptionsTrait; - - public static array $validation_rules = [ - 'defaultValue' => 'permit_empty|is_list', - ]; - - /** - * @var list - */ - protected array $defaultValue = []; - - public function __construct(string $pluginKey) - { - $this->injectRules(); - - parent::__construct($pluginKey); - } - - #[Override] - public function loadData(array $data): void - { - $data = $this->transformData($data); - - parent::loadData($data); - } - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - $options = esc(json_encode($this->getOptionsArray())); - $value = esc(json_encode($value)); - $defaultValue = esc(json_encode($this->defaultValue)); - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Text.php b/modules/Plugins/Manifest/Fields/Text.php deleted file mode 100644 index 67ee93aa..00000000 --- a/modules/Plugins/Manifest/Fields/Text.php +++ /dev/null @@ -1,37 +0,0 @@ - 'permit_empty|string', - ]; - - protected string $defaultValue = ''; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Textarea.php b/modules/Plugins/Manifest/Fields/Textarea.php deleted file mode 100644 index afb025a5..00000000 --- a/modules/Plugins/Manifest/Fields/Textarea.php +++ /dev/null @@ -1,37 +0,0 @@ - 'permit_empty|string', - ]; - - protected string $defaultValue = ''; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Toggler.php b/modules/Plugins/Manifest/Fields/Toggler.php deleted file mode 100644 index 655dc8df..00000000 --- a/modules/Plugins/Manifest/Fields/Toggler.php +++ /dev/null @@ -1,34 +0,0 @@ - 'permit_empty|is_boolean', - ]; - - protected bool $defaultValue = false; - - public function render(string $name, mixed $value, string $class = ''): string - { - $value = $value ? 'yes' : ''; - return <<{$this->label} - HTML; - } -} diff --git a/modules/Plugins/Manifest/Fields/Url.php b/modules/Plugins/Manifest/Fields/Url.php deleted file mode 100644 index 3d712d62..00000000 --- a/modules/Plugins/Manifest/Fields/Url.php +++ /dev/null @@ -1,39 +0,0 @@ - 'permit_empty|valid_url_strict', - ]; - - protected string $defaultValue = ''; - - public function render(string $name, mixed $value, string $class = ''): string - { - $isRequired = $this->optional ? 'false' : 'true'; - return << - HTML; - } -} diff --git a/modules/Plugins/Manifest/Manifest.php b/modules/Plugins/Manifest/Manifest.php deleted file mode 100644 index 6c098d6c..00000000 --- a/modules/Plugins/Manifest/Manifest.php +++ /dev/null @@ -1,84 +0,0 @@ - $keywords - * @property ?string $minCastopodVersion - * @property list $hooks - * @property ?Settings $settings - * @property ?Repository $repository - */ -class Manifest extends ManifestObject -{ - public static array $validation_rules = [ - 'name' => 'required|max_length[128]|regex_match[/^[a-z0-9]([_.-]?[a-z0-9]+)*\/[a-z0-9]([_.-]?[a-z0-9]+)*$/]', - 'version' => 'required|regex_match[/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/]', - 'description' => 'permit_empty|max_length[256]', - 'authors' => 'permit_empty|is_list', - 'homepage' => 'permit_empty|valid_url_strict', - 'license' => 'permit_empty|string', - 'private' => 'permit_empty|is_boolean', - 'submodule' => 'permit_empty|is_boolean', - 'keywords.*' => 'permit_empty', - 'minCastopodVersion' => 'permit_empty|regex_match[/^(0|[1-9]\d*)\.(0|[1-9]\d*)(\.(0|[1-9]\d*))?(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/]', - 'hooks.*' => 'permit_empty|in_list[rssBeforeChannel,rssAfterChannel,rssBeforeItem,rssAfterItem,siteHead]', - 'settings' => 'permit_empty|is_list', - 'repository' => 'permit_empty|is_list', - ]; - - protected array $casts = [ - 'authors' => [Person::class], - 'homepage' => URI::class, - 'settings' => Settings::class, - 'repository' => Repository::class, - ]; - - protected ?string $name = '???'; - - protected ?string $version = 'X.Y.Z'; - - protected ?string $description = null; - - /** - * @var Person[] - */ - protected array $authors = []; - - protected ?URI $homepage = null; - - protected ?string $license = null; - - protected bool $private = false; - - protected bool $submodule = false; - - /** - * @var list - */ - protected array $keywords = []; - - protected ?string $minCastopodVersion = null; - - /** - * @var list - */ - protected array $hooks = []; - - protected ?Settings $settings = null; - - protected ?Repository $repository = null; -} diff --git a/modules/Plugins/Manifest/ManifestObject.php b/modules/Plugins/Manifest/ManifestObject.php deleted file mode 100644 index 4070d24f..00000000 --- a/modules/Plugins/Manifest/ManifestObject.php +++ /dev/null @@ -1,166 +0,0 @@ - - */ - public static array $validation_rules = []; - - /** - * @var array - */ - protected array $casts = []; - - /** - * @var array> - */ - protected static array $errors = []; - - public function __construct( - protected readonly string $pluginKey, - ) { - self::$errors[$pluginKey] = []; - - $class = static::class; - $validation_rules = []; - $casts = []; - while ($class = get_parent_class($class)) { - $validation_rules = [...$validation_rules, ...get_class_vars($class)['validation_rules']]; - $casts = [...$casts, ...get_class_vars($class)['casts']]; - } - - $this::$validation_rules = [...$validation_rules, ...$this::$validation_rules]; - $this->casts = [...$casts, ...$this->casts]; - } - - public function __get(string $name): mixed - { - if (property_exists($this, $name)) { - // if a get method exists for this property, return that - $method = 'get' . str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $name))); - if (method_exists($this, $method)) { - return $this->{$method}(); - } - - return $this->{$name}; - } - - throw new Exception('Undefined object property ' . static::class . '::' . $name); - } - - public function __isset(string $property): bool - { - return property_exists($this, $property); - } - - public function loadFromFile(string $manifestPath): void - { - $manifestContents = @file_get_contents($manifestPath); - - if (! $manifestContents) { - $manifestContents = '{}'; - $this->addError('manifest', lang('Plugins.errors.manifestMissing', [ - 'manifestPath' => $manifestPath, - ])); - } - - /** @var array|null $manifestData */ - $manifestData = json_decode($manifestContents, true); - - if ($manifestData === null) { - $manifestData = []; - $this->addError('manifest', lang('Plugins.errors.manifestJsonInvalid', [ - 'manifestPath' => $manifestPath, - ])); - } - - $this->loadData($manifestData); - } - - /** - * @param array $data - */ - public function loadData(array $data): void - { - /** @var Validation $validation */ - $validation = service('validation'); - - $validation->setRules($this::$validation_rules); - - if (! $validation->run($data)) { - foreach ($validation->getErrors() as $key => $message) { - $this->addError($key, $message); - } - - $validation->reset(); - } - - foreach ($validation->getValidated() as $key => $value) { - $method = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); - if (is_callable([$this, $method])) { - $this->{$method}($value); - continue; - } - - if (array_key_exists($key, $this->casts)) { - $cast = $this->casts[$key]; - if (is_array($cast) && is_array($value)) { - foreach ($value as $valueKey => $valueElement) { - if (is_subclass_of($cast[0], self::class)) { - $manifestClass = $cast[0] === Field::class ? $this->getFieldClass( - $valueElement, - ) : $cast[0]; - $value[$valueKey] = new $manifestClass($this->pluginKey); - $value[$valueKey]->loadData($valueElement); - } else { - $value[$valueKey] = new $cast[0]($valueElement); - } - } - } elseif (is_subclass_of($cast, self::class)) { - $manifestClass = $cast === Field::class ? $this->getFieldClass($value) : $cast; - $valueElement = $value; - $value = new $manifestClass($this->pluginKey); - $value->loadData($valueElement ?? []); - } else { - $value = new $cast($value ?? []); - } - } - - $this->{$key} = $value; - } - } - - /** - * @return array - */ - public static function getPluginErrors(string $pluginKey): array - { - return self::$errors[$pluginKey]; - } - - protected function addError(string $errorKey, string $errorMessage): void - { - self::$errors[$this->pluginKey][$errorKey] = $errorMessage; - } - - /** - * @param array $data - */ - private function getFieldClass(array $data): string - { - $fieldType = $data['type'] ?? 'text'; - return rtrim(Field::class, "\Field") . '\\Fields\\' . str_replace( - ' ', - '', - ucwords(str_replace('-', ' ', $fieldType)), - ); - } -} diff --git a/modules/Plugins/Manifest/Option.php b/modules/Plugins/Manifest/Option.php deleted file mode 100644 index ff15180b..00000000 --- a/modules/Plugins/Manifest/Option.php +++ /dev/null @@ -1,39 +0,0 @@ - 'required|string', - 'value' => 'required|alpha_numeric_punct', - 'description' => 'permit_empty|string', - ]; - - protected string $label; - - protected string $value; - - protected string $description = ''; - - public function getTranslated(string $i18nKey, string $property): string - { - $key = sprintf('%s.%s.%s', $i18nKey, $this->value, $property); - - /** @var string $i18nField */ - $i18nField = lang($key); - - if ($this->{$property} === '' || $i18nField === $key) { - return esc($this->{$property}); - } - - return esc($i18nField); - } -} diff --git a/modules/Plugins/Manifest/Person.php b/modules/Plugins/Manifest/Person.php deleted file mode 100644 index 1a11c931..00000000 --- a/modules/Plugins/Manifest/Person.php +++ /dev/null @@ -1,58 +0,0 @@ -[^<>()]*)\s*(<(?.*)>)?\s*(\((?.*)\))?$/'; - - public static array $validation_rules = [ - 'name' => 'required', - 'email' => 'permit_empty|valid_email', - 'url' => 'permit_empty|valid_url_strict', - ]; - - /** - * @var array - */ - protected array $casts = [ - 'url' => URI::class, - ]; - - protected string $name; - - protected ?string $email = null; - - protected ?URI $url = null; - - #[Override] - public function loadData(array|string $data): void - { - if (is_string($data)) { - $result = preg_match(self::AUTHOR_STRING_PATTERN, $data, $matches); - - if (! $result) { - throw new Exception('Author string is not valid.'); - } - - $data = [ - 'name' => $matches['name'], - 'email' => $matches['email'] ?? null, - 'url' => $matches['url'] ?? null, - ]; - } - - parent::loadData($data); - } -} diff --git a/modules/Plugins/Manifest/Repository.php b/modules/Plugins/Manifest/Repository.php deleted file mode 100644 index 9a50398e..00000000 --- a/modules/Plugins/Manifest/Repository.php +++ /dev/null @@ -1,34 +0,0 @@ - 'permit_empty|in_list[git]', - 'url' => 'required|valid_url_strict', - 'directory' => 'permit_empty', - ]; - - /** - * @var array - */ - protected array $casts = [ - 'url' => URI::class, - ]; - - protected string $type = 'git'; - - protected URI $url; - - protected ?string $directory = null; -} diff --git a/modules/Plugins/Manifest/Settings.php b/modules/Plugins/Manifest/Settings.php deleted file mode 100644 index a30f3635..00000000 --- a/modules/Plugins/Manifest/Settings.php +++ /dev/null @@ -1,62 +0,0 @@ - 'permit_empty|is_list', - 'podcast' => 'permit_empty|is_list', - 'episode' => 'permit_empty|is_list', - ]; - - /** - * @var array - */ - protected array $casts = [ - 'general' => [Field::class], - 'podcast' => [Field::class], - 'episode' => [Field::class], - ]; - - /** - * @var Field[] - */ - protected array $general = []; - - /** - * @var Field[] - */ - protected array $podcast = []; - - /** - * @var Field[] - */ - protected array $episode = []; - - #[Override] - public function loadData(array $data): void - { - $newData = []; - foreach ($data as $key => $fields) { - $newFields = []; - foreach ($fields as $fieldKey => $field) { - $field['key'] = $fieldKey; - $newFields[] = $field; - } - - $newData[$key] = $newFields; - } - - parent::loadData($newData); - } -} diff --git a/modules/Plugins/Manifest/WithFieldsTrait.php b/modules/Plugins/Manifest/WithFieldsTrait.php deleted file mode 100644 index 72ac75a2..00000000 --- a/modules/Plugins/Manifest/WithFieldsTrait.php +++ /dev/null @@ -1,45 +0,0 @@ - 'is_list', - ]]; - $this->casts = [...$this->casts, ...[ - 'fields' => [Field::class], - ]]; - } - - /** - * @param array $data - * @return array - */ - public function transformData(array $data): array - { - if (array_key_exists('fields', $data)) { - $newFields = []; - foreach ($data['fields'] as $key => $field) { - $field['key'] = $key; - $newFields[] = $field; - } - - $data['fields'] = $newFields; - } - - return $data; - } -} diff --git a/modules/Plugins/Manifest/WithOptionsTrait.php b/modules/Plugins/Manifest/WithOptionsTrait.php deleted file mode 100644 index a88b0ad3..00000000 --- a/modules/Plugins/Manifest/WithOptionsTrait.php +++ /dev/null @@ -1,69 +0,0 @@ - 'is_list', - ]]; - } - - if (isset($this->casts)) { - $this->casts = [...$this->casts, ...[ - 'options' => [Option::class], - ]]; - } - } - - /** - * @param array $data - * @return array - */ - public function transformData(array $data): array - { - if (array_key_exists('options', $data)) { - $newOptions = []; - foreach ($data['options'] as $key => $option) { - $option['value'] = $key; - $newOptions[] = $option; - } - - $data['options'] = $newOptions; - } - - return $data; - } - - /** - * @return array{label:string,value:string,description:string}[] - */ - public function getOptionsArray(): array - { - $i18nKey = sprintf('%s.settings.%s.%s.options', $this->pluginKey, $this->type, $this->key); - - $optionsArray = []; - foreach ($this->options as $option) { - $optionsArray[] = [ - 'value' => $option->value, - 'label' => $option->getTranslated($i18nKey, 'label'), - 'description' => $option->getTranslated($i18nKey, 'description'), - ]; - } - - return $optionsArray; - } -} diff --git a/modules/Plugins/Manifest/manifest.schema.json b/modules/Plugins/Manifest/manifest.schema.json deleted file mode 100644 index 08ecd0eb..00000000 --- a/modules/Plugins/Manifest/manifest.schema.json +++ /dev/null @@ -1,409 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "/schemas/manifest.json", - "title": "JSON schema for Castopod Plugins's manifest.json files", - "description": "The Castopod plugin manifest defines both metadata and behavior of a plugin", - "type": "object", - "properties": { - "name": { - "description": "The plugin name, including 'vendor-name/' prefix", - "type": "string", - "pattern": "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9]([_.-]?[a-z0-9]+)*$", - "examples": ["acme/hello-world"] - }, - "version": { - "description": "The plugin's semantic version. See https://semver.org/", - "type": "string", - "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", - "examples": ["1.0.0"] - }, - "minCastopodVersion": { - "description": "The minimal version of Castopod for which the plugin is compatible with.", - "type": "string", - "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(\\.(0|[1-9]\\d*))?(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", - "examples": ["2.0"] - }, - "description": { - "description": "This helps people discover your plugin as it's listed in repositories", - "type": "string" - }, - "authors": { - "type": "array", - "items": { - "$ref": "#/$defs/person" - } - }, - "homepage": { - "description": "The URL to the plugin homepage", - "type": "string", - "format": "uri" - }, - "license": { - "description": "You should specify a license for your plugin so that people know how they are permitted to use it, and any restrictions you're placing on it.", - "default": "UNLICENSED", - "anyOf": [ - { - "type": "string" - }, - { - "enum": [ - "AGPL-3.0-only", - "AGPL-3.0-or-later", - "Apache-2.0", - "BSL-1.0", - "GPL-3.0-only", - "GPL-3.0-or-later", - "LGPL-3.0-only", - "LGPL-3.0-or-later", - "MIT", - "MPL-2.0", - "Unlicense", - "UNLICENSED" - ] - } - ] - }, - "private": { - "type": "boolean", - "description": "If set to true, then repositories should refuse to publish it.", - "default": false - }, - "submodule": { - "type": "boolean", - "description": "Set to `true` if the plugin is part of a monorepo (i.e., in the same Git repository as other plugins). Releases should be tagged as `@` to ensure proper version indexing by plugin repositories.", - "default": false - }, - "keywords": { - "description": "This helps people discover your plugin as it's listed in repositories", - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "enum": [ - "accessibility", - "analytics", - "monetization", - "podcasting2", - "privacy", - "productivity", - "seo" - ] - } - ] - }, - "uniqueItems": true - }, - "hooks": { - "description": "The hooks used by the plugin.", - "type": "array", - "items": { - "enum": [ - "rssBeforeChannel", - "rssAfterChannel", - "rssBeforeItem", - "rssAfterItem", - "siteHead" - ] - }, - "uniqueItems": true - }, - "settings": { - "type": "object", - "properties": { - "general": { - "$ref": "#/$defs/fields" - }, - "podcast": { - "$ref": "#/$defs/fields" - }, - "episode": { - "$ref": "#/$defs/fields" - } - } - }, - "files": { - "description": "List of files to include in your plugin package. If you include a folder in the array, all files inside it will also be included.", - "type": "array", - "items": { - "type": "string" - } - }, - "repository": { - "description": "Specify the place where your plugin code lives. This is helpful for people who want to contribute.", - "type": ["object", "string"], - "properties": { - "type": { - "type": "string" - }, - "url": { - "type": "string" - }, - "directory": { - "type": "string" - } - } - } - }, - "required": ["name", "version", "minCastopodVersion"], - "additionalProperties": false, - "$defs": { - "person": { - "description": "A person who has been involved in creating or maintaining this plugin.", - "type": ["object", "string"], - "required": ["name"], - "properties": { - "name": { - "type": "string" - }, - "email": { - "type": "string", - "format": "email" - }, - "url": { - "type": "string", - "format": "uri" - } - } - }, - "fields": { - "type": "object", - "patternProperties": { - "^[A-Za-z]+[\\w\\-\\:\\.]*$": { "$ref": "#/$defs/field" } - }, - "additionalProperties": false - }, - "field": { - "type": "object", - "properties": { - "type": { - "enum": [ - "checkbox", - "datetime", - "email", - "group", - "html", - "markdown", - "number", - "radio-group", - "rss", - "select-multiple", - "select", - "text", - "textarea", - "toggler", - "url" - ], - "default": "text" - }, - "label": { - "type": "string" - }, - "hint": { - "type": "string" - }, - "helper": { - "type": "string" - }, - "optional": { - "type": "boolean" - }, - "validationRules": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "multiple": { - "type": "boolean" - } - }, - "required": ["label"], - "unevaluatedProperties": false, - "allOf": [ - { "$ref": "#/$defs/field-multiple-implies-options-is-required" }, - { "$ref": "#/$defs/require-fields-for-group-type" }, - { "$ref": "#/$defs/default-value-based-on-type" } - ] - }, - "option": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": ["label"], - "additionalProperties": false - }, - "field-multiple-implies-options-is-required": { - "if": { - "properties": { - "type": { - "enum": ["radio-group", "select", "select-multiple"] - } - } - }, - "then": { - "properties": { - "options": { - "type": "object", - "patternProperties": { - "^[A-Za-z0-9]+[\\w\\-\\:\\.]*$": { "$ref": "#/$defs/option" } - }, - "additionalProperties": false - } - }, - "required": ["options"] - } - }, - "require-fields-for-group-type": { - "if": { - "properties": { - "type": { - "const": "group" - } - } - }, - "then": { - "properties": { - "fields": { - "type": "object", - "patternProperties": { - "^[A-Za-z]+[\\w\\-\\:\\.]*$": { "$ref": "#/$defs/field" } - }, - "additionalProperties": false - } - }, - "required": ["fields"] - } - }, - "default-value-based-on-type": { - "allOf": [ - { - "if": { - "properties": { - "type": { - "enum": [ - "html", - "markdown", - "radio-group", - "rss", - "select", - "text", - "textarea" - ] - } - } - }, - "then": { - "properties": { - "defaultValue": { "type": "string" } - } - } - }, - { - "if": { - "properties": { - "type": { - "enum": ["checkbox", "toggler"] - } - } - }, - "then": { - "properties": { - "defaultValue": { "type": "boolean" } - } - } - }, - { - "if": { - "properties": { - "type": { - "const": "datetime" - } - } - }, - "then": { - "properties": { - "defaultValue": { "type": "string", "format": "date-time" } - } - } - }, - { - "if": { - "properties": { - "type": { - "const": "email" - } - } - }, - "then": { - "properties": { - "defaultValue": { "type": "string", "format": "email" } - } - } - }, - { - "if": { - "properties": { - "type": { - "const": "number" - } - } - }, - "then": { - "properties": { - "defaultValue": { "type": "number" } - } - } - }, - { - "if": { - "properties": { - "type": { - "const": "select-multiple" - } - } - }, - "then": { - "properties": { - "defaultValue": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - { - "if": { - "properties": { - "type": { - "const": "url" - } - } - }, - "then": { - "properties": { - "defaultValue": { "type": "string", "format": "uri" } - } - } - } - ] - } - } -} diff --git a/modules/PodcastImport/Commands/PodcastImport.php b/modules/PodcastImport/Commands/PodcastImport.php deleted file mode 100644 index 63c835e1..00000000 --- a/modules/PodcastImport/Commands/PodcastImport.php +++ /dev/null @@ -1,599 +0,0 @@ - $task->status === TaskStatus::Running, - ), - ); - - if ($currentImport instanceof PodcastImportTask) { - $currentImport->syncWithProcess(); - - if ($currentImport->status === TaskStatus::Running) { - // process is still running - throw new Exception('An import is already running.'); - } - - // continue if the task is not running anymore - } - - // Get the next queued import - $queuedImports = array_filter( - $importQueue, - static fn (PodcastImportTask $task): bool => $task->status === TaskStatus::Queued, - ); - $nextImport = end($queuedImports); - - if (! $nextImport instanceof PodcastImportTask) { - // no queued import task, stop process. - exit(0); - } - - $this->importTask = $nextImport; - - // retrieve user who created import task - $user = new UserModel() - ->find($this->importTask->created_by); - - if (! $user instanceof User) { - throw new Exception('Could not retrieve user with ID: ' . $this->importTask->created_by); - } - - $this->user = $user; - - CLI::write('Fetching and parsing RSS feed...'); - - ini_set('user_agent', 'Castopod/' . CP_VERSION); - $this->podcastFeed = new PodcastFeed($this->importTask->feed_url); - } - - #[Override] - public function run(array $params): void - { - // FIXME: getting named routes doesn't work from v4.3 anymore, so loading all routes before importing - service('routes') - ->loadRoutes(); - - try { - $this->init(); - - CLI::write('All good! Feed was parsed successfully!'); - - CLI::write( - 'Starting import for @' . $this->importTask->handle . ' using feed: ' . $this->importTask->feed_url, - ); - - // --- START IMPORT TASK --- - $this->importTask->start(); - - CLI::write('Checking if podcast is locked.'); - - if ($this->podcastFeed->channel->podcast_locked->getValue()) { - throw new Exception('🔒 Podcast is locked.'); - } - - CLI::write('Podcast is not locked, import can resume.'); - - // check if podcast to be imported already exists by guid if exists or handle otherwise - $podcastGuid = $this->podcastFeed->channel->podcast_guid->getValue(); - if ($podcastGuid !== null) { - $podcast = new PodcastModel() - ->where('guid', $podcastGuid) - ->first(); - } else { - $podcast = new PodcastModel() - ->where('handle', $this->importTask->handle) - ->first(); - } - - if ($podcast instanceof Podcast) { - if ($podcast->handle !== $this->importTask->handle) { - throw new Exception('Podcast was already imported with a different handle.'); - } - - CLI::write('Podcast handle already exists, using existing one.'); - $this->podcast = $podcast; - } - - helper(['media', 'misc', 'auth']); - - if (! $this->podcast instanceof Podcast) { - $this->podcast = $this->importPodcast(); - } - - CLI::write('Adding podcast platforms...'); - - $this->importPodcastPlatforms(); - - CLI::write('Adding persons - ' . count($this->podcastFeed->channel->podcast_persons) . ' elements.'); - - $this->importPodcastPersons(); - - $this->importEpisodes(); - - // set podcast publication date to the first ever published episode - $this->podcast->published_at = $this->getOldestEpisodePublicationDate( - $this->podcast->id, - ) ?? $this->podcast->created_at; - - $podcastModel = new PodcastModel(); - if (! $podcastModel->update($this->podcast->id, $this->podcast)) { - throw new Exception(print_r($podcastModel->errors(), true)); - } - - CLI::showProgress(false); - - // // done, set status to passed - $this->importTask->pass(); - } catch (Exception $exception) { - $this->error($exception->getMessage()); - log_message( - 'critical', - 'Error when importing ' . $this->importTask?->feed_url . PHP_EOL . $exception->getMessage() . PHP_EOL . $exception->getTraceAsString(), - ); - } - } - - private function getOldestEpisodePublicationDate(int $podcastId): ?Time - { - $result = new EpisodeModel() - ->builder() - ->selectMax('published_at', 'oldest_published_at') - ->where('podcast_id', $podcastId) - ->get() - ->getResultArray(); - - if ($result[0]['oldest_published_at'] === null) { - return null; - } - - return Time::createFromFormat('Y-m-d H:i:s', $result[0]['oldest_published_at']); - } - - private function importPodcast(): Podcast - { - $location = null; - if ($this->podcastFeed->channel->podcast_location->getValue() !== null) { - $location = new Location( - $this->podcastFeed->channel->podcast_location->getValue(), - $this->podcastFeed->channel->podcast_location->getAttribute('geo'), - $this->podcastFeed->channel->podcast_location->getAttribute('osm'), - ); - } - - if (($showNotes = $this->getShowNotes($this->podcastFeed->channel)) === null) { - throw new Exception('Missing channel show notes. Please include a tag.'); - } - - if (($coverUrl = $this->getCoverUrl($this->podcastFeed->channel)) === null) { - throw new Exception('Missing podcast cover. Please include an tag.'); - } - - if (($ownerName = $this->podcastFeed->channel->itunes_owner->itunes_name->getValue()) === null) { - throw new Exception( - 'Missing podcast owner name. Please include an tag inside the tag.', - ); - } - - if (($ownerEmail = $this->podcastFeed->channel->itunes_owner->itunes_email->getValue()) === null) { - throw new Exception( - 'Missing podcast owner email. Please include an tag inside the tag.', - ); - } - - $parentalAdvisory = null; - if ($this->podcastFeed->channel->itunes_explicit->getValue() !== null) { - $parentalAdvisory = $this->podcastFeed->channel->itunes_explicit->getValue() ? 'explicit' : 'clean'; - } - - $db = db_connect(); - $db->transStart(); - - $htmlConverter = new HtmlConverter(); - $podcast = new Podcast([ - 'created_by' => $this->user->id, - 'updated_by' => $this->user->id, - 'guid' => $this->podcastFeed->channel->podcast_guid->getValue(), - 'handle' => $this->importTask->handle, - 'imported_feed_url' => $this->importTask->feed_url, - 'new_feed_url' => url_to('podcast-rss-feed', $this->importTask->handle), - 'title' => $this->podcastFeed->channel->title->getValue(), - 'description_markdown' => $htmlConverter->convert($showNotes), - 'description_html' => $showNotes, - 'cover' => download_file($coverUrl), - 'banner' => null, - 'language_code' => $this->importTask->language, - 'category_id' => $this->importTask->category, - 'parental_advisory' => $parentalAdvisory, - 'owner_name' => $ownerName, - 'owner_email' => $ownerEmail, - 'publisher' => $this->podcastFeed->channel->itunes_author->getValue(), - 'type' => $this->podcastFeed->channel->itunes_type->getValue(), - 'copyright' => $this->podcastFeed->channel->copyright->getValue(), - 'is_blocked' => $this->podcastFeed->channel->itunes_block->getValue(), - 'is_completed' => $this->podcastFeed->channel->itunes_complete->getValue(), - 'location' => $location, - ]); - - $podcastModel = new PodcastModel(); - if (! ($podcastId = $podcastModel->insert($podcast, true))) { - $db->transRollback(); - throw new Exception(print_r($podcastModel->errors(), true)); - } - - $podcast->id = $podcastId; - - // set current user as podcast admin - // 1. create new group - config('AuthGroups') - ->generatePodcastAuthorizations($podcast->id); - add_podcast_group($this->user, $podcast->id, 'admin'); - - $db->transComplete(); // save podcast to database - - CLI::write('Podcast was successfully created!'); - - return $podcast; - } - - private function getShowNotes(Channel|Item $channelOrItem): ?string - { - if (! $channelOrItem instanceof Item) { - return $channelOrItem->description->getValue() ?? $channelOrItem->itunes_summary->getValue(); - } - - if ($channelOrItem->content_encoded->getValue() !== null) { - return $channelOrItem->content_encoded->getValue(); - } - - return $channelOrItem->description->getValue() ?? $channelOrItem->itunes_summary->getValue(); - } - - private function getCoverUrl(Channel|Item $channelOrItem): ?string - { - if ($channelOrItem->itunes_image->getAttribute('href') !== null) { - return $channelOrItem->itunes_image->getAttribute('href'); - } - - if ($channelOrItem instanceof Channel && $channelOrItem->image->url->getValue() !== null) { - return $channelOrItem->image->url->getValue(); - } - - return null; - } - - private function importPodcastPersons(): void - { - $personsCount = count($this->podcastFeed->channel->podcast_persons); - $currPersonsStep = 1; // for progress - foreach ($this->podcastFeed->channel->podcast_persons as $person) { - CLI::showProgress($currPersonsStep++, $personsCount); - $fullName = $person->getValue(); - $newPersonId = null; - $personModel = new PersonModel(); - if (($newPerson = $personModel->getPerson($fullName)) instanceof Person) { - $newPersonId = $newPerson->id; - } else { - $newPodcastPerson = new Person([ - 'created_by' => $this->user->id, - 'updated_by' => $this->user->id, - 'full_name' => $fullName, - 'unique_name' => slugify($fullName), - 'information_url' => $person->getAttribute('href'), - 'avatar' => download_file((string) $person->getAttribute('img')), - ]); - - if (! $newPersonId = $personModel->insert($newPodcastPerson)) { - throw new Exception(print_r($personModel->errors(), true)); - } - } - - $personGroup = $person->getAttribute('group'); - $personRole = $person->getAttribute('role'); - - // set default group and role if taxonomy is not found - $personGroupSlug = 'cast'; - $personRoleSlug = 'host'; - - if (array_key_exists(strtolower((string) $personGroup), ReversedTaxonomy::$taxonomy)) { - $personGroup = ReversedTaxonomy::$taxonomy[strtolower((string) $personGroup)]; - $personGroupSlug = $personGroup['slug']; - - if (array_key_exists(strtolower((string) $personRole), $personGroup['roles'])) { - $personRoleSlug = $personGroup['roles'][strtolower((string) $personRole)]['slug']; - } - } - - $podcastPersonModel = new PersonModel(); - if (! $podcastPersonModel->addPodcastPerson( - $this->podcast->id, - $newPersonId, - $personGroupSlug, - $personRoleSlug, - )) { - throw new Exception(print_r($podcastPersonModel->errors(), true)); - } - } - - CLI::showProgress(false); - } - - private function importPodcastPlatforms(): void - { - $platformTypes = [ - [ - 'name' => 'podcasting', - 'elements' => $this->podcastFeed->channel->podcast_ids, - 'count' => count($this->podcastFeed->channel->podcast_ids), - 'account_url_key' => 'url', - 'account_id_key' => 'id', - ], - [ - 'name' => 'social', - 'elements' => $this->podcastFeed->channel->podcast_socials, - 'count' => count($this->podcastFeed->channel->podcast_socials), - 'account_url_key' => 'accountUrl', - 'account_id_key' => 'accountId', - ], - [ - 'name' => 'funding', - 'elements' => $this->podcastFeed->channel->podcast_fundings, - 'count' => count($this->podcastFeed->channel->podcast_fundings), - 'account_url_key' => 'url', - 'account_id_key' => 'id', - ], - ]; - - $platforms = service('platforms'); - $platformModel = new PlatformModel(); - foreach ($platformTypes as $platformType) { - $platformsData = []; - $currPlatformStep = 1; // for progress - CLI::write($platformType['name'] . ' - ' . $platformType['count'] . ' elements'); - foreach ($platformType['elements'] as $platform) { - CLI::showProgress($currPlatformStep++, $platformType['count']); - $platformSlug = $platform->getAttribute('platform'); - $platformData = $platforms->findPlatformBySlug($platformType['name'], $platformSlug); - - if ($platformData === null) { - continue; - } - - $platformsData[] = [ - 'podcast_id' => $this->podcast->id, - 'type' => $platformType['name'], - 'slug' => $platformSlug, - 'link_url' => $platform->getAttribute($platformType['account_url_key']), - 'account_id' => $platform->getAttribute($platformType['account_id_key']), - 'is_visible' => 0, - ]; - } - - $platformModel->savePlatforms($this->podcast->id, $platformType['name'], $platformsData); - CLI::showProgress(false); - } - } - - private function importEpisodes(): void - { - helper('text'); - - $itemsCount = count($this->podcastFeed->channel->items); - $this->importTask->setEpisodesCount($itemsCount); - - CLI::write('Adding episodes - ' . $itemsCount . ' episodes'); - - $htmlConverter = new HtmlConverter(); - - $importedGUIDs = $this->getImportedGUIDs($this->podcast->id); - - $currEpisodesStep = 0; // for progress - $episodesNewlyImported = 0; - $episodesAlreadyImported = 0; - - // insert episodes in reverse order, from the last item in the list to the first - foreach (array_reverse($this->podcastFeed->channel->items) as $key => $item) { - CLI::showProgress(++$currEpisodesStep, $itemsCount); - - if (in_array($item->guid->getValue(), $importedGUIDs, true)) { - // do not import item if already imported - // (check that item with guid has already been inserted) - $this->importTask->setEpisodesAlreadyImported(++$episodesAlreadyImported); - continue; - } - - $db = db_connect(); - $db->transStart(); - - $location = null; - if ($item->podcast_location->getValue() !== null) { - $location = new Location( - $item->podcast_location->getValue(), - $item->podcast_location->getAttribute('geo'), - $item->podcast_location->getAttribute('osm'), - ); - } - - if (($showNotes = $this->getShowNotes($item)) === null) { - $db->transRollback(); - throw new Exception('Missing item show notes. Please include a tag to item ' . $key); - } - - $coverUrl = $this->getCoverUrl($item); - - $parentalAdvisory = null; - if ($item->itunes_explicit->getValue() !== null) { - $parentalAdvisory = $item->itunes_explicit->getValue() ? 'explicit' : 'clean'; - } - - $episode = new Episode([ - 'created_by' => $this->user->id, - 'updated_by' => $this->user->id, - 'podcast_id' => $this->podcast->id, - 'title' => $item->title->getValue(), - 'slug' => slugify((string) $item->title->getValue(), 120) . '-' . strtolower( - random_string('alnum', 5), - ), - 'guid' => $item->guid->getValue(), - 'audio' => download_file( - $item->enclosure->getAttribute('url'), - $item->enclosure->getAttribute('type'), - ), - 'description_markdown' => $htmlConverter->convert($showNotes), - 'description_html' => $showNotes, - 'cover' => $coverUrl ? download_file($coverUrl) : null, - 'parental_advisory' => $parentalAdvisory, - 'number' => $item->itunes_episode->getValue(), - 'season_number' => $item->itunes_season->getValue(), - 'type' => $item->itunes_episodeType->getValue(), - 'is_blocked' => $item->itunes_block->getValue(), - 'location' => $location, - 'is_premium' => $this->podcast->is_premium_by_default, - 'published_at' => $item->pubDate->getValue(), - ]); - - $episodeModel = new EpisodeModel(); - - if (! ($episodeId = $episodeModel->insert($episode, true))) { - $db->transRollback(); - throw new Exception(print_r($episodeModel->errors(), true)); - } - - $this->importEpisodePersons($episodeId, $item->podcast_persons); - - $this->importTask->setEpisodesNewlyImported(++$episodesNewlyImported); - - $db->transComplete(); - } - } - - /** - * @return string[] - */ - private function getImportedGUIDs(int $podcastId): array - { - $result = new EpisodeModel() - ->builder() - ->select('guid') - ->where('podcast_id', $podcastId) - ->get() - ->getResultArray(); - - return array_map(static fn (array $element) => $element['guid'], $result); - } - - /** - * @param PodcastPerson[] $persons - */ - private function importEpisodePersons(int $episodeId, array $persons): void - { - foreach ($persons as $person) { - $fullName = $person->getValue(); - $personModel = new PersonModel(); - $newPersonId = null; - if (($newPerson = $personModel->getPerson($fullName)) instanceof Person) { - $newPersonId = $newPerson->id; - } else { - $newPerson = new Person([ - 'created_by' => $this->user->id, - 'updated_by' => $this->user->id, - 'full_name' => $fullName, - 'unique_name' => slugify($fullName), - 'information_url' => $person->getAttribute('href'), - 'avatar' => download_file((string) $person->getAttribute('img')), - ]); - - if (! ($newPersonId = $personModel->insert($newPerson))) { - throw new Exception(print_r($personModel->errors(), true)); - } - } - - $personGroup = $person->getAttribute('group'); - $personRole = $person->getAttribute('role'); - - // set default group and role if taxonomy is not found - $personGroupSlug = 'cast'; - $personRoleSlug = 'host'; - - if (array_key_exists(strtolower((string) $personGroup), ReversedTaxonomy::$taxonomy)) { - $personGroup = ReversedTaxonomy::$taxonomy[strtolower((string) $personGroup)]; - $personGroupSlug = $personGroup['slug']; - - if (array_key_exists(strtolower((string) $personRole), $personGroup['roles'])) { - $personRoleSlug = $personGroup['roles'][strtolower((string) $personRole)]['slug']; - } - } - - $episodePersonModel = new PersonModel(); - if (! $episodePersonModel->addEpisodePerson( - $this->podcast->id, - $episodeId, - $newPersonId, - $personGroupSlug, - $personRoleSlug, - )) { - throw new Exception(print_r($episodePersonModel->errors(), true)); - } - } - } - - private function error(string $message): void - { - if ($this->importTask instanceof PodcastImportTask) { - $this->importTask->fail($message); - } - - CLI::error('[Error] ' . $message); - } -} diff --git a/modules/PodcastImport/Config/Routes.php b/modules/PodcastImport/Config/Routes.php deleted file mode 100644 index ede5be52..00000000 --- a/modules/PodcastImport/Config/Routes.php +++ /dev/null @@ -1,50 +0,0 @@ -group( - config('Admin') - ->gateway, - [ - 'namespace' => 'Modules\PodcastImport\Controllers', - ], - static function ($routes): void { - $routes->get('imports', 'PodcastImportController::list', [ - 'as' => 'all-podcast-imports', - 'filter' => 'permission:podcasts.import', - ]); - $routes->get('imports/add', 'PodcastImportController::addToQueueView', [ - 'as' => 'podcast-imports-add', - 'filter' => 'permission:podcasts.import', - ]); - $routes->post('imports/add', 'PodcastImportController::addToQueueAction', [ - 'filter' => 'permission:podcasts.import', - ]); - $routes->get('imports/(:segment)/(:alpha)', 'PodcastImportController::taskAction/$1/$2', [ - 'as' => 'podcast-imports-task-action', - 'filter' => 'permission:podcasts.import', - ]); - - $routes->group('podcasts/(:num)', static function ($routes): void { - $routes->get('imports', 'PodcastImportController::podcastList/$1', [ - 'as' => 'podcast-imports', - 'filter' => 'permission:podcast$1.manage-import', - ]); - $routes->get('sync-feeds', 'PodcastImportController::syncImport/$1', [ - 'as' => 'podcast-imports-sync', - 'filter' => 'permission:podcast$1.manage-import', - ]); - $routes->post('sync-feeds', 'PodcastImportController::syncImportAttempt/$1', [ - 'as' => 'podcast-imports-sync', - 'filter' => 'permission:podcast$1.manage-import', - ]); - }); - }, -); diff --git a/modules/PodcastImport/Controllers/PodcastImportController.php b/modules/PodcastImport/Controllers/PodcastImportController.php deleted file mode 100644 index d15037d2..00000000 --- a/modules/PodcastImport/Controllers/PodcastImportController.php +++ /dev/null @@ -1,219 +0,0 @@ -setHtmlHead(lang('Podcast.all_imports')); - return view('import/queue', [ - 'podcastImportsQueue' => get_import_tasks(), - ]); - } - - public function podcastList(int $podcastId): string - { - if (! ($podcast = new PodcastModel()->getPodcastById($podcastId)) instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - helper('podcast_import'); - - $this->setHtmlHead(lang('Podcast.all_imports')); - replace_breadcrumb_params([ - 0 => $podcast->at_handle, - ]); - return view('import/podcast_queue', [ - 'podcast' => $podcast, - 'podcastImportsQueue' => get_import_tasks($podcast->handle), - ]); - } - - public function addToQueueView(): string - { - helper(['form', 'misc']); - - $languageOptions = new LanguageModel() - ->getLanguageOptions(); - $categoryOptions = new CategoryModel() - ->getCategoryOptions(); - - $data = [ - 'languageOptions' => $languageOptions, - 'categoryOptions' => $categoryOptions, - 'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE')), - ]; - - $this->setHtmlHead(lang('Podcast.import')); - return view('import/add_to_queue', $data); - } - - public function addToQueueAction(): RedirectResponse - { - $rules = [ - 'handle' => 'required|regex_match[/^[a-zA-Z0-9\_]{1,32}$/]', - 'imported_feed_url' => 'required|valid_url_strict', - 'language' => 'required', - 'category' => 'required', - ]; - - if (! $this->validate($rules)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $this->validator->getErrors()); - } - - $validData = $this->validator->getValidated(); - - // TODO: check that handle is not already in use - - $importTask = new PodcastImportTask([ - 'handle' => $validData['handle'], - 'feed_url' => $validData['imported_feed_url'], - 'language' => $validData['language'], - 'category' => $validData['category'], - 'status' => TaskStatus::Queued, - 'created_by' => user_id(), - 'updated_by' => user_id(), - 'created_at' => Time::now(), - 'updated_at' => Time::now(), - ]); - - $importTask->save(); - - return redirect()->route('all-podcast-imports') - ->with('message', lang('PodcastImport.messages.importTaskQueued')); - } - - public function syncImport(int $podcastId): string - { - if (! ($podcast = new PodcastModel()->getPodcastById($podcastId)) instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - helper('form'); - - $this->setHtmlHead(lang('PodcastImport.syncForm.title')); - replace_breadcrumb_params([ - 0 => $podcast->at_handle, - ]); - return view('import/podcast_sync', [ - 'podcast' => $podcast, - ]); - } - - public function syncImportAttempt(int $podcastId): RedirectResponse - { - if (! ($podcast = new PodcastModel()->getPodcastById($podcastId)) instanceof Podcast) { - throw PageNotFoundException::forPageNotFound(); - } - - $rules = [ - 'feed_url' => 'valid_url_strict', - ]; - - if (! $this->validate($rules)) { - return redirect() - ->back() - ->withInput() - ->with('errors', $this->validator->getErrors()); - } - - $validData = $this->validator->getValidated(); - - // create update task in podcastImport - $importTask = new PodcastImportTask([ - 'handle' => $podcast->handle, - 'feed_url' => $validData['feed_url'], - 'language' => $podcast->language_code, - 'category' => $podcast->category_id, - 'status' => TaskStatus::Queued, - 'created_by' => user_id(), - 'updated_by' => user_id(), - 'created_at' => Time::now(), - 'updated_at' => Time::now(), - ]); - - $importTask->save(); - - return redirect()->route('podcast-imports', [$podcastId]) - ->with('message', lang('PodcastImport.messages.syncTaskQueued')); - } - - public function taskAction(string $taskId, string $action): RedirectResponse - { - /** @var array $importQueue */ - $importQueue = service('settings') - ->get('Import.queue') ?? []; - - if (! array_key_exists($taskId, $importQueue)) { - throw PageNotFoundException::forPageNotFound(); - } - - $importTask = $importQueue[$taskId]; - switch ($action) { - case 'cancel': - if ($importTask->status === TaskStatus::Running || $importTask->status === TaskStatus::Queued) { - $importTask->cancel(); - - return redirect()->back() - ->with('message', lang('PodcastImport.messages.canceled')); - } - - return redirect()->back() - ->with('error', lang('PodcastImport.messages.notRunning')); - case 'retry': - if ($importTask->status === TaskStatus::Running || $importTask->status === TaskStatus::Queued) { - return redirect()->back() - ->with('error', lang('PodcastImport.messages.alreadyRunning')); - } - - $newImportTask = new PodcastImportTask([ - 'handle' => $importTask->handle, - 'feed_url' => $importTask->feed_url, - 'language' => $importTask->language, - 'category' => $importTask->category, - 'status' => TaskStatus::Queued, - 'created_by' => user_id(), - 'updated_by' => user_id(), - 'created_at' => Time::now(), - 'updated_at' => Time::now(), - ]); - - $newImportTask->save(); - - return redirect()->back() - ->with('message', lang('PodcastImport.messages.retried')); - case 'delete': - $importTask->delete(); - return redirect()->back() - ->with('message', lang('PodcastImport.messages.deleted')); - default: - throw new Exception('Task action ' . $action . ' was not implemented'); - } - } -} diff --git a/modules/PodcastImport/Entities/PodcastImportTask.php b/modules/PodcastImport/Entities/PodcastImportTask.php deleted file mode 100644 index b0de2f95..00000000 --- a/modules/PodcastImport/Entities/PodcastImportTask.php +++ /dev/null @@ -1,242 +0,0 @@ - $data - */ - public function __construct(array $data) - { - parent::__construct($data); - - if (! array_key_exists('id', $data)) { - $this->id = md5($this->feed_url . Time::now()); - } - } - - public function getProgress(): float - { - if ($this->episodes_count === null) { - return 0; - } - - return $this->episodes_imported / $this->episodes_count; - } - - public function getEpisodesImported(): int - { - return $this->episodes_newly_imported + $this->episodes_already_imported; - } - - public function setEpisodesNewlyImported(int $episodesImported): void - { - $this->episodes_newly_imported = $episodesImported; - - $this->save(); - } - - public function setEpisodesAlreadyImported(int $episodesImported): void - { - $this->episodes_already_imported = $episodesImported; - - $this->save(); - } - - public function setEpisodesCount(int $episodesCount): void - { - $this->episodes_count = $episodesCount; - - $this->save(); - } - - public function getDuration(): int - { - if ($this->duration === null && $this->started_at !== null && $this->ended_at !== null) { - $this->duration = ($this->started_at->difference($this->ended_at)) - ->getSeconds(); - } - - return $this->duration; - } - - public function start(): void - { - if ($this->process_id !== null) { - throw new Exception('Task is already running!'); - } - - $processId = getmypid(); - - if ($processId === false) { - throw new Exception('Error Processing Request', 1); - } - - $this->process_id = $processId; - $this->started_at = Time::now(); - $this->status = TaskStatus::Running; - $this->save(); - - service('settings') - ->set('Import.current', $this->handle); - } - - public function pass(): void - { - $this->process_id = null; - $this->ended_at = Time::now(); - $this->status = TaskStatus::Passed; - - $this->save(); - - service('settings') - ->forget('Import.current'); - } - - public function cancel(): void - { - if ($this->status !== TaskStatus::Running && $this->status !== TaskStatus::Queued) { - throw new Exception('Task can only be canceled if running or queued.'); - } - - if ($this->isProcessRunning()) { - // kill process - $isProcessKilled = posix_kill($this->process_id, 9); - - if (! $isProcessKilled) { - throw new Exception('Something wrong happened, process could not be killed.'); - } - } - - $this->process_id = null; - $this->status = TaskStatus::Canceled; - $this->ended_at = Time::now(); - $this->save(); - } - - public function delete(): void - { - if ($this->isProcessRunning()) { - $this->cancel(); - } - - $importQueue = service('settings') - ->get('Import.queue') ?? []; - - if ($importQueue === []) { - return; - } - - unset($importQueue[$this->id]); - - service('settings') - ->set('Import.queue', $importQueue); - } - - public function fail(string $message): void - { - $this->error = $message; - - $this->status = TaskStatus::Failed; - $this->ended_at = Time::now(); - $this->save(); - - service('settings') - ->forget('Import.current'); - } - - public function save(): void - { - $importQueue = service('settings') - ->get('Import.queue') ?? []; - - $now = Time::now(); - - if (! array_key_exists($this->id, $importQueue)) { - $this->created_at = $now; - } - - $this->updated_at = $now; - - $importQueue[$this->id] = $this; - - service('settings') - ->set('Import.queue', $importQueue); - } - - public function syncWithProcess(): void - { - if ($this->status !== TaskStatus::Running && $this->process_id !== null) { - $this->process_id = null; - $this->save(); - return; - } - - if ($this->status === TaskStatus::Running && $this->process_id === null) { - $this->fail('Running task has no process id set.'); - return; - } - - if (! $this->isProcessRunning()) { - $this->fail('Process was killed.'); - return; - } - } - - private function isProcessRunning(): bool - { - if ($this->process_id === null) { - return false; - } - - return posix_getpgid($this->process_id) !== false; - } -} diff --git a/modules/PodcastImport/Entities/TaskStatus.php b/modules/PodcastImport/Entities/TaskStatus.php deleted file mode 100644 index 53246d0f..00000000 --- a/modules/PodcastImport/Entities/TaskStatus.php +++ /dev/null @@ -1,14 +0,0 @@ -get('Import.queue') ?? []; - - if ($podcastHandle !== null) { - $podcastImportsQueue = array_filter( - $podcastImportsQueue, - static fn (PodcastImportTask $importTask): bool => $importTask->handle === $podcastHandle, - ); - } - - usort($podcastImportsQueue, static function (PodcastImportTask $a, PodcastImportTask $b): int { - if ($a->status === $b->status) { - return $a->created_at->isAfter($b->created_at) ? -1 : 1; - } - - if ($a->status === TaskStatus::Running) { - return -1; - } - - if ($a->status === TaskStatus::Queued && $b->status !== TaskStatus::Running) { - return -1; - } - - return $a->created_at->isAfter($b->created_at) ? -1 : 1; - }); - - return $podcastImportsQueue; - } -} diff --git a/modules/PodcastImport/Language/ar/PodcastImport.php b/modules/PodcastImport/Language/ar/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/ar/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/br/PodcastImport.php b/modules/PodcastImport/Language/br/PodcastImport.php deleted file mode 100644 index c4f01d81..00000000 --- a/modules/PodcastImport/Language/br/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Enporzhiañ', - 'text' => 'Emañ {podcastTitle} o vezañ enporzhiet.', - 'cta' => 'Gwelet stad an enporzh', - ], - 'old_podcast_section_title' => 'Ar podkast da vezañ enporzhiet', - 'old_podcast_legal_disclaimer_title' => 'Menegoù lezennel', - 'old_podcast_legal_disclaimer' => - 'Bezit sur oc\'h aotreet da enporzhiañ ar podkast-mañ a-raok en ober. Eilañ ha skignañ ur podkast hep kaout an aotre a zo heñvel ouzh dambreziñ ha gallout a reer bezañ kaset d\'al lez-varn.', - 'imported_feed_url' => 'URL ar wazh', - 'imported_feed_url_hint' => 'Rankout a ra ar wazh bezañ er furmad xml pe rss.', - 'new_podcast_section_title' => 'Ar podkast nevez', - 'lock_import' => - 'Gwarezet eo ar wazh-mañ. Ne c\'hallit ket enporzhiañ anezhi. Ma\'z oc\'h ar perc\'henn·ez, dibrennit anezhi war ar savenn orin.', - 'submit' => 'Ouzhpennañ an enporzh d\'al lost', - 'queue' => [ - 'status' => [ - 'label' => 'Statud', - 'queued' => 'el lost', - 'queued_hint' => 'Emañ an enporzh el lost.', - 'canceled' => 'nullet', - 'canceled_hint' => 'Nullet eo bet an enporzh.', - 'running' => 'war ar stern', - 'running_hint' => 'Emañ an enporzh war ar stern.', - 'failed' => 'c\'hwitet', - 'failed_hint' => 'An enporzh n\'eo ket bet graet: fazi skript.', - 'passed' => 'berzh', - 'passed_hint' => 'Enporzhiet eo bet gant berzh!', - ], - 'feed' => 'Gwazh', - 'duration' => 'Padelezh an enporzh', - 'imported_episodes' => 'Rannoù enporzhiet', - 'imported_episodes_hint' => '{newlyImportedCount} enporzhiet nevez zo, {alreadyImportedCount} enporzhiet en holl.', - 'actions' => [ - 'cancel' => 'Nullañ', - 'retry' => 'Klask en-dro', - 'delete' => 'Dilemel', - ], - ], - 'syncForm' => [ - 'title' => 'Sinkronekaat ar gwazhoù', - 'feed_url' => 'URL ar wazh', - 'feed_url_hint' => 'URL ar wazh ho peus c\'hoant da sinkronekaat ouzh ar podkast-mañ.', - 'submit' => 'Ouzhpennañ d\'al lost', - ], - 'messages' => [ - 'canceled' => 'An enporzh zo bet nullet gant berzh!', - 'notRunning' => 'Ne c\'haller ket nullañ an enporzh rak n\'eo ket krog al labour.', - 'alreadyRunning' => 'Emañ an enporzh war ar stern. Gallout a rit nullañ anezhañ a-raok klask en-dro.', - 'retried' => 'Ouzhpennet eo bet an enporzh d\'al lost, klasket e vo en-dro dindan berr!', - 'deleted' => 'An enporzh zo bet dilamet gant berzh!', - 'importTaskQueued' => 'Un enporzh nevez zo bet ouzhpennet d\'al lost, kroget e vo dindan berr!', - 'syncTaskQueued' => 'Un enporzh nevez zo bet ouzhpennet d\'al lost, kroget e vo ar sinkronekaat dindan berr!', - ], -]; diff --git a/modules/PodcastImport/Language/ca/PodcastImport.php b/modules/PodcastImport/Language/ca/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/ca/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/da/PodcastImport.php b/modules/PodcastImport/Language/da/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/da/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/de/PodcastImport.php b/modules/PodcastImport/Language/de/PodcastImport.php deleted file mode 100644 index 0cfa75f6..00000000 --- a/modules/PodcastImport/Language/de/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'Importstatus anzeigen', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'in Warteschlangen', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'abgebrochen', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'läuft', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'fehlgeschlagen', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'bestanden', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Abbrechen', - 'retry' => 'Erneut versuchen', - 'delete' => 'Löschen', - ], - ], - 'syncForm' => [ - 'title' => 'Feeds synchronisieren', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Zur Warteschlange hinzufügen', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/el/PodcastImport.php b/modules/PodcastImport/Language/el/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/el/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/en/PodcastImport.php b/modules/PodcastImport/Language/en/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/en/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/es/PodcastImport.php b/modules/PodcastImport/Language/es/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/es/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/eu/PodcastImport.php b/modules/PodcastImport/Language/eu/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/eu/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/fa/PodcastImport.php b/modules/PodcastImport/Language/fa/PodcastImport.php deleted file mode 100644 index cf5f4592..00000000 --- a/modules/PodcastImport/Language/fa/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'درون‌ریزی', - 'text' => '{podcastTitle} دارد درون‌ریخته می‌شود.', - 'cta' => 'دیدن وضعیت درون‌ریزی', - ], - 'old_podcast_section_title' => 'پادکست برای درون‌ریزی', - 'old_podcast_legal_disclaimer_title' => 'سلب مسئولیت حقوقی', - 'old_podcast_legal_disclaimer' => - 'پیش از درون‌ریزی مطمئن شوید حقوق این پادکست را دارید. رونوشت و پخش یک پادکست بدون حقوق مناسب دزدی دریایی حساب شده و قابل پیگرد است.', - 'imported_feed_url' => 'نشانی خوراک', - 'imported_feed_url_hint' => 'خورام باید در قالب xml یا rss باشد.', - 'new_podcast_section_title' => 'پادکست جدید', - 'lock_import' => - 'این خوراک محافظت شده است. نمی‌توانید درون‌ریزیش کنید. اگر مالکش هستید، روی بن‌سازهٔ اصلی قفل‌گشاییش کنید.', - 'submit' => 'افزودن درون‌ریزی به صف', - 'queue' => [ - 'status' => [ - 'label' => 'وضعیت', - 'queued' => 'صف شده', - 'queued_hint' => 'وظیفهٔ درون‌ریزی منتظر پردازش است.', - 'canceled' => 'لغو شده', - 'canceled_hint' => 'وظیفهٔ درون‌ریزی لغو شد.', - 'running' => 'درحال اجرا', - 'running_hint' => 'وظیفهٔ درون‌ریزی در حال پردازش است.', - 'failed' => 'شکست خورده', - 'failed_hint' => 'وظیفهٔ درون‌ریزی نتوانست کامل شود: شکست کدنوشته.', - 'passed' => 'قبول شده', - 'passed_hint' => 'وظیفهٔ درون‌ریزی با موفّقیت کامل شد!', - ], - 'feed' => 'خوراک', - 'duration' => 'طول درون‌ریزی', - 'imported_episodes' => 'قسمت‌های درون‌ریخته', - 'imported_episodes_hint' => '{newlyImportedCount} به تازگی درون‌ریخته. {alreadyImportedCount} از پیش درون‌ریخته.', - 'actions' => [ - 'cancel' => 'لغو', - 'retry' => 'تلاش دوباره', - 'delete' => 'حذف', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'وظیفهٔ درون‌ریزی با موفّقیت لغو شد!', - 'notRunning' => 'نمی‌توان وظیفهٔ درون‌ریزی را لغو کرد؛ چرا که در حال اجرا نیست.', - 'alreadyRunning' => 'وظیفهٔ درون‌ریزی در حال اجراست. پیش از تلاش دوباره باید لغوش کنید.', - 'retried' => 'وظیفهٔ درون‌ریزی صف شد. به زودی دوباره انجام خواهد شد!', - 'deleted' => 'وظیفهٔ درون‌ریزی با موفّقیت حذف شد!', - 'importTaskQueued' => 'وظیفه‌ای جدید صف شد. درون‌ریزی به زودی آغاز خواهد شد!', - 'syncTaskQueued' => 'وظیفهٔ درون‌ریزی جدیدی صف شد. هم‌گام سازی به زودی آغاز خواهد شد!', - ], -]; diff --git a/modules/PodcastImport/Language/fr-ca/PodcastImport.php b/modules/PodcastImport/Language/fr-ca/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/fr-ca/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/fr/PodcastImport.php b/modules/PodcastImport/Language/fr/PodcastImport.php deleted file mode 100644 index c9187b7d..00000000 --- a/modules/PodcastImport/Language/fr/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importation', - 'text' => '{podcastTitle} est actuellement en cours d\'import.', - 'cta' => 'Voir l\'état d\'import', - ], - 'old_podcast_section_title' => 'Le podcast à importer', - 'old_podcast_legal_disclaimer_title' => 'Avertissement légal', - 'old_podcast_legal_disclaimer' => - 'Assurez-vous d’être détenteur des droits du podcast avant de l’importer. Copier et diffuser un podcast sans en détenir les droits est assimilable à de la contrefaçon et est passible de poursuites.', - 'imported_feed_url' => 'Adresse du flux', - 'imported_feed_url_hint' => 'Le flux doit être au format xml ou rss.', - 'new_podcast_section_title' => 'Le nouveau podcast', - 'lock_import' => - 'Ce flux est protégé. Vous ne pouvez pas l’importer. Si en vous êtes le propriétaire, déverrouillez-le sur la plate-forme d’origine.', - 'submit' => 'Ajouter l\'import à la file d\'attente', - 'queue' => [ - 'status' => [ - 'label' => 'État', - 'queued' => 'en attente', - 'queued_hint' => 'L’import est dans la file d’attente.', - 'canceled' => 'annulé', - 'canceled_hint' => 'L’import a été annulé.', - 'running' => 'en cours', - 'running_hint' => 'L’import est en cours de traitement.', - 'failed' => 'échec', - 'failed_hint' => 'L’import n’a pas pu se terminer : échec du script.', - 'passed' => 'succès', - 'passed_hint' => 'L’import a été complété avec succès !', - ], - 'feed' => 'Flux', - 'duration' => 'Durée de l’import', - 'imported_episodes' => 'Épisodes importés', - 'imported_episodes_hint' => '{newlyImportedCount} vient d\'être importé, {alreadyImportedCount} a déjà été importé.', - 'actions' => [ - 'cancel' => 'Annuler', - 'retry' => 'Réessayer', - 'delete' => 'Supprimer', - ], - ], - 'syncForm' => [ - 'title' => 'Synchroniser les flux', - 'feed_url' => 'Adresse du flux', - 'feed_url_hint' => 'L\'URL du flux que vous voulez synchroniser avec le podcast actuel.', - 'submit' => 'Ajouter à la file d\'attente', - ], - 'messages' => [ - 'canceled' => 'L’import a été annulé avec succès !', - 'notRunning' => 'Impossible d’annuler l’import car il n’est pas en cours d’exécution.', - 'alreadyRunning' => 'L’import est déjà en cours d’exécution. Vous devez l’annuler avant de réessayer.', - 'retried' => 'L’import a été placé dans la file d’attente, il sera exécuté sous peu !', - 'deleted' => 'L’import a bien été supprimé !', - 'importTaskQueued' => 'Une nouvelle tâche a été mise attente, l’import va bientôt commencer !', - 'syncTaskQueued' => 'Une nouvelle tâche a été mise attente, la synchronisation va bientôt commencer !', - ], -]; diff --git a/modules/PodcastImport/Language/fr2/PodcastImport.php b/modules/PodcastImport/Language/fr2/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/fr2/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/gd/PodcastImport.php b/modules/PodcastImport/Language/gd/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/gd/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/gl/PodcastImport.php b/modules/PodcastImport/Language/gl/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/gl/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/id/PodcastImport.php b/modules/PodcastImport/Language/id/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/id/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/it/PodcastImport.php b/modules/PodcastImport/Language/it/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/it/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/ja/PodcastImport.php b/modules/PodcastImport/Language/ja/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/ja/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/kk/PodcastImport.php b/modules/PodcastImport/Language/kk/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/kk/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/ko/PodcastImport.php b/modules/PodcastImport/Language/ko/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/ko/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/nl/PodcastImport.php b/modules/PodcastImport/Language/nl/PodcastImport.php deleted file mode 100644 index 831e798b..00000000 --- a/modules/PodcastImport/Language/nl/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importeren', - 'text' => '{podcastTitle} wordt momenteel geïmporteerd.', - 'cta' => 'Bekijk importstatus', - ], - 'old_podcast_section_title' => 'De te importeren podcast', - 'old_podcast_legal_disclaimer_title' => 'Wettelijke disclaimer', - 'old_podcast_legal_disclaimer' => - 'Zorg ervoor dat je de rechten hebt voor deze podcast voordat je deze importeert. Het kopiëren en uitzenden van een podcast zonder de juiste rechten is piraterij en kan vervolgd worden.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'De feed moet in xml of rss formaat zijn.', - 'new_podcast_section_title' => 'De nieuwe podcast', - 'lock_import' => - 'Deze feed is beschermd. U kunt deze niet importeren. Als u de eigenaar bent, ontgrendel het op het oorsprongsplatform.', - 'submit' => 'Import toevoegen aan wachtrij', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'in wachtrij', - 'queued_hint' => 'Import taak is in afwachting van verwerking.', - 'canceled' => 'geannuleerd', - 'canceled_hint' => 'Importtaak is geannuleerd.', - 'running' => 'actief', - 'running_hint' => 'Import taak wordt verwerkt.', - 'failed' => 'mislukt', - 'failed_hint' => 'Import taak kon niet voltooid worden: script mislukt.', - 'passed' => 'geslaagd', - 'passed_hint' => 'Import taak is succesvol voltooid!', - ], - 'feed' => 'Feed', - 'duration' => 'Duur van importeren', - 'imported_episodes' => 'Geïmporteerde afleveringen', - 'imported_episodes_hint' => '{newlyImportedCount} onlangs geïmporteerd, {alreadyImportedCount} reeds geïmporteerd.', - 'actions' => [ - 'cancel' => 'Annuleer', - 'retry' => 'Opnieuw proberen', - 'delete' => 'Verwijderen', - ], - ], - 'syncForm' => [ - 'title' => 'Feeds synchroniseren', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'De feed-URL die u wilt synchroniseren met de huidige podcast.', - 'submit' => 'Aan wachtrij toevoegen', - ], - 'messages' => [ - 'canceled' => 'Import taak is succesvol geannuleerd!', - 'notRunning' => 'De Import taak kan niet worden geannuleerd omdat deze niet wordt uitgevoerd.', - 'alreadyRunning' => 'Import taak is al actief. U kunt deze annuleren voordat u opnieuw probeert.', - 'retried' => 'Import taak is in de wachtrij gezet, deze zal binnenkort opnieuw worden geprobeerd!', - 'deleted' => 'Import taak is succesvol verwijderd!', - 'importTaskQueued' => 'Een nieuwe taak is in de wachtrij gezet, de import zal binnenkort beginnen!', - 'syncTaskQueued' => 'Een nieuwe taak is in de wachtrij gezet, de import zal binnenkort beginnen!', - ], -]; diff --git a/modules/PodcastImport/Language/nn-no/PodcastImport.php b/modules/PodcastImport/Language/nn-no/PodcastImport.php deleted file mode 100644 index 83cdd088..00000000 --- a/modules/PodcastImport/Language/nn-no/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importerer', - 'text' => '{podcastTitle} blir importert.', - 'cta' => 'Sjå status på importen', - ], - 'old_podcast_section_title' => 'Podkast å importera', - 'old_podcast_legal_disclaimer_title' => 'Juridisk ansvarsfråskriving', - 'old_podcast_legal_disclaimer' => - 'Syt for at du har rettane til podkasten før du importerer han. Å kopiera og kringkasta ein podkast utan løyve er ulovleg og straffbart.', - 'imported_feed_url' => 'URL til straumen', - 'imported_feed_url_hint' => 'Straumen må vera i xml- eller rss-format.', - 'new_podcast_section_title' => 'Den nye podkasten', - 'lock_import' => - 'Denne straumen er verna. Du kan ikkje importera han. Viss du er eigaren, må du låsa han opp på den originale plattforma.', - 'submit' => 'Legg importen i køen', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'i kø', - 'queued_hint' => 'Importjobben ventar på å bli utført.', - 'canceled' => 'avbrote', - 'canceled_hint' => 'Importjobben vart avbroten.', - 'running' => 'køyrer', - 'running_hint' => 'Utfører importoppgåva.', - 'failed' => 'mislukka', - 'failed_hint' => 'Greidde ikkje fullføra importen: skriptfeil.', - 'passed' => 'utført', - 'passed_hint' => 'Importen var vellukka.', - ], - 'feed' => 'Straum', - 'duration' => 'Kor lenge importen vara', - 'imported_episodes' => 'Importerte episodar', - 'imported_episodes_hint' => '{newlyImportedCount} nyss importerte, {alreadyImportedCount} allereie importerte.', - 'actions' => [ - 'cancel' => 'Avbryt', - 'retry' => 'Prøv på nytt', - 'delete' => 'Slett', - ], - ], - 'syncForm' => [ - 'title' => 'Synkroniser straumar', - 'feed_url' => 'URL til straumen', - 'feed_url_hint' => 'URL til straumen du vil synkronisera med denne podkasten.', - 'submit' => 'Legg til i køen', - ], - 'messages' => [ - 'canceled' => 'Importen vart avbroten.', - 'notRunning' => 'Kan ikkje avbryta importen, fordi han ikkje køyrer.', - 'alreadyRunning' => 'Importen er i gang. Du kan avbryta han før du prøver på nytt.', - 'retried' => 'Importjobben er lagt i køen, og vil bli prøvd på nytt straks.', - 'deleted' => 'Importjobben er sletta.', - 'importTaskQueued' => 'Ein ny jobb er lagd i køen, og importen startar straks.', - 'syncTaskQueued' => 'Ein ny importjobb er lagd i køen, og synkroniseringa startar straks.', - ], -]; diff --git a/modules/PodcastImport/Language/oc/PodcastImport.php b/modules/PodcastImport/Language/oc/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/oc/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/pl/PodcastImport.php b/modules/PodcastImport/Language/pl/PodcastImport.php deleted file mode 100644 index 525f4327..00000000 --- a/modules/PodcastImport/Language/pl/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importowanie', - 'text' => '{podcastTitle} jest obecnie importowany.', - 'cta' => 'Zobacz status importu', - ], - 'old_podcast_section_title' => 'Podcast do zaimportowania', - 'old_podcast_legal_disclaimer_title' => 'Zastrzeżenie prawne', - 'old_podcast_legal_disclaimer' => - 'Upewnij się, że masz prawa do tego podcastu zanim go zaimportujesz. Kopiowanie i nadawanie podcastu bez odpowiednich praw jest piractwem i podlega ściganiu.', - 'imported_feed_url' => 'Adres URL kanału', - 'imported_feed_url_hint' => 'Kanał musi być w formacie xml lub rss.', - 'new_podcast_section_title' => 'Nowy podcast', - 'lock_import' => - 'Ten kanał jest chroniony. Nie możesz go zaimportować. Jeśli jesteś jego właścicielem — usuń ochronę na platformie, z której pochodzi.', - 'submit' => 'Dodaj import do kolejki', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'w kolejce', - 'queued_hint' => 'Import czeka na przetworzenie.', - 'canceled' => 'anulowano', - 'canceled_hint' => 'Zadanie importu zostało anulowane.', - 'running' => 'w toku', - 'running_hint' => 'Import jest przetwarzany.', - 'failed' => 'niepowodzenie', - 'failed_hint' => 'Zadanie importu nie powiodło się: błąd skryptu.', - 'passed' => 'powodzenie', - 'passed_hint' => 'Zadanie importu zostało zakończone pomyślnie!', - ], - 'feed' => 'Kanał', - 'duration' => 'Czas trwania importu', - 'imported_episodes' => 'Zaimportowane odcinki', - 'imported_episodes_hint' => '{newlyImportedCount} nowoimportowanych, {alreadyImportedCount} już zaimportowanych.', - 'actions' => [ - 'cancel' => 'Anuluj', - 'retry' => 'Ponów', - 'delete' => 'Usuń', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronizuj kanały', - 'feed_url' => 'Adres URL kanału', - 'feed_url_hint' => 'URL kanału, który chcesz zsynchronizować z bieżącym podcastem.', - 'submit' => 'Dodaj do kolejki', - ], - 'messages' => [ - 'canceled' => 'Zadanie importu zostało pomyślnie anulowane!', - 'notRunning' => 'Nie można anulować importu, ponieważ nie jest on uruchomiony.', - 'alreadyRunning' => 'Zadanie importu jest już uruchomione. Możesz je anulować przed ponowną próbą.', - 'retried' => 'Zadanie importu zostało umieszczone w kolejce, zostanie ono wkrótce ponowione!', - 'deleted' => 'Zadanie importu zostało pomyślnie usunięte!', - 'importTaskQueued' => 'Nowe zadanie zostało dodane, import rozpocznie się wkrótce!', - 'syncTaskQueued' => 'Nowe zadanie importu zostało dodane, synchronizacja rozpocznie się wkrótce!', - ], -]; diff --git a/modules/PodcastImport/Language/pt-br/PodcastImport.php b/modules/PodcastImport/Language/pt-br/PodcastImport.php deleted file mode 100644 index ae81ff90..00000000 --- a/modules/PodcastImport/Language/pt-br/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importando', - 'text' => '{podcastTitle} está sendo importado no momento.', - 'cta' => 'Ver status de importação', - ], - 'old_podcast_section_title' => 'O podcast para importar', - 'old_podcast_legal_disclaimer_title' => 'Aviso legal', - 'old_podcast_legal_disclaimer' => - 'Certifique-se de possuir os direitos para esse podcast antes de importá-lo. Copiar e transmitir um podcast sem os direitos adequados é pirataria e corre-se o risco de processo legal.', - 'imported_feed_url' => 'URL do feed', - 'imported_feed_url_hint' => 'O feed deve estar no formato xml ou rss.', - 'new_podcast_section_title' => 'O novo podcast', - 'lock_import' => - 'Este feed está protegido. Você não pode importá-lo. Se é o dono, desbloqueie-o na plataforma de origem.', - 'submit' => 'Adicionar importação à fila', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'na fila', - 'queued_hint' => 'Tarefa de importação está aguardando para ser processada.', - 'canceled' => 'cancelado', - 'canceled_hint' => 'Tarefa de importação foi cancelada.', - 'running' => 'executando', - 'running_hint' => 'Tarefa de importação está sendo processada.', - 'failed' => 'falhou', - 'failed_hint' => 'Tarefa de importação não pôde ser concluída: falha no script.', - 'passed' => 'aprovado', - 'passed_hint' => 'Tarefa de importação foi concluída com sucesso!', - ], - 'feed' => 'Feed', - 'duration' => 'Duração da importação', - 'imported_episodes' => 'Episódios importados', - 'imported_episodes_hint' => '{newlyImportedCount} recém importado, {alreadyImportedCount} já importado.', - 'actions' => [ - 'cancel' => 'Cancelar', - 'retry' => 'Tente novamente', - 'delete' => 'Excluir', - ], - ], - 'syncForm' => [ - 'title' => 'Sincronizar o feed', - 'feed_url' => 'URL do feed', - 'feed_url_hint' => 'A URL do feed que você deseja sincronizar com o podcast atual.', - 'submit' => 'Adicionar à fila', - ], - 'messages' => [ - 'canceled' => 'Tarefa de importação foi cancelada com sucesso!', - 'notRunning' => 'Não é possível cancelar a tarefa de importação, pois ela não está em execução.', - 'alreadyRunning' => 'Tarefa de Importação já está em execução. Você pode cancelá-la antes de tentar novamente.', - 'retried' => 'Tarefa de importação foi enfileirada, ela será repetida em breve!', - 'deleted' => 'Tarefa de importação foi cancelada com sucesso!', - 'importTaskQueued' => 'Uma nova tarefa foi colocada na fila, a importação será iniciada em breve!', - 'syncTaskQueued' => 'Uma nova tarefa de importação foi colocada na fila, a sincronização começará em breve!', - ], -]; diff --git a/modules/PodcastImport/Language/pt/PodcastImport.php b/modules/PodcastImport/Language/pt/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/pt/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/ro/PodcastImport.php b/modules/PodcastImport/Language/ro/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/ro/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/ru/PodcastImport.php b/modules/PodcastImport/Language/ru/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/ru/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/sk/PodcastImport.php b/modules/PodcastImport/Language/sk/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/sk/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/sr-latn/PodcastImport.php b/modules/PodcastImport/Language/sr-latn/PodcastImport.php deleted file mode 100644 index 504175b7..00000000 --- a/modules/PodcastImport/Language/sr-latn/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Uvoz', - 'text' => '{podcastTitle} se trenutno uvozi.', - 'cta' => 'Pogledaj status uvoza', - ], - 'old_podcast_section_title' => 'Podkast koji se uvozi', - 'old_podcast_legal_disclaimer_title' => 'Pravno odricanje od odgovornosti', - 'old_podcast_legal_disclaimer' => - 'Uverite se da posedujete prava za ovaj podkast pre nego što ga uvezete. Kopiranje i emitovanje podkasta bez odgovarajućih prava je piraterija i podložno je krivičnom gonjenju.', - 'imported_feed_url' => 'URL snabdevača', - 'imported_feed_url_hint' => 'Snabdevač mora biti u xml ili rss formatu.', - 'new_podcast_section_title' => 'Novi podkast', - 'lock_import' => - 'Ovaj snabdevač je zaštićen. Ne možete ga uvesti. Ukoliko ste vlasnik, otključajte snabdevač na originalnoj platformi na kojoj ste ga napravili.', - 'submit' => 'Dodaj uvoz na čekanje', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'čekanje', - 'queued_hint' => 'Zadatak uvoza čeka na obradu.', - 'canceled' => 'otkazano', - 'canceled_hint' => 'Zadatak uvoza je otkazan.', - 'running' => 'u toku', - 'running_hint' => 'Zadatak uvoza se procesuira.', - 'failed' => 'nije uspеlo', - 'failed_hint' => 'Zadatak uvoza nije mogao da se završi: greška skripte.', - 'passed' => 'pauzirano', - 'passed_hint' => 'Zadatak uvoza uspešno obavljen!', - ], - 'feed' => 'Snabdevač', - 'duration' => 'Trajanje uvoza', - 'imported_episodes' => 'Uvežene epizode', - 'imported_episodes_hint' => '{newlyImportedCount} novo uvežena, {alreadyImportedCount} već uveženih.', - 'actions' => [ - 'cancel' => 'Otkaži', - 'retry' => 'Pokušaj ponovo', - 'delete' => 'Obriši', - ], - ], - 'syncForm' => [ - 'title' => 'Sinhronizuj snabdevače', - 'feed_url' => 'URL snabdevača', - 'feed_url_hint' => 'URL veza snabdevača koju želite da sinhronizujete sa trenutnim podkastom.', - 'submit' => 'Dodaj u redosled', - ], - 'messages' => [ - 'canceled' => 'Zadatak uvoza uspešno otkazan!', - 'notRunning' => 'Nije moguće otkazati zadatak uvoza jer isti nije u toku.', - 'alreadyRunning' => 'Zadatak uvoza je u toku. Možete ga otkazati pre ponovnog pokušaja.', - 'retried' => 'Zadatak uvoza je na čekanju, biće pokušan ponovo uskoro!', - 'deleted' => 'Zadatak uvoza uspešno obrisan!', - 'importTaskQueued' => 'Novi zadatak je na čekanju, uvoz će krenuti uskoro!', - 'syncTaskQueued' => 'Novi zadatak uvoza je na čekanju, sinhronizacija će početi uskoro!', - ], -]; diff --git a/modules/PodcastImport/Language/sv/PodcastImport.php b/modules/PodcastImport/Language/sv/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/sv/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/uk/PodcastImport.php b/modules/PodcastImport/Language/uk/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/uk/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PodcastImport/Language/zh-hans/PodcastImport.php b/modules/PodcastImport/Language/zh-hans/PodcastImport.php deleted file mode 100644 index ca714eec..00000000 --- a/modules/PodcastImport/Language/zh-hans/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => '输入', - 'text' => '{podcastTitle} 正在导入中。', - 'cta' => '查看导入状态', - ], - 'old_podcast_section_title' => '要导入的播客', - 'old_podcast_legal_disclaimer_title' => '法律免责声明', - 'old_podcast_legal_disclaimer' => - '请确保您在导入之前拥有此播客的权限。 在没有权限的情况下复制和广播播客是盗版行为,可能受到起诉。', - 'imported_feed_url' => '摘要 URL', - 'imported_feed_url_hint' => '摘要必须是 xml 或 rss 格式。', - 'new_podcast_section_title' => '新播客', - 'lock_import' => - '该摘要受到保护。 您无法导入它。 如果您是所有者,请在源平台解锁。', - 'submit' => '添加导入到队列', - 'queue' => [ - 'status' => [ - 'label' => '状态', - 'queued' => '队列', - 'queued_hint' => '导入任务正在等待处理。', - 'canceled' => '已取消', - 'canceled_hint' => '导入任务已取消。', - 'running' => '运行中', - 'running_hint' => '导入任务正在处理中。', - 'failed' => '已失败', - 'failed_hint' => '导入任务无法完成:脚本失败。', - 'passed' => '已通过', - 'passed_hint' => '导入任务顺利完成!', - ], - 'feed' => '摘要', - 'duration' => '导入时长', - 'imported_episodes' => '导入剧集', - 'imported_episodes_hint' => '{newlyImportedCount} 新导入, {alreadyImportedCount} 已经导入。', - 'actions' => [ - 'cancel' => '取消', - 'retry' => '重试', - 'delete' => '删除', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => '导入任务已成功取消!', - 'notRunning' => '无法取消导入任务,因为它未运行。', - 'alreadyRunning' => '导入任务已在运行。 您可以在重试之前取消它。', - 'retried' => '导入任务已排队,稍后将重试!', - 'deleted' => '导入任务已成功删除!', - 'importTaskQueued' => '新任务已排队,导入即将开始!', - 'syncTaskQueued' => '新的导入任务已排队,即将开始同步!', - ], -]; diff --git a/modules/PodcastImport/Language/zh-hant/PodcastImport.php b/modules/PodcastImport/Language/zh-hant/PodcastImport.php deleted file mode 100644 index cac52509..00000000 --- a/modules/PodcastImport/Language/zh-hant/PodcastImport.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'disclaimer' => 'Importing', - 'text' => '{podcastTitle} is currently being imported.', - 'cta' => 'See import status', - ], - 'old_podcast_section_title' => 'The podcast to import', - 'old_podcast_legal_disclaimer_title' => 'Legal disclaimer', - 'old_podcast_legal_disclaimer' => - 'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.', - 'imported_feed_url' => 'Feed URL', - 'imported_feed_url_hint' => 'The feed must be in xml or rss format.', - 'new_podcast_section_title' => 'The new podcast', - 'lock_import' => - 'This feed is protected. You cannot import it. If you are the owner, unlock it on the origin platform.', - 'submit' => 'Add import to queue', - 'queue' => [ - 'status' => [ - 'label' => 'Status', - 'queued' => 'queued', - 'queued_hint' => 'Import task is awaiting to be processed.', - 'canceled' => 'canceled', - 'canceled_hint' => 'Import task was canceled.', - 'running' => 'running', - 'running_hint' => 'Import task is being processed.', - 'failed' => 'failed', - 'failed_hint' => 'Import task could not complete: script failure.', - 'passed' => 'passed', - 'passed_hint' => 'Import task was completed successfully!', - ], - 'feed' => 'Feed', - 'duration' => 'Import duration', - 'imported_episodes' => 'Imported episodes', - 'imported_episodes_hint' => '{newlyImportedCount} newly imported, {alreadyImportedCount} already imported.', - 'actions' => [ - 'cancel' => 'Cancel', - 'retry' => 'Retry', - 'delete' => 'Delete', - ], - ], - 'syncForm' => [ - 'title' => 'Synchronize feeds', - 'feed_url' => 'Feed URL', - 'feed_url_hint' => 'The feed URL you want to synchronize with the current podcast.', - 'submit' => 'Add to queue', - ], - 'messages' => [ - 'canceled' => 'Import task has been successfully canceled!', - 'notRunning' => 'Cannot cancel Import Task as it is not running.', - 'alreadyRunning' => 'Import Task is already running. You may cancel it before retrying.', - 'retried' => 'Import task has been queued, it will be retried shortly!', - 'deleted' => 'Import task has been successfully deleted!', - 'importTaskQueued' => 'A new task has been queued, import will start shortly!', - 'syncTaskQueued' => 'A new import task has been queued, synchronization will start shortly!', - ], -]; diff --git a/modules/PremiumPodcasts/Config/Registrar.php b/modules/PremiumPodcasts/Config/Registrar.php deleted file mode 100644 index 17d66880..00000000 --- a/modules/PremiumPodcasts/Config/Registrar.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ - public static function Filters(): array - { - return [ - 'aliases' => [ - 'podcast-unlock' => PodcastUnlockFilter::class, - ], - ]; - } -} diff --git a/modules/PremiumPodcasts/Config/Routes.php b/modules/PremiumPodcasts/Config/Routes.php index 80d19586..2859b596 100644 --- a/modules/PremiumPodcasts/Config/Routes.php +++ b/modules/PremiumPodcasts/Config/Routes.php @@ -4,9 +4,7 @@ declare(strict_types=1); namespace Modules\PremiumPodcasts\Config; -use CodeIgniter\Router\RouteCollection; - -/** @var RouteCollection $routes */ +$routes = service('routes'); $routes->addPlaceholder('podcastHandle', '[a-zA-Z0-9\_]{1,32}'); @@ -20,95 +18,106 @@ $routes->group( static function ($routes): void { $routes->group('podcasts/(:num)/subscriptions', static function ($routes): void { $routes->get('/', 'SubscriptionController::list/$1', [ - 'as' => 'subscription-list', - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'as' => 'subscription-list', + 'filter' => + 'permission:podcasts-view,podcast-manage_subscriptions', ]); - $routes->get('new', 'SubscriptionController::createView/$1', [ - 'as' => 'subscription-create', - 'filter' => 'permission:podcast$1.manage-subscriptions', + $routes->get('add', 'SubscriptionController::add/$1', [ + 'as' => 'subscription-add', + 'filter' => 'permission:podcast-manage_subscriptions', ]); $routes->post( - 'new', - 'SubscriptionController::createAction/$1', + 'add', + 'SubscriptionController::attemptAdd/$1', [ - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'filter' => + 'permission:podcast-manage_subscriptions', ], ); - $routes->post('save-link', 'SubscriptionController::linkSaveAction/$1', [ - 'as' => 'subscription-link-save', - 'filter' => 'permission:podcast$1.manage-subscriptions', + $routes->post('save-link', 'SubscriptionController::attemptLinkSave/$1', [ + 'as' => 'subscription-link-save', + 'filter' => 'permission:podcast-manage_subscriptions', ]); // Subscription $routes->group('(:num)', static function ($routes): void { $routes->get('/', 'SubscriptionController::view/$1/$2', [ - 'as' => 'subscription-view', - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'as' => 'subscription-view', + 'filter' => + 'permission:podcast-manage_subscriptions', ]); $routes->get( 'edit', - 'SubscriptionController::editView/$1/$2', + 'SubscriptionController::edit/$1/$2', [ - 'as' => 'subscription-edit', - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'as' => 'subscription-edit', + 'filter' => + 'permission:podcast-manage_subscriptions', ], ); $routes->post( 'edit', - 'SubscriptionController::editAction/$1/$2', + 'SubscriptionController::attemptEdit/$1/$2', [ - 'as' => 'subscription-edit', - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'as' => 'subscription-edit', + 'filter' => + 'permission:podcast-manage_subscriptions', ], ); $routes->get( 'regenerate-token', 'SubscriptionController::regenerateToken/$1/$2', [ - 'as' => 'subscription-regenerate-token', - 'filter' => 'permission:podcast$1.manage-subscriptions', - ], + 'as' => 'subscription-regenerate-token', + 'filter' => + 'permission:podcast-manage_subscriptions', + ] ); $routes->get( 'suspend', 'SubscriptionController::suspend/$1/$2', [ - 'as' => 'subscription-suspend', - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'as' => 'subscription-suspend', + 'filter' => + 'permission:podcast-manage_subscriptions', ], ); $routes->post( 'suspend', - 'SubscriptionController::suspendAction/$1/$2', + 'SubscriptionController::attemptSuspend/$1/$2', [ - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'filter' => + 'permission:podcast-manage_subscriptions', ], ); $routes->get( 'resume', 'SubscriptionController::resume/$1/$2', [ - 'as' => 'subscription-resume', - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'as' => 'subscription-resume', + 'filter' => + 'permission:podcast-manage_subscriptions', ], ); $routes->get( 'delete', 'SubscriptionController::delete/$1/$2', [ - 'as' => 'subscription-delete', - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'as' => 'subscription-delete', + 'filter' => + 'permission:podcast-manage_subscriptions', ], ); $routes->post( 'delete', - 'SubscriptionController::deleteAction/$1/$2', + 'SubscriptionController::attemptDelete/$1/$2', [ - 'filter' => 'permission:podcast$1.manage-subscriptions', + 'filter' => + 'permission:podcast-manage_subscriptions', ], ); }); }); - }, + } ); $routes->group( @@ -117,14 +126,14 @@ $routes->group( 'namespace' => 'Modules\PremiumPodcasts\Controllers', ], static function ($routes): void { - $routes->get('unlock', 'LockController::index/$1', [ + $routes->get('unlock', 'LockController/$1', [ 'as' => 'premium-podcast-unlock', ]); - $routes->post('unlock', 'LockController::unlockAction/$1', [ + $routes->post('unlock', 'LockController::attemptUnlock/$1', [ 'as' => 'premium-podcast-unlock', ]); - $routes->get('lock', 'LockController::lockAction/$1', [ + $routes->get('lock', 'LockController::attemptLock/$1', [ 'as' => 'premium-podcast-lock', ]); - }, + } ); diff --git a/modules/PremiumPodcasts/Config/Services.php b/modules/PremiumPodcasts/Config/Services.php index 9ca49df7..c8fb03b4 100644 --- a/modules/PremiumPodcasts/Config/Services.php +++ b/modules/PremiumPodcasts/Config/Services.php @@ -4,23 +4,21 @@ declare(strict_types=1); namespace Modules\PremiumPodcasts\Config; -use CodeIgniter\Config\BaseService; +use Config\Services as BaseService; use Modules\PremiumPodcasts\Models\SubscriptionModel; use Modules\PremiumPodcasts\PremiumPodcasts; class Services extends BaseService { - public static function premium_podcasts( - ?SubscriptionModel $subscriptionModel = null, - bool $getShared = true, - ): PremiumPodcasts { + public static function premium_podcasts(?SubscriptionModel $subscriptionModel = null, bool $getShared = true) + { if ($getShared) { return self::getSharedInstance('premium_podcasts', $subscriptionModel); } $premiumPodcasts = new PremiumPodcasts(); - $subscriptionModel ??= model('SubscriptionModel'); + $subscriptionModel ??= model(SubscriptionModel::class); return $premiumPodcasts ->setSubscriptionModel($subscriptionModel); diff --git a/modules/PremiumPodcasts/Controllers/LockController.php b/modules/PremiumPodcasts/Controllers/LockController.php index b06efd09..68899039 100644 --- a/modules/PremiumPodcasts/Controllers/LockController.php +++ b/modules/PremiumPodcasts/Controllers/LockController.php @@ -34,7 +34,7 @@ class LockController extends BaseController throw PageNotFoundException::forPageNotFound(); } - if (! ($podcast = new PodcastModel()->getPodcastByHandle($params[0])) instanceof Podcast) { + if (($podcast = (new PodcastModel())->getPodcastByHandle($params[0])) === null) { throw PageNotFoundException::forPageNotFound(); } @@ -58,7 +58,7 @@ class LockController extends BaseController return view('podcast/unlock', $data); } - public function unlockAction(): RedirectResponse + public function attemptUnlock(): RedirectResponse { $rules = [ 'token' => 'required', @@ -70,9 +70,7 @@ class LockController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - $token = $validData['token']; + $token = (string) $this->request->getPost('token'); // attempt unlocking the podcast with the token if (! $this->premiumPodcasts->unlock($this->podcast->handle, $token)) { @@ -85,13 +83,12 @@ class LockController extends BaseController $redirectURL = session('redirect_url') ?? site_url('/'); unset($_SESSION['redirect_url']); - return redirect() - ->to($redirectURL) + return redirect()->to($redirectURL) ->withCookies() ->with('message', lang('PremiumPodcasts.messages.unlockSuccess')); } - public function lockAction(): RedirectResponse + public function attemptLock(): RedirectResponse { $this->premiumPodcasts->lock($this->podcast->handle); diff --git a/modules/PremiumPodcasts/Controllers/SubscriptionController.php b/modules/PremiumPodcasts/Controllers/SubscriptionController.php index 7ddf669a..055de5b8 100644 --- a/modules/PremiumPodcasts/Controllers/SubscriptionController.php +++ b/modules/PremiumPodcasts/Controllers/SubscriptionController.php @@ -32,7 +32,7 @@ class SubscriptionController extends BaseController throw PageNotFoundException::forPageNotFound(); } - if (! ($podcast = new PodcastModel()->getPodcastById((int) $params[0])) instanceof Podcast) { + if (($podcast = (new PodcastModel())->getPodcastById((int) $params[0])) === null) { throw PageNotFoundException::forPageNotFound(); } @@ -42,9 +42,7 @@ class SubscriptionController extends BaseController return $this->{$method}(); } - if (! ($this->subscription = new SubscriptionModel()->getSubscriptionById( - (int) $params[1], - )) instanceof Subscription) { + if (($this->subscription = (new SubscriptionModel())->getSubscriptionById((int) $params[1])) === null) { throw PageNotFoundException::forPageNotFound(); } @@ -59,14 +57,13 @@ class SubscriptionController extends BaseController helper('form'); - $this->setHtmlHead(lang('Subscription.podcast_subscriptions')); replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, + 0 => $this->podcast->title, ]); return view('subscription/list', $data); } - public function linkSaveAction(): RedirectResponse + public function attemptLinkSave(): RedirectResponse { $rules = [ 'subscription_link' => 'valid_url_strict|permit_empty', @@ -78,15 +75,13 @@ class SubscriptionController extends BaseController ->with('errors', $this->validator->getErrors()); } - $validData = $this->validator->getValidated(); - - if (($subscriptionLink = $validData['subscription_link']) === '') { + if (($subscriptionLink = $this->request->getPost('subscription_link')) === '') { service('settings') ->forget('Subscription.link', 'podcast:' . $this->podcast->id); return redirect()->route('subscription-list', [$this->podcast->id])->with( 'message', - lang('Subscription.messages.linkRemoveSuccess'), + lang('Subscription.messages.linkRemoveSuccess') ); } @@ -99,26 +94,25 @@ class SubscriptionController extends BaseController return redirect()->route('subscription-list', [$this->podcast->id])->with( 'message', - lang('Subscription.messages.linkSaveSuccess'), + lang('Subscription.messages.linkSaveSuccess') ); } public function view(): string { $data = [ - 'podcast' => $this->podcast, + 'podcast' => $this->podcast, 'subscription' => $this->subscription, ]; - $this->setHtmlHead(lang('Subscription.view', [$this->subscription->id])); replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, + 0 => $this->podcast->title, 1 => '#' . $this->subscription->id, ]); return view('subscription/view', $data); } - public function createView(): string + public function add(): string { helper('form'); @@ -126,14 +120,13 @@ class SubscriptionController extends BaseController 'podcast' => $this->podcast, ]; - $this->setHtmlHead(lang('Subscription.add', [esc($this->podcast->title)])); replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, + 0 => $this->podcast->title, ]); - return view('subscription/create', $data); + return view('subscription/add', $data); } - public function createAction(): RedirectResponse + public function attemptAdd(): RedirectResponse { helper('text'); @@ -149,8 +142,8 @@ class SubscriptionController extends BaseController $newSubscription = new Subscription([ 'podcast_id' => $this->podcast->id, - 'email' => $this->request->getPost('email'), - 'token' => hash('sha256', $rawToken = random_string('alnum', 8)), + 'email' => $this->request->getPost('email'), + 'token' => hash('sha256', $rawToken = random_string('alnum', 8)), 'expires_at' => $expiresAt, 'created_by' => user_id(), 'updated_by' => user_id(), @@ -177,13 +170,13 @@ class SubscriptionController extends BaseController ], $this->podcast->language_code)) ->setMessage(view('subscription/email/welcome', [ 'subscription' => $newSubscription, - 'token' => $rawToken, + 'token' => $rawToken, ]))->setMailType('html') ->send()) { $db->transRollback(); return redirect()->route('subscription-list', [$this->podcast->id])->with( 'errors', - [lang('Subscription.messages.addError'), $email->printDebugger([])], + [lang('Subscription.messages.addError'), $email->printDebugger([])] ); } @@ -193,7 +186,7 @@ class SubscriptionController extends BaseController 'message', lang('Subscription.messages.addSuccess', [ 'subscriber' => $newSubscription->email, - ]), + ]) ); } @@ -224,13 +217,13 @@ class SubscriptionController extends BaseController ->setSubject(lang('Subscription.emails.reset_subject', [], $this->podcast->language_code)) ->setMessage(view('subscription/email/reset', [ 'subscription' => $this->subscription, - 'token' => $rawToken, + 'token' => $rawToken, ]))->setMailType('html') ->send()) { $db->transRollback(); return redirect()->route('subscription-list', [$this->podcast->id])->with( 'errors', - [lang('Subscription.messages.regenerateTokenError'), $email->printDebugger([])], + [lang('Subscription.messages.regenerateTokenError'), $email->printDebugger([])] ); } @@ -240,28 +233,27 @@ class SubscriptionController extends BaseController 'message', lang('Subscription.messages.regenerateTokenSuccess', [ 'subscriber' => $this->subscription->email, - ]), + ]) ); } - public function editView(): string + public function edit(): string { helper('form'); $data = [ - 'podcast' => $this->podcast, + 'podcast' => $this->podcast, 'subscription' => $this->subscription, ]; - $this->setHtmlHead(lang('Subscription.edit', [esc($this->podcast->title)])); replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, + 0 => $this->podcast->title, 1 => '#' . $this->subscription->id, ]); return view('subscription/edit', $data); } - public function editAction(): RedirectResponse + public function attemptEdit(): RedirectResponse { $expiresAt = null; $expirationDate = $this->request->getPost('expiration_date'); @@ -299,7 +291,7 @@ class SubscriptionController extends BaseController $db->transRollback(); return redirect()->route('subscription-list', [$this->podcast->id])->with( 'errors', - [lang('Subscription.messages.editError'), $email->printDebugger([])], + [lang('Subscription.messages.editError'), $email->printDebugger([])] ); } @@ -309,7 +301,7 @@ class SubscriptionController extends BaseController 'message', lang('Subscription.messages.editSuccess', [ 'subscriber' => $this->subscription->email, - ]), + ]) ); } @@ -318,19 +310,18 @@ class SubscriptionController extends BaseController helper('form'); $data = [ - 'podcast' => $this->podcast, + 'podcast' => $this->podcast, 'subscription' => $this->subscription, ]; - $this->setHtmlHead(lang('Subscription.suspend')); replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, + 0 => $this->podcast->title, 1 => '#' . $this->subscription->id, ]); return view('subscription/suspend', $data); } - public function suspendAction(): RedirectResponse + public function attemptSuspend(): RedirectResponse { $db = db_connect(); $db->transStart(); @@ -355,7 +346,7 @@ class SubscriptionController extends BaseController $db->transRollback(); return redirect()->route('subscription-list', [$this->podcast->id])->with( 'errors', - [lang('Subscription.messages.suspendError'), $email->printDebugger([])], + [lang('Subscription.messages.suspendError'), $email->printDebugger([])] ); } @@ -365,7 +356,7 @@ class SubscriptionController extends BaseController 'messages', lang('Subscription.messages.suspendSuccess', [ 'subscriber' => $this->subscription->email, - ]), + ]) ); } @@ -395,7 +386,7 @@ class SubscriptionController extends BaseController $db->transRollback(); return redirect()->route('subscription-list', [$this->podcast->id])->with( 'errors', - [lang('Subscription.messages.resumeError'), $email->printDebugger([])], + [lang('Subscription.messages.resumeError'), $email->printDebugger([])] ); } @@ -405,7 +396,7 @@ class SubscriptionController extends BaseController 'message', lang('Subscription.messages.resumeSuccess', [ 'subscriber' => $this->subscription->email, - ]), + ]) ); } @@ -414,25 +405,23 @@ class SubscriptionController extends BaseController helper('form'); $data = [ - 'podcast' => $this->podcast, + 'podcast' => $this->podcast, 'subscription' => $this->subscription, ]; - $this->setHtmlHead(lang('Subscription.delete')); replace_breadcrumb_params([ - 0 => $this->podcast->at_handle, + 0 => $this->podcast->title, 1 => '#' . $this->subscription->id, ]); return view('subscription/delete', $data); } - public function deleteAction(): RedirectResponse + public function attemptDelete(): RedirectResponse { $db = db_connect(); $db->transStart(); - new SubscriptionModel() - ->delete($this->subscription->id); + (new SubscriptionModel())->delete($this->subscription->id); /** @var Email $email */ $email = service('email'); @@ -446,7 +435,7 @@ class SubscriptionController extends BaseController $db->transRollback(); return redirect()->route('subscription-list', [$this->podcast->id])->with( 'errors', - [lang('Subscription.messages.deleteError'), $email->printDebugger([])], + [lang('Subscription.messages.deleteError'), $email->printDebugger([])] ); } @@ -456,7 +445,7 @@ class SubscriptionController extends BaseController 'messages', lang('Subscription.messages.deleteSuccess', [ 'subscriber' => $this->subscription->email, - ]), + ]) ); } } diff --git a/modules/PremiumPodcasts/Database/Migrations/2022-07-07-120000_add_subscriptions.php b/modules/PremiumPodcasts/Database/Migrations/2022-07-07-120000_add_subscriptions.php index 57fa8dfd..ae4b91ab 100644 --- a/modules/PremiumPodcasts/Database/Migrations/2022-07-07-120000_add_subscriptions.php +++ b/modules/PremiumPodcasts/Database/Migrations/2022-07-07-120000_add_subscriptions.php @@ -10,52 +10,50 @@ declare(strict_types=1); namespace Modules\PremiumPodcasts\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddSubscriptions extends BaseMigration +class AddSubscriptions extends Migration { - #[Override] public function up(): void { $this->forge->addField([ 'id' => [ - 'type' => 'INT', - 'unsigned' => true, + 'type' => 'INT', + 'unsigned' => true, 'auto_increment' => true, ], 'podcast_id' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'email' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, ], 'token' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 64, ], 'status' => [ - 'type' => 'ENUM', + 'type' => 'ENUM', 'constraint' => ['active', 'suspended'], - 'default' => 'active', + 'default' => 'active', ], 'status_message' => [ - 'type' => 'VARCHAR', + 'type' => 'VARCHAR', 'constraint' => 255, - 'null' => true, + 'null' => true, ], 'expires_at' => [ 'type' => 'DATETIME', 'null' => true, ], 'created_by' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'updated_by' => [ - 'type' => 'INT', + 'type' => 'INT', 'unsigned' => true, ], 'created_at' => [ @@ -75,7 +73,6 @@ class AddSubscriptions extends BaseMigration $this->forge->createTable('subscriptions'); } - #[Override] public function down(): void { $this->forge->dropTable('subscriptions'); diff --git a/modules/PremiumPodcasts/Entities/Subscription.php b/modules/PremiumPodcasts/Entities/Subscription.php index aa8e32be..3ea10454 100644 --- a/modules/PremiumPodcasts/Entities/Subscription.php +++ b/modules/PremiumPodcasts/Entities/Subscription.php @@ -15,6 +15,7 @@ use App\Models\PodcastModel; use CodeIgniter\Entity\Entity; use CodeIgniter\I18n\Time; use Modules\Analytics\Models\AnalyticsPodcastBySubscriptionModel; +use RuntimeException; /** * @property int $id @@ -37,7 +38,7 @@ class Subscription extends Entity protected ?Podcast $podcast = null; /** - * @var list + * @var string[] */ protected $dates = ['expires_at', 'created_at', 'updated_at']; @@ -45,19 +46,21 @@ class Subscription extends Entity * @var array */ protected $casts = [ - 'id' => 'integer', - 'podcast_id' => 'integer', - 'email' => 'string', - 'token' => 'string', - 'status' => 'string', + 'id' => 'integer', + 'podcast_id' => 'integer', + 'email' => 'string', + 'token' => 'string', + 'status' => 'string', 'status_message' => '?string', - 'created_by' => 'integer', - 'updated_by' => 'integer', + 'created_by' => 'integer', + 'updated_by' => 'integer', ]; public function getStatus(): string { - return $this->expires_at->isBefore(Time::now()) ? 'expired' : $this->attributes['status']; + return ($this->expires_at !== null && $this->expires_at->isBefore( + Time::now() + )) ? 'expired' : $this->attributes['status']; } /** @@ -99,9 +102,12 @@ class Subscription extends Entity */ public function getPodcast(): ?Podcast { + if ($this->podcast_id === null) { + throw new RuntimeException('Subscription must have a podcast_id before getting podcast.'); + } + if (! $this->podcast instanceof Podcast) { - $this->podcast = new PodcastModel() - ->getPodcastById($this->podcast_id); + $this->podcast = (new PodcastModel())->getPodcastById($this->podcast_id); } return $this->podcast; @@ -109,7 +115,9 @@ class Subscription extends Entity public function getDownloadsLast3Months(): int { - return new AnalyticsPodcastBySubscriptionModel() - ->getNumberOfDownloadsLast3Months($this->podcast_id, $this->id); + return (new AnalyticsPodcastBySubscriptionModel())->getNumberOfDownloadsLast3Months( + $this->podcast_id, + $this->id + ); } } diff --git a/modules/PremiumPodcasts/Filters/PodcastUnlockFilter.php b/modules/PremiumPodcasts/Filters/PodcastUnlockFilter.php index 2f08a68b..74468fa2 100644 --- a/modules/PremiumPodcasts/Filters/PodcastUnlockFilter.php +++ b/modules/PremiumPodcasts/Filters/PodcastUnlockFilter.php @@ -4,92 +4,88 @@ declare(strict_types=1); namespace Modules\PremiumPodcasts\Filters; -use App\Entities\Episode; use App\Models\EpisodeModel; use CodeIgniter\Filters\FilterInterface; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\Router\Router; +use Config\App; use Modules\PremiumPodcasts\PremiumPodcasts; -use Override; +use Myth\Auth\Authentication\AuthenticationBase; class PodcastUnlockFilter implements FilterInterface { /** * Verifies that a user is logged in, or redirects to login. * - * @param string[]|null $arguments + * @param array|null $params * - * @return RequestInterface|ResponseInterface|string|null + * @return mixed */ - #[Override] - public function before(RequestInterface $request, $arguments = null) + public function before(RequestInterface $request, $params = null) { if (! function_exists('is_unlocked')) { helper('premium_podcasts'); } + $current = (string) current_url(true) + ->setHost('') + ->setScheme('') + ->stripQuery('token'); + + $config = config(App::class); + if ($config->forceGlobalSecureRequests) { + // Remove "https:/" + $current = substr($current, 7); + } + /** @var Router $router */ $router = service('router'); $routerParams = $router->params(); if ($routerParams === []) { - return null; + return; } // no need to go through the unlock form if user is connected - if (auth()->loggedIn()) { - return null; + /** @var AuthenticationBase $auth */ + $auth = service('authentication'); + if ($auth->isLoggedIn()) { + return; } // Make sure this isn't already a premium podcast route - if (url_is((string) route_to('premium-podcast-unlock', $routerParams[0]))) { - return null; - } - - // expect 2 parameters (podcast handle and episode slug) - if (count($routerParams) < 2) { - return null; - } - - $episode = new EpisodeModel() - ->getEpisodeBySlug($routerParams[0], $routerParams[1]); - - if (! $episode instanceof Episode) { - return null; + if ($current === route_to('premium-podcast-unlock', $routerParams[0])) { + return; } // Make sure that public episodes are still accessible - if (! $episode->is_premium) { - return null; + if ($routerParams >= 2 && ($episode = (new EpisodeModel())->getEpisodeBySlug( + $routerParams[0], + $routerParams[1] + )) && ! $episode->is_premium) { + return; } // Episode should be embeddable even if it is premium - if (url_is((string) route_to('embed', $episode->podcast->handle, $episode->slug))) { - return null; + if ($current === route_to('embed', $episode->podcast->handle, $episode->slug)) { + return; } + // if podcast is locked then send to the unlock form /** @var PremiumPodcasts $premiumPodcasts */ $premiumPodcasts = service('premium_podcasts'); - if ($premiumPodcasts->check($routerParams[0])) { - return null; + if (! $premiumPodcasts->check($routerParams[0])) { + session()->set('redirect_url', current_url()); + + return redirect()->route('premium-podcast-unlock', [$routerParams[0]]); } - - // podcast is locked, send to the unlock form - session() - ->set('redirect_url', current_url()); - - return redirect()->route('premium-podcast-unlock', [$routerParams[0]]); } /** - * @param list|null $arguments - * - * @return ResponseInterface|null + * @param array|null $arguments */ - #[Override] - public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) + public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void { - return null; } } diff --git a/modules/PremiumPodcasts/Language/ar/Subscription.php b/modules/PremiumPodcasts/Language/ar/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/ar/Subscription.php +++ b/modules/PremiumPodcasts/Language/ar/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/br/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/br/PremiumPodcasts.php index 42e897b6..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/br/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/br/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Rannoù Premium a zo er podkast-mañ', - 'episode_is_premium' => 'Ur rann Premium eo, ne c\'hell bezañ gwelet nemet gant koumananterien·ezed Premium', - 'unlock_episode' => 'Evit koumananterien·ezed Premium eo ar rann-mañ. Klikit evit dibrennañ anezhi!', - 'banner_unlock' => 'Rannoù Premium a zo er podkast-mañ, ne c\'hellont bezañ gwelet nemet gant koumananterien·ezed Premium.', - 'banner_lock' => 'Dibrennet eo bet ar podkast. Plijadur deoc\'h gant ar rannoù Premium!', - 'subscribe' => 'Koumanantiñ', - 'lock' => 'Prennañ', - 'unlock' => 'Dibrennañ', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', + 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Endalc\'had Premium', - 'subtitle' => 'Rannoù Premium prennet zo er podkast-mañ. Ha ganeoc\'h emañ an alc\'hwez evit dibrennañ anezho?', - 'token' => 'Lakait hoc’h alc\'hwez', - 'token_hint' => 'Ma\'z oc\'h koumanantet ouzh {podcastTitle} e c\'hellit eilañ an alc’hwez a zo bet kaset deoc\'h dre bostel ha pegañ anezhañ amañ.', - 'submit' => 'Dibrennañ an holl rannoù!', - 'call_to_action' => 'Dibrennit holl rannoù {podcastTitle}:', - 'subscribe_cta' => 'Koumanantit bremañ!', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', + 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => 'Dibrennet eo bet ar podkast gant berzh! Plijadur deoc\'h gant ar rannoù Premium!', - 'unlockBadAttempt' => 'Hoc\'h alc\'hwez n\'eo seblant ket bezañ mat…', - 'lockSuccess' => 'Dibrennet eo bet ar podkast gant berzh!', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/br/Subscription.php b/modules/PremiumPodcasts/Language/br/Subscription.php index a956f60b..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/br/Subscription.php +++ b/modules/PremiumPodcasts/Language/br/Subscription.php @@ -9,92 +9,92 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Koumanantoù ar podkast', - 'add' => 'Koumanant nevez', - 'view' => 'Gwelet ar c\'houmanant', - 'edit' => 'Kemmañ ar c\'houmanant', - 'regenerate_token' => 'Azgenel ar jedouer', - 'suspend' => 'Ehanañ ar c\'houmanant', - 'resume' => 'Adkregiñ gant ar c\'houmanant', - 'delete' => 'Dilemel ar c\'houmanant', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Bev', - 'suspended' => 'Ehanet', - 'expired' => 'Tremenet', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Niverenn', - 'email' => 'Postel', - 'expiration_date' => 'Deiziad termen', - 'unlimited' => 'Didermen', - 'downloads' => 'Pellgargadennoù', - 'status' => 'Statud', + 'number' => 'Number', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', + 'downloads' => 'Downloads', + 'status' => 'Status', ], 'form' => [ - 'email' => 'Postel', - 'expiration_date' => 'Deiziad termen', - 'expiration_date_hint' => 'An deiziad hag an eur ma vo tremenet ar c\'houmanant. Laoskit goullo evit ur c\'houmanant didermen.', - 'submit_create' => 'Krouiñ ur c\'houmanant', - 'submit_edit' => 'Kemmañ ar c\'houmanant', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', + 'submit_add' => 'Add subscription', + 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ - 'link' => 'Liamm etrezek pajenn ar c\'houmanant', - 'link_hint' => 'Gant an dra-se e vo ouzhpennet d\'al lec\'hienn ur galv da ober evit pediñ ar selaouerien·ezed da goumanantiñ ouzh ar podkast.', - 'submit' => 'Enrollañ al liamm', + 'link' => 'Subscription page link', + 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', + 'submit' => 'Save link', ], 'suspend_form' => [ - 'disclaimer' => 'Ehanañ ar c\'houmanant a viro ouzh ar goumananterien·ezed da welet an endalc\'had Premium. Gallout a reoc\'h skarzhañ an ehan war-lerc\'h.', - 'reason' => 'Abeg', - 'reason_placeholder' => 'Perak ho peus c\'hoant da ehanañ ar c\'houmanant?', - "submit" => 'Ehanañ ar c\'houmanant', + 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', + 'reason' => 'Reason', + 'reason_placeholder' => 'Why are you suspending the subscription?', + "submit" => 'Suspend subscription', ], 'delete_form' => [ - 'disclaimer' => 'Dilemel koumanant {subscriber} a skarzho an holl stadegoù stag outañ.', - 'understand' => 'Kompren a ran, dilemel ar c\'houmanant da vat', - 'submit' => 'Dilemel ar c\'houmanant', + 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', + 'understand' => 'I understand, remove the subscription permanently', + 'submit' => 'Remove subscription', ], 'messages' => [ - 'addSuccess' => 'Ur c\'houmanant nevez zo bet ouzhpennet! Ur postel evit degemer {subscriber} zo bet kaset.', - 'addError' => 'N\'eo ket bet ouzhpennet ar c\'houmanant.', - 'editSuccess' => 'Deiziad termen ar c\'houmanant zo bet nevesaet! Ur postel zo bet kaset da {subscriber}.', - 'editError' => 'N\'eo ket bet kemmet ar c\'houmanant.', - 'regenerateTokenSuccess' => 'Azganet eo bet ar jedouer! Kaset eo bet ar jedouer nevez da {subscriber} dre bostel.', - 'regenerateTokenError' => 'N\'eo ket bet gellet azgenel ar jedouer.', - 'deleteSuccess' => 'Dilamet eo bet ar c\'houmanant! Ur postel zo bet kaset da {subscriber}.', - 'deleteError' => 'N\'eo ket bet gellet dilemel ar c\'houmanant.', - 'suspendSuccess' => 'Ehanet eo bet ar c\'houmanant! Ur postel zo bet kaset da {subscriber}.', - 'suspendError' => 'N\'eo ket bet gellet ehanañ ar c\'houmanant.', - 'resumeSuccess' => 'Adkroget eo bet gant ar c\'houmanant! Ur postel zo bet kaset da {subscriber}.', - 'resumeError' => 'N\'eo ket bet gellet adkregiñ gant ar c\'houmanant.', - 'linkSaveSuccess' => 'Liamm ar c\'houmanant zo bet enrollet gant berzh! Diskouezet e vo war al lec\'hienn evel ur galv da ober!', - 'linkRemoveSuccess' => 'Dilamet eo bet liamm ar c\'houmanant gant berzh!', + 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', + 'addError' => 'Subscription could not be added.', + 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', + 'editError' => 'Subscription could not be edited.', + 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', + 'regenerateTokenError' => 'Token could not be regenerated.', + 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', + 'deleteError' => 'Subscription could not be removed.', + 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', + 'suspendError' => 'Subscription could not be suspended.', + 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', + 'resumeError' => 'Subscription could not be resumed.', + 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', + 'linkRemoveSuccess' => 'Subscription link was removed successfully!', ], 'emails' => [ - 'greeting' => 'Ata,', - 'token' => 'Ho jedouer: {0}', - 'unique_feed_link' => 'Liamm ho kwazh deoc\'h-c\'hwi: {0}', - 'how_to_use' => 'Penaos ober gantañ?', - 'two_ways' => 'Daou zoare zo evit dibrennañ rannoù Premium:', - 'import_into_app' => 'Eilit liamm ho kwazh personelaet e-barzh hoc\'h arload podkast karetañ (enporzhiit anezhañ evel ur wazh prevez kuit da lakaat war wel ho titouroù).', - 'go_to_website' => 'Kit da lec\'hienn {podcastWebsite} ha dibrennit ar podkast gant ho jedouer.', - 'welcome_subject' => 'Degemer mat war {podcastTitle}', - 'welcome' => 'Koumanantet oc\'h ouzh {podcastTitle}, mersi bras deoc\'h ha degemer mat!', - 'welcome_token_title' => 'Setu an titouroù evit dibrennañ rannoù Premium ar podkast:', - 'welcome_expires' => 'Arventennet eo bet ho koumanant da echuiñ d\'an/ar {0}.', - 'welcome_never_expires' => 'Arventennet eo bet ho koumanant evit bezañ didermen.', - 'reset_subject' => 'Azganet eo bet ho jedouer!', - 'reset_token' => 'Adderaouekaet eo bet ho moned da {podcastTitle}!', - 'reset_token_title' => 'Titouroù nevez zo bet ganet evit ma tibrennfec’h rannoù Premium ar podkast:', - 'edited_subject' => 'Nevesaet eo bet ho koumanant!', - 'edited_expires' => 'Arventennet eo bet ho koumanant ouzh {podcastTitle} da echuiñ d\'an/ar {expiresAt}.', - 'edited_never_expires' => 'Arventennet eo bet ho koumanant ouzh {podcastTitle} da vezañ didermen!', - 'suspended_subject' => 'Ehanet eo bet ho koumanant!', - 'suspended' => 'Ehanet eo bet ho koumanant ouzh {podcastTitle}! Ne c\'hallit ket gwelet rannoù Premium ar podkast ken.', - 'suspended_reason' => 'Evit an abeg da-heul: {0}', - 'resumed_subject' => 'Adkrog eo ho koumanant!', - 'resumed' => 'Adkrog eo ho koumanant ouzh {podcastTitle}! Gallout a rit ket gwelet rannoù Premium ar podkast en-dro.', - 'deleted_subject' => 'Dilamet eo bet ho koumanant!', - 'deleted' => 'Dilamet eo bet ho koumanant ouzh {podcastTitle}! Ne c\'hallit ket gwelet rannoù Premium ar podkast ken.', - 'footer' => '{castopod} herberc\'hiet war {host}', + 'greeting' => 'Hey,', + 'token' => 'Your token: {0}', + 'unique_feed_link' => 'Your unique feed link: {0}', + 'how_to_use' => 'How to use?', + 'two_ways' => 'You have two ways of unlocking the premium episodes:', + 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', + 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', + 'welcome_subject' => 'Welcome to {podcastTitle}', + 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', + 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', + 'welcome_expires' => 'Your subscription was set to expire on {0}.', + 'welcome_never_expires' => 'Your subscription was set to never expire.', + 'reset_subject' => 'Your token was reset!', + 'reset_token' => 'Your access to {podcastTitle} has been reset!', + 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', + 'edited_subject' => 'Your subscription has been updated!', + 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', + 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', + 'suspended_subject' => 'Your subscription has been suspended!', + 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', + 'suspended_reason' => 'That is for the following reason: {0}', + 'resumed_subject' => 'Your subscription has been resumed!', + 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', + 'deleted_subject' => 'Your subscription has been removed!', + 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', + 'footer' => '{castopod} hosted on {host}', ], ]; diff --git a/modules/PremiumPodcasts/Language/ca/Subscription.php b/modules/PremiumPodcasts/Language/ca/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/ca/Subscription.php +++ b/modules/PremiumPodcasts/Language/ca/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/da/Subscription.php b/modules/PremiumPodcasts/Language/da/Subscription.php deleted file mode 100644 index e83f0cb2..00000000 --- a/modules/PremiumPodcasts/Language/da/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Podcast subscriptions', - 'add' => 'New subscription', - 'view' => 'View subscription', - 'edit' => 'Edit subscription', - 'regenerate_token' => 'Regenerate token', - 'suspend' => 'Suspend subscription', - 'resume' => 'Resume subscription', - 'delete' => 'Delete subscription', - 'status' => [ - 'active' => 'Active', - 'suspended' => 'Suspended', - 'expired' => 'Expired', - ], - 'list' => [ - 'number' => 'Number', - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'unlimited' => 'Unlimited', - 'downloads' => 'Downloads', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Edit subscription', - ], - 'form_link_add' => [ - 'link' => 'Subscription page link', - 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', - 'submit' => 'Save link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/de/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/de/PremiumPodcasts.php index 178640ed..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/de/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/de/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Podcast enthält Premium-Episoden', - 'episode_is_premium' => 'Diese Episode ist nur verfügbar für Premium-Abonnenten', - 'unlock_episode' => 'Diese Episode ist nur für Premium-Abonnenten. Klicke, um sie freizuschalten!', - 'banner_unlock' => 'Dieser Podcast enthält Premium-Episoden, nur verfügbar für Premium-Abonnenten.', - 'banner_lock' => 'Der Podcast ist freigeschaltet, viel Spaß mit den Premium-Episoden!', - 'subscribe' => 'Abonnieren', - 'lock' => 'Sperren', - 'unlock' => 'Entsperren', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', + 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Premium-Inhalt', - 'subtitle' => 'Dieser Podcast enthält gesperrte Premium-Episoden! Haben Sie einen Schlüssel, um diese freizuschalten?', - 'token' => 'Geben Sie Ihren Schlüssel ein', - 'token_hint' => 'Wenn Sie {podcastTitle} abonniert haben, können Sie hier den Schlüssel einfügen, den Sie per E-Mail erhalten haben.', - 'submit' => 'Alle Episoden freischalten!', - 'call_to_action' => 'Schalten Sie alle Episoden von {podcastTitle} frei:', - 'subscribe_cta' => 'Jetzt abonnieren!', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', + 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => 'Der Podcast wurde erfolgreich entsperrt! Viel Spaß mit den Premium-Episoden!', - 'unlockBadAttempt' => 'Ihr Schlüssel scheint nicht zu funktionieren…', - 'lockSuccess' => 'Der Podcast wurde erfolgreich gesperrt!', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/de/Subscription.php b/modules/PremiumPodcasts/Language/de/Subscription.php index 67b91013..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/de/Subscription.php +++ b/modules/PremiumPodcasts/Language/de/Subscription.php @@ -9,92 +9,92 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Podcast-Abonnements', - 'add' => 'Neues Abonnement', - 'view' => 'Abonnement anzeigen', - 'edit' => 'Abonnement bearbeiten', - 'regenerate_token' => 'Token neu generieren', - 'suspend' => 'Abonnement unterbrechen', - 'resume' => 'Abonnement fortsetzen', - 'delete' => 'Abonnement löschen', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Aktiv', - 'suspended' => 'Unterbrochen', - 'expired' => 'Abgelaufen', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Nummer', - 'email' => 'E-Mail', - 'expiration_date' => 'Ablaufdatum', - 'unlimited' => 'Unbegrenzt', + 'number' => 'Number', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', 'downloads' => 'Downloads', 'status' => 'Status', ], 'form' => [ - 'email' => 'E-Mail', - 'expiration_date' => 'Ablaufdatum', - 'expiration_date_hint' => 'Das Datum und die Uhrzeit, zu der das Abonnement abläuft. Leer lassen für ein unbegrenztes Abonnement.', - 'submit_create' => 'Abonnement einrichten', - 'submit_edit' => 'Abonnement bearbeiten', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', + 'submit_add' => 'Add subscription', + 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ - 'link' => 'Link zur Abonnement-Seite', - 'link_hint' => 'Dies fügt einen CTA (Call to Action) zur Webseite hinzu, der Hörer dazu einlädt, den Podcast zu abonnieren.', - 'submit' => 'Link speichern', + 'link' => 'Subscription page link', + 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', + 'submit' => 'Save link', ], 'suspend_form' => [ - 'disclaimer' => 'Das Pausieren des Abonnements wird dem Abonnenten den Zugang zu den Premium-Inhalten einschränken. Sie können die Pausierung jederzeit wieder aufheben.', - 'reason' => 'Grund', - 'reason_placeholder' => 'Warum unterbrechen Sie Ihr Abonnement?', - "submit" => 'Abonnement unterbrechen', + 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', + 'reason' => 'Reason', + 'reason_placeholder' => 'Why are you suspending the subscription?', + "submit" => 'Suspend subscription', ], 'delete_form' => [ - 'disclaimer' => 'Durch das Löschen des Abonnements von {subscriber} werden alle damit verbundenen Analysedaten entfernt.', - 'understand' => 'Ich verstehe, entferne das Abonnement dauerhaft', - 'submit' => 'Abonnement entfernen', + 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', + 'understand' => 'I understand, remove the subscription permanently', + 'submit' => 'Remove subscription', ], 'messages' => [ - 'addSuccess' => 'Neues Abonnement hinzugefügt! Eine Willkommens-E-Mail wurde an {subscriber} gesendet.', - 'addError' => 'Abonnement konnte nicht hinzugefügt werden.', - 'editSuccess' => 'Das Ablaufdatum des Abonnements wurde aktualisiert! Es wurde eine E-Mail an {subscriber} gesendet.', - 'editError' => 'Abonnement konnte nicht bearbeitet werden.', - 'regenerateTokenSuccess' => 'Der Schlüssel wurde neu generiert! Eine E-Mail mit dem neuen Schlüssel wurde an {subscriber} gesendet.', - 'regenerateTokenError' => 'Schlüssel konnte nicht neu generiert werden.', - 'deleteSuccess' => 'Das Abonnement wurde entfernt! Es wurde eine E-Mail an {subscriber} gesendet.', - 'deleteError' => 'Abonnement konnte nicht entfernt werden.', - 'suspendSuccess' => 'Das Abonnement wurde pausiert! Es wurde eine E-Mail an {subscriber} gesendet.', - 'suspendError' => 'Abonnement konnte nicht pausiert werden.', - 'resumeSuccess' => 'Das Abonnement wurde fortgesetzt! Es wurde eine E-Mail an {subscriber} gesendet.', - 'resumeError' => 'Abonnement konnte nicht fortgesetzt werden.', - 'linkSaveSuccess' => 'Der Abonnement-Link wurde erfolgreich gespeichert! Dieser wird als CTA (Call to Action) auf der Webseite erscheinen!', - 'linkRemoveSuccess' => 'Der Abonnement-Link wurde erfolgreich entfernt!', + 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', + 'addError' => 'Subscription could not be added.', + 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', + 'editError' => 'Subscription could not be edited.', + 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', + 'regenerateTokenError' => 'Token could not be regenerated.', + 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', + 'deleteError' => 'Subscription could not be removed.', + 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', + 'suspendError' => 'Subscription could not be suspended.', + 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', + 'resumeError' => 'Subscription could not be resumed.', + 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', + 'linkRemoveSuccess' => 'Subscription link was removed successfully!', ], 'emails' => [ 'greeting' => 'Hey,', - 'token' => 'Ihr Token: {0}', - 'unique_feed_link' => 'Ihr eindeutiger Feed-Link: {0}', - 'how_to_use' => 'Wie nutzt man es?', - 'two_ways' => 'Sie haben zwei Möglichkeiten, die Premium-Episoden freizuschalten:', - 'import_into_app' => 'Kopieren Sie Ihre einmalige Feed-URL in Ihre Lieblings-Podcast-App (importieren sie diesen als privaten Feed, um Ihre Anmeldedaten geheim zu halten).', - 'go_to_website' => 'Gehen Sie zu der Webseite von {podcastWebsite} und entsperren Sie den Podcast mit Ihrem Schlüssel.', - 'welcome_subject' => 'Willkommen bei {podcastTitle}', - 'welcome' => 'Sie haben {podcastTitle} abonniert, vielen Dank und herzlich willkommen!', - 'welcome_token_title' => 'Hier sind Ihre Anmeldedaten, um die Premium-Episoden des Podcasts freizuschalten:', - 'welcome_expires' => 'Ihr Abonnement läuft am {0} ab.', - 'welcome_never_expires' => 'Ihr Abonnement läuft nicht ab.', - 'reset_subject' => 'Ihr Schlüssel wurde zurückgesetzt!', - 'reset_token' => 'Ihr Zugriff auf {podcastTitle} wurde zurückgesetzt!', - 'reset_token_title' => 'Es wurden neue Anmeldedaten generiert, um die Premium-Episoden des Podcasts freizuschalten:', - 'edited_subject' => 'Ihr Abonnement wurde aktualisiert!', - 'edited_expires' => 'Ihr Abonnement für {podcastTitle} läuft am {expiresAt} ab.', - 'edited_never_expires' => 'Ihr Abonnement für {podcastTitle} läuft nie ab!', - 'suspended_subject' => 'Ihr Abonnement wurde pausiert!', - 'suspended' => 'Ihr Abonnement für {podcastTitle} wurde pausiert! Sie können nun nicht mehr auf die Premium-Episoden des Podcasts zugreifen.', - 'suspended_reason' => 'Das ist aus dem folgenden Grund: {0}', - 'resumed_subject' => 'Ihr Abonnement wurde wieder aufgenommen!', - 'resumed' => 'Ihr Abonnement für {podcastTitle} wurde fortgesetzt! Sie können nun wieder auf die Premium-Episoden des Podcasts zugreifen.', - 'deleted_subject' => 'Ihr Abonnement wurde entfernt!', - 'deleted' => 'Ihr Abonnement für {podcastTitle} wurde entfernt! Sie können nun nicht mehr auf die Premium-Episoden des Podcasts zugreifen.', - 'footer' => '{castopod} betrieben auf {host}', + 'token' => 'Your token: {0}', + 'unique_feed_link' => 'Your unique feed link: {0}', + 'how_to_use' => 'How to use?', + 'two_ways' => 'You have two ways of unlocking the premium episodes:', + 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', + 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', + 'welcome_subject' => 'Welcome to {podcastTitle}', + 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', + 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', + 'welcome_expires' => 'Your subscription was set to expire on {0}.', + 'welcome_never_expires' => 'Your subscription was set to never expire.', + 'reset_subject' => 'Your token was reset!', + 'reset_token' => 'Your access to {podcastTitle} has been reset!', + 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', + 'edited_subject' => 'Your subscription has been updated!', + 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', + 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', + 'suspended_subject' => 'Your subscription has been suspended!', + 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', + 'suspended_reason' => 'That is for the following reason: {0}', + 'resumed_subject' => 'Your subscription has been resumed!', + 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', + 'deleted_subject' => 'Your subscription has been removed!', + 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', + 'footer' => '{castopod} hosted on {host}', ], ]; diff --git a/modules/PremiumPodcasts/Language/el/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/el/PremiumPodcasts.php index 2cdc8702..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/el/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/el/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Το Podcast περιέχει premium επεισόδια', - 'episode_is_premium' => 'Το επεισόδιο είναι premium, μόνο διαθέσιμο σε συνδρομητές premium', - 'unlock_episode' => 'Αυτό το επεισόδιο είναι μόνο για premium συνδρομητές. Κάντε κλικ για να το ξεκλειδώσετε!', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', - 'banner_lock' => 'Το Podcast είναι ξεκλειδωμένο, απολαύστε τα premium επεισόδια!', - 'subscribe' => 'Συνδρομή', - 'lock' => 'Κλείδωμα', - 'unlock' => 'Ξεκλείδωμα', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Premium περιεχόμενο', - 'subtitle' => 'Αυτό το podcast περιέχει κλειδωμένα premium επεισόδια! Έχεις το κλειδί για να τα ξεκλειδώσεις;', - 'token' => 'Δώστε το κλειδί', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', - 'submit' => 'Ξεκλείδωμα όλων των επεισοδίων!', - 'call_to_action' => 'Ξεκλειδώστε όλα τα επεισόδια του {podcastTitle}:', - 'subscribe_cta' => 'Εγγραφείτε τώρα!', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => 'Το Podcast ξεκλειδώθηκε με επιτυχία! Απολαύστε τα premium επεισόδια!', - 'unlockBadAttempt' => 'Το κλειδί σας δεν φαίνεται να λειτουργεί…', - 'lockSuccess' => 'Το Podcast κλειδώθηκε με επιτυχία!', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/el/Subscription.php b/modules/PremiumPodcasts/Language/el/Subscription.php index a8f8f923..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/el/Subscription.php +++ b/modules/PremiumPodcasts/Language/el/Subscription.php @@ -9,32 +9,32 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Συνδρομές Podcast', - 'add' => 'Νέα συνδρομή', - 'view' => 'Προβολή συνδρομής', - 'edit' => 'Τροποποίηση συνδρομής', - 'regenerate_token' => 'Αναδημιουργία token', - 'suspend' => 'Αναστολή συνδρομής', - 'resume' => 'Συνέχιση συνδρομής', - 'delete' => 'Διαγραφή συνδρομής', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Ενεργή', - 'suspended' => 'Έχει ανασταλεί', - 'expired' => 'Έληξε', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Αριθμός', - 'email' => 'Ηλεκτρονική διεύθυνση', - 'expiration_date' => 'Ημερομηνία λήξης', - 'unlimited' => 'Απεριόριστα', - 'downloads' => 'Λήψεις', - 'status' => 'Κατάσταση', + 'number' => 'Number', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', + 'downloads' => 'Downloads', + 'status' => 'Status', ], 'form' => [ 'email' => 'Email', - 'expiration_date' => 'Ημερομηνία λήξης', + 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/en/Subscription.php b/modules/PremiumPodcasts/Language/en/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/en/Subscription.php +++ b/modules/PremiumPodcasts/Language/en/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/es/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/es/PremiumPodcasts.php index e7beaae7..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/es/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/es/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Podcast contiene episodios premium', - 'episode_is_premium' => 'El episodio es premium, sólo disponible para los suscriptores premium', - 'unlock_episode' => 'Este episodio es sólo para suscriptores premium. ¡Haz clic para desbloquearlo!', - 'banner_unlock' => 'Este podcast contiene episodios premium, sólo disponible para los suscriptores premium.', - 'banner_lock' => 'Podcast desbloqueado, ¡disfruta de los episodios premium!', - 'subscribe' => 'Suscríbete', - 'lock' => 'Bloquear', - 'unlock' => 'Desbloquear', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', + 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Contenido premium', - 'subtitle' => '¡Este podcast contiene episodios premium bloqueados! ¿Tienes la clave para desbloquearlos?', - 'token' => 'Introduzca su clave', - 'token_hint' => 'Si está suscrito a {podcastTitle}, puede copiar la clave que le fue enviada por correo electrónico y pegarla aquí.', - 'submit' => '¡Desbloquea todos los episodios!', - 'call_to_action' => 'Desbloquea todos los episodios de {podcastTitle}:', - 'subscribe_cta' => '¡Suscríbete ahora!', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', + 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => '¡Podcast desbloqueado con éxito! ¡Disfruta de los episodios premium!', - 'unlockBadAttempt' => 'Parece que tu clave no está funcionando…', - 'lockSuccess' => 'El Podcast fue bloqueado con éxito!', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/es/Subscription.php b/modules/PremiumPodcasts/Language/es/Subscription.php index 76df4e21..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/es/Subscription.php +++ b/modules/PremiumPodcasts/Language/es/Subscription.php @@ -9,92 +9,92 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Suscripciones de Podcast', - 'add' => 'Nueva suscripción', - 'view' => 'Ver suscripción', - 'edit' => 'Editar la suscripción', - 'regenerate_token' => 'Regenerar token', - 'suspend' => 'Suspender suscripción', - 'resume' => 'Reanudar suscripción', - 'delete' => 'Eliminar suscripción', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Activo', - 'suspended' => 'Suspendido', - 'expired' => 'Caducado', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Número', - 'email' => 'Correo electrónico', - 'expiration_date' => 'Fecha de expiración', - 'unlimited' => 'Ilimitado', - 'downloads' => 'Descargas', - 'status' => 'Estado', + 'number' => 'Number', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', + 'downloads' => 'Downloads', + 'status' => 'Status', ], 'form' => [ - 'email' => 'Correo electrónico', - 'expiration_date' => 'Fecha de expiración', - 'expiration_date_hint' => 'La fecha y hora en que caduca la suscripción. Dejar en blanco para una suscripción ilimitada.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Editar la suscripción', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', + 'submit_add' => 'Add subscription', + 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ - 'link' => 'Enlace de página de suscripción', - 'link_hint' => 'Esto añadirá una llamada a la acción en el sitio web invitando a los oyentes a suscribirse al podcast.', - 'submit' => 'Guardar enlace', + 'link' => 'Subscription page link', + 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', + 'submit' => 'Save link', ], 'suspend_form' => [ - 'disclaimer' => 'Suspender la suscripción restringirá que el suscriptor tenga acceso al contenido premium. Aún podrá levantar la suspensión después.', - 'reason' => 'Motivo', - 'reason_placeholder' => '¿Por qué quieres detener tu suscripción?', - "submit" => 'Suspender suscripción', + 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', + 'reason' => 'Reason', + 'reason_placeholder' => 'Why are you suspending the subscription?', + "submit" => 'Suspend subscription', ], 'delete_form' => [ - 'disclaimer' => 'Eliminar la suscripción de {subscriber} eliminará todos los datos analíticos asociados a ella.', - 'understand' => 'Entiendo, eliminar la suscripción permanentemente', - 'submit' => 'Eliminar Suscripción', + 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', + 'understand' => 'I understand, remove the subscription permanently', + 'submit' => 'Remove subscription', ], 'messages' => [ - 'addSuccess' => '¡Nueva suscripción añadida! Se ha enviado un correo electrónico de bienvenida a {subscriber}.', - 'addError' => 'La suscripción no pudo ser añadida.', - 'editSuccess' => '¡La fecha de caducidad de la suscripción ha sido actualizada! Se ha enviado un correo electrónico a {subscriber}.', - 'editError' => 'No se pudo editar la suscripción.', - 'regenerateTokenSuccess' => '¡Token regenerado! Un correo electrónico fue enviado a {subscriber} con el nuevo token.', - 'regenerateTokenError' => 'El token no se pudo regenerar.', - 'deleteSuccess' => '¡La suscripción ha sido eliminada! Se ha enviado un correo electrónico a {subscriber}.', - 'deleteError' => 'La suscripción no pudo ser eliminada.', - 'suspendSuccess' => '¡La suscripción ha sido suspendida! Se ha enviado un correo electrónico a {subscriber}.', - 'suspendError' => 'La suscripción no pudo ser suspendida.', - 'resumeSuccess' => 'La suscripción se ha reanudado! Se ha enviado un correo electrónico a {subscriber}.', - 'resumeError' => 'No se pudo reanudar la suscripción.', - 'linkSaveSuccess' => '¡El enlace de suscripción se ha guardado correctamente! ¡Aparecerá en el sitio web como una acción de llamada!', - 'linkRemoveSuccess' => '¡El enlace de suscripción se eliminó correctamente!', + 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', + 'addError' => 'Subscription could not be added.', + 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', + 'editError' => 'Subscription could not be edited.', + 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', + 'regenerateTokenError' => 'Token could not be regenerated.', + 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', + 'deleteError' => 'Subscription could not be removed.', + 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', + 'suspendError' => 'Subscription could not be suspended.', + 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', + 'resumeError' => 'Subscription could not be resumed.', + 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', + 'linkRemoveSuccess' => 'Subscription link was removed successfully!', ], 'emails' => [ - 'greeting' => 'Hola,', - 'token' => 'Tu token: {0}', - 'unique_feed_link' => 'Tu enlace de feed único: {0}', - 'how_to_use' => '¿Cómo se usa?', - 'two_ways' => 'Tienes dos maneras de desbloquear los episodios premium:', - 'import_into_app' => 'Copie su Url única dentro de su aplicación de podcast favorita (importe como un feed privado para evitar exponer sus credenciales).', - 'go_to_website' => 'Ve a la página web de {podcastWebsite} y desbloquea el podcast con tu token.', - 'welcome_subject' => 'Bienvenido a {podcastTitle}', - 'welcome' => 'Te has suscrito a {podcastTitle}, ¡gracias y bienvenido!', - 'welcome_token_title' => 'Aquí están tus credenciales para desbloquear los episodios premium del podcast:', - 'welcome_expires' => 'Sus suscripción caducará en {0}.', - 'welcome_never_expires' => 'Tu suscripción nunca expirará.', - 'reset_subject' => '¡Tu token ha sido restablecido!', - 'reset_token' => '¡Tu acceso a {podcastTitle} ha sido restablecido!', - 'reset_token_title' => 'Se han generado nuevas credenciales para desbloquear los episodios premium del podcast:', - 'edited_subject' => 'Su suscripción ha sido actualizada!', - 'edited_expires' => 'Su suscripción para {podcastTitle} caducará el {expiresAt}.', - 'edited_never_expires' => '¡Tu suscripción para {podcastTitle} nunca caducará!', - 'suspended_subject' => 'Tu suscripción ha sido suspendida!', - 'suspended' => '¡Tu suscripción para {podcastTitle} ha sido suspendida! Ya no puedes acceder a los episodios premium del podcast.', - 'suspended_reason' => 'Este es el siguiente motivo: {0}', - 'resumed_subject' => 'Hemos reactivado tu suscripción!', - 'resumed' => '¡Tu suscripción para {podcastTitle} ha sido reanudada! Puedes acceder de nuevo a los episodios premium del podcast.', - 'deleted_subject' => 'La suscripción ha sido eliminada!', - 'deleted' => '¡Tu suscripción para {podcastTitle} ha sido eliminada! Ya no tienes acceso a los episodios premium del podcast.', - 'footer' => '{castopod} alojado en {host}', + 'greeting' => 'Hey,', + 'token' => 'Your token: {0}', + 'unique_feed_link' => 'Your unique feed link: {0}', + 'how_to_use' => 'How to use?', + 'two_ways' => 'You have two ways of unlocking the premium episodes:', + 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', + 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', + 'welcome_subject' => 'Welcome to {podcastTitle}', + 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', + 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', + 'welcome_expires' => 'Your subscription was set to expire on {0}.', + 'welcome_never_expires' => 'Your subscription was set to never expire.', + 'reset_subject' => 'Your token was reset!', + 'reset_token' => 'Your access to {podcastTitle} has been reset!', + 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', + 'edited_subject' => 'Your subscription has been updated!', + 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', + 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', + 'suspended_subject' => 'Your subscription has been suspended!', + 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', + 'suspended_reason' => 'That is for the following reason: {0}', + 'resumed_subject' => 'Your subscription has been resumed!', + 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', + 'deleted_subject' => 'Your subscription has been removed!', + 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', + 'footer' => '{castopod} hosted on {host}', ], ]; diff --git a/modules/PremiumPodcasts/Language/fa/Subscription.php b/modules/PremiumPodcasts/Language/fa/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/fa/Subscription.php +++ b/modules/PremiumPodcasts/Language/fa/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/fr-ca/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/fr-ca/PremiumPodcasts.php deleted file mode 100644 index 18c0dd4e..00000000 --- a/modules/PremiumPodcasts/Language/fr-ca/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podcast contains premium episodes', - 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', - 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', - 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', - 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', - 'subscribe' => 'Subscribe', - 'lock' => 'Lock', - 'unlock' => 'Unlock', - 'unlock_form' => [ - 'title' => 'Premium content', - 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', - 'token' => 'Enter your key', - 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', - 'submit' => 'Unlock all episodes!', - 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', - 'subscribe_cta' => 'Subscribe now!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', - 'unlockBadAttempt' => 'Your key does not seem to be working…', - 'lockSuccess' => 'Podcast was successfully locked!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/fr/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/fr/PremiumPodcasts.php index 007b90bd..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/fr/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/fr/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Le Podcast contient des épisodes premium', - 'episode_is_premium' => 'Cet épisode est premium, uniquement disponible pour les abonnés premium', - 'unlock_episode' => 'Cet épisode est réservé aux abonnés premium. Cliquez pour le débloquer !', - 'banner_unlock' => 'Ce podcast contient des épisodes premium, uniquement disponibles pour les abonnés premium.', - 'banner_lock' => 'Podcast débloqué avec succès ! Profitez des épisodes premium !', - 'subscribe' => 'S\'abonner', - 'lock' => 'Verrouiller', - 'unlock' => 'Déverrouiller', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', + 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Contenu Premium', - 'subtitle' => 'Ce podcast contient des épisodes premium verrouillés ! Avez-vous la clé pour les déverrouiller ?', - 'token' => 'Entrez votre clé', - 'token_hint' => 'Si vous êtes abonné à {podcastTitle}, vous pouvez copier la clé qui vous a été envoyée par e-mail et la coller ici.', - 'submit' => 'Débloquer tous les épisodes!', - 'call_to_action' => 'Débloquer tous les épisodes de {podcastTitle}:', - 'subscribe_cta' => 'Je m’inscris maintenant !', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', + 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => 'Podcast débloqué avec succès ! Profitez des épisodes premium !', - 'unlockBadAttempt' => 'Votre clé ne semble pas fonctionner…', - 'lockSuccess' => 'Le podcast a été verouillé avec succès !', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/fr/Subscription.php b/modules/PremiumPodcasts/Language/fr/Subscription.php index f760c1ae..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/fr/Subscription.php +++ b/modules/PremiumPodcasts/Language/fr/Subscription.php @@ -9,92 +9,92 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Abonnements au podcast', - 'add' => 'Nouvel abonnement', - 'view' => 'Afficher l\'abonnement', - 'edit' => 'Modifier l\'inscription', - 'regenerate_token' => 'Regenerer le token', - 'suspend' => 'Suspendre l\'abonnement', - 'resume' => 'Reprendre l\'abonnement', - 'delete' => 'Supprimer l\'abonnement', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Actif', - 'suspended' => 'Suspendu', - 'expired' => 'Expiré', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Numéro', - 'email' => 'Adresse e-mail', - 'expiration_date' => 'Date d\'expiration', - 'unlimited' => 'Illimité', - 'downloads' => 'Téléchargements', - 'status' => 'Statut', + 'number' => 'Number', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', + 'downloads' => 'Downloads', + 'status' => 'Status', ], 'form' => [ - 'email' => 'Adresse e-mail', - 'expiration_date' => 'Date d\'expiration', - 'expiration_date_hint' => 'La date et l\'heure à laquelle l\'abonnement expire. Laissez vide pour un abonnement illimité.', - 'submit_create' => 'Créer un abonnement', - 'submit_edit' => 'Modifier l\'inscription', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', + 'submit_add' => 'Add subscription', + 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ - 'link' => 'Lien vers la page d\'abonnement', - 'link_hint' => 'Cela va ajouter un appel à l\'action dans le site Web invitant les auditeurs à s\'abonner au podcast.', - 'submit' => 'Enregistrer le lien', + 'link' => 'Subscription page link', + 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', + 'submit' => 'Save link', ], 'suspend_form' => [ - 'disclaimer' => 'Suspendre l\'abonnement empêchera l\'abonné d\'avoir accès au contenu premium. Vous pourrez toujours lever la suspension par la suite.', - 'reason' => 'Raison', - 'reason_placeholder' => 'Pour quelle raison arrêtez vous votre abonnement ?', - "submit" => 'Suspendre l\'abonnement', + 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', + 'reason' => 'Reason', + 'reason_placeholder' => 'Why are you suspending the subscription?', + "submit" => 'Suspend subscription', ], 'delete_form' => [ - 'disclaimer' => 'La suppression de l\'abonnement de {subscriber} supprimera toutes les données d\'analyse qui lui sont associées.', - 'understand' => 'Je comprends, supprimez l\'abonnement définitivement', - 'submit' => 'Supprimer l\'abonnement', + 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', + 'understand' => 'I understand, remove the subscription permanently', + 'submit' => 'Remove subscription', ], 'messages' => [ - 'addSuccess' => 'Un nouvel abonnement a été ajouté ! Un e-mail de bienvenue a été envoyé à {subscriber}.', - 'addError' => 'L\'abonnement n\'a pu être ajouté.', - 'editSuccess' => 'La date d\'expiration de l\'abonnement a été mise à jour ! Un e-mail a été envoyé à {subscriber}.', - 'editError' => 'L\'abonnement n\'a pas pu être modifié.', - 'regenerateTokenSuccess' => 'Jeton régénéré ! Un email a été envoyé à {subscriber} avec le nouveau jeton.', - 'regenerateTokenError' => 'Le jeton n\'a pas pu être régénéré.', - 'deleteSuccess' => 'L\'abonnement a été suspendu! Un e-mail a été envoyé à {subscriber}.', - 'deleteError' => 'L\'abonnement n\'a pas pu être supprimé.', - 'suspendSuccess' => 'L\'abonnement a été suspendu! Un e-mail a été envoyé à {subscriber}.', - 'suspendError' => 'L\'abonnement ne peut pas être suspendu.', - 'resumeSuccess' => 'L\'abonnement a été suspendu! Un e-mail a été envoyé à {subscriber}.', - 'resumeError' => 'L\'abonnement n\'a pas pu être repris.', - 'linkSaveSuccess' => 'Le lien de l\'abonnement a été enregistré avec succès ! Il apparaîtra sur le site comme un Appel à l\'action !', - 'linkRemoveSuccess' => 'Le lien de l\'abonnement a été supprimé avec succès !', + 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', + 'addError' => 'Subscription could not be added.', + 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', + 'editError' => 'Subscription could not be edited.', + 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', + 'regenerateTokenError' => 'Token could not be regenerated.', + 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', + 'deleteError' => 'Subscription could not be removed.', + 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', + 'suspendError' => 'Subscription could not be suspended.', + 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', + 'resumeError' => 'Subscription could not be resumed.', + 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', + 'linkRemoveSuccess' => 'Subscription link was removed successfully!', ], 'emails' => [ - 'greeting' => 'Hé,', - 'token' => 'Votre jeton : {0}', - 'unique_feed_link' => 'Votre lien de flux unique : {0}', - 'how_to_use' => 'Comment l\'utiliser ?', - 'two_ways' => 'Vous avez deux façons de débloquer les épisodes premium :', - 'import_into_app' => 'Copiez votre URL de flux unique dans votre application de baladodiffusion préférée (importez-la en tant que flux privé pour éviter de dévoiler vos identifiants).', - 'go_to_website' => 'Rendez-vous sur le site web de {podcastWebsite} et débloquez le podcast avec votre jeton.', - 'welcome_subject' => 'Bienvenue sur {podcastTitle}', - 'welcome' => 'Vous vous êtes abonné à {podcastTitle}, merci et bienvenue à bord !', - 'welcome_token_title' => 'Voici vos identifiants pour débloquer les épisodes premium du podcast:', - 'welcome_expires' => 'Votre abonnement a été configuré pour expirer le {0}.', - 'welcome_never_expires' => 'Votre abonnement a été configuré pour ne jamais expirer.', - 'reset_subject' => 'Votre jeton a été réinitialisé !', - 'reset_token' => 'Votre accès à {podcastTitle} a été réinitialisé !', - 'reset_token_title' => 'De nouveaux identifiants ont été générés pour vous permettre de déverrouiller les épisodes premium du podcast:', - 'edited_subject' => 'Votre abonnement a été mis à jour !', - 'edited_expires' => 'Votre abonnement pour {podcastTitle} a été configuré pour expirer le {expiresAt}.', - 'edited_never_expires' => 'Votre abonnement pour {podcastTitle} a été configuré pour ne jamais expirer !', - 'suspended_subject' => 'Votre abonnement a été suspendu !', - 'suspended' => 'Votre abonnement à {podcastTitle} a été suspendu ! Vous ne pouvez plus accéder aux épisodes premium du podcast.', - 'suspended_reason' => 'Pour la raison suivante : {0}', - 'resumed_subject' => 'Votre abonnement a été réactivé !', - 'resumed' => 'Votre abonnement à {podcastTitle} a été réactivé ! Vous pouvez à nouveau accéder aux épisodes premium du podcast.', - 'deleted_subject' => 'Votre abonnement a été supprimé !', - 'deleted' => 'Votre abonnement pour {podcastTitle} a été supprimé ! Vous n\'avez plus accès aux épisodes premium du podcast.', - 'footer' => '{castopod} hébergé sur {host}', + 'greeting' => 'Hey,', + 'token' => 'Your token: {0}', + 'unique_feed_link' => 'Your unique feed link: {0}', + 'how_to_use' => 'How to use?', + 'two_ways' => 'You have two ways of unlocking the premium episodes:', + 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', + 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', + 'welcome_subject' => 'Welcome to {podcastTitle}', + 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', + 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', + 'welcome_expires' => 'Your subscription was set to expire on {0}.', + 'welcome_never_expires' => 'Your subscription was set to never expire.', + 'reset_subject' => 'Your token was reset!', + 'reset_token' => 'Your access to {podcastTitle} has been reset!', + 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', + 'edited_subject' => 'Your subscription has been updated!', + 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', + 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', + 'suspended_subject' => 'Your subscription has been suspended!', + 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', + 'suspended_reason' => 'That is for the following reason: {0}', + 'resumed_subject' => 'Your subscription has been resumed!', + 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', + 'deleted_subject' => 'Your subscription has been removed!', + 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', + 'footer' => '{castopod} hosted on {host}', ], ]; diff --git a/modules/PremiumPodcasts/Language/fr2/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/fr2/PremiumPodcasts.php deleted file mode 100644 index 18c0dd4e..00000000 --- a/modules/PremiumPodcasts/Language/fr2/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podcast contains premium episodes', - 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', - 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', - 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', - 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', - 'subscribe' => 'Subscribe', - 'lock' => 'Lock', - 'unlock' => 'Unlock', - 'unlock_form' => [ - 'title' => 'Premium content', - 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', - 'token' => 'Enter your key', - 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', - 'submit' => 'Unlock all episodes!', - 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', - 'subscribe_cta' => 'Subscribe now!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', - 'unlockBadAttempt' => 'Your key does not seem to be working…', - 'lockSuccess' => 'Podcast was successfully locked!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/fr2/Subscription.php b/modules/PremiumPodcasts/Language/fr2/Subscription.php deleted file mode 100644 index e83f0cb2..00000000 --- a/modules/PremiumPodcasts/Language/fr2/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Podcast subscriptions', - 'add' => 'New subscription', - 'view' => 'View subscription', - 'edit' => 'Edit subscription', - 'regenerate_token' => 'Regenerate token', - 'suspend' => 'Suspend subscription', - 'resume' => 'Resume subscription', - 'delete' => 'Delete subscription', - 'status' => [ - 'active' => 'Active', - 'suspended' => 'Suspended', - 'expired' => 'Expired', - ], - 'list' => [ - 'number' => 'Number', - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'unlimited' => 'Unlimited', - 'downloads' => 'Downloads', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Edit subscription', - ], - 'form_link_add' => [ - 'link' => 'Subscription page link', - 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', - 'submit' => 'Save link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/gd/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/gd/PremiumPodcasts.php index ac6d33e4..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/gd/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/gd/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Tha eapasodan premium aig a’ phod-chraoladh seo', - 'episode_is_premium' => 'Seo eapasod premium, chan eil e ri fhaighinn ach do dh’fho-sgrìobhaichean premium', - 'unlock_episode' => 'Tha an t-eapasod seo do dh’fho-sgrìobhaichean premium a-mhàin. Briog air gus a’ ghlas a thoirt fo bhàrr!', - 'banner_unlock' => 'Tha eapasodan premium sa phod-chraoladh seo nach eil ri fhaighinn ach do dh’fho-sgrìobhaichean premium.', - 'banner_lock' => 'Thug thu a’ ghlas far a’ phod-chraolaidh, gabh tlachd às na h-eapasodan premium!', - 'subscribe' => 'Fo-sgrìobh', - 'lock' => 'Glais', - 'unlock' => 'Thoir a’ ghlas dheth', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', + 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Susbaint premium', - 'subtitle' => 'Tha eapasodan premium glaiste aig a’ phod-chraoladh seo! A bheil iuchair agad gus a’ ghlas a thoirt fo am bàrr?', - 'token' => 'Cuir a-steach an iuchair agad', - 'token_hint' => 'Ma fhuair thu fo-sgrìobhadh air {podcastTitle}, ’s urrainn dhut lethbhreac a dhèanamh dhen iuchair a chaidh a chur thugad air a’ phost-d ’s a cur ann an-seo.', - 'submit' => 'Thoir a’ ghlas far a h-uile eapasod!', - 'call_to_action' => 'Thoir a’ ghlas far a h-uile eapasod aig {podcastTitle}:', - 'subscribe_cta' => 'Fo-sgrìobh an-dràsta!', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', + 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => 'Thug thu a’ ghlas far a’ phod-chraolaidh! Gabh tlachd às na h-eapasodan premium!', - 'unlockBadAttempt' => 'Tha coltas nach eil an iuchair agad ag obair…', - 'lockSuccess' => 'Chaidh am pod-chraoladh a ghlasadh!', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/gd/Subscription.php b/modules/PremiumPodcasts/Language/gd/Subscription.php index 2dbfdeb6..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/gd/Subscription.php +++ b/modules/PremiumPodcasts/Language/gd/Subscription.php @@ -9,92 +9,92 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Fo-sgrìobhaidhean air pod-chraolaidhean', - 'add' => 'Fo-sgrìobhadh ùr', - 'view' => 'Seall am fo-sgrìobhadh', - 'edit' => 'Deasaich am fo-sgrìobhadh', - 'regenerate_token' => 'Ath-ghin an tòcan', - 'suspend' => 'Cuir am fo-sgrìobhadh à rèim', - 'resume' => 'Lean air an fho-sgrìobhadh', - 'delete' => 'Sguab às am fo-sgrìobhadh', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Gnìomhach', - 'suspended' => 'À rèim', - 'expired' => 'Dh’fhalbh an ùine air', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Àireamh', - 'email' => 'Post-d', - 'expiration_date' => 'Ceann-là crìochnachaidh', - 'unlimited' => 'Gun chrìoch', - 'downloads' => 'Luchdaidhean a-nuas', - 'status' => 'Staid', + 'number' => 'Number', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', + 'downloads' => 'Downloads', + 'status' => 'Status', ], 'form' => [ - 'email' => 'Post-d', - 'expiration_date' => 'Ceann-là crìochnachaidh', - 'expiration_date_hint' => 'An ceann-là ’s àm a dh’fhalbhas an ùine air an fho-sgrìobhadh. Fàg bàn e airson fo-sgrìobhadh gun chrìoch.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Deasaich am fo-sgrìobhadh', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', + 'submit_add' => 'Add subscription', + 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ - 'link' => 'Ceangal gu duilleag an fho-sgrìobhaidh', - 'link_hint' => 'Cuiridh seo tàladh ris an làrach-lìn a bheir cuireadh dhan luchd-èisteachd ach am faigh iad fo-sgrìobhadh air a’ phod-chraoladh.', - 'submit' => 'Sàbhail an ceangal', + 'link' => 'Subscription page link', + 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', + 'submit' => 'Save link', ], 'suspend_form' => [ - 'disclaimer' => 'Ma chuireas tu am fo-sgrìobhadh à rèim, cuingichidh seo an neach fo-sgrìobhaidh gus nach fhaigh iad cothrom air susbaint premium. ’S urrainn dhut a chur ann an rèim a-rithist uair sam bith an uairsin.', - 'reason' => 'Adhbhar', - 'reason_placeholder' => 'Carson a tha thu a’ cur am fo-sgrìobhadh à rèim?', - "submit" => 'Cuir am fo-sgrìobhadh à rèim', + 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', + 'reason' => 'Reason', + 'reason_placeholder' => 'Why are you suspending the subscription?', + "submit" => 'Suspend subscription', ], 'delete_form' => [ - 'disclaimer' => 'Ma sguabas tu às am fo-sgrìobhadh aig {subscriber}, bheir seo air falbh dàta sam bith na h-anailiseachd a tha co-cheangailte ris.', - 'understand' => 'Tha mi agaibh, thoir air falbh am fo-sgrìobhadh gu buan', - 'submit' => 'Thoir am fo-sgrìobhadh air falbh', + 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', + 'understand' => 'I understand, remove the subscription permanently', + 'submit' => 'Remove subscription', ], 'messages' => [ - 'addSuccess' => 'Chaidh fo-sgrìobhadh ùr a chur ris! Chaidh post-d fàilteachaidh a chur gu {subscriber}.', - 'addError' => 'Cha b’ urrainn dhuinn am fo-sgrìobhadh a chur ris.', - 'editSuccess' => 'Chaidh an ceann-là a dh’fhalbhas an ùine air an fho-sgrìobhadh ùrachadh! Chaidh post-d a chur gu {subscriber}.', - 'editError' => 'Cha b’ urrainn dhuinn am fo-sgrìobhadh a dheasachadh.', - 'regenerateTokenSuccess' => 'Chaidh an tòcan ath-ghintinn! Chaidh post-d a chur gu {subscriber} leis an tòcan ùr.', - 'regenerateTokenError' => 'Cha b’ urrainn dhuinn an tòcan ath-ghintinn.', - 'deleteSuccess' => 'Chaidh am fo-sgrìobhadh a thoirt air falbh! Chaidh post-d a chur gu {subscriber}.', - 'deleteError' => 'Cha b’ urrainn dhuinn am fo-sgrìobhadh a thoirt air falbh.', - 'suspendSuccess' => 'Chaidh am fo-sgrìobhadh a chur à rèim! Chaidh post-d a chur gu {subscriber}.', - 'suspendError' => 'Cha b’ urrainn dhuinn am fo-sgrìobhadh a cur à rèim.', - 'resumeSuccess' => 'Chaidh leantainn air an fho-sgrìobhadh! Chaidh post-d a chur gu {subscriber}.', - 'resumeError' => 'Cha b’ urrainn dhuinn leantainn air an fho-sgrìobhadh.', - 'linkSaveSuccess' => 'Chaidh an ceangal dhan fho-sgrìobhadh a shàbhaladh! Nochdaidh e air an làrach-lìn na thadhladh!', - 'linkRemoveSuccess' => 'Chaidh an ceangal dhan fho-sgrìobhadh a thoirt air falbh!', + 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', + 'addError' => 'Subscription could not be added.', + 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', + 'editError' => 'Subscription could not be edited.', + 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', + 'regenerateTokenError' => 'Token could not be regenerated.', + 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', + 'deleteError' => 'Subscription could not be removed.', + 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', + 'suspendError' => 'Subscription could not be suspended.', + 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', + 'resumeError' => 'Subscription could not be resumed.', + 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', + 'linkRemoveSuccess' => 'Subscription link was removed successfully!', ], 'emails' => [ - 'greeting' => 'Shin thu,', - 'token' => 'Seo an tòcan agad: {0}', - 'unique_feed_link' => 'Seo ceangal àraidh an inbhir agad: {0}', - 'how_to_use' => 'Mar a chleachdas tu e', - 'two_ways' => 'Tha dà dhòigh ann air an doir thu a’ ghlas far eapasodan premium:', - 'import_into_app' => 'Cuir lethbhreac de dh’URL àraidh an inbhir agad san aplacaid pod-chraolaidh as fheàrr leat (ion-phortaich e ’na inbhir prìobhaideach ach nach foillsich thu an teisteanas agad).', - 'go_to_website' => 'Tadhail air an làrach-lìn aig {podcastWebsite} agus thoir a’ ghlas far a’ phod-chraolaidh leis an tòcan agad.', - 'welcome_subject' => 'Fàilte gu {podcastTitle}', - 'welcome' => 'Fhuair thu fo-sgrìobhadh air {podcastTitle}, mòran taing is fàilte air bhòrd!', - 'welcome_token_title' => 'Seo an teisteanas agad airson a’ ghlas a thoirt far eapasodan premium a’ phod-chraolaidh:', - 'welcome_expires' => 'Chaidh crìoch an fho-sgrìobhaidh agad a shuidheachadh air {0}.', - 'welcome_never_expires' => 'Chaidh am fo-sgrìobhaidh agad a shuidheachadh ach nach fhalbh an ùine air.', - 'reset_subject' => 'Chaidh an tòcan agad ath-shuidheachadh!', - 'reset_token' => 'Chaidh an t-inntrigeadh agad air {podcastTitle} ath-shuidheachadh!', - 'reset_token_title' => 'Chaidh teisteanas ùr a ghintinn dhut airson a’ ghlas a thoirt far eapasodan premium a’ phod-chraolaidh:', - 'edited_subject' => 'Chaidh am fo-sgrìobhadh agad ùrachadh!', - 'edited_expires' => 'Chaidh crìoch an fho-sgrìobhaidh agad air {podcastTitle} a shuidheachadh air {expiresAt}.', - 'edited_never_expires' => 'Chaidh am fo-sgrìobhaidh agad air {podcastTitle} a shuidheachadh ach nach fhalbh an ùine air!', - 'suspended_subject' => 'Chaidh am fo-sgrìobhadh agad a chur à rèim!', - 'suspended' => 'Chaidh am fo-sgrìobhadh agad air {podcastTitle} a chur à rèim! Chan urrainn dhut eapasodan premium a’ phod-chraolaidh inntrigeadh tuilleadh.', - 'suspended_reason' => 'Seo as adhbhar dha: {0}', - 'resumed_subject' => 'Chaidh leantainn air an fho-sgrìobhadh agad!', - 'resumed' => 'Chaidh leantainn air an fho-sgrìobhadh air {podcastTitle} agad! ’S urrainn dhut eapasodan premium a’ phod-chraolaidh inntrigeadh a-rithist.', - 'deleted_subject' => 'Chaidh am fo-sgrìobhadh agad a thoirt air falbh!', - 'deleted' => 'Chaidh am fo-sgrìobhadh agad air {podcastTitle} a thoirt air falbh! Chan urrainn dhut eapasodan premium a’ phod-chraolaidh inntrigeadh tuilleadh.', - 'footer' => 'Seo {castopod} ’ga òstadh air {host}', + 'greeting' => 'Hey,', + 'token' => 'Your token: {0}', + 'unique_feed_link' => 'Your unique feed link: {0}', + 'how_to_use' => 'How to use?', + 'two_ways' => 'You have two ways of unlocking the premium episodes:', + 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', + 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', + 'welcome_subject' => 'Welcome to {podcastTitle}', + 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', + 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', + 'welcome_expires' => 'Your subscription was set to expire on {0}.', + 'welcome_never_expires' => 'Your subscription was set to never expire.', + 'reset_subject' => 'Your token was reset!', + 'reset_token' => 'Your access to {podcastTitle} has been reset!', + 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', + 'edited_subject' => 'Your subscription has been updated!', + 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', + 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', + 'suspended_subject' => 'Your subscription has been suspended!', + 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', + 'suspended_reason' => 'That is for the following reason: {0}', + 'resumed_subject' => 'Your subscription has been resumed!', + 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', + 'deleted_subject' => 'Your subscription has been removed!', + 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', + 'footer' => '{castopod} hosted on {host}', ], ]; diff --git a/modules/PremiumPodcasts/Language/gl/Subscription.php b/modules/PremiumPodcasts/Language/gl/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/gl/Subscription.php +++ b/modules/PremiumPodcasts/Language/gl/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/id/Subscription.php b/modules/PremiumPodcasts/Language/id/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/id/Subscription.php +++ b/modules/PremiumPodcasts/Language/id/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/it/Subscription.php b/modules/PremiumPodcasts/Language/it/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/it/Subscription.php +++ b/modules/PremiumPodcasts/Language/it/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/ja/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/ja/PremiumPodcasts.php deleted file mode 100644 index 18c0dd4e..00000000 --- a/modules/PremiumPodcasts/Language/ja/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podcast contains premium episodes', - 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', - 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', - 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', - 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', - 'subscribe' => 'Subscribe', - 'lock' => 'Lock', - 'unlock' => 'Unlock', - 'unlock_form' => [ - 'title' => 'Premium content', - 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', - 'token' => 'Enter your key', - 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', - 'submit' => 'Unlock all episodes!', - 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', - 'subscribe_cta' => 'Subscribe now!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', - 'unlockBadAttempt' => 'Your key does not seem to be working…', - 'lockSuccess' => 'Podcast was successfully locked!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/ja/Subscription.php b/modules/PremiumPodcasts/Language/ja/Subscription.php deleted file mode 100644 index e83f0cb2..00000000 --- a/modules/PremiumPodcasts/Language/ja/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Podcast subscriptions', - 'add' => 'New subscription', - 'view' => 'View subscription', - 'edit' => 'Edit subscription', - 'regenerate_token' => 'Regenerate token', - 'suspend' => 'Suspend subscription', - 'resume' => 'Resume subscription', - 'delete' => 'Delete subscription', - 'status' => [ - 'active' => 'Active', - 'suspended' => 'Suspended', - 'expired' => 'Expired', - ], - 'list' => [ - 'number' => 'Number', - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'unlimited' => 'Unlimited', - 'downloads' => 'Downloads', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Edit subscription', - ], - 'form_link_add' => [ - 'link' => 'Subscription page link', - 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', - 'submit' => 'Save link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/kk/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/kk/PremiumPodcasts.php deleted file mode 100644 index 18c0dd4e..00000000 --- a/modules/PremiumPodcasts/Language/kk/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podcast contains premium episodes', - 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', - 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', - 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', - 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', - 'subscribe' => 'Subscribe', - 'lock' => 'Lock', - 'unlock' => 'Unlock', - 'unlock_form' => [ - 'title' => 'Premium content', - 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', - 'token' => 'Enter your key', - 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', - 'submit' => 'Unlock all episodes!', - 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', - 'subscribe_cta' => 'Subscribe now!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', - 'unlockBadAttempt' => 'Your key does not seem to be working…', - 'lockSuccess' => 'Podcast was successfully locked!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/kk/Subscription.php b/modules/PremiumPodcasts/Language/kk/Subscription.php deleted file mode 100644 index e83f0cb2..00000000 --- a/modules/PremiumPodcasts/Language/kk/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Podcast subscriptions', - 'add' => 'New subscription', - 'view' => 'View subscription', - 'edit' => 'Edit subscription', - 'regenerate_token' => 'Regenerate token', - 'suspend' => 'Suspend subscription', - 'resume' => 'Resume subscription', - 'delete' => 'Delete subscription', - 'status' => [ - 'active' => 'Active', - 'suspended' => 'Suspended', - 'expired' => 'Expired', - ], - 'list' => [ - 'number' => 'Number', - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'unlimited' => 'Unlimited', - 'downloads' => 'Downloads', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Edit subscription', - ], - 'form_link_add' => [ - 'link' => 'Subscription page link', - 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', - 'submit' => 'Save link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/ko/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/ko/PremiumPodcasts.php deleted file mode 100644 index 18c0dd4e..00000000 --- a/modules/PremiumPodcasts/Language/ko/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podcast contains premium episodes', - 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', - 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', - 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', - 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', - 'subscribe' => 'Subscribe', - 'lock' => 'Lock', - 'unlock' => 'Unlock', - 'unlock_form' => [ - 'title' => 'Premium content', - 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', - 'token' => 'Enter your key', - 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', - 'submit' => 'Unlock all episodes!', - 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', - 'subscribe_cta' => 'Subscribe now!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', - 'unlockBadAttempt' => 'Your key does not seem to be working…', - 'lockSuccess' => 'Podcast was successfully locked!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/ko/Subscription.php b/modules/PremiumPodcasts/Language/ko/Subscription.php deleted file mode 100644 index e83f0cb2..00000000 --- a/modules/PremiumPodcasts/Language/ko/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Podcast subscriptions', - 'add' => 'New subscription', - 'view' => 'View subscription', - 'edit' => 'Edit subscription', - 'regenerate_token' => 'Regenerate token', - 'suspend' => 'Suspend subscription', - 'resume' => 'Resume subscription', - 'delete' => 'Delete subscription', - 'status' => [ - 'active' => 'Active', - 'suspended' => 'Suspended', - 'expired' => 'Expired', - ], - 'list' => [ - 'number' => 'Number', - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'unlimited' => 'Unlimited', - 'downloads' => 'Downloads', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Edit subscription', - ], - 'form_link_add' => [ - 'link' => 'Subscription page link', - 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', - 'submit' => 'Save link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/nl/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/nl/PremiumPodcasts.php index 8c05e623..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/nl/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/nl/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Podcast bevat premium afleveringen', - 'episode_is_premium' => 'Aflevering is premium, alleen beschikbaar voor premium abonnees', - 'unlock_episode' => 'Deze aflevering is alleen voor premium abonnees. Klik om te ontgrendelen!', - 'banner_unlock' => 'Deze podcast bevat premium afleveringen, alleen beschikbaar voor premium abonnees.', - 'banner_lock' => 'Podcast is ontgrendeld, geniet van de premium afleveringen!', - 'subscribe' => 'Abonneren', - 'lock' => 'Vergrendel', - 'unlock' => 'Ontgrendel', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', + 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Premium inhoud', - 'subtitle' => 'Deze podcast bevat vergrendelde premium afleveringen! Heb je de sleutel om ze te ontgrendelen?', - 'token' => 'Voer jouw sleutel in', - 'token_hint' => 'Als je geabonneerd bent op {podcastTitle}, kun je de sleutel die naar je verzonden is via e-mail kopiëren en deze hier plakken.', - 'submit' => 'Ontgrendel alle afleveringen!', - 'call_to_action' => 'Ontgrendel alle afleveringen van {podcastTitle}:', - 'subscribe_cta' => 'Nu abonneren!', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', + 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => 'Podcast is succesvol ontgrendeld! Geniet van de premium afleveringen!', - 'unlockBadAttempt' => 'Jouw sleutel lijkt niet te werken…', - 'lockSuccess' => 'Podcast is succesvol vergrendeld!', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/nl/Subscription.php b/modules/PremiumPodcasts/Language/nl/Subscription.php index 36bc8976..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/nl/Subscription.php +++ b/modules/PremiumPodcasts/Language/nl/Subscription.php @@ -9,92 +9,92 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Podcast abonnementen', - 'add' => 'Nieuw abonnement', - 'view' => 'Bekijk abonnement', - 'edit' => 'Bewerk abonnement', - 'regenerate_token' => 'Sleutel opnieuw genereren', - 'suspend' => 'Abonnement opschorten', - 'resume' => 'Abonnement hervatten', - 'delete' => 'Abonnement verwijderen', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Actief', - 'suspended' => 'Opgeschort', - 'expired' => 'Verlopen', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Nummer', - 'email' => 'E-mail', - 'expiration_date' => 'Vervaldatum', - 'unlimited' => 'Onbeperkt', + 'number' => 'Number', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', 'downloads' => 'Downloads', 'status' => 'Status', ], 'form' => [ - 'email' => 'E-mail', - 'expiration_date' => 'Vervaldatum', - 'expiration_date_hint' => 'De datum en tijd waarop het abonnement verloopt. Laat leeg voor een onbeperkt abonnement.', - 'submit_create' => 'Abonnement aanmaken', - 'submit_edit' => 'Bewerk abonnement', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', + 'submit_add' => 'Add subscription', + 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ - 'link' => 'Abonnementspagina link', - 'link_hint' => 'Dit zal een call-to-action toevoegen op de website die luisteraars uitnodigt om zich te abonneren op de podcast.', - 'submit' => 'Link opslaan', + 'link' => 'Subscription page link', + 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', + 'submit' => 'Save link', ], 'suspend_form' => [ - 'disclaimer' => 'Opschorting van het abonnement zorgt ervoor dat de abonnee geen toegang meer heeft tot premium inhoud. U kunt de opschorting op ieder moment opheffen.', - 'reason' => 'Reden', - 'reason_placeholder' => 'Waarom wilt u het abonnement onderbreken?', - "submit" => 'Abonnement opschorten', + 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', + 'reason' => 'Reason', + 'reason_placeholder' => 'Why are you suspending the subscription?', + "submit" => 'Suspend subscription', ], 'delete_form' => [ - 'disclaimer' => 'Het verwijderen van het abonnement van {subscriber} zal alle statistieken ervan verwijderen.', - 'understand' => 'Ik begrijp het, verwijder het abonnement permanent', - 'submit' => 'Abonnement verwijderen', + 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', + 'understand' => 'I understand, remove the subscription permanently', + 'submit' => 'Remove subscription', ], 'messages' => [ - 'addSuccess' => 'Nieuw abonnement toegevoegd! Er is een welkomstmail is naar {subscriber} gestuurd.', - 'addError' => 'Abonnement kon niet worden toegevoegd.', - 'editSuccess' => 'Abonnement vervaldatum is bijgewerkt! Er is een e-mail verzonden naar {subscriber}.', - 'editError' => 'Abonnement kon niet worden bijgewerkt.', - 'regenerateTokenSuccess' => 'Token vernieuwd! Er is een e-mail verzonden naar {subscriber} met de nieuwe gegevens.', - 'regenerateTokenError' => 'Token kon niet worden vernieuwd.', - 'deleteSuccess' => 'Abonnement is verwijderd! Er is een e-mail verzonden naar {subscriber}.', - 'deleteError' => 'Abonnement kon niet worden verwijderd.', - 'suspendSuccess' => 'Abonnement is opgeschort! Er is een e-mail verzonden naar {subscriber}.', - 'suspendError' => 'Abonnement kon niet opgeschort worden.', - 'resumeSuccess' => 'Abonnement is hervat! Er is een e-mail verzonden naar {subscriber}.', - 'resumeError' => 'Abonnement kon niet worden hervat.', - 'linkSaveSuccess' => 'Abonnementlink is succesvol opgeslagen! Het zal verschijnen op de website als een call-to-action!', - 'linkRemoveSuccess' => 'Abonnementlink is succesvol verwijderd!', + 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', + 'addError' => 'Subscription could not be added.', + 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', + 'editError' => 'Subscription could not be edited.', + 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', + 'regenerateTokenError' => 'Token could not be regenerated.', + 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', + 'deleteError' => 'Subscription could not be removed.', + 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', + 'suspendError' => 'Subscription could not be suspended.', + 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', + 'resumeError' => 'Subscription could not be resumed.', + 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', + 'linkRemoveSuccess' => 'Subscription link was removed successfully!', ], 'emails' => [ - 'greeting' => 'Hoi,', - 'token' => 'Uw token: {0}', - 'unique_feed_link' => 'Uw persoonlijke feed: {0}', - 'how_to_use' => 'Gebruiksaanwijzing', - 'two_ways' => 'Je hebt twee manieren om toegang te krijgen tot de premium afleveringen:', - 'import_into_app' => 'Kopieer uw persoonlijke feed in je favoriete podcast app (importeer deze als een privé feed om te voorkomen dat je inloggegevens worden gedeeld).', - 'go_to_website' => 'Ga naar de website van {podcastWebsite} en krijgt toegang tot de podcast met uw persoonlijke token.', - 'welcome_subject' => 'Welkom bij {podcastTitle}', - 'welcome' => 'Je bent geabonneerd op {podcastTitle}, bedankt en welkom bij de club!', - 'welcome_token_title' => 'Hier zijn uw inloggegevens om toegang te krijgen tot de premium afleveringen van de podcast:', - 'welcome_expires' => 'Uw abonnement verloopt op {0}.', - 'welcome_never_expires' => 'Uw abonnement stopt niet automatisch.', - 'reset_subject' => 'Je token is vernieuwd!', - 'reset_token' => 'Uw toegang tot {podcastTitle} is gereset!', - 'reset_token_title' => 'Nieuwe inloggegevens zijn gegenereerd om toegang tot de premium afleveringen van de podcast te krijgen:', - 'edited_subject' => 'Uw abonnement is bijgewerkt!', - 'edited_expires' => 'Je abonnement voor {podcastTitle} vervalt op {expiresAt}.', - 'edited_never_expires' => 'Je abonnement voor {podcastTitle} is ingesteld om niet automatisch te verlopen!', - 'suspended_subject' => 'Uw abonnement is opgeschort!', - 'suspended' => 'Uw abonnement voor {podcastTitle} is opgeschort! U heeft niet langer toegang tot de premium afleveringen van de podcast.', - 'suspended_reason' => 'Dat is gebeurd om de volgende reden: {0}', - 'resumed_subject' => 'Uw abonnement is hervat!', - 'resumed' => 'Uw abonnement op {podcastTitle} is hervat! U heeft weer toegang tot de premium afleveringen van de podcast.', - 'deleted_subject' => 'Uw abonnement is beëindigd!', - 'deleted' => 'Uw abonnement op {podcastTitle} is verwijderd! U heeft niet langer toegang tot de premium afleveringen van de podcast.', - 'footer' => '{castopod} gehost op {host}', + 'greeting' => 'Hey,', + 'token' => 'Your token: {0}', + 'unique_feed_link' => 'Your unique feed link: {0}', + 'how_to_use' => 'How to use?', + 'two_ways' => 'You have two ways of unlocking the premium episodes:', + 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', + 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', + 'welcome_subject' => 'Welcome to {podcastTitle}', + 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', + 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', + 'welcome_expires' => 'Your subscription was set to expire on {0}.', + 'welcome_never_expires' => 'Your subscription was set to never expire.', + 'reset_subject' => 'Your token was reset!', + 'reset_token' => 'Your access to {podcastTitle} has been reset!', + 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', + 'edited_subject' => 'Your subscription has been updated!', + 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', + 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', + 'suspended_subject' => 'Your subscription has been suspended!', + 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', + 'suspended_reason' => 'That is for the following reason: {0}', + 'resumed_subject' => 'Your subscription has been resumed!', + 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', + 'deleted_subject' => 'Your subscription has been removed!', + 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', + 'footer' => '{castopod} hosted on {host}', ], ]; diff --git a/modules/PremiumPodcasts/Language/da/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/nn-NO/PremiumPodcasts.php similarity index 100% rename from modules/PremiumPodcasts/Language/da/PremiumPodcasts.php rename to modules/PremiumPodcasts/Language/nn-NO/PremiumPodcasts.php diff --git a/modules/PremiumPodcasts/Language/fr-ca/Subscription.php b/modules/PremiumPodcasts/Language/nn-NO/Subscription.php similarity index 99% rename from modules/PremiumPodcasts/Language/fr-ca/Subscription.php rename to modules/PremiumPodcasts/Language/nn-NO/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/fr-ca/Subscription.php +++ b/modules/PremiumPodcasts/Language/nn-NO/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/nn-no/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/nn-no/PremiumPodcasts.php deleted file mode 100644 index 4decf740..00000000 --- a/modules/PremiumPodcasts/Language/nn-no/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podkasten inneheld betalte episodar', - 'episode_is_premium' => 'Episoden er bak betalingsmur. Berre betalande abonnentar har tilgang', - 'unlock_episode' => 'Denne episoden er berre for betalande abonnentar. Klikk for å få tilgang!', - 'banner_unlock' => 'Denne podkasten inneheld episodar som berre er tilgjengelege for betalande abonnentar.', - 'banner_lock' => 'Podkasten er låst opp, så no kan du høyra på dei betalte episodane!', - 'subscribe' => 'Abonner', - 'lock' => 'Lås', - 'unlock' => 'Lås opp', - 'unlock_form' => [ - 'title' => 'Betalt innhald', - 'subtitle' => 'Denne podkasten inneheld episodar bak betalingsmur. Har du nykelen for å få tilgang til dei?', - 'token' => 'Skriv inn nykelen', - 'token_hint' => 'Viss du abonnerer på {podcastTitle}, kan du kopiera nykelen du fekk på epost og lima han inn her.', - 'submit' => 'Få tilgang til alle episodane!', - 'call_to_action' => 'Få tilgang til alle episodane av {podcastTitle}:', - 'subscribe_cta' => 'Abonner no!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podkasten er låst opp. No kan du høyra på dei betalte episodane!', - 'unlockBadAttempt' => 'Nykelen din fungerer ikkje…', - 'lockSuccess' => 'Podkasten er låst.', - ], -]; diff --git a/modules/PremiumPodcasts/Language/nn-no/Subscription.php b/modules/PremiumPodcasts/Language/nn-no/Subscription.php deleted file mode 100644 index d32055c8..00000000 --- a/modules/PremiumPodcasts/Language/nn-no/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Abonnement til podkasten', - 'add' => 'Nytt abonnement', - 'view' => 'Vis abonnementet', - 'edit' => 'Rediger abonnementet', - 'regenerate_token' => 'Regenerer nykel', - 'suspend' => 'Stopp abonnementet', - 'resume' => 'Start oppatt abonnementet', - 'delete' => 'Slett abonnementet', - 'status' => [ - 'active' => 'Aktiv', - 'suspended' => 'Stoppa', - 'expired' => 'Utgått', - ], - 'list' => [ - 'number' => 'Nummer', - 'email' => 'Epost', - 'expiration_date' => 'Gyldig til', - 'unlimited' => 'Uavgrensa', - 'downloads' => 'Nedlastingar', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'Epost', - 'expiration_date' => 'Gyldig til', - 'expiration_date_hint' => 'Datoen og tidspunket abonnementet stoppar. La det stå tomt viss abonnementet skal gå utan sluttdato.', - 'submit_create' => 'Opprett abonnement', - 'submit_edit' => 'Rediger abonnementet', - ], - 'form_link_add' => [ - 'link' => 'Lenke til abonnementssida', - 'link_hint' => 'Her legg du til ei oppmoding på nettsida di, der du inviterer lyttarane til å abonnera på podkasten din.', - 'submit' => 'Lagre lenka', - ], - 'suspend_form' => [ - 'disclaimer' => 'Viss du stoppar abonnementet, vil ikkje abonnenten lenger få tilgang til betalt innhald. Du kan starta abonnementet att seinare.', - 'reason' => 'Grunngjeving', - 'reason_placeholder' => 'Kvifor stoppar du abonnementet?', - "submit" => 'Stopp abonnementet', - ], - 'delete_form' => [ - 'disclaimer' => 'Viss du slettar abonnementet til {subscriber}, slettar du òg alle analysedata knytt til abonnementet.', - 'understand' => 'Eg forstår, slett abonnementet', - 'submit' => 'Slett abonnementet', - ], - 'messages' => [ - 'addSuccess' => 'Du har fått ein ny abonnent! Me har sendt ein velkomstepost til {subscriber}.', - 'addError' => 'Greidde ikkje leggja til abonnementet.', - 'editSuccess' => 'Stoppdatoen for abonnementet er oppdatert! Me har sendt ein epost til {subscriber}.', - 'editError' => 'Greidde ikkje redigera abonnementet.', - 'regenerateTokenSuccess' => 'Nykelen er regenerert! Me sende ein epost til {subscriber} med den nye nykelen.', - 'regenerateTokenError' => 'Greidde ikkje regenerera nykelen.', - 'deleteSuccess' => 'Abonnementet er sletta! Me sende ein epost til {subscriber}.', - 'deleteError' => 'Greidde ikkje sletta abonnementet.', - 'suspendSuccess' => 'Abonnementet vart stoppa! Me sende ein epost til {subscriber}.', - 'suspendError' => 'Greidde ikkje stoppa abonnementet.', - 'resumeSuccess' => 'Abonnementet er starta att! Me sende ein epost til {subscriber}.', - 'resumeError' => 'Greidde ikkje starta abonnementet att.', - 'linkSaveSuccess' => 'Abonnementslenka er lagra. Ho vil visa på nettstaden som ei handlingsvarsling.', - 'linkRemoveSuccess' => 'Abonnementslenka vart fjerna.', - ], - 'emails' => [ - 'greeting' => 'Hei', - 'token' => 'Nykelen din: {0}', - 'unique_feed_link' => 'Den unike lenka til straumen: {0}', - 'how_to_use' => 'Korleis skal eg bruka dette?', - 'two_ways' => 'Du kan låsa opp betalte episodar på to måtar:', - 'import_into_app' => 'Kopier den unike adressa til podkaststraumen til favoritt-podkastappen din (importer adressa som ein privat straum slik at du ikkje avslører innloggingsopplysingane dine).', - 'go_to_website' => 'Gå til heimesida til {podcastWebsite} og lås opp podkasten med nykelen.', - 'welcome_subject' => 'Velkomen til {podcastTitle}', - 'welcome' => 'Du abonnerer på {podcastTitle}. Takk, og velkomen ombord!', - 'welcome_token_title' => 'Her er nykelen for å få tilgang til dei betalte episodane til podkasten:', - 'welcome_expires' => 'Abonnementet ditt hadde stoppdato {0}.', - 'welcome_never_expires' => 'Abonnementet ditt hadde ingen stoppdato.', - 'reset_subject' => 'Nykelen din er nullstilt!', - 'reset_token' => 'Tilgangen din til {podcastTitle} er nullstilt!', - 'reset_token_title' => 'Me har laga nye tilgangsopplysingar for deg for å få tilgang til dei betalte episodane til podkasten:', - 'edited_subject' => 'Abonnementet ditt er oppdatert!', - 'edited_expires' => 'Abonnementet ditt på {podcastTitle} hadde stoppdato {expiresAt}.', - 'edited_never_expires' => 'Abonnementet ditt på {podcastTitle} hadde ingen stoppdato!', - 'suspended_subject' => 'Abonnementet ditt er stoppa!', - 'suspended' => 'Abonnementet ditt på {podcastTitle} er stoppa! Du har ikkje lenger tilgang til dei betalte episodane til denne podkasten.', - 'suspended_reason' => 'Det er av desse grunnane: {0}', - 'resumed_subject' => 'Abonnementet ditt har starta att!', - 'resumed' => 'Abonnementet ditt på {podcastTitle} har starta att! Du har tilgang til dei betalte episodane til denne podkasten.', - 'deleted_subject' => 'Abonnementet ditt er sletta!', - 'deleted' => 'Abonnementet ditt på {podcastTitle} er sletta! Du har ikkje lenger tilgang til dei betalte episodane til podkasten.', - 'footer' => '{castopod} køyrer på {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/oc/Subscription.php b/modules/PremiumPodcasts/Language/oc/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/oc/Subscription.php +++ b/modules/PremiumPodcasts/Language/oc/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/pl/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/pl/PremiumPodcasts.php index d9a3d493..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/pl/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/pl/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Podcast zawiera odcinki premium', - 'episode_is_premium' => 'Ten odcinek premium jest dostępny tylko dla subskrybentów', - 'unlock_episode' => 'Ten odcinek jest tylko dla subskrybentów premium. Kliknij, aby go odblokować!', - 'banner_unlock' => 'Ten podcast zawiera odcinki premium, dostępne tylko dla subskrybentów premium.', - 'banner_lock' => 'Podcast został odblokowany, ciesz się odcinkami premium!', - 'subscribe' => 'Subskrybuj', - 'lock' => 'Zablokuj', - 'unlock' => 'Odblokuj', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', + 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Zawartość premium', - 'subtitle' => 'Ten podcast zawiera zablokowane odcinki premium! Czy masz klucz do ich odblokowania?', - 'token' => 'Wprowadź swój klucz', - 'token_hint' => 'Jeśli subskrybujesz {podcastTitle}, możesz skopiować klucz wysłany do Ciebie mailem i wkleić go tutaj.', - 'submit' => 'Odblokuj wszystkie odcinki!', - 'call_to_action' => 'Odblokuj wszystkie odcinki {podcastTitle}:', - 'subscribe_cta' => 'Subskrybuj teraz!', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', + 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => 'Podcast został pomyślnie odblokowany! Ciesz się odcinkami premium!', - 'unlockBadAttempt' => 'Twój klucz nie działa…', - 'lockSuccess' => 'Podcast został pomyślnie zablokowany!', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/pl/Subscription.php b/modules/PremiumPodcasts/Language/pl/Subscription.php index 8a81eca8..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/pl/Subscription.php +++ b/modules/PremiumPodcasts/Language/pl/Subscription.php @@ -9,92 +9,92 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Subskrypcje podcastu', - 'add' => 'Nowa subskrypcja', - 'view' => 'Wyświetl subskrypcję', - 'edit' => 'Edytuj subskrypcję', - 'regenerate_token' => 'Wygeneruj nowy token', - 'suspend' => 'Wstrzymaj subskrypcję', - 'resume' => 'Wznów subskrypcję', - 'delete' => 'Usuń subskrypcję', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Aktywne', - 'suspended' => 'Zawieszony', - 'expired' => 'Wygasły', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Numer', + 'number' => 'Number', 'email' => 'Email', - 'expiration_date' => 'Data ważności', - 'unlimited' => 'Nielimitowany', - 'downloads' => 'Pobrane', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', + 'downloads' => 'Downloads', 'status' => 'Status', ], 'form' => [ 'email' => 'Email', - 'expiration_date' => 'Data ważności', - 'expiration_date_hint' => 'Data i godzina wygaśnięcia subskrypcji. Pozostaw puste dla nieograniczonej subskrypcji.', - 'submit_create' => 'Utwórz subskrypcję', - 'submit_edit' => 'Edytuj subskrypcję', + 'expiration_date' => 'Expiration date', + 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', + 'submit_add' => 'Add subscription', + 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ - 'link' => 'Link do strony subskrypcji', - 'link_hint' => 'Spowoduje to dodanie przycisku zapraszającego słuchaczy do subskrypcji podcastu.', - 'submit' => 'Zapisz link', + 'link' => 'Subscription page link', + 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', + 'submit' => 'Save link', ], 'suspend_form' => [ - 'disclaimer' => 'Zawieszenie subskrypcji ograniczy subskrybentowi dostęp do treści premium. Wciąż będziesz mógł później cofnąć zawieszenie.', - 'reason' => 'Powód', - 'reason_placeholder' => 'Dlaczego zawieszasz subskrypcję?', - "submit" => 'Wstrzymaj subskrypcję', + 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', + 'reason' => 'Reason', + 'reason_placeholder' => 'Why are you suspending the subscription?', + "submit" => 'Suspend subscription', ], 'delete_form' => [ - 'disclaimer' => 'Usunięcie subskrypcji {subscriber} spowoduje usunięcie wszystkich danych analitycznych z nią związanych.', - 'understand' => 'Rozumiem, usuń subskrypcję na stałe', - 'submit' => 'Usuń subskrypcję', + 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', + 'understand' => 'I understand, remove the subscription permanently', + 'submit' => 'Remove subscription', ], 'messages' => [ - 'addSuccess' => 'Dodano nową subskrypcję! Wiadomość powitalna została wysłana na adres {subscriber}.', - 'addError' => 'Subskrypcja nie mogła zostać dodana.', - 'editSuccess' => 'Data wygaśnięcia subskrypcji została zaktualizowana! Wiadomość e-mail została wysłana do {subscriber}.', - 'editError' => 'Subskrypcja nie mogła być edytowana.', - 'regenerateTokenSuccess' => 'Token został zresetowany! Wiadomość e-mail została wysłana do {subscriber} z nowym tokenem.', - 'regenerateTokenError' => 'Token nie mógł zostać zresetowany.', - 'deleteSuccess' => 'Subskrypcja została usunięta! Wiadomość e-mail została wysłana do {subscriber}.', - 'deleteError' => 'Subskrypcja nie mogła zostać usunięta.', - 'suspendSuccess' => 'Subskrypcja została zawieszona! Wiadomość e-mail została wysłana do {subscriber}.', - 'suspendError' => 'Subskrypcja nie mogła zostać zawieszona.', - 'resumeSuccess' => 'Subskrypcja została wznowiona! Wiadomość e-mail została wysłana do {subscriber}.', - 'resumeError' => 'Subskrypcja nie mogła zostać wznowiona.', - 'linkSaveSuccess' => 'Link do subskrypcji został pomyślnie zapisany! Pojawi się na stronie internetowej jako Call To Action!', - 'linkRemoveSuccess' => 'Link do subskrypcji został pomyślnie usunięty!', + 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', + 'addError' => 'Subscription could not be added.', + 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', + 'editError' => 'Subscription could not be edited.', + 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', + 'regenerateTokenError' => 'Token could not be regenerated.', + 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', + 'deleteError' => 'Subscription could not be removed.', + 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', + 'suspendError' => 'Subscription could not be suspended.', + 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', + 'resumeError' => 'Subscription could not be resumed.', + 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', + 'linkRemoveSuccess' => 'Subscription link was removed successfully!', ], 'emails' => [ - 'greeting' => 'Cześć,', - 'token' => 'Twój token: {0}', - 'unique_feed_link' => 'Twój unikalny link do kanału: {0}', - 'how_to_use' => 'Jak używać?', - 'two_ways' => 'Masz dwa sposoby odblokowania odcinków premium:', - 'import_into_app' => 'Wklej swój unikalny adres URL kanału do swojej ulubionej aplikacji podcastowej (zaimportuj go jako prywatny kanał, aby zapobiec ujawnianiu Twoich tokenów).', - 'go_to_website' => 'Przejdź do strony {podcastWebsite} i odblokuj podcast za pomocą swojego tokenu.', - 'welcome_subject' => 'Witaj w {podcastTitle}', - 'welcome' => 'Zasubskrybowano {podcastTitle}, dziękuję i witam na pokładzie!', - 'welcome_token_title' => 'Oto twoje dane, aby odblokować odcinki premium podcastu:', - 'welcome_expires' => 'Twoja subskrypcja wygaśnie w dniu {0}.', - 'welcome_never_expires' => 'Twoja subskrypcja nigdy nie wygasa.', - 'reset_subject' => 'Twój token został zresetowany!', - 'reset_token' => 'Twój dostęp do {podcastTitle} został zresetowany!', - 'reset_token_title' => 'Wygenerowano nowe dane dostępowe do odblokowania odcinków premium podcastu:', - 'edited_subject' => 'Subskrypcja została zaktualizowana!', - 'edited_expires' => 'Twoja subskrypcja dla {podcastTitle} wygaśnie w dniu {expiresAt}.', - 'edited_never_expires' => 'Twoja subskrypcja dla {podcastTitle} nigdy nie wygaśnie!', - 'suspended_subject' => 'Twoja subskrypcja została zawieszona!', - 'suspended' => 'Twoja subskrypcja dla {podcastTitle} została zawieszona! Nie masz już dostępu do odcinków premium podcastu.', - 'suspended_reason' => 'Z następującego powodu: {0}', - 'resumed_subject' => 'Twoja subskrypcja została wznowiona!', - 'resumed' => 'Twoja subskrypcja dla {podcastTitle} została wznowiona! Masz ponownie dostęp do odcinków premium podcastu.', - 'deleted_subject' => 'Twoja subskrypcja została usunięta!', - 'deleted' => 'Twoja subskrypcja dla {podcastTitle} została usunięta! Nie masz już dostępu do odcinków premium podcastu.', - 'footer' => '{castopod} hostowane na {host}', + 'greeting' => 'Hey,', + 'token' => 'Your token: {0}', + 'unique_feed_link' => 'Your unique feed link: {0}', + 'how_to_use' => 'How to use?', + 'two_ways' => 'You have two ways of unlocking the premium episodes:', + 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', + 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', + 'welcome_subject' => 'Welcome to {podcastTitle}', + 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', + 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', + 'welcome_expires' => 'Your subscription was set to expire on {0}.', + 'welcome_never_expires' => 'Your subscription was set to never expire.', + 'reset_subject' => 'Your token was reset!', + 'reset_token' => 'Your access to {podcastTitle} has been reset!', + 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', + 'edited_subject' => 'Your subscription has been updated!', + 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', + 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', + 'suspended_subject' => 'Your subscription has been suspended!', + 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', + 'suspended_reason' => 'That is for the following reason: {0}', + 'resumed_subject' => 'Your subscription has been resumed!', + 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', + 'deleted_subject' => 'Your subscription has been removed!', + 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', + 'footer' => '{castopod} hosted on {host}', ], ]; diff --git a/modules/PremiumPodcasts/Language/eu/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/pt-BR/PremiumPodcasts.php similarity index 100% rename from modules/PremiumPodcasts/Language/eu/PremiumPodcasts.php rename to modules/PremiumPodcasts/Language/pt-BR/PremiumPodcasts.php diff --git a/modules/PremiumPodcasts/Language/eu/Subscription.php b/modules/PremiumPodcasts/Language/pt-BR/Subscription.php similarity index 99% rename from modules/PremiumPodcasts/Language/eu/Subscription.php rename to modules/PremiumPodcasts/Language/pt-BR/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/eu/Subscription.php +++ b/modules/PremiumPodcasts/Language/pt-BR/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/pt-br/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/pt-br/PremiumPodcasts.php deleted file mode 100644 index b85012d9..00000000 --- a/modules/PremiumPodcasts/Language/pt-br/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'O Podcast contém episódios premium', - 'episode_is_premium' => 'Episódio é premium, somente disponível para assinantes premium', - 'unlock_episode' => 'Este episódio é apenas para assinantes premium. Clique para desbloqueá-lo!', - 'banner_unlock' => 'Este podcast contém episódios premium, somente disponível para assinantes premium.', - 'banner_lock' => 'O Podcast desbloqueado, aproveite os episódios premium!', - 'subscribe' => 'Inscrever-se', - 'lock' => 'Bloquear', - 'unlock' => 'Desbloquear', - 'unlock_form' => [ - 'title' => 'Conteúdo premium', - 'subtitle' => 'Este podcast contém episódios premium bloqueados! Você tem a chave para desbloqueá-los?', - 'token' => 'Digite sua chave', - 'token_hint' => 'Se você se inscreveu no {podcastTitle}, você pode copiar a chave que foi enviada por email e colá-la aqui.', - 'submit' => 'Desbloquear todos os episódios!', - 'call_to_action' => 'Desbloquear todos os episódios de {podcastTitle}:', - 'subscribe_cta' => 'Inscreva-se agora!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podcast foi desbloqueado com sucesso! Aproveite os episódios premium!', - 'unlockBadAttempt' => 'Sua chave parece não estar funcionando…', - 'lockSuccess' => 'Podcast foi trancado com sucesso!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/pt-br/Subscription.php b/modules/PremiumPodcasts/Language/pt-br/Subscription.php deleted file mode 100644 index 5e125494..00000000 --- a/modules/PremiumPodcasts/Language/pt-br/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Assinaturas de Podcast', - 'add' => 'Nova assinatura', - 'view' => 'Visualizar assinatura', - 'edit' => 'Editar assinatura', - 'regenerate_token' => 'Regerar token', - 'suspend' => 'Suspender assinatura', - 'resume' => 'Retomar assinatura', - 'delete' => 'Excluir assinatura', - 'status' => [ - 'active' => 'Ativo', - 'suspended' => 'Suspenso', - 'expired' => 'Expirado', - ], - 'list' => [ - 'number' => 'Número', - 'email' => 'E-mail', - 'expiration_date' => 'Data da expiração', - 'unlimited' => 'Sem limite', - 'downloads' => 'Downloads', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'E-mail', - 'expiration_date' => 'Data da expiração', - 'expiration_date_hint' => 'A data e hora em que a assinatura expirará. Deixe em branco para uma assinatura ilimitada.', - 'submit_create' => 'Criar assinatura', - 'submit_edit' => 'Editar assinatura', - ], - 'form_link_add' => [ - 'link' => 'Link da página de assinatura', - 'link_hint' => 'Isto irá adicionar uma chamada para a ação no site que convida ouvintes a se inscreverem no podcast.', - 'submit' => 'Salvar o link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/pt/Subscription.php b/modules/PremiumPodcasts/Language/pt/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/pt/Subscription.php +++ b/modules/PremiumPodcasts/Language/pt/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/ro/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/ro/PremiumPodcasts.php deleted file mode 100644 index 18c0dd4e..00000000 --- a/modules/PremiumPodcasts/Language/ro/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podcast contains premium episodes', - 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', - 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', - 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', - 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', - 'subscribe' => 'Subscribe', - 'lock' => 'Lock', - 'unlock' => 'Unlock', - 'unlock_form' => [ - 'title' => 'Premium content', - 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', - 'token' => 'Enter your key', - 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', - 'submit' => 'Unlock all episodes!', - 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', - 'subscribe_cta' => 'Subscribe now!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', - 'unlockBadAttempt' => 'Your key does not seem to be working…', - 'lockSuccess' => 'Podcast was successfully locked!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/ro/Subscription.php b/modules/PremiumPodcasts/Language/ro/Subscription.php deleted file mode 100644 index 86a77ad8..00000000 --- a/modules/PremiumPodcasts/Language/ro/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Abonamente Podcast', - 'add' => 'Abonament nou', - 'view' => 'Vizualizare abonament', - 'edit' => 'Editare abonament', - 'regenerate_token' => 'Regenerează token de autentificare', - 'suspend' => 'Suspendare abonament', - 'resume' => 'Reluare abonament', - 'delete' => 'Şterge abonamentul', - 'status' => [ - 'active' => 'Activ', - 'suspended' => 'Suspendat', - 'expired' => 'Expirat', - ], - 'list' => [ - 'number' => 'Număr', - 'email' => 'E-mail', - 'expiration_date' => 'Data expirării', - 'unlimited' => 'Nelimitat', - 'downloads' => 'Descărcări', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'E-mail', - 'expiration_date' => 'Data expirării', - 'expiration_date_hint' => 'Data și ora la care expiră abonamentul. Lăsați gol pentru un abonament nelimitat.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Editare abonament', - ], - 'form_link_add' => [ - 'link' => 'Link-ul paginii de abonare', - 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', - 'submit' => 'Save link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/ru/Subscription.php b/modules/PremiumPodcasts/Language/ru/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/ru/Subscription.php +++ b/modules/PremiumPodcasts/Language/ru/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/sk/Subscription.php b/modules/PremiumPodcasts/Language/sk/Subscription.php index e83f0cb2..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/sk/Subscription.php +++ b/modules/PremiumPodcasts/Language/sk/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => 'Email', 'expiration_date' => 'Expiration date', 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', + 'submit_add' => 'Add subscription', 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ diff --git a/modules/PremiumPodcasts/Language/sr-latn/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/sr-latn/PremiumPodcasts.php deleted file mode 100644 index 6da5e74e..00000000 --- a/modules/PremiumPodcasts/Language/sr-latn/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podcast sadrži premijerne epizode', - 'episode_is_premium' => 'Epizoda je premijum, dostupna je samo premijum pretplatnicima', - 'unlock_episode' => 'Ova epizoda je samo za premijum pretplatnike. Klikni da je otključaš!', - 'banner_unlock' => 'Ovaj podkast sadrži premijum epizode, dostupne samo premijum pretplatnicima.', - 'banner_lock' => 'Podkast je otključan, uživajte u premijum epizodama!', - 'subscribe' => 'Pretplatite se', - 'lock' => 'Zaključaj', - 'unlock' => 'Otključaj', - 'unlock_form' => [ - 'title' => 'Premijum sadržaj', - 'subtitle' => 'Ovaj podkat sadrži zaključane premijum epizode! Da li imate ključ?', - 'token' => 'Unesite ključ', - 'token_hint' => 'Ako ste pretplaćeni na {podcastTitle}, možete kopirati ključ koji vam je poslat na E poštu i zalepiti ga ovde.', - 'submit' => 'Otključaj sve epizode!', - 'call_to_action' => 'Otključaj sve epizode {podcastTitle}:', - 'subscribe_cta' => 'Pretplati se sada!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podkast je uspešno otključan, uživajte u premijum epizodama!', - 'unlockBadAttempt' => 'Izgleda da vaš ključ ne radi…', - 'lockSuccess' => 'Podkast je uspešno zaključan!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/sr-latn/Subscription.php b/modules/PremiumPodcasts/Language/sr-latn/Subscription.php deleted file mode 100644 index 0fbeb3aa..00000000 --- a/modules/PremiumPodcasts/Language/sr-latn/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Podkast pretplate', - 'add' => 'Nova pretplata', - 'view' => 'Pogledaj pretplatu', - 'edit' => 'Uredi pretplatu', - 'regenerate_token' => 'Regeneriši token', - 'suspend' => 'Ukini pretplatu', - 'resume' => 'Nastavi pretplatu', - 'delete' => 'Obriši pretplatu', - 'status' => [ - 'active' => 'Aktivno', - 'suspended' => 'Ukinuto', - 'expired' => 'Isteklo', - ], - 'list' => [ - 'number' => 'Broj', - 'email' => 'E-pošta', - 'expiration_date' => 'Datum Isteka', - 'unlimited' => 'Neograničeno', - 'downloads' => 'Preuzimanja', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'E-pošta', - 'expiration_date' => 'Datum Isteka', - 'expiration_date_hint' => 'Datum i vreme kada pretplata ističe. Ostavite prazno za neograničenu pretplatu.', - 'submit_create' => 'Napravi pretplatu', - 'submit_edit' => 'Uredi pretplatu', - ], - 'form_link_add' => [ - 'link' => 'Veza strane za pretplate', - 'link_hint' => 'Ovo će dodati poziv na akciju na veb lokaciji koji poziva slušaoce da se pretplate na podkast.', - 'submit' => 'Sačuvaj vezu', - ], - 'suspend_form' => [ - 'disclaimer' => 'Obustavljanje pretplate će ograničiti pretplatniku pristup premijum sadržaju. I dalje ćete moći da uklonite obustavu nakon toga.', - 'reason' => 'Razlog', - 'reason_placeholder' => 'Zašto ukidate pretplatu?', - "submit" => 'Ukini pretplatu', - ], - 'delete_form' => [ - 'disclaimer' => 'Brisanje {subscriber} pretplate će ukloniti svu analitiku vezanu za tog pretplatnika.', - 'understand' => 'Razumem, želim da trajno ukinem pretplatu', - 'submit' => 'Ukloni pretplatu', - ], - 'messages' => [ - 'addSuccess' => 'Nova pretplata dodata! Poruka dobrodođlice je poslata {subscriber} putem E-pošte.', - 'addError' => 'Nije moguće dodati pretplatu.', - 'editSuccess' => 'Datum isteka pretplate je ažuriran! Poruka je poslata {subscriber} putem E-pošte.', - 'editError' => 'Nije moguće urediti pretplatu.', - 'regenerateTokenSuccess' => 'Token regenerisan! Novi token je poslat {subscriber} putem E-pošte.', - 'regenerateTokenError' => 'Token nije moguće regenerisati.', - 'deleteSuccess' => 'Pretplata je uklonjena! Poruka je poslata {subscriber} putem E-pošte.', - 'deleteError' => 'Nije moguće ukloniti pretplatu.', - 'suspendSuccess' => 'Pretplata je ukinuta! Poruka je poslata {subscriber} putem E-pošte.', - 'suspendError' => 'Nije moguće prekinuti pretplatu.', - 'resumeSuccess' => 'Pretplana je obnovljena! Poruka je poslata {subscriber} putem E-pošte.', - 'resumeError' => 'Nije moguće obnoviti pretplatu.', - 'linkSaveSuccess' => 'Veza za pretplatu je uspešno sačuvana! Pojaviće se na Veb strani kao poziv na akciju!', - 'linkRemoveSuccess' => 'Veza za pretplatu je uspešno uklonjena!', - ], - 'emails' => [ - 'greeting' => 'Hej,', - 'token' => 'Vaš token: {0}', - 'unique_feed_link' => 'Vaša jedinstvena veza sa fidom: {0}', - 'how_to_use' => 'Kako se koristi?', - 'two_ways' => 'Imate dva načina kako možete otključati premijum epizode:', - 'import_into_app' => 'Kopirajte svoj jedinstveni url fid u svoju omiljenu aplikaciju za podkaste (uvezite ga kao privatni fid da biste sprečili otkrivanje vaših akreditiva).', - 'go_to_website' => 'Idite na {podcastWebsite} veb stranicu i otključajte podkast koristeći vaš token.', - 'welcome_subject' => 'Dobrodošli na {podcastTitle}', - 'welcome' => 'Pretplatili ste se na {podcastTitle}, hvala vam i dobrodošli!', - 'welcome_token_title' => 'Evo vaših akreditiva kojima otključavate premijum epizode ovog podkasta:', - 'welcome_expires' => 'Vaša pretplata ističe {0}.', - 'welcome_never_expires' => 'Vaša pretplata je podešena tako da ne može da istekne.', - 'reset_subject' => 'Vaš token je resetovan!', - 'reset_token' => 'Vaš pristup {podcastTitle} je resetovan!', - 'reset_token_title' => 'Nove akreditive su kreirane kako bi ste pristupili premijum epizodama podkasta:', - 'edited_subject' => 'Vaša pretplata je ažurirana!', - 'edited_expires' => 'Vaša pretplata na {podcastTitle} ističe {expiresAt}.', - 'edited_never_expires' => 'Vaša pretplata na {podcastTitle} je podešena tako da nikad ne istekne!', - 'suspended_subject' => 'Vaša pretplata je ukinuta!', - 'suspended' => 'Vaša pretplata na {podcastTitle} je ukinuta! Više ne možete pristupiti premijum epizodama ovog podkasta.', - 'suspended_reason' => 'Razlog: {0}', - 'resumed_subject' => 'Vaša pretplata je ponovo pokrenuta!', - 'resumed' => 'Vaša pretplata na {podcastTitle} je ponovo pokrenuta! Sada ponovo možete pristupiti premijum epizodama ovog podkasta.', - 'deleted_subject' => 'Vaša pretplata je uklonjena!', - 'deleted' => 'Vaša pretplata na {podcastTitle} je uklonjena! Vipe ne možete pristupiti premijum epizodama ovog podkasta.', - 'footer' => '{castopod} hostovan na {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/sv/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/sv/PremiumPodcasts.php index 21dcd34b..18c0dd4e 100644 --- a/modules/PremiumPodcasts/Language/sv/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/Language/sv/PremiumPodcasts.php @@ -9,26 +9,26 @@ declare(strict_types=1); */ return [ - 'podcast_is_premium' => 'Podcast innehåller premium avsnitt', - 'episode_is_premium' => 'Avsnitt är premium, endast tillgängligt för premium-prenumeranter', - 'unlock_episode' => 'Denna episod är endast för premiumprenumeranter. Klicka för att låsa upp den!', - 'banner_unlock' => 'Denna podcast innehåller premiumavsnitt som endast är tillgängliga för premiumprenumeranter.', - 'banner_lock' => 'Podcast är olåst, njut av premiumavsnitt!', - 'subscribe' => 'Prenumerera', - 'lock' => 'Lås', - 'unlock' => 'Lås upp', + 'podcast_is_premium' => 'Podcast contains premium episodes', + 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', + 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', + 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', + 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', + 'subscribe' => 'Subscribe', + 'lock' => 'Lock', + 'unlock' => 'Unlock', 'unlock_form' => [ - 'title' => 'Premium-innehåll', - 'subtitle' => 'Denna podcast innehåller låsta premium-avsnitt! Har du nyckeln för att låsa upp dem?', - 'token' => 'Ange din nyckel', - 'token_hint' => 'Om du prenumererar på {podcastTitle} kan du kopiera nyckeln som skickades till dig via e-post och klistra in den här.', - 'submit' => 'Lås upp alla avsnitt!', - 'call_to_action' => 'Lås upp alla avsnitt av {podcastTitle}:', - 'subscribe_cta' => 'Prenumerera nu!', + 'title' => 'Premium content', + 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', + 'token' => 'Enter your key', + 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', + 'submit' => 'Unlock all episodes!', + 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', + 'subscribe_cta' => 'Subscribe now!', ], 'messages' => [ - 'unlockSuccess' => 'Podcast har låsts upp! Njut av premiumavsnitt!', - 'unlockBadAttempt' => 'Din nyckel verkar inte fungera…', - 'lockSuccess' => 'Podcast har låsts!', + 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', + 'unlockBadAttempt' => 'Your key does not seem to be working…', + 'lockSuccess' => 'Podcast was successfully locked!', ], ]; diff --git a/modules/PremiumPodcasts/Language/sv/Subscription.php b/modules/PremiumPodcasts/Language/sv/Subscription.php index 06caf6cc..f8af256f 100644 --- a/modules/PremiumPodcasts/Language/sv/Subscription.php +++ b/modules/PremiumPodcasts/Language/sv/Subscription.php @@ -9,92 +9,92 @@ declare(strict_types=1); */ return [ - 'podcast_subscriptions' => 'Podcast prenumerationer', - 'add' => 'Ny prenumeration', - 'view' => 'Visa prenumeration', - 'edit' => 'Ändra prenumeration', - 'regenerate_token' => 'Generera om token', - 'suspend' => 'Avaktivera prenumeration', - 'resume' => 'Återuppta prenumeration', - 'delete' => 'Radera prenumeration', + 'podcast_subscriptions' => 'Podcast subscriptions', + 'add' => 'New subscription', + 'view' => 'View subscription', + 'edit' => 'Edit subscription', + 'regenerate_token' => 'Regenerate token', + 'suspend' => 'Suspend subscription', + 'resume' => 'Resume subscription', + 'delete' => 'Delete subscription', 'status' => [ - 'active' => 'Aktiv', - 'suspended' => 'Suspenderad', - 'expired' => 'Utgått', + 'active' => 'Active', + 'suspended' => 'Suspended', + 'expired' => 'Expired', ], 'list' => [ - 'number' => 'Nummer', - 'email' => 'Epost', - 'expiration_date' => 'Utgångsdatum', - 'unlimited' => 'Obegränsat', - 'downloads' => 'Nerladdningar', + 'number' => 'Number', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'unlimited' => 'Unlimited', + 'downloads' => 'Downloads', 'status' => 'Status', ], 'form' => [ - 'email' => 'Epost', - 'expiration_date' => 'Utgångsdatum', - 'expiration_date_hint' => 'Datum och tid då prenumerationen går ut. Lämna tomt för ett obegränsat abonnemang.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Ändra prenumeration', + 'email' => 'Email', + 'expiration_date' => 'Expiration date', + 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', + 'submit_add' => 'Add subscription', + 'submit_edit' => 'Edit subscription', ], 'form_link_add' => [ - 'link' => 'Länk för prenumerationssida', - 'link_hint' => 'Detta kommer att lägga till en uppmaning till åtgärder på webbplatsen som bjuder in lyssnare att prenumerera på podcasten.', - 'submit' => 'Spara länk', + 'link' => 'Subscription page link', + 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', + 'submit' => 'Save link', ], 'suspend_form' => [ - 'disclaimer' => 'Avstängning av abonnemanget kommer att begränsa abonnenten från att ha tillgång till premiuminnehållet. Du kommer fortfarande att kunna lyfta suspensionen efteråt.', - 'reason' => 'Orsak', - 'reason_placeholder' => 'Varför stänger du av prenumerationen?', - "submit" => 'Avaktivera prenumeration', + 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', + 'reason' => 'Reason', + 'reason_placeholder' => 'Why are you suspending the subscription?', + "submit" => 'Suspend subscription', ], 'delete_form' => [ - 'disclaimer' => 'Borttagning av {subscriber}s prenumeration kommer att ta bort all analysdata som är kopplad till den.', - 'understand' => 'Jag förstår, ta bort prenumerationen permanent', - 'submit' => 'Ta bort prenumeration', + 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', + 'understand' => 'I understand, remove the subscription permanently', + 'submit' => 'Remove subscription', ], 'messages' => [ - 'addSuccess' => 'Ny prenumeration tillagd! Ett välkomstmeddelande skickades till {subscriber}.', - 'addError' => 'Prenumerationen kunde inte läggas till.', - 'editSuccess' => 'Prenumeration utgångsdatum uppdaterades! Ett e-postmeddelande skickades till {subscriber}.', - 'editError' => 'Prenumerationen kunde inte redigeras.', - 'regenerateTokenSuccess' => 'Token regenererad! Ett e-postmeddelande skickades till {subscriber} med den nya token.', - 'regenerateTokenError' => 'Token kunde inte regenereras.', - 'deleteSuccess' => 'Prenumerationen har tagits bort! Ett e-postmeddelande har skickats till {subscriber}.', - 'deleteError' => 'Prenumerationen kunde inte tas bort.', - 'suspendSuccess' => 'Prenumerationen suspenderades! Ett e-postmeddelande skickades till {subscriber}.', - 'suspendError' => 'Prenumerationen kunde inte stängas av.', - 'resumeSuccess' => 'Prenumerationen återupptades! Ett e-postmeddelande skickades till {subscriber}.', - 'resumeError' => 'Prenumerationen kunde inte återupptas.', - 'linkSaveSuccess' => 'Prenumerationslänken har sparats! Den kommer att visas på webbplatsen som en Call To Action!', - 'linkRemoveSuccess' => 'Prenumerationslänken har tagits bort!', + 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', + 'addError' => 'Subscription could not be added.', + 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', + 'editError' => 'Subscription could not be edited.', + 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', + 'regenerateTokenError' => 'Token could not be regenerated.', + 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', + 'deleteError' => 'Subscription could not be removed.', + 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', + 'suspendError' => 'Subscription could not be suspended.', + 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', + 'resumeError' => 'Subscription could not be resumed.', + 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', + 'linkRemoveSuccess' => 'Subscription link was removed successfully!', ], 'emails' => [ - 'greeting' => 'Hej,', - 'token' => 'Din token: {0}', - 'unique_feed_link' => 'Din unika flödeslänk: {0}', - 'how_to_use' => 'Hur gör man?', - 'two_ways' => 'Du har två sätt att låsa upp premiumavsnitt:', - 'import_into_app' => 'Kopiera din unika feed url inuti din favorit podcast-app (importera den som ett privat flöde för att förhindra att du exponerar dina referenser).', - 'go_to_website' => 'Gå till {podcastWebsite}s webbplats och lås upp podcasten med din token.', - 'welcome_subject' => 'Välkommen till {podcastTitle}', - 'welcome' => 'Du har prenumererat på {podcastTitle}, tack och välkommen ombord!', - 'welcome_token_title' => 'Här är dina referenser för att låsa upp podcastens premiumavsnitt:', - 'welcome_expires' => 'Ditt abonnemang var inställt på att löpa ut {0}.', - 'welcome_never_expires' => 'Din prenumeration var inställd på att aldrig upphöra.', - 'reset_subject' => 'Din token återställdes!', - 'reset_token' => 'Din åtkomst till {podcastTitle} har återställts!', - 'reset_token_title' => 'Nya autentiseringsuppgifter har skapats för att du ska kunna låsa upp podcastens premiumavsnitt:', - 'edited_subject' => 'Din prenumeration har uppdaterats!', - 'edited_expires' => 'Ditt abonnemang för {podcastTitle} sattes att löpa ut den {expiresAt}.', - 'edited_never_expires' => 'Din prenumeration på {podcastTitle} har ställts in på att aldrig upphör!', - 'suspended_subject' => 'Din prenumeration har stängts av!', - 'suspended' => 'Din prenumeration på {podcastTitle} har stängts av! Du kan inte längre komma åt podcastens premiumavsnitt.', - 'suspended_reason' => 'Det är av följande skäl: {0}', - 'resumed_subject' => 'Din prenumeration har återupptagits!', - 'resumed' => 'Din prenumeration på {podcastTitle} har återupptagits! Du kan komma åt podcastens premiumavsnitt igen.', - 'deleted_subject' => 'Din prenumeration har tagits bort!', - 'deleted' => 'Din prenumeration på {podcastTitle} har tagits bort! Du har inte längre tillgång till podcastens premiumavsnitt.', - 'footer' => '{castopod} hostas på {host}', + 'greeting' => 'Hey,', + 'token' => 'Your token: {0}', + 'unique_feed_link' => 'Your unique feed link: {0}', + 'how_to_use' => 'How to use?', + 'two_ways' => 'You have two ways of unlocking the premium episodes:', + 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', + 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', + 'welcome_subject' => 'Welcome to {podcastTitle}', + 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', + 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', + 'welcome_expires' => 'Your subscription was set to expire on {0}.', + 'welcome_never_expires' => 'Your subscription was set to never expire.', + 'reset_subject' => 'Your token was reset!', + 'reset_token' => 'Your access to {podcastTitle} has been reset!', + 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', + 'edited_subject' => 'Your subscription has been updated!', + 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', + 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', + 'suspended_subject' => 'Your subscription has been suspended!', + 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', + 'suspended_reason' => 'That is for the following reason: {0}', + 'resumed_subject' => 'Your subscription has been resumed!', + 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', + 'deleted_subject' => 'Your subscription has been removed!', + 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', + 'footer' => '{castopod} hosted on {host}', ], ]; diff --git a/modules/PremiumPodcasts/Language/uk/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/uk/PremiumPodcasts.php deleted file mode 100644 index bd87ddae..00000000 --- a/modules/PremiumPodcasts/Language/uk/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Подкаст містить преміум-епізоди', - 'episode_is_premium' => 'Цей подкаст містить преміум епізоди, тільки для преміум підписників', - 'unlock_episode' => 'Цей епізод призначений тільки для преміум підписників. Натисніть, щоб розблокувати його!', - 'banner_unlock' => 'Цей подкаст містить преміум епізоди, тільки для преміум підписників.', - 'banner_lock' => 'Подкаст був успішно розблокований! Насолоджуйтесь преміум епізодами!', - 'subscribe' => 'Підписатися', - 'lock' => 'Заблокувати', - 'unlock' => 'Розблокувати', - 'unlock_form' => [ - 'title' => 'Преміум контент', - 'subtitle' => 'Цей подкаст містить заблоковані преміум епізоди! Ви маєте ключ для їх розблокування?', - 'token' => 'Введіть ваш ключ', - 'token_hint' => 'Якщо ви підписані на {podcastTitle}, ви можете скопіювати ключ, відправлений вам на електрону пошту та вставити його тут.', - 'submit' => 'Розблокувати всі серії!', - 'call_to_action' => 'Розблокувати всі серії з {podcastTitle}:', - 'subscribe_cta' => 'Підписатися зараз!', - ], - 'messages' => [ - 'unlockSuccess' => 'Подкаст був успішно розблокований! Насолоджуйтесь преміум епізодами!', - 'unlockBadAttempt' => 'Здається, ваш ключ не працює…', - 'lockSuccess' => 'Подкаст успішно заблокований!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/uk/Subscription.php b/modules/PremiumPodcasts/Language/uk/Subscription.php deleted file mode 100644 index e83f0cb2..00000000 --- a/modules/PremiumPodcasts/Language/uk/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Podcast subscriptions', - 'add' => 'New subscription', - 'view' => 'View subscription', - 'edit' => 'Edit subscription', - 'regenerate_token' => 'Regenerate token', - 'suspend' => 'Suspend subscription', - 'resume' => 'Resume subscription', - 'delete' => 'Delete subscription', - 'status' => [ - 'active' => 'Active', - 'suspended' => 'Suspended', - 'expired' => 'Expired', - ], - 'list' => [ - 'number' => 'Number', - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'unlimited' => 'Unlimited', - 'downloads' => 'Downloads', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Edit subscription', - ], - 'form_link_add' => [ - 'link' => 'Subscription page link', - 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', - 'submit' => 'Save link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Language/zh-hans/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/zh-Hans/PremiumPodcasts.php similarity index 100% rename from modules/PremiumPodcasts/Language/zh-hans/PremiumPodcasts.php rename to modules/PremiumPodcasts/Language/zh-Hans/PremiumPodcasts.php diff --git a/modules/PremiumPodcasts/Language/zh-hans/Subscription.php b/modules/PremiumPodcasts/Language/zh-Hans/Subscription.php similarity index 95% rename from modules/PremiumPodcasts/Language/zh-hans/Subscription.php rename to modules/PremiumPodcasts/Language/zh-Hans/Subscription.php index 7b8e3d5b..ceaeb7df 100644 --- a/modules/PremiumPodcasts/Language/zh-hans/Subscription.php +++ b/modules/PremiumPodcasts/Language/zh-Hans/Subscription.php @@ -34,7 +34,7 @@ return [ 'email' => '邮箱', 'expiration_date' => '到期日', 'expiration_date_hint' => '订阅到期的日期和时间。 留空时没有订阅限制。', - 'submit_create' => 'Create subscription', + 'submit_add' => '添加订阅', 'submit_edit' => '编辑订阅', ], 'form_link_add' => [ @@ -72,10 +72,10 @@ return [ 'emails' => [ 'greeting' => '嘿,', 'token' => '你的令牌: {0}', - 'unique_feed_link' => '你唯一的摘要链接:{0}', + 'unique_feed_link' => '你唯一的源链接:{0}', 'how_to_use' => '如何使用?', 'two_ways' => '你有两种解锁高级剧集的方法:', - 'import_into_app' => '在你最喜欢的播客应用程序中复制你唯一的摘要 URL(将其作为私人源导入以防止暴露你的凭据)。', + 'import_into_app' => '在你最喜欢的播客应用程序中复制你唯一的源 URL(将其作为私人源导入以防止暴露你的凭据)。', 'go_to_website' => '访问 {podcastWebsite} 的网站并使用你的令牌解锁播客。', 'welcome_subject' => '欢迎来到 {podcastTitle}', 'welcome' => '你已订阅 {podcastTitle},谢谢,欢迎加入!', diff --git a/modules/PremiumPodcasts/Language/zh-hant/PremiumPodcasts.php b/modules/PremiumPodcasts/Language/zh-hant/PremiumPodcasts.php deleted file mode 100644 index 18c0dd4e..00000000 --- a/modules/PremiumPodcasts/Language/zh-hant/PremiumPodcasts.php +++ /dev/null @@ -1,34 +0,0 @@ - 'Podcast contains premium episodes', - 'episode_is_premium' => 'Episode is premium, only available to premium subscribers', - 'unlock_episode' => 'This episode is for premium subscribers only. Click to unlock it!', - 'banner_unlock' => 'This podcast contains premium episodes, only available to premium subscribers.', - 'banner_lock' => 'Podcast is unlocked, enjoy the premium episodes!', - 'subscribe' => 'Subscribe', - 'lock' => 'Lock', - 'unlock' => 'Unlock', - 'unlock_form' => [ - 'title' => 'Premium content', - 'subtitle' => 'This podcast contains locked premium episodes! Do you have the key to unlock them?', - 'token' => 'Enter your key', - 'token_hint' => 'If you are subscribed to {podcastTitle}, you may copy the key that was sent to you via email and paste it here.', - 'submit' => 'Unlock all episodes!', - 'call_to_action' => 'Unlock all episodes of {podcastTitle}:', - 'subscribe_cta' => 'Subscribe now!', - ], - 'messages' => [ - 'unlockSuccess' => 'Podcast was successfully unlocked! Enjoy the premium episodes!', - 'unlockBadAttempt' => 'Your key does not seem to be working…', - 'lockSuccess' => 'Podcast was successfully locked!', - ], -]; diff --git a/modules/PremiumPodcasts/Language/zh-hant/Subscription.php b/modules/PremiumPodcasts/Language/zh-hant/Subscription.php deleted file mode 100644 index e83f0cb2..00000000 --- a/modules/PremiumPodcasts/Language/zh-hant/Subscription.php +++ /dev/null @@ -1,100 +0,0 @@ - 'Podcast subscriptions', - 'add' => 'New subscription', - 'view' => 'View subscription', - 'edit' => 'Edit subscription', - 'regenerate_token' => 'Regenerate token', - 'suspend' => 'Suspend subscription', - 'resume' => 'Resume subscription', - 'delete' => 'Delete subscription', - 'status' => [ - 'active' => 'Active', - 'suspended' => 'Suspended', - 'expired' => 'Expired', - ], - 'list' => [ - 'number' => 'Number', - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'unlimited' => 'Unlimited', - 'downloads' => 'Downloads', - 'status' => 'Status', - ], - 'form' => [ - 'email' => 'Email', - 'expiration_date' => 'Expiration date', - 'expiration_date_hint' => 'The date and time at which the subscription expires. Leave empty for an unlimited subscription.', - 'submit_create' => 'Create subscription', - 'submit_edit' => 'Edit subscription', - ], - 'form_link_add' => [ - 'link' => 'Subscription page link', - 'link_hint' => 'This will add a call to action in the website inviting listeners to subscribe to the podcast.', - 'submit' => 'Save link', - ], - 'suspend_form' => [ - 'disclaimer' => 'Suspending the subscription will restrict the subscriber from having access to the premium content. You will still be able to lift the suspension afterwards.', - 'reason' => 'Reason', - 'reason_placeholder' => 'Why are you suspending the subscription?', - "submit" => 'Suspend subscription', - ], - 'delete_form' => [ - 'disclaimer' => 'Deleting {subscriber}\'s subscription will remove all analytics data associated with it.', - 'understand' => 'I understand, remove the subscription permanently', - 'submit' => 'Remove subscription', - ], - 'messages' => [ - 'addSuccess' => 'New subscription added! A welcome email was sent to {subscriber}.', - 'addError' => 'Subscription could not be added.', - 'editSuccess' => 'Subscription expiry date was updated! An email was sent to {subscriber}.', - 'editError' => 'Subscription could not be edited.', - 'regenerateTokenSuccess' => 'Token regenerated! An email was sent to {subscriber} with the new token.', - 'regenerateTokenError' => 'Token could not be regenerated.', - 'deleteSuccess' => 'Subscription was removed! An email was sent to {subscriber}.', - 'deleteError' => 'Subscription could not be removed.', - 'suspendSuccess' => 'Subscription was suspended! An email was sent to {subscriber}.', - 'suspendError' => 'Subscription could not be suspended.', - 'resumeSuccess' => 'Subscription was resumed! An email was sent to {subscriber}.', - 'resumeError' => 'Subscription could not be resumed.', - 'linkSaveSuccess' => 'Subscription link was saved successfully! It will appear in the website as a Call To Action!', - 'linkRemoveSuccess' => 'Subscription link was removed successfully!', - ], - 'emails' => [ - 'greeting' => 'Hey,', - 'token' => 'Your token: {0}', - 'unique_feed_link' => 'Your unique feed link: {0}', - 'how_to_use' => 'How to use?', - 'two_ways' => 'You have two ways of unlocking the premium episodes:', - 'import_into_app' => 'Copy your unique feed url inside your favourite podcast app (import it as a private feed to prevent exposing your credentials).', - 'go_to_website' => 'Go to {podcastWebsite}\'s website and unlock the podcast with your token.', - 'welcome_subject' => 'Welcome to {podcastTitle}', - 'welcome' => 'You have subscribed to {podcastTitle}, thank you and welcome aboard!', - 'welcome_token_title' => 'Here are your credentials to unlock the podcast\'s premium episodes:', - 'welcome_expires' => 'Your subscription was set to expire on {0}.', - 'welcome_never_expires' => 'Your subscription was set to never expire.', - 'reset_subject' => 'Your token was reset!', - 'reset_token' => 'Your access to {podcastTitle} has been reset!', - 'reset_token_title' => 'New credentials have been generated for you to unlock the podcast\'s premium episodes:', - 'edited_subject' => 'Your subscription has been updated!', - 'edited_expires' => 'Your subscription for {podcastTitle} was set to expire on {expiresAt}.', - 'edited_never_expires' => 'Your subscription for {podcastTitle} was set to never expire!', - 'suspended_subject' => 'Your subscription has been suspended!', - 'suspended' => 'Your subscription for {podcastTitle} has been suspended! You can no longer access the podcast\'s premium episodes.', - 'suspended_reason' => 'That is for the following reason: {0}', - 'resumed_subject' => 'Your subscription has been resumed!', - 'resumed' => 'Your subscription for {podcastTitle} has been resumed! You may access the podcast\'s premium episodes again.', - 'deleted_subject' => 'Your subscription has been removed!', - 'deleted' => 'Your subscription for {podcastTitle} has been removed! You no longer have access to the podcast\'s premium episodes.', - 'footer' => '{castopod} hosted on {host}', - ], -]; diff --git a/modules/PremiumPodcasts/Models/SubscriptionModel.php b/modules/PremiumPodcasts/Models/SubscriptionModel.php index 32619b19..5f79271a 100644 --- a/modules/PremiumPodcasts/Models/SubscriptionModel.php +++ b/modules/PremiumPodcasts/Models/SubscriptionModel.php @@ -28,7 +28,7 @@ class SubscriptionModel extends Model protected $primaryKey = 'id'; /** - * @var list + * @var string[] */ protected $allowedFields = [ 'id', @@ -42,6 +42,9 @@ class SubscriptionModel extends Model 'updated_by', ]; + /** + * @noRector + */ protected $returnType = Subscription::class; /** @@ -55,17 +58,12 @@ class SubscriptionModel extends Model protected $useTimestamps = true; /** - * @var list - */ - protected $afterInsert = ['clearCache']; - - /** - * @var list + * @var string[] */ protected $afterUpdate = ['clearCache']; /** - * @var list + * @var string[] */ protected $beforeDelete = ['clearCache']; @@ -116,13 +114,11 @@ class SubscriptionModel extends Model return $subscriptionModel ->where([ - 'token' => hash('sha256', $token), + 'token' => hash('sha256', $token), 'status' => 'active', + 'expires_at' => null, ]) - ->groupStart() - ->where('expires_at') ->orWhere('`expires_at` > UTC_TIMESTAMP()', null, false) - ->groupEnd() ->first(); } @@ -133,13 +129,7 @@ class SubscriptionModel extends Model */ protected function clearCache(array $data): array { - /** @var ?Subscription */ - $subscription = new self() - ->find(is_array($data['id']) ? $data['id'][0] : $data['id']); - - if (! $subscription instanceof Subscription) { - return $data; - } + $subscription = (new self())->find(is_array($data['id']) ? $data['id'][0] : $data['id']); cache() ->delete("subscription#{$subscription->id}"); diff --git a/modules/PremiumPodcasts/PremiumPodcasts.php b/modules/PremiumPodcasts/PremiumPodcasts.php index 036b6f05..e1469d97 100644 --- a/modules/PremiumPodcasts/PremiumPodcasts.php +++ b/modules/PremiumPodcasts/PremiumPodcasts.php @@ -63,7 +63,7 @@ class PremiumPodcasts { if (array_key_exists( $podcastHandle, - $this->subscriptions, + $this->subscriptions ) && ($this->subscriptions[$podcastHandle] instanceof Subscription)) { return true; } @@ -86,7 +86,7 @@ class PremiumPodcasts // Store the current subscription object $this->subscriptions[$podcastHandle] = $this->subscriptionModel->getSubscriptionById( - $this->subscriptions[$podcastHandle]->id, + $this->subscriptions[$podcastHandle]->id ); if (! $this->subscriptions[$podcastHandle] instanceof Subscription) { diff --git a/modules/Update/Commands/DatabaseUpdate.php b/modules/Update/Commands/DatabaseUpdate.php deleted file mode 100644 index 380f5305..00000000 --- a/modules/Update/Commands/DatabaseUpdate.php +++ /dev/null @@ -1,35 +0,0 @@ -setNamespace(null) - ->latest(); - } -} diff --git a/modules/WebSub/Config/Routes.php b/modules/WebSub/Config/Routes.php new file mode 100644 index 00000000..b86457ee --- /dev/null +++ b/modules/WebSub/Config/Routes.php @@ -0,0 +1,21 @@ +group('', [ + 'namespace' => 'Modules\WebSub\Controllers', +], static function ($routes): void { + $routes->cli('scheduled-websub-publish', 'WebSubController::publish'); +}); diff --git a/modules/WebSub/Commands/Publish.php b/modules/WebSub/Controllers/WebSubController.php similarity index 64% rename from modules/WebSub/Commands/Publish.php rename to modules/WebSub/Controllers/WebSubController.php index c0f47b22..11a0a2d7 100644 --- a/modules/WebSub/Commands/Publish.php +++ b/modules/WebSub/Controllers/WebSubController.php @@ -2,57 +2,53 @@ declare(strict_types=1); -namespace Modules\WebSub\Commands; +/** + * @copyright 2022 Ad Aures + * @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3 + * @link https://castopod.org/ + */ + +namespace Modules\WebSub\Controllers; use App\Models\EpisodeModel; use App\Models\PodcastModel; -use CodeIgniter\CLI\BaseCommand; -use CodeIgniter\HTTP\CURLRequest; +use CodeIgniter\Controller; +use Config\Services; use Exception; -use Override; -class Publish extends BaseCommand +class WebSubController extends Controller { - protected $group = 'Websub'; - - protected $name = 'websub:publish'; - - protected $description = 'Publishes feed updates to websub hubs.'; - - #[Override] - public function run(array $params): void + public function publish(): void { + /** @noRector RemoveAlwaysTrueIfConditionRector */ if (ENVIRONMENT !== 'production') { return; } - helper('misc'); - // get all podcasts that haven't been published yet // or having a published episode that hasn't been pushed yet $podcastModel = new PodcastModel(); - $podcastModel->builder() - ->select('podcasts.*') + $podcasts = $podcastModel ->distinct() + ->select('podcasts.*') ->join('episodes', 'podcasts.id = episodes.podcast_id', 'left outer') ->where('podcasts.is_published_on_hubs', false) ->where('`' . $podcastModel->db->getPrefix() . 'podcasts`.`published_at` <= UTC_TIMESTAMP()', null, false) ->orGroupStart() ->where('episodes.is_published_on_hubs', false) ->where('`' . $podcastModel->db->getPrefix() . 'episodes`.`published_at` <= UTC_TIMESTAMP()', null, false) - ->groupEnd(); - $podcasts = $podcastModel->findAll(); + ->groupEnd() + ->findAll(); if ($podcasts === []) { return; } - /** @var CURLRequest $request */ - $request = service('curlrequest'); + $request = Services::curlrequest(); $requestOptions = [ 'headers' => [ - 'User-Agent' => 'Castopod/' . CP_VERSION . '; +' . base_url('', 'https'), + 'User-Agent' => 'Castopod/' . CP_VERSION . '; +' . base_url('', 'https'), 'Content-Type' => 'application/x-www-form-urlencoded', ], ]; @@ -63,7 +59,7 @@ class Publish extends BaseCommand foreach ($podcasts as $podcast) { $requestOptions['form_params'] = [ 'hub.mode' => 'publish', - 'hub.url' => $podcast->feed_url, + 'hub.url' => $podcast->feed_url, ]; foreach ($hubUrls as $hub) { @@ -71,23 +67,21 @@ class Publish extends BaseCommand $request->post($hub, $requestOptions); } catch (Exception $exception) { log_message( - 'warning', - "COULD NOT PUBLISH @{$podcast->handle} ON {$hub}" . PHP_EOL . $exception->getMessage(), + 'critical', + "COULD NOT PUBLISH @{$podcast->handle} ON {$hub}" . PHP_EOL . $exception->getMessage() ); } } // set podcast feed as having been pushed onto hubs - new PodcastModel() - ->update($podcast->id, [ - 'is_published_on_hubs' => 1, - ]); + (new PodcastModel())->update($podcast->id, [ + 'is_published_on_hubs' => true, + ]); // set newly published episodes as pushed onto hubs - new EpisodeModel() - ->set('is_published_on_hubs', true) + (new EpisodeModel())->set('is_published_on_hubs', true) ->where([ - 'podcast_id' => $podcast->id, + 'podcast_id' => $podcast->id, 'is_published_on_hubs' => false, ]) ->where('`published_at` <= UTC_TIMESTAMP()', null, false) diff --git a/modules/WebSub/Database/Migrations/2022-03-07-180000_add_is_published_on_hubs_to_podcasts.php b/modules/WebSub/Database/Migrations/2022-03-07-180000_add_is_published_on_hubs_to_podcasts.php index 179e1bf9..fb3d68ca 100644 --- a/modules/WebSub/Database/Migrations/2022-03-07-180000_add_is_published_on_hubs_to_podcasts.php +++ b/modules/WebSub/Database/Migrations/2022-03-07-180000_add_is_published_on_hubs_to_podcasts.php @@ -10,25 +10,22 @@ declare(strict_types=1); namespace Modules\WebSub\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddIsPublishedOnHubsToPodcasts extends BaseMigration +class AddIsPublishedOnHubsToPodcasts extends Migration { - #[Override] public function up(): void { - $this->forge->addColumn('podcasts', [ - 'is_published_on_hubs' => [ - 'type' => 'BOOLEAN', - 'null' => false, - 'default' => 0, - 'after' => 'custom_rss', - ], - ]); + $prefix = $this->db->getPrefix(); + + $createQuery = <<db->query($createQuery); } - #[Override] public function down(): void { $this->forge->dropColumn('podcasts', 'is_published_on_hubs'); diff --git a/modules/WebSub/Database/Migrations/2022-03-07-181500_add_is_published_on_hubs_to_episodes.php b/modules/WebSub/Database/Migrations/2022-03-07-181500_add_is_published_on_hubs_to_episodes.php index b57be027..dfe92a08 100644 --- a/modules/WebSub/Database/Migrations/2022-03-07-181500_add_is_published_on_hubs_to_episodes.php +++ b/modules/WebSub/Database/Migrations/2022-03-07-181500_add_is_published_on_hubs_to_episodes.php @@ -10,25 +10,22 @@ declare(strict_types=1); namespace Modules\WebSub\Database\Migrations; -use App\Database\Migrations\BaseMigration; -use Override; +use CodeIgniter\Database\Migration; -class AddIsPublishedOnHubsToEpisodes extends BaseMigration +class AddIsPublishedOnHubsToEpisodes extends Migration { - #[Override] public function up(): void { - $this->forge->addColumn('episodes', [ - 'is_published_on_hubs' => [ - 'type' => 'BOOLEAN', - 'null' => false, - 'default' => 0, - 'after' => 'custom_rss', - ], - ]); + $prefix = $this->db->getPrefix(); + + $createQuery = <<db->query($createQuery); } - #[Override] public function down(): void { $this->forge->dropColumn('episodes', 'is_published_on_hubs'); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..1831f5ab --- /dev/null +++ b/package-lock.json @@ -0,0 +1,28877 @@ +{ + "name": "castopod-host", + "version": "1.0.0-beta.24", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "castopod-host", + "version": "1.0.0-beta.24", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@amcharts/amcharts4": "^4.10.29", + "@amcharts/amcharts4-geodata": "^4.1.23", + "@codemirror/commands": "^6.1.2", + "@codemirror/lang-xml": "^6.0.0", + "@codemirror/language": "^6.2.1", + "@codemirror/state": "^6.1.2", + "@floating-ui/dom": "^1.0.2", + "@github/clipboard-copy-element": "^1.1.2", + "@github/hotkey": "^2.0.1", + "@github/markdown-toolbar-element": "^2.1.1", + "@github/time-elements": "^3.1.4", + "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", + "@vime/core": "^5.3.3", + "choices.js": "^10.1.0", + "codemirror": "^6.0.1", + "flatpickr": "^4.6.13", + "leaflet": "^1.9.2", + "leaflet.markercluster": "^1.5.3", + "lit": "^2.4.0", + "marked": "^4.1.1", + "wavesurfer.js": "^6.3.0", + "xml-formatter": "^2.6.1" + }, + "devDependencies": { + "@commitlint/cli": "^17.1.2", + "@commitlint/config-conventional": "^17.1.0", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/exec": "^6.0.3", + "@semantic-release/git": "^10.0.1", + "@semantic-release/gitlab": "^9.4.2", + "@tailwindcss/forms": "^0.5.3", + "@tailwindcss/line-clamp": "^0.4.2", + "@tailwindcss/typography": "^0.5.7", + "@types/leaflet": "^1.8.0", + "@types/marked": "^4.0.7", + "@types/wavesurfer.js": "^6.0.3", + "@typescript-eslint/eslint-plugin": "^5.40.0", + "@typescript-eslint/parser": "^5.40.0", + "all-contributors-cli": "^6.24.0", + "cross-env": "^7.0.3", + "cssnano": "^5.1.13", + "cz-conventional-changelog": "^3.3.0", + "eslint": "^8.25.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.2.1", + "husky": "^8.0.1", + "is-ci": "^3.0.1", + "lint-staged": "^13.0.3", + "postcss-import": "^15.0.0", + "postcss-nesting": "^10.2.0", + "postcss-preset-env": "^7.8.2", + "postcss-reporter": "^7.0.5", + "prettier": "2.7.1", + "prettier-plugin-organize-imports": "^3.1.1", + "semantic-release": "^19.0.5", + "stylelint": "^14.13.0", + "stylelint-config-standard": "^28.0.0", + "svgo": "^2.8.0", + "tailwindcss": "^3.1.8", + "typescript": "^4.8.4", + "vite": "2.8.6", + "vite-plugin-pwa": "^0.12.8", + "workbox-build": "^6.5.4", + "workbox-core": "^6.5.4", + "workbox-routing": "^6.5.4", + "workbox-strategies": "^6.5.4" + } + }, + "node_modules/@amcharts/amcharts4": { + "version": "4.10.29", + "resolved": "https://registry.npmjs.org/@amcharts/amcharts4/-/amcharts4-4.10.29.tgz", + "integrity": "sha512-uDCvm4V0Xs2jtI0Aa7XFH0jqoyEGx9I2ukFEwaaQzYq11vwowhJsgE3sSv2jsfKETYUvPXb32NbzrXZulE2ESg==", + "dependencies": { + "@babel/runtime": "^7.6.3", + "core-js": "^3.0.0", + "d3-force": "^3.0.0", + "d3-geo": "^3.0.1", + "d3-geo-projection": "^4.0.0", + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1", + "pdfmake": "^0.2.2", + "polylabel": "^1.0.2", + "raf": "^3.4.1", + "regression": "^2.0.1", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "tslib": "^2.0.1", + "xlsx": "^0.17.0" + } + }, + "node_modules/@amcharts/amcharts4-geodata": { + "version": "4.1.23", + "resolved": "https://registry.npmjs.org/@amcharts/amcharts4-geodata/-/amcharts4-geodata-4.1.23.tgz", + "integrity": "sha512-/hFqTuc2SUB0tAgygc8yj1xvTUdddltI7/15fAT9L5XHGERgF8qAa+AisQQ0UMITvrWIr5awJupWE3vDTlWsjQ==" + }, + "node_modules/@amcharts/amcharts4/node_modules/tslib": { + "version": "2.1.0", + "license": "0BSD" + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz", + "integrity": "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.6.tgz", + "integrity": "sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.6", + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helpers": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", + "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.7", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz", + "integrity": "sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw==", + "dev": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", + "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz", + "integrity": "sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-member-expression-to-functions": "^7.18.6", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", + "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", + "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", + "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz", + "integrity": "sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz", + "integrity": "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz", + "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz", + "integrity": "sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-wrap-function": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz", + "integrity": "sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-member-expression-to-functions": "^7.18.6", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.6.tgz", + "integrity": "sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz", + "integrity": "sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.6.tgz", + "integrity": "sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz", + "integrity": "sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.6.tgz", + "integrity": "sha512-Udgu8ZRgrBrttVz6A0EVL0SJ1z+RLbIeqsu632SA1hf0awEppD6TvdznoH+orIF8wtFFAV/Enmw9Y+9oV8TQcw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz", + "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", + "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.6.tgz", + "integrity": "sha512-zr/QcUlUo7GPo6+X1wC98NJADqmy5QTFWWhqeQWiki4XHafJtLl/YMGkmRB2szDD2IYJCCdBTd4ElwhId9T7Xw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.6.tgz", + "integrity": "sha512-zMo66azZth/0tVd7gmkxOkOjs2rpHyhpcFo565PUP37hSp6hSd9uUKIfTDFMz58BwqgQKhJ9YxtM5XddjXVn+Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.6.tgz", + "integrity": "sha512-9yuM6wr4rIsKa1wlUAbZEazkCrgw2sMPEXCr4Rnwetu7cEW1NydkCWytLuYletbf8vFxdJxFhwEZqMpOx2eZyw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.18.6", + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz", + "integrity": "sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", + "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", + "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", + "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", + "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.6.tgz", + "integrity": "sha512-pRqwb91C42vs1ahSAWJkxOxU1RHWDn16XAa6ggQ72wjLlWyYeAcLvTtE0aM8ph3KNydy9CQF2nLYcjq1WysgxQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.6.tgz", + "integrity": "sha512-XTg8XW/mKpzAF3actL554Jl/dOYoJtv3l8fxaEczpgz84IeeVf+T1u2CSvPHuZbt0w3JkIx4rdn/MRQI7mo0HQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.6.tgz", + "integrity": "sha512-9repI4BhNrR0KenoR9vm3/cIc1tSBIo+u1WVjKCAynahj25O8zfbiE6JtAtHPGQSs4yZ+bA8mRasRP+qc+2R5A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.6.tgz", + "integrity": "sha512-tgy3u6lRp17ilY8r1kP4i2+HDUwxlVqq3RTc943eAWSzGgpU1qhiKpqZ5CMyHReIYPHdo3Kg8v8edKtDqSVEyQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.6.tgz", + "integrity": "sha512-NJU26U/208+sxYszf82nmGYqVF9QN8py2HFTblPT9hbawi8+1C5a9JubODLTGFuT0qlkqVinmkwOD13s0sZktg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.6.tgz", + "integrity": "sha512-WAjoMf4wIiSsy88KmG7tgj2nFdEK7E46tArVtcgED7Bkj6Fg/tG5SbvNIOKxbFS2VFgNh6+iaPswBeQZm4ox8w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.6.tgz", + "integrity": "sha512-kJha/Gbs5RjzIu0CxZwf5e3aTTSlhZnHMT8zPWnJMjNpLOUgqevg+PN5oMH68nMCXnfiMo4Bhgxqj59KHTlAnA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.6.tgz", + "integrity": "sha512-x3HEw0cJZVDoENXOp20HlypIHfl0zMIhMVZEBVTfmqbObIpsMxMbmU5nOEO8R7LYT+z5RORKPlTI5Hj4OsO9/Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", + "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", + "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.6.tgz", + "integrity": "sha512-UbPYpXxLjTw6w6yXX2BYNxF3p6QY225wcTkfQCy3OMnSlS/C3xGtwUjEzGkldb/sy6PWLiCQ3NbYfjWUTI3t4g==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", + "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.6.tgz", + "integrity": "sha512-FjdqgMv37yVl/gwvzkcB+wfjRI8HQmc5EgOG9iGNvUY1ok+TjsoaMP7IqCDZBhkFcM5f3OPVMs6Dmp03C5k4/A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", + "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "regenerator-transform": "^0.15.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.6.tgz", + "integrity": "sha512-ayT53rT/ENF8WWexIRg9AiV9h0aIteyWn5ptfZTZQrjk/+f3WdrJGCY4c9wcgl2+MKkKPhzbYp97FTsquZpDCw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.6.tgz", + "integrity": "sha512-UuqlRrQmT2SWRvahW46cGSany0uTlcj8NYOS5sRGYi8FxPYPoLd5DDmMd32ZXEj2Jq+06uGVQKHxa/hJx2EzKw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.6.tgz", + "integrity": "sha512-7m71iS/QhsPk85xSjFPovHPcH3H9qeyzsujhTc+vcdnsXavoWYJ74zx0lP5RhpC5+iDnVLO+PPMHzC11qels1g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz", + "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.6.tgz", + "integrity": "sha512-WrthhuIIYKrEFAwttYzgRNQ5hULGmwTj+D6l7Zdfsv5M7IWV/OZbUfbeL++Qrzx1nVJwWROIFhCHRYQV4xbPNw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.18.6", + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.6", + "@babel/plugin-proposal-async-generator-functions": "^7.18.6", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.6", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.6", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.18.6", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.6", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.18.6", + "@babel/plugin-transform-classes": "^7.18.6", + "@babel/plugin-transform-computed-properties": "^7.18.6", + "@babel/plugin-transform-destructuring": "^7.18.6", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.6", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.6", + "@babel/plugin-transform-function-name": "^7.18.6", + "@babel/plugin-transform-literals": "^7.18.6", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.18.6", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.6", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.18.6", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.6", + "@babel/plugin-transform-typeof-symbol": "^7.18.6", + "@babel/plugin-transform-unicode-escapes": "^7.18.6", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.6", + "babel-plugin-polyfill-corejs2": "^0.3.1", + "babel-plugin-polyfill-corejs3": "^0.5.2", + "babel-plugin-polyfill-regenerator": "^0.3.1", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz", + "integrity": "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz", + "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz", + "integrity": "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.2.tgz", + "integrity": "sha512-sO3jdX1s0pam6lIdeSJLMN3DQ6mPEbM4yLvyKkdqtmd/UDwhXA5+AwFJ89rRXm6vTeOXBsE5cAmlos/t7MJdgg==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.0.0.tgz", + "integrity": "sha512-M/HLWxIiP956xGjtrxkeHkCmDGVQGKu782x8pOH5CLJIMkWtiB1DWfDoDHqpFjdEE9dkfcqPWvYfVi6GbhuXEg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml/node_modules/@codemirror/autocomplete": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.0.2.tgz", + "integrity": "sha512-9PDjnllmXan/7Uax87KGORbxerDJ/cu10SB+n4Jz0zXMEvIh3+TGgZxhIvDOtaQ4jDBQEM7kHYW4vLdQB0DGZQ==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.2.1.tgz", + "integrity": "sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/state": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz", + "integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==" + }, + "node_modules/@codemirror/view": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.0.2.tgz", + "integrity": "sha512-mnVT/q1JvKPjpmjXJNeCi/xHyaJ3abGJsumIVpdQ1nE1MXAyHf7GHWt8QpWMUvDiqF0j+inkhVR2OviTdFFX7Q==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@commitlint/cli": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.1.2.tgz", + "integrity": "sha512-h/4Hlka3bvCLbnxf0Er2ri5A44VMlbMSkdTRp8Adv2tRiklSTRIoPGs7OEXDv3EoDs2AAzILiPookgM4Gi7LOw==", + "dev": true, + "dependencies": { + "@commitlint/format": "^17.0.0", + "@commitlint/lint": "^17.1.0", + "@commitlint/load": "^17.1.2", + "@commitlint/read": "^17.1.0", + "@commitlint/types": "^17.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.19", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/cli/node_modules/yargs": { + "version": "17.3.0", + "dev": true, + "license": "MIT", + "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/@commitlint/cli/node_modules/yargs-parser": { + "version": "21.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.1.0.tgz", + "integrity": "sha512-WU2p0c9/jLi8k2q2YrDV96Y8XVswQOceIQ/wyJvQxawJSCasLdRB3kUIYdNjOCJsxkpoUlV/b90ZPxp1MYZDiA==", + "dev": true, + "dependencies": { + "conventional-changelog-conventionalcommits": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.1.0.tgz", + "integrity": "sha512-Q1rRRSU09ngrTgeTXHq6ePJs2KrI+axPTgkNYDWSJIuS1Op4w3J30vUfSXjwn5YEJHklK3fSqWNHmBhmTR7Vdg==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.0.0", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/ensure": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.0.0.tgz", + "integrity": "sha512-M2hkJnNXvEni59S0QPOnqCKIK52G1XyXBGw51mvh7OXDudCmZ9tZiIPpU882p475Mhx48Ien1MbWjCP1zlyC0A==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.0.0", + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.0.0.tgz", + "integrity": "sha512-nVjL/w/zuqjCqSJm8UfpNaw66V9WzuJtQvEnCrK4jDw6qKTmZB+1JQ8m6BQVZbNBcwfYdDNKnhIhqI0Rk7lgpQ==", + "dev": true, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/format": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.0.0.tgz", + "integrity": "sha512-MZzJv7rBp/r6ZQJDEodoZvdRM0vXu1PfQvMTNWFb8jFraxnISMTnPBWMMjr2G/puoMashwaNM//fl7j8gGV5lA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.0.0", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.1.0.tgz", + "integrity": "sha512-JITWKDMHhIh8IpdIbcbuH9rEQJty1ZWelgjleTFrVRAcEwN/sPzk1aVUXRIZNXMJWbZj8vtXRJnFihrml8uECQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.0.0", + "semver": "7.3.7" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/lint": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.1.0.tgz", + "integrity": "sha512-ltpqM2ogt/+SDhUaScFo0MdscncEF96lvQTPMM/VTTWlw7sTGLLWkOOppsee2MN/uLNNWjQ7kqkd4h6JqoM9AQ==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^17.1.0", + "@commitlint/parse": "^17.0.0", + "@commitlint/rules": "^17.0.0", + "@commitlint/types": "^17.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/load": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.1.2.tgz", + "integrity": "sha512-sk2p/jFYAWLChIfOIp/MGSIn/WzZ0vkc3afw+l4X8hGEYkvDe4gQUUAVxjl/6xMRn0HgnSLMZ04xXh5pkTsmgg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^17.1.0", + "@commitlint/execute-rule": "^17.0.0", + "@commitlint/resolve-extends": "^17.1.0", + "@commitlint/types": "^17.0.0", + "@types/node": "^14.0.0", + "chalk": "^4.1.0", + "cosmiconfig": "^7.0.0", + "cosmiconfig-typescript-loader": "^4.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "ts-node": "^10.8.1", + "typescript": "^4.6.4" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/load/node_modules/@types/node": { + "version": "14.18.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.26.tgz", + "integrity": "sha512-0b+utRBSYj8L7XAp0d+DX7lI4cSmowNaaTkk6/1SKzbKkG+doLuPusB9EOvzLJ8ahJSk03bTLIL6cWaEd4dBKA==", + "dev": true + }, + "node_modules/@commitlint/message": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.0.0.tgz", + "integrity": "sha512-LpcwYtN+lBlfZijHUdVr8aNFTVpHjuHI52BnfoV01TF7iSLnia0jttzpLkrLmI8HNQz6Vhr9UrxDWtKZiMGsBw==", + "dev": true, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/parse": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.0.0.tgz", + "integrity": "sha512-cKcpfTIQYDG1ywTIr5AG0RAiLBr1gudqEsmAGCTtj8ffDChbBRxm6xXs2nv7GvmJN7msOt7vOKleLvcMmRa1+A==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.0.0", + "conventional-changelog-angular": "^5.0.11", + "conventional-commits-parser": "^3.2.2" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/read": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.1.0.tgz", + "integrity": "sha512-73BoFNBA/3Ozo2JQvGsE0J8SdrJAWGfZQRSHqvKaqgmY042Su4gXQLqvAzgr55S9DI1l9TiU/5WDuh8IE86d/g==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^17.0.0", + "@commitlint/types": "^17.0.0", + "fs-extra": "^10.0.0", + "git-raw-commits": "^2.0.0", + "minimist": "^1.2.6" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/read/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@commitlint/read/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/@commitlint/resolve-extends": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.1.0.tgz", + "integrity": "sha512-jqKm00LJ59T0O8O4bH4oMa4XyJVEOK4GzH8Qye9XKji+Q1FxhZznxMV/bDLyYkzbTodBt9sL0WLql8wMtRTbqQ==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^17.1.0", + "@commitlint/types": "^17.0.0", + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/rules": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.0.0.tgz", + "integrity": "sha512-45nIy3dERKXWpnwX9HeBzK5SepHwlDxdGBfmedXhL30fmFCkJOdxHyOJsh0+B0RaVsLGT01NELpfzJUmtpDwdQ==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^17.0.0", + "@commitlint/message": "^17.0.0", + "@commitlint/to-lines": "^17.0.0", + "@commitlint/types": "^17.0.0", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.0.0.tgz", + "integrity": "sha512-nEi4YEz04Rf2upFbpnEorG8iymyH7o9jYIVFBG1QdzebbIFET3ir+8kQvCZuBE5pKCtViE4XBUsRZz139uFrRQ==", + "dev": true, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/top-level": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.0.0.tgz", + "integrity": "sha512-dZrEP1PBJvodNWYPOYiLWf6XZergdksKQaT6i1KSROLdjf5Ai0brLOv5/P+CPxBeoj3vBxK4Ax8H1Pg9t7sHIQ==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/top-level/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/types": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.0.0.tgz", + "integrity": "sha512-hBAw6U+SkAT5h47zDMeOu3HSiD0SODw4Aq7rRNh1ceUmL7GyLKYhPbUvlRWqZ65XjBLPHZhFyQlRaPNz8qvUyQ==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2", + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@floating-ui/core": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.0.1.tgz", + "integrity": "sha512-bO37brCPfteXQfFY0DyNDGB3+IMe4j150KFQcgJ5aBP295p9nBGeHEs/p0czrRbtlHq4Px/yoPXO/+dOCcF4uA==" + }, + "node_modules/@floating-ui/dom": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.0.2.tgz", + "integrity": "sha512-5X9WSvZ8/fjy3gDu8yx9HAA4KG1lazUN2P4/VnaXLxTO9Dz53HI1oYoh1OlhqFNlHgGDiwFX5WhFCc2ljbW3yA==", + "dependencies": { + "@floating-ui/core": "^1.0.1" + } + }, + "node_modules/@foliojs-fork/fontkit": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "@foliojs-fork/restructure": "^2.0.2", + "brfs": "^2.0.0", + "brotli": "^1.2.0", + "browserify-optional": "^1.0.1", + "clone": "^1.0.4", + "deep-equal": "^1.0.0", + "dfa": "^1.2.0", + "tiny-inflate": "^1.0.2", + "unicode-properties": "^1.2.2", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/@foliojs-fork/linebreak": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "base64-js": "1.3.1", + "brfs": "^2.0.2", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/@foliojs-fork/pdfkit": { + "version": "0.12.3", + "license": "MIT", + "dependencies": { + "@foliojs-fork/fontkit": "^1.9.1", + "@foliojs-fork/linebreak": "^1.1.1", + "crypto-js": "^4.0.0", + "png-js": "^1.0.0" + } + }, + "node_modules/@foliojs-fork/restructure": { + "version": "2.0.2", + "license": "MIT" + }, + "node_modules/@github/clipboard-copy-element": { + "version": "1.1.2", + "license": "MIT" + }, + "node_modules/@github/hotkey": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@github/hotkey/-/hotkey-2.0.1.tgz", + "integrity": "sha512-qKXjAJjtheJbf4ie3hi8IwrHWJZHB5qdojR6JGo6jvQNPpsdUbk/NIdU8sxu4PW41CjW80vfciDMu3MAP3j2Fg==" + }, + "node_modules/@github/markdown-toolbar-element": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@github/markdown-toolbar-element/-/markdown-toolbar-element-2.1.1.tgz", + "integrity": "sha512-J++rpd5H9baztabJQB82h26jtueOeBRSTqetk9Cri+Lj/s28ndu6Tovn0uHQaOKtBWDobFunk9b5pP5vcqt7cA==" + }, + "node_modules/@github/time-elements": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@github/time-elements/-/time-elements-3.1.4.tgz", + "integrity": "sha512-DTe/w0uKVeciKzGtYadNdfS8D86pXdGF+OrKg+vi8PKlotJ45zAc26zNpmmfCcMblBBg2+uoi3OxmUm7am/0sg==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", + "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", + "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "dev": true, + "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, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "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/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@lezer/common": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.0.tgz", + "integrity": "sha512-ohydQe+Hb+w4oMDvXzs8uuJd2NoA3D8YDcLiuDsLqH+yflDTPEpgCsWI3/6rH5C3BAedtH1/R51dxENldQceEA==" + }, + "node_modules/@lezer/highlight": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.0.0.tgz", + "integrity": "sha512-nsCnNtim90UKsB5YxoX65v3GEIw3iCHw9RM2DtdgkiqAbKh9pCdvi8AWNwkYf10Lu6fxNhXPpkpHbW6mihhvJA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.1.0.tgz", + "integrity": "sha512-Iad04uVwk1PvSnj25mqj7zEEIRAsasbsTRmVzI0AUTs/+1Dz1//iYAaoLr7A+Xa7bZDfql5MKTxZmSlkYZD3Dg==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/xml": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.0.tgz", + "integrity": "sha512-73iI9UK8iqSvWtLlOEl/g+50ivwQn8Ge6foHVN66AXUS1RccFnAoc7BYU8b3c8/rP6dfCOGqAGaWLxBzhj60MA==", + "dependencies": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lit/reactive-element": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.4.1.tgz", + "integrity": "sha512-qDv4851VFSaBWzpS02cXHclo40jsbAjRXnebNXpm0uVg32kCneZPo9RYVQtrTNICtZ+1wAYHu1ZtxWSWMbKrBw==" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.0", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "11.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.17.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.34.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.13.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.34.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.6.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/rest": { + "version": "18.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.34.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^11.2.0" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace/node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@semantic-release/changelog": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "fs-extra": "^9.0.0", + "lodash": "^4.17.4" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/commit-analyzer": { + "version": "9.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-angular": "^5.0.0", + "conventional-commits-filter": "^2.0.0", + "conventional-commits-parser": "^3.2.3", + "debug": "^4.0.0", + "import-from": "^4.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0-beta.1" + } + }, + "node_modules/@semantic-release/commit-analyzer/node_modules/import-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/error": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@semantic-release/exec": { + "version": "6.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "parse-json": "^5.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/exec/node_modules/parse-json": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/git": { + "version": "10.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.0", + "p-reduce": "^2.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/github": { + "version": "8.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/rest": "^18.0.0", + "@semantic-release/error": "^2.2.0", + "aggregate-error": "^3.0.0", + "bottleneck": "^2.18.1", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "fs-extra": "^10.0.0", + "globby": "^11.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "issue-parser": "^6.0.0", + "lodash": "^4.17.4", + "mime": "^3.0.0", + "p-filter": "^2.0.0", + "p-retry": "^4.0.0", + "url-join": "^4.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0-beta.1" + } + }, + "node_modules/@semantic-release/github/node_modules/@semantic-release/error": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@semantic-release/github/node_modules/@tootallnate/once": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@semantic-release/github/node_modules/fs-extra": { + "version": "10.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@semantic-release/github/node_modules/http-proxy-agent": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@semantic-release/github/node_modules/universalify": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@semantic-release/gitlab": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@semantic-release/gitlab/-/gitlab-9.4.2.tgz", + "integrity": "sha512-ZfMe4N613C/tqfRdxDPprOoBA7HHyHFHvk+TA4HqOmNpgUKiifyJPpYJsc3PLNtec9I0TA1OOTuY82VDG+FVXw==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "escape-string-regexp": "^3.0.0", + "form-data": "^4.0.0", + "fs-extra": "^10.0.0", + "globby": "^11.0.0", + "got": "^11.0.0", + "hpagent": "^1.0.0", + "lodash": "^4.17.11", + "parse-url": "^8.0.0", + "url-join": "^4.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/gitlab/node_modules/escape-string-regexp": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/gitlab/node_modules/form-data": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@semantic-release/gitlab/node_modules/fs-extra": { + "version": "10.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@semantic-release/gitlab/node_modules/universalify": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@semantic-release/npm": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.0.tgz", + "integrity": "sha512-hj2jqayS2SPUmFtCMCOQMX975uMDfRoymj1HvMSwYdaoI6hVZvhrTFPBgJeM85O0C+G3IFviAUar5gel/1VGDQ==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "execa": "^5.0.0", + "fs-extra": "^10.0.0", + "lodash": "^4.17.15", + "nerf-dart": "^1.0.0", + "normalize-url": "^6.0.0", + "npm": "^8.3.0", + "rc": "^1.2.8", + "read-pkg": "^5.0.0", + "registry-auth-token": "^4.0.0", + "semver": "^7.1.2", + "tempy": "^1.0.0" + }, + "engines": { + "node": ">=16 || ^14.17" + }, + "peerDependencies": { + "semantic-release": ">=19.0.0" + } + }, + "node_modules/@semantic-release/npm/node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@semantic-release/npm/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@semantic-release/npm/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/@semantic-release/release-notes-generator": { + "version": "10.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-angular": "^5.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-filter": "^2.0.0", + "conventional-commits-parser": "^3.2.3", + "debug": "^4.0.0", + "get-stream": "^6.0.0", + "import-from": "^4.0.0", + "into-stream": "^6.0.0", + "lodash": "^4.17.4", + "read-pkg-up": "^7.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0-beta.1" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/get-stream": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/import-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@stencil/core": { + "version": "2.5.2", + "license": "MIT", + "bin": { + "stencil": "bin/stencil" + }, + "engines": { + "node": ">=12.10.0", + "npm": ">=6.0.0" + } + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dev": true, + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz", + "integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==", + "dev": true, + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" + } + }, + "node_modules/@tailwindcss/line-clamp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", + "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", + "dev": true, + "peerDependencies": { + "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + } + }, + "node_modules/@tailwindcss/nesting": { + "version": "0.0.0-insiders.565cd3e", + "resolved": "https://registry.npmjs.org/@tailwindcss/nesting/-/nesting-0.0.0-insiders.565cd3e.tgz", + "integrity": "sha512-WhHoFBx19TnH/c+xLwT/sxei6+4RpdfiyG3MYXfmLaMsADmVqBkF7B6lDalgZD9YdM459MF7DtxVbWkOrV7IaQ==", + "dependencies": { + "postcss-nested": "^5.0.5" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.7.tgz", + "integrity": "sha512-JTTSTrgZfp6Ki4svhPA4mkd9nmQ/j9EfE7SbHJ1cLtthKkpW2OxsFXzSmxbhYbEkfNIyAyhle5p4SYyKRbz/jg==", + "dev": true, + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/color-name": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-epMsEE85fi4lfmJUH/89/iV/LI+F5CvNIvmgs5g5jYFPfhO2S/ae8WSsLOKWdwtoaZw9Q2IhJ4tQ5tFCcS/4HA==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "node_modules/@types/fscreen": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/@types/geojson": { + "version": "7946.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/leaflet": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.8.0.tgz", + "integrity": "sha512-+sXFmiJTFdhaXXIGFlV5re9AdqtAODoXbGAvxx02e5SHXL3ir7ClP5J7pahO8VmzKY3dth4RUS1nf2BTT+DW1A==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/marked": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.7.tgz", + "integrity": "sha512-eEAhnz21CwvKVW+YvRvcTuFKNU9CV1qH+opcgVK3pIMI6YZzDm6gc8o2vHjldFk6MGKt5pueSB7IOpvpx5Qekw==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "17.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.2", + "license": "MIT" + }, + "node_modules/@types/wavesurfer.js": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/wavesurfer.js/-/wavesurfer.js-6.0.3.tgz", + "integrity": "sha512-5Sb5s3pEkOmDosaaP1DWp1Unnx8HhVorm5608TIVdT5jCMvJ6eqM19UD8n7DEbJ7rzreS9RqHmzR8TlcdQBvbA==", + "dev": true, + "dependencies": { + "@types/debounce": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.0.tgz", + "integrity": "sha512-FIBZgS3DVJgqPwJzvZTuH4HNsZhHMa9SjxTKAZTlMsPw/UzpEjcf9f4dfgDJEHjK+HboUJo123Eshl6niwEm/Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.40.0", + "@typescript-eslint/type-utils": "5.40.0", + "@typescript-eslint/utils": "5.40.0", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.0.tgz", + "integrity": "sha512-Ah5gqyX2ySkiuYeOIDg7ap51/b63QgWZA7w6AHtFrag7aH0lRQPbLzUjk0c9o5/KZ6JRkTTDKShL4AUrQa6/hw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.40.0", + "@typescript-eslint/types": "5.40.0", + "@typescript-eslint/typescript-estree": "5.40.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.0.tgz", + "integrity": "sha512-d3nPmjUeZtEWRvyReMI4I1MwPGC63E8pDoHy0BnrYjnJgilBD3hv7XOiETKLY/zTwI7kCnBDf2vWTRUVpYw0Uw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.40.0", + "@typescript-eslint/visitor-keys": "5.40.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.0.tgz", + "integrity": "sha512-nfuSdKEZY2TpnPz5covjJqav+g5qeBqwSHKBvz7Vm1SAfy93SwKk/JeSTymruDGItTwNijSsno5LhOHRS1pcfw==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.40.0", + "@typescript-eslint/utils": "5.40.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.0.tgz", + "integrity": "sha512-V1KdQRTXsYpf1Y1fXCeZ+uhjW48Niiw0VGt4V8yzuaDTU8Z1Xl7yQDyQNqyAFcVhpYXIVCEuxSIWTsLDpHgTbw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.0.tgz", + "integrity": "sha512-b0GYlDj8TLTOqwX7EGbw2gL5EXS2CPEWhF9nGJiGmEcmlpNBjyHsTwbqpyIEPVpl6br4UcBOYlcI2FJVtJkYhg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.40.0", + "@typescript-eslint/visitor-keys": "5.40.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.0.tgz", + "integrity": "sha512-MO0y3T5BQ5+tkkuYZJBjePewsY+cQnfkYeRqS6tPh28niiIwPnQ1t59CSRcs1ZwJJNOdWw7rv9pF8aP58IMihA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.40.0", + "@typescript-eslint/types": "5.40.0", + "@typescript-eslint/typescript-estree": "5.40.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.0.tgz", + "integrity": "sha512-ijJ+6yig+x9XplEpG2K6FUdJeQGGj/15U3S56W9IqXKJqleuD7zJ2AX/miLezwxpd7ZxDAqO87zWufKg+RPZyQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.40.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vime/core": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@vime/core/-/core-5.3.3.tgz", + "integrity": "sha512-bGn6bwiOwI/0d+P+gLH9U3ySK4tar6Qiv7g+RR+c7iuCsl0S16/wP1G677PiglJTvM3wuo2wD3hztMEkiWfvhw==", + "dependencies": { + "@stencil/core": "2.5.2", + "@types/fscreen": "^1.0.1", + "fscreen": "^1.2.0", + "mitt": "^3.0.0", + "stencil-wormhole": "^3.4.1" + } + }, + "node_modules/abab": { + "version": "2.0.5", + "license": "BSD-3-Clause" + }, + "node_modules/acorn": { + "version": "7.4.1", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "license": "MIT", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adler-32": { + "version": "1.2.0", + "license": "Apache-2.0", + "dependencies": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + }, + "bin": { + "adler32": "bin/adler32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/all-contributors-cli": { + "version": "6.24.0", + "resolved": "https://registry.npmjs.org/all-contributors-cli/-/all-contributors-cli-6.24.0.tgz", + "integrity": "sha512-7oSKr2PnqxsOotuSwciltcFTS1eVRdjR0cn99hbElfff7gRQBShVhsf/XBprY41sLcgqTk0l0MKgKv6QNgZdMg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.7.6", + "async": "^3.1.0", + "chalk": "^4.0.0", + "didyoumean": "^1.2.1", + "inquirer": "^7.3.3", + "json-fixer": "^1.6.8", + "lodash": "^4.11.2", + "node-fetch": "^2.6.0", + "pify": "^5.0.0", + "yargs": "^15.0.1" + }, + "bin": { + "all-contributors": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/all-contributors-cli/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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/all-contributors-cli/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/all-contributors-cli/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" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/all-contributors-cli/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/all-contributors-cli/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/all-contributors-cli/node_modules/inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/all-contributors-cli/node_modules/pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/all-contributors-cli/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/all-contributors-cli/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/all-contributors-cli/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/all-contributors-cli/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "license": "BSD-3-Clause OR MIT", + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", + "dev": true + }, + "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, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "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/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/argv-formatter": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/array-from": { + "version": "2.1.1", + "license": "MIT" + }, + "node_modules/array-ify": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-transform": { + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "escodegen": "~1.2.0", + "esprima": "~1.0.4", + "through": "~2.3.4" + } + }, + "node_modules/ast-transform/node_modules/esprima": { + "version": "1.0.4", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ast-types": { + "version": "0.7.8", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.12", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.12.tgz", + "integrity": "sha512-WrCGV9/b97Pa+jtwf5UGaRjgQIg7OK3D06GnoYoZNcG1Xb8Gt3EfuKjlhh9i/VtT16g6PYjZ69jdJ2g8FxSC4Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-lite": "^1.0.30001407", + "fraction.js": "^4.2.0", + "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" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "license": "MIT", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/core-js": { + "version": "2.6.12", + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "2.2.2", + "dev": true, + "license": "Apache-2.0" + }, + "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/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brfs": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^3.0.2", + "through2": "^2.0.0" + }, + "bin": { + "brfs": "bin/cmd.js" + } + }, + "node_modules/brfs/node_modules/through2": { + "version": "2.0.5", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/brotli": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "license": "BSD-2-Clause" + }, + "node_modules/browser-resolve": { + "version": "1.11.3", + "license": "MIT", + "dependencies": { + "resolve": "1.1.7" + } + }, + "node_modules/browser-resolve/node_modules/resolve": { + "version": "1.1.7", + "license": "MIT" + }, + "node_modules/browserify-optional": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "ast-transform": "0.0.0", + "ast-types": "^0.7.0", + "browser-resolve": "^1.8.1" + } + }, + "node_modules/browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal": { + "version": "0.0.1", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "license": "MIT" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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/camelcase-keys": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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.30001412", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz", + "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "dev": true, + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/cfb": { + "version": "1.2.1", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0", + "printj": "~1.3.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cfb/node_modules/adler-32": { + "version": "1.3.0", + "license": "Apache-2.0", + "dependencies": { + "printj": "~1.2.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cfb/node_modules/adler-32/node_modules/printj": { + "version": "1.2.3", + "license": "Apache-2.0", + "bin": { + "printj": "bin/printj.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cfb/node_modules/printj": { + "version": "1.3.0", + "license": "Apache-2.0", + "bin": { + "printj": "bin/printj.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/choices.js": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-10.1.0.tgz", + "integrity": "sha512-NtrFt7c7ZQEGmkWsAV+EHynJhADWoZ82JEfg1+vQ9MMKJD4Ax2rzYPxXe+Q64i0HgUgWG/XTN3gN2pB8UFFFlA==", + "dependencies": { + "deepmerge": "^4.2.2", + "fuse.js": "^6.5.3", + "redux": "^4.1.2" + } + }, + "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/" + } + ], + "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" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/ci-info": { + "version": "3.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", + "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "colors": "1.4.0" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/codemirror": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", + "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, + "node_modules/codemirror/node_modules/@codemirror/autocomplete": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.0.2.tgz", + "integrity": "sha512-9PDjnllmXan/7Uax87KGORbxerDJ/cu10SB+n4Jz0zXMEvIh3+TGgZxhIvDOtaQ4jDBQEM7kHYW4vLdQB0DGZQ==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/codemirror/node_modules/@codemirror/lint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.0.0.tgz", + "integrity": "sha512-nUUXcJW1Xp54kNs+a1ToPLK8MadO0rMTnJB8Zk4Z8gBdrN0kqV7uvUraU/T2yqg+grDNR38Vmy/MrhQN/RgwiA==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/codemirror/node_modules/@codemirror/search": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.0.0.tgz", + "integrity": "sha512-rL0rd3AhI0TAsaJPUaEwC63KHLO7KL0Z/dYozXj6E7L3wNHRyx7RfE0/j5HsIf912EE5n2PCb4Vg0rGYmDv4UQ==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "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 + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz", + "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/commitizen": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.5.tgz", + "integrity": "sha512-9sXju8Qrz1B4Tw7kC5KhnvwYQN88qs2zbiB8oyMsnXZyJ24PPGiNM3nHr73d32dnE3i8VJEXddBFIbOgYSEXtQ==", + "dev": true, + "dependencies": { + "cachedir": "2.3.0", + "cz-conventional-changelog": "3.3.0", + "dedent": "0.7.0", + "detect-indent": "6.1.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "9.1.0", + "glob": "7.2.3", + "inquirer": "8.2.4", + "is-utf8": "^0.2.1", + "lodash": "4.17.21", + "minimist": "1.2.6", + "strip-bom": "4.0.0", + "strip-json-comments": "3.1.1" + }, + "bin": { + "commitizen": "bin/commitizen", + "cz": "bin/git-cz", + "git-cz": "bin/git-cz" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/commitizen/node_modules/find-node-modules": { + "version": "2.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "findup-sync": "^4.0.0", + "merge": "^2.1.0" + } + }, + "node_modules/commitizen/node_modules/findup-sync": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/commitizen/node_modules/merge": { + "version": "2.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", + "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.6", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commit-types": { + "version": "3.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/conventional-commits-filter": { + "version": "2.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commits-parser": { + "version": "3.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/convert-source-map": { + "version": "1.7.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/core-js": { + "version": "3.6.5", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.23.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.3.tgz", + "integrity": "sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.0", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.0.0.tgz", + "integrity": "sha512-cVpucSc2Tf+VPwCCR7SZzmQTQkPbkk4O01yXsYqXBIbjE1bhwqSyAgYQkRK1un4i0OPziTleqFhdkmOc4RQ/9g==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "ts-node": ">=10", + "typescript": ">=3" + } + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crc-32": { + "version": "1.2.0", + "license": "Apache-2.0", + "dependencies": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + }, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/crelt": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", + "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" + }, + "node_modules/cross-env": { + "version": "7.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-js": { + "version": "4.1.1", + "license": "MIT" + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-blank-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", + "integrity": "sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, + "node_modules/css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-has-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "dev": true, + "bin": { + "css-prefers-color-scheme": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssdb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.0.1.tgz", + "integrity": "sha512-pT3nzyGM78poCKLAEy2zWIVX2hikq6dIrjuZzLV98MumBg+xMTNYfHx7paUlfiRTgg91O/vR889CIf+qiv79Rw==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", + "dev": true, + "dependencies": { + "cssnano-preset-default": "^5.2.12", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.12.tgz", + "integrity": "sha512-OyCBTZi+PXgylz9HAA5kHyoYhfGcYdwFmyaJzWnzxuGRtnMw/kR6ilW9XzlzlRAtB6PLT/r+prYgkef7hngFew==", + "dev": true, + "dependencies": { + "css-declaration-sorter": "^6.3.0", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.0", + "postcss-convert-values": "^5.1.2", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.6", + "postcss-merge-rules": "^5.1.2", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.3", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.0", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.0", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "license": "MIT" + }, + "node_modules/cz-conventional-changelog": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" + } + }, + "node_modules/cz-conventional-changelog/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/d": { + "version": "1.0.1", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/d3-array": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.0.tgz", + "integrity": "sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz", + "integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo-projection": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-4.0.0.tgz", + "integrity": "sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==", + "dependencies": { + "commander": "7", + "d3-array": "1 - 3", + "d3-geo": "1.12.0 - 3" + }, + "bin": { + "geo2svg": "bin/geo2svg.js", + "geograticule": "bin/geograticule.js", + "geoproject": "bin/geoproject.js", + "geoquantize": "bin/geoquantize.js", + "geostitch": "bin/geostitch.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo-projection/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==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dash-ast": { + "version": "1.0.0", + "license": "Apache-2.0" + }, + "node_modules/data-urls": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.3.1", + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-equal": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "node_modules/del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "dev": true, + "license": "ISC" + }, + "node_modules/detect-file": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dfa": { + "version": "1.2.0", + "license": "MIT" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/domexception": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.264", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz", + "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-ci": { + "version": "5.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "fromentries": "^1.3.2", + "java-properties": "^1.0.0" + }, + "engines": { + "node": ">=10.17" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "license": "ISC", + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-map": { + "version": "0.1.5", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "node_modules/es6-set": { + "version": "0.1.5", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } + }, + "node_modules/es6-set/node_modules/es6-symbol": { + "version": "3.1.1", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/esbuild": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz", + "integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-64": "0.14.48", + "esbuild-android-arm64": "0.14.48", + "esbuild-darwin-64": "0.14.48", + "esbuild-darwin-arm64": "0.14.48", + "esbuild-freebsd-64": "0.14.48", + "esbuild-freebsd-arm64": "0.14.48", + "esbuild-linux-32": "0.14.48", + "esbuild-linux-64": "0.14.48", + "esbuild-linux-arm": "0.14.48", + "esbuild-linux-arm64": "0.14.48", + "esbuild-linux-mips64le": "0.14.48", + "esbuild-linux-ppc64le": "0.14.48", + "esbuild-linux-riscv64": "0.14.48", + "esbuild-linux-s390x": "0.14.48", + "esbuild-netbsd-64": "0.14.48", + "esbuild-openbsd-64": "0.14.48", + "esbuild-sunos-64": "0.14.48", + "esbuild-windows-32": "0.14.48", + "esbuild-windows-64": "0.14.48", + "esbuild-windows-arm64": "0.14.48" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz", + "integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz", + "integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz", + "integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz", + "integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz", + "integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz", + "integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz", + "integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz", + "integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz", + "integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz", + "integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz", + "integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz", + "integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz", + "integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz", + "integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz", + "integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz", + "integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz", + "integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz", + "integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz", + "integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz", + "integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.2.0", + "dependencies": { + "esprima": "~1.0.4", + "estraverse": "~1.5.0", + "esutils": "~1.0.0" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.4.0" + }, + "optionalDependencies": { + "source-map": "~0.1.30" + } + }, + "node_modules/escodegen/node_modules/esprima": { + "version": "1.0.4", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "1.5.1", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/escodegen/node_modules/esutils": { + "version": "1.0.0", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.1.43", + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", + "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.10.5", + "@humanwhocodes/module-importer": "^1.0.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-is-function": { + "version": "1.0.0", + "license": "Apache-2.0" + }, + "node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/esutils": { + "version": "2.0.3", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/human-signals": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/exit-on-epipe": { + "version": "1.0.1", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext": { + "version": "1.5.0", + "license": "ISC", + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.5.0", + "license": "ISC" + }, + "node_modules/external-editor": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@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" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "license": "MIT" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.8.0", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fflate": { + "version": "0.3.11", + "license": "MIT" + }, + "node_modules/figures": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/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/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-versions": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver-regex": "^3.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatpickr": { + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", + "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==" + }, + "node_modules/flatted": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/fontkit": { + "version": "1.8.1", + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.26.0", + "brfs": "^2.0.0", + "brotli": "^1.2.0", + "browserify-optional": "^1.0.1", + "clone": "^1.0.4", + "deep-equal": "^1.0.0", + "dfa": "^1.2.0", + "restructure": "^0.5.3", + "tiny-inflate": "^1.0.2", + "unicode-properties": "^1.2.2", + "unicode-trie": "^0.3.0" + } + }, + "node_modules/fontkit/node_modules/unicode-trie": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/form-data": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/frac": { + "version": "1.1.2", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fromentries": { + "version": "1.3.2", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-extra/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/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/fscreen": { + "version": "1.2.0", + "license": "MIT" + }, + "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, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fuse.js": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.5.3.tgz", + "integrity": "sha512-sA5etGE7yD/pOqivZRBvUBd/NaL2sjAu6QuSaFoe1H2BrJSkH/T/UXAJ8CdXdw7DvY3Hs8CXKYkDWX7RiP5KOg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-assigned-identifiers": { + "version": "1.2.0", + "license": "Apache-2.0" + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "node_modules/get-stream": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/git-log-parser": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argv-formatter": "~1.0.0", + "spawn-error-forwarder": "~1.0.0", + "split2": "~1.0.0", + "stream-combiner2": "~1.1.1", + "through2": "~2.0.0", + "traverse": "~0.6.6" + } + }, + "node_modules/git-log-parser/node_modules/split2": { + "version": "1.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "through2": "~2.0.0" + } + }, + "node_modules/git-log-parser/node_modules/through2": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "dev": true, + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/got": { + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "dev": true, + "license": "ISC" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.7", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hook-std": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hosted-git-info": { + "version": "4.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hpagent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.0.0.tgz", + "integrity": "sha512-SCleE2Uc1bM752ymxg8QXYGW0TWtAV4ZW3TqH1aOnyi6T6YW2xadCcclm5qeVjvMvfQ2RKNtZxO7uVb9CTPt1A==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/http2-wrapper/node_modules/quick-lru": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "dev": true, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/husky": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", + "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idb": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.2.tgz", + "integrity": "sha512-jjKrT1EnyZewQ/gCBb/eyiYrhGzws2FeY92Yx8qT9S9GeQAmo4JFVIiWRIfKW/6Ob9A+UDAOW9j9jn58fy2HIg==", + "dev": true + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "dev": true, + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inquirer/node_modules/rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/inquirer/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/into-stream": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arguments": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/issue-parser": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": ">=10.13" + } + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/java-properties": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-sdsl": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", + "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "license": "MIT", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/acorn": { + "version": "8.5.0", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsdom/node_modules/escodegen": { + "version": "2.0.0", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/jsdom/node_modules/estraverse": { + "version": "5.2.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/jsdom/node_modules/levn": { + "version": "0.3.0", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/jsdom/node_modules/optionator": { + "version": "0.8.3", + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/jsdom/node_modules/prelude-ls": { + "version": "1.1.2", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/jsdom/node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsdom/node_modules/type-check": { + "version": "0.3.2", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-fixer": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/json-fixer/-/json-fixer-1.6.13.tgz", + "integrity": "sha512-DKQ71M+0uwAG3QsUkeVgh6XREw/OkpnTfHfM+sdmxRjHvYZ8PlcMVF4ibsHQ1ckR63NROs68qUr1I0u6yPVePQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.6", + "chalk": "^4.1.2", + "pegjs": "^0.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "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/jsonfile/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/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/jsonpointer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", + "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/keyv": { + "version": "4.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", + "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", + "dev": true + }, + "node_modules/leaflet": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.2.tgz", + "integrity": "sha512-Kc77HQvWO+y9y2oIs3dn5h5sy2kr3j41ewdqCMEUA4N89lgfUUfOBy7wnnHEstDpefiGFObq12FdopGRMx4J7g==" + }, + "node_modules/leaflet.markercluster": { + "version": "1.5.3", + "license": "MIT", + "peerDependencies": { + "leaflet": "^1.3.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/linebreak": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "base64-js": "0.0.8", + "brfs": "^2.0.2", + "unicode-trie": "^1.0.0" + } + }, + "node_modules/linebreak/node_modules/base64-js": { + "version": "0.0.8", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/linebreak/node_modules/unicode-trie": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "dev": true, + "license": "MIT" + }, + "node_modules/lint-staged": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.3.tgz", + "integrity": "sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==", + "dev": true, + "dependencies": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.17", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^6.1.0", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.1.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/ansi-styles": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/string-width": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.0.1.tgz", + "integrity": "sha512-5ohWO/M4//8lErlUUtrFy3b11GtNOuMOU0ysKCDXFcfXuuvUXu95akgj/i8ofmaGdN0hCqyl6uu9i8dS/mQp5g==", + "dev": true, + "dependencies": { + "emoji-regex": "^9.2.2", + "is-fullwidth-code-point": "^4.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.1.tgz", + "integrity": "sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/listr2/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "node_modules/lit": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.4.0.tgz", + "integrity": "sha512-fdgzxEtLrZFQU/BqTtxFQCLwlZd9bdat+ltzSFjvWkZrs7eBmeX0L5MHUMb3kYIkuS8Xlfnii/iI5klirF8/Xg==", + "dependencies": { + "@lit/reactive-element": "^1.4.0", + "lit-element": "^3.2.0", + "lit-html": "^2.4.0" + } + }, + "node_modules/lit-element": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.0.tgz", + "integrity": "sha512-HbE7yt2SnUtg5DCrWt028oaU4D5F4k/1cntAFHTkzY8ZIa8N0Wmu92PxSxucsQSOXlODFrICkQ5x/tEshKi13g==", + "dependencies": { + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.2.0" + } + }, + "node_modules/lit-html": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.4.0.tgz", + "integrity": "sha512-G6qXu4JNUpY6aaF2VMfaszhO9hlWw0hOTRFDmuMheg/nDYGB+2RztUSOyrzALAbr8Nh0Y7qjhYkReh3rPnplVg==", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "license": "MIT" + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.map": { + "version": "4.6.0", + "dev": true, + "license": "MIT" + }, + "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.merge": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "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/lodash.uniqby": { + "version": "4.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/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" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-update/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/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/longest": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.25.1", + "license": "MIT", + "dependencies": { + "sourcemap-codec": "^1.4.1" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/map-obj": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", + "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/marked-terminal": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.0.0.tgz", + "integrity": "sha512-26604GmGmW63ElxcXpE2xfMdbtgD/qiwIqOh/+5+uPe6NVU4bU433+wvPTfq6NZcGr16KWqwu/dzsKxg3IL2Xw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^5.0.0", + "cardinal": "^2.1.1", + "chalk": "^5.0.0", + "cli-table3": "^0.6.0", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.2.0" + }, + "engines": { + "node": " >=14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" + } + }, + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", + "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.0.tgz", + "integrity": "sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/marked-terminal/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/meow": { + "version": "8.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-source-map": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "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" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.45.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.28", + "license": "MIT", + "dependencies": { + "mime-db": "1.45.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-svg-data-uri": { + "version": "1.2.3", + "dev": true, + "license": "MIT" + }, + "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_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/mitt": { + "version": "3.0.0", + "license": "MIT" + }, + "node_modules/modify-values": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha1-5tq3/r9a2Bbqgc9cYpxaDr3nLBo=", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "resolve": "^1.20.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.3.5", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "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": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm": { + "version": "8.13.2", + "resolved": "https://registry.npmjs.org/npm/-/npm-8.13.2.tgz", + "integrity": "sha512-aS6q/QKxkw9mTX8gR7Ft38BcRkW1i+h3sI1yAFmfQ30Yl1a1G4ZX3oNGDzaLCilU5ThFZQBS1F4ZSZsrVxJ7HA==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/ci-detect", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/run-script", + "abbrev", + "archy", + "cacache", + "chalk", + "chownr", + "cli-columns", + "cli-table3", + "columnify", + "fastest-levenshtein", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minipass", + "minipass-pipeline", + "mkdirp", + "mkdirp-infer-owner", + "ms", + "node-gyp", + "nopt", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "npmlog", + "opener", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "read-package-json", + "read-package-json-fast", + "readdir-scoped-modules", + "rimraf", + "semver", + "ssri", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dev": true, + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^5.0.4", + "@npmcli/ci-detect": "^2.0.0", + "@npmcli/config": "^4.1.0", + "@npmcli/fs": "^2.1.0", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/package-json": "^2.0.0", + "@npmcli/run-script": "^4.1.5", + "abbrev": "~1.1.1", + "archy": "~1.0.0", + "cacache": "^16.1.1", + "chalk": "^4.1.2", + "chownr": "^2.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.2", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.12", + "glob": "^8.0.1", + "graceful-fs": "^4.2.10", + "hosted-git-info": "^5.0.0", + "ini": "^3.0.0", + "init-package-json": "^3.0.2", + "is-cidr": "^4.0.2", + "json-parse-even-better-errors": "^2.3.1", + "libnpmaccess": "^6.0.2", + "libnpmdiff": "^4.0.2", + "libnpmexec": "^4.0.2", + "libnpmfund": "^3.0.1", + "libnpmhook": "^8.0.2", + "libnpmorg": "^4.0.2", + "libnpmpack": "^4.0.2", + "libnpmpublish": "^6.0.2", + "libnpmsearch": "^5.0.2", + "libnpmteam": "^4.0.2", + "libnpmversion": "^3.0.1", + "make-fetch-happen": "^10.1.8", + "minipass": "^3.1.6", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "ms": "^2.1.2", + "node-gyp": "^9.0.0", + "nopt": "^5.0.0", + "npm-audit-report": "^3.0.0", + "npm-install-checks": "^5.0.0", + "npm-package-arg": "^9.0.2", + "npm-pick-manifest": "^7.0.1", + "npm-profile": "^6.1.0", + "npm-registry-fetch": "^13.1.1", + "npm-user-validate": "^1.0.1", + "npmlog": "^6.0.2", + "opener": "^1.5.2", + "pacote": "^13.6.1", + "parse-conflict-json": "^2.0.2", + "proc-log": "^2.0.1", + "qrcode-terminal": "^0.12.0", + "read": "~1.0.7", + "read-package-json": "^5.0.1", + "read-package-json-fast": "^2.0.3", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^9.0.1", + "tar": "^6.1.11", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^2.0.0", + "validate-npm-package-name": "^4.0.0", + "which": "^2.0.2", + "write-file-atomic": "^4.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/@colors/colors": { + "version": "1.5.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/npm/node_modules/@gar/promisify": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "5.2.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/metavuln-calculator": "^3.0.1", + "@npmcli/move-file": "^2.0.0", + "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/package-json": "^2.0.0", + "@npmcli/run-script": "^4.1.3", + "bin-links": "^3.0.0", + "cacache": "^16.0.6", + "common-ancestor-path": "^1.0.1", + "json-parse-even-better-errors": "^2.3.1", + "json-stringify-nice": "^1.1.4", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "nopt": "^5.0.0", + "npm-install-checks": "^5.0.0", + "npm-package-arg": "^9.0.0", + "npm-pick-manifest": "^7.0.0", + "npm-registry-fetch": "^13.0.0", + "npmlog": "^6.0.2", + "pacote": "^13.6.1", + "parse-conflict-json": "^2.0.1", + "proc-log": "^2.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.1", + "read-package-json-fast": "^2.0.2", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^9.0.0", + "treeverse": "^2.0.0", + "walk-up-path": "^1.0.0" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/ci-detect": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm/node_modules/@npmcli/config": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^2.0.2", + "ini": "^3.0.0", + "mkdirp-infer-owner": "^2.0.0", + "nopt": "^5.0.0", + "proc-log": "^2.0.0", + "read-package-json-fast": "^2.0.3", + "semver": "^7.3.5", + "walk-up-path": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/disparity-colors": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "ansi-styles": "^4.3.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^3.0.0", + "lru-cache": "^7.4.4", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^7.0.0", + "proc-log": "^2.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "1.0.7", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "installed-package-contents": "index.js" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^1.0.1", + "glob": "^8.0.1", + "minimatch": "^5.0.1", + "read-package-json-fast": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cacache": "^16.0.0", + "json-parse-even-better-errors": "^2.3.1", + "pacote": "^13.0.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/move-file": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^2.3.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "infer-owner": "^1.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "4.1.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/promise-spawn": "^3.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^2.0.3", + "which": "^2.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/@tootallnate/once": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/agent-base": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/npm/node_modules/agentkeepalive": { + "version": "4.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/are-we-there-yet": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm/node_modules/asap": { + "version": "2.0.6", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^5.0.0", + "mkdirp-infer-owner": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0", + "read-cmd-shim": "^3.0.0", + "rimraf": "^3.0.0", + "write-file-atomic": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/builtins": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "16.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^4.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cli-table3": { + "version": "0.6.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/npm/node_modules/clone": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "mkdirp-infer-owner": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/color-support": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/npm/node_modules/columnify": { + "version": "1.6.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/console-control-strings": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/debuglog": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/defaults": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/npm/node_modules/delegates": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/depd": { + "version": "1.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/dezalgo": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/npm/node_modules/diff": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.12", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/function-bind": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/gauge": { + "version": "4.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "8.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.10", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/has": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/npm/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/has-unicode": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm/node_modules/humanize-ms": { + "version": "1.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^5.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/infer-owner": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/npm/node_modules/inherits": { + "version": "2.0.4", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/ini": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^9.0.1", + "promzard": "^0.3.0", + "read": "^1.0.7", + "read-package-json": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/ip": { + "version": "1.1.8", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "^3.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/is-core-module": { + "version": "2.9.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-lambda": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff": { + "version": "5.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.2.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "6.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "minipass": "^3.1.1", + "npm-package-arg": "^9.0.1", + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "4.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/disparity-colors": "^2.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "binary-extensions": "^2.2.0", + "diff": "^5.0.0", + "minimatch": "^5.0.1", + "npm-package-arg": "^9.0.1", + "pacote": "^13.6.1", + "tar": "^6.1.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "4.0.8", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^5.0.0", + "@npmcli/ci-detect": "^2.0.0", + "@npmcli/run-script": "^4.1.3", + "chalk": "^4.1.0", + "mkdirp-infer-owner": "^2.0.0", + "npm-package-arg": "^9.0.1", + "npmlog": "^6.0.2", + "pacote": "^13.6.1", + "proc-log": "^2.0.0", + "read": "^1.0.7", + "read-package-json-fast": "^2.0.2", + "walk-up-path": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "8.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "4.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "4.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/run-script": "^4.1.3", + "npm-package-arg": "^9.0.1", + "pacote": "^13.6.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "6.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "normalize-package-data": "^4.0.0", + "npm-package-arg": "^9.0.1", + "npm-registry-fetch": "^13.0.0", + "semver": "^7.3.7", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "5.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "4.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "3.0.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^3.0.0", + "@npmcli/run-script": "^4.1.3", + "json-parse-even-better-errors": "^2.3.1", + "proc-log": "^2.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "7.9.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "10.1.8", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "5.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "3.1.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-json-stream": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/mkdirp-infer-owner": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "infer-owner": "^1.0.4", + "mkdirp": "^1.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "0.0.8", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/negotiator": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.22 || ^14.13 || >=16" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "1.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "9.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "5.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "glob": "^8.0.1", + "ignore-walk": "^5.0.1", + "npm-bundled": "^1.1.2", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "7.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^5.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "6.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "13.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "make-fetch-happen": "^10.0.6", + "minipass": "^3.1.6", + "minipass-fetch": "^2.0.3", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^9.0.1", + "proc-log": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/npmlog": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/once": { + "version": "1.4.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/npm/node_modules/opener": { + "version": "1.5.2", + "dev": true, + "inBundle": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/pacote": { + "version": "13.6.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^3.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/promise-spawn": "^3.0.0", + "@npmcli/run-script": "^4.1.0", + "cacache": "^16.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.6", + "mkdirp": "^1.0.4", + "npm-package-arg": "^9.0.0", + "npm-packlist": "^5.1.0", + "npm-pick-manifest": "^7.0.0", + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^5.0.0", + "read-package-json-fast": "^2.0.3", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^2.3.1", + "just-diff": "^5.0.1", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-inflight": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "0.3.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "read": "1" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "1.0.7", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "glob": "^8.0.1", + "json-parse-even-better-errors": "^2.3.1", + "normalize-package-data": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm/node_modules/readdir-scoped-modules": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm/node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/safe-buffer": { + "version": "5.2.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.3.7", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "3.0.7", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.6.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.3.0", + "dev": true, + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.11", + "dev": true, + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/ssri": { + "version": "9.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/string_decoder": { + "version": "1.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.1.11", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/treeverse": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/wcwidth": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/npm/node_modules/which": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/wide-align": { + "version": "1.1.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/npm/node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/nwsapi": { + "version": "2.2.0", + "license": "MIT" + }, + "node_modules/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, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-each-series": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-map": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-filter/node_modules/p-map": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-reduce": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "4.6.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/retry": "^0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "license": "MIT" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module/node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-path": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", + "dev": true, + "dependencies": { + "protocols": "^2.0.0" + } + }, + "node_modules/parse-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", + "dev": true, + "dependencies": { + "parse-path": "^7.0.0" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pdfkit": { + "version": "0.12.3", + "license": "MIT", + "dependencies": { + "crypto-js": "^4.0.0", + "fontkit": "^1.8.1", + "linebreak": "^1.0.2", + "png-js": "^1.0.0" + } + }, + "node_modules/pdfmake": { + "version": "0.2.2", + "license": "MIT", + "dependencies": { + "@foliojs-fork/linebreak": "^1.1.1", + "@foliojs-fork/pdfkit": "^0.12.3", + "iconv-lite": "^0.6.3", + "svg-to-pdfkit": "^0.1.8", + "xmldoc": "^1.1.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/pdfmake/node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==", + "dev": true, + "bin": { + "pegjs": "bin/pegjs" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "license": "ISC" + }, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-try": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/png-js": { + "version": "1.0.0" + }, + "node_modules/polylabel": { + "version": "1.1.0", + "license": "ISC", + "dependencies": { + "tinyqueue": "^2.0.3" + } + }, + "node_modules/postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", + "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.2.tgz", + "integrity": "sha512-c6Hzc4GAv95B7suy4udszX9Zy4ETyMCgFPUDtWjdFTKH1SE9eFY/jEpHSwTH1QPuwxHpWslhckUQWbNRM4ho5g==", + "dev": true, + "dependencies": { + "browserslist": "^4.20.3", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-properties": { + "version": "12.1.9", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.9.tgz", + "integrity": "sha512-/E7PRvK8DAVljBbeWrcEQJPG72jaImxF3vvCNFwv9cC8CzigVoNIpeyfnJzphnN3Fd8/auBf5wvkw6W9MfmTyg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "dev": true, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-import": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.0.0.tgz", + "integrity": "sha512-Y20shPQ07RitgBGv2zvkEAu9bqvrD77C9axhj/aA1BQj4czape2MdClCExvB27EwYEJdGgKZBpKanb0t1rK2Kg==", + "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/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.6.tgz", + "integrity": "sha512-6C/UGF/3T5OE2CEbOuX7iNO63dnvqhGZeUnKkDeifebY0XqkkvrctYSZurpNE902LDf2yKwwPFgotnfSoPhQiw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.2.tgz", + "integrity": "sha512-zKMUlnw+zYCWoPN6yhPjtcEdlJaMUZ0WyVcxTAmw3lkkN/NDMRkOkiuctQEoWAOvH7twaxUUdvBWl0d4+hifRQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dev": true, + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.3.tgz", + "integrity": "sha512-bkzpWcjykkqIujNL+EVEPOlLYi/eZ050oImVtHU7b4lFS82jPnsCb44gvC6pxaNt38Els3jWYDHTjHKf0koTgg==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-nested": { + "version": "5.0.6", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.6" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz", + "integrity": "sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dev": true, + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz", + "integrity": "sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==", + "dev": true, + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "engines": { + "node": "^12 || ^14 || >=16" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dev": true, + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-preset-env": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.2.tgz", + "integrity": "sha512-rSMUEaOCnovKnwc5LvBDHUDzpGP+nrUeWZGWt9M72fBvckCi45JmnJigUr4QG4zZeOHmOCNCZnd2LKDvP++ZuQ==", + "dev": true, + "dependencies": { + "@csstools/postcss-cascade-layers": "^1.1.0", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.11", + "browserslist": "^4.21.3", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.0.1", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.9", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz", + "integrity": "sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-reporter": { + "version": "7.0.5", + "dev": true, + "license": "MIT", + "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-resolve-nested-selector": { + "version": "0.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-organize-imports": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.1.1.tgz", + "integrity": "sha512-6bHIQzybqA644h0WGUW3gpWEVbMBvzui5wCMRBi7qA++d5ov2xjjfDk8pxJJ/ardfZrGAwizKMq/fQMFdJ+0Zw==", + "dev": true, + "peerDependencies": { + "@volar/vue-typescript": ">=0.40.2", + "prettier": ">=2.0", + "typescript": ">=2.9" + }, + "peerDependenciesMeta": { + "@volar/vue-typescript": { + "optional": true + } + } + }, + "node_modules/pretty-bytes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.0.0.tgz", + "integrity": "sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==", + "dev": true, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/printj": { + "version": "1.1.2", + "license": "Apache-2.0", + "bin": { + "printj": "bin/printj.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/protocols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/quote-stream": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "buffer-equal": "0.0.1", + "minimist": "^1.1.3", + "through2": "^2.0.0" + }, + "bin": { + "quote-stream": "bin/cmd.js" + } + }, + "node_modules/quote-stream/node_modules/through2": { + "version": "2.0.5", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/raf": { + "version": "3.4.1", + "license": "MIT", + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "dev": true, + "license": "ISC" + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/parse-json": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "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" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "dev": true, + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/redux": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.7", + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", + "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/regression": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/responselike": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restructure": { + "version": "0.5.4", + "license": "MIT", + "dependencies": { + "browserify-optional": "^1.0.0" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", + "engines": { + "node": ">= 0.8.15" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "2.75.7", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz", + "integrity": "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.1.9", + "dev": true, + "license": "MIT" + }, + "node_modules/rxjs": { + "version": "6.6.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.2.4", + "license": "ISC" + }, + "node_modules/saxes": { + "version": "5.0.1", + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/scope-analyzer": { + "version": "2.1.1", + "license": "Apache-2.0", + "dependencies": { + "array-from": "^2.1.1", + "dash-ast": "^1.0.0", + "es6-map": "^0.1.5", + "es6-set": "^0.1.5", + "es6-symbol": "^3.1.1", + "estree-is-function": "^1.0.0", + "get-assigned-identifiers": "^1.1.0" + } + }, + "node_modules/semantic-release": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.5.tgz", + "integrity": "sha512-NMPKdfpXTnPn49FDogMBi36SiBfXkSOJqCkk0E4iWOY1tusvvgBwqUmxTX1kmlT6kIYed9YwNKD1sfPpqa5yaA==", + "dev": true, + "dependencies": { + "@semantic-release/commit-analyzer": "^9.0.2", + "@semantic-release/error": "^3.0.0", + "@semantic-release/github": "^8.0.0", + "@semantic-release/npm": "^9.0.0", + "@semantic-release/release-notes-generator": "^10.0.0", + "aggregate-error": "^3.0.0", + "cosmiconfig": "^7.0.0", + "debug": "^4.0.0", + "env-ci": "^5.0.0", + "execa": "^5.0.0", + "figures": "^3.0.0", + "find-versions": "^4.0.0", + "get-stream": "^6.0.0", + "git-log-parser": "^1.2.0", + "hook-std": "^2.0.0", + "hosted-git-info": "^4.0.0", + "lodash": "^4.17.21", + "marked": "^4.0.10", + "marked-terminal": "^5.0.0", + "micromatch": "^4.0.2", + "p-each-series": "^2.1.0", + "p-reduce": "^2.0.0", + "read-pkg-up": "^7.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.3.2", + "semver-diff": "^3.1.1", + "signale": "^1.2.1", + "yargs": "^16.2.0" + }, + "bin": { + "semantic-release": "bin/semantic-release.js" + }, + "engines": { + "node": ">=16 || ^14.17" + } + }, + "node_modules/semantic-release/node_modules/figures": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/get-stream": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/semver": { + "version": "7.3.5", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-regex": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", + "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/shallow-copy": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/signale": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/signale/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi/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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/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" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/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/source-map": { + "version": "0.5.7", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "license": "MIT" + }, + "node_modules/spawn-error-forwarder": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.7", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ssf": { + "version": "0.11.2", + "license": "Apache-2.0", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "dev": true, + "license": "MIT" + }, + "node_modules/stackblur-canvas": { + "version": "2.5.0", + "license": "MIT", + "engines": { + "node": ">=0.1.14" + } + }, + "node_modules/static-eval": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "escodegen": "^1.11.1" + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.14.3", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/levn": { + "version": "0.3.0", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/optionator": { + "version": "0.8.3", + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/prelude-ls": { + "version": "1.1.2", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval/node_modules/type-check": { + "version": "0.3.2", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-module": { + "version": "3.0.4", + "license": "MIT", + "dependencies": { + "acorn-node": "^1.3.0", + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "^1.11.1", + "has": "^1.0.1", + "magic-string": "0.25.1", + "merge-source-map": "1.0.4", + "object-inspect": "^1.6.0", + "readable-stream": "~2.3.3", + "scope-analyzer": "^2.0.1", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.5", + "through2": "~2.0.3" + } + }, + "node_modules/static-module/node_modules/escodegen": { + "version": "1.14.3", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-module/node_modules/levn": { + "version": "0.3.0", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-module/node_modules/optionator": { + "version": "0.8.3", + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-module/node_modules/prelude-ls": { + "version": "1.1.2", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-module/node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-module/node_modules/through2": { + "version": "2.0.5", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/static-module/node_modules/type-check": { + "version": "0.3.2", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/stencil-wormhole": { + "version": "3.4.1", + "license": "MIT" + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "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, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/stringify-object/node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-mod": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", + "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==" + }, + "node_modules/style-search": { + "version": "0.1.0", + "dev": true, + "license": "ISC" + }, + "node_modules/stylehacks": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", + "integrity": "sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/stylelint": { + "version": "14.13.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz", + "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^7.0.1", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.2.0", + "ignore": "^5.2.0", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.25.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.16", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^2.3.0", + "svg-tags": "^1.0.0", + "table": "^6.8.0", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^4.0.2" + }, + "bin": { + "stylelint": "bin/stylelint.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-9.0.0.tgz", + "integrity": "sha512-9YQSrJq4NvvRuTbzDsWX3rrFOzOlYBmZP+o513BJN/yfEmGSr0AxdvrWs0P/ilSpVV/wisamAHu5XSk8Rcf4CQ==", + "dev": true, + "peerDependencies": { + "stylelint": "^14.10.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "28.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-28.0.0.tgz", + "integrity": "sha512-q/StuowDdDmFCravzGHAwgS9pjX0bdOQUEBBDIkIWsQuYGgYz/xsO8CM6eepmIQ1fc5bKdDVimlJZ6MoOUcJ5Q==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^9.0.0" + }, + "peerDependencies": { + "stylelint": "^14.11.0" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/stylelint/node_modules/global-modules": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stylelint/node_modules/global-prefix": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stylelint/node_modules/meow": { + "version": "9.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "dev": true + }, + "node_modules/svg-to-pdfkit": { + "version": "0.1.8", + "license": "MIT", + "dependencies": { + "pdfkit": ">=0.8.1" + } + }, + "node_modules/svgo": { + "version": "2.8.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "4.1.3", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^5.0.0", + "domhandler": "^4.2.0", + "domutils": "^2.6.0", + "nth-check": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/css-what": { + "version": "5.0.1", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domelementtype": { + "version": "2.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "4.2.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "2.7.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/svgo/node_modules/nth-check": { + "version": "2.0.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "license": "MIT" + }, + "node_modules/table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/table/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" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/table/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/table/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/tailwindcss": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz", + "integrity": "sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==", + "dev": true, + "dependencies": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.6", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.14", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/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/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss/node_modules/lilconfig": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/tailwindcss/node_modules/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/tailwindcss/node_modules/quick-lru": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", + "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", + "dev": true, + "dependencies": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", + "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/thenby": { + "version": "1.3.4", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/through": { + "version": "2.3.8", + "license": "MIT" + }, + "node_modules/through2": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/tinyqueue": { + "version": "2.0.3", + "license": "ISC" + }, + "node_modules/tmp": { + "version": "0.0.33", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "4.0.0", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/traverse": { + "version": "0.6.6", + "dev": true, + "license": "MIT" + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-node": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", + "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/tslib": { + "version": "1.13.0", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.18.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.14.5", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-properties": { + "version": "1.3.1", + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/universalify": { + "version": "0.1.2", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", + "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vite": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.8.6.tgz", + "integrity": "sha512-e4H0QpludOVKkmOsRyqQ7LTcMUDF3mcgyNU4lmi0B5JUbe0ZxeBBl8VoZ8Y6Rfn9eFKYtdXNPcYK97ZwH+K2ug==", + "dev": true, + "dependencies": { + "esbuild": "^0.14.14", + "postcss": "^8.4.6", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": ">=12.2.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + } + } + }, + "node_modules/vite-plugin-pwa": { + "version": "0.12.8", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.12.8.tgz", + "integrity": "sha512-pSiFHmnJGMQJJL8aJzQ8SaraZBSBPMGvGUkCNzheIq9UQCEk/eP3UmANNmS9eupuhIpTK8AdxTOHcaMcAqAbCA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "fast-glob": "^3.2.11", + "pretty-bytes": "^6.0.0", + "rollup": "^2.75.7", + "workbox-build": "^6.5.3", + "workbox-window": "^6.5.3" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.0.0 || ^3.0.0-0", + "workbox-build": "^6.4.0", + "workbox-window": "^6.4.0" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", + "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/wavesurfer.js": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-6.3.0.tgz", + "integrity": "sha512-x7efObHMHY3nwqWzIC0yeZTo0u/aC9T5Av6KhSdhTlsgtKdTG7JAE3mNqnYBXUjq0yGYfTB9F85/pks9830Vjw==" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "license": "MIT", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "node_modules/wmf": { + "version": "1.0.2", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.4.0", + "license": "Apache-2.0", + "dependencies": { + "cfb": "^1.2.0", + "jsdom": "^16.2.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "dev": true, + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "dev": true, + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.5.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dev": true, + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-build/node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workbox-build/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/workbox-build/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workbox-build/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/workbox-build/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==", + "dev": true + }, + "node_modules/workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "dev": true, + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "dev": true, + "dependencies": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "dev": true, + "dependencies": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "dev": true, + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "node_modules/workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==", + "dev": true + }, + "node_modules/workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "dev": true, + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.5", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xlsx": { + "version": "0.17.2", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.2.0", + "cfb": "^1.1.4", + "codepage": "~1.15.0", + "commander": "~2.17.1", + "crc-32": "~1.2.0", + "exit-on-epipe": "~1.0.1", + "fflate": "^0.3.8", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.4.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xlsx/node_modules/commander": { + "version": "2.17.1", + "license": "MIT" + }, + "node_modules/xml-formatter": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-2.6.1.tgz", + "integrity": "sha512-dOiGwoqm8y22QdTNI7A+N03tyVfBlQ0/oehAzxIZtwnFAHGeSlrfjF73YQvzSsa/Kt6+YZasKsrdu6OIpuBggw==", + "dependencies": { + "xml-parser-xo": "^3.2.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "license": "Apache-2.0" + }, + "node_modules/xml-parser-xo": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-3.2.0.tgz", + "integrity": "sha512-8LRU6cq+d7mVsoDaMhnkkt3CTtAs4153p49fRo+HIB3I1FD1o5CeXRjRH29sQevIfVJIcPjKSsPU/+Ujhq09Rg==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "license": "MIT" + }, + "node_modules/xmldoc": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "sax": "^1.2.1" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.7", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@amcharts/amcharts4": { + "version": "4.10.29", + "resolved": "https://registry.npmjs.org/@amcharts/amcharts4/-/amcharts4-4.10.29.tgz", + "integrity": "sha512-uDCvm4V0Xs2jtI0Aa7XFH0jqoyEGx9I2ukFEwaaQzYq11vwowhJsgE3sSv2jsfKETYUvPXb32NbzrXZulE2ESg==", + "requires": { + "@babel/runtime": "^7.6.3", + "core-js": "^3.0.0", + "d3-force": "^3.0.0", + "d3-geo": "^3.0.1", + "d3-geo-projection": "^4.0.0", + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1", + "pdfmake": "^0.2.2", + "polylabel": "^1.0.2", + "raf": "^3.4.1", + "regression": "^2.0.1", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "tslib": "^2.0.1", + "xlsx": "^0.17.0" + }, + "dependencies": { + "tslib": { + "version": "2.1.0" + } + } + }, + "@amcharts/amcharts4-geodata": { + "version": "4.1.23", + "resolved": "https://registry.npmjs.org/@amcharts/amcharts4-geodata/-/amcharts4-geodata-4.1.23.tgz", + "integrity": "sha512-/hFqTuc2SUB0tAgygc8yj1xvTUdddltI7/15fAT9L5XHGERgF8qAa+AisQQ0UMITvrWIr5awJupWE3vDTlWsjQ==" + }, + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz", + "integrity": "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ==", + "dev": true + }, + "@babel/core": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.6.tgz", + "integrity": "sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.6", + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helpers": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + } + }, + "@babel/generator": { + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", + "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", + "dev": true, + "requires": { + "@babel/types": "^7.18.7", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz", + "integrity": "sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", + "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz", + "integrity": "sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-member-expression-to-functions": "^7.18.6", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", + "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", + "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", + "dev": true + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-function-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", + "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", + "dev": true, + "requires": { + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz", + "integrity": "sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz", + "integrity": "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz", + "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz", + "integrity": "sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-wrap-function": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-replace-supers": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz", + "integrity": "sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-member-expression-to-functions": "^7.18.6", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.6.tgz", + "integrity": "sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz", + "integrity": "sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/helpers": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.6.tgz", + "integrity": "sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ==", + "dev": true, + "requires": { + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@babel/parser": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz", + "integrity": "sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw==", + "dev": true + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.6.tgz", + "integrity": "sha512-Udgu8ZRgrBrttVz6A0EVL0SJ1z+RLbIeqsu632SA1hf0awEppD6TvdznoH+orIF8wtFFAV/Enmw9Y+9oV8TQcw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.6" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz", + "integrity": "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", + "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.6.tgz", + "integrity": "sha512-zr/QcUlUo7GPo6+X1wC98NJADqmy5QTFWWhqeQWiki4XHafJtLl/YMGkmRB2szDD2IYJCCdBTd4ElwhId9T7Xw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.6.tgz", + "integrity": "sha512-zMo66azZth/0tVd7gmkxOkOjs2rpHyhpcFo565PUP37hSp6hSd9uUKIfTDFMz58BwqgQKhJ9YxtM5XddjXVn+Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.6.tgz", + "integrity": "sha512-9yuM6wr4rIsKa1wlUAbZEazkCrgw2sMPEXCr4Rnwetu7cEW1NydkCWytLuYletbf8vFxdJxFhwEZqMpOx2eZyw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.18.6", + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.6" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz", + "integrity": "sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", + "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", + "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", + "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", + "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.6.tgz", + "integrity": "sha512-pRqwb91C42vs1ahSAWJkxOxU1RHWDn16XAa6ggQ72wjLlWyYeAcLvTtE0aM8ph3KNydy9CQF2nLYcjq1WysgxQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.6.tgz", + "integrity": "sha512-XTg8XW/mKpzAF3actL554Jl/dOYoJtv3l8fxaEczpgz84IeeVf+T1u2CSvPHuZbt0w3JkIx4rdn/MRQI7mo0HQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.6.tgz", + "integrity": "sha512-9repI4BhNrR0KenoR9vm3/cIc1tSBIo+u1WVjKCAynahj25O8zfbiE6JtAtHPGQSs4yZ+bA8mRasRP+qc+2R5A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.6.tgz", + "integrity": "sha512-tgy3u6lRp17ilY8r1kP4i2+HDUwxlVqq3RTc943eAWSzGgpU1qhiKpqZ5CMyHReIYPHdo3Kg8v8edKtDqSVEyQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.6.tgz", + "integrity": "sha512-NJU26U/208+sxYszf82nmGYqVF9QN8py2HFTblPT9hbawi8+1C5a9JubODLTGFuT0qlkqVinmkwOD13s0sZktg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.6.tgz", + "integrity": "sha512-WAjoMf4wIiSsy88KmG7tgj2nFdEK7E46tArVtcgED7Bkj6Fg/tG5SbvNIOKxbFS2VFgNh6+iaPswBeQZm4ox8w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.6.tgz", + "integrity": "sha512-kJha/Gbs5RjzIu0CxZwf5e3aTTSlhZnHMT8zPWnJMjNpLOUgqevg+PN5oMH68nMCXnfiMo4Bhgxqj59KHTlAnA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.6.tgz", + "integrity": "sha512-x3HEw0cJZVDoENXOp20HlypIHfl0zMIhMVZEBVTfmqbObIpsMxMbmU5nOEO8R7LYT+z5RORKPlTI5Hj4OsO9/Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", + "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", + "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.6.tgz", + "integrity": "sha512-UbPYpXxLjTw6w6yXX2BYNxF3p6QY225wcTkfQCy3OMnSlS/C3xGtwUjEzGkldb/sy6PWLiCQ3NbYfjWUTI3t4g==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", + "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.6.tgz", + "integrity": "sha512-FjdqgMv37yVl/gwvzkcB+wfjRI8HQmc5EgOG9iGNvUY1ok+TjsoaMP7IqCDZBhkFcM5f3OPVMs6Dmp03C5k4/A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", + "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "regenerator-transform": "^0.15.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.6.tgz", + "integrity": "sha512-ayT53rT/ENF8WWexIRg9AiV9h0aIteyWn5ptfZTZQrjk/+f3WdrJGCY4c9wcgl2+MKkKPhzbYp97FTsquZpDCw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.6" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.6.tgz", + "integrity": "sha512-UuqlRrQmT2SWRvahW46cGSany0uTlcj8NYOS5sRGYi8FxPYPoLd5DDmMd32ZXEj2Jq+06uGVQKHxa/hJx2EzKw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.6.tgz", + "integrity": "sha512-7m71iS/QhsPk85xSjFPovHPcH3H9qeyzsujhTc+vcdnsXavoWYJ74zx0lP5RhpC5+iDnVLO+PPMHzC11qels1g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz", + "integrity": "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/preset-env": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.6.tgz", + "integrity": "sha512-WrthhuIIYKrEFAwttYzgRNQ5hULGmwTj+D6l7Zdfsv5M7IWV/OZbUfbeL++Qrzx1nVJwWROIFhCHRYQV4xbPNw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.18.6", + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.6", + "@babel/plugin-proposal-async-generator-functions": "^7.18.6", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.6", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.6", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.18.6", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.6", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.18.6", + "@babel/plugin-transform-classes": "^7.18.6", + "@babel/plugin-transform-computed-properties": "^7.18.6", + "@babel/plugin-transform-destructuring": "^7.18.6", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.6", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.6", + "@babel/plugin-transform-function-name": "^7.18.6", + "@babel/plugin-transform-literals": "^7.18.6", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.18.6", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.6", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.18.6", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.6", + "@babel/plugin-transform-typeof-symbol": "^7.18.6", + "@babel/plugin-transform-unicode-escapes": "^7.18.6", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.6", + "babel-plugin-polyfill-corejs2": "^0.3.1", + "babel-plugin-polyfill-corejs3": "^0.5.2", + "babel-plugin-polyfill-regenerator": "^0.3.1", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz", + "integrity": "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/traverse": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz", + "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz", + "integrity": "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@codemirror/commands": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.2.tgz", + "integrity": "sha512-sO3jdX1s0pam6lIdeSJLMN3DQ6mPEbM4yLvyKkdqtmd/UDwhXA5+AwFJ89rRXm6vTeOXBsE5cAmlos/t7MJdgg==", + "requires": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "@codemirror/lang-xml": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.0.0.tgz", + "integrity": "sha512-M/HLWxIiP956xGjtrxkeHkCmDGVQGKu782x8pOH5CLJIMkWtiB1DWfDoDHqpFjdEE9dkfcqPWvYfVi6GbhuXEg==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + }, + "dependencies": { + "@codemirror/autocomplete": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.0.2.tgz", + "integrity": "sha512-9PDjnllmXan/7Uax87KGORbxerDJ/cu10SB+n4Jz0zXMEvIh3+TGgZxhIvDOtaQ4jDBQEM7kHYW4vLdQB0DGZQ==", + "requires": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + } + } + }, + "@codemirror/language": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.2.1.tgz", + "integrity": "sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "@codemirror/state": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz", + "integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==" + }, + "@codemirror/view": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.0.2.tgz", + "integrity": "sha512-mnVT/q1JvKPjpmjXJNeCi/xHyaJ3abGJsumIVpdQ1nE1MXAyHf7GHWt8QpWMUvDiqF0j+inkhVR2OviTdFFX7Q==", + "requires": { + "@codemirror/state": "^6.0.0", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, + "@commitlint/cli": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.1.2.tgz", + "integrity": "sha512-h/4Hlka3bvCLbnxf0Er2ri5A44VMlbMSkdTRp8Adv2tRiklSTRIoPGs7OEXDv3EoDs2AAzILiPookgM4Gi7LOw==", + "dev": true, + "requires": { + "@commitlint/format": "^17.0.0", + "@commitlint/lint": "^17.1.0", + "@commitlint/load": "^17.1.2", + "@commitlint/read": "^17.1.0", + "@commitlint/types": "^17.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.19", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "dependencies": { + "yargs": { + "version": "17.3.0", + "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.0", + "dev": true + } + } + }, + "@commitlint/config-conventional": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.1.0.tgz", + "integrity": "sha512-WU2p0c9/jLi8k2q2YrDV96Y8XVswQOceIQ/wyJvQxawJSCasLdRB3kUIYdNjOCJsxkpoUlV/b90ZPxp1MYZDiA==", + "dev": true, + "requires": { + "conventional-changelog-conventionalcommits": "^5.0.0" + } + }, + "@commitlint/config-validator": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.1.0.tgz", + "integrity": "sha512-Q1rRRSU09ngrTgeTXHq6ePJs2KrI+axPTgkNYDWSJIuS1Op4w3J30vUfSXjwn5YEJHklK3fSqWNHmBhmTR7Vdg==", + "dev": true, + "requires": { + "@commitlint/types": "^17.0.0", + "ajv": "^8.11.0" + } + }, + "@commitlint/ensure": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.0.0.tgz", + "integrity": "sha512-M2hkJnNXvEni59S0QPOnqCKIK52G1XyXBGw51mvh7OXDudCmZ9tZiIPpU882p475Mhx48Ien1MbWjCP1zlyC0A==", + "dev": true, + "requires": { + "@commitlint/types": "^17.0.0", + "lodash": "^4.17.19" + } + }, + "@commitlint/execute-rule": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.0.0.tgz", + "integrity": "sha512-nVjL/w/zuqjCqSJm8UfpNaw66V9WzuJtQvEnCrK4jDw6qKTmZB+1JQ8m6BQVZbNBcwfYdDNKnhIhqI0Rk7lgpQ==", + "dev": true + }, + "@commitlint/format": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.0.0.tgz", + "integrity": "sha512-MZzJv7rBp/r6ZQJDEodoZvdRM0vXu1PfQvMTNWFb8jFraxnISMTnPBWMMjr2G/puoMashwaNM//fl7j8gGV5lA==", + "dev": true, + "requires": { + "@commitlint/types": "^17.0.0", + "chalk": "^4.1.0" + } + }, + "@commitlint/is-ignored": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.1.0.tgz", + "integrity": "sha512-JITWKDMHhIh8IpdIbcbuH9rEQJty1ZWelgjleTFrVRAcEwN/sPzk1aVUXRIZNXMJWbZj8vtXRJnFihrml8uECQ==", + "dev": true, + "requires": { + "@commitlint/types": "^17.0.0", + "semver": "7.3.7" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@commitlint/lint": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.1.0.tgz", + "integrity": "sha512-ltpqM2ogt/+SDhUaScFo0MdscncEF96lvQTPMM/VTTWlw7sTGLLWkOOppsee2MN/uLNNWjQ7kqkd4h6JqoM9AQ==", + "dev": true, + "requires": { + "@commitlint/is-ignored": "^17.1.0", + "@commitlint/parse": "^17.0.0", + "@commitlint/rules": "^17.0.0", + "@commitlint/types": "^17.0.0" + } + }, + "@commitlint/load": { + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.1.2.tgz", + "integrity": "sha512-sk2p/jFYAWLChIfOIp/MGSIn/WzZ0vkc3afw+l4X8hGEYkvDe4gQUUAVxjl/6xMRn0HgnSLMZ04xXh5pkTsmgg==", + "dev": true, + "requires": { + "@commitlint/config-validator": "^17.1.0", + "@commitlint/execute-rule": "^17.0.0", + "@commitlint/resolve-extends": "^17.1.0", + "@commitlint/types": "^17.0.0", + "@types/node": "^14.0.0", + "chalk": "^4.1.0", + "cosmiconfig": "^7.0.0", + "cosmiconfig-typescript-loader": "^4.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "ts-node": "^10.8.1", + "typescript": "^4.6.4" + }, + "dependencies": { + "@types/node": { + "version": "14.18.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.26.tgz", + "integrity": "sha512-0b+utRBSYj8L7XAp0d+DX7lI4cSmowNaaTkk6/1SKzbKkG+doLuPusB9EOvzLJ8ahJSk03bTLIL6cWaEd4dBKA==", + "dev": true + } + } + }, + "@commitlint/message": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.0.0.tgz", + "integrity": "sha512-LpcwYtN+lBlfZijHUdVr8aNFTVpHjuHI52BnfoV01TF7iSLnia0jttzpLkrLmI8HNQz6Vhr9UrxDWtKZiMGsBw==", + "dev": true + }, + "@commitlint/parse": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.0.0.tgz", + "integrity": "sha512-cKcpfTIQYDG1ywTIr5AG0RAiLBr1gudqEsmAGCTtj8ffDChbBRxm6xXs2nv7GvmJN7msOt7vOKleLvcMmRa1+A==", + "dev": true, + "requires": { + "@commitlint/types": "^17.0.0", + "conventional-changelog-angular": "^5.0.11", + "conventional-commits-parser": "^3.2.2" + } + }, + "@commitlint/read": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.1.0.tgz", + "integrity": "sha512-73BoFNBA/3Ozo2JQvGsE0J8SdrJAWGfZQRSHqvKaqgmY042Su4gXQLqvAzgr55S9DI1l9TiU/5WDuh8IE86d/g==", + "dev": true, + "requires": { + "@commitlint/top-level": "^17.0.0", + "@commitlint/types": "^17.0.0", + "fs-extra": "^10.0.0", + "git-raw-commits": "^2.0.0", + "minimist": "^1.2.6" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "@commitlint/resolve-extends": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.1.0.tgz", + "integrity": "sha512-jqKm00LJ59T0O8O4bH4oMa4XyJVEOK4GzH8Qye9XKji+Q1FxhZznxMV/bDLyYkzbTodBt9sL0WLql8wMtRTbqQ==", + "dev": true, + "requires": { + "@commitlint/config-validator": "^17.1.0", + "@commitlint/types": "^17.0.0", + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + } + }, + "@commitlint/rules": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.0.0.tgz", + "integrity": "sha512-45nIy3dERKXWpnwX9HeBzK5SepHwlDxdGBfmedXhL30fmFCkJOdxHyOJsh0+B0RaVsLGT01NELpfzJUmtpDwdQ==", + "dev": true, + "requires": { + "@commitlint/ensure": "^17.0.0", + "@commitlint/message": "^17.0.0", + "@commitlint/to-lines": "^17.0.0", + "@commitlint/types": "^17.0.0", + "execa": "^5.0.0" + } + }, + "@commitlint/to-lines": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.0.0.tgz", + "integrity": "sha512-nEi4YEz04Rf2upFbpnEorG8iymyH7o9jYIVFBG1QdzebbIFET3ir+8kQvCZuBE5pKCtViE4XBUsRZz139uFrRQ==", + "dev": true + }, + "@commitlint/top-level": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.0.0.tgz", + "integrity": "sha512-dZrEP1PBJvodNWYPOYiLWf6XZergdksKQaT6i1KSROLdjf5Ai0brLOv5/P+CPxBeoj3vBxK4Ax8H1Pg9t7sHIQ==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + } + } + }, + "@commitlint/types": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.0.0.tgz", + "integrity": "sha512-hBAw6U+SkAT5h47zDMeOu3HSiD0SODw4Aq7rRNh1ceUmL7GyLKYhPbUvlRWqZ65XjBLPHZhFyQlRaPNz8qvUyQ==", + "dev": true, + "requires": { + "chalk": "^4.1.0" + } + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "dev": true, + "requires": {} + }, + "@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true, + "requires": {} + }, + "@eslint/eslintrc": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "@floating-ui/core": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.0.1.tgz", + "integrity": "sha512-bO37brCPfteXQfFY0DyNDGB3+IMe4j150KFQcgJ5aBP295p9nBGeHEs/p0czrRbtlHq4Px/yoPXO/+dOCcF4uA==" + }, + "@floating-ui/dom": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.0.2.tgz", + "integrity": "sha512-5X9WSvZ8/fjy3gDu8yx9HAA4KG1lazUN2P4/VnaXLxTO9Dz53HI1oYoh1OlhqFNlHgGDiwFX5WhFCc2ljbW3yA==", + "requires": { + "@floating-ui/core": "^1.0.1" + } + }, + "@foliojs-fork/fontkit": { + "version": "1.9.1", + "requires": { + "@foliojs-fork/restructure": "^2.0.2", + "brfs": "^2.0.0", + "brotli": "^1.2.0", + "browserify-optional": "^1.0.1", + "clone": "^1.0.4", + "deep-equal": "^1.0.0", + "dfa": "^1.2.0", + "tiny-inflate": "^1.0.2", + "unicode-properties": "^1.2.2", + "unicode-trie": "^2.0.0" + } + }, + "@foliojs-fork/linebreak": { + "version": "1.1.1", + "requires": { + "base64-js": "1.3.1", + "brfs": "^2.0.2", + "unicode-trie": "^2.0.0" + } + }, + "@foliojs-fork/pdfkit": { + "version": "0.12.3", + "requires": { + "@foliojs-fork/fontkit": "^1.9.1", + "@foliojs-fork/linebreak": "^1.1.1", + "crypto-js": "^4.0.0", + "png-js": "^1.0.0" + } + }, + "@foliojs-fork/restructure": { + "version": "2.0.2" + }, + "@github/clipboard-copy-element": { + "version": "1.1.2" + }, + "@github/hotkey": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@github/hotkey/-/hotkey-2.0.1.tgz", + "integrity": "sha512-qKXjAJjtheJbf4ie3hi8IwrHWJZHB5qdojR6JGo6jvQNPpsdUbk/NIdU8sxu4PW41CjW80vfciDMu3MAP3j2Fg==" + }, + "@github/markdown-toolbar-element": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@github/markdown-toolbar-element/-/markdown-toolbar-element-2.1.1.tgz", + "integrity": "sha512-J++rpd5H9baztabJQB82h26jtueOeBRSTqetk9Cri+Lj/s28ndu6Tovn0uHQaOKtBWDobFunk9b5pP5vcqt7cA==" + }, + "@github/time-elements": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@github/time-elements/-/time-elements-3.1.4.tgz", + "integrity": "sha512-DTe/w0uKVeciKzGtYadNdfS8D86pXdGF+OrKg+vi8PKlotJ45zAc26zNpmmfCcMblBBg2+uoi3OxmUm7am/0sg==" + }, + "@humanwhocodes/config-array": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", + "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", + "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "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/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@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 + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@lezer/common": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.0.tgz", + "integrity": "sha512-ohydQe+Hb+w4oMDvXzs8uuJd2NoA3D8YDcLiuDsLqH+yflDTPEpgCsWI3/6rH5C3BAedtH1/R51dxENldQceEA==" + }, + "@lezer/highlight": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.0.0.tgz", + "integrity": "sha512-nsCnNtim90UKsB5YxoX65v3GEIw3iCHw9RM2DtdgkiqAbKh9pCdvi8AWNwkYf10Lu6fxNhXPpkpHbW6mihhvJA==", + "requires": { + "@lezer/common": "^1.0.0" + } + }, + "@lezer/lr": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.1.0.tgz", + "integrity": "sha512-Iad04uVwk1PvSnj25mqj7zEEIRAsasbsTRmVzI0AUTs/+1Dz1//iYAaoLr7A+Xa7bZDfql5MKTxZmSlkYZD3Dg==", + "requires": { + "@lezer/common": "^1.0.0" + } + }, + "@lezer/xml": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.0.tgz", + "integrity": "sha512-73iI9UK8iqSvWtLlOEl/g+50ivwQn8Ge6foHVN66AXUS1RccFnAoc7BYU8b3c8/rP6dfCOGqAGaWLxBzhj60MA==", + "requires": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "@lit/reactive-element": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.4.1.tgz", + "integrity": "sha512-qDv4851VFSaBWzpS02cXHclo40jsbAjRXnebNXpm0uVg32kCneZPo9RYVQtrTNICtZ+1wAYHu1ZtxWSWMbKrBw==" + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@octokit/auth-token": { + "version": "2.5.0", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.5.1", + "dev": true, + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.0", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "dev": true, + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "11.2.0", + "dev": true + }, + "@octokit/plugin-paginate-rest": { + "version": "2.17.0", + "dev": true, + "requires": { + "@octokit/types": "^6.34.0" + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.4", + "dev": true, + "requires": {} + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "5.13.0", + "dev": true, + "requires": { + "@octokit/types": "^6.34.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.6.2", + "dev": true, + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "18.12.0", + "dev": true, + "requires": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "@octokit/types": { + "version": "6.34.0", + "dev": true, + "requires": { + "@octokit/openapi-types": "^11.2.0" + } + }, + "@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + } + }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + } + }, + "@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "dependencies": { + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + } + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "@semantic-release/changelog": { + "version": "6.0.1", + "dev": true, + "requires": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "fs-extra": "^9.0.0", + "lodash": "^4.17.4" + } + }, + "@semantic-release/commit-analyzer": { + "version": "9.0.2", + "dev": true, + "requires": { + "conventional-changelog-angular": "^5.0.0", + "conventional-commits-filter": "^2.0.0", + "conventional-commits-parser": "^3.2.3", + "debug": "^4.0.0", + "import-from": "^4.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.2" + }, + "dependencies": { + "import-from": { + "version": "4.0.0", + "dev": true + } + } + }, + "@semantic-release/error": { + "version": "3.0.0", + "dev": true + }, + "@semantic-release/exec": { + "version": "6.0.3", + "dev": true, + "requires": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "parse-json": "^5.0.0" + }, + "dependencies": { + "parse-json": { + "version": "5.1.0", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + } + } + }, + "@semantic-release/git": { + "version": "10.0.1", + "dev": true, + "requires": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.0", + "p-reduce": "^2.0.0" + } + }, + "@semantic-release/github": { + "version": "8.0.2", + "dev": true, + "requires": { + "@octokit/rest": "^18.0.0", + "@semantic-release/error": "^2.2.0", + "aggregate-error": "^3.0.0", + "bottleneck": "^2.18.1", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "fs-extra": "^10.0.0", + "globby": "^11.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "issue-parser": "^6.0.0", + "lodash": "^4.17.4", + "mime": "^3.0.0", + "p-filter": "^2.0.0", + "p-retry": "^4.0.0", + "url-join": "^4.0.0" + }, + "dependencies": { + "@semantic-release/error": { + "version": "2.2.0", + "dev": true + }, + "@tootallnate/once": { + "version": "2.0.0", + "dev": true + }, + "fs-extra": { + "version": "10.0.0", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "http-proxy-agent": { + "version": "5.0.0", + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "universalify": { + "version": "2.0.0", + "dev": true + } + } + }, + "@semantic-release/gitlab": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@semantic-release/gitlab/-/gitlab-9.4.2.tgz", + "integrity": "sha512-ZfMe4N613C/tqfRdxDPprOoBA7HHyHFHvk+TA4HqOmNpgUKiifyJPpYJsc3PLNtec9I0TA1OOTuY82VDG+FVXw==", + "dev": true, + "requires": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "escape-string-regexp": "^3.0.0", + "form-data": "^4.0.0", + "fs-extra": "^10.0.0", + "globby": "^11.0.0", + "got": "^11.0.0", + "hpagent": "^1.0.0", + "lodash": "^4.17.11", + "parse-url": "^8.0.0", + "url-join": "^4.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "3.0.0", + "dev": true + }, + "form-data": { + "version": "4.0.0", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fs-extra": { + "version": "10.0.0", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "dev": true + } + } + }, + "@semantic-release/npm": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.0.tgz", + "integrity": "sha512-hj2jqayS2SPUmFtCMCOQMX975uMDfRoymj1HvMSwYdaoI6hVZvhrTFPBgJeM85O0C+G3IFviAUar5gel/1VGDQ==", + "dev": true, + "requires": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "execa": "^5.0.0", + "fs-extra": "^10.0.0", + "lodash": "^4.17.15", + "nerf-dart": "^1.0.0", + "normalize-url": "^6.0.0", + "npm": "^8.3.0", + "rc": "^1.2.8", + "read-pkg": "^5.0.0", + "registry-auth-token": "^4.0.0", + "semver": "^7.1.2", + "tempy": "^1.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "@semantic-release/release-notes-generator": { + "version": "10.0.3", + "dev": true, + "requires": { + "conventional-changelog-angular": "^5.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-filter": "^2.0.0", + "conventional-commits-parser": "^3.2.3", + "debug": "^4.0.0", + "get-stream": "^6.0.0", + "import-from": "^4.0.0", + "into-stream": "^6.0.0", + "lodash": "^4.17.4", + "read-pkg-up": "^7.0.0" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "dev": true + }, + "import-from": { + "version": "4.0.0", + "dev": true + } + } + }, + "@sindresorhus/is": { + "version": "4.2.0", + "dev": true + }, + "@stencil/core": { + "version": "2.5.2" + }, + "@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dev": true, + "requires": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@tailwindcss/forms": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz", + "integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==", + "dev": true, + "requires": { + "mini-svg-data-uri": "^1.2.3" + } + }, + "@tailwindcss/line-clamp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz", + "integrity": "sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==", + "dev": true, + "requires": {} + }, + "@tailwindcss/nesting": { + "version": "0.0.0-insiders.565cd3e", + "resolved": "https://registry.npmjs.org/@tailwindcss/nesting/-/nesting-0.0.0-insiders.565cd3e.tgz", + "integrity": "sha512-WhHoFBx19TnH/c+xLwT/sxei6+4RpdfiyG3MYXfmLaMsADmVqBkF7B6lDalgZD9YdM459MF7DtxVbWkOrV7IaQ==", + "requires": { + "postcss-nested": "^5.0.5" + } + }, + "@tailwindcss/typography": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.7.tgz", + "integrity": "sha512-JTTSTrgZfp6Ki4svhPA4mkd9nmQ/j9EfE7SbHJ1cLtthKkpW2OxsFXzSmxbhYbEkfNIyAyhle5p4SYyKRbz/jg==", + "dev": true, + "requires": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + } + }, + "@tootallnate/once": { + "version": "1.1.2" + }, + "@trysound/sax": { + "version": "0.2.0", + "dev": true + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "@types/cacheable-request": { + "version": "6.0.2", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "dev": true + }, + "@types/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-epMsEE85fi4lfmJUH/89/iV/LI+F5CvNIvmgs5g5jYFPfhO2S/ae8WSsLOKWdwtoaZw9Q2IhJ4tQ5tFCcS/4HA==", + "dev": true + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/fscreen": { + "version": "1.0.1" + }, + "@types/geojson": { + "version": "7946.0.8", + "dev": true + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/keyv": { + "version": "3.1.3", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/leaflet": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.8.0.tgz", + "integrity": "sha512-+sXFmiJTFdhaXXIGFlV5re9AdqtAODoXbGAvxx02e5SHXL3ir7ClP5J7pahO8VmzKY3dth4RUS1nf2BTT+DW1A==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, + "@types/marked": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.0.7.tgz", + "integrity": "sha512-eEAhnz21CwvKVW+YvRvcTuFKNU9CV1qH+opcgVK3pIMI6YZzDm6gc8o2vHjldFk6MGKt5pueSB7IOpvpx5Qekw==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.1", + "dev": true + }, + "@types/node": { + "version": "17.0.5", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "dev": true + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/responselike": { + "version": "1.0.0", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/retry": { + "version": "0.12.1", + "dev": true + }, + "@types/trusted-types": { + "version": "2.0.2" + }, + "@types/wavesurfer.js": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/wavesurfer.js/-/wavesurfer.js-6.0.3.tgz", + "integrity": "sha512-5Sb5s3pEkOmDosaaP1DWp1Unnx8HhVorm5608TIVdT5jCMvJ6eqM19UD8n7DEbJ7rzreS9RqHmzR8TlcdQBvbA==", + "dev": true, + "requires": { + "@types/debounce": "*" + } + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.0.tgz", + "integrity": "sha512-FIBZgS3DVJgqPwJzvZTuH4HNsZhHMa9SjxTKAZTlMsPw/UzpEjcf9f4dfgDJEHjK+HboUJo123Eshl6niwEm/Q==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.40.0", + "@typescript-eslint/type-utils": "5.40.0", + "@typescript-eslint/utils": "5.40.0", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.0.tgz", + "integrity": "sha512-Ah5gqyX2ySkiuYeOIDg7ap51/b63QgWZA7w6AHtFrag7aH0lRQPbLzUjk0c9o5/KZ6JRkTTDKShL4AUrQa6/hw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.40.0", + "@typescript-eslint/types": "5.40.0", + "@typescript-eslint/typescript-estree": "5.40.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.0.tgz", + "integrity": "sha512-d3nPmjUeZtEWRvyReMI4I1MwPGC63E8pDoHy0BnrYjnJgilBD3hv7XOiETKLY/zTwI7kCnBDf2vWTRUVpYw0Uw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.40.0", + "@typescript-eslint/visitor-keys": "5.40.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.0.tgz", + "integrity": "sha512-nfuSdKEZY2TpnPz5covjJqav+g5qeBqwSHKBvz7Vm1SAfy93SwKk/JeSTymruDGItTwNijSsno5LhOHRS1pcfw==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.40.0", + "@typescript-eslint/utils": "5.40.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.0.tgz", + "integrity": "sha512-V1KdQRTXsYpf1Y1fXCeZ+uhjW48Niiw0VGt4V8yzuaDTU8Z1Xl7yQDyQNqyAFcVhpYXIVCEuxSIWTsLDpHgTbw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.0.tgz", + "integrity": "sha512-b0GYlDj8TLTOqwX7EGbw2gL5EXS2CPEWhF9nGJiGmEcmlpNBjyHsTwbqpyIEPVpl6br4UcBOYlcI2FJVtJkYhg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.40.0", + "@typescript-eslint/visitor-keys": "5.40.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.0.tgz", + "integrity": "sha512-MO0y3T5BQ5+tkkuYZJBjePewsY+cQnfkYeRqS6tPh28niiIwPnQ1t59CSRcs1ZwJJNOdWw7rv9pF8aP58IMihA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.40.0", + "@typescript-eslint/types": "5.40.0", + "@typescript-eslint/typescript-estree": "5.40.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.40.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.0.tgz", + "integrity": "sha512-ijJ+6yig+x9XplEpG2K6FUdJeQGGj/15U3S56W9IqXKJqleuD7zJ2AX/miLezwxpd7ZxDAqO87zWufKg+RPZyQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.40.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@vime/core": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@vime/core/-/core-5.3.3.tgz", + "integrity": "sha512-bGn6bwiOwI/0d+P+gLH9U3ySK4tar6Qiv7g+RR+c7iuCsl0S16/wP1G677PiglJTvM3wuo2wD3hztMEkiWfvhw==", + "requires": { + "@stencil/core": "2.5.2", + "@types/fscreen": "^1.0.1", + "fscreen": "^1.2.0", + "mitt": "^3.0.0", + "stencil-wormhole": "^3.4.1" + } + }, + "abab": { + "version": "2.0.5" + }, + "acorn": { + "version": "7.4.1" + }, + "acorn-globals": { + "version": "6.0.0", + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-node": { + "version": "1.8.2", + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "acorn-walk": { + "version": "7.2.0" + }, + "adler-32": { + "version": "1.2.0", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "agent-base": { + "version": "6.0.2", + "requires": { + "debug": "4" + } + }, + "aggregate-error": { + "version": "3.1.0", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "all-contributors-cli": { + "version": "6.24.0", + "resolved": "https://registry.npmjs.org/all-contributors-cli/-/all-contributors-cli-6.24.0.tgz", + "integrity": "sha512-7oSKr2PnqxsOotuSwciltcFTS1eVRdjR0cn99hbElfff7gRQBShVhsf/XBprY41sLcgqTk0l0MKgKv6QNgZdMg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.6", + "async": "^3.1.0", + "chalk": "^4.0.0", + "didyoumean": "^1.2.1", + "inquirer": "^7.3.3", + "json-fixer": "^1.6.8", + "lodash": "^4.11.2", + "node-fetch": "^2.6.0", + "pify": "^5.0.0", + "yargs": "^15.0.1" + }, + "dependencies": { + "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": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.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 + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + } + }, + "pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "dev": true + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "amdefine": { + "version": "1.0.1", + "optional": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "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 + }, + "ansi-styles": { + "version": "3.2.1", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", + "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 + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "argv-formatter": { + "version": "1.0.0", + "dev": true + }, + "array-from": { + "version": "2.1.1" + }, + "array-ify": { + "version": "1.0.0", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "dev": true + }, + "ast-transform": { + "version": "0.0.0", + "requires": { + "escodegen": "~1.2.0", + "esprima": "~1.0.4", + "through": "~2.3.4" + }, + "dependencies": { + "esprima": { + "version": "1.0.4" + } + } + }, + "ast-types": { + "version": "0.7.8" + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0" + }, + "at-least-node": { + "version": "1.0.0", + "dev": true + }, + "autoprefixer": { + "version": "10.4.12", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.12.tgz", + "integrity": "sha512-WrCGV9/b97Pa+jtwf5UGaRjgQIg7OK3D06GnoYoZNcG1Xb8Gt3EfuKjlhh9i/VtT16g6PYjZ69jdJ2g8FxSC4Q==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "caniuse-lite": "^1.0.30001407", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + } + }, + "babel-runtime": { + "version": "6.26.0", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.12" + }, + "regenerator-runtime": { + "version": "0.11.1" + } + } + }, + "balanced-match": { + "version": "1.0.0", + "dev": true + }, + "base64-js": { + "version": "1.3.1" + }, + "before-after-hook": { + "version": "2.2.2", + "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 + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "boolbase": { + "version": "1.0.0", + "dev": true + }, + "bottleneck": { + "version": "2.19.5", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brfs": { + "version": "2.0.2", + "requires": { + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^3.0.2", + "through2": "^2.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "brotli": { + "version": "1.3.2", + "requires": { + "base64-js": "^1.1.2" + } + }, + "browser-process-hrtime": { + "version": "1.0.0" + }, + "browser-resolve": { + "version": "1.11.3", + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7" + } + } + }, + "browserify-optional": { + "version": "1.0.1", + "requires": { + "ast-transform": "0.0.0", + "ast-types": "^0.7.0", + "browser-resolve": "^1.8.1" + } + }, + "browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-equal": { + "version": "0.0.1" + }, + "buffer-from": { + "version": "1.1.2" + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true + }, + "cacheable-lookup": { + "version": "5.0.4", + "dev": true + }, + "cacheable-request": { + "version": "7.0.2", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, + "cachedir": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "camelcase": { + "version": "5.3.1", + "dev": true + }, + "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 + }, + "camelcase-keys": { + "version": "6.2.2", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, + "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.30001412", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz", + "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==", + "dev": true + }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "dev": true, + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, + "cfb": { + "version": "1.2.1", + "requires": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0", + "printj": "~1.3.0" + }, + "dependencies": { + "adler-32": { + "version": "1.3.0", + "requires": { + "printj": "~1.2.2" + }, + "dependencies": { + "printj": { + "version": "1.2.3" + } + } + }, + "printj": { + "version": "1.3.0" + } + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "dev": true + }, + "choices.js": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-10.1.0.tgz", + "integrity": "sha512-NtrFt7c7ZQEGmkWsAV+EHynJhADWoZ82JEfg1+vQ9MMKJD4Ax2rzYPxXe+Q64i0HgUgWG/XTN3gN2pB8UFFFlA==", + "requires": { + "deepmerge": "^4.2.2", + "fuse.js": "^6.5.3", + "redux": "^4.1.2" + } + }, + "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" + } + }, + "ci-info": { + "version": "3.3.0", + "dev": true + }, + "clean-stack": { + "version": "2.2.0", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true + }, + "cli-table3": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", + "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", + "dev": true, + "requires": { + "colors": "1.4.0", + "string-width": "^4.2.0" + } + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4" + }, + "clone-response": { + "version": "1.0.2", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "codemirror": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", + "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + }, + "dependencies": { + "@codemirror/autocomplete": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.0.2.tgz", + "integrity": "sha512-9PDjnllmXan/7Uax87KGORbxerDJ/cu10SB+n4Jz0zXMEvIh3+TGgZxhIvDOtaQ4jDBQEM7kHYW4vLdQB0DGZQ==", + "requires": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "@codemirror/lint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.0.0.tgz", + "integrity": "sha512-nUUXcJW1Xp54kNs+a1ToPLK8MadO0rMTnJB8Zk4Z8gBdrN0kqV7uvUraU/T2yqg+grDNR38Vmy/MrhQN/RgwiA==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "@codemirror/search": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.0.0.tgz", + "integrity": "sha512-rL0rd3AhI0TAsaJPUaEwC63KHLO7KL0Z/dYozXj6E7L3wNHRyx7RfE0/j5HsIf912EE5n2PCb4Vg0rGYmDv4UQ==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + } + } + }, + "codepage": { + "version": "1.15.0" + }, + "color-convert": { + "version": "1.9.3", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "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 + }, + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "optional": true + }, + "combined-stream": { + "version": "1.0.8", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz", + "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==", + "dev": true + }, + "commitizen": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.5.tgz", + "integrity": "sha512-9sXju8Qrz1B4Tw7kC5KhnvwYQN88qs2zbiB8oyMsnXZyJ24PPGiNM3nHr73d32dnE3i8VJEXddBFIbOgYSEXtQ==", + "dev": true, + "requires": { + "cachedir": "2.3.0", + "cz-conventional-changelog": "3.3.0", + "dedent": "0.7.0", + "detect-indent": "6.1.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "9.1.0", + "glob": "7.2.3", + "inquirer": "8.2.4", + "is-utf8": "^0.2.1", + "lodash": "4.17.21", + "minimist": "1.2.6", + "strip-bom": "4.0.0", + "strip-json-comments": "3.1.1" + }, + "dependencies": { + "find-node-modules": { + "version": "2.1.2", + "dev": true, + "requires": { + "findup-sync": "^4.0.0", + "merge": "^2.1.0" + } + }, + "findup-sync": { + "version": "4.0.0", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + } + }, + "merge": { + "version": "2.1.1", + "dev": true + } + } + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true + }, + "compare-func": { + "version": "2.0.0", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "conventional-changelog-angular": { + "version": "5.0.13", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + } + }, + "conventional-changelog-conventionalcommits": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", + "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + } + }, + "conventional-changelog-writer": { + "version": "5.0.0", + "dev": true, + "requires": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.6", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + } + }, + "conventional-commit-types": { + "version": "3.0.0", + "dev": true + }, + "conventional-commits-filter": { + "version": "2.0.7", + "dev": true, + "requires": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + } + }, + "conventional-commits-parser": { + "version": "3.2.3", + "dev": true, + "requires": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + } + }, + "convert-source-map": { + "version": "1.7.0", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-js": { + "version": "3.6.5" + }, + "core-js-compat": { + "version": "3.23.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.3.tgz", + "integrity": "sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw==", + "dev": true, + "requires": { + "browserslist": "^4.21.0", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2" + }, + "cosmiconfig": { + "version": "7.0.1", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "dependencies": { + "parse-json": { + "version": "5.2.0", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + } + } + }, + "cosmiconfig-typescript-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.0.0.tgz", + "integrity": "sha512-cVpucSc2Tf+VPwCCR7SZzmQTQkPbkk4O01yXsYqXBIbjE1bhwqSyAgYQkRK1un4i0OPziTleqFhdkmOc4RQ/9g==", + "dev": true, + "requires": {} + }, + "crc-32": { + "version": "1.2.0", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "crelt": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", + "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" + }, + "cross-env": { + "version": "7.0.3", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "crypto-js": { + "version": "4.1.1" + }, + "crypto-random-string": { + "version": "2.0.0", + "dev": true + }, + "css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "css-declaration-sorter": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", + "integrity": "sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==", + "dev": true, + "requires": {} + }, + "css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true + }, + "css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "dev": true, + "requires": {} + }, + "css-tree": { + "version": "1.1.3", + "dev": true, + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "dev": true + } + } + }, + "cssdb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.0.1.tgz", + "integrity": "sha512-pT3nzyGM78poCKLAEy2zWIVX2hikq6dIrjuZzLV98MumBg+xMTNYfHx7paUlfiRTgg91O/vR889CIf+qiv79Rw==", + "dev": true + }, + "cssesc": { + "version": "3.0.0" + }, + "cssnano": { + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", + "dev": true, + "requires": { + "cssnano-preset-default": "^5.2.12", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + } + }, + "cssnano-preset-default": { + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.12.tgz", + "integrity": "sha512-OyCBTZi+PXgylz9HAA5kHyoYhfGcYdwFmyaJzWnzxuGRtnMw/kR6ilW9XzlzlRAtB6PLT/r+prYgkef7hngFew==", + "dev": true, + "requires": { + "css-declaration-sorter": "^6.3.0", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.0", + "postcss-convert-values": "^5.1.2", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.6", + "postcss-merge-rules": "^5.1.2", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.3", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.0", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.0", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + } + }, + "cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "dev": true, + "requires": {} + }, + "csso": { + "version": "4.2.0", + "dev": true, + "requires": { + "css-tree": "^1.1.2" + } + }, + "cssom": { + "version": "0.4.4" + }, + "cssstyle": { + "version": "2.3.0", + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8" + } + } + }, + "cz-conventional-changelog": { + "version": "3.3.0", + "dev": true, + "requires": { + "@commitlint/load": ">6.1.1", + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "d": { + "version": "1.0.1", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "d3-array": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.0.tgz", + "integrity": "sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" + }, + "d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==" + }, + "d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" + }, + "d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "requires": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + } + }, + "d3-geo": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.0.1.tgz", + "integrity": "sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==", + "requires": { + "d3-array": "2.5.0 - 3" + } + }, + "d3-geo-projection": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-4.0.0.tgz", + "integrity": "sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==", + "requires": { + "commander": "7", + "d3-array": "1 - 3", + "d3-geo": "1.12.0 - 3" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + } + } + }, + "d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "requires": { + "d3-color": "1 - 3" + } + }, + "d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==" + }, + "d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" + }, + "d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==" + }, + "d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "requires": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + } + }, + "dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true + }, + "dash-ast": { + "version": "1.0.0" + }, + "data-urls": { + "version": "2.0.0", + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "dateformat": { + "version": "3.0.3", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "dev": true + } + } + }, + "decimal.js": { + "version": "10.3.1" + }, + "decompress-response": { + "version": "6.0.0", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "dev": true + } + } + }, + "dedent": { + "version": "0.7.0", + "dev": true + }, + "deep-equal": { + "version": "1.1.1", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3" + }, + "deepmerge": { + "version": "4.2.2" + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "defer-to-connect": { + "version": "2.0.1", + "dev": true + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0" + }, + "deprecation": { + "version": "2.3.1", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "dev": true + }, + "detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true + }, + "detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "requires": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + } + }, + "dfa": { + "version": "1.2.0" + }, + "didyoumean": { + "version": "1.2.2", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dlv": { + "version": "1.1.3", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "domexception": { + "version": "2.0.1", + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0" + } + } + }, + "dot-prop": { + "version": "5.3.0", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer2": { + "version": "0.1.4", + "requires": { + "readable-stream": "^2.0.2" + } + }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, + "electron-to-chromium": { + "version": "1.4.264", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz", + "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "2.2.0", + "dev": true + }, + "env-ci": { + "version": "5.4.1", + "dev": true, + "requires": { + "execa": "^5.0.0", + "fromentries": "^1.3.2", + "java-properties": "^1.0.0" + } + }, + "error-ex": { + "version": "1.3.2", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.2.1", + "dev": true + } + } + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-symbol": { + "version": "3.1.3", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "esbuild": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz", + "integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==", + "dev": true, + "requires": { + "esbuild-android-64": "0.14.48", + "esbuild-android-arm64": "0.14.48", + "esbuild-darwin-64": "0.14.48", + "esbuild-darwin-arm64": "0.14.48", + "esbuild-freebsd-64": "0.14.48", + "esbuild-freebsd-arm64": "0.14.48", + "esbuild-linux-32": "0.14.48", + "esbuild-linux-64": "0.14.48", + "esbuild-linux-arm": "0.14.48", + "esbuild-linux-arm64": "0.14.48", + "esbuild-linux-mips64le": "0.14.48", + "esbuild-linux-ppc64le": "0.14.48", + "esbuild-linux-riscv64": "0.14.48", + "esbuild-linux-s390x": "0.14.48", + "esbuild-netbsd-64": "0.14.48", + "esbuild-openbsd-64": "0.14.48", + "esbuild-sunos-64": "0.14.48", + "esbuild-windows-32": "0.14.48", + "esbuild-windows-64": "0.14.48", + "esbuild-windows-arm64": "0.14.48" + } + }, + "esbuild-android-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz", + "integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz", + "integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz", + "integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz", + "integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz", + "integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz", + "integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz", + "integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz", + "integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz", + "integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz", + "integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz", + "integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz", + "integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz", + "integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz", + "integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz", + "integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz", + "integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz", + "integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz", + "integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz", + "integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.48", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz", + "integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "dev": true + }, + "escodegen": { + "version": "1.2.0", + "requires": { + "esprima": "~1.0.4", + "estraverse": "~1.5.0", + "esutils": "~1.0.0", + "source-map": "~0.1.30" + }, + "dependencies": { + "esprima": { + "version": "1.0.4" + }, + "estraverse": { + "version": "1.5.1" + }, + "esutils": { + "version": "1.0.0" + }, + "source-map": { + "version": "0.1.43", + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "eslint": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", + "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.10.5", + "@humanwhocodes/module-importer": "^1.0.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "dev": true + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "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" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + } + } + }, + "eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "requires": {} + }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "espree": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "dependencies": { + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1" + }, + "esquery": { + "version": "1.4.0", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0" + }, + "estree-is-function": { + "version": "1.0.0" + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "esutils": { + "version": "2.0.3" + }, + "event-emitter": { + "version": "0.3.5", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "execa": { + "version": "5.1.1", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "dev": true + }, + "human-signals": { + "version": "2.1.0", + "dev": true + } + } + }, + "exit-on-epipe": { + "version": "1.0.1" + }, + "expand-tilde": { + "version": "2.0.2", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "ext": { + "version": "1.5.0", + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.5.0" + } + } + }, + "external-editor": { + "version": "3.1.0", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "dev": true + }, + "fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "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" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6" + }, + "fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true + }, + "fastq": { + "version": "1.8.0", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fflate": { + "version": "0.3.11" + }, + "figures": { + "version": "2.0.0", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "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" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "fill-range": { + "version": "7.0.1", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-root": { + "version": "1.1.0", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "find-versions": { + "version": "4.0.0", + "dev": true, + "requires": { + "semver-regex": "^3.1.2" + } + }, + "flat-cache": { + "version": "3.0.4", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatpickr": { + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", + "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==" + }, + "flatted": { + "version": "3.1.1", + "dev": true + }, + "fontkit": { + "version": "1.8.1", + "requires": { + "babel-runtime": "^6.26.0", + "brfs": "^2.0.0", + "brotli": "^1.2.0", + "browserify-optional": "^1.0.1", + "clone": "^1.0.4", + "deep-equal": "^1.0.0", + "dfa": "^1.2.0", + "restructure": "^0.5.3", + "tiny-inflate": "^1.0.2", + "unicode-properties": "^1.2.2", + "unicode-trie": "^0.3.0" + }, + "dependencies": { + "unicode-trie": { + "version": "0.3.1", + "requires": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + } + } + }, + "form-data": { + "version": "3.0.0", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "frac": { + "version": "1.1.2" + }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true + }, + "from2": { + "version": "2.3.0", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fromentries": { + "version": "1.3.2", + "dev": true + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "dev": true + }, + "fscreen": { + "version": "1.2.0" + }, + "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" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "fuse.js": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.5.3.tgz", + "integrity": "sha512-sA5etGE7yD/pOqivZRBvUBd/NaL2sjAu6QuSaFoe1H2BrJSkH/T/UXAJ8CdXdw7DvY3Hs8CXKYkDWX7RiP5KOg==" + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-assigned-identifiers": { + "version": "1.2.0" + }, + "get-caller-file": { + "version": "2.0.5", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "get-stream": { + "version": "5.2.0", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "git-log-parser": { + "version": "1.2.0", + "dev": true, + "requires": { + "argv-formatter": "~1.0.0", + "spawn-error-forwarder": "~1.0.0", + "split2": "~1.0.0", + "stream-combiner2": "~1.1.1", + "through2": "~2.0.0", + "traverse": "~0.6.6" + }, + "dependencies": { + "split2": { + "version": "1.0.0", + "dev": true, + "requires": { + "through2": "~2.0.0" + } + }, + "through2": { + "version": "2.0.5", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "git-raw-commits": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "dev": true, + "requires": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "global-modules": { + "version": "1.0.0", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "globjoin": { + "version": "0.1.4", + "dev": true + }, + "got": { + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "dev": true + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "handlebars": { + "version": "4.7.7", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "dev": true + } + } + }, + "hard-rejection": { + "version": "2.1.0", + "dev": true + }, + "has": { + "version": "1.0.3", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hook-std": { + "version": "2.0.0", + "dev": true + }, + "hosted-git-info": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "hpagent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.0.0.tgz", + "integrity": "sha512-SCleE2Uc1bM752ymxg8QXYGW0TWtAV4ZW3TqH1aOnyi6T6YW2xadCcclm5qeVjvMvfQ2RKNtZxO7uVb9CTPt1A==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.1.0", + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "http2-wrapper": { + "version": "1.0.3", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "dependencies": { + "quick-lru": { + "version": "5.1.1", + "dev": true + } + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "dev": true + }, + "husky": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", + "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "idb": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.2.tgz", + "integrity": "sha512-jjKrT1EnyZewQ/gCBb/eyiYrhGzws2FeY92Yx8qT9S9GeQAmo4JFVIiWRIfKW/6Ob9A+UDAOW9j9jn58fy2HIg==", + "dev": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "dev": true + } + } + }, + "import-lazy": { + "version": "4.0.0", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4" + }, + "ini": { + "version": "1.3.8", + "dev": true + }, + "inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + } + } + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, + "into-stream": { + "version": "6.0.0", + "dev": true, + "requires": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + } + }, + "is-arguments": { + "version": "1.1.0", + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "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-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-ci": { + "version": "3.0.1", + "dev": true, + "requires": { + "ci-info": "^3.2.0" + } + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.2" + }, + "is-extglob": { + "version": "2.1.1", + "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", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "dev": true + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "dev": true + }, + "is-potential-custom-element-name": { + "version": "1.0.1" + }, + "is-regex": { + "version": "1.1.4", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "2.0.0", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-text-path": { + "version": "1.0.1", + "dev": true, + "requires": { + "text-extensions": "^1.0.0" + } + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-windows": { + "version": "1.0.2", + "dev": true + }, + "isarray": { + "version": "1.0.0" + }, + "isexe": { + "version": "2.0.0", + "dev": true + }, + "issue-parser": { + "version": "6.0.0", + "dev": true, + "requires": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + } + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + } + }, + "java-properties": { + "version": "1.0.2", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-sdsl": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", + "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsdom": { + "version": "16.7.0", + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "8.5.0" + }, + "escodegen": { + "version": "2.0.0", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "5.2.0" + }, + "levn": { + "version": "0.3.0", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2" + }, + "source-map": { + "version": "0.6.1", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "dev": true + }, + "json-fixer": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/json-fixer/-/json-fixer-1.6.13.tgz", + "integrity": "sha512-DKQ71M+0uwAG3QsUkeVgh6XREw/OkpnTfHfM+sdmxRjHvYZ8PlcMVF4ibsHQ1ckR63NROs68qUr1I0u6yPVePQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.14.6", + "chalk": "^4.1.2", + "pegjs": "^0.10.0" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.0", + "dev": true + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "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" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "jsonparse": { + "version": "1.3.1", + "dev": true + }, + "jsonpointer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", + "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "keyv": { + "version": "4.0.4", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "dev": true + }, + "known-css-properties": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", + "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", + "dev": true + }, + "leaflet": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.2.tgz", + "integrity": "sha512-Kc77HQvWO+y9y2oIs3dn5h5sy2kr3j41ewdqCMEUA4N89lgfUUfOBy7wnnHEstDpefiGFObq12FdopGRMx4J7g==" + }, + "leaflet.markercluster": { + "version": "1.5.3", + "requires": {} + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true + }, + "linebreak": { + "version": "1.0.2", + "requires": { + "base64-js": "0.0.8", + "brfs": "^2.0.2", + "unicode-trie": "^1.0.0" + }, + "dependencies": { + "base64-js": { + "version": "0.0.8" + }, + "unicode-trie": { + "version": "1.0.0", + "requires": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + } + } + }, + "lines-and-columns": { + "version": "1.1.6", + "dev": true + }, + "lint-staged": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.3.tgz", + "integrity": "sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==", + "dev": true, + "requires": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.17", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^6.1.0", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "dev": true + }, + "cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + } + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + } + }, + "string-width": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.0.1.tgz", + "integrity": "sha512-5ohWO/M4//8lErlUUtrFy3b11GtNOuMOU0ysKCDXFcfXuuvUXu95akgj/i8ofmaGdN0hCqyl6uu9i8dS/mQp5g==", + "dev": true, + "requires": { + "emoji-regex": "^9.2.2", + "is-fullwidth-code-point": "^4.0.0", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + }, + "yaml": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.1.tgz", + "integrity": "sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==", + "dev": true + } + } + }, + "listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + } + } + }, + "lit": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.4.0.tgz", + "integrity": "sha512-fdgzxEtLrZFQU/BqTtxFQCLwlZd9bdat+ltzSFjvWkZrs7eBmeX0L5MHUMb3kYIkuS8Xlfnii/iI5klirF8/Xg==", + "requires": { + "@lit/reactive-element": "^1.4.0", + "lit-element": "^3.2.0", + "lit-html": "^2.4.0" + } + }, + "lit-element": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.0.tgz", + "integrity": "sha512-HbE7yt2SnUtg5DCrWt028oaU4D5F4k/1cntAFHTkzY8ZIa8N0Wmu92PxSxucsQSOXlODFrICkQ5x/tEshKi13g==", + "requires": { + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.2.0" + } + }, + "lit-html": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.4.0.tgz", + "integrity": "sha512-G6qXu4JNUpY6aaF2VMfaszhO9hlWw0hOTRFDmuMheg/nDYGB+2RztUSOyrzALAbr8Nh0Y7qjhYkReh3rPnplVg==", + "requires": { + "@types/trusted-types": "^2.0.2" + } + }, + "load-json-file": { + "version": "4.0.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "dev": true + } + } + }, + "locate-path": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21" + }, + "lodash.capitalize": { + "version": "4.2.1", + "dev": true + }, + "lodash.castarray": { + "version": "4.4.0", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "dev": true + }, + "lodash.ismatch": { + "version": "4.4.0", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "dev": true + }, + "lodash.map": { + "version": "4.6.0", + "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.merge": { + "version": "4.6.2", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "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 + }, + "lodash.uniqby": { + "version": "4.7.0", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "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": { + "color-convert": "^2.0.1" + } + }, + "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 + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "longest": { + "version": "2.0.1", + "dev": true + }, + "lowercase-keys": { + "version": "2.0.0", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "magic-string": { + "version": "0.25.1", + "requires": { + "sourcemap-codec": "^1.4.1" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "map-obj": { + "version": "4.2.0", + "dev": true + }, + "marked": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", + "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==" + }, + "marked-terminal": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.0.0.tgz", + "integrity": "sha512-26604GmGmW63ElxcXpE2xfMdbtgD/qiwIqOh/+5+uPe6NVU4bU433+wvPTfq6NZcGr16KWqwu/dzsKxg3IL2Xw==", + "dev": true, + "requires": { + "ansi-escapes": "^5.0.0", + "cardinal": "^2.1.1", + "chalk": "^5.0.0", + "cli-table3": "^0.6.0", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.2.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", + "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "dev": true, + "requires": { + "type-fest": "^1.0.2" + } + }, + "chalk": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.0.tgz", + "integrity": "sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ==", + "dev": true + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } + } + }, + "mathml-tag-names": { + "version": "2.1.3", + "dev": true + }, + "mdn-data": { + "version": "2.0.14", + "dev": true + }, + "meow": { + "version": "8.1.2", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + } + }, + "merge-source-map": { + "version": "1.0.4", + "requires": { + "source-map": "^0.5.6" + } + }, + "merge-stream": { + "version": "2.0.0", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "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" + } + }, + "mime": { + "version": "3.0.0", + "dev": true + }, + "mime-db": { + "version": "1.45.0" + }, + "mime-types": { + "version": "2.1.28", + "requires": { + "mime-db": "1.45.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "dev": true + }, + "mini-svg-data-uri": { + "version": "1.2.3", + "dev": true + }, + "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" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "minimist-options": { + "version": "4.1.0", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "mitt": { + "version": "3.0.0" + }, + "modify-values": { + "version": "1.0.1", + "dev": true + }, + "ms": { + "version": "2.1.2" + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, + "natural-compare": { + "version": "1.4.0", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "dev": true + }, + "nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha1-5tq3/r9a2Bbqgc9cYpxaDr3nLBo=", + "dev": true + }, + "next-tick": { + "version": "1.0.0" + }, + "node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "requires": { + "lodash": "^4.17.21" + } + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "normalize-package-data": { + "version": "3.0.2", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "resolve": "^1.20.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "normalize-path": { + "version": "3.0.0", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true + }, + "normalize-url": { + "version": "6.1.0", + "dev": true + }, + "npm": { + "version": "8.13.2", + "resolved": "https://registry.npmjs.org/npm/-/npm-8.13.2.tgz", + "integrity": "sha512-aS6q/QKxkw9mTX8gR7Ft38BcRkW1i+h3sI1yAFmfQ30Yl1a1G4ZX3oNGDzaLCilU5ThFZQBS1F4ZSZsrVxJ7HA==", + "dev": true, + "requires": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^5.0.4", + "@npmcli/ci-detect": "^2.0.0", + "@npmcli/config": "^4.1.0", + "@npmcli/fs": "^2.1.0", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/package-json": "^2.0.0", + "@npmcli/run-script": "^4.1.5", + "abbrev": "~1.1.1", + "archy": "~1.0.0", + "cacache": "^16.1.1", + "chalk": "^4.1.2", + "chownr": "^2.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.2", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.12", + "glob": "^8.0.1", + "graceful-fs": "^4.2.10", + "hosted-git-info": "^5.0.0", + "ini": "^3.0.0", + "init-package-json": "^3.0.2", + "is-cidr": "^4.0.2", + "json-parse-even-better-errors": "^2.3.1", + "libnpmaccess": "^6.0.2", + "libnpmdiff": "^4.0.2", + "libnpmexec": "^4.0.2", + "libnpmfund": "^3.0.1", + "libnpmhook": "^8.0.2", + "libnpmorg": "^4.0.2", + "libnpmpack": "^4.0.2", + "libnpmpublish": "^6.0.2", + "libnpmsearch": "^5.0.2", + "libnpmteam": "^4.0.2", + "libnpmversion": "^3.0.1", + "make-fetch-happen": "^10.1.8", + "minipass": "^3.1.6", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "ms": "^2.1.2", + "node-gyp": "^9.0.0", + "nopt": "^5.0.0", + "npm-audit-report": "^3.0.0", + "npm-install-checks": "^5.0.0", + "npm-package-arg": "^9.0.2", + "npm-pick-manifest": "^7.0.1", + "npm-profile": "^6.1.0", + "npm-registry-fetch": "^13.1.1", + "npm-user-validate": "^1.0.1", + "npmlog": "^6.0.2", + "opener": "^1.5.2", + "pacote": "^13.6.1", + "parse-conflict-json": "^2.0.2", + "proc-log": "^2.0.1", + "qrcode-terminal": "^0.12.0", + "read": "~1.0.7", + "read-package-json": "^5.0.1", + "read-package-json-fast": "^2.0.3", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^9.0.1", + "tar": "^6.1.11", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^2.0.0", + "validate-npm-package-name": "^4.0.0", + "which": "^2.0.2", + "write-file-atomic": "^4.0.1" + }, + "dependencies": { + "@colors/colors": { + "version": "1.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "@gar/promisify": { + "version": "1.1.3", + "bundled": true, + "dev": true + }, + "@isaacs/string-locale-compare": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "@npmcli/arborist": { + "version": "5.2.3", + "bundled": true, + "dev": true, + "requires": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/metavuln-calculator": "^3.0.1", + "@npmcli/move-file": "^2.0.0", + "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/package-json": "^2.0.0", + "@npmcli/run-script": "^4.1.3", + "bin-links": "^3.0.0", + "cacache": "^16.0.6", + "common-ancestor-path": "^1.0.1", + "json-parse-even-better-errors": "^2.3.1", + "json-stringify-nice": "^1.1.4", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "nopt": "^5.0.0", + "npm-install-checks": "^5.0.0", + "npm-package-arg": "^9.0.0", + "npm-pick-manifest": "^7.0.0", + "npm-registry-fetch": "^13.0.0", + "npmlog": "^6.0.2", + "pacote": "^13.6.1", + "parse-conflict-json": "^2.0.1", + "proc-log": "^2.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.1", + "read-package-json-fast": "^2.0.2", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^9.0.0", + "treeverse": "^2.0.0", + "walk-up-path": "^1.0.0" + } + }, + "@npmcli/ci-detect": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "@npmcli/config": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/map-workspaces": "^2.0.2", + "ini": "^3.0.0", + "mkdirp-infer-owner": "^2.0.0", + "nopt": "^5.0.0", + "proc-log": "^2.0.0", + "read-package-json-fast": "^2.0.3", + "semver": "^7.3.5", + "walk-up-path": "^1.0.0" + } + }, + "@npmcli/disparity-colors": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "^4.3.0" + } + }, + "@npmcli/fs": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + } + }, + "@npmcli/git": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/promise-spawn": "^3.0.0", + "lru-cache": "^7.4.4", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^7.0.0", + "proc-log": "^2.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + } + }, + "@npmcli/installed-package-contents": { + "version": "1.0.7", + "bundled": true, + "dev": true, + "requires": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "@npmcli/map-workspaces": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/name-from-folder": "^1.0.1", + "glob": "^8.0.1", + "minimatch": "^5.0.1", + "read-package-json-fast": "^2.0.3" + } + }, + "@npmcli/metavuln-calculator": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "requires": { + "cacache": "^16.0.0", + "json-parse-even-better-errors": "^2.3.1", + "pacote": "^13.0.3", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@npmcli/name-from-folder": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "@npmcli/node-gyp": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "@npmcli/package-json": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.1" + } + }, + "@npmcli/promise-spawn": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "infer-owner": "^1.0.4" + } + }, + "@npmcli/run-script": { + "version": "4.1.5", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/promise-spawn": "^3.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^2.0.3", + "which": "^2.0.2" + } + }, + "@tootallnate/once": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "bundled": true, + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "aproba": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "archy": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "are-we-there-yet": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "asap": { + "version": "2.0.6", + "bundled": true, + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "bin-links": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "cmd-shim": "^5.0.0", + "mkdirp-infer-owner": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0", + "read-cmd-shim": "^3.0.0", + "rimraf": "^3.0.0", + "write-file-atomic": "^4.0.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "builtins": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "requires": { + "semver": "^7.0.0" + } + }, + "cacache": { + "version": "16.1.1", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^1.1.1" + } + }, + "chalk": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chownr": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "cidr-regex": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "requires": { + "ip-regex": "^4.1.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "bundled": true, + "dev": true + }, + "cli-columns": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + } + }, + "cli-table3": { + "version": "0.6.2", + "bundled": true, + "dev": true, + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + } + }, + "clone": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "cmd-shim": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "mkdirp-infer-owner": "^2.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "bundled": true, + "dev": true + }, + "color-support": { + "version": "1.1.3", + "bundled": true, + "dev": true + }, + "columnify": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "requires": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + } + }, + "common-ancestor-path": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "debug": { + "version": "4.3.4", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true + } + } + }, + "debuglog": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "depd": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "dezalgo": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "diff": { + "version": "5.0.0", + "bundled": true, + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "bundled": true, + "dev": true + }, + "encoding": { + "version": "0.1.13", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "env-paths": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "err-code": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "bundled": true, + "dev": true + }, + "fs-minipass": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "gauge": { + "version": "4.0.4", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "glob": { + "version": "8.0.3", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "bundled": true, + "dev": true + }, + "has": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "hosted-git-info": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "^7.5.1" + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "http-proxy-agent": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "ignore-walk": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "requires": { + "minimatch": "^5.0.1" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "ini": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "init-package-json": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "npm-package-arg": "^9.0.1", + "promzard": "^0.3.0", + "read": "^1.0.7", + "read-package-json": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^4.0.0" + } + }, + "ip": { + "version": "1.1.8", + "bundled": true, + "dev": true + }, + "ip-regex": { + "version": "4.3.0", + "bundled": true, + "dev": true + }, + "is-cidr": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "requires": { + "cidr-regex": "^3.1.1" + } + }, + "is-core-module": { + "version": "2.9.0", + "bundled": true, + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "is-lambda": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "bundled": true, + "dev": true + }, + "json-stringify-nice": { + "version": "1.1.4", + "bundled": true, + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true, + "dev": true + }, + "just-diff": { + "version": "5.0.2", + "bundled": true, + "dev": true + }, + "just-diff-apply": { + "version": "5.2.0", + "bundled": true, + "dev": true + }, + "libnpmaccess": { + "version": "6.0.3", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^2.0.0", + "minipass": "^3.1.1", + "npm-package-arg": "^9.0.1", + "npm-registry-fetch": "^13.0.0" + } + }, + "libnpmdiff": { + "version": "4.0.4", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/disparity-colors": "^2.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "binary-extensions": "^2.2.0", + "diff": "^5.0.0", + "minimatch": "^5.0.1", + "npm-package-arg": "^9.0.1", + "pacote": "^13.6.1", + "tar": "^6.1.0" + } + }, + "libnpmexec": { + "version": "4.0.8", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/arborist": "^5.0.0", + "@npmcli/ci-detect": "^2.0.0", + "@npmcli/run-script": "^4.1.3", + "chalk": "^4.1.0", + "mkdirp-infer-owner": "^2.0.0", + "npm-package-arg": "^9.0.1", + "npmlog": "^6.0.2", + "pacote": "^13.6.1", + "proc-log": "^2.0.0", + "read": "^1.0.7", + "read-package-json-fast": "^2.0.2", + "walk-up-path": "^1.0.0" + } + }, + "libnpmfund": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/arborist": "^5.0.0" + } + }, + "libnpmhook": { + "version": "8.0.3", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + } + }, + "libnpmorg": { + "version": "4.0.3", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + } + }, + "libnpmpack": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/run-script": "^4.1.3", + "npm-package-arg": "^9.0.1", + "pacote": "^13.6.1" + } + }, + "libnpmpublish": { + "version": "6.0.4", + "bundled": true, + "dev": true, + "requires": { + "normalize-package-data": "^4.0.0", + "npm-package-arg": "^9.0.1", + "npm-registry-fetch": "^13.0.0", + "semver": "^7.3.7", + "ssri": "^9.0.0" + } + }, + "libnpmsearch": { + "version": "5.0.3", + "bundled": true, + "dev": true, + "requires": { + "npm-registry-fetch": "^13.0.0" + } + }, + "libnpmteam": { + "version": "4.0.3", + "bundled": true, + "dev": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + } + }, + "libnpmversion": { + "version": "3.0.6", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/git": "^3.0.0", + "@npmcli/run-script": "^4.1.3", + "json-parse-even-better-errors": "^2.3.1", + "proc-log": "^2.0.0", + "semver": "^7.3.7" + } + }, + "lru-cache": { + "version": "7.9.0", + "bundled": true, + "dev": true + }, + "make-fetch-happen": { + "version": "10.1.8", + "bundled": true, + "dev": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "3.1.6", + "bundled": true, + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + } + }, + "minipass-flush": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-json-stream": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "mkdirp-infer-owner": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "chownr": "^2.0.0", + "infer-owner": "^1.0.4", + "mkdirp": "^1.0.3" + } + }, + "ms": { + "version": "2.1.3", + "bundled": true, + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "bundled": true, + "dev": true + }, + "node-gyp": { + "version": "9.0.0", + "bundled": true, + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "nopt": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + } + }, + "npm-audit-report": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "npm-bundled": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-install-checks": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "requires": { + "semver": "^7.1.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "npm-package-arg": { + "version": "9.0.2", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^4.0.0" + } + }, + "npm-packlist": { + "version": "5.1.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "^8.0.1", + "ignore-walk": "^5.0.1", + "npm-bundled": "^1.1.2", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "7.0.1", + "bundled": true, + "dev": true, + "requires": { + "npm-install-checks": "^5.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^9.0.0", + "semver": "^7.3.5" + } + }, + "npm-profile": { + "version": "6.1.0", + "bundled": true, + "dev": true, + "requires": { + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0" + } + }, + "npm-registry-fetch": { + "version": "13.1.1", + "bundled": true, + "dev": true, + "requires": { + "make-fetch-happen": "^10.0.6", + "minipass": "^3.1.6", + "minipass-fetch": "^2.0.3", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^9.0.1", + "proc-log": "^2.0.0" + } + }, + "npm-user-validate": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "npmlog": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.2", + "bundled": true, + "dev": true + }, + "p-map": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "pacote": { + "version": "13.6.1", + "bundled": true, + "dev": true, + "requires": { + "@npmcli/git": "^3.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/promise-spawn": "^3.0.0", + "@npmcli/run-script": "^4.1.0", + "cacache": "^16.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.6", + "mkdirp": "^1.0.4", + "npm-package-arg": "^9.0.0", + "npm-packlist": "^5.1.0", + "npm-pick-manifest": "^7.0.0", + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^5.0.0", + "read-package-json-fast": "^2.0.3", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11" + } + }, + "parse-conflict-json": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.1", + "just-diff": "^5.0.1", + "just-diff-apply": "^5.2.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "proc-log": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "promise-all-reject-late": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "promise-call-limit": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "promise-retry": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "promzard": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "read": "1" + } + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true, + "dev": true + }, + "read": { + "version": "1.0.7", + "bundled": true, + "dev": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "read-package-json": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "^8.0.1", + "json-parse-even-better-errors": "^2.3.1", + "normalize-package-data": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "read-package-json-fast": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "readable-stream": { + "version": "3.6.0", + "bundled": true, + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdir-scoped-modules": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "retry": { + "version": "0.12.0", + "bundled": true, + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "7.3.7", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "bundled": true, + "dev": true + }, + "smart-buffer": { + "version": "4.2.0", + "bundled": true, + "dev": true + }, + "socks": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "7.0.0", + "bundled": true, + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, + "spdx-correct": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.11", + "bundled": true, + "dev": true + }, + "ssri": { + "version": "9.0.1", + "bundled": true, + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "bundled": true, + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "bundled": true, + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tar": { + "version": "6.1.11", + "bundled": true, + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "treeverse": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtins": "^5.0.0" + } + }, + "walk-up-path": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "write-file-atomic": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "yallist": { + "version": "4.0.0", + "bundled": true, + "dev": true + } + } + }, + "npm-run-path": { + "version": "4.0.1", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "nwsapi": { + "version": "2.2.0" + }, + "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 + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-is": { + "version": "1.1.5", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1" + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "once": { + "version": "1.4.0", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.9.1", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "dev": true + }, + "p-cancelable": { + "version": "2.1.1", + "dev": true + }, + "p-each-series": { + "version": "2.2.0", + "dev": true + }, + "p-filter": { + "version": "2.1.0", + "dev": true, + "requires": { + "p-map": "^2.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "dev": true + } + } + }, + "p-is-promise": { + "version": "3.0.0", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "4.0.0", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-reduce": { + "version": "2.1.0", + "dev": true + }, + "p-retry": { + "version": "4.6.1", + "dev": true, + "requires": { + "@types/retry": "^0.12.0", + "retry": "^0.13.1" + } + }, + "p-try": { + "version": "2.2.0", + "dev": true + }, + "pako": { + "version": "0.2.9" + }, + "parent-module": { + "version": "1.0.1", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "dev": true + } + } + }, + "parse-json": { + "version": "4.0.0", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "dev": true + }, + "parse-path": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", + "dev": true, + "requires": { + "protocols": "^2.0.0" + } + }, + "parse-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", + "dev": true, + "requires": { + "parse-path": "^7.0.0" + } + }, + "parse5": { + "version": "6.0.1" + }, + "path-exists": { + "version": "4.0.0", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "dev": true + }, + "path-parse": { + "version": "1.0.7" + }, + "path-type": { + "version": "4.0.0", + "dev": true + }, + "pdfkit": { + "version": "0.12.3", + "requires": { + "crypto-js": "^4.0.0", + "fontkit": "^1.8.1", + "linebreak": "^1.0.2", + "png-js": "^1.0.0" + } + }, + "pdfmake": { + "version": "0.2.2", + "requires": { + "@foliojs-fork/linebreak": "^1.1.1", + "@foliojs-fork/pdfkit": "^0.12.3", + "iconv-lite": "^0.6.3", + "svg-to-pdfkit": "^0.1.8", + "xmldoc": "^1.1.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==", + "dev": true + }, + "performance-now": { + "version": "2.1.0" + }, + "picocolors": { + "version": "1.0.0" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "dev": true + }, + "pkg-conf": { + "version": "2.1.0", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "dev": true + } + } + }, + "png-js": { + "version": "1.0.0" + }, + "polylabel": { + "version": "1.1.0", + "requires": { + "tinyqueue": "^2.0.3" + } + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-colormin": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", + "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-convert-values": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.2.tgz", + "integrity": "sha512-c6Hzc4GAv95B7suy4udszX9Zy4ETyMCgFPUDtWjdFTKH1SE9eFY/jEpHSwTH1QPuwxHpWslhckUQWbNRM4ho5g==", + "dev": true, + "requires": { + "browserslist": "^4.20.3", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-properties": { + "version": "12.1.9", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.9.tgz", + "integrity": "sha512-/E7PRvK8DAVljBbeWrcEQJPG72jaImxF3vvCNFwv9cC8CzigVoNIpeyfnJzphnN3Fd8/auBf5wvkw6W9MfmTyg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "dev": true, + "requires": {} + }, + "postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "dev": true, + "requires": {} + }, + "postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "dev": true, + "requires": {} + }, + "postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "dev": true, + "requires": {} + }, + "postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "dev": true, + "requires": {} + }, + "postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "dev": true, + "requires": {} + }, + "postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-import": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.0.0.tgz", + "integrity": "sha512-Y20shPQ07RitgBGv2zvkEAu9bqvrD77C9axhj/aA1BQj4czape2MdClCExvB27EwYEJdGgKZBpKanb0t1rK2Kg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "dev": true, + "requires": {} + }, + "postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, + "postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "dev": true, + "requires": {} + }, + "postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "dev": true, + "requires": {} + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "dev": true + }, + "postcss-merge-longhand": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.6.tgz", + "integrity": "sha512-6C/UGF/3T5OE2CEbOuX7iNO63dnvqhGZeUnKkDeifebY0XqkkvrctYSZurpNE902LDf2yKwwPFgotnfSoPhQiw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.0" + } + }, + "postcss-merge-rules": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.2.tgz", + "integrity": "sha512-zKMUlnw+zYCWoPN6yhPjtcEdlJaMUZ0WyVcxTAmw3lkkN/NDMRkOkiuctQEoWAOvH7twaxUUdvBWl0d4+hifRQ==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dev": true, + "requires": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-params": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.3.tgz", + "integrity": "sha512-bkzpWcjykkqIujNL+EVEPOlLYi/eZ050oImVtHU7b4lFS82jPnsCb44gvC6pxaNt38Els3jWYDHTjHKf0koTgg==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-nested": { + "version": "5.0.6", + "requires": { + "postcss-selector-parser": "^6.0.6" + } + }, + "postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "dev": true, + "requires": {} + }, + "postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-unicode": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz", + "integrity": "sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dev": true, + "requires": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-opacity-percentage": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz", + "integrity": "sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==", + "dev": true + }, + "postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dev": true, + "requires": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "dev": true, + "requires": {} + }, + "postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-preset-env": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.2.tgz", + "integrity": "sha512-rSMUEaOCnovKnwc5LvBDHUDzpGP+nrUeWZGWt9M72fBvckCi45JmnJigUr4QG4zZeOHmOCNCZnd2LKDvP++ZuQ==", + "dev": true, + "requires": { + "@csstools/postcss-cascade-layers": "^1.1.0", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.11", + "browserslist": "^4.21.3", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.0.1", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.9", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-reduce-initial": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz", + "integrity": "sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "dev": true, + "requires": {} + }, + "postcss-reporter": { + "version": "7.0.5", + "dev": true, + "requires": { + "picocolors": "^1.0.0", + "thenby": "^1.3.4" + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "dev": true + }, + "postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "requires": {} + }, + "postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + } + }, + "postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "dev": true + }, + "prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "prettier-plugin-organize-imports": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.1.1.tgz", + "integrity": "sha512-6bHIQzybqA644h0WGUW3gpWEVbMBvzui5wCMRBi7qA++d5ov2xjjfDk8pxJJ/ardfZrGAwizKMq/fQMFdJ+0Zw==", + "dev": true, + "requires": {} + }, + "pretty-bytes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.0.0.tgz", + "integrity": "sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==", + "dev": true + }, + "printj": { + "version": "1.1.2" + }, + "process-nextick-args": { + "version": "2.0.1" + }, + "protocols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", + "dev": true + }, + "psl": { + "version": "1.8.0" + }, + "pump": { + "version": "3.0.0", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1" + }, + "q": { + "version": "1.5.1", + "dev": true + }, + "quick-lru": { + "version": "4.0.1", + "dev": true + }, + "quote-stream": { + "version": "1.0.2", + "requires": { + "buffer-equal": "0.0.1", + "minimist": "^1.1.3", + "through2": "^2.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "raf": { + "version": "3.4.1", + "requires": { + "performance-now": "^2.1.0" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "read-cache": { + "version": "1.0.0", + "dev": true, + "requires": { + "pify": "^2.3.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "parse-json": { + "version": "5.2.0", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "semver": { + "version": "5.7.1", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.7", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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" + } + }, + "redent": { + "version": "3.0.0", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "dev": true, + "requires": { + "esprima": "~4.0.0" + } + }, + "redux": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", + "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.7" + }, + "regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "regexpp": { + "version": "3.2.0", + "dev": true + }, + "regexpu-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", + "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", + "dev": true, + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + } + }, + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "dev": true + }, + "regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + } + } + }, + "regression": { + "version": "2.0.1" + }, + "require-directory": { + "version": "2.1.1", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-alpn": { + "version": "1.2.1", + "dev": true + }, + "resolve-dir": { + "version": "1.0.1", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "dev": true + }, + "resolve-global": { + "version": "1.0.0", + "dev": true, + "requires": { + "global-dirs": "^0.1.1" + } + }, + "responselike": { + "version": "2.0.0", + "dev": true, + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "restructure": { + "version": "0.5.4", + "requires": { + "browserify-optional": "^1.0.0" + } + }, + "retry": { + "version": "0.13.1", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "dev": true + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "rgbcolor": { + "version": "1.0.1" + }, + "rimraf": { + "version": "3.0.2", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "2.75.7", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz", + "integrity": "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + } + }, + "run-async": { + "version": "2.4.1", + "dev": true + }, + "run-parallel": { + "version": "1.1.9", + "dev": true + }, + "rxjs": { + "version": "6.6.2", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2" + }, + "safer-buffer": { + "version": "2.1.2" + }, + "sax": { + "version": "1.2.4" + }, + "saxes": { + "version": "5.0.1", + "requires": { + "xmlchars": "^2.2.0" + } + }, + "scope-analyzer": { + "version": "2.1.1", + "requires": { + "array-from": "^2.1.1", + "dash-ast": "^1.0.0", + "es6-map": "^0.1.5", + "es6-set": "^0.1.5", + "es6-symbol": "^3.1.1", + "estree-is-function": "^1.0.0", + "get-assigned-identifiers": "^1.1.0" + } + }, + "semantic-release": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.5.tgz", + "integrity": "sha512-NMPKdfpXTnPn49FDogMBi36SiBfXkSOJqCkk0E4iWOY1tusvvgBwqUmxTX1kmlT6kIYed9YwNKD1sfPpqa5yaA==", + "dev": true, + "requires": { + "@semantic-release/commit-analyzer": "^9.0.2", + "@semantic-release/error": "^3.0.0", + "@semantic-release/github": "^8.0.0", + "@semantic-release/npm": "^9.0.0", + "@semantic-release/release-notes-generator": "^10.0.0", + "aggregate-error": "^3.0.0", + "cosmiconfig": "^7.0.0", + "debug": "^4.0.0", + "env-ci": "^5.0.0", + "execa": "^5.0.0", + "figures": "^3.0.0", + "find-versions": "^4.0.0", + "get-stream": "^6.0.0", + "git-log-parser": "^1.2.0", + "hook-std": "^2.0.0", + "hosted-git-info": "^4.0.0", + "lodash": "^4.17.21", + "marked": "^4.0.10", + "marked-terminal": "^5.0.0", + "micromatch": "^4.0.2", + "p-each-series": "^2.1.0", + "p-reduce": "^2.0.0", + "read-pkg-up": "^7.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.3.2", + "semver-diff": "^3.1.1", + "signale": "^1.2.1", + "yargs": "^16.2.0" + }, + "dependencies": { + "figures": { + "version": "3.2.0", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "get-stream": { + "version": "6.0.1", + "dev": true + }, + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "semver": { + "version": "6.3.0", + "dev": true + }, + "semver-diff": { + "version": "3.1.1", + "dev": true, + "requires": { + "semver": "^6.3.0" + } + }, + "semver-regex": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", + "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", + "dev": true + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "shallow-copy": { + "version": "0.0.1" + }, + "shebang-command": { + "version": "2.0.0", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "signale": { + "version": "1.4.0", + "dev": true, + "requires": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "slash": { + "version": "3.0.0", + "dev": true + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "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": { + "color-convert": "^2.0.1" + } + }, + "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 + } + } + }, + "source-map": { + "version": "0.5.7" + }, + "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==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "sourcemap-codec": { + "version": "1.4.8" + }, + "spawn-error-forwarder": { + "version": "1.0.0", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.7", + "dev": true + }, + "split": { + "version": "1.0.1", + "dev": true, + "requires": { + "through": "2" + } + }, + "split2": { + "version": "3.2.2", + "dev": true, + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ssf": { + "version": "0.11.2", + "requires": { + "frac": "~1.1.2" + } + }, + "stable": { + "version": "0.1.8", + "dev": true + }, + "stackblur-canvas": { + "version": "2.5.0" + }, + "static-eval": { + "version": "2.1.0", + "requires": { + "escodegen": "^1.11.1" + }, + "dependencies": { + "escodegen": { + "version": "1.14.3", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "levn": { + "version": "0.3.0", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2" + }, + "source-map": { + "version": "0.6.1", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "static-module": { + "version": "3.0.4", + "requires": { + "acorn-node": "^1.3.0", + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "^1.11.1", + "has": "^1.0.1", + "magic-string": "0.25.1", + "merge-source-map": "1.0.4", + "object-inspect": "^1.6.0", + "readable-stream": "~2.3.3", + "scope-analyzer": "^2.0.1", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.5", + "through2": "~2.0.3" + }, + "dependencies": { + "escodegen": { + "version": "1.14.3", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "levn": { + "version": "0.3.0", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2" + }, + "source-map": { + "version": "0.6.1", + "optional": true + }, + "through2": { + "version": "2.0.5", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "type-check": { + "version": "0.3.2", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "stencil-wormhole": { + "version": "3.4.1" + }, + "stream-combiner2": { + "version": "1.1.1", + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-argv": { + "version": "0.3.1", + "dev": true + }, + "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": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true + } + } + }, + "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": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "dev": true + }, + "strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "dev": true + }, + "strip-indent": { + "version": "3.0.0", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "style-mod": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", + "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==" + }, + "style-search": { + "version": "0.1.0", + "dev": true + }, + "stylehacks": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", + "integrity": "sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "postcss-selector-parser": "^6.0.4" + } + }, + "stylelint": { + "version": "14.13.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz", + "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.2", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^7.0.1", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.2.0", + "ignore": "^5.2.0", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.25.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.16", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^2.3.0", + "svg-tags": "^1.0.0", + "table": "^6.8.0", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^4.0.2" + }, + "dependencies": { + "balanced-match": { + "version": "2.0.0", + "dev": true + }, + "global-modules": { + "version": "2.0.0", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + }, + "meow": { + "version": "9.0.0", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + } + } + } + }, + "stylelint-config-recommended": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-9.0.0.tgz", + "integrity": "sha512-9YQSrJq4NvvRuTbzDsWX3rrFOzOlYBmZP+o513BJN/yfEmGSr0AxdvrWs0P/ilSpVV/wisamAHu5XSk8Rcf4CQ==", + "dev": true, + "requires": {} + }, + "stylelint-config-standard": { + "version": "28.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-28.0.0.tgz", + "integrity": "sha512-q/StuowDdDmFCravzGHAwgS9pjX0bdOQUEBBDIkIWsQuYGgYz/xsO8CM6eepmIQ1fc5bKdDVimlJZ6MoOUcJ5Q==", + "dev": true, + "requires": { + "stylelint-config-recommended": "^9.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "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==" + }, + "svg-tags": { + "version": "1.0.0", + "dev": true + }, + "svg-to-pdfkit": { + "version": "0.1.8", + "requires": { + "pdfkit": ">=0.8.1" + } + }, + "svgo": { + "version": "2.8.0", + "dev": true, + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "dev": true + }, + "css-select": { + "version": "4.1.3", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.0.0", + "domhandler": "^4.2.0", + "domutils": "^2.6.0", + "nth-check": "^2.0.0" + } + }, + "css-what": { + "version": "5.0.1", + "dev": true + }, + "dom-serializer": { + "version": "1.3.2", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "dev": true + }, + "domhandler": { + "version": "4.2.0", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.7.0", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "nth-check": { + "version": "2.0.1", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + } + } + }, + "symbol-tree": { + "version": "3.2.4" + }, + "table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "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": { + "color-convert": "^2.0.1" + } + }, + "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 + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + } + } + }, + "tailwindcss": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz", + "integrity": "sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==", + "dev": true, + "requires": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.6", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.14", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "dependencies": { + "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 + }, + "glob-parent": { + "version": "6.0.2", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "lilconfig": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "dev": true + }, + "postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "quick-lru": { + "version": "5.1.1", + "dev": true + } + } + }, + "temp-dir": { + "version": "2.0.0", + "dev": true + }, + "tempy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", + "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", + "dev": true, + "requires": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "dependencies": { + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true + } + } + }, + "terser": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", + "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "text-extensions": { + "version": "1.9.0", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "dev": true + }, + "thenby": { + "version": "1.3.4", + "dev": true + }, + "through": { + "version": "2.3.8" + }, + "through2": { + "version": "4.0.2", + "dev": true, + "requires": { + "readable-stream": "3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "tiny-inflate": { + "version": "1.0.3" + }, + "tinyqueue": { + "version": "2.0.3" + }, + "tmp": { + "version": "0.0.33", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tough-cookie": { + "version": "4.0.0", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "tr46": { + "version": "2.1.0", + "requires": { + "punycode": "^2.1.1" + } + }, + "traverse": { + "version": "0.6.6", + "dev": true + }, + "trim-newlines": { + "version": "3.0.1", + "dev": true + }, + "ts-node": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", + "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + } + } + }, + "tslib": { + "version": "1.13.0", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type": { + "version": "1.2.0" + }, + "type-check": { + "version": "0.4.0", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.18.1", + "dev": true + }, + "typedarray": { + "version": "0.0.6" + }, + "typescript": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "dev": true + }, + "uglify-js": { + "version": "3.14.5", + "dev": true, + "optional": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true + }, + "unicode-properties": { + "version": "1.3.1", + "requires": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true + }, + "unicode-trie": { + "version": "2.0.0", + "requires": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "unique-string": { + "version": "2.0.0", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universal-user-agent": { + "version": "6.0.0", + "dev": true + }, + "universalify": { + "version": "0.1.2" + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", + "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url-join": { + "version": "4.0.1", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2" + }, + "v8-compile-cache": { + "version": "2.3.0", + "dev": true + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vite": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.8.6.tgz", + "integrity": "sha512-e4H0QpludOVKkmOsRyqQ7LTcMUDF3mcgyNU4lmi0B5JUbe0ZxeBBl8VoZ8Y6Rfn9eFKYtdXNPcYK97ZwH+K2ug==", + "dev": true, + "requires": { + "esbuild": "^0.14.14", + "fsevents": "~2.3.2", + "postcss": "^8.4.6", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + } + }, + "vite-plugin-pwa": { + "version": "0.12.8", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.12.8.tgz", + "integrity": "sha512-pSiFHmnJGMQJJL8aJzQ8SaraZBSBPMGvGUkCNzheIq9UQCEk/eP3UmANNmS9eupuhIpTK8AdxTOHcaMcAqAbCA==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "fast-glob": "^3.2.11", + "pretty-bytes": "^6.0.0", + "rollup": "^2.75.7", + "workbox-build": "^6.5.3", + "workbox-window": "^6.5.3" + } + }, + "w3c-hr-time": { + "version": "1.0.2", + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-keyname": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", + "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "wavesurfer.js": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-6.3.0.tgz", + "integrity": "sha512-x7efObHMHY3nwqWzIC0yeZTo0u/aC9T5Av6KhSdhTlsgtKdTG7JAE3mNqnYBXUjq0yGYfTB9F85/pks9830Vjw==" + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "webidl-conversions": { + "version": "6.1.0" + }, + "whatwg-encoding": { + "version": "1.0.5", + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0" + }, + "whatwg-url": { + "version": "8.7.0", + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "which": { + "version": "1.3.1", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "dev": true + }, + "wmf": { + "version": "1.0.2" + }, + "word": { + "version": "0.4.0", + "requires": { + "cfb": "^1.2.0", + "jsdom": "^16.2.2" + } + }, + "word-wrap": { + "version": "1.2.3" + }, + "wordwrap": { + "version": "1.0.0", + "dev": true + }, + "workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "dev": true, + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "dev": true, + "requires": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.5.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "dependencies": { + "@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dev": true, + "requires": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + } + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "requires": { + "whatwg-url": "^7.0.0" + } + }, + "tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dev": true, + "requires": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==", + "dev": true + }, + "workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "dev": true, + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "dev": true, + "requires": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "dev": true, + "requires": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dev": true, + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "dev": true, + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==", + "dev": true + }, + "workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "dev": true, + "requires": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "dev": true + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "ws": { + "version": "7.5.5", + "requires": {} + }, + "xlsx": { + "version": "0.17.2", + "requires": { + "adler-32": "~1.2.0", + "cfb": "^1.1.4", + "codepage": "~1.15.0", + "commander": "~2.17.1", + "crc-32": "~1.2.0", + "exit-on-epipe": "~1.0.1", + "fflate": "^0.3.8", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.4.0" + }, + "dependencies": { + "commander": { + "version": "2.17.1" + } + } + }, + "xml-formatter": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-2.6.1.tgz", + "integrity": "sha512-dOiGwoqm8y22QdTNI7A+N03tyVfBlQ0/oehAzxIZtwnFAHGeSlrfjF73YQvzSsa/Kt6+YZasKsrdu6OIpuBggw==", + "requires": { + "xml-parser-xo": "^3.2.0" + } + }, + "xml-name-validator": { + "version": "3.0.0" + }, + "xml-parser-xo": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-3.2.0.tgz", + "integrity": "sha512-8LRU6cq+d7mVsoDaMhnkkt3CTtAs4153p49fRo+HIB3I1FD1o5CeXRjRH29sQevIfVJIcPjKSsPU/+Ujhq09Rg==" + }, + "xmlchars": { + "version": "2.2.0" + }, + "xmldoc": { + "version": "1.1.2", + "requires": { + "sax": "^1.2.1" + } + }, + "xtend": { + "version": "4.0.2" + }, + "y18n": { + "version": "5.0.5", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "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.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.7", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json index 3b51642c..e2c2cb63 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,9 @@ { - "name": "castopod", - "version": "2.0.0-next.3", + "name": "castopod-host", + "version": "1.0.0-beta.24", "description": "Castopod Host is an open-source hosting platform made for podcasters who want engage and interact with their audience.", "private": true, "license": "AGPL-3.0-or-later", - "type": "module", "repository": { "type": "git", "url": "https://code.castopod.org/adaures/castopod.git" @@ -13,104 +12,91 @@ "dev": "vite", "build": "tsc && vite build", "serve": "vite preview", - "build:static": "pnpm run build:icons && pnpm run build:svg", - "build:icons": "svgo -f resources/icons -o resources/icons -r --config=./.svgo.icons.cjs", - "build:svg": "svgo -f resources/static/images -o resources/static/images -r --config=./.svgo.cjs", - "lint": "eslint", - "lint:fix": "eslint --fix", - "lint:css": "stylelint -f verbose \"resources/**/*.css\"", - "lint:css:fix": "stylelint -f verbose --fix \"resources/**/*.css\"", - "prettier": "prettier --check . --ignore-path ./.gitignore --ignore-path ./docs/.gitignore", - "format": "prettier --write . --ignore-path ./.gitignore --ignore-path ./docs/.gitignore", + "build:static": "npm run build:icons && npm run build:svg", + "build:icons": "svgo -f app/Resources/icons -o public/assets/icons -r --config=./.svgo.icons.js", + "build:svg": "svgo -f app/Resources/images -o public/assets/images -r --config=./.svgo.js", + "lint": "eslint --ext js,ts app/Resources", + "lint:fix": "eslint --ext js,ts app/Resources --fix", + "lint:css": "stylelint \"app/Resources/**/*.css\"", + "lint:css:fix": "stylelint --fix \"app/Resources/**/*.css\"", + "prettier": "prettier --check --ignore-path .gitignore .", + "prettier:fix": "prettier --write --ignore-path .gitignore .", "typecheck": "tsc", - "all-contributors:add": "all-contributors add", - "all-contributors:generate": "all-contributors generate", "commit": "cz", "release": "semantic-release", - "prepare": "is-ci || husky" + "prepare": "is-ci || husky install" }, "dependencies": { - "@amcharts/amcharts4": "^4.10.40", - "@amcharts/amcharts4-geodata": "^4.1.31", - "@codemirror/commands": "^6.10.2", - "@codemirror/lang-html": "^6.4.11", - "@codemirror/lang-xml": "^6.1.0", - "@codemirror/language": "^6.12.1", - "@codemirror/state": "^6.5.4", - "@codemirror/view": "^6.39.14", - "@floating-ui/dom": "^1.7.5", - "@github/clipboard-copy-element": "^1.3.0", - "@github/hotkey": "^3.1.1", - "@github/markdown-toolbar-element": "^2.2.3", - "@github/relative-time-element": "^5.0.0", - "@patternfly/elements": "^4.3.1", - "@vime/core": "^5.4.1", - "choices.js": "^11.1.0", - "codemirror": "^6.0.2", + "@amcharts/amcharts4": "^4.10.29", + "@amcharts/amcharts4-geodata": "^4.1.23", + "@codemirror/commands": "^6.1.2", + "@codemirror/lang-xml": "^6.0.0", + "@codemirror/language": "^6.2.1", + "@codemirror/state": "^6.1.2", + "@floating-ui/dom": "^1.0.2", + "@github/clipboard-copy-element": "^1.1.2", + "@github/hotkey": "^2.0.1", + "@github/markdown-toolbar-element": "^2.1.1", + "@github/time-elements": "^3.1.4", + "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", + "@vime/core": "^5.3.3", + "choices.js": "^10.1.0", + "codemirror": "^6.0.1", "flatpickr": "^4.6.13", - "htmlfy": "^1.0.1", - "leaflet": "^1.9.4", + "leaflet": "^1.9.2", "leaflet.markercluster": "^1.5.3", - "lit": "^3.3.2", - "marked": "^17.0.3", - "wavesurfer.js": "^7.12.1", - "xml-formatter": "^3.6.7" + "lit": "^2.4.0", + "marked": "^4.1.1", + "wavesurfer.js": "^6.3.0", + "xml-formatter": "^2.6.1" }, "devDependencies": { - "@commitlint/cli": "^20.4.2", - "@commitlint/config-conventional": "^20.4.2", - "@csstools/css-tokenizer": "^4.0.0", - "@eslint/eslintrc": "^3.3.3", - "@eslint/js": "^10.0.1", - "@semantic-release/changelog": "^6.0.3", - "@semantic-release/exec": "^7.1.0", + "@commitlint/cli": "^17.1.2", + "@commitlint/config-conventional": "^17.1.0", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", - "@semantic-release/gitlab": "^13.3.0", - "@tailwindcss/forms": "^0.5.11", - "@tailwindcss/typography": "^0.5.19", - "@types/leaflet": "^1.9.21", - "all-contributors-cli": "^6.26.1", - "commitizen": "^4.3.1", - "conventional-changelog-conventionalcommits": "^9.1.0", - "cross-env": "^10.1.0", - "cssnano": "^7.1.2", + "@semantic-release/gitlab": "^9.4.2", + "@tailwindcss/forms": "^0.5.3", + "@tailwindcss/line-clamp": "^0.4.2", + "@tailwindcss/typography": "^0.5.7", + "@types/leaflet": "^1.8.0", + "@types/marked": "^4.0.7", + "@types/wavesurfer.js": "^6.0.3", + "@typescript-eslint/eslint-plugin": "^5.40.0", + "@typescript-eslint/parser": "^5.40.0", + "all-contributors-cli": "^6.24.0", + "cross-env": "^7.0.3", + "cssnano": "^5.1.13", "cz-conventional-changelog": "^3.3.0", - "eslint": "^10.0.0", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-prettier": "^5.5.5", - "glob": "^13.0.5", - "globals": "^17.3.0", - "husky": "^9.1.7", - "is-ci": "^4.1.0", - "lint-staged": "^16.2.7", - "postcss": "^8.5.6", - "postcss-import": "^16.1.1", - "postcss-nesting": "^14.0.0", - "postcss-preset-env": "^11.1.3", - "postcss-reporter": "^7.1.0", - "prettier": "3.8.1", - "prettier-plugin-organize-imports": "^4.3.0", - "semantic-release": "^25.0.3", - "sharp": "^0.34.5", - "stylelint": "^17.3.0", - "stylelint-config-standard": "^40.0.0", - "svgo": "^4.0.0", - "tailwindcss": "^3.4.19", - "typescript": "~5.9.3", - "typescript-eslint": "^8.56.0", - "vite": "^7.3.1", - "vite-plugin-codeigniter": "^2.0.0", - "vite-plugin-inspect": "^11.3.3", - "vite-plugin-pwa": "^1.2.0", - "vite-plugin-static-copy": "^3.2.0", - "workbox-build": "^7.4.0", - "workbox-core": "^7.4.0", - "workbox-routing": "^7.4.0", - "workbox-strategies": "^7.4.0" + "eslint": "^8.25.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.2.1", + "husky": "^8.0.1", + "is-ci": "^3.0.1", + "lint-staged": "^13.0.3", + "postcss-import": "^15.0.0", + "postcss-nesting": "^10.2.0", + "postcss-preset-env": "^7.8.2", + "postcss-reporter": "^7.0.5", + "prettier": "2.7.1", + "prettier-plugin-organize-imports": "^3.1.1", + "semantic-release": "^19.0.5", + "stylelint": "^14.13.0", + "stylelint-config-standard": "^28.0.0", + "svgo": "^2.8.0", + "tailwindcss": "^3.1.8", + "typescript": "^4.8.4", + "vite": "2.8.6", + "vite-plugin-pwa": "^0.12.8", + "workbox-build": "^6.5.4", + "workbox-core": "^6.5.4", + "workbox-routing": "^6.5.4", + "workbox-strategies": "^6.5.4" }, "lint-staged": { "*.{js,ts,css,md,json}": "prettier --write", - "*.{ts,js}": "eslint --fix", + "*.{ts,js}": "eslint --ext js,ts,tsx app/Resources --fix", "*.css": "stylelint --fix" }, "config": { diff --git a/php-icons.php b/php-icons.php deleted file mode 100644 index afcb4588..00000000 --- a/php-icons.php +++ /dev/null @@ -1,21 +0,0 @@ -withPaths([__DIR__ . '/app', __DIR__ . '/themes', __DIR__ . '/resources']) - ->withLocalIconSets([ - 'funding' => __DIR__ . '/resources/icons/funding', - 'podcasting' => __DIR__ . '/resources/icons/podcasting', - 'social' => __DIR__ . '/resources/icons/social', - 'custom' => __DIR__ . '/resources/icons/custom', - ]) - ->withDefaultIconPerSet([ - 'funding' => 'funding:default', - 'podcasting' => 'podcasting:default', - 'social' => 'social:default', - ]) - ->withDefaultPrefix('ri') - ->withPlaceholder('�'); diff --git a/phpstan.neon b/phpstan.neon index 37bf9c76..cbedb485 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,51 +3,23 @@ parameters: level: 6 paths: - app - - modules - tests bootstrapFiles: - vendor/codeigniter4/framework/system/Test/bootstrap.php scanDirectories: - - app - - modules - - vendor/codeigniter4 + - app/Helpers + - modules/Analytics/Helpers + - modules/Fediverse/Helpers + - modules/PremiumPodcasts/Helpers + - vendor/codeigniter4/framework/system/Helpers + - vendor/myth/auth/src/Helpers excludePaths: - app/Libraries/Router.php - app/Views/* - modules/*/Views/* - themes/* - codeigniter: - additionalConfigNamespaces: - - Modules\Admin\Config\ - - Modules\Analytics\Config\ - - Modules\Api\Rest\V1\Config\ - - Modules\Auth\Config\ - - Modules\Fediverse\Config\ - - Modules\Install\Config\ - - Modules\Media\Config\ - - Modules\MediaClipper\Config\ - - Modules\Plugins\Config\ - - Modules\PodcastImport\Config\ - - Modules\PremiumPodcasts\Config\ - - Modules\WebSub\Config\ - - ViewThemes\Config\ - - Vite\Config\ - additionalModelNamespaces: - - Modules\Analytics\Models\ - - Modules\Auth\Models\ - - Modules\Fediverse\Models\ - - Modules\Media\Models\ - - Modules\PremiumPodcasts\Models\ - - CodeIgniter\Shield\Models\ - additionalServices: - - CodeIgniter\Settings\Config\Services - - CodeIgniter\Shield\Config\Services - - Michalsn\Uuid\Config\Services - - Modules\Media\Config\Services - - Modules\Platforms\Config\Services - - Modules\Plugins\Config\Services - - Modules\PremiumPodcasts\Config\Services - - Modules\Api\Rest\V1\Config\Services ignoreErrors: - - identifier: missingType.generics - - '#\$callback of static method CodeIgniter\\Events\\Events\:\:on\(\) expects callable\(mixed\)\: mixed, Closure\(mixed, mixed\)\: void given.#' + - '#Cannot access property [\$a-z_]+ on ((array\|)?object)#' + - '#^Call to an undefined method CodeIgniter\\Database\\ConnectionInterface#' + - '#^Access to an undefined property App\\Entities\\Media\\Image#' + - '#^Call to an undefined method CodeIgniter\\HTTP\\RequestInterface#' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 766a18f5..dcd86923 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,66 +1,56 @@ - - - - - - - - - - - - - ./tests - - - - - - - - - - ./app - - - ./app/Views - ./app/Config/Routes.php - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + ./app + + + ./app/Views + ./app/Config/Routes.php + + + + + + + + + + + ./tests + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 6e2c7420..00000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,16208 +0,0 @@ -lockfileVersion: "9.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - .: - dependencies: - "@amcharts/amcharts4": - specifier: ^4.10.40 - version: 4.10.40 - "@amcharts/amcharts4-geodata": - specifier: ^4.1.31 - version: 4.1.31 - "@codemirror/commands": - specifier: ^6.10.2 - version: 6.10.2 - "@codemirror/lang-html": - specifier: ^6.4.11 - version: 6.4.11 - "@codemirror/lang-xml": - specifier: ^6.1.0 - version: 6.1.0 - "@codemirror/language": - specifier: ^6.12.1 - version: 6.12.1 - "@codemirror/state": - specifier: ^6.5.4 - version: 6.5.4 - "@codemirror/view": - specifier: ^6.39.14 - version: 6.39.14 - "@floating-ui/dom": - specifier: ^1.7.5 - version: 1.7.5 - "@github/clipboard-copy-element": - specifier: ^1.3.0 - version: 1.3.0 - "@github/hotkey": - specifier: ^3.1.1 - version: 3.1.1 - "@github/markdown-toolbar-element": - specifier: ^2.2.3 - version: 2.2.3 - "@github/relative-time-element": - specifier: ^5.0.0 - version: 5.0.0 - "@patternfly/elements": - specifier: ^4.3.1 - version: 4.3.1 - "@vime/core": - specifier: ^5.4.1 - version: 5.4.1 - choices.js: - specifier: ^11.1.0 - version: 11.1.0 - codemirror: - specifier: ^6.0.2 - version: 6.0.2 - flatpickr: - specifier: ^4.6.13 - version: 4.6.13 - htmlfy: - specifier: ^1.0.1 - version: 1.0.1 - leaflet: - specifier: ^1.9.4 - version: 1.9.4 - leaflet.markercluster: - specifier: ^1.5.3 - version: 1.5.3(leaflet@1.9.4) - lit: - specifier: ^3.3.2 - version: 3.3.2 - marked: - specifier: ^17.0.3 - version: 17.0.3 - wavesurfer.js: - specifier: ^7.12.1 - version: 7.12.1 - xml-formatter: - specifier: ^3.6.7 - version: 3.6.7 - devDependencies: - "@commitlint/cli": - specifier: ^20.4.2 - version: 20.4.2(@types/node@24.7.0)(typescript@5.9.3) - "@commitlint/config-conventional": - specifier: ^20.4.2 - version: 20.4.2 - "@csstools/css-tokenizer": - specifier: ^4.0.0 - version: 4.0.0 - "@eslint/eslintrc": - specifier: ^3.3.3 - version: 3.3.3 - "@eslint/js": - specifier: ^10.0.1 - version: 10.0.1(eslint@10.0.0(jiti@1.21.7)) - "@semantic-release/changelog": - specifier: ^6.0.3 - version: 6.0.3(semantic-release@25.0.3(typescript@5.9.3)) - "@semantic-release/exec": - specifier: ^7.1.0 - version: 7.1.0(semantic-release@25.0.3(typescript@5.9.3)) - "@semantic-release/git": - specifier: ^10.0.1 - version: 10.0.1(semantic-release@25.0.3(typescript@5.9.3)) - "@semantic-release/gitlab": - specifier: ^13.3.0 - version: 13.3.0(semantic-release@25.0.3(typescript@5.9.3)) - "@tailwindcss/forms": - specifier: ^0.5.11 - version: 0.5.11(tailwindcss@3.4.19(yaml@2.8.2)) - "@tailwindcss/typography": - specifier: ^0.5.19 - version: 0.5.19(tailwindcss@3.4.19(yaml@2.8.2)) - "@types/leaflet": - specifier: ^1.9.21 - version: 1.9.21 - all-contributors-cli: - specifier: ^6.26.1 - version: 6.26.1 - commitizen: - specifier: ^4.3.1 - version: 4.3.1(@types/node@24.7.0)(typescript@5.9.3) - conventional-changelog-conventionalcommits: - specifier: ^9.1.0 - version: 9.1.0 - cross-env: - specifier: ^10.1.0 - version: 10.1.0 - cssnano: - specifier: ^7.1.2 - version: 7.1.2(postcss@8.5.6) - cz-conventional-changelog: - specifier: ^3.3.0 - version: 3.3.0(@types/node@24.7.0)(typescript@5.9.3) - eslint: - specifier: ^10.0.0 - version: 10.0.0(jiti@1.21.7) - eslint-config-prettier: - specifier: ^10.1.8 - version: 10.1.8(eslint@10.0.0(jiti@1.21.7)) - eslint-plugin-prettier: - specifier: ^5.5.5 - version: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.0.0(jiti@1.21.7)))(eslint@10.0.0(jiti@1.21.7))(prettier@3.8.1) - glob: - specifier: ^13.0.5 - version: 13.0.5 - globals: - specifier: ^17.3.0 - version: 17.3.0 - husky: - specifier: ^9.1.7 - version: 9.1.7 - is-ci: - specifier: ^4.1.0 - version: 4.1.0 - lint-staged: - specifier: ^16.2.7 - version: 16.2.7 - postcss: - specifier: ^8.5.6 - version: 8.5.6 - postcss-import: - specifier: ^16.1.1 - version: 16.1.1(postcss@8.5.6) - postcss-nesting: - specifier: ^14.0.0 - version: 14.0.0(postcss@8.5.6) - postcss-preset-env: - specifier: ^11.1.3 - version: 11.1.3(postcss@8.5.6) - postcss-reporter: - specifier: ^7.1.0 - version: 7.1.0(postcss@8.5.6) - prettier: - specifier: 3.8.1 - version: 3.8.1 - prettier-plugin-organize-imports: - specifier: ^4.3.0 - version: 4.3.0(prettier@3.8.1)(typescript@5.9.3) - semantic-release: - specifier: ^25.0.3 - version: 25.0.3(typescript@5.9.3) - sharp: - specifier: ^0.34.5 - version: 0.34.5 - stylelint: - specifier: ^17.3.0 - version: 17.3.0(typescript@5.9.3) - stylelint-config-standard: - specifier: ^40.0.0 - version: 40.0.0(stylelint@17.3.0(typescript@5.9.3)) - svgo: - specifier: ^4.0.0 - version: 4.0.0 - tailwindcss: - specifier: ^3.4.19 - version: 3.4.19(yaml@2.8.2) - typescript: - specifier: ~5.9.3 - version: 5.9.3 - typescript-eslint: - specifier: ^8.56.0 - version: 8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3) - vite: - specifier: ^7.3.1 - version: 7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2) - vite-plugin-codeigniter: - specifier: ^2.0.0 - version: 2.0.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)) - vite-plugin-inspect: - specifier: ^11.3.3 - version: 11.3.3(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)) - vite-plugin-pwa: - specifier: ^1.2.0 - version: 1.2.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0) - vite-plugin-static-copy: - specifier: ^3.2.0 - version: 3.2.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)) - workbox-build: - specifier: ^7.4.0 - version: 7.4.0 - workbox-core: - specifier: ^7.4.0 - version: 7.4.0 - workbox-routing: - specifier: ^7.4.0 - version: 7.4.0 - workbox-strategies: - specifier: ^7.4.0 - version: 7.4.0 - -packages: - "@actions/core@3.0.0": - resolution: - { - integrity: sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg==, - } - - "@actions/exec@3.0.0": - resolution: - { - integrity: sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==, - } - - "@actions/http-client@4.0.0": - resolution: - { - integrity: sha512-QuwPsgVMsD6qaPD57GLZi9sqzAZCtiJT8kVBCDpLtxhL5MydQ4gS+DrejtZZPdIYyB1e95uCK9Luyds7ybHI3g==, - } - - "@actions/io@3.0.2": - resolution: - { - integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==, - } - - "@alloc/quick-lru@5.2.0": - resolution: - { - integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==, - } - engines: { node: ">=10" } - - "@amcharts/amcharts4-geodata@4.1.31": - resolution: - { - integrity: sha512-ciX2rOX6YZaRv/GGXqQNjV4ixhe1Ke9r+4xlwm9YuUHZ5QZSfLx6obXRqhmQeTdnNcxjveMoZ//E7xfotvqgVg==, - } - - "@amcharts/amcharts4@4.10.40": - resolution: - { - integrity: sha512-F5RrlWCg/fIRvTnnXenWZg7bTlEWJDvELyvXVAAi5GFvFVF4IegIP1vk5TatkgBzYO5v+SNGj2S3N1MkLwYA8w==, - } - - "@apideck/better-ajv-errors@0.3.6": - resolution: - { - integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==, - } - engines: { node: ">=10" } - peerDependencies: - ajv: ">=8" - - "@babel/code-frame@7.29.0": - resolution: - { - integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==, - } - engines: { node: ">=6.9.0" } - - "@babel/compat-data@7.29.0": - resolution: - { - integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==, - } - engines: { node: ">=6.9.0" } - - "@babel/core@7.29.0": - resolution: - { - integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==, - } - engines: { node: ">=6.9.0" } - - "@babel/generator@7.29.1": - resolution: - { - integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-annotate-as-pure@7.27.3": - resolution: - { - integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-compilation-targets@7.28.6": - resolution: - { - integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-create-class-features-plugin@7.28.6": - resolution: - { - integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/helper-create-regexp-features-plugin@7.28.5": - resolution: - { - integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/helper-define-polyfill-provider@0.6.6": - resolution: - { - integrity: sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==, - } - peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - - "@babel/helper-globals@7.28.0": - resolution: - { - integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-member-expression-to-functions@7.28.5": - resolution: - { - integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-module-imports@7.28.6": - resolution: - { - integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-module-transforms@7.28.6": - resolution: - { - integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/helper-optimise-call-expression@7.27.1": - resolution: - { - integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-plugin-utils@7.28.6": - resolution: - { - integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-remap-async-to-generator@7.27.1": - resolution: - { - integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/helper-replace-supers@7.28.6": - resolution: - { - integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/helper-skip-transparent-expression-wrappers@7.27.1": - resolution: - { - integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-string-parser@7.27.1": - resolution: - { - integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-validator-identifier@7.28.5": - resolution: - { - integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-validator-option@7.27.1": - resolution: - { - integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==, - } - engines: { node: ">=6.9.0" } - - "@babel/helper-wrap-function@7.28.6": - resolution: - { - integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==, - } - engines: { node: ">=6.9.0" } - - "@babel/helpers@7.28.6": - resolution: - { - integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==, - } - engines: { node: ">=6.9.0" } - - "@babel/parser@7.29.0": - resolution: - { - integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==, - } - engines: { node: ">=6.0.0" } - hasBin: true - - "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5": - resolution: - { - integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1": - resolution: - { - integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1": - resolution: - { - integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1": - resolution: - { - integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.13.0 - - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6": - resolution: - { - integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": - resolution: - { - integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-import-assertions@7.28.6": - resolution: - { - integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-import-attributes@7.28.6": - resolution: - { - integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-unicode-sets-regex@7.18.6": - resolution: - { - integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-transform-arrow-functions@7.27.1": - resolution: - { - integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-async-generator-functions@7.29.0": - resolution: - { - integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-async-to-generator@7.28.6": - resolution: - { - integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-block-scoped-functions@7.27.1": - resolution: - { - integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-block-scoping@7.28.6": - resolution: - { - integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-class-properties@7.28.6": - resolution: - { - integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-class-static-block@7.28.6": - resolution: - { - integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.12.0 - - "@babel/plugin-transform-classes@7.28.6": - resolution: - { - integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-computed-properties@7.28.6": - resolution: - { - integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-destructuring@7.28.5": - resolution: - { - integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-dotall-regex@7.28.6": - resolution: - { - integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-duplicate-keys@7.27.1": - resolution: - { - integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0": - resolution: - { - integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-transform-dynamic-import@7.27.1": - resolution: - { - integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-explicit-resource-management@7.28.6": - resolution: - { - integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-exponentiation-operator@7.28.6": - resolution: - { - integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-export-namespace-from@7.27.1": - resolution: - { - integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-for-of@7.27.1": - resolution: - { - integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-function-name@7.27.1": - resolution: - { - integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-json-strings@7.28.6": - resolution: - { - integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-literals@7.27.1": - resolution: - { - integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-logical-assignment-operators@7.28.6": - resolution: - { - integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-member-expression-literals@7.27.1": - resolution: - { - integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-modules-amd@7.27.1": - resolution: - { - integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-modules-commonjs@7.28.6": - resolution: - { - integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-modules-systemjs@7.29.0": - resolution: - { - integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-modules-umd@7.27.1": - resolution: - { - integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-named-capturing-groups-regex@7.29.0": - resolution: - { - integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-transform-new-target@7.27.1": - resolution: - { - integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-nullish-coalescing-operator@7.28.6": - resolution: - { - integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-numeric-separator@7.28.6": - resolution: - { - integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-object-rest-spread@7.28.6": - resolution: - { - integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-object-super@7.27.1": - resolution: - { - integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-optional-catch-binding@7.28.6": - resolution: - { - integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-optional-chaining@7.28.6": - resolution: - { - integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-parameters@7.27.7": - resolution: - { - integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-private-methods@7.28.6": - resolution: - { - integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-private-property-in-object@7.28.6": - resolution: - { - integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-property-literals@7.27.1": - resolution: - { - integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-regenerator@7.29.0": - resolution: - { - integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-regexp-modifiers@7.28.6": - resolution: - { - integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-transform-reserved-words@7.27.1": - resolution: - { - integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-shorthand-properties@7.27.1": - resolution: - { - integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-spread@7.28.6": - resolution: - { - integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-sticky-regex@7.27.1": - resolution: - { - integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-template-literals@7.27.1": - resolution: - { - integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-typeof-symbol@7.27.1": - resolution: - { - integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-unicode-escapes@7.27.1": - resolution: - { - integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-unicode-property-regex@7.28.6": - resolution: - { - integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-unicode-regex@7.27.1": - resolution: - { - integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-unicode-sets-regex@7.28.6": - resolution: - { - integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/preset-env@7.29.0": - resolution: - { - integrity: sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/preset-modules@0.1.6-no-external-plugins": - resolution: - { - integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==, - } - peerDependencies: - "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 - - "@babel/runtime@7.28.6": - resolution: - { - integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==, - } - engines: { node: ">=6.9.0" } - - "@babel/template@7.28.6": - resolution: - { - integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==, - } - engines: { node: ">=6.9.0" } - - "@babel/traverse@7.29.0": - resolution: - { - integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==, - } - engines: { node: ">=6.9.0" } - - "@babel/types@7.29.0": - resolution: - { - integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==, - } - engines: { node: ">=6.9.0" } - - "@cacheable/memory@2.0.7": - resolution: - { - integrity: sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A==, - } - - "@cacheable/utils@2.3.4": - resolution: - { - integrity: sha512-knwKUJEYgIfwShABS1BX6JyJJTglAFcEU7EXqzTdiGCXur4voqkiJkdgZIQtWNFhynzDWERcTYv/sETMu3uJWA==, - } - - "@codemirror/autocomplete@6.20.0": - resolution: - { - integrity: sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==, - } - - "@codemirror/commands@6.10.2": - resolution: - { - integrity: sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ==, - } - - "@codemirror/lang-css@6.3.1": - resolution: - { - integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==, - } - - "@codemirror/lang-html@6.4.11": - resolution: - { - integrity: sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==, - } - - "@codemirror/lang-javascript@6.2.4": - resolution: - { - integrity: sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==, - } - - "@codemirror/lang-xml@6.1.0": - resolution: - { - integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==, - } - - "@codemirror/language@6.12.1": - resolution: - { - integrity: sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==, - } - - "@codemirror/lint@6.9.4": - resolution: - { - integrity: sha512-ABc9vJ8DEmvOWuH26P3i8FpMWPQkduD9Rvba5iwb6O3hxASgclm3T3krGo8NASXkHCidz6b++LWlzWIUfEPSWw==, - } - - "@codemirror/search@6.6.0": - resolution: - { - integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==, - } - - "@codemirror/state@6.5.4": - resolution: - { - integrity: sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==, - } - - "@codemirror/view@6.39.14": - resolution: - { - integrity: sha512-WJcvgHm/6Q7dvGT0YFv/6PSkoc36QlR0VCESS6x9tGsnF1lWLmmYxOgX3HH6v8fo6AvSLgpcs+H0Olre6MKXlg==, - } - - "@colors/colors@1.5.0": - resolution: - { - integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==, - } - engines: { node: ">=0.1.90" } - - "@commitlint/cli@20.4.2": - resolution: - { - integrity: sha512-YjYSX2yj/WsVoxh9mNiymfFS2ADbg2EK4+1WAsMuckwKMCqJ5PDG0CJU/8GvmHWcv4VRB2V02KqSiecRksWqZQ==, - } - engines: { node: ">=v18" } - hasBin: true - - "@commitlint/config-conventional@20.4.2": - resolution: - { - integrity: sha512-rwkTF55q7Q+6dpSKUmJoScV0f3EpDlWKw2UPzklkLS4o5krMN1tPWAVOgHRtyUTMneIapLeQwaCjn44Td6OzBQ==, - } - engines: { node: ">=v18" } - - "@commitlint/config-validator@20.4.0": - resolution: - { - integrity: sha512-zShmKTF+sqyNOfAE0vKcqnpvVpG0YX8F9G/ZIQHI2CoKyK+PSdladXMSns400aZ5/QZs+0fN75B//3Q5CHw++w==, - } - engines: { node: ">=v18" } - - "@commitlint/ensure@20.4.1": - resolution: - { - integrity: sha512-WLQqaFx1pBooiVvBrA1YfJNFqZF8wS/YGOtr5RzApDbV9tQ52qT5VkTsY65hFTnXhW8PcDfZLaknfJTmPejmlw==, - } - engines: { node: ">=v18" } - - "@commitlint/execute-rule@20.0.0": - resolution: - { - integrity: sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==, - } - engines: { node: ">=v18" } - - "@commitlint/format@20.4.0": - resolution: - { - integrity: sha512-i3ki3WR0rgolFVX6r64poBHXM1t8qlFel1G1eCBvVgntE3fCJitmzSvH5JD/KVJN/snz6TfaX2CLdON7+s4WVQ==, - } - engines: { node: ">=v18" } - - "@commitlint/is-ignored@20.4.1": - resolution: - { - integrity: sha512-In5EO4JR1lNsAv1oOBBO24V9ND1IqdAJDKZiEpdfjDl2HMasAcT7oA+5BKONv1pRoLG380DGPE2W2RIcUwdgLA==, - } - engines: { node: ">=v18" } - - "@commitlint/lint@20.4.2": - resolution: - { - integrity: sha512-buquzNRtFng6xjXvBU1abY/WPEEjCgUipNQrNmIWe8QuJ6LWLtei/LDBAzEe5ASm45+Q9L2Xi3/GVvlj50GAug==, - } - engines: { node: ">=v18" } - - "@commitlint/load@20.4.0": - resolution: - { - integrity: sha512-Dauup/GfjwffBXRJUdlX/YRKfSVXsXZLnINXKz0VZkXdKDcaEILAi9oflHGbfydonJnJAbXEbF3nXPm9rm3G6A==, - } - engines: { node: ">=v18" } - - "@commitlint/message@20.4.0": - resolution: - { - integrity: sha512-B5lGtvHgiLAIsK5nLINzVW0bN5hXv+EW35sKhYHE8F7V9Uz1fR4tx3wt7mobA5UNhZKUNgB/+ldVMQE6IHZRyA==, - } - engines: { node: ">=v18" } - - "@commitlint/parse@20.4.1": - resolution: - { - integrity: sha512-XNtZjeRcFuAfUnhYrCY02+mpxwY4OmnvD3ETbVPs25xJFFz1nRo/25nHj+5eM+zTeRFvWFwD4GXWU2JEtoK1/w==, - } - engines: { node: ">=v18" } - - "@commitlint/read@20.4.0": - resolution: - { - integrity: sha512-QfpFn6/I240ySEGv7YWqho4vxqtPpx40FS7kZZDjUJ+eHxu3azfhy7fFb5XzfTqVNp1hNoI3tEmiEPbDB44+cg==, - } - engines: { node: ">=v18" } - - "@commitlint/resolve-extends@20.4.0": - resolution: - { - integrity: sha512-ay1KM8q0t+/OnlpqXJ+7gEFQNlUtSU5Gxr8GEwnVf2TPN3+ywc5DzL3JCxmpucqxfHBTFwfRMXxPRRnR5Ki20g==, - } - engines: { node: ">=v18" } - - "@commitlint/rules@20.4.2": - resolution: - { - integrity: sha512-oz83pnp5Yq6uwwTAabuVQPNlPfeD2Y5ZjMb7Wx8FSUlu4sLYJjbBWt8031Z0osCFPfHzAwSYrjnfDFKtuSMdKg==, - } - engines: { node: ">=v18" } - - "@commitlint/to-lines@20.0.0": - resolution: - { - integrity: sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==, - } - engines: { node: ">=v18" } - - "@commitlint/top-level@20.4.0": - resolution: - { - integrity: sha512-NDzq8Q6jmFaIIBC/GG6n1OQEaHdmaAAYdrZRlMgW6glYWGZ+IeuXmiymDvQNXPc82mVxq2KiE3RVpcs+1OeDeA==, - } - engines: { node: ">=v18" } - - "@commitlint/types@20.4.0": - resolution: - { - integrity: sha512-aO5l99BQJ0X34ft8b0h7QFkQlqxC6e7ZPVmBKz13xM9O8obDaM1Cld4sQlJDXXU/VFuUzQ30mVtHjVz74TuStw==, - } - engines: { node: ">=v18" } - - "@csstools/cascade-layer-name-parser@3.0.0": - resolution: - { - integrity: sha512-/3iksyevwRfSJx5yH0RkcrcYXwuhMQx3Juqf40t97PeEy2/Mz2TItZ/z/216qpe4GgOyFBP8MKIwVvytzHmfIQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - "@csstools/css-parser-algorithms": ^4.0.0 - "@csstools/css-tokenizer": ^4.0.0 - - "@csstools/color-helpers@6.0.1": - resolution: - { - integrity: sha512-NmXRccUJMk2AWA5A7e5a//3bCIMyOu2hAtdRYrhPPHjDxINuCwX1w6rnIZ4xjLcp0ayv6h8Pc3X0eJUGiAAXHQ==, - } - engines: { node: ">=20.19.0" } - - "@csstools/css-calc@3.1.1": - resolution: - { - integrity: sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - "@csstools/css-parser-algorithms": ^4.0.0 - "@csstools/css-tokenizer": ^4.0.0 - - "@csstools/css-color-parser@4.0.1": - resolution: - { - integrity: sha512-vYwO15eRBEkeF6xjAno/KQ61HacNhfQuuU/eGwH67DplL0zD5ZixUa563phQvUelA07yDczIXdtmYojCphKJcw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - "@csstools/css-parser-algorithms": ^4.0.0 - "@csstools/css-tokenizer": ^4.0.0 - - "@csstools/css-parser-algorithms@4.0.0": - resolution: - { - integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - "@csstools/css-tokenizer": ^4.0.0 - - "@csstools/css-syntax-patches-for-csstree@1.0.27": - resolution: - { - integrity: sha512-sxP33Jwg1bviSUXAV43cVYdmjt2TLnLXNqCWl9xmxHawWVjGz/kEbdkr7F9pxJNBN2Mh+dq0crgItbW6tQvyow==, - } - - "@csstools/css-tokenizer@4.0.0": - resolution: - { - integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==, - } - engines: { node: ">=20.19.0" } - - "@csstools/media-query-list-parser@5.0.0": - resolution: - { - integrity: sha512-T9lXmZOfnam3eMERPsszjY5NK0jX8RmThmmm99FZ8b7z8yMaFZWKwLWGZuTwdO3ddRY5fy13GmmEYZXB4I98Eg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - "@csstools/css-parser-algorithms": ^4.0.0 - "@csstools/css-tokenizer": ^4.0.0 - - "@csstools/postcss-alpha-function@2.0.2": - resolution: - { - integrity: sha512-EXdJC5fds0h1KqoioUBkcYPZvcNKR64jrGkbqlDNbMU3FP1MzLEr/QJR8bj/bu53TJFIgkc9WvKcpbwVqZ4WPg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-cascade-layers@6.0.0": - resolution: - { - integrity: sha512-WhsECqmrEZQGqaPlBA7JkmF/CJ2/+wetL4fkL9sOPccKd32PQ1qToFM6gqSI5rkpmYqubvbxjEJhyMTHYK0vZQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-color-function-display-p3-linear@2.0.1": - resolution: - { - integrity: sha512-blnzzMkMswoagp1u3JS1OiiTuQCW1F+lQEtlxu2BXhTUmEeKHhSgrrAceF7s4bwZOwKYbkxuw/FC9Ni/zxB7Xw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-color-function@5.0.1": - resolution: - { - integrity: sha512-SNU4o63+oZpB7ufkTmj3FholvMtJwuyIWqTOVOxnZjNDFEg1hwdbnPjoytZVgKRQGkvkHdAS0uZWn0zH+ZwXCQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-color-mix-function@4.0.1": - resolution: - { - integrity: sha512-B9XBCd8cmHVwnc5YTn2YVXOlNMTNwuPIpJQ87665vaNdfNorVWz8JhAAv7Vq0v66TA6htE7+QW0OidL/QV0tiA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-color-mix-variadic-function-arguments@2.0.1": - resolution: - { - integrity: sha512-PV5nv9EHsEsvC5GlVqAHa1PznP/qZxFAIABImrkGJUbSoFUTwpnPch/dYSKw52CQ0aNnwCqMHoM29wDwmpVLqw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-content-alt-text@3.0.0": - resolution: - { - integrity: sha512-OHa+4aCcrJtHpPWB3zptScHwpS1TUbeLR4uO0ntIz0Su/zw9SoWkVu+tDMSySSAsNtNSI3kut4fTliFwIsrHxA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-contrast-color-function@3.0.1": - resolution: - { - integrity: sha512-Zy2gyAPsUyoAUkmBjLbWcXJhglM+toBRpNegyJc/LTHpSpIbMKVmByGQ+VSw01E1Pov8Dk/fgEs9hd11xtGC8g==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-exponential-functions@3.0.0": - resolution: - { - integrity: sha512-KCtnlZw1VrDCAbYxE44rUHONYAkjhh0/iS5T3L2K5OHuvoSEvxDjJO82pRwTmsRxVtSiC+syPjx2k2xsqHOM7w==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-font-format-keywords@5.0.0": - resolution: - { - integrity: sha512-M1EjCe/J3u8fFhOZgRci74cQhJ7R0UFBX6T+WqoEvjrr8hVfMiV+HTYrzxLY5OW8YllvXYr5Q5t5OvJbsUSeDg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-gamut-mapping@3.0.1": - resolution: - { - integrity: sha512-0S7D+gArVXsgRDxjoNv8g2QlaIi/SegqdlTMgVwowaPSyxaZsVnwrhShvmlpoLOVHmpJfHKGiXzn1Hc1BcZCzQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-gradients-interpolation-method@6.0.1": - resolution: - { - integrity: sha512-Y5dxOstuUCdmU1tuEB/EgKxDw+/DAZes4gQeitb/H0S5khmjT24CfbVa/l2ZelNCEEq9KjxqO2cjwDV2vqj62w==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-hwb-function@5.0.1": - resolution: - { - integrity: sha512-9f8TA/B8iEpzF0y4Z6qPVfP9nMp2ti10OFbtyDtoBz3+eK0KPV4CCCjTwYIpPRopLgctFZt7xqmOxA7JgAJEug==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-ic-unit@5.0.0": - resolution: - { - integrity: sha512-/ws5d6c4uKqfM9zIL3ugcGI+3fvZEOOkJHNzAyTAGJIdZ+aSL9BVPNlHGV4QzmL0vqBSCOdU3+rhcMEj3+KzYw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-initial@3.0.0": - resolution: - { - integrity: sha512-UVUrFmrTQyLomVepnjWlbBg7GoscLmXLwYFyjbcEnmpeGW7wde6lNpx5eM3eVwZI2M+7hCE3ykYnAsEPLcLa+Q==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-is-pseudo-class@6.0.0": - resolution: - { - integrity: sha512-1Hdy/ykg9RDo8vU8RiM2o+RaXO39WpFPaIkHxlAEJFofle/lc33tdQMKhBk3jR/Fe+uZNLOs3HlowFafyFptVw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-light-dark-function@3.0.0": - resolution: - { - integrity: sha512-s++V5/hYazeRUCYIn2lsBVzUsxdeC46gtwpgW6lu5U/GlPOS5UTDT14kkEyPgXmFbCvaWLREqV7YTMJq1K3G6w==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-logical-float-and-clear@4.0.0": - resolution: - { - integrity: sha512-NGzdIRVj/VxOa/TjVdkHeyiJoDihONV0+uB0csUdgWbFFr8xndtfqK8iIGP9IKJzco+w0hvBF2SSk2sDSTAnOQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-logical-overflow@3.0.0": - resolution: - { - integrity: sha512-5cRg93QXVskM0MNepHpPcL0WLSf5Hncky0DrFDQY/4ozbH5lH7SX5ejayVpNTGSX7IpOvu7ykQDLOdMMGYzwpA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-logical-overscroll-behavior@3.0.0": - resolution: - { - integrity: sha512-82Jnl/5Wi5jb19nQE1XlBHrZcNL3PzOgcj268cDkfwf+xi10HBqufGo1Unwf5n8bbbEFhEKgyQW+vFsc9iY1jw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-logical-resize@4.0.0": - resolution: - { - integrity: sha512-L0T3q0gei/tGetCGZU0c7VN77VTivRpz1YZRNxjXYmW+85PKeI6U9YnSvDqLU2vBT2uN4kLEzfgZ0ThIZpN18A==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-logical-viewport-units@4.0.0": - resolution: - { - integrity: sha512-TA3AqVN/1IH3dKRC2UUWvprvwyOs2IeD7FDZk5Hz20w4q33yIuSg0i0gjyTUkcn90g8A4n7QpyZ2AgBrnYPnnA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-media-minmax@3.0.0": - resolution: - { - integrity: sha512-42szvyZ/oqG7NSvBQOGq1IaJaHR6mr/iXqqjW8/JuIajIHRs9HcJR5ExC4vbyCqk+fr7/DIOhm5ZrELBytLDsw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-media-queries-aspect-ratio-number-values@4.0.0": - resolution: - { - integrity: sha512-FDdC3lbrj8Vr0SkGIcSLTcRB7ApG6nlJFxOxkEF2C5hIZC1jtgjISFSGn/WjFdVkn8Dqe+Vx9QXI3axS2w1XHw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-mixins@1.0.0": - resolution: - { - integrity: sha512-rz6qjT2w9L3k65jGc2dX+3oGiSrYQ70EZPDrINSmSVoVys7lLBFH0tvEa8DW2sr9cbRVD/W+1sy8+7bfu0JUfg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-nested-calc@5.0.0": - resolution: - { - integrity: sha512-aPSw8P60e/i9BEfugauhikBqgjiwXcw3I9o4vXs+hktl4NSTgZRI0QHimxk9mst8N01A2TKDBxOln3mssRxiHQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-normalize-display-values@5.0.1": - resolution: - { - integrity: sha512-FcbEmoxDEGYvm2W3rQzVzcuo66+dDJjzzVDs+QwRmZLHYofGmMGwIKPqzF86/YW+euMDa7sh1xjWDvz/fzByZQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-oklab-function@5.0.1": - resolution: - { - integrity: sha512-Ql+X4zu29ITihxHKcCFEU84ww+Nkv44M2s0fT7Nv4iQYlQ4+liF6v9RL0ezeogeiLRNLLC6yh0ay1PHpmaNIgQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-position-area-property@2.0.0": - resolution: - { - integrity: sha512-TeEfzsJGB23Syv7yCm8AHCD2XTFujdjr9YYu9ebH64vnfCEvY4BG319jXAYSlNlf3Yc9PNJ6WnkDkUF5XVgSKQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-progressive-custom-properties@5.0.0": - resolution: - { - integrity: sha512-NsJoZ89rxmDrUsITf8QIk5w+lQZQ8Xw5K6cLFG+cfiffsLYHb3zcbOOrHLetGl1WIhjWWQ4Cr8MMrg46Q+oACg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-property-rule-prelude-list@2.0.0": - resolution: - { - integrity: sha512-qcMAkc9AhpzHgmQCD8hoJgGYifcOAxd1exXjjxilMM6euwRE619xDa4UsKBCv/v4g+sS63sd6c29LPM8s2ylSQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-random-function@3.0.0": - resolution: - { - integrity: sha512-H/Zt5o9NAd8mowq3XRy8uU19wOEe8sbKyKOKxrzOdG0rz2maA4fLcXc9MQucdm3s4zMDfVJtCqvwrLP7lKWybA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-relative-color-syntax@4.0.1": - resolution: - { - integrity: sha512-zRLO9xMGtCCT0FTpTsaGI6cmdzJKbwWjg92AuczlSDuriEAPEJL+ZJ4jDyw51p23DfoAFgK8soB/LyoY1kFOLQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-scope-pseudo-class@5.0.0": - resolution: - { - integrity: sha512-kBrBFJcAji3MSHS4qQIihPvJfJC5xCabXLbejqDMiQi+86HD4eMBiTayAo46Urg7tlEmZZQFymFiJt+GH6nvXw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-sign-functions@2.0.0": - resolution: - { - integrity: sha512-32Bw7++8ToSLMEOSJUuxJsAJJdsIfgeD1dYPKRCk9/fTciVZ8MjkPXypwiXIo7xIJk0h5CJz6QUkDoc6dcAJ7Q==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-stepped-value-functions@5.0.0": - resolution: - { - integrity: sha512-NueCSNbaq7QtAj6QwseMqOlM3C8nN2GWaPwd2Uw+IOYAbGvO/84BxUtNeZljeOmqJX61hwSNhLfwmgJXgY0W5A==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-syntax-descriptor-syntax-production@2.0.0": - resolution: - { - integrity: sha512-elYcbdiBXAkPqvojB9kIBRuHY6htUhjSITtFQ+XiXnt6SvZCbNGxQmaaw6uZ7SPHu/+i/XVjzIt09/1k3SIerQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-system-ui-font-family@2.0.0": - resolution: - { - integrity: sha512-FyGZCgchFImFyiHS2x3rD5trAqatf/x23veBLTIgbaqyFfna6RNBD+Qf8HRSjt6HGMXOLhAjxJ3OoZg0bbn7Qw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-text-decoration-shorthand@5.0.2": - resolution: - { - integrity: sha512-0VUTt79lfQ2LGQLfyOBeqpinDLzOf3w+tlA1Re/KjSOc86H6tRz6TeXbISrBSJlfM1fYKNmBNw+ON8Ovy6aNeg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-trigonometric-functions@5.0.0": - resolution: - { - integrity: sha512-isjkD3l1MVjanGuaS7RIYP/9txZKbZ8eQPaUHoxEWmySm3k6KutSepzPINL6MXyyi0ZUijZcktA++/L66IK71A==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/postcss-unset-value@5.0.0": - resolution: - { - integrity: sha512-EoO54sS2KCIfesvHyFYAW99RtzwHdgaJzhl7cqKZSaMYKZv3fXSOehDjAQx8WZBKn1JrMd7xJJI1T1BxPF7/jA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@csstools/selector-resolve-nested@4.0.0": - resolution: - { - integrity: sha512-9vAPxmp+Dx3wQBIUwc1v7Mdisw1kbbaGqXUM8QLTgWg7SoPGYtXBsMXvsFs/0Bn5yoFhcktzxNZGNaUt0VjgjA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss-selector-parser: ^7.1.1 - - "@csstools/selector-specificity@6.0.0": - resolution: - { - integrity: sha512-4sSgl78OtOXEX/2d++8A83zHNTgwCJMaR24FvsYL7Uf/VS8HZk9PTwR51elTbGqMuwH3szLvvOXEaVnqn0Z3zA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss-selector-parser: ^7.1.1 - - "@csstools/utilities@3.0.0": - resolution: - { - integrity: sha512-etDqA/4jYvOGBM6yfKCOsEXfH96BKztZdgGmGqKi2xHnDe0ILIBraRspwgYatJH9JsCZ5HCGoCst8w18EKOAdg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - "@emnapi/runtime@1.8.1": - resolution: - { - integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==, - } - - "@epic-web/invariant@1.0.0": - resolution: - { - integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==, - } - - "@esbuild/aix-ppc64@0.27.3": - resolution: - { - integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==, - } - engines: { node: ">=18" } - cpu: [ppc64] - os: [aix] - - "@esbuild/android-arm64@0.27.3": - resolution: - { - integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [android] - - "@esbuild/android-arm@0.27.3": - resolution: - { - integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==, - } - engines: { node: ">=18" } - cpu: [arm] - os: [android] - - "@esbuild/android-x64@0.27.3": - resolution: - { - integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [android] - - "@esbuild/darwin-arm64@0.27.3": - resolution: - { - integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [darwin] - - "@esbuild/darwin-x64@0.27.3": - resolution: - { - integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [darwin] - - "@esbuild/freebsd-arm64@0.27.3": - resolution: - { - integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [freebsd] - - "@esbuild/freebsd-x64@0.27.3": - resolution: - { - integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [freebsd] - - "@esbuild/linux-arm64@0.27.3": - resolution: - { - integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [linux] - - "@esbuild/linux-arm@0.27.3": - resolution: - { - integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==, - } - engines: { node: ">=18" } - cpu: [arm] - os: [linux] - - "@esbuild/linux-ia32@0.27.3": - resolution: - { - integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==, - } - engines: { node: ">=18" } - cpu: [ia32] - os: [linux] - - "@esbuild/linux-loong64@0.27.3": - resolution: - { - integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==, - } - engines: { node: ">=18" } - cpu: [loong64] - os: [linux] - - "@esbuild/linux-mips64el@0.27.3": - resolution: - { - integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==, - } - engines: { node: ">=18" } - cpu: [mips64el] - os: [linux] - - "@esbuild/linux-ppc64@0.27.3": - resolution: - { - integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==, - } - engines: { node: ">=18" } - cpu: [ppc64] - os: [linux] - - "@esbuild/linux-riscv64@0.27.3": - resolution: - { - integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==, - } - engines: { node: ">=18" } - cpu: [riscv64] - os: [linux] - - "@esbuild/linux-s390x@0.27.3": - resolution: - { - integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==, - } - engines: { node: ">=18" } - cpu: [s390x] - os: [linux] - - "@esbuild/linux-x64@0.27.3": - resolution: - { - integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [linux] - - "@esbuild/netbsd-arm64@0.27.3": - resolution: - { - integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [netbsd] - - "@esbuild/netbsd-x64@0.27.3": - resolution: - { - integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [netbsd] - - "@esbuild/openbsd-arm64@0.27.3": - resolution: - { - integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [openbsd] - - "@esbuild/openbsd-x64@0.27.3": - resolution: - { - integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [openbsd] - - "@esbuild/openharmony-arm64@0.27.3": - resolution: - { - integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [openharmony] - - "@esbuild/sunos-x64@0.27.3": - resolution: - { - integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [sunos] - - "@esbuild/win32-arm64@0.27.3": - resolution: - { - integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [win32] - - "@esbuild/win32-ia32@0.27.3": - resolution: - { - integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==, - } - engines: { node: ">=18" } - cpu: [ia32] - os: [win32] - - "@esbuild/win32-x64@0.27.3": - resolution: - { - integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [win32] - - "@eslint-community/eslint-utils@4.9.1": - resolution: - { - integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - "@eslint-community/regexpp@4.12.2": - resolution: - { - integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, - } - engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } - - "@eslint/config-array@0.23.1": - resolution: - { - integrity: sha512-uVSdg/V4dfQmTjJzR0szNczjOH/J+FyUMMjYtr07xFRXR7EDf9i1qdxrD0VusZH9knj1/ecxzCQQxyic5NzAiA==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - - "@eslint/config-helpers@0.5.2": - resolution: - { - integrity: sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - - "@eslint/core@1.1.0": - resolution: - { - integrity: sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - - "@eslint/eslintrc@3.3.3": - resolution: - { - integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@eslint/js@10.0.1": - resolution: - { - integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - peerDependencies: - eslint: ^10.0.0 - peerDependenciesMeta: - eslint: - optional: true - - "@eslint/object-schema@3.0.1": - resolution: - { - integrity: sha512-P9cq2dpr+LU8j3qbLygLcSZrl2/ds/pUpfnHNNuk5HW7mnngHs+6WSq5C9mO3rqRX8A1poxqLTC9cu0KOyJlBg==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - - "@eslint/plugin-kit@0.6.0": - resolution: - { - integrity: sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - - "@floating-ui/core@1.7.4": - resolution: - { - integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==, - } - - "@floating-ui/dom@1.7.5": - resolution: - { - integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==, - } - - "@floating-ui/utils@0.2.10": - resolution: - { - integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==, - } - - "@foliojs-fork/fontkit@1.9.2": - resolution: - { - integrity: sha512-IfB5EiIb+GZk+77TRB86AHroVaqfq8JRFlUbz0WEwsInyCG0epX2tCPOy+UfaWPju30DeVoUAXfzWXmhn753KA==, - } - - "@foliojs-fork/linebreak@1.1.2": - resolution: - { - integrity: sha512-ZPohpxxbuKNE0l/5iBJnOAfUaMACwvUIKCvqtWGKIMv1lPYoNjYXRfhi9FeeV9McBkBLxsMFWTVVhHJA8cyzvg==, - } - - "@foliojs-fork/pdfkit@0.15.3": - resolution: - { - integrity: sha512-Obc0Wmy3bm7BINFVvPhcl2rnSSK61DQrlHU8aXnAqDk9LCjWdUOPwhgD8Ywz5VtuFjRxmVOM/kQ/XLIBjDvltw==, - } - - "@foliojs-fork/restructure@2.0.2": - resolution: - { - integrity: sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==, - } - - "@github/clipboard-copy-element@1.3.0": - resolution: - { - integrity: sha512-wyntkQkwoLbLo+Hqg2LIVMXDIzcvUb9bSDz+clX6nVJItwzh103rHxdXFRZD+DmxVbuEW5xSznYQXkz1jZT+xg==, - } - - "@github/hotkey@3.1.1": - resolution: - { - integrity: sha512-H30I6XDO3gFSgLuEuHoMBRZG9c3uCKNdAcYklL1FaZDPdU1bXfgjnpzGDPcUr0U6eGQ+T3XLY9slatwZYWL1dA==, - } - - "@github/markdown-toolbar-element@2.2.3": - resolution: - { - integrity: sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A==, - } - - "@github/relative-time-element@5.0.0": - resolution: - { - integrity: sha512-L/2r0DNR/rMbmHWcsdmhtOiy2gESoGOhItNFD4zJ3nZfHl79Dx3N18Vfx/pYr2lruMOdk1cJZb4wEumm+Dxm1w==, - } - - "@humanfs/core@0.19.1": - resolution: - { - integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==, - } - engines: { node: ">=18.18.0" } - - "@humanfs/node@0.16.7": - resolution: - { - integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==, - } - engines: { node: ">=18.18.0" } - - "@humanwhocodes/module-importer@1.0.1": - resolution: - { - integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, - } - engines: { node: ">=12.22" } - - "@humanwhocodes/retry@0.4.3": - resolution: - { - integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==, - } - engines: { node: ">=18.18" } - - "@img/colour@1.0.0": - resolution: - { - integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==, - } - engines: { node: ">=18" } - - "@img/sharp-darwin-arm64@0.34.5": - resolution: - { - integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [darwin] - - "@img/sharp-darwin-x64@0.34.5": - resolution: - { - integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [darwin] - - "@img/sharp-libvips-darwin-arm64@1.2.4": - resolution: - { - integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==, - } - cpu: [arm64] - os: [darwin] - - "@img/sharp-libvips-darwin-x64@1.2.4": - resolution: - { - integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==, - } - cpu: [x64] - os: [darwin] - - "@img/sharp-libvips-linux-arm64@1.2.4": - resolution: - { - integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==, - } - cpu: [arm64] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-arm@1.2.4": - resolution: - { - integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==, - } - cpu: [arm] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-ppc64@1.2.4": - resolution: - { - integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==, - } - cpu: [ppc64] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-riscv64@1.2.4": - resolution: - { - integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==, - } - cpu: [riscv64] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-s390x@1.2.4": - resolution: - { - integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==, - } - cpu: [s390x] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linux-x64@1.2.4": - resolution: - { - integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==, - } - cpu: [x64] - os: [linux] - libc: [glibc] - - "@img/sharp-libvips-linuxmusl-arm64@1.2.4": - resolution: - { - integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==, - } - cpu: [arm64] - os: [linux] - libc: [musl] - - "@img/sharp-libvips-linuxmusl-x64@1.2.4": - resolution: - { - integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==, - } - cpu: [x64] - os: [linux] - libc: [musl] - - "@img/sharp-linux-arm64@0.34.5": - resolution: - { - integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-arm@0.34.5": - resolution: - { - integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-ppc64@0.34.5": - resolution: - { - integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [ppc64] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-riscv64@0.34.5": - resolution: - { - integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [riscv64] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-s390x@0.34.5": - resolution: - { - integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [s390x] - os: [linux] - libc: [glibc] - - "@img/sharp-linux-x64@0.34.5": - resolution: - { - integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [linux] - libc: [glibc] - - "@img/sharp-linuxmusl-arm64@0.34.5": - resolution: - { - integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [linux] - libc: [musl] - - "@img/sharp-linuxmusl-x64@0.34.5": - resolution: - { - integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [linux] - libc: [musl] - - "@img/sharp-wasm32@0.34.5": - resolution: - { - integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [wasm32] - - "@img/sharp-win32-arm64@0.34.5": - resolution: - { - integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [win32] - - "@img/sharp-win32-ia32@0.34.5": - resolution: - { - integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [ia32] - os: [win32] - - "@img/sharp-win32-x64@0.34.5": - resolution: - { - integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [win32] - - "@isaacs/cliui@9.0.0": - resolution: - { - integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==, - } - engines: { node: ">=18" } - - "@jridgewell/gen-mapping@0.3.13": - resolution: - { - integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==, - } - - "@jridgewell/remapping@2.3.5": - resolution: - { - integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==, - } - - "@jridgewell/resolve-uri@3.1.2": - resolution: - { - integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, - } - engines: { node: ">=6.0.0" } - - "@jridgewell/source-map@0.3.11": - resolution: - { - integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==, - } - - "@jridgewell/sourcemap-codec@1.5.5": - resolution: - { - integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, - } - - "@jridgewell/trace-mapping@0.3.31": - resolution: - { - integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, - } - - "@keyv/bigmap@1.3.1": - resolution: - { - integrity: sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==, - } - engines: { node: ">= 18" } - peerDependencies: - keyv: ^5.6.0 - - "@keyv/serialize@1.1.1": - resolution: - { - integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==, - } - - "@lezer/common@1.5.1": - resolution: - { - integrity: sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==, - } - - "@lezer/css@1.3.1": - resolution: - { - integrity: sha512-PYAKeUVBo3HFThruRyp/iK91SwiZJnzXh8QzkQlwijB5y+N5iB28+iLk78o2zmKqqV0uolNhCwFqB8LA7b0Svg==, - } - - "@lezer/highlight@1.2.3": - resolution: - { - integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==, - } - - "@lezer/html@1.3.13": - resolution: - { - integrity: sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==, - } - - "@lezer/javascript@1.5.4": - resolution: - { - integrity: sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==, - } - - "@lezer/lr@1.4.8": - resolution: - { - integrity: sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==, - } - - "@lezer/xml@1.0.6": - resolution: - { - integrity: sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==, - } - - "@lit-labs/ssr-dom-shim@1.5.1": - resolution: - { - integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==, - } - - "@lit/context@1.1.6": - resolution: - { - integrity: sha512-M26qDE6UkQbZA2mQ3RjJ3Gzd8TxP+/0obMgE5HfkfLhEEyYE3Bui4A5XHiGPjy0MUGAyxB3QgVuw2ciS0kHn6A==, - } - - "@lit/reactive-element@2.1.2": - resolution: - { - integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==, - } - - "@marijn/find-cluster-break@1.0.2": - resolution: - { - integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==, - } - - "@nodelib/fs.scandir@2.1.5": - resolution: - { - integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, - } - engines: { node: ">= 8" } - - "@nodelib/fs.stat@2.0.5": - resolution: - { - integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, - } - engines: { node: ">= 8" } - - "@nodelib/fs.walk@1.2.8": - resolution: - { - integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, - } - engines: { node: ">= 8" } - - "@octokit/auth-token@6.0.0": - resolution: - { - integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==, - } - engines: { node: ">= 20" } - - "@octokit/core@7.0.6": - resolution: - { - integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==, - } - engines: { node: ">= 20" } - - "@octokit/endpoint@11.0.3": - resolution: - { - integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==, - } - engines: { node: ">= 20" } - - "@octokit/graphql@9.0.3": - resolution: - { - integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==, - } - engines: { node: ">= 20" } - - "@octokit/openapi-types@27.0.0": - resolution: - { - integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==, - } - - "@octokit/plugin-paginate-rest@14.0.0": - resolution: - { - integrity: sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==, - } - engines: { node: ">= 20" } - peerDependencies: - "@octokit/core": ">=6" - - "@octokit/plugin-retry@8.1.0": - resolution: - { - integrity: sha512-O1FZgXeiGb2sowEr/hYTr6YunGdSAFWnr2fyW39Ah85H8O33ELASQxcvOFF5LE6Tjekcyu2ms4qAzJVhSaJxTw==, - } - engines: { node: ">= 20" } - peerDependencies: - "@octokit/core": ">=7" - - "@octokit/plugin-throttling@11.0.3": - resolution: - { - integrity: sha512-34eE0RkFCKycLl2D2kq7W+LovheM/ex3AwZCYN8udpi6bxsyjZidb2McXs69hZhLmJlDqTSP8cH+jSRpiaijBg==, - } - engines: { node: ">= 20" } - peerDependencies: - "@octokit/core": ^7.0.0 - - "@octokit/request-error@7.1.0": - resolution: - { - integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==, - } - engines: { node: ">= 20" } - - "@octokit/request@10.0.7": - resolution: - { - integrity: sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==, - } - engines: { node: ">= 20" } - - "@octokit/types@16.0.0": - resolution: - { - integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==, - } - - "@patternfly/elements@4.3.1": - resolution: - { - integrity: sha512-MRVwxcam+ACyy+0Xy5igPr+LcSVRbX422NGPE4I7WRuwAEhRBA3BayyLi8mNVKXpLLZbk8EtJ17kM30PcMziMw==, - } - - "@patternfly/icons@1.0.3": - resolution: - { - integrity: sha512-8BARaCFBUZU2/TxuOQb8R2/VIpxGMnFwdw5ddT1AMnR2KSifdo+d05SgZtVmFkOIAOA0oCo/YKRgSORDA47wig==, - } - - "@patternfly/pfe-core@5.0.6": - resolution: - { - integrity: sha512-95j0BDltTTVQzOSIqpiZXQYzm1kuwqpHeB/7/QOjmZP3wtvYcaccnE/2dldKF68rn0Rwgk9xbgz7MR8/CnKFgQ==, - } - - "@pkgr/core@0.2.9": - resolution: - { - integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==, - } - engines: { node: ^12.20.0 || ^14.18.0 || >=16.0.0 } - - "@pnpm/config.env-replace@1.1.0": - resolution: - { - integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==, - } - engines: { node: ">=12.22.0" } - - "@pnpm/network.ca-file@1.0.2": - resolution: - { - integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==, - } - engines: { node: ">=12.22.0" } - - "@pnpm/npm-conf@3.0.2": - resolution: - { - integrity: sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==, - } - engines: { node: ">=12" } - - "@polka/url@1.0.0-next.29": - resolution: - { - integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==, - } - - "@rollup/plugin-babel@5.3.1": - resolution: - { - integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==, - } - engines: { node: ">= 10.0.0" } - peerDependencies: - "@babel/core": ^7.0.0 - "@types/babel__core": ^7.1.9 - rollup: ^1.20.0||^2.0.0 - peerDependenciesMeta: - "@types/babel__core": - optional: true - - "@rollup/plugin-node-resolve@15.3.1": - resolution: - { - integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==, - } - engines: { node: ">=14.0.0" } - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - "@rollup/plugin-replace@2.4.2": - resolution: - { - integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==, - } - peerDependencies: - rollup: ^1.20.0 || ^2.0.0 - - "@rollup/plugin-terser@0.4.4": - resolution: - { - integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==, - } - engines: { node: ">=14.0.0" } - peerDependencies: - rollup: ^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - "@rollup/pluginutils@3.1.0": - resolution: - { - integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==, - } - engines: { node: ">= 8.0.0" } - peerDependencies: - rollup: ^1.20.0||^2.0.0 - - "@rollup/pluginutils@5.3.0": - resolution: - { - integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==, - } - engines: { node: ">=14.0.0" } - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - "@rollup/rollup-android-arm-eabi@4.57.1": - resolution: - { - integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==, - } - cpu: [arm] - os: [android] - - "@rollup/rollup-android-arm64@4.57.1": - resolution: - { - integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==, - } - cpu: [arm64] - os: [android] - - "@rollup/rollup-darwin-arm64@4.57.1": - resolution: - { - integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==, - } - cpu: [arm64] - os: [darwin] - - "@rollup/rollup-darwin-x64@4.57.1": - resolution: - { - integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==, - } - cpu: [x64] - os: [darwin] - - "@rollup/rollup-freebsd-arm64@4.57.1": - resolution: - { - integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==, - } - cpu: [arm64] - os: [freebsd] - - "@rollup/rollup-freebsd-x64@4.57.1": - resolution: - { - integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==, - } - cpu: [x64] - os: [freebsd] - - "@rollup/rollup-linux-arm-gnueabihf@4.57.1": - resolution: - { - integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==, - } - cpu: [arm] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-arm-musleabihf@4.57.1": - resolution: - { - integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==, - } - cpu: [arm] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-arm64-gnu@4.57.1": - resolution: - { - integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==, - } - cpu: [arm64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-arm64-musl@4.57.1": - resolution: - { - integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==, - } - cpu: [arm64] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-loong64-gnu@4.57.1": - resolution: - { - integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==, - } - cpu: [loong64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-loong64-musl@4.57.1": - resolution: - { - integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==, - } - cpu: [loong64] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-ppc64-gnu@4.57.1": - resolution: - { - integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==, - } - cpu: [ppc64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-ppc64-musl@4.57.1": - resolution: - { - integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==, - } - cpu: [ppc64] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-riscv64-gnu@4.57.1": - resolution: - { - integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==, - } - cpu: [riscv64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-riscv64-musl@4.57.1": - resolution: - { - integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==, - } - cpu: [riscv64] - os: [linux] - libc: [musl] - - "@rollup/rollup-linux-s390x-gnu@4.57.1": - resolution: - { - integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==, - } - cpu: [s390x] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-x64-gnu@4.57.1": - resolution: - { - integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==, - } - cpu: [x64] - os: [linux] - libc: [glibc] - - "@rollup/rollup-linux-x64-musl@4.57.1": - resolution: - { - integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==, - } - cpu: [x64] - os: [linux] - libc: [musl] - - "@rollup/rollup-openbsd-x64@4.57.1": - resolution: - { - integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==, - } - cpu: [x64] - os: [openbsd] - - "@rollup/rollup-openharmony-arm64@4.57.1": - resolution: - { - integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==, - } - cpu: [arm64] - os: [openharmony] - - "@rollup/rollup-win32-arm64-msvc@4.57.1": - resolution: - { - integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==, - } - cpu: [arm64] - os: [win32] - - "@rollup/rollup-win32-ia32-msvc@4.57.1": - resolution: - { - integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==, - } - cpu: [ia32] - os: [win32] - - "@rollup/rollup-win32-x64-gnu@4.57.1": - resolution: - { - integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==, - } - cpu: [x64] - os: [win32] - - "@rollup/rollup-win32-x64-msvc@4.57.1": - resolution: - { - integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==, - } - cpu: [x64] - os: [win32] - - "@sec-ant/readable-stream@0.4.1": - resolution: - { - integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==, - } - - "@semantic-release/changelog@6.0.3": - resolution: - { - integrity: sha512-dZuR5qByyfe3Y03TpmCvAxCyTnp7r5XwtHRf/8vD9EAn4ZWbavUX8adMtXYzE86EVh0gyLA7lm5yW4IV30XUag==, - } - engines: { node: ">=14.17" } - peerDependencies: - semantic-release: ">=18.0.0" - - "@semantic-release/commit-analyzer@13.0.1": - resolution: - { - integrity: sha512-wdnBPHKkr9HhNhXOhZD5a2LNl91+hs8CC2vsAVYxtZH3y0dV3wKn+uZSN61rdJQZ8EGxzWB3inWocBHV9+u/CQ==, - } - engines: { node: ">=20.8.1" } - peerDependencies: - semantic-release: ">=20.1.0" - - "@semantic-release/error@3.0.0": - resolution: - { - integrity: sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==, - } - engines: { node: ">=14.17" } - - "@semantic-release/error@4.0.0": - resolution: - { - integrity: sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==, - } - engines: { node: ">=18" } - - "@semantic-release/exec@7.1.0": - resolution: - { - integrity: sha512-4ycZ2atgEUutspPZ2hxO6z8JoQt4+y/kkHvfZ1cZxgl9WKJId1xPj+UadwInj+gMn2Gsv+fLnbrZ4s+6tK2TFQ==, - } - engines: { node: ">=20.8.1" } - peerDependencies: - semantic-release: ">=24.1.0" - - "@semantic-release/git@10.0.1": - resolution: - { - integrity: sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==, - } - engines: { node: ">=14.17" } - peerDependencies: - semantic-release: ">=18.0.0" - - "@semantic-release/github@12.0.6": - resolution: - { - integrity: sha512-aYYFkwHW3c6YtHwQF0t0+lAjlU+87NFOZuH2CvWFD0Ylivc7MwhZMiHOJ0FMpIgPpCVib/VUAcOwvrW0KnxQtA==, - } - engines: { node: ^22.14.0 || >= 24.10.0 } - peerDependencies: - semantic-release: ">=24.1.0" - - "@semantic-release/gitlab@13.3.0": - resolution: - { - integrity: sha512-E0q4qbTdVQZW8Siqz1YQjfSSXE2U/Z7lJasUlpHGRu+OYXsLCIU6o18scquofyP7CBxyKLIx7TDiLVRko1ekGw==, - } - engines: { node: ">=20.8.1" } - peerDependencies: - semantic-release: ">=20.1.0" - - "@semantic-release/npm@13.1.4": - resolution: - { - integrity: sha512-z5Fn9ftK1QQgFxMSuOd3DtYbTl4hWI2trCEvZcEJMQJy1/OBR0WHcxqzfVun455FSkHML8KgvPxJEa9MtZIBsg==, - } - engines: { node: ^22.14.0 || >= 24.10.0 } - peerDependencies: - semantic-release: ">=20.1.0" - - "@semantic-release/release-notes-generator@14.1.0": - resolution: - { - integrity: sha512-CcyDRk7xq+ON/20YNR+1I/jP7BYKICr1uKd1HHpROSnnTdGqOTburi4jcRiTYz0cpfhxSloQO3cGhnoot7IEkA==, - } - engines: { node: ">=20.8.1" } - peerDependencies: - semantic-release: ">=20.1.0" - - "@sindresorhus/is@4.6.0": - resolution: - { - integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==, - } - engines: { node: ">=10" } - - "@sindresorhus/is@7.2.0": - resolution: - { - integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==, - } - engines: { node: ">=18" } - - "@sindresorhus/merge-streams@2.3.0": - resolution: - { - integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==, - } - engines: { node: ">=18" } - - "@sindresorhus/merge-streams@4.0.0": - resolution: - { - integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==, - } - engines: { node: ">=18" } - - "@stencil/core@2.5.2": - resolution: - { - integrity: sha512-bgjPXkSzzg1WnTgVUm6m5ZzpKt602WmA/QljODAW1xVN40OHJdbGblzF/F6MFzqv2c5Cy30CB41arc8qADIdcQ==, - } - engines: { node: ">=12.10.0", npm: ">=6.0.0" } - hasBin: true - - "@surma/rollup-plugin-off-main-thread@2.2.3": - resolution: - { - integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==, - } - - "@tailwindcss/forms@0.5.11": - resolution: - { - integrity: sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA==, - } - peerDependencies: - tailwindcss: ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" - - "@tailwindcss/typography@0.5.19": - resolution: - { - integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==, - } - peerDependencies: - tailwindcss: ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" - - "@types/eslint@9.6.1": - resolution: - { - integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==, - } - - "@types/esrecurse@4.3.1": - resolution: - { - integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==, - } - - "@types/estree@0.0.39": - resolution: - { - integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==, - } - - "@types/estree@1.0.8": - resolution: - { - integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, - } - - "@types/fscreen@1.0.4": - resolution: - { - integrity: sha512-TsjxyAUvlvuQyao9vNk0yES4nY07K9xoAbkhgXU948JG39EqlLxniWuW9OiZde9Q8ACSpu3fmbXXRAfb/l/HqQ==, - } - - "@types/geojson@7946.0.16": - resolution: - { - integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==, - } - - "@types/http-cache-semantics@4.2.0": - resolution: - { - integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==, - } - - "@types/json-schema@7.0.15": - resolution: - { - integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, - } - - "@types/leaflet@1.9.21": - resolution: - { - integrity: sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==, - } - - "@types/node@24.7.0": - resolution: - { - integrity: sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw==, - } - - "@types/normalize-package-data@2.4.4": - resolution: - { - integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==, - } - - "@types/resolve@1.20.2": - resolution: - { - integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==, - } - - "@types/trusted-types@2.0.7": - resolution: - { - integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==, - } - - "@typescript-eslint/eslint-plugin@8.56.0": - resolution: - { - integrity: sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - "@typescript-eslint/parser": ^8.56.0 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/parser@8.56.0": - resolution: - { - integrity: sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/project-service@8.56.0": - resolution: - { - integrity: sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/scope-manager@8.56.0": - resolution: - { - integrity: sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@typescript-eslint/tsconfig-utils@8.56.0": - resolution: - { - integrity: sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/type-utils@8.56.0": - resolution: - { - integrity: sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/types@8.56.0": - resolution: - { - integrity: sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@typescript-eslint/typescript-estree@8.56.0": - resolution: - { - integrity: sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/utils@8.56.0": - resolution: - { - integrity: sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - - "@typescript-eslint/visitor-keys@8.56.0": - resolution: - { - integrity: sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - "@vime/core@5.4.1": - resolution: - { - integrity: sha512-ZFpV3xqZJ5tvh5rZOYKRh8zFzNIKr2ZcK6L75nJjFjbWt/ZmFF2nMBxtD9/hC4Xjk9v7hp1+P9cmctL674VFgA==, - } - - acorn-jsx@5.3.2: - resolution: - { - integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, - } - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.15.0: - resolution: - { - integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==, - } - engines: { node: ">=0.4.0" } - hasBin: true - - agent-base@7.1.4: - resolution: - { - integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==, - } - engines: { node: ">= 14" } - - aggregate-error@3.1.0: - resolution: - { - integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==, - } - engines: { node: ">=8" } - - aggregate-error@5.0.0: - resolution: - { - integrity: sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==, - } - engines: { node: ">=18" } - - ajv@6.12.6: - resolution: - { - integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==, - } - - ajv@8.18.0: - resolution: - { - integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==, - } - - all-contributors-cli@6.26.1: - resolution: - { - integrity: sha512-Ymgo3FJACRBEd1eE653FD1J/+uD0kqpUNYfr9zNC1Qby0LgbhDBzB3EF6uvkAbYpycStkk41J+0oo37Lc02yEw==, - } - engines: { node: ">=4" } - hasBin: true - - ansi-escapes@4.3.2: - resolution: - { - integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==, - } - engines: { node: ">=8" } - - ansi-escapes@7.3.0: - resolution: - { - integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==, - } - engines: { node: ">=18" } - - ansi-regex@5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, - } - engines: { node: ">=8" } - - ansi-regex@6.2.2: - resolution: - { - integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, - } - engines: { node: ">=12" } - - ansi-styles@3.2.1: - resolution: - { - integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==, - } - engines: { node: ">=4" } - - ansi-styles@4.3.0: - resolution: - { - integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, - } - engines: { node: ">=8" } - - ansi-styles@6.2.3: - resolution: - { - integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==, - } - engines: { node: ">=12" } - - ansis@4.2.0: - resolution: - { - integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==, - } - engines: { node: ">=14" } - - any-promise@1.3.0: - resolution: - { - integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==, - } - - anymatch@3.1.3: - resolution: - { - integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, - } - engines: { node: ">= 8" } - - arg@5.0.2: - resolution: - { - integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==, - } - - argparse@2.0.1: - resolution: - { - integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, - } - - argv-formatter@1.0.0: - resolution: - { - integrity: sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==, - } - - array-buffer-byte-length@1.0.2: - resolution: - { - integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==, - } - engines: { node: ">= 0.4" } - - array-ify@1.0.0: - resolution: - { - integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==, - } - - arraybuffer.prototype.slice@1.0.4: - resolution: - { - integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==, - } - engines: { node: ">= 0.4" } - - astral-regex@2.0.0: - resolution: - { - integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==, - } - engines: { node: ">=8" } - - async-function@1.0.0: - resolution: - { - integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==, - } - engines: { node: ">= 0.4" } - - async@3.2.6: - resolution: - { - integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==, - } - - at-least-node@1.0.0: - resolution: - { - integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==, - } - engines: { node: ">= 4.0.0" } - - autoprefixer@10.4.24: - resolution: - { - integrity: sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==, - } - engines: { node: ^10 || ^12 || >=14 } - hasBin: true - peerDependencies: - postcss: ^8.1.0 - - available-typed-arrays@1.0.7: - resolution: - { - integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==, - } - engines: { node: ">= 0.4" } - - babel-plugin-polyfill-corejs2@0.4.15: - resolution: - { - integrity: sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==, - } - peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-polyfill-corejs3@0.14.0: - resolution: - { - integrity: sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==, - } - peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-polyfill-regenerator@0.6.6: - resolution: - { - integrity: sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==, - } - peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - - balanced-match@1.0.2: - resolution: - { - integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, - } - - balanced-match@3.0.1: - resolution: - { - integrity: sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==, - } - engines: { node: ">= 16" } - - balanced-match@4.0.3: - resolution: - { - integrity: sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==, - } - engines: { node: 20 || >=22 } - - base64-js@1.3.1: - resolution: - { - integrity: sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==, - } - - base64-js@1.5.1: - resolution: - { - integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, - } - - baseline-browser-mapping@2.10.0: - resolution: - { - integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==, - } - engines: { node: ">=6.0.0" } - hasBin: true - - before-after-hook@4.0.0: - resolution: - { - integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==, - } - - binary-extensions@2.3.0: - resolution: - { - integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==, - } - engines: { node: ">=8" } - - birpc@2.9.0: - resolution: - { - integrity: sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==, - } - - bl@4.1.0: - resolution: - { - integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==, - } - - boolbase@1.0.0: - resolution: - { - integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==, - } - - bottleneck@2.19.5: - resolution: - { - integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==, - } - - brace-expansion@1.1.12: - resolution: - { - integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==, - } - - brace-expansion@2.0.2: - resolution: - { - integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==, - } - - brace-expansion@5.0.2: - resolution: - { - integrity: sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==, - } - engines: { node: 20 || >=22 } - - braces@3.0.3: - resolution: - { - integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, - } - engines: { node: ">=8" } - - brotli@1.3.3: - resolution: - { - integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==, - } - - browserslist@4.28.1: - resolution: - { - integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==, - } - engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } - hasBin: true - - buffer-from@1.1.2: - resolution: - { - integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, - } - - buffer@5.7.1: - resolution: - { - integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==, - } - - bundle-name@4.1.0: - resolution: - { - integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==, - } - engines: { node: ">=18" } - - byte-counter@0.1.0: - resolution: - { - integrity: sha512-jheRLVMeUKrDBjVw2O5+k4EvR4t9wtxHL+bo/LxfkxsVeuGMy3a5SEGgXdAFA4FSzTrU8rQXQIrsZ3oBq5a0pQ==, - } - engines: { node: ">=20" } - - cacheable-lookup@7.0.0: - resolution: - { - integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==, - } - engines: { node: ">=14.16" } - - cacheable-request@13.0.18: - resolution: - { - integrity: sha512-rFWadDRKJs3s2eYdXlGggnBZKG7MTblkFBB0YllFds+UYnfogDp2wcR6JN97FhRkHTvq59n2vhNoHNZn29dh/Q==, - } - engines: { node: ">=18" } - - cacheable@2.3.2: - resolution: - { - integrity: sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==, - } - - cachedir@2.3.0: - resolution: - { - integrity: sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==, - } - engines: { node: ">=6" } - - call-bind-apply-helpers@1.0.2: - resolution: - { - integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, - } - engines: { node: ">= 0.4" } - - call-bind@1.0.8: - resolution: - { - integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==, - } - engines: { node: ">= 0.4" } - - call-bound@1.0.4: - resolution: - { - integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, - } - engines: { node: ">= 0.4" } - - callsites@3.1.0: - resolution: - { - integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, - } - engines: { node: ">=6" } - - camelcase-css@2.0.1: - resolution: - { - integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==, - } - engines: { node: ">= 6" } - - camelcase@5.3.1: - resolution: - { - integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==, - } - engines: { node: ">=6" } - - caniuse-api@3.0.0: - resolution: - { - integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==, - } - - caniuse-lite@1.0.30001770: - resolution: - { - integrity: sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==, - } - - chalk@2.4.2: - resolution: - { - integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==, - } - engines: { node: ">=4" } - - chalk@4.1.2: - resolution: - { - integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, - } - engines: { node: ">=10" } - - chalk@5.6.2: - resolution: - { - integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==, - } - engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } - - char-regex@1.0.2: - resolution: - { - integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==, - } - engines: { node: ">=10" } - - chardet@0.7.0: - resolution: - { - integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==, - } - - choices.js@11.1.0: - resolution: - { - integrity: sha512-mIt0uLhedHg2ea/K2PACrVpt391vRGHuOoctPAiHcyemezwzNMxj7jOzNEk8e7EbjLh0S0sspDkSCADOKz9kcw==, - } - - chokidar@3.6.0: - resolution: - { - integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==, - } - engines: { node: ">= 8.10.0" } - - ci-info@4.4.0: - resolution: - { - integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==, - } - engines: { node: ">=8" } - - clean-stack@2.2.0: - resolution: - { - integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==, - } - engines: { node: ">=6" } - - clean-stack@5.3.0: - resolution: - { - integrity: sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg==, - } - engines: { node: ">=14.16" } - - cli-cursor@3.1.0: - resolution: - { - integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==, - } - engines: { node: ">=8" } - - cli-cursor@5.0.0: - resolution: - { - integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==, - } - engines: { node: ">=18" } - - cli-highlight@2.1.11: - resolution: - { - integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==, - } - engines: { node: ">=8.0.0", npm: ">=5.0.0" } - hasBin: true - - cli-spinners@2.9.2: - resolution: - { - integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==, - } - engines: { node: ">=6" } - - cli-table3@0.6.5: - resolution: - { - integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==, - } - engines: { node: 10.* || >= 12.* } - - cli-truncate@5.1.1: - resolution: - { - integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==, - } - engines: { node: ">=20" } - - cli-width@3.0.0: - resolution: - { - integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==, - } - engines: { node: ">= 10" } - - cliui@6.0.0: - resolution: - { - integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==, - } - - cliui@7.0.4: - resolution: - { - integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==, - } - - cliui@8.0.1: - resolution: - { - integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, - } - engines: { node: ">=12" } - - cliui@9.0.1: - resolution: - { - integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==, - } - engines: { node: ">=20" } - - clone@1.0.4: - resolution: - { - integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==, - } - engines: { node: ">=0.8" } - - codemirror@6.0.2: - resolution: - { - integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==, - } - - color-convert@1.9.3: - resolution: - { - integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, - } - - color-convert@2.0.1: - resolution: - { - integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, - } - engines: { node: ">=7.0.0" } - - color-name@1.1.3: - resolution: - { - integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, - } - - color-name@1.1.4: - resolution: - { - integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, - } - - colord@2.9.3: - resolution: - { - integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==, - } - - colorette@2.0.20: - resolution: - { - integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==, - } - - commander@11.1.0: - resolution: - { - integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==, - } - engines: { node: ">=16" } - - commander@14.0.3: - resolution: - { - integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==, - } - engines: { node: ">=20" } - - commander@2.20.3: - resolution: - { - integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==, - } - - commander@4.1.1: - resolution: - { - integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==, - } - engines: { node: ">= 6" } - - commander@7.2.0: - resolution: - { - integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==, - } - engines: { node: ">= 10" } - - commitizen@4.3.1: - resolution: - { - integrity: sha512-gwAPAVTy/j5YcOOebcCRIijn+mSjWJC+IYKivTu6aG8Ei/scoXgfsMRnuAk6b0GRste2J4NGxVdMN3ZpfNaVaw==, - } - engines: { node: ">= 12" } - hasBin: true - - common-tags@1.8.2: - resolution: - { - integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==, - } - engines: { node: ">=4.0.0" } - - compare-func@2.0.0: - resolution: - { - integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==, - } - - concat-map@0.0.1: - resolution: - { - integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, - } - - config-chain@1.1.13: - resolution: - { - integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==, - } - - conventional-changelog-angular@8.1.0: - resolution: - { - integrity: sha512-GGf2Nipn1RUCAktxuVauVr1e3r8QrLP/B0lEUsFktmGqc3ddbQkhoJZHJctVU829U1c6mTSWftrVOCHaL85Q3w==, - } - engines: { node: ">=18" } - - conventional-changelog-conventionalcommits@9.1.0: - resolution: - { - integrity: sha512-MnbEysR8wWa8dAEvbj5xcBgJKQlX/m0lhS8DsyAAWDHdfs2faDJxTgzRYlRYpXSe7UiKrIIlB4TrBKU9q9DgkA==, - } - engines: { node: ">=18" } - - conventional-changelog-writer@8.2.0: - resolution: - { - integrity: sha512-Y2aW4596l9AEvFJRwFGJGiQjt2sBYTjPD18DdvxX9Vpz0Z7HQ+g1Z+6iYDAm1vR3QOJrDBkRHixHK/+FhkR6Pw==, - } - engines: { node: ">=18" } - hasBin: true - - conventional-commit-types@3.0.0: - resolution: - { - integrity: sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==, - } - - conventional-commits-filter@5.0.0: - resolution: - { - integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==, - } - engines: { node: ">=18" } - - conventional-commits-parser@6.2.1: - resolution: - { - integrity: sha512-20pyHgnO40rvfI0NGF/xiEoFMkXDtkF8FwHvk5BokoFoCuTQRI8vrNCNFWUOfuolKJMm1tPCHc8GgYEtr1XRNA==, - } - engines: { node: ">=18" } - hasBin: true - - convert-hrtime@5.0.0: - resolution: - { - integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==, - } - engines: { node: ">=12" } - - convert-source-map@2.0.0: - resolution: - { - integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, - } - - core-js-compat@3.48.0: - resolution: - { - integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==, - } - - core-js@3.48.0: - resolution: - { - integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==, - } - - core-util-is@1.0.3: - resolution: - { - integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, - } - - cosmiconfig-typescript-loader@6.2.0: - resolution: - { - integrity: sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==, - } - engines: { node: ">=v18" } - peerDependencies: - "@types/node": "*" - cosmiconfig: ">=9" - typescript: ">=5" - - cosmiconfig@9.0.0: - resolution: - { - integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==, - } - engines: { node: ">=14" } - peerDependencies: - typescript: ">=4.9.5" - peerDependenciesMeta: - typescript: - optional: true - - crelt@1.0.6: - resolution: - { - integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==, - } - - cross-env@10.1.0: - resolution: - { - integrity: sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==, - } - engines: { node: ">=20" } - hasBin: true - - cross-spawn@7.0.6: - resolution: - { - integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, - } - engines: { node: ">= 8" } - - crypto-js@4.2.0: - resolution: - { - integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==, - } - - crypto-random-string@2.0.0: - resolution: - { - integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==, - } - engines: { node: ">=8" } - - crypto-random-string@4.0.0: - resolution: - { - integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==, - } - engines: { node: ">=12" } - - css-blank-pseudo@8.0.1: - resolution: - { - integrity: sha512-C5B2e5hCM4llrQkUms+KnWEMVW8K1n2XvX9G7ppfMZJQ7KAS/4rNnkP1Cs+HhWriOz1mWWTMFD4j1J7s31Dgug==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - css-declaration-sorter@7.3.1: - resolution: - { - integrity: sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==, - } - engines: { node: ^14 || ^16 || >=18 } - peerDependencies: - postcss: ^8.0.9 - - css-functions-list@3.3.3: - resolution: - { - integrity: sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==, - } - engines: { node: ">=12" } - - css-has-pseudo@8.0.0: - resolution: - { - integrity: sha512-Uz/bsHRbOeir/5Oeuz85tq/yLJLxX+3dpoRdjNTshs6jjqwUg8XaEZGDd0ci3fw7l53Srw0EkJ8mYan0eW5uGQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - css-prefers-color-scheme@11.0.0: - resolution: - { - integrity: sha512-fv0mgtwUhh2m9iio3Kxc2CkrogjIaRdMFaaqyzSFdii17JF4cfPyMNX72B15ZW2Nrr/NZUpxI4dec1VMHYJvdw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - css-select@5.2.2: - resolution: - { - integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==, - } - - css-tree@2.2.1: - resolution: - { - integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==, - } - engines: { node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: ">=7.0.0" } - - css-tree@3.1.0: - resolution: - { - integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==, - } - engines: { node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0 } - - css-what@6.2.2: - resolution: - { - integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==, - } - engines: { node: ">= 6" } - - cssdb@8.7.1: - resolution: - { - integrity: sha512-+F6LKx48RrdGOtE4DT5jz7Uo+VeyKXpK797FAevIkzjV8bMHz6xTO5F7gNDcRCHmPgD5jj2g6QCsY9zmVrh38A==, - } - - cssesc@3.0.0: - resolution: - { - integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==, - } - engines: { node: ">=4" } - hasBin: true - - cssnano-preset-default@7.0.10: - resolution: - { - integrity: sha512-6ZBjW0Lf1K1Z+0OKUAUpEN62tSXmYChXWi2NAA0afxEVsj9a+MbcB1l5qel6BHJHmULai2fCGRthCeKSFbScpA==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - cssnano-utils@5.0.1: - resolution: - { - integrity: sha512-ZIP71eQgG9JwjVZsTPSqhc6GHgEr53uJ7tK5///VfyWj6Xp2DBmixWHqJgPno+PqATzn48pL42ww9x5SSGmhZg==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - cssnano@7.1.2: - resolution: - { - integrity: sha512-HYOPBsNvoiFeR1eghKD5C3ASm64v9YVyJB4Ivnl2gqKoQYvjjN/G0rztvKQq8OxocUtC6sjqY8jwYngIB4AByA==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - csso@5.0.5: - resolution: - { - integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==, - } - engines: { node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: ">=7.0.0" } - - cz-conventional-changelog@3.3.0: - resolution: - { - integrity: sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==, - } - engines: { node: ">= 10" } - - d3-array@3.2.4: - resolution: - { - integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==, - } - engines: { node: ">=12" } - - d3-color@3.1.0: - resolution: - { - integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==, - } - engines: { node: ">=12" } - - d3-dispatch@3.0.1: - resolution: - { - integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==, - } - engines: { node: ">=12" } - - d3-ease@3.0.1: - resolution: - { - integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==, - } - engines: { node: ">=12" } - - d3-force@3.0.0: - resolution: - { - integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==, - } - engines: { node: ">=12" } - - d3-geo-projection@4.0.0: - resolution: - { - integrity: sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==, - } - engines: { node: ">=12" } - hasBin: true - - d3-geo@3.1.1: - resolution: - { - integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==, - } - engines: { node: ">=12" } - - d3-interpolate@3.0.1: - resolution: - { - integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==, - } - engines: { node: ">=12" } - - d3-quadtree@3.0.1: - resolution: - { - integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==, - } - engines: { node: ">=12" } - - d3-selection@3.0.0: - resolution: - { - integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==, - } - engines: { node: ">=12" } - - d3-timer@3.0.1: - resolution: - { - integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==, - } - engines: { node: ">=12" } - - d3-transition@3.0.1: - resolution: - { - integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==, - } - engines: { node: ">=12" } - peerDependencies: - d3-selection: 2 - 3 - - dargs@8.1.0: - resolution: - { - integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==, - } - engines: { node: ">=12" } - - data-view-buffer@1.0.2: - resolution: - { - integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==, - } - engines: { node: ">= 0.4" } - - data-view-byte-length@1.0.2: - resolution: - { - integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==, - } - engines: { node: ">= 0.4" } - - data-view-byte-offset@1.0.1: - resolution: - { - integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==, - } - engines: { node: ">= 0.4" } - - debug@4.4.3: - resolution: - { - integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, - } - engines: { node: ">=6.0" } - peerDependencies: - supports-color: "*" - peerDependenciesMeta: - supports-color: - optional: true - - decamelize@1.2.0: - resolution: - { - integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==, - } - engines: { node: ">=0.10.0" } - - decompress-response@10.0.0: - resolution: - { - integrity: sha512-oj7KWToJuuxlPr7VV0vabvxEIiqNMo+q0NueIiL3XhtwC6FVOX7Hr1c0C4eD0bmf7Zr+S/dSf2xvkH3Ad6sU3Q==, - } - engines: { node: ">=20" } - - dedent@0.7.0: - resolution: - { - integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==, - } - - deep-equal@1.1.2: - resolution: - { - integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==, - } - engines: { node: ">= 0.4" } - - deep-extend@0.6.0: - resolution: - { - integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==, - } - engines: { node: ">=4.0.0" } - - deep-is@0.1.4: - resolution: - { - integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, - } - - deepmerge@4.3.1: - resolution: - { - integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==, - } - engines: { node: ">=0.10.0" } - - default-browser-id@5.0.1: - resolution: - { - integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==, - } - engines: { node: ">=18" } - - default-browser@5.5.0: - resolution: - { - integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==, - } - engines: { node: ">=18" } - - defaults@1.0.4: - resolution: - { - integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==, - } - - define-data-property@1.1.4: - resolution: - { - integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, - } - engines: { node: ">= 0.4" } - - define-lazy-prop@3.0.0: - resolution: - { - integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==, - } - engines: { node: ">=12" } - - define-properties@1.2.1: - resolution: - { - integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==, - } - engines: { node: ">= 0.4" } - - detect-file@1.0.0: - resolution: - { - integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==, - } - engines: { node: ">=0.10.0" } - - detect-indent@6.1.0: - resolution: - { - integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==, - } - engines: { node: ">=8" } - - detect-libc@2.1.2: - resolution: - { - integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==, - } - engines: { node: ">=8" } - - dfa@1.2.0: - resolution: - { - integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==, - } - - didyoumean@1.2.2: - resolution: - { - integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==, - } - - dir-glob@3.0.1: - resolution: - { - integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==, - } - engines: { node: ">=8" } - - dlv@1.1.3: - resolution: - { - integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==, - } - - dom-serializer@2.0.0: - resolution: - { - integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==, - } - - domelementtype@2.3.0: - resolution: - { - integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==, - } - - domhandler@5.0.3: - resolution: - { - integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==, - } - engines: { node: ">= 4" } - - domutils@3.2.2: - resolution: - { - integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==, - } - - dot-prop@5.3.0: - resolution: - { - integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==, - } - engines: { node: ">=8" } - - dunder-proto@1.0.1: - resolution: - { - integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, - } - engines: { node: ">= 0.4" } - - duplexer2@0.1.4: - resolution: - { - integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==, - } - - ejs@3.1.10: - resolution: - { - integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==, - } - engines: { node: ">=0.10.0" } - hasBin: true - - electron-to-chromium@1.5.286: - resolution: - { - integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==, - } - - emoji-regex@10.6.0: - resolution: - { - integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==, - } - - emoji-regex@8.0.0: - resolution: - { - integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, - } - - emojilib@2.4.0: - resolution: - { - integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==, - } - - entities@4.5.0: - resolution: - { - integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, - } - engines: { node: ">=0.12" } - - env-ci@11.2.0: - resolution: - { - integrity: sha512-D5kWfzkmaOQDioPmiviWAVtKmpPT4/iJmMVQxWxMPJTFyTkdc5JQUfc5iXEeWxcOdsYTKSAiA/Age4NUOqKsRA==, - } - engines: { node: ^18.17 || >=20.6.1 } - - env-paths@2.2.1: - resolution: - { - integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==, - } - engines: { node: ">=6" } - - environment@1.1.0: - resolution: - { - integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==, - } - engines: { node: ">=18" } - - error-ex@1.3.4: - resolution: - { - integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==, - } - - error-stack-parser-es@1.0.5: - resolution: - { - integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==, - } - - es-abstract@1.24.1: - resolution: - { - integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==, - } - engines: { node: ">= 0.4" } - - es-define-property@1.0.1: - resolution: - { - integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, - } - engines: { node: ">= 0.4" } - - es-errors@1.3.0: - resolution: - { - integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, - } - engines: { node: ">= 0.4" } - - es-object-atoms@1.1.1: - resolution: - { - integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==, - } - engines: { node: ">= 0.4" } - - es-set-tostringtag@2.1.0: - resolution: - { - integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, - } - engines: { node: ">= 0.4" } - - es-to-primitive@1.3.0: - resolution: - { - integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==, - } - engines: { node: ">= 0.4" } - - esbuild@0.27.3: - resolution: - { - integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==, - } - engines: { node: ">=18" } - hasBin: true - - escalade@3.2.0: - resolution: - { - integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, - } - engines: { node: ">=6" } - - escape-string-regexp@1.0.5: - resolution: - { - integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, - } - engines: { node: ">=0.8.0" } - - escape-string-regexp@4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, - } - engines: { node: ">=10" } - - escape-string-regexp@5.0.0: - resolution: - { - integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==, - } - engines: { node: ">=12" } - - eslint-config-prettier@10.1.8: - resolution: - { - integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==, - } - hasBin: true - peerDependencies: - eslint: ">=7.0.0" - - eslint-plugin-prettier@5.5.5: - resolution: - { - integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==, - } - engines: { node: ^14.18.0 || >=16.0.0 } - peerDependencies: - "@types/eslint": ">=8.0.0" - eslint: ">=8.0.0" - eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" - prettier: ">=3.0.0" - peerDependenciesMeta: - "@types/eslint": - optional: true - eslint-config-prettier: - optional: true - - eslint-scope@9.1.0: - resolution: - { - integrity: sha512-CkWE42hOJsNj9FJRaoMX9waUFYhqY4jmyLFdAdzZr6VaCg3ynLYx4WnOdkaIifGfH4gsUcBTn4OZbHXkpLD0FQ==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - - eslint-visitor-keys@3.4.3: - resolution: - { - integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } - - eslint-visitor-keys@4.2.1: - resolution: - { - integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - eslint-visitor-keys@5.0.0: - resolution: - { - integrity: sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - - eslint@10.0.0: - resolution: - { - integrity: sha512-O0piBKY36YSJhlFSG8p9VUdPV/SxxS4FYDWVpr/9GJuMaepzwlf4J8I4ov1b+ySQfDTPhc3DtLaxcT1fN0yqCg==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - hasBin: true - peerDependencies: - jiti: "*" - peerDependenciesMeta: - jiti: - optional: true - - espree@10.4.0: - resolution: - { - integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - - espree@11.1.0: - resolution: - { - integrity: sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } - - esquery@1.7.0: - resolution: - { - integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==, - } - engines: { node: ">=0.10" } - - esrecurse@4.3.0: - resolution: - { - integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, - } - engines: { node: ">=4.0" } - - estraverse@5.3.0: - resolution: - { - integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, - } - engines: { node: ">=4.0" } - - estree-walker@1.0.1: - resolution: - { - integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==, - } - - estree-walker@2.0.2: - resolution: - { - integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==, - } - - esutils@2.0.3: - resolution: - { - integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, - } - engines: { node: ">=0.10.0" } - - eventemitter3@5.0.4: - resolution: - { - integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==, - } - - execa@5.1.1: - resolution: - { - integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==, - } - engines: { node: ">=10" } - - execa@8.0.1: - resolution: - { - integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==, - } - engines: { node: ">=16.17" } - - execa@9.6.1: - resolution: - { - integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==, - } - engines: { node: ^18.19.0 || >=20.5.0 } - - expand-tilde@2.0.2: - resolution: - { - integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==, - } - engines: { node: ">=0.10.0" } - - external-editor@3.1.0: - resolution: - { - integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==, - } - engines: { node: ">=4" } - - fast-content-type-parse@3.0.0: - resolution: - { - integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==, - } - - fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } - - fast-diff@1.3.0: - resolution: - { - integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==, - } - - fast-glob@3.3.3: - resolution: - { - integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==, - } - engines: { node: ">=8.6.0" } - - fast-json-stable-stringify@2.1.0: - resolution: - { - integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, - } - - fast-levenshtein@2.0.6: - resolution: - { - integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, - } - - fast-uri@3.1.0: - resolution: - { - integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==, - } - - fastest-levenshtein@1.0.16: - resolution: - { - integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==, - } - engines: { node: ">= 4.9.1" } - - fastq@1.20.1: - resolution: - { - integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==, - } - - fdir@6.5.0: - resolution: - { - integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, - } - engines: { node: ">=12.0.0" } - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - figures@2.0.0: - resolution: - { - integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==, - } - engines: { node: ">=4" } - - figures@3.2.0: - resolution: - { - integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==, - } - engines: { node: ">=8" } - - figures@6.1.0: - resolution: - { - integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==, - } - engines: { node: ">=18" } - - file-entry-cache@11.1.2: - resolution: - { - integrity: sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log==, - } - - file-entry-cache@8.0.0: - resolution: - { - integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==, - } - engines: { node: ">=16.0.0" } - - filelist@1.0.4: - resolution: - { - integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==, - } - - fill-range@7.1.1: - resolution: - { - integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, - } - engines: { node: ">=8" } - - find-node-modules@2.1.3: - resolution: - { - integrity: sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==, - } - - find-root@1.1.0: - resolution: - { - integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==, - } - - find-up-simple@1.0.1: - resolution: - { - integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==, - } - engines: { node: ">=18" } - - find-up@2.1.0: - resolution: - { - integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==, - } - engines: { node: ">=4" } - - find-up@4.1.0: - resolution: - { - integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==, - } - engines: { node: ">=8" } - - find-up@5.0.0: - resolution: - { - integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, - } - engines: { node: ">=10" } - - find-versions@6.0.0: - resolution: - { - integrity: sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==, - } - engines: { node: ">=18" } - - findup-sync@4.0.0: - resolution: - { - integrity: sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==, - } - engines: { node: ">= 8" } - - flat-cache@4.0.1: - resolution: - { - integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==, - } - engines: { node: ">=16" } - - flat-cache@6.1.20: - resolution: - { - integrity: sha512-AhHYqwvN62NVLp4lObVXGVluiABTHapoB57EyegZVmazN+hhGhLTn3uZbOofoTw4DSDvVCadzzyChXhOAvy8uQ==, - } - - flatpickr@4.6.13: - resolution: - { - integrity: sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==, - } - - flatted@3.3.3: - resolution: - { - integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==, - } - - for-each@0.3.5: - resolution: - { - integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==, - } - engines: { node: ">= 0.4" } - - foreground-child@3.3.1: - resolution: - { - integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, - } - engines: { node: ">=14" } - - form-data-encoder@4.1.0: - resolution: - { - integrity: sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw==, - } - engines: { node: ">= 18" } - - formdata-node@6.0.3: - resolution: - { - integrity: sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==, - } - engines: { node: ">= 18" } - - fraction.js@5.3.4: - resolution: - { - integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==, - } - - from2@2.3.0: - resolution: - { - integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==, - } - - fs-extra@11.3.3: - resolution: - { - integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==, - } - engines: { node: ">=14.14" } - - fs-extra@9.1.0: - resolution: - { - integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==, - } - engines: { node: ">=10" } - - fs.realpath@1.0.0: - resolution: - { - integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, - } - - fscreen@1.2.0: - resolution: - { - integrity: sha512-hlq4+BU0hlPmwsFjwGGzZ+OZ9N/wq9Ljg/sq3pX+2CD7hrJsX9tJgWWK/wiNTFM212CLHWhicOoqwXyZGGetJg==, - } - - fsevents@2.3.3: - resolution: - { - integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } - os: [darwin] - - function-bind@1.1.2: - resolution: - { - integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, - } - - function-timeout@1.0.2: - resolution: - { - integrity: sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==, - } - engines: { node: ">=18" } - - function.prototype.name@1.1.8: - resolution: - { - integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==, - } - engines: { node: ">= 0.4" } - - functions-have-names@1.2.3: - resolution: - { - integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==, - } - - fuse.js@7.1.0: - resolution: - { - integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==, - } - engines: { node: ">=10" } - - generator-function@2.0.1: - resolution: - { - integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==, - } - engines: { node: ">= 0.4" } - - gensync@1.0.0-beta.2: - resolution: - { - integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, - } - engines: { node: ">=6.9.0" } - - get-caller-file@2.0.5: - resolution: - { - integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, - } - engines: { node: 6.* || 8.* || >= 10.* } - - get-east-asian-width@1.5.0: - resolution: - { - integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==, - } - engines: { node: ">=18" } - - get-intrinsic@1.3.0: - resolution: - { - integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, - } - engines: { node: ">= 0.4" } - - get-own-enumerable-property-symbols@3.0.2: - resolution: - { - integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==, - } - - get-proto@1.0.1: - resolution: - { - integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, - } - engines: { node: ">= 0.4" } - - get-stream@6.0.1: - resolution: - { - integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, - } - engines: { node: ">=10" } - - get-stream@7.0.1: - resolution: - { - integrity: sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==, - } - engines: { node: ">=16" } - - get-stream@8.0.1: - resolution: - { - integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==, - } - engines: { node: ">=16" } - - get-stream@9.0.1: - resolution: - { - integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==, - } - engines: { node: ">=18" } - - get-symbol-description@1.1.0: - resolution: - { - integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==, - } - engines: { node: ">= 0.4" } - - git-log-parser@1.2.1: - resolution: - { - integrity: sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==, - } - - git-raw-commits@4.0.0: - resolution: - { - integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==, - } - engines: { node: ">=16" } - hasBin: true - - glob-parent@5.1.2: - resolution: - { - integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, - } - engines: { node: ">= 6" } - - glob-parent@6.0.2: - resolution: - { - integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, - } - engines: { node: ">=10.13.0" } - - glob@11.1.0: - resolution: - { - integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==, - } - engines: { node: 20 || >=22 } - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - hasBin: true - - glob@13.0.5: - resolution: - { - integrity: sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw==, - } - engines: { node: 20 || >=22 } - - glob@7.2.3: - resolution: - { - integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==, - } - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - - global-directory@4.0.1: - resolution: - { - integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==, - } - engines: { node: ">=18" } - - global-modules@1.0.0: - resolution: - { - integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==, - } - engines: { node: ">=0.10.0" } - - global-modules@2.0.0: - resolution: - { - integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==, - } - engines: { node: ">=6" } - - global-prefix@1.0.2: - resolution: - { - integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==, - } - engines: { node: ">=0.10.0" } - - global-prefix@3.0.0: - resolution: - { - integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==, - } - engines: { node: ">=6" } - - globals@14.0.0: - resolution: - { - integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==, - } - engines: { node: ">=18" } - - globals@17.3.0: - resolution: - { - integrity: sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==, - } - engines: { node: ">=18" } - - globalthis@1.0.4: - resolution: - { - integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==, - } - engines: { node: ">= 0.4" } - - globby@14.1.0: - resolution: - { - integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==, - } - engines: { node: ">=18" } - - globby@16.1.1: - resolution: - { - integrity: sha512-dW7vl+yiAJSp6aCekaVnVJxurRv7DCOLyXqEG3RYMYUg7AuJ2jCqPkZTA8ooqC2vtnkaMcV5WfFBMuEnTu1OQg==, - } - engines: { node: ">=20" } - - globjoin@0.1.4: - resolution: - { - integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==, - } - - gopd@1.2.0: - resolution: - { - integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, - } - engines: { node: ">= 0.4" } - - got@14.6.6: - resolution: - { - integrity: sha512-QLV1qeYSo5l13mQzWgP/y0LbMr5Plr5fJilgAIwgnwseproEbtNym8xpLsDzeZ6MWXgNE6kdWGBjdh3zT/Qerg==, - } - engines: { node: ">=20" } - - graceful-fs@4.2.10: - resolution: - { - integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==, - } - - graceful-fs@4.2.11: - resolution: - { - integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, - } - - handlebars@4.7.8: - resolution: - { - integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==, - } - engines: { node: ">=0.4.7" } - hasBin: true - - has-bigints@1.1.0: - resolution: - { - integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==, - } - engines: { node: ">= 0.4" } - - has-flag@3.0.0: - resolution: - { - integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, - } - engines: { node: ">=4" } - - has-flag@4.0.0: - resolution: - { - integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, - } - engines: { node: ">=8" } - - has-flag@5.0.1: - resolution: - { - integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==, - } - engines: { node: ">=12" } - - has-property-descriptors@1.0.2: - resolution: - { - integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==, - } - - has-proto@1.2.0: - resolution: - { - integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==, - } - engines: { node: ">= 0.4" } - - has-symbols@1.1.0: - resolution: - { - integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, - } - engines: { node: ">= 0.4" } - - has-tostringtag@1.0.2: - resolution: - { - integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, - } - engines: { node: ">= 0.4" } - - hashery@1.5.0: - resolution: - { - integrity: sha512-nhQ6ExaOIqti2FDWoEMWARUqIKyjr2VcZzXShrI+A3zpeiuPWzx6iPftt44LhP74E5sW36B75N6VHbvRtpvO6Q==, - } - engines: { node: ">=20" } - - hasown@2.0.2: - resolution: - { - integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==, - } - engines: { node: ">= 0.4" } - - highlight.js@10.7.3: - resolution: - { - integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==, - } - - homedir-polyfill@1.0.3: - resolution: - { - integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==, - } - engines: { node: ">=0.10.0" } - - hook-std@4.0.0: - resolution: - { - integrity: sha512-IHI4bEVOt3vRUDJ+bFA9VUJlo7SzvFARPNLw75pqSmAOP2HmTWfFJtPvLBrDrlgjEYXY9zs7SFdHPQaJShkSCQ==, - } - engines: { node: ">=20" } - - hookified@1.15.1: - resolution: - { - integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==, - } - - hosted-git-info@7.0.2: - resolution: - { - integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - hosted-git-info@9.0.2: - resolution: - { - integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==, - } - engines: { node: ^20.17.0 || >=22.9.0 } - - hpagent@1.2.0: - resolution: - { - integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==, - } - engines: { node: ">=14" } - - html-tags@5.1.0: - resolution: - { - integrity: sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==, - } - engines: { node: ">=20.10" } - - htmlfy@1.0.1: - resolution: - { - integrity: sha512-M85PmyEpWUDqhlEknsnvqmqGLq67h8e86WuKLMdXQdUl8iyvOSDbAAyv0tv0IVmIfh7Py1Vsot/IU1skdswt6g==, - } - - http-cache-semantics@4.2.0: - resolution: - { - integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==, - } - - http-proxy-agent@7.0.2: - resolution: - { - integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==, - } - engines: { node: ">= 14" } - - http2-wrapper@2.2.1: - resolution: - { - integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==, - } - engines: { node: ">=10.19.0" } - - https-proxy-agent@7.0.6: - resolution: - { - integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==, - } - engines: { node: ">= 14" } - - human-signals@2.1.0: - resolution: - { - integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==, - } - engines: { node: ">=10.17.0" } - - human-signals@5.0.0: - resolution: - { - integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==, - } - engines: { node: ">=16.17.0" } - - human-signals@8.0.1: - resolution: - { - integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==, - } - engines: { node: ">=18.18.0" } - - husky@9.1.7: - resolution: - { - integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==, - } - engines: { node: ">=18" } - hasBin: true - - iconv-lite@0.4.24: - resolution: - { - integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==, - } - engines: { node: ">=0.10.0" } - - iconv-lite@0.7.2: - resolution: - { - integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==, - } - engines: { node: ">=0.10.0" } - - idb@7.1.1: - resolution: - { - integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==, - } - - ieee754@1.2.1: - resolution: - { - integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, - } - - ignore@5.3.2: - resolution: - { - integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, - } - engines: { node: ">= 4" } - - ignore@7.0.5: - resolution: - { - integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, - } - engines: { node: ">= 4" } - - import-fresh@3.3.1: - resolution: - { - integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, - } - engines: { node: ">=6" } - - import-from-esm@2.0.0: - resolution: - { - integrity: sha512-YVt14UZCgsX1vZQ3gKjkWVdBdHQ6eu3MPU1TBgL1H5orXe2+jWD006WCPPtOuwlQm10NuzOW5WawiF1Q9veW8g==, - } - engines: { node: ">=18.20" } - - import-meta-resolve@4.2.0: - resolution: - { - integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==, - } - - imurmurhash@0.1.4: - resolution: - { - integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, - } - engines: { node: ">=0.8.19" } - - indent-string@4.0.0: - resolution: - { - integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==, - } - engines: { node: ">=8" } - - indent-string@5.0.0: - resolution: - { - integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==, - } - engines: { node: ">=12" } - - index-to-position@1.2.0: - resolution: - { - integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==, - } - engines: { node: ">=18" } - - inflight@1.0.6: - resolution: - { - integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, - } - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, - } - - ini@1.3.8: - resolution: - { - integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==, - } - - ini@4.1.1: - resolution: - { - integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==, - } - engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } - - inquirer@7.3.3: - resolution: - { - integrity: sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==, - } - engines: { node: ">=8.0.0" } - - inquirer@8.2.5: - resolution: - { - integrity: sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==, - } - engines: { node: ">=12.0.0" } - - internal-slot@1.1.0: - resolution: - { - integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==, - } - engines: { node: ">= 0.4" } - - internmap@2.0.3: - resolution: - { - integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==, - } - engines: { node: ">=12" } - - into-stream@7.0.0: - resolution: - { - integrity: sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==, - } - engines: { node: ">=12" } - - is-arguments@1.2.0: - resolution: - { - integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==, - } - engines: { node: ">= 0.4" } - - is-array-buffer@3.0.5: - resolution: - { - integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==, - } - engines: { node: ">= 0.4" } - - is-arrayish@0.2.1: - resolution: - { - integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, - } - - is-async-function@2.1.1: - resolution: - { - integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==, - } - engines: { node: ">= 0.4" } - - is-bigint@1.1.0: - resolution: - { - integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==, - } - engines: { node: ">= 0.4" } - - is-binary-path@2.1.0: - resolution: - { - integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, - } - engines: { node: ">=8" } - - is-boolean-object@1.2.2: - resolution: - { - integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==, - } - engines: { node: ">= 0.4" } - - is-callable@1.2.7: - resolution: - { - integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==, - } - engines: { node: ">= 0.4" } - - is-ci@4.1.0: - resolution: - { - integrity: sha512-Ab9bQDQ11lWootZUI5qxgN2ZXwxNI5hTwnsvOc1wyxQ7zQ8OkEDw79mI0+9jI3x432NfwbVRru+3noJfXF6lSQ==, - } - hasBin: true - - is-core-module@2.16.1: - resolution: - { - integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==, - } - engines: { node: ">= 0.4" } - - is-data-view@1.0.2: - resolution: - { - integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==, - } - engines: { node: ">= 0.4" } - - is-date-object@1.1.0: - resolution: - { - integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==, - } - engines: { node: ">= 0.4" } - - is-docker@3.0.0: - resolution: - { - integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - hasBin: true - - is-extglob@2.1.1: - resolution: - { - integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, - } - engines: { node: ">=0.10.0" } - - is-finalizationregistry@1.1.1: - resolution: - { - integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==, - } - engines: { node: ">= 0.4" } - - is-fullwidth-code-point@3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: ">=8" } - - is-fullwidth-code-point@5.1.0: - resolution: - { - integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==, - } - engines: { node: ">=18" } - - is-generator-function@1.1.2: - resolution: - { - integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==, - } - engines: { node: ">= 0.4" } - - is-glob@4.0.3: - resolution: - { - integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, - } - engines: { node: ">=0.10.0" } - - is-inside-container@1.0.0: - resolution: - { - integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==, - } - engines: { node: ">=14.16" } - hasBin: true - - is-interactive@1.0.0: - resolution: - { - integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==, - } - engines: { node: ">=8" } - - is-map@2.0.3: - resolution: - { - integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==, - } - engines: { node: ">= 0.4" } - - is-module@1.0.0: - resolution: - { - integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==, - } - - is-negative-zero@2.0.3: - resolution: - { - integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==, - } - engines: { node: ">= 0.4" } - - is-number-object@1.1.1: - resolution: - { - integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==, - } - engines: { node: ">= 0.4" } - - is-number@7.0.0: - resolution: - { - integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, - } - engines: { node: ">=0.12.0" } - - is-obj@1.0.1: - resolution: - { - integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==, - } - engines: { node: ">=0.10.0" } - - is-obj@2.0.0: - resolution: - { - integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==, - } - engines: { node: ">=8" } - - is-path-inside@4.0.0: - resolution: - { - integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==, - } - engines: { node: ">=12" } - - is-plain-obj@4.1.0: - resolution: - { - integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==, - } - engines: { node: ">=12" } - - is-plain-object@5.0.0: - resolution: - { - integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==, - } - engines: { node: ">=0.10.0" } - - is-regex@1.2.1: - resolution: - { - integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==, - } - engines: { node: ">= 0.4" } - - is-regexp@1.0.0: - resolution: - { - integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==, - } - engines: { node: ">=0.10.0" } - - is-set@2.0.3: - resolution: - { - integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==, - } - engines: { node: ">= 0.4" } - - is-shared-array-buffer@1.0.4: - resolution: - { - integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==, - } - engines: { node: ">= 0.4" } - - is-stream@2.0.1: - resolution: - { - integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, - } - engines: { node: ">=8" } - - is-stream@3.0.0: - resolution: - { - integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - - is-stream@4.0.1: - resolution: - { - integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==, - } - engines: { node: ">=18" } - - is-string@1.1.1: - resolution: - { - integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==, - } - engines: { node: ">= 0.4" } - - is-symbol@1.1.1: - resolution: - { - integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==, - } - engines: { node: ">= 0.4" } - - is-typed-array@1.1.15: - resolution: - { - integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==, - } - engines: { node: ">= 0.4" } - - is-unicode-supported@0.1.0: - resolution: - { - integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==, - } - engines: { node: ">=10" } - - is-unicode-supported@2.1.0: - resolution: - { - integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==, - } - engines: { node: ">=18" } - - is-utf8@0.2.1: - resolution: - { - integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==, - } - - is-weakmap@2.0.2: - resolution: - { - integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==, - } - engines: { node: ">= 0.4" } - - is-weakref@1.1.1: - resolution: - { - integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==, - } - engines: { node: ">= 0.4" } - - is-weakset@2.0.4: - resolution: - { - integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==, - } - engines: { node: ">= 0.4" } - - is-windows@1.0.2: - resolution: - { - integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==, - } - engines: { node: ">=0.10.0" } - - is-wsl@3.1.1: - resolution: - { - integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==, - } - engines: { node: ">=16" } - - isarray@1.0.0: - resolution: - { - integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==, - } - - isarray@2.0.5: - resolution: - { - integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==, - } - - isexe@2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } - - issue-parser@7.0.1: - resolution: - { - integrity: sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==, - } - engines: { node: ^18.17 || >=20.6.1 } - - jackspeak@4.2.3: - resolution: - { - integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==, - } - engines: { node: 20 || >=22 } - - jake@10.9.4: - resolution: - { - integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==, - } - engines: { node: ">=10" } - hasBin: true - - java-properties@1.0.2: - resolution: - { - integrity: sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==, - } - engines: { node: ">= 0.6.0" } - - jiti@1.21.7: - resolution: - { - integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==, - } - hasBin: true - - jiti@2.6.1: - resolution: - { - integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==, - } - hasBin: true - - jpeg-exif@1.1.4: - resolution: - { - integrity: sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==, - } - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - - js-tokens@4.0.0: - resolution: - { - integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, - } - - js-yaml@4.1.1: - resolution: - { - integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==, - } - hasBin: true - - jsesc@3.1.0: - resolution: - { - integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==, - } - engines: { node: ">=6" } - hasBin: true - - json-buffer@3.0.1: - resolution: - { - integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, - } - - json-fixer@1.6.15: - resolution: - { - integrity: sha512-TuDuZ5KrgyjoCIppdPXBMqiGfota55+odM+j2cQ5rt/XKyKmqGB3Whz1F8SN8+60yYGy/Nu5lbRZ+rx8kBIvBw==, - } - engines: { node: ">=10" } - - json-parse-better-errors@1.0.2: - resolution: - { - integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==, - } - - json-parse-even-better-errors@2.3.1: - resolution: - { - integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, - } - - json-schema-traverse@0.4.1: - resolution: - { - integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, - } - - json-schema-traverse@1.0.0: - resolution: - { - integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, - } - - json-schema@0.4.0: - resolution: - { - integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==, - } - - json-stable-stringify-without-jsonify@1.0.1: - resolution: - { - integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, - } - - json5@2.2.3: - resolution: - { - integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, - } - engines: { node: ">=6" } - hasBin: true - - jsonfile@6.2.0: - resolution: - { - integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==, - } - - jsonpointer@5.0.1: - resolution: - { - integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==, - } - engines: { node: ">=0.10.0" } - - keyv@4.5.4: - resolution: - { - integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, - } - - keyv@5.6.0: - resolution: - { - integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==, - } - - kind-of@6.0.3: - resolution: - { - integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==, - } - engines: { node: ">=0.10.0" } - - known-css-properties@0.37.0: - resolution: - { - integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==, - } - - leaflet.markercluster@1.5.3: - resolution: - { - integrity: sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==, - } - peerDependencies: - leaflet: ^1.3.1 - - leaflet@1.9.4: - resolution: - { - integrity: sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==, - } - - leven@3.1.0: - resolution: - { - integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==, - } - engines: { node: ">=6" } - - levn@0.4.1: - resolution: - { - integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, - } - engines: { node: ">= 0.8.0" } - - lilconfig@3.1.3: - resolution: - { - integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==, - } - engines: { node: ">=14" } - - lines-and-columns@1.2.4: - resolution: - { - integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, - } - - lint-staged@16.2.7: - resolution: - { - integrity: sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==, - } - engines: { node: ">=20.17" } - hasBin: true - - listr2@9.0.5: - resolution: - { - integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==, - } - engines: { node: ">=20.0.0" } - - lit-element@4.2.2: - resolution: - { - integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==, - } - - lit-html@3.3.2: - resolution: - { - integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==, - } - - lit@3.3.2: - resolution: - { - integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==, - } - - load-json-file@4.0.0: - resolution: - { - integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==, - } - engines: { node: ">=4" } - - locate-path@2.0.0: - resolution: - { - integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==, - } - engines: { node: ">=4" } - - locate-path@5.0.0: - resolution: - { - integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==, - } - engines: { node: ">=8" } - - locate-path@6.0.0: - resolution: - { - integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, - } - engines: { node: ">=10" } - - lodash-es@4.17.23: - resolution: - { - integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==, - } - - lodash.camelcase@4.3.0: - resolution: - { - integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==, - } - - lodash.capitalize@4.2.1: - resolution: - { - integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==, - } - - lodash.debounce@4.0.8: - resolution: - { - integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==, - } - - lodash.escaperegexp@4.1.2: - resolution: - { - integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==, - } - - lodash.isplainobject@4.0.6: - resolution: - { - integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==, - } - - lodash.isstring@4.0.1: - resolution: - { - integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==, - } - - lodash.kebabcase@4.1.1: - resolution: - { - integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==, - } - - lodash.map@4.6.0: - resolution: - { - integrity: sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==, - } - - lodash.memoize@4.1.2: - resolution: - { - integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==, - } - - lodash.mergewith@4.6.2: - resolution: - { - integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==, - } - - lodash.snakecase@4.1.1: - resolution: - { - integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==, - } - - lodash.sortby@4.7.0: - resolution: - { - integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==, - } - - lodash.startcase@4.4.0: - resolution: - { - integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==, - } - - lodash.truncate@4.4.2: - resolution: - { - integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==, - } - - lodash.uniq@4.5.0: - resolution: - { - integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==, - } - - lodash.uniqby@4.7.0: - resolution: - { - integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==, - } - - lodash.upperfirst@4.3.1: - resolution: - { - integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==, - } - - lodash@4.17.21: - resolution: - { - integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, - } - - lodash@4.17.23: - resolution: - { - integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==, - } - - log-symbols@4.1.0: - resolution: - { - integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==, - } - engines: { node: ">=10" } - - log-update@6.1.0: - resolution: - { - integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==, - } - engines: { node: ">=18" } - - longest@2.0.1: - resolution: - { - integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==, - } - engines: { node: ">=0.10.0" } - - lowercase-keys@3.0.0: - resolution: - { - integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - - lru-cache@10.4.3: - resolution: - { - integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==, - } - - lru-cache@11.2.6: - resolution: - { - integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==, - } - engines: { node: 20 || >=22 } - - lru-cache@5.1.1: - resolution: - { - integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, - } - - magic-string@0.25.9: - resolution: - { - integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==, - } - - make-asynchronous@1.0.1: - resolution: - { - integrity: sha512-T9BPOmEOhp6SmV25SwLVcHK4E6JyG/coH3C6F1NjNXSziv/fd4GmsqMk8YR6qpPOswfaOCApSNkZv6fxoaYFcQ==, - } - engines: { node: ">=18" } - - marked-terminal@7.3.0: - resolution: - { - integrity: sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==, - } - engines: { node: ">=16.0.0" } - peerDependencies: - marked: ">=1 <16" - - marked@15.0.12: - resolution: - { - integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==, - } - engines: { node: ">= 18" } - hasBin: true - - marked@17.0.3: - resolution: - { - integrity: sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A==, - } - engines: { node: ">= 20" } - hasBin: true - - math-intrinsics@1.1.0: - resolution: - { - integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, - } - engines: { node: ">= 0.4" } - - mathml-tag-names@4.0.0: - resolution: - { - integrity: sha512-aa6AU2Pcx0VP/XWnh8IGL0SYSgQHDT6Ucror2j2mXeFAlN3ahaNs8EZtG1YiticMkSLj3Gt6VPFfZogt7G5iFQ==, - } - - mdn-data@2.0.28: - resolution: - { - integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==, - } - - mdn-data@2.12.2: - resolution: - { - integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==, - } - - meow@12.1.1: - resolution: - { - integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==, - } - engines: { node: ">=16.10" } - - meow@13.2.0: - resolution: - { - integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==, - } - engines: { node: ">=18" } - - meow@14.0.0: - resolution: - { - integrity: sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==, - } - engines: { node: ">=20" } - - merge-stream@2.0.0: - resolution: - { - integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, - } - - merge2@1.4.1: - resolution: - { - integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, - } - engines: { node: ">= 8" } - - merge@2.1.1: - resolution: - { - integrity: sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==, - } - - micromatch@4.0.8: - resolution: - { - integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==, - } - engines: { node: ">=8.6" } - - mime@4.1.0: - resolution: - { - integrity: sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==, - } - engines: { node: ">=16" } - hasBin: true - - mimic-fn@2.1.0: - resolution: - { - integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==, - } - engines: { node: ">=6" } - - mimic-fn@4.0.0: - resolution: - { - integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==, - } - engines: { node: ">=12" } - - mimic-function@5.0.1: - resolution: - { - integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==, - } - engines: { node: ">=18" } - - mimic-response@4.0.0: - resolution: - { - integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - - mini-svg-data-uri@1.4.4: - resolution: - { - integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==, - } - hasBin: true - - minimatch@10.2.1: - resolution: - { - integrity: sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==, - } - engines: { node: 20 || >=22 } - - minimatch@3.1.2: - resolution: - { - integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, - } - - minimatch@5.1.6: - resolution: - { - integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==, - } - engines: { node: ">=10" } - - minimatch@9.0.5: - resolution: - { - integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==, - } - engines: { node: ">=16 || 14 >=14.17" } - - minimist@1.2.7: - resolution: - { - integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==, - } - - minimist@1.2.8: - resolution: - { - integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, - } - - minipass@7.1.3: - resolution: - { - integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==, - } - engines: { node: ">=16 || 14 >=14.17" } - - mitt@3.0.1: - resolution: - { - integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==, - } - - mrmime@2.0.1: - resolution: - { - integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==, - } - engines: { node: ">=10" } - - ms@2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } - - mute-stream@0.0.8: - resolution: - { - integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==, - } - - mz@2.7.0: - resolution: - { - integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==, - } - - nano-spawn@2.0.0: - resolution: - { - integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==, - } - engines: { node: ">=20.17" } - - nanoid@3.3.11: - resolution: - { - integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==, - } - engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } - hasBin: true - - natural-compare@1.4.0: - resolution: - { - integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, - } - - neo-async@2.6.2: - resolution: - { - integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==, - } - - nerf-dart@1.0.0: - resolution: - { - integrity: sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==, - } - - node-emoji@2.2.0: - resolution: - { - integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==, - } - engines: { node: ">=18" } - - node-fetch@2.7.0: - resolution: - { - integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==, - } - engines: { node: 4.x || >=6.0.0 } - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - node-releases@2.0.27: - resolution: - { - integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==, - } - - normalize-package-data@6.0.2: - resolution: - { - integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==, - } - engines: { node: ^16.14.0 || >=18.0.0 } - - normalize-package-data@8.0.0: - resolution: - { - integrity: sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ==, - } - engines: { node: ^20.17.0 || >=22.9.0 } - - normalize-path@3.0.0: - resolution: - { - integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, - } - engines: { node: ">=0.10.0" } - - normalize-url@8.1.1: - resolution: - { - integrity: sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==, - } - engines: { node: ">=14.16" } - - npm-run-path@4.0.1: - resolution: - { - integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==, - } - engines: { node: ">=8" } - - npm-run-path@5.3.0: - resolution: - { - integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - - npm-run-path@6.0.0: - resolution: - { - integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==, - } - engines: { node: ">=18" } - - npm@11.10.0: - resolution: - { - integrity: sha512-i8hE43iSIAMFuYVi8TxsEISdELM4fIza600aLjJ0ankGPLqd0oTPKMJqAcO/QWm307MbSlWGzJcNZ0lGMQgHPA==, - } - engines: { node: ^20.17.0 || >=22.9.0 } - hasBin: true - bundledDependencies: - - "@isaacs/string-locale-compare" - - "@npmcli/arborist" - - "@npmcli/config" - - "@npmcli/fs" - - "@npmcli/map-workspaces" - - "@npmcli/metavuln-calculator" - - "@npmcli/package-json" - - "@npmcli/promise-spawn" - - "@npmcli/redact" - - "@npmcli/run-script" - - "@sigstore/tuf" - - abbrev - - archy - - cacache - - chalk - - ci-info - - cli-columns - - fastest-levenshtein - - fs-minipass - - glob - - graceful-fs - - hosted-git-info - - ini - - init-package-json - - is-cidr - - json-parse-even-better-errors - - libnpmaccess - - libnpmdiff - - libnpmexec - - libnpmfund - - libnpmorg - - libnpmpack - - libnpmpublish - - libnpmsearch - - libnpmteam - - libnpmversion - - make-fetch-happen - - minimatch - - minipass - - minipass-pipeline - - ms - - node-gyp - - nopt - - npm-audit-report - - npm-install-checks - - npm-package-arg - - npm-pick-manifest - - npm-profile - - npm-registry-fetch - - npm-user-validate - - p-map - - pacote - - parse-conflict-json - - proc-log - - qrcode-terminal - - read - - semver - - spdx-expression-parse - - ssri - - supports-color - - tar - - text-table - - tiny-relative-date - - treeverse - - validate-npm-package-name - - which - - nth-check@2.1.1: - resolution: - { - integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==, - } - - object-assign@4.1.1: - resolution: - { - integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, - } - engines: { node: ">=0.10.0" } - - object-hash@3.0.0: - resolution: - { - integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==, - } - engines: { node: ">= 6" } - - object-inspect@1.13.4: - resolution: - { - integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, - } - engines: { node: ">= 0.4" } - - object-is@1.1.6: - resolution: - { - integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==, - } - engines: { node: ">= 0.4" } - - object-keys@1.1.1: - resolution: - { - integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, - } - engines: { node: ">= 0.4" } - - object.assign@4.1.7: - resolution: - { - integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==, - } - engines: { node: ">= 0.4" } - - ohash@2.0.11: - resolution: - { - integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==, - } - - once@1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, - } - - onetime@5.1.2: - resolution: - { - integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==, - } - engines: { node: ">=6" } - - onetime@6.0.0: - resolution: - { - integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==, - } - engines: { node: ">=12" } - - onetime@7.0.0: - resolution: - { - integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==, - } - engines: { node: ">=18" } - - open@10.2.0: - resolution: - { - integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==, - } - engines: { node: ">=18" } - - optionator@0.9.4: - resolution: - { - integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, - } - engines: { node: ">= 0.8.0" } - - ora@5.4.1: - resolution: - { - integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==, - } - engines: { node: ">=10" } - - os-tmpdir@1.0.2: - resolution: - { - integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==, - } - engines: { node: ">=0.10.0" } - - own-keys@1.0.1: - resolution: - { - integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==, - } - engines: { node: ">= 0.4" } - - p-cancelable@4.0.1: - resolution: - { - integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==, - } - engines: { node: ">=14.16" } - - p-each-series@3.0.0: - resolution: - { - integrity: sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==, - } - engines: { node: ">=12" } - - p-event@6.0.1: - resolution: - { - integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==, - } - engines: { node: ">=16.17" } - - p-filter@4.1.0: - resolution: - { - integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==, - } - engines: { node: ">=18" } - - p-is-promise@3.0.0: - resolution: - { - integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==, - } - engines: { node: ">=8" } - - p-limit@1.3.0: - resolution: - { - integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==, - } - engines: { node: ">=4" } - - p-limit@2.3.0: - resolution: - { - integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==, - } - engines: { node: ">=6" } - - p-limit@3.1.0: - resolution: - { - integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, - } - engines: { node: ">=10" } - - p-locate@2.0.0: - resolution: - { - integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==, - } - engines: { node: ">=4" } - - p-locate@4.1.0: - resolution: - { - integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==, - } - engines: { node: ">=8" } - - p-locate@5.0.0: - resolution: - { - integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, - } - engines: { node: ">=10" } - - p-map@7.0.4: - resolution: - { - integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==, - } - engines: { node: ">=18" } - - p-reduce@2.1.0: - resolution: - { - integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==, - } - engines: { node: ">=8" } - - p-reduce@3.0.0: - resolution: - { - integrity: sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==, - } - engines: { node: ">=12" } - - p-timeout@6.1.4: - resolution: - { - integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==, - } - engines: { node: ">=14.16" } - - p-try@1.0.0: - resolution: - { - integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==, - } - engines: { node: ">=4" } - - p-try@2.2.0: - resolution: - { - integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==, - } - engines: { node: ">=6" } - - package-json-from-dist@1.0.1: - resolution: - { - integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, - } - - pako@0.2.9: - resolution: - { - integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==, - } - - parent-module@1.0.1: - resolution: - { - integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, - } - engines: { node: ">=6" } - - parse-json@4.0.0: - resolution: - { - integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==, - } - engines: { node: ">=4" } - - parse-json@5.2.0: - resolution: - { - integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, - } - engines: { node: ">=8" } - - parse-json@8.3.0: - resolution: - { - integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==, - } - engines: { node: ">=18" } - - parse-ms@4.0.0: - resolution: - { - integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==, - } - engines: { node: ">=18" } - - parse-passwd@1.0.0: - resolution: - { - integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==, - } - engines: { node: ">=0.10.0" } - - parse-path@7.1.0: - resolution: - { - integrity: sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==, - } - - parse-url@10.0.3: - resolution: - { - integrity: sha512-RvldzLvNE0DtOO1loukZsYcHCzHVUnHe7GNyrKIkavp7fNWs5ueX3kUzY/hXS8uRqDWwtaRKDcAmLEVouPIxIw==, - } - engines: { node: ">=14.13.0" } - - parse5-htmlparser2-tree-adapter@6.0.1: - resolution: - { - integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==, - } - - parse5@5.1.1: - resolution: - { - integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==, - } - - parse5@6.0.1: - resolution: - { - integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==, - } - - path-exists@3.0.0: - resolution: - { - integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==, - } - engines: { node: ">=4" } - - path-exists@4.0.0: - resolution: - { - integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, - } - engines: { node: ">=8" } - - path-is-absolute@1.0.1: - resolution: - { - integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, - } - engines: { node: ">=0.10.0" } - - path-key@3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: ">=8" } - - path-key@4.0.0: - resolution: - { - integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==, - } - engines: { node: ">=12" } - - path-parse@1.0.7: - resolution: - { - integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, - } - - path-scurry@2.0.1: - resolution: - { - integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==, - } - engines: { node: 20 || >=22 } - - path-type@4.0.0: - resolution: - { - integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, - } - engines: { node: ">=8" } - - path-type@6.0.0: - resolution: - { - integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==, - } - engines: { node: ">=18" } - - pathe@2.0.3: - resolution: - { - integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, - } - - pdfmake@0.2.23: - resolution: - { - integrity: sha512-A/IksoKb/ikOZH1edSDJ/2zBbqJKDghD4+fXn3rT7quvCJDlsZMs3NmIB3eajLMMFU9Bd3bZPVvlUMXhvFI+bQ==, - } - engines: { node: ">=18" } - - pegjs@0.10.0: - resolution: - { - integrity: sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==, - } - engines: { node: ">=0.10" } - hasBin: true - - perfect-debounce@2.1.0: - resolution: - { - integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==, - } - - performance-now@2.1.0: - resolution: - { - integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==, - } - - picocolors@1.1.1: - resolution: - { - integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, - } - - picomatch@2.3.1: - resolution: - { - integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, - } - engines: { node: ">=8.6" } - - picomatch@4.0.3: - resolution: - { - integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==, - } - engines: { node: ">=12" } - - pidtree@0.6.0: - resolution: - { - integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==, - } - engines: { node: ">=0.10" } - hasBin: true - - pify@2.3.0: - resolution: - { - integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==, - } - engines: { node: ">=0.10.0" } - - pify@3.0.0: - resolution: - { - integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==, - } - engines: { node: ">=4" } - - pify@5.0.0: - resolution: - { - integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==, - } - engines: { node: ">=10" } - - pirates@4.0.7: - resolution: - { - integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==, - } - engines: { node: ">= 6" } - - pkg-conf@2.1.0: - resolution: - { - integrity: sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==, - } - engines: { node: ">=4" } - - png-js@1.0.0: - resolution: - { - integrity: sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==, - } - - polylabel@1.1.0: - resolution: - { - integrity: sha512-bxaGcA40sL3d6M4hH72Z4NdLqxpXRsCFk8AITYg6x1rn1Ei3izf00UMLklerBZTO49aPA3CYrIwVulx2Bce2pA==, - } - - possible-typed-array-names@1.1.0: - resolution: - { - integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==, - } - engines: { node: ">= 0.4" } - - postcss-attribute-case-insensitive@8.0.0: - resolution: - { - integrity: sha512-fovIPEV35c2JzVXdmP+sp2xirbBMt54J+upU8u6TSj410kUU5+axgEzvBBSAX8KCybze8CFCelzFAw/FfWg2TA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-calc@10.1.1: - resolution: - { - integrity: sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw==, - } - engines: { node: ^18.12 || ^20.9 || >=22.0 } - peerDependencies: - postcss: ^8.4.38 - - postcss-clamp@4.1.0: - resolution: - { - integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==, - } - engines: { node: ">=7.6.0" } - peerDependencies: - postcss: ^8.4.6 - - postcss-color-functional-notation@8.0.1: - resolution: - { - integrity: sha512-f1itLOG10iAa9mBAAtIHj/wfDs3srsNv/vrAsiRrIOfTCjhjxHxL1g06vvpQ86he2BP5HwB4cN72EZQ8rkegpA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-color-hex-alpha@11.0.0: - resolution: - { - integrity: sha512-NCGa6vjIyrjosz9GqRxVKbONBklz5TeipYqTJp3IqbnBWlBq5e5EMtG6MaX4vqk9LzocPfMQkuRK9tfk+OQuKg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-color-rebeccapurple@11.0.0: - resolution: - { - integrity: sha512-g9561mx7cbdqx7XeO/L+lJzVlzu7bICyXr72efBVKZGxIhvBBJf9fGXn3Cb6U4Bwh3LbzQO2e9NWBLVYdX5Eag==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-colormin@7.0.5: - resolution: - { - integrity: sha512-ekIBP/nwzRWhEMmIxHHbXHcMdzd1HIUzBECaj5KEdLz9DVP2HzT065sEhvOx1dkLjYW7jyD0CngThx6bpFi2fA==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-convert-values@7.0.8: - resolution: - { - integrity: sha512-+XNKuPfkHTCEo499VzLMYn94TiL3r9YqRE3Ty+jP7UX4qjewUONey1t7CG21lrlTLN07GtGM8MqFVp86D4uKJg==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-custom-media@12.0.0: - resolution: - { - integrity: sha512-jIgEvqceN6ru2uQ0f75W1g+JDi0UyECFeJKjPG7UcSkW3+03LDKH2c6h+9C0XuDTV4y2pEHmD5AJtVBq1OGnZA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-custom-properties@15.0.0: - resolution: - { - integrity: sha512-FsD3VNtFr3qmspvIobDRszK9onKPHp8iHG4Aox2Nnm9SL93uw5GDw4z+NM7zWKiw6U+DSNm24JUm4coyIyanzQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-custom-selectors@9.0.0: - resolution: - { - integrity: sha512-VuV5tLPAm6wq1u699dsrhGCzfLobKe0eD3G8bw3BcTJt6wqQ7RQdfaveJVsCAi23OaQbjIi3K1C7Fj3yZH3f1g==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-dir-pseudo-class@10.0.0: - resolution: - { - integrity: sha512-DmtIzULpyC8XaH4b5AaUgt4Jic4QmrECqidNCdR7u7naQFdnxX80YI06u238a+ZVRXwURDxVzy0s/UQnWmpVeg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-discard-comments@7.0.5: - resolution: - { - integrity: sha512-IR2Eja8WfYgN5n32vEGSctVQ1+JARfu4UH8M7bgGh1bC+xI/obsPJXaBpQF7MAByvgwZinhpHpdrmXtvVVlKcQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-discard-duplicates@7.0.2: - resolution: - { - integrity: sha512-eTonaQvPZ/3i1ASDHOKkYwAybiM45zFIc7KXils4mQmHLqIswXD9XNOKEVxtTFnsmwYzF66u4LMgSr0abDlh5w==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-discard-empty@7.0.1: - resolution: - { - integrity: sha512-cFrJKZvcg/uxB6Ijr4l6qmn3pXQBna9zyrPC+sK0zjbkDUZew+6xDltSF7OeB7rAtzaaMVYSdbod+sZOCWnMOg==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-discard-overridden@7.0.1: - resolution: - { - integrity: sha512-7c3MMjjSZ/qYrx3uc1940GSOzN1Iqjtlqe8uoSg+qdVPYyRb0TILSqqmtlSFuE4mTDECwsm397Ya7iXGzfF7lg==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-double-position-gradients@7.0.0: - resolution: - { - integrity: sha512-Msr/dxj8Os7KLJE5Hdhvprwm3K5Zrh1KTY0eFN3ngPKNkej/Usy4BM9JQmqE6CLAkDpHoQVsi4snbL72CPt6qg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-focus-visible@11.0.0: - resolution: - { - integrity: sha512-VG1a9kBKizUBWS66t5xyB4uLONBnvZLCmZXxT40FALu8EF0QgVZBYy5ApC0KhmpHsv+pvHMJHB3agKHwmocWjw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-focus-within@10.0.0: - resolution: - { - integrity: sha512-dvql0fzUTG+gcJYp+KTbag5vAjuo94LDYZHkqDV1rnf5gPGer1v/SrmIZBdvKU8moep3HbcbujqGjzSb3DL53Q==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-font-variant@5.0.0: - resolution: - { - integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==, - } - peerDependencies: - postcss: ^8.1.0 - - postcss-gap-properties@7.0.0: - resolution: - { - integrity: sha512-PSDF2QoZMRUbsINvXObQgxx4HExRP85QTT8qS/YN9fBsCPWCqUuwqAD6E6PNp0BqL/jU1eyWUBORaOK/J/9LDA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-image-set-function@8.0.0: - resolution: - { - integrity: sha512-rEGNkOkNusf4+IuMmfEoIdLuVmvbExGbmG+MIsyV6jR5UaWSoyPcAYHV/PxzVDCmudyF+2Nh/o6Ub2saqUdnuA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-import@15.1.0: - resolution: - { - integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==, - } - engines: { node: ">=14.0.0" } - peerDependencies: - postcss: ^8.0.0 - - postcss-import@16.1.1: - resolution: - { - integrity: sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==, - } - engines: { node: ">=18.0.0" } - peerDependencies: - postcss: ^8.0.0 - - postcss-js@4.1.0: - resolution: - { - integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==, - } - engines: { node: ^12 || ^14 || >= 16 } - peerDependencies: - postcss: ^8.4.21 - - postcss-lab-function@8.0.1: - resolution: - { - integrity: sha512-Q/ANnuCYtanAc+2NnCaZrYu+GofYQUV603JXL0KB6GlcXxpnm/UerPAmpKQdb9pxYUkpKovGxfL43aOUnpF/Hg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-load-config@6.0.1: - resolution: - { - integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==, - } - engines: { node: ">= 18" } - peerDependencies: - jiti: ">=1.21.0" - postcss: ">=8.0.9" - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - jiti: - optional: true - postcss: - optional: true - tsx: - optional: true - yaml: - optional: true - - postcss-logical@9.0.0: - resolution: - { - integrity: sha512-A4LNd9dk3q/juEUA9Gd8ALhBO3TeOeYurnyHLlf2aAToD94VHR8c5Uv7KNmf8YVRhTxvWsyug4c5fKtARzyIRQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-merge-longhand@7.0.5: - resolution: - { - integrity: sha512-Kpu5v4Ys6QI59FxmxtNB/iHUVDn9Y9sYw66D6+SZoIk4QTz1prC4aYkhIESu+ieG1iylod1f8MILMs1Em3mmIw==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-merge-rules@7.0.7: - resolution: - { - integrity: sha512-njWJrd/Ms6XViwowaaCc+/vqhPG3SmXn725AGrnl+BgTuRPEacjiLEaGq16J6XirMJbtKkTwnt67SS+e2WGoew==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-minify-font-values@7.0.1: - resolution: - { - integrity: sha512-2m1uiuJeTplll+tq4ENOQSzB8LRnSUChBv7oSyFLsJRtUgAAJGP6LLz0/8lkinTgxrmJSPOEhgY1bMXOQ4ZXhQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-minify-gradients@7.0.1: - resolution: - { - integrity: sha512-X9JjaysZJwlqNkJbUDgOclyG3jZEpAMOfof6PUZjPnPrePnPG62pS17CjdM32uT1Uq1jFvNSff9l7kNbmMSL2A==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-minify-params@7.0.5: - resolution: - { - integrity: sha512-FGK9ky02h6Ighn3UihsyeAH5XmLEE2MSGH5Tc4tXMFtEDx7B+zTG6hD/+/cT+fbF7PbYojsmmWjyTwFwW1JKQQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-minify-selectors@7.0.5: - resolution: - { - integrity: sha512-x2/IvofHcdIrAm9Q+p06ZD1h6FPcQ32WtCRVodJLDR+WMn8EVHI1kvLxZuGKz/9EY5nAmI6lIQIrpo4tBy5+ug==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-nested@6.2.0: - resolution: - { - integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==, - } - engines: { node: ">=12.0" } - peerDependencies: - postcss: ^8.2.14 - - postcss-nesting@14.0.0: - resolution: - { - integrity: sha512-YGFOfVrjxYfeGTS5XctP1WCI5hu8Lr9SmntjfRC+iX5hCihEO+QZl9Ra+pkjqkgoVdDKvb2JccpElcowhZtzpw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-normalize-charset@7.0.1: - resolution: - { - integrity: sha512-sn413ofhSQHlZFae//m9FTOfkmiZ+YQXsbosqOWRiVQncU2BA3daX3n0VF3cG6rGLSFVc5Di/yns0dFfh8NFgQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-normalize-display-values@7.0.1: - resolution: - { - integrity: sha512-E5nnB26XjSYz/mGITm6JgiDpAbVuAkzXwLzRZtts19jHDUBFxZ0BkXAehy0uimrOjYJbocby4FVswA/5noOxrQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-normalize-positions@7.0.1: - resolution: - { - integrity: sha512-pB/SzrIP2l50ZIYu+yQZyMNmnAcwyYb9R1fVWPRxm4zcUFCY2ign7rcntGFuMXDdd9L2pPNUgoODDk91PzRZuQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-normalize-repeat-style@7.0.1: - resolution: - { - integrity: sha512-NsSQJ8zj8TIDiF0ig44Byo3Jk9e4gNt9x2VIlJudnQQ5DhWAHJPF4Tr1ITwyHio2BUi/I6Iv0HRO7beHYOloYQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-normalize-string@7.0.1: - resolution: - { - integrity: sha512-QByrI7hAhsoze992kpbMlJSbZ8FuCEc1OT9EFbZ6HldXNpsdpZr+YXC5di3UEv0+jeZlHbZcoCADgb7a+lPmmQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-normalize-timing-functions@7.0.1: - resolution: - { - integrity: sha512-bHifyuuSNdKKsnNJ0s8fmfLMlvsQwYVxIoUBnowIVl2ZAdrkYQNGVB4RxjfpvkMjipqvbz0u7feBZybkl/6NJg==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-normalize-unicode@7.0.5: - resolution: - { - integrity: sha512-X6BBwiRxVaFHrb2WyBMddIeB5HBjJcAaUHyhLrM2FsxSq5TFqcHSsK7Zu1otag+o0ZphQGJewGH1tAyrD0zX1Q==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-normalize-url@7.0.1: - resolution: - { - integrity: sha512-sUcD2cWtyK1AOL/82Fwy1aIVm/wwj5SdZkgZ3QiUzSzQQofrbq15jWJ3BA7Z+yVRwamCjJgZJN0I9IS7c6tgeQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-normalize-whitespace@7.0.1: - resolution: - { - integrity: sha512-vsbgFHMFQrJBJKrUFJNZ2pgBeBkC2IvvoHjz1to0/0Xk7sII24T0qFOiJzG6Fu3zJoq/0yI4rKWi7WhApW+EFA==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-opacity-percentage@3.0.0: - resolution: - { - integrity: sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==, - } - engines: { node: ">=18" } - peerDependencies: - postcss: ^8.4 - - postcss-ordered-values@7.0.2: - resolution: - { - integrity: sha512-AMJjt1ECBffF7CEON/Y0rekRLS6KsePU6PRP08UqYW4UGFRnTXNrByUzYK1h8AC7UWTZdQ9O3Oq9kFIhm0SFEw==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-overflow-shorthand@7.0.0: - resolution: - { - integrity: sha512-9SLpjoUdGRoRrzoOdX66HbUs0+uDwfIAiXsRa7piKGOqPd6F4ZlON9oaDSP5r1Qpgmzw5L9Ht0undIK6igJPMA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-page-break@3.0.4: - resolution: - { - integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==, - } - peerDependencies: - postcss: ^8 - - postcss-place@11.0.0: - resolution: - { - integrity: sha512-fAifpyjQ+fuDRp2nmF95WbotqbpjdazebedahXdfBxy5sHembOLpBQ1cHveZD9ZmjK26tYM8tikeNaUlp/KfHA==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-preset-env@11.1.3: - resolution: - { - integrity: sha512-kZOfgzUc52yq2fJRZig7sHgWaHJoDOLABBoswe6TPTHgW3581VkP3eRj+Silhc7cJTomMjZZsyRHNjQ+bW11Gg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-pseudo-class-any-link@11.0.0: - resolution: - { - integrity: sha512-DNFZ4GMa3C3pU5dM+UCTG1CEeLtS1ZqV5DKSqCTJQMn1G5jnd/30fS8+A7H4o5bSD3MOcnx+VgI+xPE9Z5Wvig==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-reduce-initial@7.0.5: - resolution: - { - integrity: sha512-RHagHLidG8hTZcnr4FpyMB2jtgd/OcyAazjMhoy5qmWJOx1uxKh4ntk0Pb46ajKM0rkf32lRH4C8c9qQiPR6IA==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-reduce-transforms@7.0.1: - resolution: - { - integrity: sha512-MhyEbfrm+Mlp/36hvZ9mT9DaO7dbncU0CvWI8V93LRkY6IYlu38OPg3FObnuKTUxJ4qA8HpurdQOo5CyqqO76g==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-replace-overflow-wrap@4.0.0: - resolution: - { - integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==, - } - peerDependencies: - postcss: ^8.0.3 - - postcss-reporter@7.1.0: - resolution: - { - integrity: sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA==, - } - engines: { node: ">=10" } - peerDependencies: - postcss: ^8.1.0 - - postcss-safe-parser@7.0.1: - resolution: - { - integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==, - } - engines: { node: ">=18.0" } - peerDependencies: - postcss: ^8.4.31 - - postcss-selector-not@9.0.0: - resolution: - { - integrity: sha512-xhAtTdHnVU2M/CrpYOPyRUvg3njhVlKmn2GNYXDaRJV9Ygx4d5OkSkc7NINzjUqnbDFtaKXlISOBeyMXU/zyFQ==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - postcss: ^8.4 - - postcss-selector-parser@6.0.10: - resolution: - { - integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==, - } - engines: { node: ">=4" } - - postcss-selector-parser@6.1.2: - resolution: - { - integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==, - } - engines: { node: ">=4" } - - postcss-selector-parser@7.1.1: - resolution: - { - integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==, - } - engines: { node: ">=4" } - - postcss-svgo@7.1.0: - resolution: - { - integrity: sha512-KnAlfmhtoLz6IuU3Sij2ycusNs4jPW+QoFE5kuuUOK8awR6tMxZQrs5Ey3BUz7nFCzT3eqyFgqkyrHiaU2xx3w==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >= 18 } - peerDependencies: - postcss: ^8.4.32 - - postcss-unique-selectors@7.0.4: - resolution: - { - integrity: sha512-pmlZjsmEAG7cHd7uK3ZiNSW6otSZ13RHuZ/4cDN/bVglS5EpF2r2oxY99SuOHa8m7AWoBCelTS3JPpzsIs8skQ==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - postcss-value-parser@4.2.0: - resolution: - { - integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==, - } - - postcss@8.5.6: - resolution: - { - integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==, - } - engines: { node: ^10 || ^12 || >=14 } - - prelude-ls@1.2.1: - resolution: - { - integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, - } - engines: { node: ">= 0.8.0" } - - prettier-linter-helpers@1.0.1: - resolution: - { - integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==, - } - engines: { node: ">=6.0.0" } - - prettier-plugin-organize-imports@4.3.0: - resolution: - { - integrity: sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==, - } - peerDependencies: - prettier: ">=2.0" - typescript: ">=2.9" - vue-tsc: ^2.1.0 || 3 - peerDependenciesMeta: - vue-tsc: - optional: true - - prettier@2.8.8: - resolution: - { - integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==, - } - engines: { node: ">=10.13.0" } - hasBin: true - - prettier@3.8.1: - resolution: - { - integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==, - } - engines: { node: ">=14" } - hasBin: true - - pretty-bytes@5.6.0: - resolution: - { - integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==, - } - engines: { node: ">=6" } - - pretty-bytes@6.1.1: - resolution: - { - integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==, - } - engines: { node: ^14.13.1 || >=16.0.0 } - - pretty-ms@9.3.0: - resolution: - { - integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==, - } - engines: { node: ">=18" } - - process-nextick-args@2.0.1: - resolution: - { - integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==, - } - - proto-list@1.2.4: - resolution: - { - integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==, - } - - protocols@2.0.2: - resolution: - { - integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==, - } - - punycode@2.3.1: - resolution: - { - integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, - } - engines: { node: ">=6" } - - qified@0.6.0: - resolution: - { - integrity: sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==, - } - engines: { node: ">=20" } - - queue-microtask@1.2.3: - resolution: - { - integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, - } - - quick-lru@5.1.1: - resolution: - { - integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==, - } - engines: { node: ">=10" } - - raf@3.4.1: - resolution: - { - integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==, - } - - randombytes@2.1.0: - resolution: - { - integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==, - } - - rc@1.2.8: - resolution: - { - integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==, - } - hasBin: true - - read-cache@1.0.0: - resolution: - { - integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==, - } - - read-package-up@11.0.0: - resolution: - { - integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==, - } - engines: { node: ">=18" } - - read-package-up@12.0.0: - resolution: - { - integrity: sha512-Q5hMVBYur/eQNWDdbF4/Wqqr9Bjvtrw2kjGxxBbKLbx8bVCL8gcArjTy8zDUuLGQicftpMuU0riQNcAsbtOVsw==, - } - engines: { node: ">=20" } - - read-pkg@10.1.0: - resolution: - { - integrity: sha512-I8g2lArQiP78ll51UeMZojewtYgIRCKCWqZEgOO8c/uefTI+XDXvCSXu3+YNUaTNvZzobrL5+SqHjBrByRRTdg==, - } - engines: { node: ">=20" } - - read-pkg@9.0.1: - resolution: - { - integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==, - } - engines: { node: ">=18" } - - readable-stream@2.3.8: - resolution: - { - integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==, - } - - readable-stream@3.6.2: - resolution: - { - integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, - } - engines: { node: ">= 6" } - - readdirp@3.6.0: - resolution: - { - integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, - } - engines: { node: ">=8.10.0" } - - reflect.getprototypeof@1.0.10: - resolution: - { - integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==, - } - engines: { node: ">= 0.4" } - - regenerate-unicode-properties@10.2.2: - resolution: - { - integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==, - } - engines: { node: ">=4" } - - regenerate@1.4.2: - resolution: - { - integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==, - } - - regexp.prototype.flags@1.5.4: - resolution: - { - integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==, - } - engines: { node: ">= 0.4" } - - regexpu-core@6.4.0: - resolution: - { - integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==, - } - engines: { node: ">=4" } - - registry-auth-token@5.1.1: - resolution: - { - integrity: sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==, - } - engines: { node: ">=14" } - - regjsgen@0.8.0: - resolution: - { - integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==, - } - - regjsparser@0.13.0: - resolution: - { - integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==, - } - hasBin: true - - regression@2.0.1: - resolution: - { - integrity: sha512-A4XYsc37dsBaNOgEjkJKzfJlE394IMmUPlI/p3TTI9u3T+2a+eox5Pr/CPUqF0eszeWZJPAc6QkroAhuUpWDJQ==, - } - - require-directory@2.1.1: - resolution: - { - integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, - } - engines: { node: ">=0.10.0" } - - require-from-string@2.0.2: - resolution: - { - integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, - } - engines: { node: ">=0.10.0" } - - require-main-filename@2.0.0: - resolution: - { - integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==, - } - - resolve-alpn@1.2.1: - resolution: - { - integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==, - } - - resolve-dir@1.0.1: - resolution: - { - integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==, - } - engines: { node: ">=0.10.0" } - - resolve-from@4.0.0: - resolution: - { - integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, - } - engines: { node: ">=4" } - - resolve-from@5.0.0: - resolution: - { - integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==, - } - engines: { node: ">=8" } - - resolve@1.22.11: - resolution: - { - integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==, - } - engines: { node: ">= 0.4" } - hasBin: true - - responselike@4.0.2: - resolution: - { - integrity: sha512-cGk8IbWEAnaCpdAt1BHzJ3Ahz5ewDJa0KseTsE3qIRMJ3C698W8psM7byCeWVpd/Ha7FUYzuRVzXoKoM6nRUbA==, - } - engines: { node: ">=20" } - - restore-cursor@3.1.0: - resolution: - { - integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==, - } - engines: { node: ">=8" } - - restore-cursor@5.1.0: - resolution: - { - integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==, - } - engines: { node: ">=18" } - - reusify@1.1.0: - resolution: - { - integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==, - } - engines: { iojs: ">=1.0.0", node: ">=0.10.0" } - - rfdc@1.4.1: - resolution: - { - integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==, - } - - rgbcolor@1.0.1: - resolution: - { - integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==, - } - engines: { node: ">= 0.8.15" } - - rollup@2.79.2: - resolution: - { - integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==, - } - engines: { node: ">=10.0.0" } - hasBin: true - - rollup@4.57.1: - resolution: - { - integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==, - } - engines: { node: ">=18.0.0", npm: ">=8.0.0" } - hasBin: true - - run-applescript@7.1.0: - resolution: - { - integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==, - } - engines: { node: ">=18" } - - run-async@2.4.1: - resolution: - { - integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==, - } - engines: { node: ">=0.12.0" } - - run-parallel@1.2.0: - resolution: - { - integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, - } - - rxjs@6.6.7: - resolution: - { - integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==, - } - engines: { npm: ">=2.0.0" } - - rxjs@7.8.2: - resolution: - { - integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==, - } - - safe-array-concat@1.1.3: - resolution: - { - integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==, - } - engines: { node: ">=0.4" } - - safe-buffer@5.1.2: - resolution: - { - integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, - } - - safe-buffer@5.2.1: - resolution: - { - integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, - } - - safe-push-apply@1.0.0: - resolution: - { - integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==, - } - engines: { node: ">= 0.4" } - - safe-regex-test@1.1.0: - resolution: - { - integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==, - } - engines: { node: ">= 0.4" } - - safer-buffer@2.1.2: - resolution: - { - integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, - } - - sax@1.4.4: - resolution: - { - integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==, - } - engines: { node: ">=11.0.0" } - - semantic-release@25.0.3: - resolution: - { - integrity: sha512-WRgl5GcypwramYX4HV+eQGzUbD7UUbljVmS+5G1uMwX/wLgYuJAxGeerXJDMO2xshng4+FXqCgyB5QfClV6WjA==, - } - engines: { node: ^22.14.0 || >= 24.10.0 } - hasBin: true - - semver-regex@4.0.5: - resolution: - { - integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==, - } - engines: { node: ">=12" } - - semver@6.3.1: - resolution: - { - integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==, - } - hasBin: true - - semver@7.7.4: - resolution: - { - integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==, - } - engines: { node: ">=10" } - hasBin: true - - serialize-javascript@6.0.2: - resolution: - { - integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==, - } - - set-blocking@2.0.0: - resolution: - { - integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==, - } - - set-function-length@1.2.2: - resolution: - { - integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==, - } - engines: { node: ">= 0.4" } - - set-function-name@2.0.2: - resolution: - { - integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==, - } - engines: { node: ">= 0.4" } - - set-proto@1.0.0: - resolution: - { - integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==, - } - engines: { node: ">= 0.4" } - - sharp@0.34.5: - resolution: - { - integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - - shebang-command@2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: ">=8" } - - shebang-regex@3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: ">=8" } - - side-channel-list@1.0.0: - resolution: - { - integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==, - } - engines: { node: ">= 0.4" } - - side-channel-map@1.0.1: - resolution: - { - integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, - } - engines: { node: ">= 0.4" } - - side-channel-weakmap@1.0.2: - resolution: - { - integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, - } - engines: { node: ">= 0.4" } - - side-channel@1.1.0: - resolution: - { - integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==, - } - engines: { node: ">= 0.4" } - - signal-exit@3.0.7: - resolution: - { - integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, - } - - signal-exit@4.1.0: - resolution: - { - integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, - } - engines: { node: ">=14" } - - signale@1.4.0: - resolution: - { - integrity: sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==, - } - engines: { node: ">=6" } - - sirv@3.0.2: - resolution: - { - integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==, - } - engines: { node: ">=18" } - - skin-tone@2.0.0: - resolution: - { - integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==, - } - engines: { node: ">=8" } - - slash@5.1.0: - resolution: - { - integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==, - } - engines: { node: ">=14.16" } - - slice-ansi@4.0.0: - resolution: - { - integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==, - } - engines: { node: ">=10" } - - slice-ansi@7.1.2: - resolution: - { - integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==, - } - engines: { node: ">=18" } - - smob@1.6.1: - resolution: - { - integrity: sha512-KAkBqZl3c2GvNgNhcoyJae1aKldDW0LO279wF9bk1PnluRTETKBq0WyzRXxEhoQLk56yHaOY4JCBEKDuJIET5g==, - } - engines: { node: ">=20.0.0" } - - source-map-js@1.2.1: - resolution: - { - integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, - } - engines: { node: ">=0.10.0" } - - source-map-support@0.5.21: - resolution: - { - integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==, - } - - source-map@0.6.1: - resolution: - { - integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, - } - engines: { node: ">=0.10.0" } - - source-map@0.8.0-beta.0: - resolution: - { - integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==, - } - engines: { node: ">= 8" } - deprecated: The work that was done in this beta branch won't be included in future versions - - sourcemap-codec@1.4.8: - resolution: - { - integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==, - } - deprecated: Please use @jridgewell/sourcemap-codec instead - - spawn-error-forwarder@1.0.0: - resolution: - { - integrity: sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==, - } - - spdx-correct@3.2.0: - resolution: - { - integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==, - } - - spdx-exceptions@2.5.0: - resolution: - { - integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==, - } - - spdx-expression-parse@3.0.1: - resolution: - { - integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==, - } - - spdx-license-ids@3.0.22: - resolution: - { - integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==, - } - - split2@1.0.0: - resolution: - { - integrity: sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==, - } - - split2@4.2.0: - resolution: - { - integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==, - } - engines: { node: ">= 10.x" } - - stackblur-canvas@2.7.0: - resolution: - { - integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==, - } - engines: { node: ">=0.1.14" } - - stencil-wormhole@3.4.1: - resolution: - { - integrity: sha512-ppYTcWTJnIl4ZAKwF39LTA9f/ypHfbVefsHdN2hpMQGrR57wt1TieZo9tlCM/r1Y4SFiZ5yz/cjho564C921Xw==, - } - - stop-iteration-iterator@1.1.0: - resolution: - { - integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==, - } - engines: { node: ">= 0.4" } - - stream-combiner2@1.1.1: - resolution: - { - integrity: sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==, - } - - string-argv@0.3.2: - resolution: - { - integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==, - } - engines: { node: ">=0.6.19" } - - string-width@4.2.3: - resolution: - { - integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, - } - engines: { node: ">=8" } - - string-width@7.2.0: - resolution: - { - integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==, - } - engines: { node: ">=18" } - - string-width@8.2.0: - resolution: - { - integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==, - } - engines: { node: ">=20" } - - string.prototype.matchall@4.0.12: - resolution: - { - integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==, - } - engines: { node: ">= 0.4" } - - string.prototype.trim@1.2.10: - resolution: - { - integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==, - } - engines: { node: ">= 0.4" } - - string.prototype.trimend@1.0.9: - resolution: - { - integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==, - } - engines: { node: ">= 0.4" } - - string.prototype.trimstart@1.0.8: - resolution: - { - integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==, - } - engines: { node: ">= 0.4" } - - string_decoder@1.1.1: - resolution: - { - integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==, - } - - string_decoder@1.3.0: - resolution: - { - integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, - } - - stringify-object@3.3.0: - resolution: - { - integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==, - } - engines: { node: ">=4" } - - strip-ansi@6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, - } - engines: { node: ">=8" } - - strip-ansi@7.1.2: - resolution: - { - integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==, - } - engines: { node: ">=12" } - - strip-bom@3.0.0: - resolution: - { - integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, - } - engines: { node: ">=4" } - - strip-bom@4.0.0: - resolution: - { - integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==, - } - engines: { node: ">=8" } - - strip-comments@2.0.1: - resolution: - { - integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==, - } - engines: { node: ">=10" } - - strip-final-newline@2.0.0: - resolution: - { - integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==, - } - engines: { node: ">=6" } - - strip-final-newline@3.0.0: - resolution: - { - integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==, - } - engines: { node: ">=12" } - - strip-final-newline@4.0.0: - resolution: - { - integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==, - } - engines: { node: ">=18" } - - strip-json-comments@2.0.1: - resolution: - { - integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==, - } - engines: { node: ">=0.10.0" } - - strip-json-comments@3.1.1: - resolution: - { - integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, - } - engines: { node: ">=8" } - - style-mod@4.1.3: - resolution: - { - integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==, - } - - stylehacks@7.0.7: - resolution: - { - integrity: sha512-bJkD0JkEtbRrMFtwgpJyBbFIwfDDONQ1Ov3sDLZQP8HuJ73kBOyx66H4bOcAbVWmnfLdvQ0AJwXxOMkpujcO6g==, - } - engines: { node: ^18.12.0 || ^20.9.0 || >=22.0 } - peerDependencies: - postcss: ^8.4.32 - - stylelint-config-recommended@18.0.0: - resolution: - { - integrity: sha512-mxgT2XY6YZ3HWWe3Di8umG6aBmWmHTblTgu/f10rqFXnyWxjKWwNdjSWkgkwCtxIKnqjSJzvFmPT5yabVIRxZg==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - stylelint: ^17.0.0 - - stylelint-config-standard@40.0.0: - resolution: - { - integrity: sha512-EznGJxOUhtWck2r6dJpbgAdPATIzvpLdK9+i5qPd4Lx70es66TkBPljSg4wN3Qnc6c4h2n+WbUrUynQ3fanjHw==, - } - engines: { node: ">=20.19.0" } - peerDependencies: - stylelint: ^17.0.0 - - stylelint@17.3.0: - resolution: - { - integrity: sha512-1POV91lcEMhj6SLVaOeA0KlS9yattS+qq+cyWqP/nYzWco7K5jznpGH1ExngvPlTM9QF1Kjd2bmuzJu9TH2OcA==, - } - engines: { node: ">=20.19.0" } - hasBin: true - - sucrase@3.35.1: - resolution: - { - integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==, - } - engines: { node: ">=16 || 14 >=14.17" } - hasBin: true - - super-regex@1.1.0: - resolution: - { - integrity: sha512-WHkws2ZflZe41zj6AolvvmaTrWds/VuyeYr9iPVv/oQeaIoVxMKaushfFWpOGDT+GuBrM/sVqF8KUCYQlSSTdQ==, - } - engines: { node: ">=18" } - - supports-color@10.2.2: - resolution: - { - integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==, - } - engines: { node: ">=18" } - - supports-color@5.5.0: - resolution: - { - integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, - } - engines: { node: ">=4" } - - supports-color@7.2.0: - resolution: - { - integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, - } - engines: { node: ">=8" } - - supports-hyperlinks@3.2.0: - resolution: - { - integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==, - } - engines: { node: ">=14.18" } - - supports-hyperlinks@4.4.0: - resolution: - { - integrity: sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==, - } - engines: { node: ">=20" } - - supports-preserve-symlinks-flag@1.0.0: - resolution: - { - integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, - } - engines: { node: ">= 0.4" } - - svg-tags@1.0.0: - resolution: - { - integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==, - } - - svgo@4.0.0: - resolution: - { - integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==, - } - engines: { node: ">=16" } - hasBin: true - - synckit@0.11.12: - resolution: - { - integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==, - } - engines: { node: ^14.18.0 || >=16.0.0 } - - table@6.9.0: - resolution: - { - integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==, - } - engines: { node: ">=10.0.0" } - - tagged-tag@1.0.0: - resolution: - { - integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==, - } - engines: { node: ">=20" } - - tailwindcss@3.4.19: - resolution: - { - integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==, - } - engines: { node: ">=14.0.0" } - hasBin: true - - temp-dir@2.0.0: - resolution: - { - integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==, - } - engines: { node: ">=8" } - - temp-dir@3.0.0: - resolution: - { - integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==, - } - engines: { node: ">=14.16" } - - tempy@0.6.0: - resolution: - { - integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==, - } - engines: { node: ">=10" } - - tempy@3.2.0: - resolution: - { - integrity: sha512-d79HhZya5Djd7am0q+W4RTsSU+D/aJzM+4Y4AGJGuGlgM2L6sx5ZvOYTmZjqPhrDrV6xJTtRSm1JCLj6V6LHLQ==, - } - engines: { node: ">=14.16" } - - terser@5.46.0: - resolution: - { - integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==, - } - engines: { node: ">=10" } - hasBin: true - - thenby@1.3.4: - resolution: - { - integrity: sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==, - } - - thenify-all@1.6.0: - resolution: - { - integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==, - } - engines: { node: ">=0.8" } - - thenify@3.3.1: - resolution: - { - integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==, - } - - through2@2.0.5: - resolution: - { - integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==, - } - - through@2.3.8: - resolution: - { - integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==, - } - - time-span@5.1.0: - resolution: - { - integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==, - } - engines: { node: ">=12" } - - tiny-inflate@1.0.3: - resolution: - { - integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==, - } - - tinyexec@1.0.2: - resolution: - { - integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==, - } - engines: { node: ">=18" } - - tinyglobby@0.2.15: - resolution: - { - integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==, - } - engines: { node: ">=12.0.0" } - - tinyqueue@2.0.3: - resolution: - { - integrity: sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==, - } - - tmp@0.0.33: - resolution: - { - integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==, - } - engines: { node: ">=0.6.0" } - - to-regex-range@5.0.1: - resolution: - { - integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, - } - engines: { node: ">=8.0" } - - totalist@3.0.1: - resolution: - { - integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==, - } - engines: { node: ">=6" } - - tr46@0.0.3: - resolution: - { - integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, - } - - tr46@1.0.1: - resolution: - { - integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==, - } - - traverse@0.6.8: - resolution: - { - integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==, - } - engines: { node: ">= 0.4" } - - ts-api-utils@2.4.0: - resolution: - { - integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==, - } - engines: { node: ">=18.12" } - peerDependencies: - typescript: ">=4.8.4" - - ts-interface-checker@0.1.13: - resolution: - { - integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==, - } - - tslib@1.14.1: - resolution: - { - integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==, - } - - tslib@2.8.1: - resolution: - { - integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, - } - - tunnel@0.0.6: - resolution: - { - integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==, - } - engines: { node: ">=0.6.11 <=0.7.0 || >=0.7.3" } - - type-check@0.4.0: - resolution: - { - integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, - } - engines: { node: ">= 0.8.0" } - - type-fest@0.16.0: - resolution: - { - integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==, - } - engines: { node: ">=10" } - - type-fest@0.21.3: - resolution: - { - integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==, - } - engines: { node: ">=10" } - - type-fest@1.4.0: - resolution: - { - integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==, - } - engines: { node: ">=10" } - - type-fest@2.19.0: - resolution: - { - integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==, - } - engines: { node: ">=12.20" } - - type-fest@4.41.0: - resolution: - { - integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==, - } - engines: { node: ">=16" } - - type-fest@5.4.4: - resolution: - { - integrity: sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==, - } - engines: { node: ">=20" } - - typed-array-buffer@1.0.3: - resolution: - { - integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==, - } - engines: { node: ">= 0.4" } - - typed-array-byte-length@1.0.3: - resolution: - { - integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==, - } - engines: { node: ">= 0.4" } - - typed-array-byte-offset@1.0.4: - resolution: - { - integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==, - } - engines: { node: ">= 0.4" } - - typed-array-length@1.0.7: - resolution: - { - integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==, - } - engines: { node: ">= 0.4" } - - typescript-eslint@8.56.0: - resolution: - { - integrity: sha512-c7toRLrotJ9oixgdW7liukZpsnq5CZ7PuKztubGYlNppuTqhIoWfhgHo/7EU0v06gS2l/x0i2NEFK1qMIf0rIg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - - typescript@5.9.3: - resolution: - { - integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, - } - engines: { node: ">=14.17" } - hasBin: true - - uglify-js@3.19.3: - resolution: - { - integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==, - } - engines: { node: ">=0.8.0" } - hasBin: true - - unbox-primitive@1.1.0: - resolution: - { - integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==, - } - engines: { node: ">= 0.4" } - - undici-types@7.14.0: - resolution: - { - integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==, - } - - undici@6.23.0: - resolution: - { - integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==, - } - engines: { node: ">=18.17" } - - undici@7.22.0: - resolution: - { - integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==, - } - engines: { node: ">=20.18.1" } - - unicode-canonical-property-names-ecmascript@2.0.1: - resolution: - { - integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==, - } - engines: { node: ">=4" } - - unicode-emoji-modifier-base@1.0.0: - resolution: - { - integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==, - } - engines: { node: ">=4" } - - unicode-match-property-ecmascript@2.0.0: - resolution: - { - integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==, - } - engines: { node: ">=4" } - - unicode-match-property-value-ecmascript@2.2.1: - resolution: - { - integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==, - } - engines: { node: ">=4" } - - unicode-properties@1.4.1: - resolution: - { - integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==, - } - - unicode-property-aliases-ecmascript@2.2.0: - resolution: - { - integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==, - } - engines: { node: ">=4" } - - unicode-trie@2.0.0: - resolution: - { - integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==, - } - - unicorn-magic@0.1.0: - resolution: - { - integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==, - } - engines: { node: ">=18" } - - unicorn-magic@0.3.0: - resolution: - { - integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==, - } - engines: { node: ">=18" } - - unicorn-magic@0.4.0: - resolution: - { - integrity: sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==, - } - engines: { node: ">=20" } - - unique-string@2.0.0: - resolution: - { - integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==, - } - engines: { node: ">=8" } - - unique-string@3.0.0: - resolution: - { - integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==, - } - engines: { node: ">=12" } - - universal-user-agent@7.0.3: - resolution: - { - integrity: sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==, - } - - universalify@2.0.1: - resolution: - { - integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, - } - engines: { node: ">= 10.0.0" } - - unplugin-utils@0.3.1: - resolution: - { - integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==, - } - engines: { node: ">=20.19.0" } - - upath@1.2.0: - resolution: - { - integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==, - } - engines: { node: ">=4" } - - update-browserslist-db@1.2.3: - resolution: - { - integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, - } - hasBin: true - peerDependencies: - browserslist: ">= 4.21.0" - - uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } - - url-join@4.0.1: - resolution: - { - integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==, - } - - url-join@5.0.0: - resolution: - { - integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } - - util-deprecate@1.0.2: - resolution: - { - integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, - } - - validate-npm-package-license@3.0.4: - resolution: - { - integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==, - } - - vite-dev-rpc@1.1.0: - resolution: - { - integrity: sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==, - } - peerDependencies: - vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0 - - vite-hot-client@2.1.0: - resolution: - { - integrity: sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==, - } - peerDependencies: - vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 - - vite-plugin-codeigniter@2.0.0: - resolution: - { - integrity: sha512-F4S23BlXu1Yhb2k/cHeB3DV8q1BN+GNFf63jDFRqL4vwdv12/RWK+hBhNSsUUQguklogluza6GL+U1W8t/ba0w==, - } - peerDependencies: - vite: ^7.0.0 - - vite-plugin-inspect@11.3.3: - resolution: - { - integrity: sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==, - } - engines: { node: ">=14" } - peerDependencies: - "@nuxt/kit": "*" - vite: ^6.0.0 || ^7.0.0-0 - peerDependenciesMeta: - "@nuxt/kit": - optional: true - - vite-plugin-pwa@1.2.0: - resolution: - { - integrity: sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==, - } - engines: { node: ">=16.0.0" } - peerDependencies: - "@vite-pwa/assets-generator": ^1.0.0 - vite: ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - workbox-build: ^7.4.0 - workbox-window: ^7.4.0 - peerDependenciesMeta: - "@vite-pwa/assets-generator": - optional: true - - vite-plugin-static-copy@3.2.0: - resolution: - { - integrity: sha512-g2k9z8B/1Bx7D4wnFjPLx9dyYGrqWMLTpwTtPHhcU+ElNZP2O4+4OsyaficiDClus0dzVhdGvoGFYMJxoXZ12Q==, - } - engines: { node: ^18.0.0 || >=20.0.0 } - peerDependencies: - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 - - vite@7.3.1: - resolution: - { - integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==, - } - engines: { node: ^20.19.0 || >=22.12.0 } - hasBin: true - peerDependencies: - "@types/node": ^20.19.0 || >=22.12.0 - jiti: ">=1.21.0" - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: ">=0.54.8" - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - "@types/node": - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - w3c-keyname@2.2.8: - resolution: - { - integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==, - } - - wavesurfer.js@7.12.1: - resolution: - { - integrity: sha512-NswPjVHxk0Q1F/VMRemCPUzSojjuHHisQrBqQiRXg7MVbe3f5vQ6r0rTTXA/a/neC/4hnOEC4YpXca4LpH0SUg==, - } - - wcwidth@1.0.1: - resolution: - { - integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==, - } - - web-worker@1.2.0: - resolution: - { - integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==, - } - - webidl-conversions@3.0.1: - resolution: - { - integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, - } - - webidl-conversions@4.0.2: - resolution: - { - integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==, - } - - whatwg-url@5.0.0: - resolution: - { - integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, - } - - whatwg-url@7.1.0: - resolution: - { - integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==, - } - - which-boxed-primitive@1.1.1: - resolution: - { - integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==, - } - engines: { node: ">= 0.4" } - - which-builtin-type@1.2.1: - resolution: - { - integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==, - } - engines: { node: ">= 0.4" } - - which-collection@1.0.2: - resolution: - { - integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==, - } - engines: { node: ">= 0.4" } - - which-module@2.0.1: - resolution: - { - integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==, - } - - which-typed-array@1.1.20: - resolution: - { - integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==, - } - engines: { node: ">= 0.4" } - - which@1.3.1: - resolution: - { - integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==, - } - hasBin: true - - which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: ">= 8" } - hasBin: true - - word-wrap@1.2.5: - resolution: - { - integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, - } - engines: { node: ">=0.10.0" } - - wordwrap@1.0.0: - resolution: - { - integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==, - } - - workbox-background-sync@7.4.0: - resolution: - { - integrity: sha512-8CB9OxKAgKZKyNMwfGZ1XESx89GryWTfI+V5yEj8sHjFH8MFelUwYXEyldEK6M6oKMmn807GoJFUEA1sC4XS9w==, - } - - workbox-broadcast-update@7.4.0: - resolution: - { - integrity: sha512-+eZQwoktlvo62cI0b+QBr40v5XjighxPq3Fzo9AWMiAosmpG5gxRHgTbGGhaJv/q/MFVxwFNGh/UwHZ/8K88lA==, - } - - workbox-build@7.4.0: - resolution: - { - integrity: sha512-Ntk1pWb0caOFIvwz/hfgrov/OJ45wPEhI5PbTywQcYjyZiVhT3UrwwUPl6TRYbTm4moaFYithYnl1lvZ8UjxcA==, - } - engines: { node: ">=20.0.0" } - - workbox-cacheable-response@7.4.0: - resolution: - { - integrity: sha512-0Fb8795zg/x23ISFkAc7lbWes6vbw34DGFIMw31cwuHPgDEC/5EYm6m/ZkylLX0EnEbbOyOCLjKgFS/Z5g0HeQ==, - } - - workbox-core@7.4.0: - resolution: - { - integrity: sha512-6BMfd8tYEnN4baG4emG9U0hdXM4gGuDU3ectXuVHnj71vwxTFI7WOpQJC4siTOlVtGqCUtj0ZQNsrvi6kZZTAQ==, - } - - workbox-expiration@7.4.0: - resolution: - { - integrity: sha512-V50p4BxYhtA80eOvulu8xVfPBgZbkxJ1Jr8UUn0rvqjGhLDqKNtfrDfjJKnLz2U8fO2xGQJTx/SKXNTzHOjnHw==, - } - - workbox-google-analytics@7.4.0: - resolution: - { - integrity: sha512-MVPXQslRF6YHkzGoFw1A4GIB8GrKym/A5+jYDUSL+AeJw4ytQGrozYdiZqUW1TPQHW8isBCBtyFJergUXyNoWQ==, - } - - workbox-navigation-preload@7.4.0: - resolution: - { - integrity: sha512-etzftSgdQfjMcfPgbfaZCfM2QuR1P+4o8uCA2s4rf3chtKTq/Om7g/qvEOcZkG6v7JZOSOxVYQiOu6PbAZgU6w==, - } - - workbox-precaching@7.4.0: - resolution: - { - integrity: sha512-VQs37T6jDqf1rTxUJZXRl3yjZMf5JX/vDPhmx2CPgDDKXATzEoqyRqhYnRoxl6Kr0rqaQlp32i9rtG5zTzIlNg==, - } - - workbox-range-requests@7.4.0: - resolution: - { - integrity: sha512-3Vq854ZNuP6Y0KZOQWLaLC9FfM7ZaE+iuQl4VhADXybwzr4z/sMmnLgTeUZLq5PaDlcJBxYXQ3U91V7dwAIfvw==, - } - - workbox-recipes@7.4.0: - resolution: - { - integrity: sha512-kOkWvsAn4H8GvAkwfJTbwINdv4voFoiE9hbezgB1sb/0NLyTG4rE7l6LvS8lLk5QIRIto+DjXLuAuG3Vmt3cxQ==, - } - - workbox-routing@7.4.0: - resolution: - { - integrity: sha512-C/ooj5uBWYAhAqwmU8HYQJdOjjDKBp9MzTQ+otpMmd+q0eF59K+NuXUek34wbL0RFrIXe/KKT+tUWcZcBqxbHQ==, - } - - workbox-strategies@7.4.0: - resolution: - { - integrity: sha512-T4hVqIi5A4mHi92+5EppMX3cLaVywDp8nsyUgJhOZxcfSV/eQofcOA6/EMo5rnTNmNTpw0rUgjAI6LaVullPpg==, - } - - workbox-streams@7.4.0: - resolution: - { - integrity: sha512-QHPBQrey7hQbnTs5GrEVoWz7RhHJXnPT+12qqWM378orDMo5VMJLCkCM1cnCk+8Eq92lccx/VgRZ7WAzZWbSLg==, - } - - workbox-sw@7.4.0: - resolution: - { - integrity: sha512-ltU+Kr3qWR6BtbdlMnCjobZKzeV1hN+S6UvDywBrwM19TTyqA03X66dzw1tEIdJvQ4lYKkBFox6IAEhoSEZ8Xw==, - } - - workbox-window@7.4.0: - resolution: - { - integrity: sha512-/bIYdBLAVsNR3v7gYGaV4pQW3M3kEPx5E8vDxGvxo6khTrGtSSCS7QiFKv9ogzBgZiy0OXLP9zO28U/1nF1mfw==, - } - - wrap-ansi@6.2.0: - resolution: - { - integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==, - } - engines: { node: ">=8" } - - wrap-ansi@7.0.0: - resolution: - { - integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, - } - engines: { node: ">=10" } - - wrap-ansi@9.0.2: - resolution: - { - integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==, - } - engines: { node: ">=18" } - - wrappy@1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } - - write-file-atomic@7.0.0: - resolution: - { - integrity: sha512-YnlPC6JqnZl6aO4uRc+dx5PHguiR9S6WeoLtpxNT9wIG+BDya7ZNE1q7KOjVgaA73hKhKLpVPgJ5QA9THQ5BRg==, - } - engines: { node: ^20.17.0 || >=22.9.0 } - - wsl-utils@0.1.0: - resolution: - { - integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==, - } - engines: { node: ">=18" } - - xml-formatter@3.6.7: - resolution: - { - integrity: sha512-IsfFYJQuoDqtUlKhm4EzeoBOb+fQwzQVeyxxAQ0sThn/nFnQmyLPTplqq4yRhaOENH/tAyujD2TBfIYzUKB6hg==, - } - engines: { node: ">= 16" } - - xml-parser-xo@4.1.5: - resolution: - { - integrity: sha512-TxyRxk9sTOUg3glxSIY6f0nfuqRll2OEF8TspLgh5mZkLuBgheCn3zClcDSGJ58TvNmiwyCCuat4UajPud/5Og==, - } - engines: { node: ">= 16" } - - xmldoc@2.0.3: - resolution: - { - integrity: sha512-6gRk4NY/Jvg67xn7OzJuxLRsGgiXBaPUQplVJ/9l99uIugxh4FTOewYz5ic8WScj7Xx/2WvhENiQKwkK9RpE4w==, - } - engines: { node: ">=12.0.0" } - - xtend@4.0.2: - resolution: - { - integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, - } - engines: { node: ">=0.4" } - - y18n@4.0.3: - resolution: - { - integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==, - } - - y18n@5.0.8: - resolution: - { - integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, - } - engines: { node: ">=10" } - - yallist@3.1.1: - resolution: - { - integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==, - } - - yaml@2.8.2: - resolution: - { - integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==, - } - engines: { node: ">= 14.6" } - hasBin: true - - yargs-parser@18.1.3: - resolution: - { - integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==, - } - engines: { node: ">=6" } - - yargs-parser@20.2.9: - resolution: - { - integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==, - } - engines: { node: ">=10" } - - yargs-parser@21.1.1: - resolution: - { - integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, - } - engines: { node: ">=12" } - - yargs-parser@22.0.0: - resolution: - { - integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==, - } - engines: { node: ^20.19.0 || ^22.12.0 || >=23 } - - yargs@15.4.1: - resolution: - { - integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==, - } - engines: { node: ">=8" } - - yargs@16.2.0: - resolution: - { - integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==, - } - engines: { node: ">=10" } - - yargs@17.7.2: - resolution: - { - integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==, - } - engines: { node: ">=12" } - - yargs@18.0.0: - resolution: - { - integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==, - } - engines: { node: ^20.19.0 || ^22.12.0 || >=23 } - - yocto-queue@0.1.0: - resolution: - { - integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, - } - engines: { node: ">=10" } - - yoctocolors@2.1.2: - resolution: - { - integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==, - } - engines: { node: ">=18" } - - zod@4.3.6: - resolution: - { - integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==, - } - -snapshots: - "@actions/core@3.0.0": - dependencies: - "@actions/exec": 3.0.0 - "@actions/http-client": 4.0.0 - - "@actions/exec@3.0.0": - dependencies: - "@actions/io": 3.0.2 - - "@actions/http-client@4.0.0": - dependencies: - tunnel: 0.0.6 - undici: 6.23.0 - - "@actions/io@3.0.2": {} - - "@alloc/quick-lru@5.2.0": {} - - "@amcharts/amcharts4-geodata@4.1.31": {} - - "@amcharts/amcharts4@4.10.40": - dependencies: - "@babel/runtime": 7.28.6 - core-js: 3.48.0 - d3-force: 3.0.0 - d3-geo: 3.1.1 - d3-geo-projection: 4.0.0 - d3-selection: 3.0.0 - d3-transition: 3.0.1(d3-selection@3.0.0) - pdfmake: 0.2.23 - polylabel: 1.1.0 - raf: 3.4.1 - regression: 2.0.1 - rgbcolor: 1.0.1 - stackblur-canvas: 2.7.0 - tslib: 2.8.1 - - "@apideck/better-ajv-errors@0.3.6(ajv@8.18.0)": - dependencies: - ajv: 8.18.0 - json-schema: 0.4.0 - jsonpointer: 5.0.1 - leven: 3.1.0 - - "@babel/code-frame@7.29.0": - dependencies: - "@babel/helper-validator-identifier": 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - "@babel/compat-data@7.29.0": {} - - "@babel/core@7.29.0": - dependencies: - "@babel/code-frame": 7.29.0 - "@babel/generator": 7.29.1 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helpers": 7.28.6 - "@babel/parser": 7.29.0 - "@babel/template": 7.28.6 - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 - "@jridgewell/remapping": 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - "@babel/generator@7.29.1": - dependencies: - "@babel/parser": 7.29.0 - "@babel/types": 7.29.0 - "@jridgewell/gen-mapping": 0.3.13 - "@jridgewell/trace-mapping": 0.3.31 - jsesc: 3.1.0 - - "@babel/helper-annotate-as-pure@7.27.3": - dependencies: - "@babel/types": 7.29.0 - - "@babel/helper-compilation-targets@7.28.6": - dependencies: - "@babel/compat-data": 7.29.0 - "@babel/helper-validator-option": 7.27.1 - browserslist: 4.28.1 - lru-cache: 5.1.1 - semver: 6.3.1 - - "@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-member-expression-to-functions": 7.28.5 - "@babel/helper-optimise-call-expression": 7.27.1 - "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 - "@babel/traverse": 7.29.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - "@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - regexpu-core: 6.4.0 - semver: 6.3.1 - - "@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - debug: 4.4.3 - lodash.debounce: 4.0.8 - resolve: 1.22.11 - transitivePeerDependencies: - - supports-color - - "@babel/helper-globals@7.28.0": {} - - "@babel/helper-member-expression-to-functions@7.28.5": - dependencies: - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/helper-module-imports@7.28.6": - dependencies: - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-imports": 7.28.6 - "@babel/helper-validator-identifier": 7.28.5 - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/helper-optimise-call-expression@7.27.1": - dependencies: - "@babel/types": 7.29.0 - - "@babel/helper-plugin-utils@7.28.6": {} - - "@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-wrap-function": 7.28.6 - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-member-expression-to-functions": 7.28.5 - "@babel/helper-optimise-call-expression": 7.27.1 - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/helper-skip-transparent-expression-wrappers@7.27.1": - dependencies: - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/helper-string-parser@7.27.1": {} - - "@babel/helper-validator-identifier@7.28.5": {} - - "@babel/helper-validator-option@7.27.1": {} - - "@babel/helper-wrap-function@7.28.6": - dependencies: - "@babel/template": 7.28.6 - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/helpers@7.28.6": - dependencies: - "@babel/template": 7.28.6 - "@babel/types": 7.29.0 - - "@babel/parser@7.29.0": - dependencies: - "@babel/types": 7.29.0 - - "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 - "@babel/plugin-transform-optional-chaining": 7.28.6(@babel/core@7.29.0) - transitivePeerDependencies: - - supports-color - - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - - "@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-remap-async-to-generator": 7.27.1(@babel/core@7.29.0) - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-imports": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-remap-async-to-generator": 7.27.1(@babel/core@7.29.0) - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-globals": 7.28.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/template": 7.28.6 - - "@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-validator-identifier": 7.28.5 - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) - "@babel/plugin-transform-parameters": 7.27.7(@babel/core@7.29.0) - "@babel/traverse": 7.29.0 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 - transitivePeerDependencies: - - supports-color - - "@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - - "@babel/preset-env@7.29.0(@babel/core@7.29.0)": - dependencies: - "@babel/compat-data": 7.29.0 - "@babel/core": 7.29.0 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-validator-option": 7.27.1 - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": 7.28.5(@babel/core@7.29.0) - "@babel/plugin-bugfix-safari-class-field-initializer-scope": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) - "@babel/plugin-syntax-import-assertions": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-syntax-import-attributes": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-syntax-unicode-sets-regex": 7.18.6(@babel/core@7.29.0) - "@babel/plugin-transform-arrow-functions": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-async-generator-functions": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-async-to-generator": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-block-scoped-functions": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-block-scoping": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-class-properties": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-class-static-block": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-classes": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-computed-properties": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) - "@babel/plugin-transform-dotall-regex": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-duplicate-keys": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-dynamic-import": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-explicit-resource-management": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-exponentiation-operator": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-export-namespace-from": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-for-of": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-function-name": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-json-strings": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-literals": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-logical-assignment-operators": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-member-expression-literals": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-modules-amd": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-modules-commonjs": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-modules-systemjs": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-modules-umd": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-named-capturing-groups-regex": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-new-target": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-nullish-coalescing-operator": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-numeric-separator": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-object-rest-spread": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-object-super": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-optional-catch-binding": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-optional-chaining": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-parameters": 7.27.7(@babel/core@7.29.0) - "@babel/plugin-transform-private-methods": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-private-property-in-object": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-property-literals": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-regenerator": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-regexp-modifiers": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-reserved-words": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-shorthand-properties": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-spread": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-sticky-regex": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-template-literals": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-typeof-symbol": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-unicode-escapes": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-unicode-property-regex": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-unicode-regex": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-unicode-sets-regex": 7.28.6(@babel/core@7.29.0) - "@babel/preset-modules": 0.1.6-no-external-plugins(@babel/core@7.29.0) - babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0) - babel-plugin-polyfill-corejs3: 0.14.0(@babel/core@7.29.0) - babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0) - core-js-compat: 3.48.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - "@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/types": 7.29.0 - esutils: 2.0.3 - - "@babel/runtime@7.28.6": {} - - "@babel/template@7.28.6": - dependencies: - "@babel/code-frame": 7.29.0 - "@babel/parser": 7.29.0 - "@babel/types": 7.29.0 - - "@babel/traverse@7.29.0": - dependencies: - "@babel/code-frame": 7.29.0 - "@babel/generator": 7.29.1 - "@babel/helper-globals": 7.28.0 - "@babel/parser": 7.29.0 - "@babel/template": 7.28.6 - "@babel/types": 7.29.0 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - "@babel/types@7.29.0": - dependencies: - "@babel/helper-string-parser": 7.27.1 - "@babel/helper-validator-identifier": 7.28.5 - - "@cacheable/memory@2.0.7": - dependencies: - "@cacheable/utils": 2.3.4 - "@keyv/bigmap": 1.3.1(keyv@5.6.0) - hookified: 1.15.1 - keyv: 5.6.0 - - "@cacheable/utils@2.3.4": - dependencies: - hashery: 1.5.0 - keyv: 5.6.0 - - "@codemirror/autocomplete@6.20.0": - dependencies: - "@codemirror/language": 6.12.1 - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - "@lezer/common": 1.5.1 - - "@codemirror/commands@6.10.2": - dependencies: - "@codemirror/language": 6.12.1 - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - "@lezer/common": 1.5.1 - - "@codemirror/lang-css@6.3.1": - dependencies: - "@codemirror/autocomplete": 6.20.0 - "@codemirror/language": 6.12.1 - "@codemirror/state": 6.5.4 - "@lezer/common": 1.5.1 - "@lezer/css": 1.3.1 - - "@codemirror/lang-html@6.4.11": - dependencies: - "@codemirror/autocomplete": 6.20.0 - "@codemirror/lang-css": 6.3.1 - "@codemirror/lang-javascript": 6.2.4 - "@codemirror/language": 6.12.1 - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - "@lezer/common": 1.5.1 - "@lezer/css": 1.3.1 - "@lezer/html": 1.3.13 - - "@codemirror/lang-javascript@6.2.4": - dependencies: - "@codemirror/autocomplete": 6.20.0 - "@codemirror/language": 6.12.1 - "@codemirror/lint": 6.9.4 - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - "@lezer/common": 1.5.1 - "@lezer/javascript": 1.5.4 - - "@codemirror/lang-xml@6.1.0": - dependencies: - "@codemirror/autocomplete": 6.20.0 - "@codemirror/language": 6.12.1 - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - "@lezer/common": 1.5.1 - "@lezer/xml": 1.0.6 - - "@codemirror/language@6.12.1": - dependencies: - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - "@lezer/common": 1.5.1 - "@lezer/highlight": 1.2.3 - "@lezer/lr": 1.4.8 - style-mod: 4.1.3 - - "@codemirror/lint@6.9.4": - dependencies: - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - crelt: 1.0.6 - - "@codemirror/search@6.6.0": - dependencies: - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - crelt: 1.0.6 - - "@codemirror/state@6.5.4": - dependencies: - "@marijn/find-cluster-break": 1.0.2 - - "@codemirror/view@6.39.14": - dependencies: - "@codemirror/state": 6.5.4 - crelt: 1.0.6 - style-mod: 4.1.3 - w3c-keyname: 2.2.8 - - "@colors/colors@1.5.0": - optional: true - - "@commitlint/cli@20.4.2(@types/node@24.7.0)(typescript@5.9.3)": - dependencies: - "@commitlint/format": 20.4.0 - "@commitlint/lint": 20.4.2 - "@commitlint/load": 20.4.0(@types/node@24.7.0)(typescript@5.9.3) - "@commitlint/read": 20.4.0 - "@commitlint/types": 20.4.0 - tinyexec: 1.0.2 - yargs: 17.7.2 - transitivePeerDependencies: - - "@types/node" - - typescript - - "@commitlint/config-conventional@20.4.2": - dependencies: - "@commitlint/types": 20.4.0 - conventional-changelog-conventionalcommits: 9.1.0 - - "@commitlint/config-validator@20.4.0": - dependencies: - "@commitlint/types": 20.4.0 - ajv: 8.18.0 - - "@commitlint/ensure@20.4.1": - dependencies: - "@commitlint/types": 20.4.0 - lodash.camelcase: 4.3.0 - lodash.kebabcase: 4.1.1 - lodash.snakecase: 4.1.1 - lodash.startcase: 4.4.0 - lodash.upperfirst: 4.3.1 - - "@commitlint/execute-rule@20.0.0": {} - - "@commitlint/format@20.4.0": - dependencies: - "@commitlint/types": 20.4.0 - picocolors: 1.1.1 - - "@commitlint/is-ignored@20.4.1": - dependencies: - "@commitlint/types": 20.4.0 - semver: 7.7.4 - - "@commitlint/lint@20.4.2": - dependencies: - "@commitlint/is-ignored": 20.4.1 - "@commitlint/parse": 20.4.1 - "@commitlint/rules": 20.4.2 - "@commitlint/types": 20.4.0 - - "@commitlint/load@20.4.0(@types/node@24.7.0)(typescript@5.9.3)": - dependencies: - "@commitlint/config-validator": 20.4.0 - "@commitlint/execute-rule": 20.0.0 - "@commitlint/resolve-extends": 20.4.0 - "@commitlint/types": 20.4.0 - cosmiconfig: 9.0.0(typescript@5.9.3) - cosmiconfig-typescript-loader: 6.2.0(@types/node@24.7.0)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3) - is-plain-obj: 4.1.0 - lodash.mergewith: 4.6.2 - picocolors: 1.1.1 - transitivePeerDependencies: - - "@types/node" - - typescript - - "@commitlint/message@20.4.0": {} - - "@commitlint/parse@20.4.1": - dependencies: - "@commitlint/types": 20.4.0 - conventional-changelog-angular: 8.1.0 - conventional-commits-parser: 6.2.1 - - "@commitlint/read@20.4.0": - dependencies: - "@commitlint/top-level": 20.4.0 - "@commitlint/types": 20.4.0 - git-raw-commits: 4.0.0 - minimist: 1.2.8 - tinyexec: 1.0.2 - - "@commitlint/resolve-extends@20.4.0": - dependencies: - "@commitlint/config-validator": 20.4.0 - "@commitlint/types": 20.4.0 - global-directory: 4.0.1 - import-meta-resolve: 4.2.0 - lodash.mergewith: 4.6.2 - resolve-from: 5.0.0 - - "@commitlint/rules@20.4.2": - dependencies: - "@commitlint/ensure": 20.4.1 - "@commitlint/message": 20.4.0 - "@commitlint/to-lines": 20.0.0 - "@commitlint/types": 20.4.0 - - "@commitlint/to-lines@20.0.0": {} - - "@commitlint/top-level@20.4.0": - dependencies: - escalade: 3.2.0 - - "@commitlint/types@20.4.0": - dependencies: - conventional-commits-parser: 6.2.1 - picocolors: 1.1.1 - - "@csstools/cascade-layer-name-parser@3.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - - "@csstools/color-helpers@6.0.1": {} - - "@csstools/css-calc@3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - - "@csstools/css-color-parser@4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)": - dependencies: - "@csstools/color-helpers": 6.0.1 - "@csstools/css-calc": 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - - "@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)": - dependencies: - "@csstools/css-tokenizer": 4.0.0 - - "@csstools/css-syntax-patches-for-csstree@1.0.27": {} - - "@csstools/css-tokenizer@4.0.0": {} - - "@csstools/media-query-list-parser@5.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - - "@csstools/postcss-alpha-function@2.0.2(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-cascade-layers@6.0.0(postcss@8.5.6)": - dependencies: - "@csstools/selector-specificity": 6.0.0(postcss-selector-parser@7.1.1) - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - "@csstools/postcss-color-function-display-p3-linear@2.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-color-function@5.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-color-mix-function@4.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-color-mix-variadic-function-arguments@2.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-content-alt-text@3.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-contrast-color-function@3.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-exponential-functions@3.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-calc": 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-font-format-keywords@5.0.0(postcss@8.5.6)": - dependencies: - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - "@csstools/postcss-gamut-mapping@3.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-gradients-interpolation-method@6.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-hwb-function@5.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-ic-unit@5.0.0(postcss@8.5.6)": - dependencies: - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - "@csstools/postcss-initial@3.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - - "@csstools/postcss-is-pseudo-class@6.0.0(postcss@8.5.6)": - dependencies: - "@csstools/selector-specificity": 6.0.0(postcss-selector-parser@7.1.1) - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - "@csstools/postcss-light-dark-function@3.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-logical-float-and-clear@4.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - - "@csstools/postcss-logical-overflow@3.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - - "@csstools/postcss-logical-overscroll-behavior@3.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - - "@csstools/postcss-logical-resize@4.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - "@csstools/postcss-logical-viewport-units@4.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-tokenizer": 4.0.0 - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-media-minmax@3.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-calc": 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/media-query-list-parser": 5.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - postcss: 8.5.6 - - "@csstools/postcss-media-queries-aspect-ratio-number-values@4.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/media-query-list-parser": 5.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - postcss: 8.5.6 - - "@csstools/postcss-mixins@1.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-nested-calc@5.0.0(postcss@8.5.6)": - dependencies: - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - "@csstools/postcss-normalize-display-values@5.0.1(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - "@csstools/postcss-oklab-function@5.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-position-area-property@2.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - - "@csstools/postcss-progressive-custom-properties@5.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - "@csstools/postcss-property-rule-prelude-list@2.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-random-function@3.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-calc": 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-relative-color-syntax@4.0.1(postcss@8.5.6)": - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - "@csstools/postcss-scope-pseudo-class@5.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - "@csstools/postcss-sign-functions@2.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-calc": 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-stepped-value-functions@5.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-calc": 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-syntax-descriptor-syntax-production@2.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-system-ui-font-family@2.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-text-decoration-shorthand@5.0.2(postcss@8.5.6)": - dependencies: - "@csstools/color-helpers": 6.0.1 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - "@csstools/postcss-trigonometric-functions@5.0.0(postcss@8.5.6)": - dependencies: - "@csstools/css-calc": 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - - "@csstools/postcss-unset-value@5.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - - "@csstools/selector-resolve-nested@4.0.0(postcss-selector-parser@7.1.1)": - dependencies: - postcss-selector-parser: 7.1.1 - - "@csstools/selector-specificity@6.0.0(postcss-selector-parser@7.1.1)": - dependencies: - postcss-selector-parser: 7.1.1 - - "@csstools/utilities@3.0.0(postcss@8.5.6)": - dependencies: - postcss: 8.5.6 - - "@emnapi/runtime@1.8.1": - dependencies: - tslib: 2.8.1 - optional: true - - "@epic-web/invariant@1.0.0": {} - - "@esbuild/aix-ppc64@0.27.3": - optional: true - - "@esbuild/android-arm64@0.27.3": - optional: true - - "@esbuild/android-arm@0.27.3": - optional: true - - "@esbuild/android-x64@0.27.3": - optional: true - - "@esbuild/darwin-arm64@0.27.3": - optional: true - - "@esbuild/darwin-x64@0.27.3": - optional: true - - "@esbuild/freebsd-arm64@0.27.3": - optional: true - - "@esbuild/freebsd-x64@0.27.3": - optional: true - - "@esbuild/linux-arm64@0.27.3": - optional: true - - "@esbuild/linux-arm@0.27.3": - optional: true - - "@esbuild/linux-ia32@0.27.3": - optional: true - - "@esbuild/linux-loong64@0.27.3": - optional: true - - "@esbuild/linux-mips64el@0.27.3": - optional: true - - "@esbuild/linux-ppc64@0.27.3": - optional: true - - "@esbuild/linux-riscv64@0.27.3": - optional: true - - "@esbuild/linux-s390x@0.27.3": - optional: true - - "@esbuild/linux-x64@0.27.3": - optional: true - - "@esbuild/netbsd-arm64@0.27.3": - optional: true - - "@esbuild/netbsd-x64@0.27.3": - optional: true - - "@esbuild/openbsd-arm64@0.27.3": - optional: true - - "@esbuild/openbsd-x64@0.27.3": - optional: true - - "@esbuild/openharmony-arm64@0.27.3": - optional: true - - "@esbuild/sunos-x64@0.27.3": - optional: true - - "@esbuild/win32-arm64@0.27.3": - optional: true - - "@esbuild/win32-ia32@0.27.3": - optional: true - - "@esbuild/win32-x64@0.27.3": - optional: true - - "@eslint-community/eslint-utils@4.9.1(eslint@10.0.0(jiti@1.21.7))": - dependencies: - eslint: 10.0.0(jiti@1.21.7) - eslint-visitor-keys: 3.4.3 - - "@eslint-community/regexpp@4.12.2": {} - - "@eslint/config-array@0.23.1": - dependencies: - "@eslint/object-schema": 3.0.1 - debug: 4.4.3 - minimatch: 10.2.1 - transitivePeerDependencies: - - supports-color - - "@eslint/config-helpers@0.5.2": - dependencies: - "@eslint/core": 1.1.0 - - "@eslint/core@1.1.0": - dependencies: - "@types/json-schema": 7.0.15 - - "@eslint/eslintrc@3.3.3": - dependencies: - ajv: 6.12.6 - debug: 4.4.3 - espree: 10.4.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - "@eslint/js@10.0.1(eslint@10.0.0(jiti@1.21.7))": - optionalDependencies: - eslint: 10.0.0(jiti@1.21.7) - - "@eslint/object-schema@3.0.1": {} - - "@eslint/plugin-kit@0.6.0": - dependencies: - "@eslint/core": 1.1.0 - levn: 0.4.1 - - "@floating-ui/core@1.7.4": - dependencies: - "@floating-ui/utils": 0.2.10 - - "@floating-ui/dom@1.7.5": - dependencies: - "@floating-ui/core": 1.7.4 - "@floating-ui/utils": 0.2.10 - - "@floating-ui/utils@0.2.10": {} - - "@foliojs-fork/fontkit@1.9.2": - dependencies: - "@foliojs-fork/restructure": 2.0.2 - brotli: 1.3.3 - clone: 1.0.4 - deep-equal: 1.1.2 - dfa: 1.2.0 - tiny-inflate: 1.0.3 - unicode-properties: 1.4.1 - unicode-trie: 2.0.0 - - "@foliojs-fork/linebreak@1.1.2": - dependencies: - base64-js: 1.3.1 - unicode-trie: 2.0.0 - - "@foliojs-fork/pdfkit@0.15.3": - dependencies: - "@foliojs-fork/fontkit": 1.9.2 - "@foliojs-fork/linebreak": 1.1.2 - crypto-js: 4.2.0 - jpeg-exif: 1.1.4 - png-js: 1.0.0 - - "@foliojs-fork/restructure@2.0.2": {} - - "@github/clipboard-copy-element@1.3.0": {} - - "@github/hotkey@3.1.1": {} - - "@github/markdown-toolbar-element@2.2.3": {} - - "@github/relative-time-element@5.0.0": {} - - "@humanfs/core@0.19.1": {} - - "@humanfs/node@0.16.7": - dependencies: - "@humanfs/core": 0.19.1 - "@humanwhocodes/retry": 0.4.3 - - "@humanwhocodes/module-importer@1.0.1": {} - - "@humanwhocodes/retry@0.4.3": {} - - "@img/colour@1.0.0": {} - - "@img/sharp-darwin-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-darwin-arm64": 1.2.4 - optional: true - - "@img/sharp-darwin-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-darwin-x64": 1.2.4 - optional: true - - "@img/sharp-libvips-darwin-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-darwin-x64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-arm@1.2.4": - optional: true - - "@img/sharp-libvips-linux-ppc64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-riscv64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-s390x@1.2.4": - optional: true - - "@img/sharp-libvips-linux-x64@1.2.4": - optional: true - - "@img/sharp-libvips-linuxmusl-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-linuxmusl-x64@1.2.4": - optional: true - - "@img/sharp-linux-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-arm64": 1.2.4 - optional: true - - "@img/sharp-linux-arm@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-arm": 1.2.4 - optional: true - - "@img/sharp-linux-ppc64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-ppc64": 1.2.4 - optional: true - - "@img/sharp-linux-riscv64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-riscv64": 1.2.4 - optional: true - - "@img/sharp-linux-s390x@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-s390x": 1.2.4 - optional: true - - "@img/sharp-linux-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-x64": 1.2.4 - optional: true - - "@img/sharp-linuxmusl-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linuxmusl-arm64": 1.2.4 - optional: true - - "@img/sharp-linuxmusl-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linuxmusl-x64": 1.2.4 - optional: true - - "@img/sharp-wasm32@0.34.5": - dependencies: - "@emnapi/runtime": 1.8.1 - optional: true - - "@img/sharp-win32-arm64@0.34.5": - optional: true - - "@img/sharp-win32-ia32@0.34.5": - optional: true - - "@img/sharp-win32-x64@0.34.5": - optional: true - - "@isaacs/cliui@9.0.0": {} - - "@jridgewell/gen-mapping@0.3.13": - dependencies: - "@jridgewell/sourcemap-codec": 1.5.5 - "@jridgewell/trace-mapping": 0.3.31 - - "@jridgewell/remapping@2.3.5": - dependencies: - "@jridgewell/gen-mapping": 0.3.13 - "@jridgewell/trace-mapping": 0.3.31 - - "@jridgewell/resolve-uri@3.1.2": {} - - "@jridgewell/source-map@0.3.11": - dependencies: - "@jridgewell/gen-mapping": 0.3.13 - "@jridgewell/trace-mapping": 0.3.31 - - "@jridgewell/sourcemap-codec@1.5.5": {} - - "@jridgewell/trace-mapping@0.3.31": - dependencies: - "@jridgewell/resolve-uri": 3.1.2 - "@jridgewell/sourcemap-codec": 1.5.5 - - "@keyv/bigmap@1.3.1(keyv@5.6.0)": - dependencies: - hashery: 1.5.0 - hookified: 1.15.1 - keyv: 5.6.0 - - "@keyv/serialize@1.1.1": {} - - "@lezer/common@1.5.1": {} - - "@lezer/css@1.3.1": - dependencies: - "@lezer/common": 1.5.1 - "@lezer/highlight": 1.2.3 - "@lezer/lr": 1.4.8 - - "@lezer/highlight@1.2.3": - dependencies: - "@lezer/common": 1.5.1 - - "@lezer/html@1.3.13": - dependencies: - "@lezer/common": 1.5.1 - "@lezer/highlight": 1.2.3 - "@lezer/lr": 1.4.8 - - "@lezer/javascript@1.5.4": - dependencies: - "@lezer/common": 1.5.1 - "@lezer/highlight": 1.2.3 - "@lezer/lr": 1.4.8 - - "@lezer/lr@1.4.8": - dependencies: - "@lezer/common": 1.5.1 - - "@lezer/xml@1.0.6": - dependencies: - "@lezer/common": 1.5.1 - "@lezer/highlight": 1.2.3 - "@lezer/lr": 1.4.8 - - "@lit-labs/ssr-dom-shim@1.5.1": {} - - "@lit/context@1.1.6": - dependencies: - "@lit/reactive-element": 2.1.2 - - "@lit/reactive-element@2.1.2": - dependencies: - "@lit-labs/ssr-dom-shim": 1.5.1 - - "@marijn/find-cluster-break@1.0.2": {} - - "@nodelib/fs.scandir@2.1.5": - dependencies: - "@nodelib/fs.stat": 2.0.5 - run-parallel: 1.2.0 - - "@nodelib/fs.stat@2.0.5": {} - - "@nodelib/fs.walk@1.2.8": - dependencies: - "@nodelib/fs.scandir": 2.1.5 - fastq: 1.20.1 - - "@octokit/auth-token@6.0.0": {} - - "@octokit/core@7.0.6": - dependencies: - "@octokit/auth-token": 6.0.0 - "@octokit/graphql": 9.0.3 - "@octokit/request": 10.0.7 - "@octokit/request-error": 7.1.0 - "@octokit/types": 16.0.0 - before-after-hook: 4.0.0 - universal-user-agent: 7.0.3 - - "@octokit/endpoint@11.0.3": - dependencies: - "@octokit/types": 16.0.0 - universal-user-agent: 7.0.3 - - "@octokit/graphql@9.0.3": - dependencies: - "@octokit/request": 10.0.7 - "@octokit/types": 16.0.0 - universal-user-agent: 7.0.3 - - "@octokit/openapi-types@27.0.0": {} - - "@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.6)": - dependencies: - "@octokit/core": 7.0.6 - "@octokit/types": 16.0.0 - - "@octokit/plugin-retry@8.1.0(@octokit/core@7.0.6)": - dependencies: - "@octokit/core": 7.0.6 - "@octokit/request-error": 7.1.0 - "@octokit/types": 16.0.0 - bottleneck: 2.19.5 - - "@octokit/plugin-throttling@11.0.3(@octokit/core@7.0.6)": - dependencies: - "@octokit/core": 7.0.6 - "@octokit/types": 16.0.0 - bottleneck: 2.19.5 - - "@octokit/request-error@7.1.0": - dependencies: - "@octokit/types": 16.0.0 - - "@octokit/request@10.0.7": - dependencies: - "@octokit/endpoint": 11.0.3 - "@octokit/request-error": 7.1.0 - "@octokit/types": 16.0.0 - fast-content-type-parse: 3.0.0 - universal-user-agent: 7.0.3 - - "@octokit/types@16.0.0": - dependencies: - "@octokit/openapi-types": 27.0.0 - - "@patternfly/elements@4.3.1": - dependencies: - "@lit/context": 1.1.6 - "@patternfly/icons": 1.0.3 - "@patternfly/pfe-core": 5.0.6 - lit: 3.3.2 - tslib: 2.8.1 - - "@patternfly/icons@1.0.3": {} - - "@patternfly/pfe-core@5.0.6": - dependencies: - "@lit/context": 1.1.6 - lit: 3.3.2 - - "@pkgr/core@0.2.9": {} - - "@pnpm/config.env-replace@1.1.0": {} - - "@pnpm/network.ca-file@1.0.2": - dependencies: - graceful-fs: 4.2.10 - - "@pnpm/npm-conf@3.0.2": - dependencies: - "@pnpm/config.env-replace": 1.1.0 - "@pnpm/network.ca-file": 1.0.2 - config-chain: 1.1.13 - - "@polka/url@1.0.0-next.29": {} - - "@rollup/plugin-babel@5.3.1(@babel/core@7.29.0)(rollup@2.79.2)": - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-imports": 7.28.6 - "@rollup/pluginutils": 3.1.0(rollup@2.79.2) - rollup: 2.79.2 - transitivePeerDependencies: - - supports-color - - "@rollup/plugin-node-resolve@15.3.1(rollup@2.79.2)": - dependencies: - "@rollup/pluginutils": 5.3.0(rollup@2.79.2) - "@types/resolve": 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.11 - optionalDependencies: - rollup: 2.79.2 - - "@rollup/plugin-replace@2.4.2(rollup@2.79.2)": - dependencies: - "@rollup/pluginutils": 3.1.0(rollup@2.79.2) - magic-string: 0.25.9 - rollup: 2.79.2 - - "@rollup/plugin-terser@0.4.4(rollup@2.79.2)": - dependencies: - serialize-javascript: 6.0.2 - smob: 1.6.1 - terser: 5.46.0 - optionalDependencies: - rollup: 2.79.2 - - "@rollup/pluginutils@3.1.0(rollup@2.79.2)": - dependencies: - "@types/estree": 0.0.39 - estree-walker: 1.0.1 - picomatch: 2.3.1 - rollup: 2.79.2 - - "@rollup/pluginutils@5.3.0(rollup@2.79.2)": - dependencies: - "@types/estree": 1.0.8 - estree-walker: 2.0.2 - picomatch: 4.0.3 - optionalDependencies: - rollup: 2.79.2 - - "@rollup/rollup-android-arm-eabi@4.57.1": - optional: true - - "@rollup/rollup-android-arm64@4.57.1": - optional: true - - "@rollup/rollup-darwin-arm64@4.57.1": - optional: true - - "@rollup/rollup-darwin-x64@4.57.1": - optional: true - - "@rollup/rollup-freebsd-arm64@4.57.1": - optional: true - - "@rollup/rollup-freebsd-x64@4.57.1": - optional: true - - "@rollup/rollup-linux-arm-gnueabihf@4.57.1": - optional: true - - "@rollup/rollup-linux-arm-musleabihf@4.57.1": - optional: true - - "@rollup/rollup-linux-arm64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-arm64-musl@4.57.1": - optional: true - - "@rollup/rollup-linux-loong64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-loong64-musl@4.57.1": - optional: true - - "@rollup/rollup-linux-ppc64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-ppc64-musl@4.57.1": - optional: true - - "@rollup/rollup-linux-riscv64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-riscv64-musl@4.57.1": - optional: true - - "@rollup/rollup-linux-s390x-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-x64-gnu@4.57.1": - optional: true - - "@rollup/rollup-linux-x64-musl@4.57.1": - optional: true - - "@rollup/rollup-openbsd-x64@4.57.1": - optional: true - - "@rollup/rollup-openharmony-arm64@4.57.1": - optional: true - - "@rollup/rollup-win32-arm64-msvc@4.57.1": - optional: true - - "@rollup/rollup-win32-ia32-msvc@4.57.1": - optional: true - - "@rollup/rollup-win32-x64-gnu@4.57.1": - optional: true - - "@rollup/rollup-win32-x64-msvc@4.57.1": - optional: true - - "@sec-ant/readable-stream@0.4.1": {} - - "@semantic-release/changelog@6.0.3(semantic-release@25.0.3(typescript@5.9.3))": - dependencies: - "@semantic-release/error": 3.0.0 - aggregate-error: 3.1.0 - fs-extra: 11.3.3 - lodash: 4.17.23 - semantic-release: 25.0.3(typescript@5.9.3) - - "@semantic-release/commit-analyzer@13.0.1(semantic-release@25.0.3(typescript@5.9.3))": - dependencies: - conventional-changelog-angular: 8.1.0 - conventional-changelog-writer: 8.2.0 - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.2.1 - debug: 4.4.3 - import-from-esm: 2.0.0 - lodash-es: 4.17.23 - micromatch: 4.0.8 - semantic-release: 25.0.3(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - - "@semantic-release/error@3.0.0": {} - - "@semantic-release/error@4.0.0": {} - - "@semantic-release/exec@7.1.0(semantic-release@25.0.3(typescript@5.9.3))": - dependencies: - "@semantic-release/error": 4.0.0 - aggregate-error: 3.1.0 - debug: 4.4.3 - execa: 9.6.1 - lodash-es: 4.17.23 - parse-json: 8.3.0 - semantic-release: 25.0.3(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - - "@semantic-release/git@10.0.1(semantic-release@25.0.3(typescript@5.9.3))": - dependencies: - "@semantic-release/error": 3.0.0 - aggregate-error: 3.1.0 - debug: 4.4.3 - dir-glob: 3.0.1 - execa: 5.1.1 - lodash: 4.17.23 - micromatch: 4.0.8 - p-reduce: 2.1.0 - semantic-release: 25.0.3(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - - "@semantic-release/github@12.0.6(semantic-release@25.0.3(typescript@5.9.3))": - dependencies: - "@octokit/core": 7.0.6 - "@octokit/plugin-paginate-rest": 14.0.0(@octokit/core@7.0.6) - "@octokit/plugin-retry": 8.1.0(@octokit/core@7.0.6) - "@octokit/plugin-throttling": 11.0.3(@octokit/core@7.0.6) - "@semantic-release/error": 4.0.0 - aggregate-error: 5.0.0 - debug: 4.4.3 - dir-glob: 3.0.1 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - issue-parser: 7.0.1 - lodash-es: 4.17.23 - mime: 4.1.0 - p-filter: 4.1.0 - semantic-release: 25.0.3(typescript@5.9.3) - tinyglobby: 0.2.15 - undici: 7.22.0 - url-join: 5.0.0 - transitivePeerDependencies: - - supports-color - - "@semantic-release/gitlab@13.3.0(semantic-release@25.0.3(typescript@5.9.3))": - dependencies: - "@semantic-release/error": 4.0.0 - aggregate-error: 5.0.0 - debug: 4.4.3 - dir-glob: 3.0.1 - escape-string-regexp: 5.0.0 - formdata-node: 6.0.3 - fs-extra: 11.3.3 - globby: 14.1.0 - got: 14.6.6 - hpagent: 1.2.0 - lodash-es: 4.17.23 - parse-url: 10.0.3 - semantic-release: 25.0.3(typescript@5.9.3) - url-join: 4.0.1 - transitivePeerDependencies: - - supports-color - - "@semantic-release/npm@13.1.4(semantic-release@25.0.3(typescript@5.9.3))": - dependencies: - "@actions/core": 3.0.0 - "@semantic-release/error": 4.0.0 - aggregate-error: 5.0.0 - env-ci: 11.2.0 - execa: 9.6.1 - fs-extra: 11.3.3 - lodash-es: 4.17.23 - nerf-dart: 1.0.0 - normalize-url: 8.1.1 - npm: 11.10.0 - rc: 1.2.8 - read-pkg: 10.1.0 - registry-auth-token: 5.1.1 - semantic-release: 25.0.3(typescript@5.9.3) - semver: 7.7.4 - tempy: 3.2.0 - - "@semantic-release/release-notes-generator@14.1.0(semantic-release@25.0.3(typescript@5.9.3))": - dependencies: - conventional-changelog-angular: 8.1.0 - conventional-changelog-writer: 8.2.0 - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.2.1 - debug: 4.4.3 - get-stream: 7.0.1 - import-from-esm: 2.0.0 - into-stream: 7.0.0 - lodash-es: 4.17.23 - read-package-up: 11.0.0 - semantic-release: 25.0.3(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - - "@sindresorhus/is@4.6.0": {} - - "@sindresorhus/is@7.2.0": {} - - "@sindresorhus/merge-streams@2.3.0": {} - - "@sindresorhus/merge-streams@4.0.0": {} - - "@stencil/core@2.5.2": {} - - "@surma/rollup-plugin-off-main-thread@2.2.3": - dependencies: - ejs: 3.1.10 - json5: 2.2.3 - magic-string: 0.25.9 - string.prototype.matchall: 4.0.12 - - "@tailwindcss/forms@0.5.11(tailwindcss@3.4.19(yaml@2.8.2))": - dependencies: - mini-svg-data-uri: 1.4.4 - tailwindcss: 3.4.19(yaml@2.8.2) - - "@tailwindcss/typography@0.5.19(tailwindcss@3.4.19(yaml@2.8.2))": - dependencies: - postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.19(yaml@2.8.2) - - "@types/eslint@9.6.1": - dependencies: - "@types/estree": 1.0.8 - "@types/json-schema": 7.0.15 - optional: true - - "@types/esrecurse@4.3.1": {} - - "@types/estree@0.0.39": {} - - "@types/estree@1.0.8": {} - - "@types/fscreen@1.0.4": {} - - "@types/geojson@7946.0.16": {} - - "@types/http-cache-semantics@4.2.0": {} - - "@types/json-schema@7.0.15": {} - - "@types/leaflet@1.9.21": - dependencies: - "@types/geojson": 7946.0.16 - - "@types/node@24.7.0": - dependencies: - undici-types: 7.14.0 - - "@types/normalize-package-data@2.4.4": {} - - "@types/resolve@1.20.2": {} - - "@types/trusted-types@2.0.7": {} - - "@typescript-eslint/eslint-plugin@8.56.0(@typescript-eslint/parser@8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3))(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3)": - dependencies: - "@eslint-community/regexpp": 4.12.2 - "@typescript-eslint/parser": 8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3) - "@typescript-eslint/scope-manager": 8.56.0 - "@typescript-eslint/type-utils": 8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3) - "@typescript-eslint/utils": 8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3) - "@typescript-eslint/visitor-keys": 8.56.0 - eslint: 10.0.0(jiti@1.21.7) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/parser@8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3)": - dependencies: - "@typescript-eslint/scope-manager": 8.56.0 - "@typescript-eslint/types": 8.56.0 - "@typescript-eslint/typescript-estree": 8.56.0(typescript@5.9.3) - "@typescript-eslint/visitor-keys": 8.56.0 - debug: 4.4.3 - eslint: 10.0.0(jiti@1.21.7) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/project-service@8.56.0(typescript@5.9.3)": - dependencies: - "@typescript-eslint/tsconfig-utils": 8.56.0(typescript@5.9.3) - "@typescript-eslint/types": 8.56.0 - debug: 4.4.3 - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/scope-manager@8.56.0": - dependencies: - "@typescript-eslint/types": 8.56.0 - "@typescript-eslint/visitor-keys": 8.56.0 - - "@typescript-eslint/tsconfig-utils@8.56.0(typescript@5.9.3)": - dependencies: - typescript: 5.9.3 - - "@typescript-eslint/type-utils@8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3)": - dependencies: - "@typescript-eslint/types": 8.56.0 - "@typescript-eslint/typescript-estree": 8.56.0(typescript@5.9.3) - "@typescript-eslint/utils": 8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3) - debug: 4.4.3 - eslint: 10.0.0(jiti@1.21.7) - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/types@8.56.0": {} - - "@typescript-eslint/typescript-estree@8.56.0(typescript@5.9.3)": - dependencies: - "@typescript-eslint/project-service": 8.56.0(typescript@5.9.3) - "@typescript-eslint/tsconfig-utils": 8.56.0(typescript@5.9.3) - "@typescript-eslint/types": 8.56.0 - "@typescript-eslint/visitor-keys": 8.56.0 - debug: 4.4.3 - minimatch: 9.0.5 - semver: 7.7.4 - tinyglobby: 0.2.15 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/utils@8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3)": - dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@10.0.0(jiti@1.21.7)) - "@typescript-eslint/scope-manager": 8.56.0 - "@typescript-eslint/types": 8.56.0 - "@typescript-eslint/typescript-estree": 8.56.0(typescript@5.9.3) - eslint: 10.0.0(jiti@1.21.7) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - "@typescript-eslint/visitor-keys@8.56.0": - dependencies: - "@typescript-eslint/types": 8.56.0 - eslint-visitor-keys: 5.0.0 - - "@vime/core@5.4.1": - dependencies: - "@stencil/core": 2.5.2 - "@types/fscreen": 1.0.4 - fscreen: 1.2.0 - mitt: 3.0.1 - stencil-wormhole: 3.4.1 - - acorn-jsx@5.3.2(acorn@8.15.0): - dependencies: - acorn: 8.15.0 - - acorn@8.15.0: {} - - agent-base@7.1.4: {} - - aggregate-error@3.1.0: - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - - aggregate-error@5.0.0: - dependencies: - clean-stack: 5.3.0 - indent-string: 5.0.0 - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ajv@8.18.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - all-contributors-cli@6.26.1: - dependencies: - "@babel/runtime": 7.28.6 - async: 3.2.6 - chalk: 4.1.2 - didyoumean: 1.2.2 - inquirer: 7.3.3 - json-fixer: 1.6.15 - lodash: 4.17.23 - node-fetch: 2.7.0 - pify: 5.0.0 - yargs: 15.4.1 - optionalDependencies: - prettier: 2.8.8 - transitivePeerDependencies: - - encoding - - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 - - ansi-escapes@7.3.0: - dependencies: - environment: 1.1.0 - - ansi-regex@5.0.1: {} - - ansi-regex@6.2.2: {} - - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.3: {} - - ansis@4.2.0: {} - - any-promise@1.3.0: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - arg@5.0.2: {} - - argparse@2.0.1: {} - - argv-formatter@1.0.0: {} - - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - is-array-buffer: 3.0.5 - - array-ify@1.0.0: {} - - arraybuffer.prototype.slice@1.0.4: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - is-array-buffer: 3.0.5 - - astral-regex@2.0.0: {} - - async-function@1.0.0: {} - - async@3.2.6: {} - - at-least-node@1.0.0: {} - - autoprefixer@10.4.24(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - caniuse-lite: 1.0.30001770 - fraction.js: 5.3.4 - picocolors: 1.1.1 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 - - babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0): - dependencies: - "@babel/compat-data": 7.29.0 - "@babel/core": 7.29.0 - "@babel/helper-define-polyfill-provider": 0.6.6(@babel/core@7.29.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - babel-plugin-polyfill-corejs3@0.14.0(@babel/core@7.29.0): - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-define-polyfill-provider": 0.6.6(@babel/core@7.29.0) - core-js-compat: 3.48.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.29.0): - dependencies: - "@babel/core": 7.29.0 - "@babel/helper-define-polyfill-provider": 0.6.6(@babel/core@7.29.0) - transitivePeerDependencies: - - supports-color - - balanced-match@1.0.2: {} - - balanced-match@3.0.1: {} - - balanced-match@4.0.3: {} - - base64-js@1.3.1: {} - - base64-js@1.5.1: {} - - baseline-browser-mapping@2.10.0: {} - - before-after-hook@4.0.0: {} - - binary-extensions@2.3.0: {} - - birpc@2.9.0: {} - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - boolbase@1.0.0: {} - - bottleneck@2.19.5: {} - - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.2: - dependencies: - balanced-match: 1.0.2 - - brace-expansion@5.0.2: - dependencies: - balanced-match: 4.0.3 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - brotli@1.3.3: - dependencies: - base64-js: 1.5.1 - - browserslist@4.28.1: - dependencies: - baseline-browser-mapping: 2.10.0 - caniuse-lite: 1.0.30001770 - electron-to-chromium: 1.5.286 - node-releases: 2.0.27 - update-browserslist-db: 1.2.3(browserslist@4.28.1) - - buffer-from@1.1.2: {} - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - bundle-name@4.1.0: - dependencies: - run-applescript: 7.1.0 - - byte-counter@0.1.0: {} - - cacheable-lookup@7.0.0: {} - - cacheable-request@13.0.18: - dependencies: - "@types/http-cache-semantics": 4.2.0 - get-stream: 9.0.1 - http-cache-semantics: 4.2.0 - keyv: 5.6.0 - mimic-response: 4.0.0 - normalize-url: 8.1.1 - responselike: 4.0.2 - - cacheable@2.3.2: - dependencies: - "@cacheable/memory": 2.0.7 - "@cacheable/utils": 2.3.4 - hookified: 1.15.1 - keyv: 5.6.0 - qified: 0.6.0 - - cachedir@2.3.0: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.8: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - get-intrinsic: 1.3.0 - set-function-length: 1.2.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - - callsites@3.1.0: {} - - camelcase-css@2.0.1: {} - - camelcase@5.3.1: {} - - caniuse-api@3.0.0: - dependencies: - browserslist: 4.28.1 - caniuse-lite: 1.0.30001770 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 - - caniuse-lite@1.0.30001770: {} - - chalk@2.4.2: - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chalk@5.6.2: {} - - char-regex@1.0.2: {} - - chardet@0.7.0: {} - - choices.js@11.1.0: - dependencies: - fuse.js: 7.1.0 - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - ci-info@4.4.0: {} - - clean-stack@2.2.0: {} - - clean-stack@5.3.0: - dependencies: - escape-string-regexp: 5.0.0 - - cli-cursor@3.1.0: - dependencies: - restore-cursor: 3.1.0 - - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-highlight@2.1.11: - dependencies: - chalk: 4.1.2 - highlight.js: 10.7.3 - mz: 2.7.0 - parse5: 5.1.1 - parse5-htmlparser2-tree-adapter: 6.0.1 - yargs: 16.2.0 - - cli-spinners@2.9.2: {} - - cli-table3@0.6.5: - dependencies: - string-width: 4.2.3 - optionalDependencies: - "@colors/colors": 1.5.0 - - cli-truncate@5.1.1: - dependencies: - slice-ansi: 7.1.2 - string-width: 8.2.0 - - cli-width@3.0.0: {} - - cliui@6.0.0: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - cliui@9.0.1: - dependencies: - string-width: 7.2.0 - strip-ansi: 7.1.2 - wrap-ansi: 9.0.2 - - clone@1.0.4: {} - - codemirror@6.0.2: - dependencies: - "@codemirror/autocomplete": 6.20.0 - "@codemirror/commands": 6.10.2 - "@codemirror/language": 6.12.1 - "@codemirror/lint": 6.9.4 - "@codemirror/search": 6.6.0 - "@codemirror/state": 6.5.4 - "@codemirror/view": 6.39.14 - - color-convert@1.9.3: - dependencies: - color-name: 1.1.3 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.3: {} - - color-name@1.1.4: {} - - colord@2.9.3: {} - - colorette@2.0.20: {} - - commander@11.1.0: {} - - commander@14.0.3: {} - - commander@2.20.3: {} - - commander@4.1.1: {} - - commander@7.2.0: {} - - commitizen@4.3.1(@types/node@24.7.0)(typescript@5.9.3): - dependencies: - cachedir: 2.3.0 - cz-conventional-changelog: 3.3.0(@types/node@24.7.0)(typescript@5.9.3) - dedent: 0.7.0 - detect-indent: 6.1.0 - find-node-modules: 2.1.3 - find-root: 1.1.0 - fs-extra: 9.1.0 - glob: 7.2.3 - inquirer: 8.2.5 - is-utf8: 0.2.1 - lodash: 4.17.21 - minimist: 1.2.7 - strip-bom: 4.0.0 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - "@types/node" - - typescript - - common-tags@1.8.2: {} - - compare-func@2.0.0: - dependencies: - array-ify: 1.0.0 - dot-prop: 5.3.0 - - concat-map@0.0.1: {} - - config-chain@1.1.13: - dependencies: - ini: 1.3.8 - proto-list: 1.2.4 - - conventional-changelog-angular@8.1.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-conventionalcommits@9.1.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-writer@8.2.0: - dependencies: - conventional-commits-filter: 5.0.0 - handlebars: 4.7.8 - meow: 13.2.0 - semver: 7.7.4 - - conventional-commit-types@3.0.0: {} - - conventional-commits-filter@5.0.0: {} - - conventional-commits-parser@6.2.1: - dependencies: - meow: 13.2.0 - - convert-hrtime@5.0.0: {} - - convert-source-map@2.0.0: {} - - core-js-compat@3.48.0: - dependencies: - browserslist: 4.28.1 - - core-js@3.48.0: {} - - core-util-is@1.0.3: {} - - cosmiconfig-typescript-loader@6.2.0(@types/node@24.7.0)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3): - dependencies: - "@types/node": 24.7.0 - cosmiconfig: 9.0.0(typescript@5.9.3) - jiti: 2.6.1 - typescript: 5.9.3 - - cosmiconfig@9.0.0(typescript@5.9.3): - dependencies: - env-paths: 2.2.1 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - parse-json: 5.2.0 - optionalDependencies: - typescript: 5.9.3 - - crelt@1.0.6: {} - - cross-env@10.1.0: - dependencies: - "@epic-web/invariant": 1.0.0 - cross-spawn: 7.0.6 - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - crypto-js@4.2.0: {} - - crypto-random-string@2.0.0: {} - - crypto-random-string@4.0.0: - dependencies: - type-fest: 1.4.0 - - css-blank-pseudo@8.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - css-declaration-sorter@7.3.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - css-functions-list@3.3.3: {} - - css-has-pseudo@8.0.0(postcss@8.5.6): - dependencies: - "@csstools/selector-specificity": 6.0.0(postcss-selector-parser@7.1.1) - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - postcss-value-parser: 4.2.0 - - css-prefers-color-scheme@11.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - css-select@5.2.2: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 - - css-tree@2.2.1: - dependencies: - mdn-data: 2.0.28 - source-map-js: 1.2.1 - - css-tree@3.1.0: - dependencies: - mdn-data: 2.12.2 - source-map-js: 1.2.1 - - css-what@6.2.2: {} - - cssdb@8.7.1: {} - - cssesc@3.0.0: {} - - cssnano-preset-default@7.0.10(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - css-declaration-sorter: 7.3.1(postcss@8.5.6) - cssnano-utils: 5.0.1(postcss@8.5.6) - postcss: 8.5.6 - postcss-calc: 10.1.1(postcss@8.5.6) - postcss-colormin: 7.0.5(postcss@8.5.6) - postcss-convert-values: 7.0.8(postcss@8.5.6) - postcss-discard-comments: 7.0.5(postcss@8.5.6) - postcss-discard-duplicates: 7.0.2(postcss@8.5.6) - postcss-discard-empty: 7.0.1(postcss@8.5.6) - postcss-discard-overridden: 7.0.1(postcss@8.5.6) - postcss-merge-longhand: 7.0.5(postcss@8.5.6) - postcss-merge-rules: 7.0.7(postcss@8.5.6) - postcss-minify-font-values: 7.0.1(postcss@8.5.6) - postcss-minify-gradients: 7.0.1(postcss@8.5.6) - postcss-minify-params: 7.0.5(postcss@8.5.6) - postcss-minify-selectors: 7.0.5(postcss@8.5.6) - postcss-normalize-charset: 7.0.1(postcss@8.5.6) - postcss-normalize-display-values: 7.0.1(postcss@8.5.6) - postcss-normalize-positions: 7.0.1(postcss@8.5.6) - postcss-normalize-repeat-style: 7.0.1(postcss@8.5.6) - postcss-normalize-string: 7.0.1(postcss@8.5.6) - postcss-normalize-timing-functions: 7.0.1(postcss@8.5.6) - postcss-normalize-unicode: 7.0.5(postcss@8.5.6) - postcss-normalize-url: 7.0.1(postcss@8.5.6) - postcss-normalize-whitespace: 7.0.1(postcss@8.5.6) - postcss-ordered-values: 7.0.2(postcss@8.5.6) - postcss-reduce-initial: 7.0.5(postcss@8.5.6) - postcss-reduce-transforms: 7.0.1(postcss@8.5.6) - postcss-svgo: 7.1.0(postcss@8.5.6) - postcss-unique-selectors: 7.0.4(postcss@8.5.6) - - cssnano-utils@5.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - cssnano@7.1.2(postcss@8.5.6): - dependencies: - cssnano-preset-default: 7.0.10(postcss@8.5.6) - lilconfig: 3.1.3 - postcss: 8.5.6 - - csso@5.0.5: - dependencies: - css-tree: 2.2.1 - - cz-conventional-changelog@3.3.0(@types/node@24.7.0)(typescript@5.9.3): - dependencies: - chalk: 2.4.2 - commitizen: 4.3.1(@types/node@24.7.0)(typescript@5.9.3) - conventional-commit-types: 3.0.0 - lodash.map: 4.6.0 - longest: 2.0.1 - word-wrap: 1.2.5 - optionalDependencies: - "@commitlint/load": 20.4.0(@types/node@24.7.0)(typescript@5.9.3) - transitivePeerDependencies: - - "@types/node" - - typescript - - d3-array@3.2.4: - dependencies: - internmap: 2.0.3 - - d3-color@3.1.0: {} - - d3-dispatch@3.0.1: {} - - d3-ease@3.0.1: {} - - d3-force@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-quadtree: 3.0.1 - d3-timer: 3.0.1 - - d3-geo-projection@4.0.0: - dependencies: - commander: 7.2.0 - d3-array: 3.2.4 - d3-geo: 3.1.1 - - d3-geo@3.1.1: - dependencies: - d3-array: 3.2.4 - - d3-interpolate@3.0.1: - dependencies: - d3-color: 3.1.0 - - d3-quadtree@3.0.1: {} - - d3-selection@3.0.0: {} - - d3-timer@3.0.1: {} - - d3-transition@3.0.1(d3-selection@3.0.0): - dependencies: - d3-color: 3.1.0 - d3-dispatch: 3.0.1 - d3-ease: 3.0.1 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-timer: 3.0.1 - - dargs@8.1.0: {} - - data-view-buffer@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-offset@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - decamelize@1.2.0: {} - - decompress-response@10.0.0: - dependencies: - mimic-response: 4.0.0 - - dedent@0.7.0: {} - - deep-equal@1.1.2: - dependencies: - is-arguments: 1.2.0 - is-date-object: 1.1.0 - is-regex: 1.2.1 - object-is: 1.1.6 - object-keys: 1.1.1 - regexp.prototype.flags: 1.5.4 - - deep-extend@0.6.0: {} - - deep-is@0.1.4: {} - - deepmerge@4.3.1: {} - - default-browser-id@5.0.1: {} - - default-browser@5.5.0: - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.1 - - defaults@1.0.4: - dependencies: - clone: 1.0.4 - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - define-lazy-prop@3.0.0: {} - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - detect-file@1.0.0: {} - - detect-indent@6.1.0: {} - - detect-libc@2.1.2: {} - - dfa@1.2.0: {} - - didyoumean@1.2.2: {} - - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - - dlv@1.1.3: {} - - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - - domelementtype@2.3.0: {} - - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - - dot-prop@5.3.0: - dependencies: - is-obj: 2.0.0 - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - duplexer2@0.1.4: - dependencies: - readable-stream: 2.3.8 - - ejs@3.1.10: - dependencies: - jake: 10.9.4 - - electron-to-chromium@1.5.286: {} - - emoji-regex@10.6.0: {} - - emoji-regex@8.0.0: {} - - emojilib@2.4.0: {} - - entities@4.5.0: {} - - env-ci@11.2.0: - dependencies: - execa: 8.0.1 - java-properties: 1.0.2 - - env-paths@2.2.1: {} - - environment@1.1.0: {} - - error-ex@1.3.4: - dependencies: - is-arrayish: 0.2.1 - - error-stack-parser-es@1.0.5: {} - - es-abstract@1.24.1: - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.4 - data-view-buffer: 1.0.2 - data-view-byte-length: 1.0.2 - data-view-byte-offset: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - get-symbol-description: 1.1.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - internal-slot: 1.1.0 - is-array-buffer: 3.0.5 - is-callable: 1.2.7 - is-data-view: 1.0.2 - is-negative-zero: 2.0.3 - is-regex: 1.2.1 - is-set: 2.0.3 - is-shared-array-buffer: 1.0.4 - is-string: 1.1.1 - is-typed-array: 1.1.15 - is-weakref: 1.1.1 - math-intrinsics: 1.1.0 - object-inspect: 1.13.4 - object-keys: 1.1.1 - object.assign: 4.1.7 - own-keys: 1.0.1 - regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 - safe-push-apply: 1.0.0 - safe-regex-test: 1.1.0 - set-proto: 1.0.0 - stop-iteration-iterator: 1.1.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.3 - typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.20 - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - es-to-primitive@1.3.0: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - - esbuild@0.27.3: - optionalDependencies: - "@esbuild/aix-ppc64": 0.27.3 - "@esbuild/android-arm": 0.27.3 - "@esbuild/android-arm64": 0.27.3 - "@esbuild/android-x64": 0.27.3 - "@esbuild/darwin-arm64": 0.27.3 - "@esbuild/darwin-x64": 0.27.3 - "@esbuild/freebsd-arm64": 0.27.3 - "@esbuild/freebsd-x64": 0.27.3 - "@esbuild/linux-arm": 0.27.3 - "@esbuild/linux-arm64": 0.27.3 - "@esbuild/linux-ia32": 0.27.3 - "@esbuild/linux-loong64": 0.27.3 - "@esbuild/linux-mips64el": 0.27.3 - "@esbuild/linux-ppc64": 0.27.3 - "@esbuild/linux-riscv64": 0.27.3 - "@esbuild/linux-s390x": 0.27.3 - "@esbuild/linux-x64": 0.27.3 - "@esbuild/netbsd-arm64": 0.27.3 - "@esbuild/netbsd-x64": 0.27.3 - "@esbuild/openbsd-arm64": 0.27.3 - "@esbuild/openbsd-x64": 0.27.3 - "@esbuild/openharmony-arm64": 0.27.3 - "@esbuild/sunos-x64": 0.27.3 - "@esbuild/win32-arm64": 0.27.3 - "@esbuild/win32-ia32": 0.27.3 - "@esbuild/win32-x64": 0.27.3 - - escalade@3.2.0: {} - - escape-string-regexp@1.0.5: {} - - escape-string-regexp@4.0.0: {} - - escape-string-regexp@5.0.0: {} - - eslint-config-prettier@10.1.8(eslint@10.0.0(jiti@1.21.7)): - dependencies: - eslint: 10.0.0(jiti@1.21.7) - - eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.0.0(jiti@1.21.7)))(eslint@10.0.0(jiti@1.21.7))(prettier@3.8.1): - dependencies: - eslint: 10.0.0(jiti@1.21.7) - prettier: 3.8.1 - prettier-linter-helpers: 1.0.1 - synckit: 0.11.12 - optionalDependencies: - "@types/eslint": 9.6.1 - eslint-config-prettier: 10.1.8(eslint@10.0.0(jiti@1.21.7)) - - eslint-scope@9.1.0: - dependencies: - "@types/esrecurse": 4.3.1 - "@types/estree": 1.0.8 - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.1: {} - - eslint-visitor-keys@5.0.0: {} - - eslint@10.0.0(jiti@1.21.7): - dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@10.0.0(jiti@1.21.7)) - "@eslint-community/regexpp": 4.12.2 - "@eslint/config-array": 0.23.1 - "@eslint/config-helpers": 0.5.2 - "@eslint/core": 1.1.0 - "@eslint/plugin-kit": 0.6.0 - "@humanfs/node": 0.16.7 - "@humanwhocodes/module-importer": 1.0.1 - "@humanwhocodes/retry": 0.4.3 - "@types/estree": 1.0.8 - ajv: 6.12.6 - cross-spawn: 7.0.6 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint-scope: 9.1.0 - eslint-visitor-keys: 5.0.0 - espree: 11.1.0 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.1 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 1.21.7 - transitivePeerDependencies: - - supports-color - - espree@10.4.0: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 4.2.1 - - espree@11.1.0: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 5.0.0 - - esquery@1.7.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - estree-walker@1.0.1: {} - - estree-walker@2.0.2: {} - - esutils@2.0.3: {} - - eventemitter3@5.0.4: {} - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - execa@9.6.1: - dependencies: - "@sindresorhus/merge-streams": 4.0.0 - cross-spawn: 7.0.6 - figures: 6.1.0 - get-stream: 9.0.1 - human-signals: 8.0.1 - is-plain-obj: 4.1.0 - is-stream: 4.0.1 - npm-run-path: 6.0.0 - pretty-ms: 9.3.0 - signal-exit: 4.1.0 - strip-final-newline: 4.0.0 - yoctocolors: 2.1.2 - - expand-tilde@2.0.2: - dependencies: - homedir-polyfill: 1.0.3 - - external-editor@3.1.0: - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - - fast-content-type-parse@3.0.0: {} - - fast-deep-equal@3.1.3: {} - - fast-diff@1.3.0: {} - - fast-glob@3.3.3: - dependencies: - "@nodelib/fs.stat": 2.0.5 - "@nodelib/fs.walk": 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fast-uri@3.1.0: {} - - fastest-levenshtein@1.0.16: {} - - fastq@1.20.1: - dependencies: - reusify: 1.1.0 - - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - - figures@2.0.0: - dependencies: - escape-string-regexp: 1.0.5 - - figures@3.2.0: - dependencies: - escape-string-regexp: 1.0.5 - - figures@6.1.0: - dependencies: - is-unicode-supported: 2.1.0 - - file-entry-cache@11.1.2: - dependencies: - flat-cache: 6.1.20 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - filelist@1.0.4: - dependencies: - minimatch: 5.1.6 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-node-modules@2.1.3: - dependencies: - findup-sync: 4.0.0 - merge: 2.1.1 - - find-root@1.1.0: {} - - find-up-simple@1.0.1: {} - - find-up@2.1.0: - dependencies: - locate-path: 2.0.0 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - find-versions@6.0.0: - dependencies: - semver-regex: 4.0.5 - super-regex: 1.1.0 - - findup-sync@4.0.0: - dependencies: - detect-file: 1.0.0 - is-glob: 4.0.3 - micromatch: 4.0.8 - resolve-dir: 1.0.1 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.3 - keyv: 4.5.4 - - flat-cache@6.1.20: - dependencies: - cacheable: 2.3.2 - flatted: 3.3.3 - hookified: 1.15.1 - - flatpickr@4.6.13: {} - - flatted@3.3.3: {} - - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 - - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - form-data-encoder@4.1.0: {} - - formdata-node@6.0.3: {} - - fraction.js@5.3.4: {} - - from2@2.3.0: - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.8 - - fs-extra@11.3.3: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fs-extra@9.1.0: - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fs.realpath@1.0.0: {} - - fscreen@1.2.0: {} - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - function-timeout@1.0.2: {} - - function.prototype.name@1.1.8: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - hasown: 2.0.2 - is-callable: 1.2.7 - - functions-have-names@1.2.3: {} - - fuse.js@7.1.0: {} - - generator-function@2.0.1: {} - - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - - get-east-asian-width@1.5.0: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-own-enumerable-property-symbols@3.0.2: {} - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - get-stream@6.0.1: {} - - get-stream@7.0.1: {} - - get-stream@8.0.1: {} - - get-stream@9.0.1: - dependencies: - "@sec-ant/readable-stream": 0.4.1 - is-stream: 4.0.1 - - get-symbol-description@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - - git-log-parser@1.2.1: - dependencies: - argv-formatter: 1.0.0 - spawn-error-forwarder: 1.0.0 - split2: 1.0.0 - stream-combiner2: 1.1.1 - through2: 2.0.5 - traverse: 0.6.8 - - git-raw-commits@4.0.0: - dependencies: - dargs: 8.1.0 - meow: 12.1.1 - split2: 4.2.0 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@11.1.0: - dependencies: - foreground-child: 3.3.1 - jackspeak: 4.2.3 - minimatch: 10.2.1 - minipass: 7.1.3 - package-json-from-dist: 1.0.1 - path-scurry: 2.0.1 - - glob@13.0.5: - dependencies: - minimatch: 10.2.1 - minipass: 7.1.3 - path-scurry: 2.0.1 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - global-directory@4.0.1: - dependencies: - ini: 4.1.1 - - global-modules@1.0.0: - dependencies: - global-prefix: 1.0.2 - is-windows: 1.0.2 - resolve-dir: 1.0.1 - - global-modules@2.0.0: - dependencies: - global-prefix: 3.0.0 - - global-prefix@1.0.2: - dependencies: - expand-tilde: 2.0.2 - homedir-polyfill: 1.0.3 - ini: 1.3.8 - is-windows: 1.0.2 - which: 1.3.1 - - global-prefix@3.0.0: - dependencies: - ini: 1.3.8 - kind-of: 6.0.3 - which: 1.3.1 - - globals@14.0.0: {} - - globals@17.3.0: {} - - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - - globby@14.1.0: - dependencies: - "@sindresorhus/merge-streams": 2.3.0 - fast-glob: 3.3.3 - ignore: 7.0.5 - path-type: 6.0.0 - slash: 5.1.0 - unicorn-magic: 0.3.0 - - globby@16.1.1: - dependencies: - "@sindresorhus/merge-streams": 4.0.0 - fast-glob: 3.3.3 - ignore: 7.0.5 - is-path-inside: 4.0.0 - slash: 5.1.0 - unicorn-magic: 0.4.0 - - globjoin@0.1.4: {} - - gopd@1.2.0: {} - - got@14.6.6: - dependencies: - "@sindresorhus/is": 7.2.0 - byte-counter: 0.1.0 - cacheable-lookup: 7.0.0 - cacheable-request: 13.0.18 - decompress-response: 10.0.0 - form-data-encoder: 4.1.0 - http2-wrapper: 2.2.1 - keyv: 5.6.0 - lowercase-keys: 3.0.0 - p-cancelable: 4.0.1 - responselike: 4.0.2 - type-fest: 4.41.0 - - graceful-fs@4.2.10: {} - - graceful-fs@4.2.11: {} - - handlebars@4.7.8: - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - - has-bigints@1.1.0: {} - - has-flag@3.0.0: {} - - has-flag@4.0.0: {} - - has-flag@5.0.1: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - - has-proto@1.2.0: - dependencies: - dunder-proto: 1.0.1 - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hashery@1.5.0: - dependencies: - hookified: 1.15.1 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - highlight.js@10.7.3: {} - - homedir-polyfill@1.0.3: - dependencies: - parse-passwd: 1.0.0 - - hook-std@4.0.0: {} - - hookified@1.15.1: {} - - hosted-git-info@7.0.2: - dependencies: - lru-cache: 10.4.3 - - hosted-git-info@9.0.2: - dependencies: - lru-cache: 11.2.6 - - hpagent@1.2.0: {} - - html-tags@5.1.0: {} - - htmlfy@1.0.1: {} - - http-cache-semantics@4.2.0: {} - - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - http2-wrapper@2.2.1: - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - - https-proxy-agent@7.0.6: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - human-signals@2.1.0: {} - - human-signals@5.0.0: {} - - human-signals@8.0.1: {} - - husky@9.1.7: {} - - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - - iconv-lite@0.7.2: - dependencies: - safer-buffer: 2.1.2 - - idb@7.1.1: {} - - ieee754@1.2.1: {} - - ignore@5.3.2: {} - - ignore@7.0.5: {} - - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - import-from-esm@2.0.0: - dependencies: - debug: 4.4.3 - import-meta-resolve: 4.2.0 - transitivePeerDependencies: - - supports-color - - import-meta-resolve@4.2.0: {} - - imurmurhash@0.1.4: {} - - indent-string@4.0.0: {} - - indent-string@5.0.0: {} - - index-to-position@1.2.0: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - ini@1.3.8: {} - - ini@4.1.1: {} - - inquirer@7.3.3: - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.23 - mute-stream: 0.0.8 - run-async: 2.4.1 - rxjs: 6.6.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - - inquirer@8.2.5: - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.8.2 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 7.0.0 - - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - - internmap@2.0.3: {} - - into-stream@7.0.0: - dependencies: - from2: 2.3.0 - p-is-promise: 3.0.0 - - is-arguments@1.2.0: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - - is-arrayish@0.2.1: {} - - is-async-function@2.1.1: - dependencies: - async-function: 1.0.0 - call-bound: 1.0.4 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-bigint@1.1.0: - dependencies: - has-bigints: 1.1.0 - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-boolean-object@1.2.2: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-callable@1.2.7: {} - - is-ci@4.1.0: - dependencies: - ci-info: 4.4.0 - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-data-view@1.0.2: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - is-typed-array: 1.1.15 - - is-date-object@1.1.0: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-docker@3.0.0: {} - - is-extglob@2.1.1: {} - - is-finalizationregistry@1.1.1: - dependencies: - call-bound: 1.0.4 - - is-fullwidth-code-point@3.0.0: {} - - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.5.0 - - is-generator-function@1.1.2: - dependencies: - call-bound: 1.0.4 - generator-function: 2.0.1 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-inside-container@1.0.0: - dependencies: - is-docker: 3.0.0 - - is-interactive@1.0.0: {} - - is-map@2.0.3: {} - - is-module@1.0.0: {} - - is-negative-zero@2.0.3: {} - - is-number-object@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-number@7.0.0: {} - - is-obj@1.0.1: {} - - is-obj@2.0.0: {} - - is-path-inside@4.0.0: {} - - is-plain-obj@4.1.0: {} - - is-plain-object@5.0.0: {} - - is-regex@1.2.1: - dependencies: - call-bound: 1.0.4 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - is-regexp@1.0.0: {} - - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.4 - - is-stream@2.0.1: {} - - is-stream@3.0.0: {} - - is-stream@4.0.1: {} - - is-string@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-symbol@1.1.1: - dependencies: - call-bound: 1.0.4 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.20 - - is-unicode-supported@0.1.0: {} - - is-unicode-supported@2.1.0: {} - - is-utf8@0.2.1: {} - - is-weakmap@2.0.2: {} - - is-weakref@1.1.1: - dependencies: - call-bound: 1.0.4 - - is-weakset@2.0.4: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - - is-windows@1.0.2: {} - - is-wsl@3.1.1: - dependencies: - is-inside-container: 1.0.0 - - isarray@1.0.0: {} - - isarray@2.0.5: {} - - isexe@2.0.0: {} - - issue-parser@7.0.1: - dependencies: - lodash.capitalize: 4.2.1 - lodash.escaperegexp: 4.1.2 - lodash.isplainobject: 4.0.6 - lodash.isstring: 4.0.1 - lodash.uniqby: 4.7.0 - - jackspeak@4.2.3: - dependencies: - "@isaacs/cliui": 9.0.0 - - jake@10.9.4: - dependencies: - async: 3.2.6 - filelist: 1.0.4 - picocolors: 1.1.1 - - java-properties@1.0.2: {} - - jiti@1.21.7: {} - - jiti@2.6.1: {} - - jpeg-exif@1.1.4: {} - - js-tokens@4.0.0: {} - - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 - - jsesc@3.1.0: {} - - json-buffer@3.0.1: {} - - json-fixer@1.6.15: - dependencies: - "@babel/runtime": 7.28.6 - chalk: 4.1.2 - pegjs: 0.10.0 - - json-parse-better-errors@1.0.2: {} - - json-parse-even-better-errors@2.3.1: {} - - json-schema-traverse@0.4.1: {} - - json-schema-traverse@1.0.0: {} - - json-schema@0.4.0: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@2.2.3: {} - - jsonfile@6.2.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - jsonpointer@5.0.1: {} - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - keyv@5.6.0: - dependencies: - "@keyv/serialize": 1.1.1 - - kind-of@6.0.3: {} - - known-css-properties@0.37.0: {} - - leaflet.markercluster@1.5.3(leaflet@1.9.4): - dependencies: - leaflet: 1.9.4 - - leaflet@1.9.4: {} - - leven@3.1.0: {} - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lilconfig@3.1.3: {} - - lines-and-columns@1.2.4: {} - - lint-staged@16.2.7: - dependencies: - commander: 14.0.3 - listr2: 9.0.5 - micromatch: 4.0.8 - nano-spawn: 2.0.0 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.8.2 - - listr2@9.0.5: - dependencies: - cli-truncate: 5.1.1 - colorette: 2.0.20 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 9.0.2 - - lit-element@4.2.2: - dependencies: - "@lit-labs/ssr-dom-shim": 1.5.1 - "@lit/reactive-element": 2.1.2 - lit-html: 3.3.2 - - lit-html@3.3.2: - dependencies: - "@types/trusted-types": 2.0.7 - - lit@3.3.2: - dependencies: - "@lit/reactive-element": 2.1.2 - lit-element: 4.2.2 - lit-html: 3.3.2 - - load-json-file@4.0.0: - dependencies: - graceful-fs: 4.2.11 - parse-json: 4.0.0 - pify: 3.0.0 - strip-bom: 3.0.0 - - locate-path@2.0.0: - dependencies: - p-locate: 2.0.0 - path-exists: 3.0.0 - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash-es@4.17.23: {} - - lodash.camelcase@4.3.0: {} - - lodash.capitalize@4.2.1: {} - - lodash.debounce@4.0.8: {} - - lodash.escaperegexp@4.1.2: {} - - lodash.isplainobject@4.0.6: {} - - lodash.isstring@4.0.1: {} - - lodash.kebabcase@4.1.1: {} - - lodash.map@4.6.0: {} - - lodash.memoize@4.1.2: {} - - lodash.mergewith@4.6.2: {} - - lodash.snakecase@4.1.1: {} - - lodash.sortby@4.7.0: {} - - lodash.startcase@4.4.0: {} - - lodash.truncate@4.4.2: {} - - lodash.uniq@4.5.0: {} - - lodash.uniqby@4.7.0: {} - - lodash.upperfirst@4.3.1: {} - - lodash@4.17.21: {} - - lodash@4.17.23: {} - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - log-update@6.1.0: - dependencies: - ansi-escapes: 7.3.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.1.2 - wrap-ansi: 9.0.2 - - longest@2.0.1: {} - - lowercase-keys@3.0.0: {} - - lru-cache@10.4.3: {} - - lru-cache@11.2.6: {} - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - magic-string@0.25.9: - dependencies: - sourcemap-codec: 1.4.8 - - make-asynchronous@1.0.1: - dependencies: - p-event: 6.0.1 - type-fest: 4.41.0 - web-worker: 1.2.0 - - marked-terminal@7.3.0(marked@15.0.12): - dependencies: - ansi-escapes: 7.3.0 - ansi-regex: 6.2.2 - chalk: 5.6.2 - cli-highlight: 2.1.11 - cli-table3: 0.6.5 - marked: 15.0.12 - node-emoji: 2.2.0 - supports-hyperlinks: 3.2.0 - - marked@15.0.12: {} - - marked@17.0.3: {} - - math-intrinsics@1.1.0: {} - - mathml-tag-names@4.0.0: {} - - mdn-data@2.0.28: {} - - mdn-data@2.12.2: {} - - meow@12.1.1: {} - - meow@13.2.0: {} - - meow@14.0.0: {} - - merge-stream@2.0.0: {} - - merge2@1.4.1: {} - - merge@2.1.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mime@4.1.0: {} - - mimic-fn@2.1.0: {} - - mimic-fn@4.0.0: {} - - mimic-function@5.0.1: {} - - mimic-response@4.0.0: {} - - mini-svg-data-uri@1.4.4: {} - - minimatch@10.2.1: - dependencies: - brace-expansion: 5.0.2 - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 - - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.2 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.2 - - minimist@1.2.7: {} - - minimist@1.2.8: {} - - minipass@7.1.3: {} - - mitt@3.0.1: {} - - mrmime@2.0.1: {} - - ms@2.1.3: {} - - mute-stream@0.0.8: {} - - mz@2.7.0: - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - - nano-spawn@2.0.0: {} - - nanoid@3.3.11: {} - - natural-compare@1.4.0: {} - - neo-async@2.6.2: {} - - nerf-dart@1.0.0: {} - - node-emoji@2.2.0: - dependencies: - "@sindresorhus/is": 4.6.0 - char-regex: 1.0.2 - emojilib: 2.4.0 - skin-tone: 2.0.0 - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-releases@2.0.27: {} - - normalize-package-data@6.0.2: - dependencies: - hosted-git-info: 7.0.2 - semver: 7.7.4 - validate-npm-package-license: 3.0.4 - - normalize-package-data@8.0.0: - dependencies: - hosted-git-info: 9.0.2 - semver: 7.7.4 - validate-npm-package-license: 3.0.4 - - normalize-path@3.0.0: {} - - normalize-url@8.1.1: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - - npm-run-path@6.0.0: - dependencies: - path-key: 4.0.0 - unicorn-magic: 0.3.0 - - npm@11.10.0: {} - - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 - - object-assign@4.1.1: {} - - object-hash@3.0.0: {} - - object-inspect@1.13.4: {} - - object-is@1.1.6: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - - ohash@2.0.11: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - - onetime@7.0.0: - dependencies: - mimic-function: 5.0.1 - - open@10.2.0: - dependencies: - default-browser: 5.5.0 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - wsl-utils: 0.1.0 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - ora@5.4.1: - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - - os-tmpdir@1.0.2: {} - - own-keys@1.0.1: - dependencies: - get-intrinsic: 1.3.0 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - - p-cancelable@4.0.1: {} - - p-each-series@3.0.0: {} - - p-event@6.0.1: - dependencies: - p-timeout: 6.1.4 - - p-filter@4.1.0: - dependencies: - p-map: 7.0.4 - - p-is-promise@3.0.0: {} - - p-limit@1.3.0: - dependencies: - p-try: 1.0.0 - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@2.0.0: - dependencies: - p-limit: 1.3.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - p-map@7.0.4: {} - - p-reduce@2.1.0: {} - - p-reduce@3.0.0: {} - - p-timeout@6.1.4: {} - - p-try@1.0.0: {} - - p-try@2.2.0: {} - - package-json-from-dist@1.0.1: {} - - pako@0.2.9: {} - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse-json@4.0.0: - dependencies: - error-ex: 1.3.4 - json-parse-better-errors: 1.0.2 - - parse-json@5.2.0: - dependencies: - "@babel/code-frame": 7.29.0 - error-ex: 1.3.4 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - parse-json@8.3.0: - dependencies: - "@babel/code-frame": 7.29.0 - index-to-position: 1.2.0 - type-fest: 4.41.0 - - parse-ms@4.0.0: {} - - parse-passwd@1.0.0: {} - - parse-path@7.1.0: - dependencies: - protocols: 2.0.2 - - parse-url@10.0.3: - dependencies: - parse-path: 7.1.0 - - parse5-htmlparser2-tree-adapter@6.0.1: - dependencies: - parse5: 6.0.1 - - parse5@5.1.1: {} - - parse5@6.0.1: {} - - path-exists@3.0.0: {} - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-key@4.0.0: {} - - path-parse@1.0.7: {} - - path-scurry@2.0.1: - dependencies: - lru-cache: 11.2.6 - minipass: 7.1.3 - - path-type@4.0.0: {} - - path-type@6.0.0: {} - - pathe@2.0.3: {} - - pdfmake@0.2.23: - dependencies: - "@foliojs-fork/linebreak": 1.1.2 - "@foliojs-fork/pdfkit": 0.15.3 - iconv-lite: 0.7.2 - xmldoc: 2.0.3 - - pegjs@0.10.0: {} - - perfect-debounce@2.1.0: {} - - performance-now@2.1.0: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - picomatch@4.0.3: {} - - pidtree@0.6.0: {} - - pify@2.3.0: {} - - pify@3.0.0: {} - - pify@5.0.0: {} - - pirates@4.0.7: {} - - pkg-conf@2.1.0: - dependencies: - find-up: 2.1.0 - load-json-file: 4.0.0 - - png-js@1.0.0: {} - - polylabel@1.1.0: - dependencies: - tinyqueue: 2.0.3 - - possible-typed-array-names@1.1.0: {} - - postcss-attribute-case-insensitive@8.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-calc@10.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - postcss-value-parser: 4.2.0 - - postcss-clamp@4.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-color-functional-notation@8.0.1(postcss@8.5.6): - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - postcss-color-hex-alpha@11.0.0(postcss@8.5.6): - dependencies: - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-color-rebeccapurple@11.0.0(postcss@8.5.6): - dependencies: - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-colormin@7.0.5(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - caniuse-api: 3.0.0 - colord: 2.9.3 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-convert-values@7.0.8(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-custom-media@12.0.0(postcss@8.5.6): - dependencies: - "@csstools/cascade-layer-name-parser": 3.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/media-query-list-parser": 5.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - postcss: 8.5.6 - - postcss-custom-properties@15.0.0(postcss@8.5.6): - dependencies: - "@csstools/cascade-layer-name-parser": 3.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-custom-selectors@9.0.0(postcss@8.5.6): - dependencies: - "@csstools/cascade-layer-name-parser": 3.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-dir-pseudo-class@10.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-discard-comments@7.0.5(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-discard-duplicates@7.0.2(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-discard-empty@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-discard-overridden@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-double-position-gradients@7.0.0(postcss@8.5.6): - dependencies: - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-focus-visible@11.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-focus-within@10.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-font-variant@5.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-gap-properties@7.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-image-set-function@8.0.0(postcss@8.5.6): - dependencies: - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-import@15.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.11 - - postcss-import@16.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.11 - - postcss-js@4.1.0(postcss@8.5.6): - dependencies: - camelcase-css: 2.0.1 - postcss: 8.5.6 - - postcss-lab-function@8.0.1(postcss@8.5.6): - dependencies: - "@csstools/css-color-parser": 4.0.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-tokenizer": 4.0.0 - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/utilities": 3.0.0(postcss@8.5.6) - postcss: 8.5.6 - - postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(yaml@2.8.2): - dependencies: - lilconfig: 3.1.3 - optionalDependencies: - jiti: 1.21.7 - postcss: 8.5.6 - yaml: 2.8.2 - - postcss-logical@9.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-merge-longhand@7.0.5(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - stylehacks: 7.0.7(postcss@8.5.6) - - postcss-merge-rules@7.0.7(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - caniuse-api: 3.0.0 - cssnano-utils: 5.0.1(postcss@8.5.6) - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-minify-font-values@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-gradients@7.0.1(postcss@8.5.6): - dependencies: - colord: 2.9.3 - cssnano-utils: 5.0.1(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-params@7.0.5(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - cssnano-utils: 5.0.1(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-selectors@7.0.5(postcss@8.5.6): - dependencies: - cssesc: 3.0.0 - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-nested@6.2.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - postcss-nesting@14.0.0(postcss@8.5.6): - dependencies: - "@csstools/selector-resolve-nested": 4.0.0(postcss-selector-parser@7.1.1) - "@csstools/selector-specificity": 6.0.0(postcss-selector-parser@7.1.1) - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-normalize-charset@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-normalize-display-values@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-positions@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-repeat-style@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-string@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-timing-functions@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-unicode@7.0.5(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-url@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-whitespace@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-opacity-percentage@3.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-ordered-values@7.0.2(postcss@8.5.6): - dependencies: - cssnano-utils: 5.0.1(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-overflow-shorthand@7.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-page-break@3.0.4(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-place@11.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-preset-env@11.1.3(postcss@8.5.6): - dependencies: - "@csstools/postcss-alpha-function": 2.0.2(postcss@8.5.6) - "@csstools/postcss-cascade-layers": 6.0.0(postcss@8.5.6) - "@csstools/postcss-color-function": 5.0.1(postcss@8.5.6) - "@csstools/postcss-color-function-display-p3-linear": 2.0.1(postcss@8.5.6) - "@csstools/postcss-color-mix-function": 4.0.1(postcss@8.5.6) - "@csstools/postcss-color-mix-variadic-function-arguments": 2.0.1(postcss@8.5.6) - "@csstools/postcss-content-alt-text": 3.0.0(postcss@8.5.6) - "@csstools/postcss-contrast-color-function": 3.0.1(postcss@8.5.6) - "@csstools/postcss-exponential-functions": 3.0.0(postcss@8.5.6) - "@csstools/postcss-font-format-keywords": 5.0.0(postcss@8.5.6) - "@csstools/postcss-gamut-mapping": 3.0.1(postcss@8.5.6) - "@csstools/postcss-gradients-interpolation-method": 6.0.1(postcss@8.5.6) - "@csstools/postcss-hwb-function": 5.0.1(postcss@8.5.6) - "@csstools/postcss-ic-unit": 5.0.0(postcss@8.5.6) - "@csstools/postcss-initial": 3.0.0(postcss@8.5.6) - "@csstools/postcss-is-pseudo-class": 6.0.0(postcss@8.5.6) - "@csstools/postcss-light-dark-function": 3.0.0(postcss@8.5.6) - "@csstools/postcss-logical-float-and-clear": 4.0.0(postcss@8.5.6) - "@csstools/postcss-logical-overflow": 3.0.0(postcss@8.5.6) - "@csstools/postcss-logical-overscroll-behavior": 3.0.0(postcss@8.5.6) - "@csstools/postcss-logical-resize": 4.0.0(postcss@8.5.6) - "@csstools/postcss-logical-viewport-units": 4.0.0(postcss@8.5.6) - "@csstools/postcss-media-minmax": 3.0.0(postcss@8.5.6) - "@csstools/postcss-media-queries-aspect-ratio-number-values": 4.0.0(postcss@8.5.6) - "@csstools/postcss-mixins": 1.0.0(postcss@8.5.6) - "@csstools/postcss-nested-calc": 5.0.0(postcss@8.5.6) - "@csstools/postcss-normalize-display-values": 5.0.1(postcss@8.5.6) - "@csstools/postcss-oklab-function": 5.0.1(postcss@8.5.6) - "@csstools/postcss-position-area-property": 2.0.0(postcss@8.5.6) - "@csstools/postcss-progressive-custom-properties": 5.0.0(postcss@8.5.6) - "@csstools/postcss-property-rule-prelude-list": 2.0.0(postcss@8.5.6) - "@csstools/postcss-random-function": 3.0.0(postcss@8.5.6) - "@csstools/postcss-relative-color-syntax": 4.0.1(postcss@8.5.6) - "@csstools/postcss-scope-pseudo-class": 5.0.0(postcss@8.5.6) - "@csstools/postcss-sign-functions": 2.0.0(postcss@8.5.6) - "@csstools/postcss-stepped-value-functions": 5.0.0(postcss@8.5.6) - "@csstools/postcss-syntax-descriptor-syntax-production": 2.0.0(postcss@8.5.6) - "@csstools/postcss-system-ui-font-family": 2.0.0(postcss@8.5.6) - "@csstools/postcss-text-decoration-shorthand": 5.0.2(postcss@8.5.6) - "@csstools/postcss-trigonometric-functions": 5.0.0(postcss@8.5.6) - "@csstools/postcss-unset-value": 5.0.0(postcss@8.5.6) - autoprefixer: 10.4.24(postcss@8.5.6) - browserslist: 4.28.1 - css-blank-pseudo: 8.0.1(postcss@8.5.6) - css-has-pseudo: 8.0.0(postcss@8.5.6) - css-prefers-color-scheme: 11.0.0(postcss@8.5.6) - cssdb: 8.7.1 - postcss: 8.5.6 - postcss-attribute-case-insensitive: 8.0.0(postcss@8.5.6) - postcss-clamp: 4.1.0(postcss@8.5.6) - postcss-color-functional-notation: 8.0.1(postcss@8.5.6) - postcss-color-hex-alpha: 11.0.0(postcss@8.5.6) - postcss-color-rebeccapurple: 11.0.0(postcss@8.5.6) - postcss-custom-media: 12.0.0(postcss@8.5.6) - postcss-custom-properties: 15.0.0(postcss@8.5.6) - postcss-custom-selectors: 9.0.0(postcss@8.5.6) - postcss-dir-pseudo-class: 10.0.0(postcss@8.5.6) - postcss-double-position-gradients: 7.0.0(postcss@8.5.6) - postcss-focus-visible: 11.0.0(postcss@8.5.6) - postcss-focus-within: 10.0.0(postcss@8.5.6) - postcss-font-variant: 5.0.0(postcss@8.5.6) - postcss-gap-properties: 7.0.0(postcss@8.5.6) - postcss-image-set-function: 8.0.0(postcss@8.5.6) - postcss-lab-function: 8.0.1(postcss@8.5.6) - postcss-logical: 9.0.0(postcss@8.5.6) - postcss-nesting: 14.0.0(postcss@8.5.6) - postcss-opacity-percentage: 3.0.0(postcss@8.5.6) - postcss-overflow-shorthand: 7.0.0(postcss@8.5.6) - postcss-page-break: 3.0.4(postcss@8.5.6) - postcss-place: 11.0.0(postcss@8.5.6) - postcss-pseudo-class-any-link: 11.0.0(postcss@8.5.6) - postcss-replace-overflow-wrap: 4.0.0(postcss@8.5.6) - postcss-selector-not: 9.0.0(postcss@8.5.6) - - postcss-pseudo-class-any-link@11.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-reduce-initial@7.0.5(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - caniuse-api: 3.0.0 - postcss: 8.5.6 - - postcss-reduce-transforms@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-replace-overflow-wrap@4.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-reporter@7.1.0(postcss@8.5.6): - dependencies: - picocolors: 1.1.1 - postcss: 8.5.6 - thenby: 1.3.4 - - postcss-safe-parser@7.0.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-selector-not@9.0.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-selector-parser@6.0.10: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-selector-parser@6.1.2: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-selector-parser@7.1.1: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-svgo@7.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - svgo: 4.0.0 - - postcss-unique-selectors@7.0.4(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-value-parser@4.2.0: {} - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - prettier-linter-helpers@1.0.1: - dependencies: - fast-diff: 1.3.0 - - prettier-plugin-organize-imports@4.3.0(prettier@3.8.1)(typescript@5.9.3): - dependencies: - prettier: 3.8.1 - typescript: 5.9.3 - - prettier@2.8.8: - optional: true - - prettier@3.8.1: {} - - pretty-bytes@5.6.0: {} - - pretty-bytes@6.1.1: {} - - pretty-ms@9.3.0: - dependencies: - parse-ms: 4.0.0 - - process-nextick-args@2.0.1: {} - - proto-list@1.2.4: {} - - protocols@2.0.2: {} - - punycode@2.3.1: {} - - qified@0.6.0: - dependencies: - hookified: 1.15.1 - - queue-microtask@1.2.3: {} - - quick-lru@5.1.1: {} - - raf@3.4.1: - dependencies: - performance-now: 2.1.0 - - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - - read-cache@1.0.0: - dependencies: - pify: 2.3.0 - - read-package-up@11.0.0: - dependencies: - find-up-simple: 1.0.1 - read-pkg: 9.0.1 - type-fest: 4.41.0 - - read-package-up@12.0.0: - dependencies: - find-up-simple: 1.0.1 - read-pkg: 10.1.0 - type-fest: 5.4.4 - - read-pkg@10.1.0: - dependencies: - "@types/normalize-package-data": 2.4.4 - normalize-package-data: 8.0.0 - parse-json: 8.3.0 - type-fest: 5.4.4 - unicorn-magic: 0.4.0 - - read-pkg@9.0.1: - dependencies: - "@types/normalize-package-data": 2.4.4 - normalize-package-data: 6.0.2 - parse-json: 8.3.0 - type-fest: 4.41.0 - unicorn-magic: 0.1.0 - - readable-stream@2.3.8: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - - regenerate-unicode-properties@10.2.2: - dependencies: - regenerate: 1.4.2 - - regenerate@1.4.2: {} - - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - - regexpu-core@6.4.0: - dependencies: - regenerate: 1.4.2 - regenerate-unicode-properties: 10.2.2 - regjsgen: 0.8.0 - regjsparser: 0.13.0 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.2.1 - - registry-auth-token@5.1.1: - dependencies: - "@pnpm/npm-conf": 3.0.2 - - regjsgen@0.8.0: {} - - regjsparser@0.13.0: - dependencies: - jsesc: 3.1.0 - - regression@2.0.1: {} - - require-directory@2.1.1: {} - - require-from-string@2.0.2: {} - - require-main-filename@2.0.0: {} - - resolve-alpn@1.2.1: {} - - resolve-dir@1.0.1: - dependencies: - expand-tilde: 2.0.2 - global-modules: 1.0.0 - - resolve-from@4.0.0: {} - - resolve-from@5.0.0: {} - - resolve@1.22.11: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - responselike@4.0.2: - dependencies: - lowercase-keys: 3.0.0 - - restore-cursor@3.1.0: - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - - reusify@1.1.0: {} - - rfdc@1.4.1: {} - - rgbcolor@1.0.1: {} - - rollup@2.79.2: - optionalDependencies: - fsevents: 2.3.3 - - rollup@4.57.1: - dependencies: - "@types/estree": 1.0.8 - optionalDependencies: - "@rollup/rollup-android-arm-eabi": 4.57.1 - "@rollup/rollup-android-arm64": 4.57.1 - "@rollup/rollup-darwin-arm64": 4.57.1 - "@rollup/rollup-darwin-x64": 4.57.1 - "@rollup/rollup-freebsd-arm64": 4.57.1 - "@rollup/rollup-freebsd-x64": 4.57.1 - "@rollup/rollup-linux-arm-gnueabihf": 4.57.1 - "@rollup/rollup-linux-arm-musleabihf": 4.57.1 - "@rollup/rollup-linux-arm64-gnu": 4.57.1 - "@rollup/rollup-linux-arm64-musl": 4.57.1 - "@rollup/rollup-linux-loong64-gnu": 4.57.1 - "@rollup/rollup-linux-loong64-musl": 4.57.1 - "@rollup/rollup-linux-ppc64-gnu": 4.57.1 - "@rollup/rollup-linux-ppc64-musl": 4.57.1 - "@rollup/rollup-linux-riscv64-gnu": 4.57.1 - "@rollup/rollup-linux-riscv64-musl": 4.57.1 - "@rollup/rollup-linux-s390x-gnu": 4.57.1 - "@rollup/rollup-linux-x64-gnu": 4.57.1 - "@rollup/rollup-linux-x64-musl": 4.57.1 - "@rollup/rollup-openbsd-x64": 4.57.1 - "@rollup/rollup-openharmony-arm64": 4.57.1 - "@rollup/rollup-win32-arm64-msvc": 4.57.1 - "@rollup/rollup-win32-ia32-msvc": 4.57.1 - "@rollup/rollup-win32-x64-gnu": 4.57.1 - "@rollup/rollup-win32-x64-msvc": 4.57.1 - fsevents: 2.3.3 - - run-applescript@7.1.0: {} - - run-async@2.4.1: {} - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - rxjs@6.6.7: - dependencies: - tslib: 1.14.1 - - rxjs@7.8.2: - dependencies: - tslib: 2.8.1 - - safe-array-concat@1.1.3: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - isarray: 2.0.5 - - safe-buffer@5.1.2: {} - - safe-buffer@5.2.1: {} - - safe-push-apply@1.0.0: - dependencies: - es-errors: 1.3.0 - isarray: 2.0.5 - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-regex: 1.2.1 - - safer-buffer@2.1.2: {} - - sax@1.4.4: {} - - semantic-release@25.0.3(typescript@5.9.3): - dependencies: - "@semantic-release/commit-analyzer": 13.0.1(semantic-release@25.0.3(typescript@5.9.3)) - "@semantic-release/error": 4.0.0 - "@semantic-release/github": 12.0.6(semantic-release@25.0.3(typescript@5.9.3)) - "@semantic-release/npm": 13.1.4(semantic-release@25.0.3(typescript@5.9.3)) - "@semantic-release/release-notes-generator": 14.1.0(semantic-release@25.0.3(typescript@5.9.3)) - aggregate-error: 5.0.0 - cosmiconfig: 9.0.0(typescript@5.9.3) - debug: 4.4.3 - env-ci: 11.2.0 - execa: 9.6.1 - figures: 6.1.0 - find-versions: 6.0.0 - get-stream: 6.0.1 - git-log-parser: 1.2.1 - hook-std: 4.0.0 - hosted-git-info: 9.0.2 - import-from-esm: 2.0.0 - lodash-es: 4.17.23 - marked: 15.0.12 - marked-terminal: 7.3.0(marked@15.0.12) - micromatch: 4.0.8 - p-each-series: 3.0.0 - p-reduce: 3.0.0 - read-package-up: 12.0.0 - resolve-from: 5.0.0 - semver: 7.7.4 - signale: 1.4.0 - yargs: 18.0.0 - transitivePeerDependencies: - - supports-color - - typescript - - semver-regex@4.0.5: {} - - semver@6.3.1: {} - - semver@7.7.4: {} - - serialize-javascript@6.0.2: - dependencies: - randombytes: 2.1.0 - - set-blocking@2.0.0: {} - - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - - set-proto@1.0.0: - dependencies: - dunder-proto: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - - sharp@0.34.5: - dependencies: - "@img/colour": 1.0.0 - detect-libc: 2.1.2 - semver: 7.7.4 - optionalDependencies: - "@img/sharp-darwin-arm64": 0.34.5 - "@img/sharp-darwin-x64": 0.34.5 - "@img/sharp-libvips-darwin-arm64": 1.2.4 - "@img/sharp-libvips-darwin-x64": 1.2.4 - "@img/sharp-libvips-linux-arm": 1.2.4 - "@img/sharp-libvips-linux-arm64": 1.2.4 - "@img/sharp-libvips-linux-ppc64": 1.2.4 - "@img/sharp-libvips-linux-riscv64": 1.2.4 - "@img/sharp-libvips-linux-s390x": 1.2.4 - "@img/sharp-libvips-linux-x64": 1.2.4 - "@img/sharp-libvips-linuxmusl-arm64": 1.2.4 - "@img/sharp-libvips-linuxmusl-x64": 1.2.4 - "@img/sharp-linux-arm": 0.34.5 - "@img/sharp-linux-arm64": 0.34.5 - "@img/sharp-linux-ppc64": 0.34.5 - "@img/sharp-linux-riscv64": 0.34.5 - "@img/sharp-linux-s390x": 0.34.5 - "@img/sharp-linux-x64": 0.34.5 - "@img/sharp-linuxmusl-arm64": 0.34.5 - "@img/sharp-linuxmusl-x64": 0.34.5 - "@img/sharp-wasm32": 0.34.5 - "@img/sharp-win32-arm64": 0.34.5 - "@img/sharp-win32-ia32": 0.34.5 - "@img/sharp-win32-x64": 0.34.5 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - signal-exit@3.0.7: {} - - signal-exit@4.1.0: {} - - signale@1.4.0: - dependencies: - chalk: 2.4.2 - figures: 2.0.0 - pkg-conf: 2.1.0 - - sirv@3.0.2: - dependencies: - "@polka/url": 1.0.0-next.29 - mrmime: 2.0.1 - totalist: 3.0.1 - - skin-tone@2.0.0: - dependencies: - unicode-emoji-modifier-base: 1.0.0 - - slash@5.1.0: {} - - slice-ansi@4.0.0: - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - smob@1.6.1: {} - - source-map-js@1.2.1: {} - - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - source-map@0.8.0-beta.0: - dependencies: - whatwg-url: 7.1.0 - - sourcemap-codec@1.4.8: {} - - spawn-error-forwarder@1.0.0: {} - - spdx-correct@3.2.0: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.22 - - spdx-exceptions@2.5.0: {} - - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.22 - - spdx-license-ids@3.0.22: {} - - split2@1.0.0: - dependencies: - through2: 2.0.5 - - split2@4.2.0: {} - - stackblur-canvas@2.7.0: {} - - stencil-wormhole@3.4.1: {} - - stop-iteration-iterator@1.1.0: - dependencies: - es-errors: 1.3.0 - internal-slot: 1.1.0 - - stream-combiner2@1.1.1: - dependencies: - duplexer2: 0.1.4 - readable-stream: 2.3.8 - - string-argv@0.3.2: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.5.0 - strip-ansi: 7.1.2 - - string-width@8.2.0: - dependencies: - get-east-asian-width: 1.5.0 - strip-ansi: 7.1.2 - - string.prototype.matchall@4.0.12: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - regexp.prototype.flags: 1.5.4 - set-function-name: 2.0.2 - side-channel: 1.1.0 - - string.prototype.trim@1.2.10: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - has-property-descriptors: 1.0.2 - - string.prototype.trimend@1.0.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string_decoder@1.1.1: - dependencies: - safe-buffer: 5.1.2 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - stringify-object@3.3.0: - dependencies: - get-own-enumerable-property-symbols: 3.0.2 - is-obj: 1.0.1 - is-regexp: 1.0.0 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.2: - dependencies: - ansi-regex: 6.2.2 - - strip-bom@3.0.0: {} - - strip-bom@4.0.0: {} - - strip-comments@2.0.1: {} - - strip-final-newline@2.0.0: {} - - strip-final-newline@3.0.0: {} - - strip-final-newline@4.0.0: {} - - strip-json-comments@2.0.1: {} - - strip-json-comments@3.1.1: {} - - style-mod@4.1.3: {} - - stylehacks@7.0.7(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - stylelint-config-recommended@18.0.0(stylelint@17.3.0(typescript@5.9.3)): - dependencies: - stylelint: 17.3.0(typescript@5.9.3) - - stylelint-config-standard@40.0.0(stylelint@17.3.0(typescript@5.9.3)): - dependencies: - stylelint: 17.3.0(typescript@5.9.3) - stylelint-config-recommended: 18.0.0(stylelint@17.3.0(typescript@5.9.3)) - - stylelint@17.3.0(typescript@5.9.3): - dependencies: - "@csstools/css-calc": 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/css-parser-algorithms": 4.0.0(@csstools/css-tokenizer@4.0.0) - "@csstools/css-syntax-patches-for-csstree": 1.0.27 - "@csstools/css-tokenizer": 4.0.0 - "@csstools/media-query-list-parser": 5.0.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) - "@csstools/selector-resolve-nested": 4.0.0(postcss-selector-parser@7.1.1) - "@csstools/selector-specificity": 6.0.0(postcss-selector-parser@7.1.1) - balanced-match: 3.0.1 - colord: 2.9.3 - cosmiconfig: 9.0.0(typescript@5.9.3) - css-functions-list: 3.3.3 - css-tree: 3.1.0 - debug: 4.4.3 - fast-glob: 3.3.3 - fastest-levenshtein: 1.0.16 - file-entry-cache: 11.1.2 - global-modules: 2.0.0 - globby: 16.1.1 - globjoin: 0.1.4 - html-tags: 5.1.0 - ignore: 7.0.5 - import-meta-resolve: 4.2.0 - imurmurhash: 0.1.4 - is-plain-object: 5.0.0 - known-css-properties: 0.37.0 - mathml-tag-names: 4.0.0 - meow: 14.0.0 - micromatch: 4.0.8 - normalize-path: 3.0.0 - picocolors: 1.1.1 - postcss: 8.5.6 - postcss-safe-parser: 7.0.1(postcss@8.5.6) - postcss-selector-parser: 7.1.1 - postcss-value-parser: 4.2.0 - string-width: 8.2.0 - supports-hyperlinks: 4.4.0 - svg-tags: 1.0.0 - table: 6.9.0 - write-file-atomic: 7.0.0 - transitivePeerDependencies: - - supports-color - - typescript - - sucrase@3.35.1: - dependencies: - "@jridgewell/gen-mapping": 0.3.13 - commander: 4.1.1 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.7 - tinyglobby: 0.2.15 - ts-interface-checker: 0.1.13 - - super-regex@1.1.0: - dependencies: - function-timeout: 1.0.2 - make-asynchronous: 1.0.1 - time-span: 5.1.0 - - supports-color@10.2.2: {} - - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-hyperlinks@3.2.0: - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 - - supports-hyperlinks@4.4.0: - dependencies: - has-flag: 5.0.1 - supports-color: 10.2.2 - - supports-preserve-symlinks-flag@1.0.0: {} - - svg-tags@1.0.0: {} - - svgo@4.0.0: - dependencies: - commander: 11.1.0 - css-select: 5.2.2 - css-tree: 3.1.0 - css-what: 6.2.2 - csso: 5.0.5 - picocolors: 1.1.1 - sax: 1.4.4 - - synckit@0.11.12: - dependencies: - "@pkgr/core": 0.2.9 - - table@6.9.0: - dependencies: - ajv: 8.18.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - tagged-tag@1.0.0: {} - - tailwindcss@3.4.19(yaml@2.8.2): - dependencies: - "@alloc/quick-lru": 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.3 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.7 - lilconfig: 3.1.3 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.1 - postcss: 8.5.6 - postcss-import: 15.1.0(postcss@8.5.6) - postcss-js: 4.1.0(postcss@8.5.6) - postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(yaml@2.8.2) - postcss-nested: 6.2.0(postcss@8.5.6) - postcss-selector-parser: 6.1.2 - resolve: 1.22.11 - sucrase: 3.35.1 - transitivePeerDependencies: - - tsx - - yaml - - temp-dir@2.0.0: {} - - temp-dir@3.0.0: {} - - tempy@0.6.0: - dependencies: - is-stream: 2.0.1 - temp-dir: 2.0.0 - type-fest: 0.16.0 - unique-string: 2.0.0 - - tempy@3.2.0: - dependencies: - is-stream: 3.0.0 - temp-dir: 3.0.0 - type-fest: 2.19.0 - unique-string: 3.0.0 - - terser@5.46.0: - dependencies: - "@jridgewell/source-map": 0.3.11 - acorn: 8.15.0 - commander: 2.20.3 - source-map-support: 0.5.21 - - thenby@1.3.4: {} - - thenify-all@1.6.0: - dependencies: - thenify: 3.3.1 - - thenify@3.3.1: - dependencies: - any-promise: 1.3.0 - - through2@2.0.5: - dependencies: - readable-stream: 2.3.8 - xtend: 4.0.2 - - through@2.3.8: {} - - time-span@5.1.0: - dependencies: - convert-hrtime: 5.0.0 - - tiny-inflate@1.0.3: {} - - tinyexec@1.0.2: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - tinyqueue@2.0.3: {} - - tmp@0.0.33: - dependencies: - os-tmpdir: 1.0.2 - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - totalist@3.0.1: {} - - tr46@0.0.3: {} - - tr46@1.0.1: - dependencies: - punycode: 2.3.1 - - traverse@0.6.8: {} - - ts-api-utils@2.4.0(typescript@5.9.3): - dependencies: - typescript: 5.9.3 - - ts-interface-checker@0.1.13: {} - - tslib@1.14.1: {} - - tslib@2.8.1: {} - - tunnel@0.0.6: {} - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-fest@0.16.0: {} - - type-fest@0.21.3: {} - - type-fest@1.4.0: {} - - type-fest@2.19.0: {} - - type-fest@4.41.0: {} - - type-fest@5.4.4: - dependencies: - tagged-tag: 1.0.0 - - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - typed-array-byte-length@1.0.3: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - - typed-array-byte-offset@1.0.4: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - reflect.getprototypeof: 1.0.10 - - typed-array-length@1.0.7: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - is-typed-array: 1.1.15 - possible-typed-array-names: 1.1.0 - reflect.getprototypeof: 1.0.10 - - typescript-eslint@8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3): - dependencies: - "@typescript-eslint/eslint-plugin": 8.56.0(@typescript-eslint/parser@8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3))(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3) - "@typescript-eslint/parser": 8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3) - "@typescript-eslint/typescript-estree": 8.56.0(typescript@5.9.3) - "@typescript-eslint/utils": 8.56.0(eslint@10.0.0(jiti@1.21.7))(typescript@5.9.3) - eslint: 10.0.0(jiti@1.21.7) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - typescript@5.9.3: {} - - uglify-js@3.19.3: - optional: true - - unbox-primitive@1.1.0: - dependencies: - call-bound: 1.0.4 - has-bigints: 1.1.0 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.1 - - undici-types@7.14.0: {} - - undici@6.23.0: {} - - undici@7.22.0: {} - - unicode-canonical-property-names-ecmascript@2.0.1: {} - - unicode-emoji-modifier-base@1.0.0: {} - - unicode-match-property-ecmascript@2.0.0: - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.1 - unicode-property-aliases-ecmascript: 2.2.0 - - unicode-match-property-value-ecmascript@2.2.1: {} - - unicode-properties@1.4.1: - dependencies: - base64-js: 1.5.1 - unicode-trie: 2.0.0 - - unicode-property-aliases-ecmascript@2.2.0: {} - - unicode-trie@2.0.0: - dependencies: - pako: 0.2.9 - tiny-inflate: 1.0.3 - - unicorn-magic@0.1.0: {} - - unicorn-magic@0.3.0: {} - - unicorn-magic@0.4.0: {} - - unique-string@2.0.0: - dependencies: - crypto-random-string: 2.0.0 - - unique-string@3.0.0: - dependencies: - crypto-random-string: 4.0.0 - - universal-user-agent@7.0.3: {} - - universalify@2.0.1: {} - - unplugin-utils@0.3.1: - dependencies: - pathe: 2.0.3 - picomatch: 4.0.3 - - upath@1.2.0: {} - - update-browserslist-db@1.2.3(browserslist@4.28.1): - dependencies: - browserslist: 4.28.1 - escalade: 3.2.0 - picocolors: 1.1.1 - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - url-join@4.0.1: {} - - url-join@5.0.0: {} - - util-deprecate@1.0.2: {} - - validate-npm-package-license@3.0.4: - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - - vite-dev-rpc@1.1.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)): - dependencies: - birpc: 2.9.0 - vite: 7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2) - vite-hot-client: 2.1.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)) - - vite-hot-client@2.1.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)): - dependencies: - vite: 7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2) - - vite-plugin-codeigniter@2.0.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)): - dependencies: - glob: 11.1.0 - picocolors: 1.1.1 - sharp: 0.34.5 - vite: 7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2) - vite-plugin-static-copy: 3.2.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)) - zod: 4.3.6 - - vite-plugin-inspect@11.3.3(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)): - dependencies: - ansis: 4.2.0 - debug: 4.4.3 - error-stack-parser-es: 1.0.5 - ohash: 2.0.11 - open: 10.2.0 - perfect-debounce: 2.1.0 - sirv: 3.0.2 - unplugin-utils: 0.3.1 - vite: 7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2) - vite-dev-rpc: 1.1.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)) - transitivePeerDependencies: - - supports-color - - vite-plugin-pwa@1.2.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2))(workbox-build@7.4.0)(workbox-window@7.4.0): - dependencies: - debug: 4.4.3 - pretty-bytes: 6.1.1 - tinyglobby: 0.2.15 - vite: 7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2) - workbox-build: 7.4.0 - workbox-window: 7.4.0 - transitivePeerDependencies: - - supports-color - - vite-plugin-static-copy@3.2.0(vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2)): - dependencies: - chokidar: 3.6.0 - p-map: 7.0.4 - picocolors: 1.1.1 - tinyglobby: 0.2.15 - vite: 7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2) - - vite@7.3.1(@types/node@24.7.0)(jiti@1.21.7)(terser@5.46.0)(yaml@2.8.2): - dependencies: - esbuild: 0.27.3 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.57.1 - tinyglobby: 0.2.15 - optionalDependencies: - "@types/node": 24.7.0 - fsevents: 2.3.3 - jiti: 1.21.7 - terser: 5.46.0 - yaml: 2.8.2 - - w3c-keyname@2.2.8: {} - - wavesurfer.js@7.12.1: {} - - wcwidth@1.0.1: - dependencies: - defaults: 1.0.4 - - web-worker@1.2.0: {} - - webidl-conversions@3.0.1: {} - - webidl-conversions@4.0.2: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - whatwg-url@7.1.0: - dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - - which-boxed-primitive@1.1.1: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.2 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - - which-builtin-type@1.2.1: - dependencies: - call-bound: 1.0.4 - function.prototype.name: 1.1.8 - has-tostringtag: 1.0.2 - is-async-function: 2.1.1 - is-date-object: 1.1.0 - is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.2 - is-regex: 1.2.1 - is-weakref: 1.1.1 - isarray: 2.0.5 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.20 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - - which-module@2.0.1: {} - - which-typed-array@1.1.20: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.4 - for-each: 0.3.5 - get-proto: 1.0.1 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - which@1.3.1: - dependencies: - isexe: 2.0.0 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - word-wrap@1.2.5: {} - - wordwrap@1.0.0: {} - - workbox-background-sync@7.4.0: - dependencies: - idb: 7.1.1 - workbox-core: 7.4.0 - - workbox-broadcast-update@7.4.0: - dependencies: - workbox-core: 7.4.0 - - workbox-build@7.4.0: - dependencies: - "@apideck/better-ajv-errors": 0.3.6(ajv@8.18.0) - "@babel/core": 7.29.0 - "@babel/preset-env": 7.29.0(@babel/core@7.29.0) - "@babel/runtime": 7.28.6 - "@rollup/plugin-babel": 5.3.1(@babel/core@7.29.0)(rollup@2.79.2) - "@rollup/plugin-node-resolve": 15.3.1(rollup@2.79.2) - "@rollup/plugin-replace": 2.4.2(rollup@2.79.2) - "@rollup/plugin-terser": 0.4.4(rollup@2.79.2) - "@surma/rollup-plugin-off-main-thread": 2.2.3 - ajv: 8.18.0 - common-tags: 1.8.2 - fast-json-stable-stringify: 2.1.0 - fs-extra: 9.1.0 - glob: 11.1.0 - lodash: 4.17.23 - pretty-bytes: 5.6.0 - rollup: 2.79.2 - source-map: 0.8.0-beta.0 - stringify-object: 3.3.0 - strip-comments: 2.0.1 - tempy: 0.6.0 - upath: 1.2.0 - workbox-background-sync: 7.4.0 - workbox-broadcast-update: 7.4.0 - workbox-cacheable-response: 7.4.0 - workbox-core: 7.4.0 - workbox-expiration: 7.4.0 - workbox-google-analytics: 7.4.0 - workbox-navigation-preload: 7.4.0 - workbox-precaching: 7.4.0 - workbox-range-requests: 7.4.0 - workbox-recipes: 7.4.0 - workbox-routing: 7.4.0 - workbox-strategies: 7.4.0 - workbox-streams: 7.4.0 - workbox-sw: 7.4.0 - workbox-window: 7.4.0 - transitivePeerDependencies: - - "@types/babel__core" - - supports-color - - workbox-cacheable-response@7.4.0: - dependencies: - workbox-core: 7.4.0 - - workbox-core@7.4.0: {} - - workbox-expiration@7.4.0: - dependencies: - idb: 7.1.1 - workbox-core: 7.4.0 - - workbox-google-analytics@7.4.0: - dependencies: - workbox-background-sync: 7.4.0 - workbox-core: 7.4.0 - workbox-routing: 7.4.0 - workbox-strategies: 7.4.0 - - workbox-navigation-preload@7.4.0: - dependencies: - workbox-core: 7.4.0 - - workbox-precaching@7.4.0: - dependencies: - workbox-core: 7.4.0 - workbox-routing: 7.4.0 - workbox-strategies: 7.4.0 - - workbox-range-requests@7.4.0: - dependencies: - workbox-core: 7.4.0 - - workbox-recipes@7.4.0: - dependencies: - workbox-cacheable-response: 7.4.0 - workbox-core: 7.4.0 - workbox-expiration: 7.4.0 - workbox-precaching: 7.4.0 - workbox-routing: 7.4.0 - workbox-strategies: 7.4.0 - - workbox-routing@7.4.0: - dependencies: - workbox-core: 7.4.0 - - workbox-strategies@7.4.0: - dependencies: - workbox-core: 7.4.0 - - workbox-streams@7.4.0: - dependencies: - workbox-core: 7.4.0 - workbox-routing: 7.4.0 - - workbox-sw@7.4.0: {} - - workbox-window@7.4.0: - dependencies: - "@types/trusted-types": 2.0.7 - workbox-core: 7.4.0 - - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.1.2 - - wrappy@1.0.2: {} - - write-file-atomic@7.0.0: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 4.1.0 - - wsl-utils@0.1.0: - dependencies: - is-wsl: 3.1.1 - - xml-formatter@3.6.7: - dependencies: - xml-parser-xo: 4.1.5 - - xml-parser-xo@4.1.5: {} - - xmldoc@2.0.3: - dependencies: - sax: 1.4.4 - - xtend@4.0.2: {} - - y18n@4.0.3: {} - - y18n@5.0.8: {} - - yallist@3.1.1: {} - - yaml@2.8.2: {} - - yargs-parser@18.1.3: - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - - yargs-parser@20.2.9: {} - - yargs-parser@21.1.1: {} - - yargs-parser@22.0.0: {} - - yargs@15.4.1: - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.1 - y18n: 4.0.3 - yargs-parser: 18.1.3 - - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yargs@18.0.0: - dependencies: - cliui: 9.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - string-width: 7.2.0 - y18n: 5.0.8 - yargs-parser: 22.0.0 - - yocto-queue@0.1.0: {} - - yoctocolors@2.1.2: {} - - zod@4.3.6: {} diff --git a/postcss.config.cjs b/postcss.config.js similarity index 82% rename from postcss.config.cjs rename to postcss.config.js index ec20059e..3af612e6 100644 --- a/postcss.config.cjs +++ b/postcss.config.js @@ -3,9 +3,10 @@ module.exports = { plugins: [ require("postcss-reporter"), + require("tailwindcss/nesting")(require("postcss-nesting")), require("tailwindcss"), require("postcss-preset-env")({ - stage: 4, + stage: 1, features: { "nesting-rules": false }, }), ...(process.env.NODE_ENV === "production" diff --git a/preload.php b/preload.php index 5e9937cf..5840d804 100644 --- a/preload.php +++ b/preload.php @@ -1,10 +1,5 @@ > Paths to preload. */ private array $paths = [ [ - 'include' => __DIR__ . '/vendor/codeigniter4/framework/system', // Change this path if using manual installation + 'include' => __DIR__ . '/vendor/codeigniter4/framework/system', 'exclude' => [ // Not needed if you don't use them. '/system/Database/OCI8/', '/system/Database/Postgre/', - '/system/Database/SQLite3/', '/system/Database/SQLSRV/', - // Not needed for web apps. + // Not needed. '/system/Database/Seeder.php', '/system/Test/', + '/system/Language/', '/system/CLI/', '/system/Commands/', '/system/Publisher/', '/system/ComposerScripts.php', - // Not Class/Function files. - '/system/Config/Routes.php', - '/system/Language/', - '/system/bootstrap.php', - '/system/util_bootstrap.php', - '/system/rewrite.php', '/Views/', // Errors occur. + '/system/Config/Routes.php', '/system/ThirdParty/', ], ], @@ -73,6 +75,12 @@ class preload $this->loadAutoloader(); } + private function loadAutoloader(): void + { + $paths = new Config\Paths(); + require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; + } + /** * Load PHP files. */ @@ -80,8 +88,12 @@ class preload { foreach ($this->paths as $path) { $directory = new RecursiveDirectoryIterator($path['include']); - $fullTree = new RecursiveIteratorIterator($directory); - $phpFiles = new RegexIterator($fullTree, '/.+((? $file) { foreach ($path['exclude'] as $exclude) { @@ -91,20 +103,10 @@ class preload } require_once $file[0]; - // Uncomment only for debugging (to inspect which files are included). - // Never use this in production - preload scripts must not generate output. - // echo 'Loaded: ' . $file[0] . "\n"; + echo 'Loaded: ' . $file[0] . "\n"; } } } - - private function loadAutoloader(): void - { - $paths = new Paths(); - require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'Boot.php'; - - Boot::preload($paths); - } } (new preload())->load(); diff --git a/public/.htaccess b/public/.htaccess index 396272bc..9fe97382 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,5 +1,5 @@ # Disable directory browsing -Options -Indexes +Options All -Indexes # ---------------------------------------------------------------------- # Rewrite engine @@ -45,5 +45,5 @@ Options -Indexes # Disable server signature start -ServerSignature Off + ServerSignature Off # Disable server signature end diff --git a/public/index.php b/public/index.php index 070db6ca..cc758a8b 100644 --- a/public/index.php +++ b/public/index.php @@ -2,42 +2,15 @@ declare(strict_types=1); -use CodeIgniter\Boot; +use CodeIgniter\Config\DotEnv; use Config\Paths; - -/* - *--------------------------------------------------------------- - * CHECK PHP VERSION - *--------------------------------------------------------------- - */ - -$minPhpVersion = '8.5'; // If you update this, don't forget to update `spark`. -if (version_compare(PHP_VERSION, $minPhpVersion, '<')) { - $message = sprintf( - 'Your PHP version must be %s or higher to run CodeIgniter. Current version: %s', - $minPhpVersion, - PHP_VERSION, - ); - - header('HTTP/1.1 503 Service Unavailable.', true, 503); - echo $message; - - exit(1); -} - -/* - *--------------------------------------------------------------- - * SET THE CURRENT DIRECTORY - *--------------------------------------------------------------- - */ +use Config\Services; // Path to the front controller (this file) define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR); // Ensure the current directory is pointing to the front controller's directory -if (getcwd() . DIRECTORY_SEPARATOR !== FCPATH) { - chdir(FCPATH); -} +chdir(FCPATH); /* *--------------------------------------------------------------- @@ -48,14 +21,41 @@ if (getcwd() . DIRECTORY_SEPARATOR !== FCPATH) { * and fires up an environment-specific bootstrapping. */ -// LOAD OUR PATHS CONFIG FILE +// Load our paths config file // This is the line that might need to be changed, depending on your folder structure. require FCPATH . '../app/Config/Paths.php'; // ^^^ Change this line if you move your application folder $paths = new Paths(); -// LOAD THE FRAMEWORK BOOTSTRAP FILE -require $paths->systemDirectory . '/Boot.php'; +// Location of the framework bootstrap file. +require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; -exit(Boot::bootWeb($paths)); +// Load environment settings from .env files into $_SERVER and $_ENV +require_once SYSTEMPATH . 'Config/DotEnv.php'; +(new DotEnv(ROOTPATH))->load(); + +/* + * --------------------------------------------------------------- + * GRAB OUR CODEIGNITER INSTANCE + * --------------------------------------------------------------- + * + * The CodeIgniter class contains the core functionality to make + * the application run, and does all of the dirty work to get + * the pieces all working together. + */ + +$app = Services::codeigniter(); +$app->initialize(); +$context = is_cli() ? 'php-cli' : 'web'; +$app->setContext($context); + +/* + *--------------------------------------------------------------- + * LAUNCH THE APPLICATION + *--------------------------------------------------------------- + * Now that everything is setup, it's time to actually fire + * up the engines and make this app do its thang. + */ + +$app->run(); diff --git a/resources/static/images/castopod-avatar.jpg b/public/media/castopod-avatar.jpg similarity index 100% rename from resources/static/images/castopod-avatar.jpg rename to public/media/castopod-avatar.jpg diff --git a/public/media/castopod-avatar_medium.webp b/public/media/castopod-avatar_medium.webp new file mode 100644 index 00000000..910a2b35 Binary files /dev/null and b/public/media/castopod-avatar_medium.webp differ diff --git a/public/media/castopod-avatar_thumbnail.webp b/public/media/castopod-avatar_thumbnail.webp new file mode 100644 index 00000000..b0625dc0 Binary files /dev/null and b/public/media/castopod-avatar_thumbnail.webp differ diff --git a/public/media/castopod-avatar_tiny.webp b/public/media/castopod-avatar_tiny.webp new file mode 100644 index 00000000..21cc75d8 Binary files /dev/null and b/public/media/castopod-avatar_tiny.webp differ diff --git a/resources/static/images/castopod-banner-amber.jpg b/public/media/castopod-banner-amber.jpg similarity index 100% rename from resources/static/images/castopod-banner-amber.jpg rename to public/media/castopod-banner-amber.jpg diff --git a/public/media/castopod-banner-amber_federation.jpg b/public/media/castopod-banner-amber_federation.jpg new file mode 100644 index 00000000..425305f3 Binary files /dev/null and b/public/media/castopod-banner-amber_federation.jpg differ diff --git a/public/media/castopod-banner-amber_medium.webp b/public/media/castopod-banner-amber_medium.webp new file mode 100644 index 00000000..234ec532 Binary files /dev/null and b/public/media/castopod-banner-amber_medium.webp differ diff --git a/public/media/castopod-banner-amber_small.webp b/public/media/castopod-banner-amber_small.webp new file mode 100644 index 00000000..8c9ec454 Binary files /dev/null and b/public/media/castopod-banner-amber_small.webp differ diff --git a/resources/static/images/castopod-banner-crimson.jpg b/public/media/castopod-banner-crimson.jpg similarity index 100% rename from resources/static/images/castopod-banner-crimson.jpg rename to public/media/castopod-banner-crimson.jpg diff --git a/public/media/castopod-banner-crimson_federation.jpg b/public/media/castopod-banner-crimson_federation.jpg new file mode 100644 index 00000000..a016c399 Binary files /dev/null and b/public/media/castopod-banner-crimson_federation.jpg differ diff --git a/public/media/castopod-banner-crimson_medium.webp b/public/media/castopod-banner-crimson_medium.webp new file mode 100644 index 00000000..48589283 Binary files /dev/null and b/public/media/castopod-banner-crimson_medium.webp differ diff --git a/public/media/castopod-banner-crimson_small.webp b/public/media/castopod-banner-crimson_small.webp new file mode 100644 index 00000000..1291f73b Binary files /dev/null and b/public/media/castopod-banner-crimson_small.webp differ diff --git a/resources/static/images/castopod-banner-jacaranda.jpg b/public/media/castopod-banner-jacaranda.jpg similarity index 100% rename from resources/static/images/castopod-banner-jacaranda.jpg rename to public/media/castopod-banner-jacaranda.jpg diff --git a/public/media/castopod-banner-jacaranda_federation.jpg b/public/media/castopod-banner-jacaranda_federation.jpg new file mode 100644 index 00000000..33eada3c Binary files /dev/null and b/public/media/castopod-banner-jacaranda_federation.jpg differ diff --git a/public/media/castopod-banner-jacaranda_medium.webp b/public/media/castopod-banner-jacaranda_medium.webp new file mode 100644 index 00000000..ffca50ee Binary files /dev/null and b/public/media/castopod-banner-jacaranda_medium.webp differ diff --git a/public/media/castopod-banner-jacaranda_small.webp b/public/media/castopod-banner-jacaranda_small.webp new file mode 100644 index 00000000..b1154d22 Binary files /dev/null and b/public/media/castopod-banner-jacaranda_small.webp differ diff --git a/resources/static/images/castopod-banner-lake.jpg b/public/media/castopod-banner-lake.jpg similarity index 100% rename from resources/static/images/castopod-banner-lake.jpg rename to public/media/castopod-banner-lake.jpg diff --git a/public/media/castopod-banner-lake_federation.jpg b/public/media/castopod-banner-lake_federation.jpg new file mode 100644 index 00000000..f7527948 Binary files /dev/null and b/public/media/castopod-banner-lake_federation.jpg differ diff --git a/public/media/castopod-banner-lake_medium.webp b/public/media/castopod-banner-lake_medium.webp new file mode 100644 index 00000000..4dcd70df Binary files /dev/null and b/public/media/castopod-banner-lake_medium.webp differ diff --git a/public/media/castopod-banner-lake_small.webp b/public/media/castopod-banner-lake_small.webp new file mode 100644 index 00000000..b3e5c539 Binary files /dev/null and b/public/media/castopod-banner-lake_small.webp differ diff --git a/resources/static/images/castopod-banner-onyx.jpg b/public/media/castopod-banner-onyx.jpg similarity index 100% rename from resources/static/images/castopod-banner-onyx.jpg rename to public/media/castopod-banner-onyx.jpg diff --git a/public/media/castopod-banner-onyx_federation.jpg b/public/media/castopod-banner-onyx_federation.jpg new file mode 100644 index 00000000..73e4423a Binary files /dev/null and b/public/media/castopod-banner-onyx_federation.jpg differ diff --git a/public/media/castopod-banner-onyx_medium.webp b/public/media/castopod-banner-onyx_medium.webp new file mode 100644 index 00000000..189f77f5 Binary files /dev/null and b/public/media/castopod-banner-onyx_medium.webp differ diff --git a/public/media/castopod-banner-onyx_small.webp b/public/media/castopod-banner-onyx_small.webp new file mode 100644 index 00000000..81bd7fff Binary files /dev/null and b/public/media/castopod-banner-onyx_small.webp differ diff --git a/resources/static/images/castopod-banner-pine.jpg b/public/media/castopod-banner-pine.jpg similarity index 100% rename from resources/static/images/castopod-banner-pine.jpg rename to public/media/castopod-banner-pine.jpg diff --git a/public/media/castopod-banner-pine_federation.jpg b/public/media/castopod-banner-pine_federation.jpg new file mode 100644 index 00000000..9e9df5cb Binary files /dev/null and b/public/media/castopod-banner-pine_federation.jpg differ diff --git a/public/media/castopod-banner-pine_medium.webp b/public/media/castopod-banner-pine_medium.webp new file mode 100644 index 00000000..6371a5e5 Binary files /dev/null and b/public/media/castopod-banner-pine_medium.webp differ diff --git a/public/media/castopod-banner-pine_small.webp b/public/media/castopod-banner-pine_small.webp new file mode 100644 index 00000000..ac43b616 Binary files /dev/null and b/public/media/castopod-banner-pine_small.webp differ diff --git a/public/media/index.html b/public/media/index.html index cf672743..eebf8ecb 100644 --- a/public/media/index.html +++ b/public/media/index.html @@ -1,4 +1,4 @@ - + 403 Forbidden diff --git a/public/media/persons/index.html b/public/media/persons/index.html index cf672743..e69de29b 100644 --- a/public/media/persons/index.html +++ b/public/media/persons/index.html @@ -1,9 +0,0 @@ - - - - 403 Forbidden - - -

    Directory access is forbidden.

    - - diff --git a/public/media/podcasts/index.html b/public/media/podcasts/index.html deleted file mode 100644 index cf672743..00000000 --- a/public/media/podcasts/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - 403 Forbidden - - -

    Directory access is forbidden.

    - - diff --git a/rector.php b/rector.php index 9fb15216..881a5ebd 100644 --- a/rector.php +++ b/rector.php @@ -2,32 +2,50 @@ declare(strict_types=1); -use Rector\CodeQuality\Rector\ClassMethod\ExplicitReturnNullRector; +use Rector\CodeQuality\Rector\PropertyFetch\ExplicitMethodCallOverMagicGetSetRector; +use Rector\CodingStyle\Rector\ClassMethod\UnSpreadOperatorRector; use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector; +use Rector\CodingStyle\Rector\FuncCall\ConsistentPregDelimiterRector; use Rector\CodingStyle\Rector\Stmt\NewlineAfterStatementRector; -use Rector\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector; +use Rector\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector; use Rector\Config\RectorConfig; -use Rector\DeadCode\Rector\If_\UnwrapFutureCompatibleIfPhpVersionRector; -use Rector\DeadCode\Rector\Stmt\RemoveUnreachableStatementRector; +use Rector\Core\ValueObject\PhpVersion; use Rector\EarlyReturn\Rector\If_\ChangeOrIfContinueToMultiContinueRector; +use Rector\EarlyReturn\Rector\If_\ChangeOrIfReturnToEarlyReturnRector; use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector; -use Rector\ValueObject\PhpVersion; +use Rector\Set\ValueObject\SetList; -return RectorConfig::configure() - ->withPaths([__DIR__ . '/app', __DIR__ . '/modules', __DIR__ . '/tests', __DIR__ . '/public']) - ->withBootstrapFiles([__DIR__ . '/vendor/codeigniter4/framework/system/Test/bootstrap.php']) - ->withPhpVersion(PhpVersion::PHP_85) - ->withPhpSets(php85: true) - ->withPreparedSets( - typeDeclarations: true, - codeQuality: true, - codingStyle: true, - earlyReturn: true, - deadCode: true, - ) - ->withImportNames(true, true, true, true) - ->withSkip([ +return static function (RectorConfig $rectorConfig): void { + // get parameters + $rectorConfig->paths([ + __DIR__ . '/app', + __DIR__ . '/modules', + __DIR__ . '/tests', + __DIR__ . '/public', + ]); + + // do you need to include constants, class aliases or custom autoloader? files listed will be executed + $rectorConfig->bootstrapFiles([ + __DIR__ . '/vendor/codeigniter4/framework/system/Test/bootstrap.php', + ]); + + // Define what rule sets will be applied + $rectorConfig->sets([SetList::PHP_80, + SetList::TYPE_DECLARATION, + SetList::TYPE_DECLARATION_STRICT, + SetList::CODE_QUALITY, + SetList::CODING_STYLE, + SetList::EARLY_RETURN, + SetList::DEAD_CODE, + ]); + + // auto import fully qualified class names + $rectorConfig->importNames(); + + $rectorConfig->phpVersion(PhpVersion::PHP_80); + + $rectorConfig->skip([ // .mp3 files were somehow processed by rector, so skip all media files __DIR__ . '/public/media/*', @@ -37,23 +55,32 @@ return RectorConfig::configure() __DIR__ . '/modules/Admin/Language/*/PersonsTaxonomy.php', // skip rules from used sets + ChangeOrIfReturnToEarlyReturnRector::class, ChangeOrIfContinueToMultiContinueRector::class, EncapsedStringsToSprintfRector::class, + UnSpreadOperatorRector::class, + ExplicitMethodCallOverMagicGetSetRector::class, RemoveExtraParametersRector::class, - UnwrapFutureCompatibleIfPhpVersionRector::class, - ExplicitReturnNullRector::class, // skip rule in specific directory StringClassNameToClassConstantRector::class => [ __DIR__ . '/app/Language/*', __DIR__ . '/modules/*/Language/*', ], - SimplifyQuoteEscapeRector::class => [__DIR__ . '/app/Language/*', __DIR__ . '/modules/*/Language/*'], - - NewlineAfterStatementRector::class => [__DIR__ . '/app/Views'], - - RemoveUnreachableStatementRector::class => [ - __DIR__ . '/modules/Install/Controllers/InstallController.php', + SymplifyQuoteEscapeRector::class => [ + __DIR__ . '/app/Language/*', + __DIR__ . '/modules/*/Language/*', ], - ]) - ->withPHPStanConfigs([__DIR__ . '/phpstan.neon', 'vendor/codeigniter/phpstan-codeigniter/extension.neon']); + + NewlineAfterStatementRector::class => [ + __DIR__ . '/app/Views', + ] + ]); + + // Path to phpstan with extensions, that PHPStan in Rector uses to determine types + $rectorConfig->phpstanConfig(__DIR__ . '/phpstan.neon'); + + $rectorConfig->ruleWithConfiguration(ConsistentPregDelimiterRector::class, [ + ConsistentPregDelimiterRector::DELIMITER => '~', + ]); +}; diff --git a/resources/icons/custom/_index.php b/resources/icons/custom/_index.php deleted file mode 100644 index 0ef2821e..00000000 --- a/resources/icons/custom/_index.php +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/_index.php b/resources/icons/funding/_index.php deleted file mode 100644 index f939dcca..00000000 --- a/resources/icons/funding/_index.php +++ /dev/null @@ -1,19 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/default.svg b/resources/icons/funding/default.svg deleted file mode 100644 index 7dd88909..00000000 --- a/resources/icons/funding/default.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/donorbox.svg b/resources/icons/funding/donorbox.svg deleted file mode 100644 index a9102a6f..00000000 --- a/resources/icons/funding/donorbox.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/gofundme.svg b/resources/icons/funding/gofundme.svg deleted file mode 100755 index 5cee4579..00000000 --- a/resources/icons/funding/gofundme.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/helloasso.svg b/resources/icons/funding/helloasso.svg deleted file mode 100755 index 381aefef..00000000 --- a/resources/icons/funding/helloasso.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/indiegogo.svg b/resources/icons/funding/indiegogo.svg deleted file mode 100755 index 6cad95a0..00000000 --- a/resources/icons/funding/indiegogo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/kickstarter.svg b/resources/icons/funding/kickstarter.svg deleted file mode 100755 index 9be7ebac..00000000 --- a/resources/icons/funding/kickstarter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/kisskissbankbank.svg b/resources/icons/funding/kisskissbankbank.svg deleted file mode 100755 index aafd6f4c..00000000 --- a/resources/icons/funding/kisskissbankbank.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/kofi.svg b/resources/icons/funding/kofi.svg deleted file mode 100644 index 0bcbc636..00000000 --- a/resources/icons/funding/kofi.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/liberapay.svg b/resources/icons/funding/liberapay.svg deleted file mode 100755 index 79b03686..00000000 --- a/resources/icons/funding/liberapay.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/patreon.svg b/resources/icons/funding/patreon.svg deleted file mode 100755 index 0bf9b7f0..00000000 --- a/resources/icons/funding/patreon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/paypal.svg b/resources/icons/funding/paypal.svg deleted file mode 100755 index 9f3be76a..00000000 --- a/resources/icons/funding/paypal.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/tipeee.svg b/resources/icons/funding/tipeee.svg deleted file mode 100755 index 0c346332..00000000 --- a/resources/icons/funding/tipeee.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/funding/ulule.svg b/resources/icons/funding/ulule.svg deleted file mode 100755 index 72f1a65a..00000000 --- a/resources/icons/funding/ulule.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/_index.php b/resources/icons/podcasting/_index.php deleted file mode 100644 index 562854ec..00000000 --- a/resources/icons/podcasting/_index.php +++ /dev/null @@ -1,48 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/antennapod.svg b/resources/icons/podcasting/antennapod.svg deleted file mode 100755 index 044712e6..00000000 --- a/resources/icons/podcasting/antennapod.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/anytime.svg b/resources/icons/podcasting/anytime.svg deleted file mode 100644 index 14f22a8b..00000000 --- a/resources/icons/podcasting/anytime.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/apple.svg b/resources/icons/podcasting/apple.svg deleted file mode 100755 index 74f3efc7..00000000 --- a/resources/icons/podcasting/apple.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/blubrry.svg b/resources/icons/podcasting/blubrry.svg deleted file mode 100755 index ca2a4da4..00000000 --- a/resources/icons/podcasting/blubrry.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/breaker.svg b/resources/icons/podcasting/breaker.svg deleted file mode 100755 index d4447648..00000000 --- a/resources/icons/podcasting/breaker.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/breez.svg b/resources/icons/podcasting/breez.svg deleted file mode 100644 index 905542ac..00000000 --- a/resources/icons/podcasting/breez.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/castamatic.svg b/resources/icons/podcasting/castamatic.svg deleted file mode 100644 index e0914121..00000000 --- a/resources/icons/podcasting/castamatic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/castbox.svg b/resources/icons/podcasting/castbox.svg deleted file mode 100755 index c9f27fae..00000000 --- a/resources/icons/podcasting/castbox.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/castopod.svg b/resources/icons/podcasting/castopod.svg deleted file mode 100755 index b0d4374d..00000000 --- a/resources/icons/podcasting/castopod.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/castro.svg b/resources/icons/podcasting/castro.svg deleted file mode 100755 index 0e075b05..00000000 --- a/resources/icons/podcasting/castro.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/deezer.svg b/resources/icons/podcasting/deezer.svg deleted file mode 100755 index bcd3b7b3..00000000 --- a/resources/icons/podcasting/deezer.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/default.svg b/resources/icons/podcasting/default.svg deleted file mode 100644 index 6437d60d..00000000 --- a/resources/icons/podcasting/default.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/episodes-fm.svg b/resources/icons/podcasting/episodes-fm.svg deleted file mode 100644 index e5ed1e34..00000000 --- a/resources/icons/podcasting/episodes-fm.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/fountain.svg b/resources/icons/podcasting/fountain.svg deleted file mode 100644 index 796047e7..00000000 --- a/resources/icons/podcasting/fountain.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/fyyd.svg b/resources/icons/podcasting/fyyd.svg deleted file mode 100755 index 696d4983..00000000 --- a/resources/icons/podcasting/fyyd.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/google.svg b/resources/icons/podcasting/google.svg deleted file mode 100755 index ecd0e555..00000000 --- a/resources/icons/podcasting/google.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/gpodder.svg b/resources/icons/podcasting/gpodder.svg deleted file mode 100644 index b2b4b86d..00000000 --- a/resources/icons/podcasting/gpodder.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/ivoox.svg b/resources/icons/podcasting/ivoox.svg deleted file mode 100755 index 8cd43cb6..00000000 --- a/resources/icons/podcasting/ivoox.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/listennotes.svg b/resources/icons/podcasting/listennotes.svg deleted file mode 100755 index f5336785..00000000 --- a/resources/icons/podcasting/listennotes.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/overcast.svg b/resources/icons/podcasting/overcast.svg deleted file mode 100755 index 0fef49c4..00000000 --- a/resources/icons/podcasting/overcast.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/playerfm.svg b/resources/icons/podcasting/playerfm.svg deleted file mode 100755 index fe15dc7a..00000000 --- a/resources/icons/podcasting/playerfm.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/plink.svg b/resources/icons/podcasting/plink.svg deleted file mode 100644 index f300d7b2..00000000 --- a/resources/icons/podcasting/plink.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/pocketcasts.svg b/resources/icons/podcasting/pocketcasts.svg deleted file mode 100755 index 1815c259..00000000 --- a/resources/icons/podcasting/pocketcasts.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podbean.svg b/resources/icons/podcasting/podbean.svg deleted file mode 100755 index dc522606..00000000 --- a/resources/icons/podcasting/podbean.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podcastaddict.svg b/resources/icons/podcasting/podcastaddict.svg deleted file mode 100755 index c16a756d..00000000 --- a/resources/icons/podcasting/podcastaddict.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podcastguru.svg b/resources/icons/podcasting/podcastguru.svg deleted file mode 100644 index ea61e070..00000000 --- a/resources/icons/podcasting/podcastguru.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podcastindex.svg b/resources/icons/podcasting/podcastindex.svg deleted file mode 100755 index 40659726..00000000 --- a/resources/icons/podcasting/podcastindex.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podchaser.svg b/resources/icons/podcasting/podchaser.svg deleted file mode 100755 index f3fd817b..00000000 --- a/resources/icons/podcasting/podchaser.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podcloud.svg b/resources/icons/podcasting/podcloud.svg deleted file mode 100755 index ab39751b..00000000 --- a/resources/icons/podcasting/podcloud.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podfriend.svg b/resources/icons/podcasting/podfriend.svg deleted file mode 100755 index 026b66af..00000000 --- a/resources/icons/podcasting/podfriend.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podinstall.svg b/resources/icons/podcasting/podinstall.svg deleted file mode 100755 index 773cef9b..00000000 --- a/resources/icons/podcasting/podinstall.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podlink.svg b/resources/icons/podcasting/podlink.svg deleted file mode 100755 index 44c9abfb..00000000 --- a/resources/icons/podcasting/podlink.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podlp.svg b/resources/icons/podcasting/podlp.svg deleted file mode 100644 index 55fcc6a1..00000000 --- a/resources/icons/podcasting/podlp.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podnews.svg b/resources/icons/podcasting/podnews.svg deleted file mode 100644 index fd9302c8..00000000 --- a/resources/icons/podcasting/podnews.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podtail.svg b/resources/icons/podcasting/podtail.svg deleted file mode 100755 index 222d9086..00000000 --- a/resources/icons/podcasting/podtail.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/podverse.svg b/resources/icons/podcasting/podverse.svg deleted file mode 100755 index e823ae45..00000000 --- a/resources/icons/podcasting/podverse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/radiopublic.svg b/resources/icons/podcasting/radiopublic.svg deleted file mode 100755 index 5c6e8893..00000000 --- a/resources/icons/podcasting/radiopublic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/sphinxchat.svg b/resources/icons/podcasting/sphinxchat.svg deleted file mode 100644 index b02f3575..00000000 --- a/resources/icons/podcasting/sphinxchat.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/spotify.svg b/resources/icons/podcasting/spotify.svg deleted file mode 100755 index 2068709c..00000000 --- a/resources/icons/podcasting/spotify.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/spreaker.svg b/resources/icons/podcasting/spreaker.svg deleted file mode 100755 index dcb7573f..00000000 --- a/resources/icons/podcasting/spreaker.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/stitcher.svg b/resources/icons/podcasting/stitcher.svg deleted file mode 100755 index 50541d55..00000000 --- a/resources/icons/podcasting/stitcher.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/truefans.svg b/resources/icons/podcasting/truefans.svg deleted file mode 100644 index e8aa9c14..00000000 --- a/resources/icons/podcasting/truefans.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/tsacdop.svg b/resources/icons/podcasting/tsacdop.svg deleted file mode 100644 index 680bda13..00000000 --- a/resources/icons/podcasting/tsacdop.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/tunein.svg b/resources/icons/podcasting/tunein.svg deleted file mode 100755 index 2e97932b..00000000 --- a/resources/icons/podcasting/tunein.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/podcasting/youtube-music.svg b/resources/icons/podcasting/youtube-music.svg deleted file mode 100755 index 55b6d3dd..00000000 --- a/resources/icons/podcasting/youtube-music.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/_index.php b/resources/icons/social/_index.php deleted file mode 100644 index 72ef25ca..00000000 --- a/resources/icons/social/_index.php +++ /dev/null @@ -1,29 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/castopod.svg b/resources/icons/social/castopod.svg deleted file mode 100755 index b0d4374d..00000000 --- a/resources/icons/social/castopod.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/default.svg b/resources/icons/social/default.svg deleted file mode 100644 index 80fa3727..00000000 --- a/resources/icons/social/default.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/discord.svg b/resources/icons/social/discord.svg deleted file mode 100644 index b58f33e9..00000000 --- a/resources/icons/social/discord.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/discourse.svg b/resources/icons/social/discourse.svg deleted file mode 100644 index b8f621c7..00000000 --- a/resources/icons/social/discourse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/facebook.svg b/resources/icons/social/facebook.svg deleted file mode 100755 index 5246848b..00000000 --- a/resources/icons/social/facebook.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/funkwhale.svg b/resources/icons/social/funkwhale.svg deleted file mode 100755 index 8ec1da29..00000000 --- a/resources/icons/social/funkwhale.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/instagram.svg b/resources/icons/social/instagram.svg deleted file mode 100755 index 18f914d8..00000000 --- a/resources/icons/social/instagram.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/linkedin.svg b/resources/icons/social/linkedin.svg deleted file mode 100755 index 06cc775d..00000000 --- a/resources/icons/social/linkedin.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/mastodon.svg b/resources/icons/social/mastodon.svg deleted file mode 100755 index ea82e727..00000000 --- a/resources/icons/social/mastodon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/matrix.svg b/resources/icons/social/matrix.svg deleted file mode 100644 index ae72a3bd..00000000 --- a/resources/icons/social/matrix.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/misskey.svg b/resources/icons/social/misskey.svg deleted file mode 100644 index bd256f34..00000000 --- a/resources/icons/social/misskey.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/mobilizon.svg b/resources/icons/social/mobilizon.svg deleted file mode 100755 index 55166c3c..00000000 --- a/resources/icons/social/mobilizon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/peertube.svg b/resources/icons/social/peertube.svg deleted file mode 100755 index 07e78d42..00000000 --- a/resources/icons/social/peertube.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/pixelfed.svg b/resources/icons/social/pixelfed.svg deleted file mode 100755 index 70d7f222..00000000 --- a/resources/icons/social/pixelfed.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/pleroma.svg b/resources/icons/social/pleroma.svg deleted file mode 100644 index 06795c62..00000000 --- a/resources/icons/social/pleroma.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/plume.svg b/resources/icons/social/plume.svg deleted file mode 100755 index 17a3e787..00000000 --- a/resources/icons/social/plume.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/reddit.svg b/resources/icons/social/reddit.svg deleted file mode 100755 index c6f879fe..00000000 --- a/resources/icons/social/reddit.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/slack.svg b/resources/icons/social/slack.svg deleted file mode 100755 index 4bddffc1..00000000 --- a/resources/icons/social/slack.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/telegram.svg b/resources/icons/social/telegram.svg deleted file mode 100644 index 8c1bb674..00000000 --- a/resources/icons/social/telegram.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/threads.svg b/resources/icons/social/threads.svg deleted file mode 100644 index 691d7276..00000000 --- a/resources/icons/social/threads.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/tiktok.svg b/resources/icons/social/tiktok.svg deleted file mode 100755 index c68b6645..00000000 --- a/resources/icons/social/tiktok.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/twitch.svg b/resources/icons/social/twitch.svg deleted file mode 100755 index 14747c46..00000000 --- a/resources/icons/social/twitch.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/twitter.svg b/resources/icons/social/twitter.svg deleted file mode 100755 index 1d17015b..00000000 --- a/resources/icons/social/twitter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/writefreely.svg b/resources/icons/social/writefreely.svg deleted file mode 100755 index 05965a88..00000000 --- a/resources/icons/social/writefreely.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/x.svg b/resources/icons/social/x.svg deleted file mode 100755 index 9da09775..00000000 --- a/resources/icons/social/x.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/social/youtube.svg b/resources/icons/social/youtube.svg deleted file mode 100755 index 279e6b32..00000000 --- a/resources/icons/social/youtube.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/js/_modules/FieldArray.ts b/resources/js/_modules/FieldArray.ts deleted file mode 100644 index 05baad4e..00000000 --- a/resources/js/_modules/FieldArray.ts +++ /dev/null @@ -1,159 +0,0 @@ -import Tooltip from "./Tooltip"; - -const FieldArray = (): void => { - const fieldArrays: NodeListOf = - document.querySelectorAll("[data-field-array]"); - - for (let i = 0; i < fieldArrays.length; i++) { - const fieldArray = fieldArrays[i]; - const fieldArrayContainer = fieldArray.querySelector( - "[data-field-array-container]" - ); - const items: NodeListOf = fieldArray.querySelectorAll( - "[data-field-array-item]" - ); - const addButton = fieldArray.querySelector( - "button[data-field-array-add]" - ) as HTMLButtonElement; - - const deleteButtons: NodeListOf = - fieldArray.querySelectorAll("[data-field-array-delete]"); - - deleteButtons.forEach((deleteBtn) => { - deleteBtn.addEventListener("click", (e) => { - e.preventDefault(); - deleteBtn.blur(); - fieldArrayContainer - ?.querySelector( - `[data-field-array-item="${deleteBtn.dataset.fieldArrayDelete}"]` - ) - ?.remove(); - }); - }); - - // create base element to clone - const baseItem = items[0].cloneNode(true) as HTMLElement; - - const elements: NodeListOf = baseItem.querySelectorAll( - "input, select, textarea" - ); - - elements.forEach((element) => { - element.value = ""; - }); - - if (fieldArrayContainer && addButton) { - addButton.addEventListener("click", (event) => { - event.preventDefault(); - - const newItem = baseItem.cloneNode(true) as HTMLElement; - - const deleteBtn: HTMLButtonElement | null = newItem.querySelector( - "button[data-field-array-delete]" - ); - - if (deleteBtn) { - deleteBtn.addEventListener("click", () => { - deleteBtn.blur(); - newItem.remove(); - }); - - fieldArrayContainer.appendChild(newItem); - newItem.scrollIntoView({ - behavior: "auto", - block: "center", - inline: "center", - }); - - // reload tooltip module for showing remove button label - Tooltip(); - - // focus to first form element if mouse click - if (event.screenX !== 0 && event.screenY !== 0) { - const elements: NodeListOf = - newItem.querySelectorAll("input, select, textarea"); - - if (elements.length > 0) { - elements[0].focus(); - } - } - } - }); - - const updateIndexes = () => { - // get last child item to set item count - const items: NodeListOf = - fieldArrayContainer.querySelectorAll("[data-field-array-item]"); - - let itemIndex = 0; - items.forEach((item) => { - const itemNumber: HTMLElement | null = item.querySelector( - "[data-field-array-number]" - ); - - if (itemNumber) { - itemNumber.innerHTML = "#"; - const indexNum = itemIndex + 1; - if (item.dataset.fieldArrayItem !== itemIndex.toString()) { - item.classList.add("motion-safe:animate-single-pulse"); - setTimeout(() => { - item.classList.remove("motion-safe:animate-single-pulse"); - itemNumber.innerHTML = indexNum.toString(); - }, 300); - } else { - itemNumber.innerHTML = indexNum.toString(); - } - } - - item.dataset.fieldArrayItem = itemIndex.toString(); - const deleteBtn = item.querySelector( - "button[data-field-array-delete]" - ) as HTMLButtonElement | null; - - if (deleteBtn) { - deleteBtn.dataset.fieldArrayDelete = itemIndex.toString(); - } - - const itemElements: NodeListOf = - item.querySelectorAll("input, select, textarea"); - - itemElements.forEach((element) => { - const label: HTMLLabelElement | null = item.querySelector( - `label[for="${element.id}"]` - ); - - const elementID = element.name.replace( - /(.*\[)\d+?(\].*)/g, - `$1${itemIndex}$2` - ); - - if (label) { - label.htmlFor = elementID; - } - - element.id = elementID; - element.name = elementID; - }); - - itemIndex++; - }); - }; - - // add mutation observer to run index updates when field array - // items are added or removed - const callback = function (mutationList: MutationRecord[]) { - for (const mutation of mutationList) { - if (mutation.type === "childList") { - updateIndexes(); - } - } - }; - - const observer = new MutationObserver(callback); - - observer.observe(fieldArrayContainer, { childList: true }); - } - } -}; - -export default FieldArray; diff --git a/resources/js/_modules/code-editor.ts b/resources/js/_modules/code-editor.ts deleted file mode 100644 index 446752ca..00000000 --- a/resources/js/_modules/code-editor.ts +++ /dev/null @@ -1,229 +0,0 @@ -import { indentWithTab } from "@codemirror/commands"; -import { html as htmlLang } from "@codemirror/lang-html"; -import { xml } from "@codemirror/lang-xml"; -import { - defaultHighlightStyle, - syntaxHighlighting, -} from "@codemirror/language"; -import { Compartment, EditorState, Extension } from "@codemirror/state"; -import { keymap, ViewUpdate } from "@codemirror/view"; -import { basicSetup, EditorView } from "codemirror"; -import { prettify as prettifyHTML, minify as minifyHTML } from "htmlfy"; -import { css, html, LitElement, TemplateResult } from "lit"; -import { - customElement, - property, - queryAssignedNodes, - state, -} from "lit/decorators.js"; -import xmlFormat from "xml-formatter"; - -const language = new Compartment(); - -@customElement("code-editor") -export class XMLEditor extends LitElement { - @queryAssignedNodes({ slot: "textarea" }) - _textarea!: NodeListOf; - - @property() - lang = "html"; - - @state() - editorState!: EditorState; - - @state() - editorView!: EditorView; - - _textareaEvents = [ - { - events: ["focus", "invalid"], - onEvent: (_: Event, editor: EditorView) => { - // focus editor when textarea is focused or invalid - editor.focus(); - }, - }, - ]; - - firstUpdated(): void { - const minHeightEditor = EditorView.baseTheme({ - ".cm-content, .cm-gutter": { - minHeight: this._textarea[0].clientHeight + "px", - }, - }); - - const extensions: Extension[] = [ - basicSetup, - keymap.of([indentWithTab]), - minHeightEditor, - syntaxHighlighting(defaultHighlightStyle), - EditorView.updateListener.of((viewUpdate: ViewUpdate) => { - if (viewUpdate.docChanged) { - // Document changed, minify and update textarea value - switch (this.lang) { - case "xml": - this._textarea[0].value = minifyXML( - viewUpdate.state.doc.toString() - ); - break; - case "html": - this._textarea[0].value = minifyHTML( - viewUpdate.state.doc.toString() - ); - break; - default: - this._textarea[0].value = viewUpdate.state.doc.toString(); - break; - } - } - }), - ]; - - let editorContents = ""; - switch (this.lang) { - case "xml": - editorContents = formatXML(this._textarea[0].value); - extensions.push(language.of(xml())); - break; - case "html": - editorContents = prettifyHTML(this._textarea[0].value); - extensions.push(language.of(htmlLang())); - break; - default: - break; - } - - this.editorState = EditorState.create({ - doc: editorContents, - extensions: extensions, - }); - - this.editorView = new EditorView({ - state: this.editorState, - root: this.shadowRoot as ShadowRoot, - parent: this.shadowRoot as ShadowRoot, - }); - - // hide textarea - this._textarea[0].style.position = "absolute"; - this._textarea[0].style.opacity = "0"; - this._textarea[0].style.zIndex = "-9999"; - this._textarea[0].style.pointerEvents = "none"; - - for (const event of this._textareaEvents) { - event.events.forEach((name) => { - this._textarea[0].addEventListener(name, (e) => - event.onEvent(e, this.editorView) - ); - }); - } - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - for (const event of this._textareaEvents) { - event.events.forEach((name) => { - this._textarea[0].removeEventListener(name, (e) => - event.onEvent(e, this.editorView) - ); - }); - } - } - - static styles = css` - .cm-editor { - border-radius: 0.5rem; - overflow: hidden; - border: 3px solid hsl(var(--color-border-contrast)); - background-color: hsl(var(--color-background-elevated)); - transition-property: - color, - background-color, - border-color, - text-decoration-color, - fill, - stroke, - opacity, - box-shadow, - transform, - filter, - backdrop-filter, - -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - } - .cm-editor.cm-focused { - outline: 2px solid transparent; - box-shadow: - 0 0 0 2px hsl(var(--color-background-elevated)), - 0 0 0 calc(4px) hsl(var(--color-accent-base)); - } - .cm-gutters { - background-color: hsl(var(--color-background-elevated)) !important; - } - - .cm-activeLine { - background-color: hsla( - var(--color-background-highlight) / 0.25 - ) !important; - } - - .cm-activeLineGutter { - background-color: hsl(var(--color-background-highlight)) !important; - } - - .ͼ4 .cm-line { - caret-color: hsl(var(--color-text-base)) !important; - } - - .ͼ1 .cm-cursor { - border: none; - } - `; - - render(): TemplateResult<1> { - return html``; - } -} - -function formatXML(contents: string) { - if (contents === "") { - return contents; - } - - try { - return xmlFormat(contents, { - indentation: " ", - }); - } catch { - // xml doesn't have a root node - const editorContents = xmlFormat("" + contents + "", { - indentation: " ", - }); - // remove root, unnecessary lines and indents - return editorContents - .replace(/^/, "") - .replace(/<\/root>$/, "") - .replace(/^\s*[\r\n]/gm, "") - .replace(/[\r\n] {2}/gm, "\r\n") - .trim(); - } -} - -function minifyXML(contents: string) { - if (contents === "") { - return contents; - } - - try { - return xmlFormat.minify(contents, { - collapseContent: true, - }); - } catch { - const minifiedContent = xmlFormat.minify(`${contents}`, { - collapseContent: true, - }); - // remove root - return minifiedContent.replace(/^/, "").replace(/<\/root>$/, ""); - } -} diff --git a/resources/js/admin.ts b/resources/js/admin.ts deleted file mode 100644 index bc87479d..00000000 --- a/resources/js/admin.ts +++ /dev/null @@ -1,43 +0,0 @@ -import "@github/markdown-toolbar-element"; -import "@github/relative-time-element"; -import "./_modules/audio-clipper"; -import ClientTimezone from "./_modules/ClientTimezone"; -import Clipboard from "./_modules/Clipboard"; -import DateTimePicker from "./_modules/DateTimePicker"; -import Dropdown from "./_modules/Dropdown"; -import HotKeys from "./_modules/HotKeys"; -import "./_modules/markdown-preview"; -import "./_modules/markdown-write-preview"; -import SelectMulti from "./_modules/SelectMulti"; -import "./_modules/permalink-edit"; -import "./_modules/play-soundbite"; -import PublishMessageWarning from "./_modules/PublishMessageWarning"; -import Select from "./_modules/Select"; -import SidebarToggler from "./_modules/SidebarToggler"; -import Slugify from "./_modules/Slugify"; -import ThemePicker from "./_modules/ThemePicker"; -import Time from "./_modules/Time"; -import Tooltip from "./_modules/Tooltip"; -import ValidateFileSize from "./_modules/ValidateFileSize"; -import "./_modules/video-clip-previewer"; -import VideoClipBuilder from "./_modules/VideoClipBuilder"; -import "./_modules/code-editor"; -import "@patternfly/elements/pf-tabs/pf-tabs.js"; -import FieldArray from "./_modules/FieldArray"; - -Dropdown(); -Tooltip(); -Select(); -SelectMulti(); -Slugify(); -SidebarToggler(); -ClientTimezone(); -DateTimePicker(); -Time(); -Clipboard(); -ThemePicker(); -PublishMessageWarning(); -HotKeys(); -ValidateFileSize(); -VideoClipBuilder(); -FieldArray(); diff --git a/resources/js/app.ts b/resources/js/app.ts deleted file mode 100644 index 65bf64d4..00000000 --- a/resources/js/app.ts +++ /dev/null @@ -1,5 +0,0 @@ -import Dropdown from "./_modules/Dropdown"; -import Tooltip from "./_modules/Tooltip"; - -Dropdown(); -Tooltip(); diff --git a/resources/js/charts.ts b/resources/js/charts.ts deleted file mode 100644 index 9b09ccaa..00000000 --- a/resources/js/charts.ts +++ /dev/null @@ -1,3 +0,0 @@ -import DrawCharts from "./_modules/Charts"; - -DrawCharts(); diff --git a/resources/js/install.ts b/resources/js/install.ts deleted file mode 100644 index 5f57a192..00000000 --- a/resources/js/install.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Tooltip from "./_modules/Tooltip"; - -Tooltip(); diff --git a/resources/js/map.ts b/resources/js/map.ts deleted file mode 100644 index 2f3785e7..00000000 --- a/resources/js/map.ts +++ /dev/null @@ -1,3 +0,0 @@ -import DrawEpisodesMaps from "./_modules/EpisodesMap"; - -DrawEpisodesMaps(); diff --git a/resources/js/podcast.ts b/resources/js/podcast.ts deleted file mode 100644 index f16c5618..00000000 --- a/resources/js/podcast.ts +++ /dev/null @@ -1,10 +0,0 @@ -import "@github/relative-time-element"; -import SidebarToggler from "./_modules/SidebarToggler"; -import Time from "./_modules/Time"; -import Toggler from "./_modules/Toggler"; -import Tooltip from "./_modules/Tooltip"; - -Time(); -Toggler(); -Tooltip(); -SidebarToggler(); diff --git a/resources/static/images/castopod-logo-base.svg b/resources/static/images/castopod-logo-base.svg deleted file mode 100644 index 72221cfa..00000000 --- a/resources/static/images/castopod-logo-base.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/images/castopod-logo.svg b/resources/static/images/castopod-logo.svg deleted file mode 100644 index 55f4b22b..00000000 --- a/resources/static/images/castopod-logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/images/castopod-mascot_confused.svg b/resources/static/images/castopod-mascot_confused.svg deleted file mode 100644 index 89d51627..00000000 --- a/resources/static/images/castopod-mascot_confused.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/vm-player-icons/check.svg b/resources/static/vm-player-icons/check.svg deleted file mode 100644 index bf36197d..00000000 --- a/resources/static/vm-player-icons/check.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/vm-player-icons/pause.svg b/resources/static/vm-player-icons/pause.svg deleted file mode 100644 index ea2847b9..00000000 --- a/resources/static/vm-player-icons/pause.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/vm-player-icons/play.svg b/resources/static/vm-player-icons/play.svg deleted file mode 100644 index 75ad8b10..00000000 --- a/resources/static/vm-player-icons/play.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/vm-player-icons/settings.svg b/resources/static/vm-player-icons/settings.svg deleted file mode 100644 index a8cd5895..00000000 --- a/resources/static/vm-player-icons/settings.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/vm-player-icons/volume-high.svg b/resources/static/vm-player-icons/volume-high.svg deleted file mode 100644 index f352c50a..00000000 --- a/resources/static/vm-player-icons/volume-high.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/vm-player-icons/volume-low.svg b/resources/static/vm-player-icons/volume-low.svg deleted file mode 100644 index 999e6126..00000000 --- a/resources/static/vm-player-icons/volume-low.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/static/vm-player-icons/volume-mute.svg b/resources/static/vm-player-icons/volume-mute.svg deleted file mode 100644 index 44f6c50c..00000000 --- a/resources/static/vm-player-icons/volume-mute.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/styles/_modules/custom.css b/resources/styles/_modules/custom.css deleted file mode 100644 index e327b2ca..00000000 --- a/resources/styles/_modules/custom.css +++ /dev/null @@ -1,105 +0,0 @@ -@layer base { - html { - scroll-behavior: smooth; - } - - .form-helper { - @apply text-skin-muted; - } - - select { - box-shadow: 2px 2px 0 hsl(var(--color-border-contrast)); - } -} - -@layer components { - .post-content { - & a { - @apply text-sm font-semibold text-accent-base hover:text-accent-hover; - } - } - - .ring-accent { - @apply outline-none ring-2 ring-offset-2 ring-accent-base; - - /* FIXME: why doesn't ring-accent-base work? */ - --tw-ring-opacity: 1; - --tw-ring-color: hsl(var(--color-accent-base) / var(--tw-ring-opacity)); - --tw-ring-offset-color: hsl(var(--color-background-base)); - } - - .rounded-conditional-b-xl { - border-bottom-right-radius: max( - 0px, - min(0.75rem, calc((100vw - 0.75rem - 100%) * 9999)) - ); - border-bottom-left-radius: max( - 0px, - min(0.75rem, calc((100vw - 0.75rem - 100%) * 9999)) - ); - } - - .rounded-conditional-2xl { - border-radius: max(0px, min(1rem, calc((100vw - 1rem - 100%) * 9999))); - } - - .rounded-conditional-full { - border-radius: max(0px, min(9999px, calc((100vw - 1rem - 100%) * 9999))); - } - - .backdrop-gradient { - background-image: linear-gradient( - 180deg, - hsl(0deg 0% 35.29% / 0%) 0%, - hsl(0deg 0% 34.53% / 3.44%) 16.36%, - hsl(0deg 0% 32.42% / 12.5%) 33.34%, - hsl(0deg 0% 29.18% / 25.3%) 50.1%, - hsl(0deg 0% 24.96% / 40%) 65.75%, - hsl(0deg 0% 19.85% / 54.7%) 79.43%, - hsl(0deg 0% 13.95% / 67.5%) 90.28%, - hsl(0deg 0% 7.32% / 76.6%) 97.43%, - hsl(0deg 0% 0% / 80%) 100% - ); - } - - .backdrop-gradient-accent { - /* stylelint-disable-next-line declaration-property-value-no-unknown */ - background-image: linear-gradient( - 180deg, - theme(colors.background.base / 0.4) 0%, - theme(colors.background.base / 0.6) 65.75%, - theme(colors.background.base / 1) 90.28%, - theme(colors.background.base / 1) 97.43%, - theme(colors.background.base / 1) 100% - ); - } - - .bg-stripes-default { - background-image: repeating-linear-gradient( - -45deg, - #f3f4f6, - #f3f4f6 10px, - #e5e7eb 10px, - #e5e7eb 20px - ); - } - - .bg-stripes-warning { - background-image: repeating-linear-gradient( - -45deg, - #fde047, - #fde047 10px, - #facc15 10px, - #facc15 20px - ); - } - - .divide-fieldset-y > :not([hidden], legend) ~ :not([hidden], legend) { - @apply pt-4; - - --tw-divide-y-reverse: 0; - - border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); - border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); - } -} diff --git a/resources/styles/_modules/radioBtn.css b/resources/styles/_modules/radioBtn.css deleted file mode 100644 index e892ee0d..00000000 --- a/resources/styles/_modules/radioBtn.css +++ /dev/null @@ -1,33 +0,0 @@ -@layer components { - .form-radio-btn { - @apply absolute right-4 top-4 border-contrast border-3 text-accent-base transition; - - &:focus { - @apply ring-accent; - } - - &:checked { - & + label { - @apply text-accent-hover bg-base border-accent-base shadow-none; - } - - & + label .form-radio-btn-description { - @apply text-accent-base; - } - } - - & + label { - @apply h-full w-full inline-flex flex-col items-start py-3 px-4 text-sm font-bold rounded-lg cursor-pointer border-contrast bg-elevated border-3 transition-all; - - box-shadow: 2px 2px 0 hsl(var(--color-border-contrast)); - } - - & + label span { - @apply pr-8; - } - - & + label .form-radio-btn-description { - @apply font-normal text-xs text-skin-muted text-balance; - } - } -} diff --git a/resources/styles/admin.css b/resources/styles/admin.css deleted file mode 100644 index bb90fa4b..00000000 --- a/resources/styles/admin.css +++ /dev/null @@ -1,17 +0,0 @@ -@import url("./_modules/tailwind.css"); -@import url("./_modules/custom.css"); -@import url("./_modules/fonts.css"); -@import url("./_modules/colors.css"); -@import url("./_modules/breadcrumb.css"); -@import url("./_modules/dropdown.css"); -@import url("./_modules/choices.css"); -@import url("./_modules/radioBtn.css"); -@import url("./_modules/colorRadioBtn.css"); -@import url("./_modules/switch.css"); -@import url("./_modules/radioToggler.css"); -@import url("./_modules/formInputTabs.css"); -@import url("./_modules/stickyHeader.css"); -@import url("./_modules/readMore.css"); -@import url("./_modules/seeMore.css"); - -@config '../../tailwind.admin.config.js'; diff --git a/resources/styles/install.css b/resources/styles/install.css deleted file mode 100644 index e14d0dc0..00000000 --- a/resources/styles/install.css +++ /dev/null @@ -1,17 +0,0 @@ -@import url("./_modules/tailwind.css"); -@import url("./_modules/custom.css"); -@import url("./_modules/fonts.css"); -@import url("./_modules/colors.css"); -@import url("./_modules/breadcrumb.css"); -@import url("./_modules/dropdown.css"); -@import url("./_modules/choices.css"); -@import url("./_modules/radioBtn.css"); -@import url("./_modules/colorRadioBtn.css"); -@import url("./_modules/switch.css"); -@import url("./_modules/radioToggler.css"); -@import url("./_modules/formInputTabs.css"); -@import url("./_modules/stickyHeader.css"); -@import url("./_modules/readMore.css"); -@import url("./_modules/seeMore.css"); - -@config '../../tailwind.install.config.js'; diff --git a/resources/styles/site.css b/resources/styles/site.css deleted file mode 100644 index c5e54f99..00000000 --- a/resources/styles/site.css +++ /dev/null @@ -1,17 +0,0 @@ -@import url("./_modules/tailwind.css"); -@import url("./_modules/custom.css"); -@import url("./_modules/fonts.css"); -@import url("./_modules/colors.css"); -@import url("./_modules/breadcrumb.css"); -@import url("./_modules/dropdown.css"); -@import url("./_modules/choices.css"); -@import url("./_modules/radioBtn.css"); -@import url("./_modules/colorRadioBtn.css"); -@import url("./_modules/switch.css"); -@import url("./_modules/radioToggler.css"); -@import url("./_modules/formInputTabs.css"); -@import url("./_modules/stickyHeader.css"); -@import url("./_modules/readMore.css"); -@import url("./_modules/seeMore.css"); - -@config '../../tailwind.config.js'; diff --git a/scripts/bundle-prepare.sh b/scripts/bundle-prepare.sh index 4d011586..6bddd173 100644 --- a/scripts/bundle-prepare.sh +++ b/scripts/bundle-prepare.sh @@ -1,9 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e # install only production dependencies using the --no-dev option composer install --no-dev --prefer-dist --no-ansi --no-interaction --no-progress --ignore-platform-reqs # build all production static assets (css, js, images, icons, fonts, etc.) -pnpm run build -pnpm run build:static +npm run build +npm run build:static diff --git a/scripts/bundle.sh b/scripts/bundle.sh index 2d049601..95e31c48 100644 --- a/scripts/bundle.sh +++ b/scripts/bundle.sh @@ -1,21 +1,30 @@ -#!/bin/sh +#!/bin/bash set -e VERSION=$1 -COMPOSER_VERSION=$(echo "$VERSION" | sed -r 's/(alpha|beta|next)./\1/g') -COMPOSER_VERSION=$(echo "$COMPOSER_VERSION" | sed -r 's/next[0-9]+/dev/g') +COMPOSER_VERSION=$(echo "$VERSION" | perl -pe 's/(?<=[alpha|beta])\.//g') # replace composer.json version using jq +apt-get install jq -y echo "$( jq '.version = "'$COMPOSER_VERSION'"' composer.json )" > composer.json # replace CP_VERSION constant in app/config/constants sed -i "s/^defined('CP_VERSION').*/defined('CP_VERSION') || define('CP_VERSION', '$VERSION');/" ./app/Config/Constants.php +# fill CP_VERSION.env for docker build +echo "$VERSION" > ./CP_VERSION.env + +# install wget to download archives +apt-get install wget + # download GeoLite2-City archive and extract it to writable/uploads wget -c "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=$MAXMIND_LICENCE_KEY&suffix=tar.gz" -O - | tar -xz -C ./writable/uploads/ # rename extracted archives' folders mv ./writable/uploads/GeoLite2-City* ./writable/uploads/GeoLite2-City +# install rsync for file transfers +apt-get install rsync -y + # create castopod folder bundle: uses .rsync-filter (-F) file to copy only needed files -rsync -aF . ./castopod +rsync -aF --progress . ./castopod diff --git a/scripts/lint-commit-msg.sh b/scripts/lint-commit-msg.sh index 173d5821..c48b935b 100755 --- a/scripts/lint-commit-msg.sh +++ b/scripts/lint-commit-msg.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e # see https://github.com/conventional-changelog/commitlint/issues/885 @@ -6,14 +6,14 @@ set -e if [ "${CI_COMMIT_BEFORE_SHA}" = "0000000000000000000000000000000000000000" ]; then echo "commitlint from HEAD^" - pnpm exec commitlint --from=HEAD^ + npx commitlint --from=HEAD^ else echo "commitlint from ${CI_COMMIT_BEFORE_SHA}" br=`git branch -r --contains ${CI_COMMIT_BEFORE_SHA}` if [ ! -n $br ]; then - pnpm exec commitlint --from=HEAD^ + npx commitlint --from=HEAD^ else - pnpm exec commitlint --from="${CI_COMMIT_BEFORE_SHA}" + npx commitlint --from="${CI_COMMIT_BEFORE_SHA}" fi fi diff --git a/scripts/package.sh b/scripts/package.sh index c6269f5c..c36c8cf5 100644 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -1,8 +1,10 @@ -#!/bin/sh +#!/bin/bash set -e VERSION=$1 +apt-get install zip -y + # create zip and tar.gz packages for release upload zip -r castopod-$VERSION.zip castopod tar -zcvf castopod-$VERSION.tar.gz castopod diff --git a/spark b/spark index aef372bc..225422aa 100644 --- a/spark +++ b/spark @@ -1,65 +1,41 @@ #!/usr/bin/env php * - * For the full copyright and license information, please view the LICENSE file that was distributed with this source - * code. + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. */ /* * -------------------------------------------------------------------- - * CODEIGNITER COMMAND-LINE TOOLS + * CodeIgniter command-line tools * -------------------------------------------------------------------- * The main entry point into the CLI system and allows you to run * commands and perform maintenance on your application. - */ - -/* - *--------------------------------------------------------------- - * CHECK SERVER API - *--------------------------------------------------------------- + * + * Because CodeIgniter can handle CLI requests as just another web request + * this class mainly acts as a passthru to the framework itself. */ // Refuse to run when called from php-cgi -if (str_starts_with(PHP_SAPI, 'cgi')) { +if (strpos(PHP_SAPI, 'cgi') === 0) { exit("The cli tool is not supported when running php-cgi. It needs php-cli to function!\n\n"); } -/* - *--------------------------------------------------------------- - * CHECK PHP VERSION - *--------------------------------------------------------------- - */ - -$minPhpVersion = '8.5'; // If you update this, don't forget to update `public/index.php`. -if (version_compare(PHP_VERSION, $minPhpVersion, '<')) { - $message = sprintf( - 'Your PHP version must be %s or higher to run CodeIgniter. Current version: %s', - $minPhpVersion, - PHP_VERSION, - ); - - exit($message); -} - // We want errors to be shown when using it from the CLI. -error_reporting(E_ALL); +error_reporting(-1); ini_set('display_errors', '1'); -/* - *--------------------------------------------------------------- - * SET THE CURRENT DIRECTORY - *--------------------------------------------------------------- +/** + * @var bool + * + * @deprecated No longer in use. `CodeIgniter` has `$context` property. */ +define('SPARKED', true); // Path to the front controller define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR); @@ -76,14 +52,39 @@ chdir(FCPATH); * and fires up an environment-specific bootstrapping. */ -// LOAD OUR PATHS CONFIG FILE +// Load our paths config file // This is the line that might need to be changed, depending on your folder structure. require FCPATH . '../app/Config/Paths.php'; // ^^^ Change this line if you move your application folder -$paths = new Paths(); +$paths = new Config\Paths(); -// LOAD THE FRAMEWORK BOOTSTRAP FILE -require $paths->systemDirectory . '/Boot.php'; +// Location of the framework bootstrap file. +require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; -exit(Boot::bootSpark($paths)); +// Load environment settings from .env files into $_SERVER and $_ENV +require_once SYSTEMPATH . 'Config/DotEnv.php'; +(new CodeIgniter\Config\DotEnv(ROOTPATH))->load(); + +// Grab our CodeIgniter +$app = Config\Services::codeigniter(); +$app->initialize(); +$app->setContext('spark'); + +// Grab our Console +$console = new CodeIgniter\CLI\Console($app); + +// Show basic information before we do anything else. +if (is_int($suppress = array_search('--no-header', $_SERVER['argv'], true))) { + unset($_SERVER['argv'][$suppress]); // @codeCoverageIgnore + $suppress = true; +} + +$console->showHeader($suppress); + +// fire off the command in the main framework. +$response = $console->run(); + +if ($response->getStatusCode() >= 300) { + exit($response->getStatusCode()); +} diff --git a/tailwind.admin.config.js b/tailwind.admin.config.js deleted file mode 100644 index f6d4fea4..00000000 --- a/tailwind.admin.config.js +++ /dev/null @@ -1,171 +0,0 @@ -import defaultTheme from "tailwindcss/defaultTheme"; -import tailwindForms from "@tailwindcss/forms"; -import tailwindTypography from "@tailwindcss/typography"; - -/** @type {import('tailwindcss').Config} */ -export default { - content: [ - "./app/Views/**/*.php", - "./themes/cp_admin/**/*.php", - "./themes/cp_auth/**/*.php", - "./app/Helpers/*.php", - "./resources/**/*.ts", - ], - theme: { - extend: { - content: { - chevronRightIcon: - "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23ffffff' viewBox='0 0 24 24'%3E%3Cpath d='M13.17 12 8.22 7.05l1.42-1.41L16 12l-6.36 6.36-1.42-1.41L13.17 12Z'/%3E%3C/svg%3E%0A\")", - prohibitedIcon: - "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23ffffff' viewBox='0 0 24 24'%3E%3Cpath d='M7.0943 5.68009L18.3199 16.9057C19.3736 15.5506 20 13.8491 20 12C20 7.58172 16.4183 4 12 4C10.1509 4 8.44939 4.62644 7.0943 5.68009ZM16.9057 18.3199L5.68009 7.0943C4.62644 8.44939 4 10.1509 4 12C4 16.4183 7.58172 20 12 20C13.8491 20 15.5506 19.3736 16.9057 18.3199ZM4.92893 4.92893C6.73748 3.12038 9.23885 2 12 2C17.5228 2 22 6.47715 22 12C22 14.7611 20.8796 17.2625 19.0711 19.0711C17.2625 20.8796 14.7611 22 12 22C6.47715 22 2 17.5228 2 12C2 9.23885 3.12038 6.73748 4.92893 4.92893Z'/%3E%3C/svg%3E%0A\")", - }, - fontFamily: { - sans: ["Inter", ...defaultTheme.fontFamily.sans], - display: ["Kumbh Sans", ...defaultTheme.fontFamily.sans], - mono: ["Noto Sans Mono", ...defaultTheme.fontFamily.mono], - }, - textDecorationThickness: { - 3: "3px", - }, - textColor: { - skin: { - base: "hsl(var(--color-text-base) / )", - muted: "hsl(var(--color-text-muted) / )", - }, - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - muted: "hsl(var(--color-accent-muted) / )", - contrast: "hsl(var(--color-accent-contrast) / )", - }, - }, - backgroundColor: { - base: "hsl(var(--color-background-base) / )", - elevated: "hsl(var(--color-background-elevated) / )", - subtle: "hsl(var(--color-border-subtle) / )", - navigation: "hsl(var(--color-background-navigation) / )", - "navigation-active": - "hsl(var(--color-background-navigation-active) / )", - backdrop: "hsl(var(--color-background-backdrop) / )", - header: "hsl(var(--color-background-header) / )", - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - }, - highlight: "hsl(var(--color-background-highlight) / )", - }, - borderColor: { - subtle: "hsl(var(--color-border-subtle) / )", - contrast: "hsl(var(--color-border-contrast) / )", - navigation: "hsl(var(--color-border-navigation) / )", - "navigation-bg": - "hsl(var(--color-background-navigation) / )", - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - }, - background: { - base: "hsl(var(--color-background-base) / )", - elevated: "hsl(var(--color-background-elevated) / )", - }, - }, - ringColor: { - contrast: "hsl(var(--color-border-contrast) / )", - background: { - base: "hsl(var(--color-background-base) / )", - elevated: "hsl(var(--color-background-elevated) / )", - }, - }, - colors: { - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - }, - background: { - header: "hsl(var(--color-background-header) / )", - base: "hsl(var(--color-background-base) / )", - }, - heading: { - foreground: "hsl(var(--color-heading-foreground) / )", - background: "hsl(var(--color-heading-background) / )", - }, - pine: { - 50: "#F2FAF9", - 100: "#E7F9E4", - 200: "#bfe4e1", - 300: "#99d4cf", - 400: "#4db4aa", - 500: "#009486", - 600: "#008579", - 700: "#006D60", - 800: "#00564A", - 900: "#003D0B", - }, - }, - gridTemplateColumns: { - admin: "300px calc(100% - 300px)", - podcast: "1fr minmax(auto, 960px) 1fr", - podcastMain: "1fr minmax(200px, 300px)", - cards: "repeat(auto-fill, minmax(14rem, 1fr))", - latestEpisodes: "repeat(5, 1fr)", - colorButtons: "repeat(auto-fill, minmax(4rem, 1fr))", - platforms: "repeat(auto-fill, minmax(18rem, 1fr))", - plugins: "repeat(auto-fill, minmax(20rem, 1fr))", - radioGroup: "repeat(auto-fit, minmax(14rem, 1fr))", - }, - gridTemplateRows: { - admin: "40px 1fr", - }, - borderWidth: { - 3: "3px", - }, - ringWidth: { - 3: "3px", - }, - typography: { - DEFAULT: { - css: { - a: { - textDecoration: "underline", - fontWeight: 600, - "&:hover": { - textDecoration: "none", - }, - }, - input: { - margin: 0, - }, - }, - }, - sm: { - css: { - a: { - textDecoration: "underline", - fontWeight: 600, - "&:hover": { - textDecoration: "none", - }, - }, - }, - }, - }, - zIndex: { - 60: 60, - }, - keyframes: { - "slight-pulse": { - "0%": { transform: "scale(1)" }, - "60%": { transform: "scale(0.96)" }, - "75%": { transform: "scale(1.05)" }, - "95%": { transform: "scale(0.98)" }, - "100%": { transform: "scale(1)" }, - }, - }, - animation: { - "single-pulse": "slight-pulse 300ms linear 1", - }, - }, - }, - variants: {}, - plugins: [tailwindForms, tailwindTypography], -}; diff --git a/tailwind.config.js b/tailwind.config.js index 42ba73eb..0da9244a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,24 +1,18 @@ -import defaultTheme from "tailwindcss/defaultTheme"; -import tailwindForms from "@tailwindcss/forms"; -import tailwindTypography from "@tailwindcss/typography"; +/* eslint-disable */ +const defaultTheme = require("tailwindcss/defaultTheme"); +const { nodeModuleNameResolver } = require("typescript"); /** @type {import('tailwindcss').Config} */ -export default { +module.exports = { content: [ "./app/Views/**/*.php", "./modules/**/Views/**/*.php", - "./themes/cp_app/**/*.php", + "./themes/**/*.php", "./app/Helpers/*.php", - "./resources/**/*.ts", + "./app/Resources/**/*.ts", ], theme: { extend: { - content: { - chevronRightIcon: - "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23ffffff' viewBox='0 0 24 24'%3E%3Cpath d='M13.17 12 8.22 7.05l1.42-1.41L16 12l-6.36 6.36-1.42-1.41L13.17 12Z'/%3E%3C/svg%3E%0A\")", - prohibitedIcon: - "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23ffffff' viewBox='0 0 24 24'%3E%3Cpath d='M7.0943 5.68009L18.3199 16.9057C19.3736 15.5506 20 13.8491 20 12C20 7.58172 16.4183 4 12 4C10.1509 4 8.44939 4.62644 7.0943 5.68009ZM16.9057 18.3199L5.68009 7.0943C4.62644 8.44939 4 10.1509 4 12C4 16.4183 7.58172 20 12 20C13.8491 20 15.5506 19.3736 16.9057 18.3199ZM4.92893 4.92893C6.73748 3.12038 9.23885 2 12 2C17.5228 2 22 6.47715 22 12C22 14.7611 20.8796 17.2625 19.0711 19.0711C17.2625 20.8796 14.7611 22 12 22C6.47715 22 2 17.5228 2 12C2 9.23885 3.12038 6.73748 4.92893 4.92893Z'/%3E%3C/svg%3E%0A\")", - }, fontFamily: { sans: ["Inter", ...defaultTheme.fontFamily.sans], display: ["Kumbh Sans", ...defaultTheme.fontFamily.sans], @@ -42,10 +36,7 @@ export default { backgroundColor: { base: "hsl(var(--color-background-base) / )", elevated: "hsl(var(--color-background-elevated) / )", - subtle: "hsl(var(--color-border-subtle) / )", navigation: "hsl(var(--color-background-navigation) / )", - "navigation-active": - "hsl(var(--color-background-navigation-active) / )", backdrop: "hsl(var(--color-background-backdrop) / )", header: "hsl(var(--color-background-header) / )", accent: { @@ -77,13 +68,9 @@ export default { }, }, colors: { - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - }, + accent: "hsl(var(--color-accent-base) / )", background: { header: "hsl(var(--color-background-header) / )", - base: "hsl(var(--color-background-base) / )", }, heading: { foreground: "hsl(var(--color-heading-foreground) / )", @@ -101,6 +88,18 @@ export default { 800: "#00564A", 900: "#003D0B", }, + rose: { + 50: "#fcf9f8", + 100: "#fdeef2", + 200: "#fbcfe4", + 300: "#faa7cd", + 400: "#fb6ea5", + 500: "#fc437c", + 600: "#f24664", + 700: "#dd1f47", + 800: "#b21a39", + 900: "#8e162e", + }, }, gridTemplateColumns: { admin: "300px calc(100% - 300px)", @@ -109,9 +108,6 @@ export default { cards: "repeat(auto-fill, minmax(14rem, 1fr))", latestEpisodes: "repeat(5, 1fr)", colorButtons: "repeat(auto-fill, minmax(4rem, 1fr))", - platforms: "repeat(auto-fill, minmax(18rem, 1fr))", - plugins: "repeat(auto-fill, minmax(20rem, 1fr))", - radioGroup: "repeat(auto-fit, minmax(14rem, 1fr))", }, gridTemplateRows: { admin: "40px 1fr", @@ -132,9 +128,6 @@ export default { textDecoration: "none", }, }, - input: { - margin: 0, - }, }, }, sm: { @@ -155,5 +148,9 @@ export default { }, }, variants: {}, - plugins: [tailwindForms, tailwindTypography], + plugins: [ + require("@tailwindcss/forms"), + require("@tailwindcss/typography"), + require("@tailwindcss/line-clamp"), + ], }; diff --git a/tailwind.install.config.js b/tailwind.install.config.js deleted file mode 100644 index 3313dcee..00000000 --- a/tailwind.install.config.js +++ /dev/null @@ -1,106 +0,0 @@ -import defaultTheme from "tailwindcss/defaultTheme"; -import tailwindForms from "@tailwindcss/forms"; - -/** @type {import('tailwindcss').Config} */ -export default { - content: [ - "./app/Views/**/*.php", - "./themes/cp_install/**/*.php", - "./resources/**/*.ts", - ], - theme: { - extend: { - fontFamily: { - sans: ["Inter", ...defaultTheme.fontFamily.sans], - display: ["Kumbh Sans", ...defaultTheme.fontFamily.sans], - mono: ["Noto Sans Mono", ...defaultTheme.fontFamily.mono], - }, - textDecorationThickness: { - 3: "3px", - }, - textColor: { - skin: { - base: "hsl(var(--color-text-base) / )", - muted: "hsl(var(--color-text-muted) / )", - }, - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - muted: "hsl(var(--color-accent-muted) / )", - contrast: "hsl(var(--color-accent-contrast) / )", - }, - }, - backgroundColor: { - base: "hsl(var(--color-background-base) / )", - elevated: "hsl(var(--color-background-elevated) / )", - subtle: "hsl(var(--color-border-subtle) / )", - navigation: "hsl(var(--color-background-navigation) / )", - "navigation-active": - "hsl(var(--color-background-navigation-active) / )", - backdrop: "hsl(var(--color-background-backdrop) / )", - header: "hsl(var(--color-background-header) / )", - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - }, - highlight: "hsl(var(--color-background-highlight) / )", - }, - borderColor: { - subtle: "hsl(var(--color-border-subtle) / )", - contrast: "hsl(var(--color-border-contrast) / )", - navigation: "hsl(var(--color-border-navigation) / )", - "navigation-bg": - "hsl(var(--color-background-navigation) / )", - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - }, - background: { - base: "hsl(var(--color-background-base) / )", - elevated: "hsl(var(--color-background-elevated) / )", - }, - }, - ringColor: { - contrast: "hsl(var(--color-border-contrast) / )", - background: { - base: "hsl(var(--color-background-base) / )", - elevated: "hsl(var(--color-background-elevated) / )", - }, - }, - colors: { - accent: { - base: "hsl(var(--color-accent-base) / )", - hover: "hsl(var(--color-accent-hover) / )", - }, - background: { - header: "hsl(var(--color-background-header) / )", - base: "hsl(var(--color-background-base) / )", - }, - heading: { - foreground: "hsl(var(--color-heading-foreground) / )", - background: "hsl(var(--color-heading-background) / )", - }, - pine: { - 50: "#F2FAF9", - 100: "#E7F9E4", - 200: "#bfe4e1", - 300: "#99d4cf", - 400: "#4db4aa", - 500: "#009486", - 600: "#008579", - 700: "#006D60", - 800: "#00564A", - 900: "#003D0B", - }, - }, - borderWidth: { - 3: "3px", - }, - ringWidth: { - 3: "3px", - }, - }, - }, - variants: {}, - plugins: [tailwindForms], -}; diff --git a/tests/.htaccess b/tests/.htaccess deleted file mode 100644 index 3462048a..00000000 --- a/tests/.htaccess +++ /dev/null @@ -1,6 +0,0 @@ - - Require all denied - - - Deny from all - diff --git a/tests/README.md b/tests/README.md index d4224da6..c9ab19cb 100644 --- a/tests/README.md +++ b/tests/README.md @@ -7,14 +7,14 @@ test your application. Those details can be found in the documentation. ## Resources -- [CodeIgniter 4 User Guide on Testing](https://codeigniter.com/user_guide/testing/index.html) +- [CodeIgniter 4 User Guide on Testing](https://codeigniter4.github.io/userguide/testing/index.html) - [PHPUnit docs](https://phpunit.de/documentation.html) - [Any tutorials on Unit testing in CI4?](https://forum.codeigniter.com/showthread.php?tid=81830) ## Requirements It is recommended to use the latest version of PHPUnit. At the time of this -writing, we are running version 9.x. Support for this has been built into the +writing we are running version 9.x. Support for this has been built into the **composer.json** file that ships with CodeIgniter and can easily be installed via [Composer](https://getcomposer.org/) if you don't already have it installed globally. @@ -38,9 +38,9 @@ add `xdebug.mode=coverage` in the **php.ini** file to enable code coverage. A number of the tests use a running database. In order to set up the database edit the details for the `tests` group in **app/Config/Database.php** or -**.env**. Make sure that you provide a database engine that is currently running -on your machine. More details on a test database setup are in the -[Testing Your Database](https://codeigniter.com/user_guide/testing/database.html) +**phpunit.xml**. Make sure that you provide a database engine that is currently +running on your machine. More details on a test database setup are in the +[Testing Your Database](https://codeigniter4.github.io/userguide/testing/database.html) section of the documentation. ## Running the tests @@ -96,12 +96,14 @@ to exclude database tests, or automatically generate HTML code coverage reports. ## Test Cases Every test needs a _test case_, or class that your tests extend. CodeIgniter 4 -provides one class that you may use directly: +provides a few that you may use directly: -- `CodeIgniter\Test\CIUnitTestCase` +- `CodeIgniter\Test\CIUnitTestCase` - for basic tests with no other service + needs +- `CodeIgniter\Test\DatabaseTestTrait` - for tests that need database access -Most of the time you will want to write your own test cases that extend -`CIUnitTestCase` to hold functions and services common to your test suites. +Most of the time you will want to write your own test cases to hold functions +and services common to your test suites. ## Creating Tests @@ -116,9 +118,13 @@ how. Review the links above and always pay attention to your code coverage. ### Database Tests -Tests can include migrating, seeding, and testing against a mock or live -database. Be sure to modify the test case (or create your own) to point to your -seed and migrations and include any additional steps to be run before tests in -the `setUp()` method. See -[Testing Your Database](https://codeigniter.com/user_guide/testing/database.html) -for details. +Tests can include migrating, seeding, and testing against a mock or +live1 database. Be sure to modify the test case (or create your own) +to point to your seed and migrations and include any additional steps to be run +before tests in the `setUp()` method. + +1 Note: If you are using database tests that require a live database +connection you will need to rename **phpunit.xml.dist** to **phpunit.xml**, +uncomment the database configuration lines and add your connection details. +Prevent **phpunit.xml** from being tracked in your repo by adding it to +**.gitignore**. diff --git a/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php b/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php index faf98ca8..243f4682 100644 --- a/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php +++ b/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace Tests\Support\Database\Migrations; use CodeIgniter\Database\Migration; -use Override; class ExampleMigration extends Migration { @@ -14,28 +13,27 @@ class ExampleMigration extends Migration */ protected $DBGroup = 'tests'; - #[Override] public function up(): void { $fields = [ 'name' => [ - 'type' => 'varchar', + 'type' => 'varchar', 'constraint' => 31, ], 'uid' => [ - 'type' => 'varchar', + 'type' => 'varchar', 'constraint' => 31, ], 'class' => [ - 'type' => 'varchar', + 'type' => 'varchar', 'constraint' => 63, ], 'icon' => [ - 'type' => 'varchar', + 'type' => 'varchar', 'constraint' => 31, ], 'summary' => [ - 'type' => 'varchar', + 'type' => 'varchar', 'constraint' => 255, ], 'created_at' => [ @@ -63,7 +61,6 @@ class ExampleMigration extends Migration $this->forge->createTable('factories'); } - #[Override] public function down(): void { $this->forge->dropTable('factories'); diff --git a/tests/_support/Database/Seeds/ExampleSeeder.php b/tests/_support/Database/Seeds/ExampleSeeder.php index 52a4bed6..e519a913 100644 --- a/tests/_support/Database/Seeds/ExampleSeeder.php +++ b/tests/_support/Database/Seeds/ExampleSeeder.php @@ -5,33 +5,31 @@ declare(strict_types=1); namespace Tests\Support\Database\Seeds; use CodeIgniter\Database\Seeder; -use Override; class ExampleSeeder extends Seeder { - #[Override] public function run(): void { $factories = [ [ - 'name' => 'Test Factory', - 'uid' => 'test001', - 'class' => 'Factories\Tests\NewFactory', - 'icon' => 'fas fa-puzzle-piece', + 'name' => 'Test Factory', + 'uid' => 'test001', + 'class' => 'Factories\Tests\NewFactory', + 'icon' => 'fas fa-puzzle-piece', 'summary' => 'Longer sample text for testing', ], [ - 'name' => 'Widget Factory', - 'uid' => 'widget', - 'class' => 'Factories\Tests\WidgetPlant', - 'icon' => 'fas fa-puzzle-piece', + 'name' => 'Widget Factory', + 'uid' => 'widget', + 'class' => 'Factories\Tests\WidgetPlant', + 'icon' => 'fas fa-puzzle-piece', 'summary' => 'Create widgets in your factory', ], [ - 'name' => 'Evil Factory', - 'uid' => 'evil-maker', - 'class' => 'Factories\Evil\MyFactory', - 'icon' => 'fas fa-book-dead', + 'name' => 'Evil Factory', + 'uid' => 'evil-maker', + 'class' => 'Factories\Evil\MyFactory', + 'icon' => 'fas fa-book-dead', 'summary' => 'Abandon all hope, ye who enter here', ], ]; diff --git a/tests/_support/Database/Seeds/FakeSinglePodcastApiSeeder.php b/tests/_support/Database/Seeds/FakeSinglePodcastApiSeeder.php deleted file mode 100644 index 3fbd17c4..00000000 --- a/tests/_support/Database/Seeds/FakeSinglePodcastApiSeeder.php +++ /dev/null @@ -1,202 +0,0 @@ - 3, - 'file_key' => 'podcasts/test/1685531765_84fb3309111ece22ca37.mp3', - 'file_size' => '2737773', - 'file_mimetype' => 'audio/mpeg', - 'file_metadata' => '{"GETID3_VERSION":"2.0.x-202207161647","filesize":2737773,"filepath":"\\/tmp","filename":"php76vXQR","filenamepath":"\\/tmp\\/php76vXQR","avdataoffset":45,"avdataend":2737773,"fileformat":"mp3","audio":{"dataformat":"mp3","channels":2,"sample_rate":48000,"bitrate":128008.9774161874,"channelmode":"stereo","bitrate_mode":"cbr","lossless":false,"encoder_options":"CBR128","compression_ratio":0.08333917800533033,"streams":[{"dataformat":"mp3","channels":2,"sample_rate":48000,"bitrate":128008.9774161874,"channelmode":"stereo","bitrate_mode":"cbr","lossless":false,"encoder_options":"CBR128","compression_ratio":0.08333917800533033}]},"tags":{"id3v2":{"encoder_settings":["Lavf58.29.100"]}},"encoding":"UTF-8","id3v2":{"header":true,"flags":{"unsynch":false,"exthead":false,"experim":false,"isfooter":false},"majorversion":4,"minorversion":0,"headerlength":45,"tag_offset_start":0,"tag_offset_end":45,"encoding":"UTF-8","comments":{"encoder_settings":["Lavf58.29.100"]},"TSSE":[{"frame_name":"TSSE","frame_flags_raw":0,"data":"Lavf58.29.100","datalength":15,"dataoffset":10,"framenamelong":"Software\\/Hardware and settings used for encoding","framenameshort":"encoder_settings","flags":{"TagAlterPreservation":false,"FileAlterPreservation":false,"ReadOnly":false,"GroupingIdentity":false,"compression":false,"Encryption":false,"Unsynchronisation":false,"DataLengthIndicator":false},"encodingid":3,"encoding":"UTF-8"}],"padding":{"start":35,"length":10,"valid":true}},"mime_type":"audio\\/mpeg","mpeg":{"audio":{"raw":{"synch":4094,"version":3,"layer":1,"protection":1,"bitrate":5,"sample_rate":1,"padding":0,"private":0,"channelmode":0,"modeextension":0,"copyright":0,"original":0,"emphasis":0},"version":"1","layer":3,"channelmode":"stereo","channels":2,"sample_rate":48000,"protection":false,"private":false,"modeextension":"","copyright":false,"original":false,"emphasis":"none","padding":false,"bitrate":128008.9774161874,"framelength":384,"bitrate_mode":"cbr","VBR_method":"Xing","xing_flags_raw":15,"xing_flags":{"frames":true,"bytes":true,"toc":true,"vbr_scale":true},"VBR_frames":7129,"VBR_bytes":2737728,"toc":[0,3,5,8,10,13,16,18,20,22,26,28,31,33,36,39,41,43,45,49,51,54,56,59,62,64,66,68,72,74,77,79,82,85,87,89,91,95,97,99,102,105,108,110,112,114,118,120,122,125,128,131,133,135,137,141,143,145,148,150,153,156,158,160,164,166,168,171,173,176,179,181,183,187,189,191,194,196,199,202,204,206,210,212,214,217,219,222,225,227,229,233,235,237,240,242,245,248,250,252],"VBR_scale":0,"VBR_bitrate":128008.9774161874}},"playtime_seconds":171.0720016831475,"tags_html":{"id3v2":{"encoder_settings":["Lavf58.29.100"]}},"bitrate":128008.9774161874,"playtime_string":"2:51"}', - 'type' => 'audio', - 'description' => null, - 'language_code' => 'pl', - 'uploaded_by' => '1', - 'updated_by' => '1', - 'uploaded_at' => '2023-05-31 11:16:05', - 'updated_at' => '2023-05-31 11:16:05', - ]; - } - - /** - * @return array{id: int, file_key: string, file_size: int, file_mimetype: string, file_metadata: string, type: string, description: null, language_code: null, uploaded_by: int, updated_by: int, uploaded_at: string, updated_at: string} - */ - public static function cover(): array - { - return [ - 'id' => 1, - 'file_key' => 'podcasts/Handle/cover.jpg', - 'file_size' => 400000, - 'file_mimetype' => 'image/jpeg', - 'file_metadata' => '{"FILE":{"FileName":"cover.jpg","FileDateTime":1654861723,"FileSize":468541,"FileType":2,"MimeType":"image\/jpeg","SectionsFound":"COMMENT"},"COMPUTED":{"html":"width=\"1400\" height=\"1400\"","Height":1400,"Width":1400,"IsColor":1},"COMMENT":["CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 90\n"],"sizes":{"tiny":{"width":40,"height":40,"mimetype":"image\/webp","extension":"webp"},"thumbnail":{"width":150,"height":150,"mimetype":"image\/webp","extension":"webp"},"medium":{"width":320,"height":320,"mimetype":"image\/webp","extension":"webp"},"large":{"width":1024,"height":1024,"mimetype":"image\/webp","extension":"webp"},"feed":{"width":1400,"height":1400},"id3":{"width":500,"height":500},"og":{"width":1200,"height":1200},"federation":{"width":400,"height":400},"webmanifest192":{"width":192,"height":192,"mimetype":"image\/png","extension":"png"},"webmanifest512":{"width":512,"height":512,"mimetype":"image\/png","extension":"png"}}}', - 'type' => 'image', - 'description' => null, - 'language_code' => null, - 'uploaded_by' => 1, - 'updated_by' => 1, - 'uploaded_at' => '2022-06-13 8:00:00', - 'updated_at' => '2022-06-13 8:00:00', - ]; - } - - /** - * @return array{id: int, file_key: string, file_size: int, file_mimetype: string, file_metadata: string, type: string, description: null, language_code: null, uploaded_by: int, updated_by: int, uploaded_at: string, updated_at: string} - */ - public static function banner(): array - { - return [ - 'id' => 2, - 'file_key' => 'podcasts/Handle/banner.jpg', - 'file_size' => 400000, - 'file_mimetype' => 'image/jpeg', - 'file_metadata' => '{"FILE":{"FileName":"banner.jpg","FileDateTime":1654861724,"FileSize":98209,"FileType":2,"MimeType":"image\/jpeg","SectionsFound":""},"COMPUTED":{"html":"width=\"1500\" height=\"500\"","Height":500,"Width":1500,"IsColor":1},"sizes":{"small":{"width":320,"height":128,"mimetype":"image\/webp","extension":"webp"},"medium":{"width":960,"height":320,"mimetype":"image\/webp","extension":"webp"},"federation":{"width":1500,"height":500}}}', - 'type' => 'image', - 'description' => null, - 'language_code' => null, - 'uploaded_by' => 1, - 'updated_by' => 1, - 'uploaded_at' => '2022-06-13 8:00:00', - 'updated_at' => '2022-06-13 8:00:00', - ]; - } - - /** - * @return array{id: int, uri: string, username: string, domain: string|false, private_key: string, public_key: string, display_name: string, summary: string, avatar_image_url: string, avatar_image_mimetype: string, cover_image_url: null, cover_image_mimetype: null, inbox_url: string, outbox_url: string, followers_url: string, followers_count: int, posts_count: int, is_blocked: int, created_at: string, updated_at: string} - */ - public static function actor(): array - { - return [ - 'id' => 1, - 'uri' => getenv('app_baseURL') . '@Handle', - 'username' => 'Handle', - 'domain' => getenv('app_baseURL'), - 'private_key' => 'private_key', - 'public_key' => 'public_key', - 'display_name' => 'Title', - 'summary' => '

    description

    ', - 'avatar_image_url' => getenv('app_baseURL') . 'media/podcasts/Handle', - 'avatar_image_mimetype' => 'image/webp', - 'cover_image_url' => null, - 'cover_image_mimetype' => null, - 'inbox_url' => getenv('app_baseURL') . '@Handle/inbox', - 'outbox_url' => getenv('app_baseURL') . '@Handle/outbox', - 'followers_url' => getenv('app_baseURL') . '@Handle/followers', - 'followers_count' => 0, - 'posts_count' => 0, - 'is_blocked' => 0, - 'created_at' => '2022-06-13 8:00:00', - 'updated_at' => '2022-06-13 8:00:00', - ]; - } - - /** - * @return array{id: int, guid: string, actor_id: int, handle: string, title: string, description_markdown: string, description_html: string, cover_id: int, banner_id: int, language_code: string, category_id: int, parental_advisory: null, owner_name: string, owner_email: string, publisher: string, type: string, copyright: string, is_blocked: int, is_completed: int, is_locked: int, imported_feed_url: null, new_feed_url: null, location_name: null, location_geo: null, location_osm: null, is_published_on_hubs: int, created_by: int, updated_by: int, created_at: string, updated_at: string} - */ - public static function podcast(): array - { - return [ - 'id' => 1, - 'guid' => '0d341200-0234-5de7-99a6-a7d02bea4ce2', - 'actor_id' => 1, - 'handle' => 'Handle', - 'title' => 'Title', - 'description_markdown' => 'description', - 'description_html' => '

    description

    ', - 'cover_id' => 1, - 'banner_id' => 2, - 'language_code' => 'en', - 'category_id' => 1, - 'parental_advisory' => null, - 'owner_name' => 'Owner', - 'owner_email' => 'Owner@gmail.com', - 'publisher' => '', - 'type' => 'episodic', - 'copyright' => '', - 'is_blocked' => 0, - 'is_completed' => 0, - 'is_locked' => 1, - 'imported_feed_url' => null, - 'new_feed_url' => null, - 'location_name' => null, - 'location_geo' => null, - 'location_osm' => null, - 'is_published_on_hubs' => 0, - 'created_by' => 1, - 'updated_by' => 1, - 'created_at' => '2022-06-13 8:00:00', - 'updated_at' => '2022-06-13 8:00:00', - ]; - } - - /** - * @return array{id:int,podcast_id:int,guid:string,title:string,slug:string,audio_id:int,description_markdown:string,description_html:string,cover_id:int,transcript_id:null,transcript_remote_url:null,chapters_id:null,chapters_remote_url:null,parental_advisory:null,number:int,season_number:null,type:string,is_blocked:false,location_name:null,location_geo:null,location_osm:null,is_published_on_hubs:false,posts_count:int,comments_count:int,is_premium:false,created_by:int,updated_by:int,published_at:null,created_at:string,updated_at:string} - */ - public static function episode(): array - { - return [ - 'id' => 1, - 'podcast_id' => 1, - 'guid' => 'http://localhost:8080/@test/episodes/muzyka-marzen', - 'title' => 'Episode title', - 'slug' => 'episode-slug', - 'audio_id' => 3, - 'description_markdown' => '123', - 'description_html' => '

    123

    ', - 'cover_id' => 1, - 'transcript_id' => null, - 'transcript_remote_url' => null, - 'chapters_id' => null, - 'chapters_remote_url' => null, - 'parental_advisory' => null, - 'number' => 1, - 'season_number' => null, - 'type' => 'full', - 'is_blocked' => false, - 'location_name' => null, - 'location_geo' => null, - 'location_osm' => null, - 'is_published_on_hubs' => false, - 'posts_count' => 0, - 'comments_count' => 0, - 'is_premium' => false, - 'created_by' => 1, - 'updated_by' => 1, - 'published_at' => null, - 'created_at' => '2023-05-31 11:16:06', - 'updated_at' => '2023-05-31 11:16:06', - ]; - } - - #[Override] - public function run(): void - { - $this->call(AppSeeder::class); - $this->call(DevSeeder::class); - $this->db->table('media') - ->insert(self::cover()); - $this->db->table('media') - ->insert(self::banner()); - $this->db->table('media') - ->insert(self::audio()); - $this->db->table('fediverse_actors') - ->insert(self::actor()); - $this->db->table('podcasts') - ->insert(self::podcast()); - $this->db->table('episodes') - ->insert(self::episode()); - } -} diff --git a/tests/_support/Libraries/ConfigReader.php b/tests/_support/Libraries/ConfigReader.php index 9c9080e8..19a02db0 100644 --- a/tests/_support/Libraries/ConfigReader.php +++ b/tests/_support/Libraries/ConfigReader.php @@ -36,6 +36,8 @@ namespace Tests\Support\Libraries; use Config\App; /** + * Class ConfigReader + * * An extension of BaseConfig that prevents the constructor from loading external values. Used to read actual local * values from a config file. */ diff --git a/tests/_support/Models/ExampleModel.php b/tests/_support/Models/ExampleModel.php index 55d0e18c..aedcdd94 100644 --- a/tests/_support/Models/ExampleModel.php +++ b/tests/_support/Models/ExampleModel.php @@ -19,7 +19,7 @@ class ExampleModel extends Model protected $primaryKey = 'id'; /** - * @var 'object' + * @var string */ protected $returnType = 'object'; @@ -29,7 +29,7 @@ class ExampleModel extends Model protected $useSoftDeletes = false; /** - * @var list + * @var string[] */ protected $allowedFields = ['name', 'uid', 'class', 'icon', 'summary']; @@ -39,12 +39,12 @@ class ExampleModel extends Model protected $useTimestamps = true; /** - * @var array|string>|string>|string + * @var mixed[] */ protected $validationRules = []; /** - * @var array> + * @var mixed[] */ protected $validationMessages = []; diff --git a/tests/database/ExampleDatabaseTest.php b/tests/database/ExampleDatabaseTest.php index eda4a6eb..0108160d 100644 --- a/tests/database/ExampleDatabaseTest.php +++ b/tests/database/ExampleDatabaseTest.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace Tests\Database; -use CodeIgniter\Database\Seeder; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; use Tests\Support\Database\Seeds\ExampleSeeder; @@ -15,7 +14,7 @@ class ExampleDatabaseTest extends CIUnitTestCase use DatabaseTestTrait; /** - * @var class-string|list> + * @var string */ protected $seed = ExampleSeeder::class; @@ -37,15 +36,9 @@ class ExampleDatabaseTest extends CIUnitTestCase $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); $object = $model->first(); - - if (! is_object($object)) { - return; - } - $model->delete($object->id); // The model should no longer find it - // @phpstan-ignore-next-line $this->assertNull($model->find($object->id)); // ... but it should still be in the database diff --git a/tests/index.html b/tests/index.html deleted file mode 100644 index cf672743..00000000 --- a/tests/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - 403 Forbidden - - -

    Directory access is forbidden.

    - - diff --git a/tests/modules/Api/Rest/V1/EpisodeTest.php b/tests/modules/Api/Rest/V1/EpisodeTest.php deleted file mode 100644 index 990652f7..00000000 --- a/tests/modules/Api/Rest/V1/EpisodeTest.php +++ /dev/null @@ -1,120 +0,0 @@ -|list> - */ - protected $seed = FakeSinglePodcastApiSeeder::class; - - /** - * @var string - */ - protected $basePath = 'app/Database'; - - /** - * @var array - */ - private array $episode = []; - - private string $apiUrl = ''; - - #[Override] - protected function setUp(): void - { - parent::setUp(); - - $this->episode = FakeSinglePodcastApiSeeder::episode(); - - $this->episode['created_at'] = []; - $this->episode['updated_at'] = []; - $this->apiUrl = config('RestApi') - ->gateway; - } - - #[Override] - protected function tearDown(): void - { - parent::tearDown(); - - restore_error_handler(); - restore_exception_handler(); - } - - public function testList(): void - { - $result = $this->call('get', $this->apiUrl . 'episodes'); - $result->assertStatus(200); - $result->assertHeader('Content-Type', 'application/json; charset=UTF-8'); - $result->assertJSONFragment([ - 0 => $this->episode, - ]); - } - - public function testView(): void - { - $result = $this->call('get', $this->apiUrl . 'episodes/1'); - $result->assertStatus(200); - $result->assertHeader('Content-Type', 'application/json; charset=UTF-8'); - $result->assertJSONFragment($this->episode); - } - - public function testViewNotFound(): void - { - $result = $this->call('get', $this->apiUrl . 'episodes/2'); - $result->assertStatus(404); - $result->assertJSONExact( - [ - 'status' => 404, - 'error' => 404, - 'messages' => [ - 'error' => 'Episode not found', - ], - ], - ); - $result->assertHeader('Content-Type', 'application/json; charset=UTF-8'); - } - - /* - * Refreshing database to fetch empty array of episodes - */ - public function testListEmpty(): void - { - $this->regressDatabase(); - $this->migrateDatabase(); - $result = $this->call('get', $this->apiUrl . 'episodes'); - $result->assertStatus(200); - $result->assertHeader('Content-Type', 'application/json; charset=UTF-8'); - $result->assertJSONExact([]); - $this->seed($this->seed); - } -} diff --git a/tests/modules/Api/Rest/V1/PodcastTest.php b/tests/modules/Api/Rest/V1/PodcastTest.php index cdf5a446..ba6bc019 100644 --- a/tests/modules/Api/Rest/V1/PodcastTest.php +++ b/tests/modules/Api/Rest/V1/PodcastTest.php @@ -2,14 +2,12 @@ declare(strict_types=1); -namespace Tests\Modules\Api\Rest\V1; +namespace modules\Api\Rest\V1; -use CodeIgniter\Database\Seeder; +use App\Database\Seeds\FakeSinglePodcastApiSeeder; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; use CodeIgniter\Test\FeatureTestTrait; -use Override; -use Tests\Support\Database\Seeds\FakeSinglePodcastApiSeeder; class PodcastTest extends CIUnitTestCase { @@ -32,9 +30,9 @@ class PodcastTest extends CIUnitTestCase protected $namespace; /** - * @var class-string|list> + * @var string */ - protected $seed = FakeSinglePodcastApiSeeder::class; + protected $seed = 'FakeSinglePodcastApiSeeder'; /** * @var string @@ -46,13 +44,14 @@ class PodcastTest extends CIUnitTestCase */ private array $podcast = []; - private string $podcastApiUrl = ''; + private string $podcastApiUrl; - #[Override] - protected function setUp(): void + /** + * @param array $data + */ + public function __construct(?string $name = null, array $data = [], $dataName = '') { - parent::setUp(); - + parent::__construct($name, $data, $dataName); $this->podcast = FakeSinglePodcastApiSeeder::podcast(); $this->podcast['created_at'] = []; $this->podcast['updated_at'] = []; @@ -60,15 +59,6 @@ class PodcastTest extends CIUnitTestCase ->gateway; } - #[Override] - protected function tearDown(): void - { - parent::tearDown(); - - restore_error_handler(); - restore_exception_handler(); - } - public function testList(): void { $result = $this->call('get', $this->podcastApiUrl . 'podcasts'); @@ -93,12 +83,12 @@ class PodcastTest extends CIUnitTestCase $result->assertStatus(404); $result->assertJSONExact( [ - 'status' => 404, - 'error' => 404, + 'status' => 404, + 'error' => 404, 'messages' => [ 'error' => 'Podcast not found', ], - ], + ] ); $result->assertHeader('Content-Type', 'application/json; charset=UTF-8'); } diff --git a/tests/modules/Plugins/ManifestTest.php b/tests/modules/Plugins/ManifestTest.php deleted file mode 100644 index c5557e9b..00000000 --- a/tests/modules/Plugins/ManifestTest.php +++ /dev/null @@ -1,67 +0,0 @@ -assertNotEquals($manifest->name, 'acme/hello-world'); - $this->assertNotEquals($manifest->version, '1.0.0'); - - $manifest->loadFromFile(TESTPATH . 'modules/Plugins/mocks/manifests/manifest-required.json'); - - // no errors - $this->assertEmpty($manifest->getPluginErrors('acme/hello-world')); - - // properties have been set - $this->assertEquals($manifest->name, 'acme/hello-world'); - $this->assertEquals($manifest->version, '1.0.0'); - } - - public function testLoadEmptyData(): void - { - $manifest = new Manifest('acme/hello-world'); - - $manifest->loadFromFile(TESTPATH . 'modules/Plugins/mocks/manifests/manifest-empty.json'); - - $errors = $manifest->getPluginErrors('acme/hello-world'); - - $this->assertCount(2, $errors); - - // missing required name and version - $this->assertArrayHasKey('name', $errors); - $this->assertArrayHasKey('version', $errors); - } - - public function testLoadValidData(): void - { - $manifest = new Manifest('acme/hello-world'); - - $manifest->loadFromFile(TESTPATH . 'modules/Plugins/mocks/manifests/manifest-full-valid.json'); - - // no errors - $this->assertEmpty($manifest->getPluginErrors('acme/hello-world')); - } - - public function testLoadInvalidData(): void - { - $manifest = new Manifest('acme/hello-world'); - - $manifest->loadFromFile(TESTPATH . 'modules/Plugins/mocks/manifests/manifest-full-invalid.json'); - - // errors - $this->assertNotEmpty($manifest->getPluginErrors('acme/hello-world')); - } -} diff --git a/tests/modules/Plugins/PluginsTest.php b/tests/modules/Plugins/PluginsTest.php deleted file mode 100644 index 4594bbbe..00000000 --- a/tests/modules/Plugins/PluginsTest.php +++ /dev/null @@ -1,190 +0,0 @@ -folder = __DIR__ . '/mocks/plugins' . DIRECTORY_SEPARATOR; - - self::$plugins = new Plugins($pluginsConfig); - } - - public function testRegister(): void - { - $this->assertCount(7, self::$plugins->getAllPlugins()); - $this->assertEquals(7, self::$plugins->getInstalledCount()); - $this->assertEquals(0, self::$plugins->getActiveCount()); - } - - public function testActivateDeactivate(): void - { - $this->assertEquals(0, self::$plugins->getActiveCount()); - - $plugin = self::$plugins->getAllPlugins()[0]; - - // get first plugin and activate it - self::$plugins->activate($plugin); - - $this->assertEquals(1, self::$plugins->getActiveCount()); - $this->assertEquals(PluginStatus::ACTIVE, $plugin->getStatus()); - $this->seeInDatabase('settings', [ - 'class' => PluginsConfig::class, - 'key' => 'active', - 'value' => '1', - 'type' => 'boolean', - 'context' => 'plugin:' . $plugin->getKey(), - ]); - - // get first plugin and deactivate it - self::$plugins->deactivate($plugin); - - $this->assertEquals(0, self::$plugins->getActiveCount()); - $this->assertEquals(PluginStatus::INACTIVE, $plugin->getStatus()); - $this->seeInDatabase('settings', [ - 'class' => PluginsConfig::class, - 'key' => 'active', - 'value' => '0', - 'type' => 'boolean', - 'context' => 'plugin:' . $plugin->getKey(), - ]); - } - - public function testRunHooksActive(): void - { - $acmeAllHooksPlugin = self::$plugins->getPlugin('acme', 'all-hooks'); - - self::$plugins->activate($acmeAllHooksPlugin); - - $this->assertEquals(1, self::$plugins->getActiveCount()); - - $podcast = new Podcast(); - $this->assertEquals('', $podcast->title); - self::$plugins->runHook('rssBeforeChannel', [$podcast]); - $this->assertEquals('Podcast test', $podcast->title); - - $channel = new RssFeed(''); - $this->assertTrue(empty($channel->foo)); - self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]); - $this->assertFalse(empty($channel->foo)); - - $episode = new Episode(); - $this->assertEquals('', $episode->title); - self::$plugins->runHook('rssBeforeItem', [$episode]); - $this->assertEquals('Episode test', $episode->title); - - $item = new RssFeed(''); - $this->assertTrue(empty($item->efoo)); - self::$plugins->runHook('rssAfterItem', [$episode, $item]); - $this->assertFalse(empty($item->efoo)); - - $head = new HtmlHead(); - self::$plugins->runHook('siteHead', [$head]); - - $this->assertEquals( - (string) $head, - ' foo foo ', - ); - } - - public function testRunHooksInactive(): void - { - $acmeAllHooksPlugin = self::$plugins->getPlugin('acme', 'all-hooks'); - - self::$plugins->deactivate($acmeAllHooksPlugin); - - $this->assertEquals(0, self::$plugins->getActiveCount()); - - // nothing should change when running hooks as the plugin is inactive - - $podcast = new Podcast(); - $this->assertEquals('', $podcast->title); - self::$plugins->runHook('rssBeforeChannel', [$podcast]); - $this->assertEquals('', $podcast->title); - - $channel = new RssFeed(''); - $this->assertTrue(empty($channel->foo)); - self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]); - $this->assertTrue(empty($channel->foo)); - - $episode = new Episode(); - $this->assertEquals('', $episode->title); - self::$plugins->runHook('rssBeforeItem', [$episode]); - $this->assertEquals('', $episode->title); - - $item = new RssFeed(''); - $this->assertTrue(empty($item->efoo)); - self::$plugins->runHook('rssAfterItem', [$episode, $item]); - $this->assertTrue(empty($item->efoo)); - - ob_start(); - self::$plugins->runHook('siteHead', []); - $result = ob_get_contents(); - ob_end_clean(); //Discard output buffer - $this->assertEquals('', $result); - } - - public function testRunUndeclaredHook(): void - { - $acmeUndeclaredHookPlugin = self::$plugins->getPlugin('acme', 'undeclared-hook'); - - self::$plugins->activate($acmeUndeclaredHookPlugin); - - $podcast = new Podcast(); - $this->assertEquals('', $podcast->title); - self::$plugins->runHook('rssBeforeChannel', [$podcast]); - $this->assertEquals('Podcast test undeclared', $podcast->title); - - // rssAfterChannel has not been declared in plugin manifest, should not be running - $channel = new RssFeed(''); - $this->assertTrue(empty($channel->foo)); - self::$plugins->runHook('rssAfterChannel', [$podcast, $channel]); - $this->assertTrue(empty($channel->foo)); - } -} diff --git a/tests/modules/Plugins/mocks/manifests/manifest-empty.json b/tests/modules/Plugins/mocks/manifests/manifest-empty.json deleted file mode 100644 index 0967ef42..00000000 --- a/tests/modules/Plugins/mocks/manifests/manifest-empty.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/modules/Plugins/mocks/manifests/manifest-full-invalid.json b/tests/modules/Plugins/mocks/manifests/manifest-full-invalid.json deleted file mode 100644 index e13a5bc0..00000000 --- a/tests/modules/Plugins/mocks/manifests/manifest-full-invalid.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "name": "acme/hello-world", - "description": true, - "version": "1.0.0", - "authors": [ - { - "name": "Acme Corporation", - "email": "acme@example.com", - "url": "https://example.com/" - } - ], - "homepage": "https://example.com/", - "license": ["MIT", "AGPLv3"], - "keywords": ["seo", "analytics"], - "hooks": ["rssAfterChannel"], - "settings": { - "general": { - "name": { - "type": "radio-group", - "label": "Name", - "options": { - "foo": { "label": "Foo", "hint": "This is a hint." }, - "bar": { "label": "Bar" } - } - }, - "email": { - "type": "email", - "label": "Email" - }, - "url": { - "type": "url", - "label": "Your website URL" - }, - "toggler": { - "type": "toggler", - "label": "Toggle this?" - }, - "number": { - "type": "number", - "label": "Number" - }, - "datetime": { - "type": "datetime", - "label": "Enter a date", - "optional": true - }, - "select": { - "type": "select", - "label": "Select something", - "options": { - "foo": { - "label": "Foo" - }, - "bar": { - "label": "Bar" - }, - "baz": { - "label": "Baz" - } - } - }, - "select-multiple": { - "type": "select-multiple", - "label": "Select multiple things", - "options": { - "foo": { - "label": "Foo" - }, - "bar": { - "label": "Bar" - }, - "baz": { - "label": "Baz" - } - } - }, - "radio-group": { - "type": "radio-group", - "label": "Radio Group", - "helper": "This is a helper.", - "options": { - "foo": { - "label": "Foo" - }, - "bar": { - "label": "Bar" - }, - "baz": { - "label": "Baz" - } - } - }, - "texting": { - "type": "textarea", - "label": "Your text", - "hint": "This is a hint." - }, - "hello": { - "type": "markdown", - "label": "Name Podcast", - "hint": "This is a hint.", - "optional": true - } - }, - "podcast": { - "name": { - "type": "text", - "label": "Name Podcast", - "hint": "This is a hint." - } - }, - "episode": { - "name": { - "type": "text", - "label": "Name Episode", - "helper": "This is a helper." - } - } - } -} diff --git a/tests/modules/Plugins/mocks/manifests/manifest-full-valid.json b/tests/modules/Plugins/mocks/manifests/manifest-full-valid.json deleted file mode 100644 index f8223ba3..00000000 --- a/tests/modules/Plugins/mocks/manifests/manifest-full-valid.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "name": "acme/hello-world", - "description": "A Castopod plugin to add a hello world greeting to your RSS feed!", - "version": "1.0.0", - "authors": [ - { - "name": "Acme Corporation", - "email": "acme@example.com", - "url": "https://example.com/" - } - ], - "homepage": "https://example.com/", - "license": "MIT", - "keywords": ["seo", "analytics"], - "hooks": ["rssAfterChannel"], - "settings": { - "general": { - "name": { - "type": "radio-group", - "label": "Name", - "options": { - "foo": { "label": "Foo", "hint": "This is a hint." }, - "bar": { "label": "Bar" }, - "baz": { "label": "Baz" } - } - }, - "email": { - "type": "email", - "label": "Email" - }, - "url": { - "type": "url", - "label": "Your website URL" - }, - "toggler": { - "type": "toggler", - "label": "Toggle this?" - }, - "number": { - "type": "number", - "label": "Number" - }, - "datetime": { - "type": "datetime", - "label": "Enter a date", - "optional": true - }, - "select": { - "type": "select", - "label": "Select something", - "options": { - "foo": { - "label": "Foo" - }, - "bar": { - "label": "Bar" - }, - "baz": { - "label": "Baz" - } - } - }, - "select-multiple": { - "type": "select-multiple", - "label": "Select multiple things", - "options": { - "foo": { - "label": "Foo" - }, - "bar": { - "label": "Bar" - }, - "baz": { - "label": "Baz" - } - } - }, - "radio-group": { - "type": "radio-group", - "label": "Radio Group", - "helper": "This is a helper.", - "options": { - "foo": { - "label": "Foo" - }, - "bar": { - "label": "Bar" - }, - "baz": { - "label": "Baz" - } - } - }, - "textarea": { - "type": "textarea", - "label": "Your text", - "hint": "This is a hint." - }, - "markdown": { - "type": "markdown", - "label": "Markdown", - "hint": "This is a hint.", - "optional": true - } - }, - "podcast": { - "name": { - "type": "text", - "label": "Name Podcast", - "hint": "This is a hint." - } - }, - "episode": { - "name": { - "type": "text", - "label": "Name Episode", - "helper": "This is a helper." - } - } - } -} diff --git a/tests/modules/Plugins/mocks/manifests/manifest-required.json b/tests/modules/Plugins/mocks/manifests/manifest-required.json deleted file mode 100644 index 5272f045..00000000 --- a/tests/modules/Plugins/mocks/manifests/manifest-required.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "acme/hello-world", - "version": "1.0.0" -} diff --git a/tests/modules/Plugins/mocks/plugins/acme/all-hooks/Plugin.php b/tests/modules/Plugins/mocks/plugins/acme/all-hooks/Plugin.php deleted file mode 100644 index 53c93cdc..00000000 --- a/tests/modules/Plugins/mocks/plugins/acme/all-hooks/Plugin.php +++ /dev/null @@ -1,42 +0,0 @@ -title = 'Podcast test'; - } - - #[Override] - public function rssAfterChannel(Podcast $podcast, RssFeed $channel): void - { - $channel->addChild('foo', 'bar'); - } - - #[Override] - public function rssBeforeItem(Episode $episode): void - { - $episode->title = 'Episode test'; - } - - #[Override] - public function rssAfterItem(Episode $episode, RssFeed $item): void - { - $item->addChild('efoo', 'ebar'); - } - - #[Override] - public function siteHead(HtmlHead $head): void - { - $head->tag('title', 'foo'); - } -} diff --git a/tests/modules/Plugins/mocks/plugins/acme/all-hooks/manifest.json b/tests/modules/Plugins/mocks/plugins/acme/all-hooks/manifest.json deleted file mode 100644 index b564821b..00000000 --- a/tests/modules/Plugins/mocks/plugins/acme/all-hooks/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "acme/all-hooks", - "version": "1.0.0", - "hooks": [ - "rssBeforeChannel", - "rssAfterChannel", - "rssBeforeItem", - "rssAfterItem", - "siteHead" - ] -} diff --git a/tests/modules/Plugins/mocks/plugins/acme/empty-manifest/Plugin.php b/tests/modules/Plugins/mocks/plugins/acme/empty-manifest/Plugin.php deleted file mode 100644 index 4aaf8422..00000000 --- a/tests/modules/Plugins/mocks/plugins/acme/empty-manifest/Plugin.php +++ /dev/null @@ -1,9 +0,0 @@ -title = 'Podcast test undeclared'; - } - - #[Override] - public function rssAfterChannel(Podcast $podcast, RssFeed $channel): void - { - $channel->addChild('foo', 'bar'); - } -} diff --git a/tests/modules/Plugins/mocks/plugins/acme/undeclared-hook/manifest.json b/tests/modules/Plugins/mocks/plugins/acme/undeclared-hook/manifest.json deleted file mode 100644 index af9293ae..00000000 --- a/tests/modules/Plugins/mocks/plugins/acme/undeclared-hook/manifest.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "acme/all-hooks", - "version": "1.0.0", - "hooks": ["rssBeforeChannel"] -} diff --git a/tests/modules/Plugins/mocks/plugins/atlantis/empty/.gitkeep b/tests/modules/Plugins/mocks/plugins/atlantis/empty/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/modules/Plugins/mocks/plugins/atlantis/hello-broken/Plugin.php b/tests/modules/Plugins/mocks/plugins/atlantis/hello-broken/Plugin.php deleted file mode 100644 index 8309b442..00000000 --- a/tests/modules/Plugins/mocks/plugins/atlantis/hello-broken/Plugin.php +++ /dev/null @@ -1,9 +0,0 @@ -set('logged_in', 123); $this->assertSame(123, $session->get('logged_in')); diff --git a/tests/unit/HealthTest.php b/tests/unit/HealthTest.php index db2b46eb..b3b5dbce 100644 --- a/tests/unit/HealthTest.php +++ b/tests/unit/HealthTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); use CodeIgniter\Test\CIUnitTestCase; use Config\App; +use Config\Services; use Tests\Support\Libraries\ConfigReader; /** @@ -13,13 +14,12 @@ final class HealthTest extends CIUnitTestCase { public function testIsDefinedAppPath(): void { - /** @phpstan-ignore method.alreadyNarrowedType */ $this->assertTrue(defined('APPPATH')); } public function testBaseUrlHasBeenSet(): void { - $validation = service('validation'); + $validation = Services::validation(); $env = false; @@ -35,7 +35,7 @@ final class HealthTest extends CIUnitTestCase $config = new App(); $this->assertTrue( $validation->check($config->baseURL, 'valid_url_strict'), - 'baseURL "' . $config->baseURL . '" in .env is not valid URL', + 'baseURL "' . $config->baseURL . '" in .env is not valid URL' ); } @@ -46,7 +46,7 @@ final class HealthTest extends CIUnitTestCase // BaseURL in app/Config/App.php is a valid URL? $this->assertTrue( $validation->check($reader->baseURL, 'valid_url_strict'), - 'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL', + 'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL' ); } } diff --git a/themes/cp_admin/_layout.php b/themes/cp_admin/_layout.php index 6f78c843..d23a48a4 100644 --- a/themes/cp_admin/_layout.php +++ b/themes/cp_admin/_layout.php @@ -8,54 +8,53 @@ $isEpisodeArea = isset($podcast) && isset($episode); - + + + + + <?= $this->renderSection('title') ?> | Castopod Admin + + + + + + + ' /> + asset('styles/index.css', 'css') ?> + asset('js/admin.ts', 'js') ?> + asset('js/admin-audio-player.ts', 'js') ?> + include('_partials/_nav_header') ?> include('_partials/_nav_aside') ?>
    -
    -
    +
    +
    -
    +
    is_premium) || ($isPodcastArea && $podcast->is_premium)): ?>
    - - is_premium) ? lang('PremiumPodcasts.episode_is_premium') : lang('PremiumPodcasts.podcast_is_premium') ?> - renderSection('pageTitle') ?> + is_premium) ? lang('PremiumPodcasts.episode_is_premium') : lang('PremiumPodcasts.podcast_is_premium') ?> + renderSection('pageTitle') ?>
    - - renderSection('pageTitle') ?> - + + renderSection('pageTitle') ?> + renderSection('headerLeft') ?>
    renderSection('headerRight') ?>
    - renderSection('subtitle') ?>
    - - get('Import.current') === $podcast->handle): ?> - - - publication_status !== 'published'): ?> + publication_status !== 'published'): ?> published_at, $podcast->id, $podcast->publication_status) ?> - - - publication_status !== 'published'): ?> - - +
    renderSection('content') ?> diff --git a/themes/cp_admin/_message_block.php b/themes/cp_admin/_message_block.php index 42a34097..5f1ba623 100644 --- a/themes/cp_admin/_message_block.php +++ b/themes/cp_admin/_message_block.php @@ -1,33 +1,33 @@ has('message')): ?> - + has('error')): ?> - + has('errors')): ?> - +
    -
    + has('warning')): ?> - + has('warnings')): ?> - +
    -
    + diff --git a/themes/cp_admin/_partials/_nav_aside.php b/themes/cp_admin/_partials/_nav_aside.php index 0f2867b1..eddfc4b0 100644 --- a/themes/cp_admin/_partials/_nav_aside.php +++ b/themes/cp_admin/_partials/_nav_aside.php @@ -15,10 +15,9 @@ $isEpisodeArea = isset($podcast) && isset($episode); - + \ No newline at end of file diff --git a/themes/cp_admin/_partials/_nav_header.php b/themes/cp_admin/_partials/_nav_header.php index 38e25d2b..b3711aa9 100644 --- a/themes/cp_admin/_partials/_nav_header.php +++ b/themes/cp_admin/_partials/_nav_header.php @@ -1,57 +1,48 @@ -user()); ?> -
    + class="h-full pr-1 text-xl md:hidden focus:ring-accent focus:ring-inset" aria-label="">
    - - 'html', - 'content' => esc(<< 'html', + 'content' => esc(<<{$notificationsTitle} - HTML), - ], -]; + CODE_SAMPLE), + ], + ]; -if ($userPodcasts !== []) { - foreach ($userPodcasts as $userPodcast) { - $userPodcastTitle = esc($userPodcast->title); + if (user()->podcasts !== []) { + foreach (user()->podcasts as $userPodcast) { + $userPodcastTitle = esc($userPodcast->title); - $unreadNotificationDotDisplayClass = in_array($userPodcast->actor_id, $actorIdsWithUnreadNotifications, true) ? '' : 'hidden'; + $unreadNotificationDotDisplayClass = in_array($userPodcast->actor_id, user()->actorIdsWithUnreadNotifications, true) ? '' : 'hidden'; - $items[] = [ - 'type' => 'link', - 'title' => << 'link', + 'title' => <<
    @@ -59,100 +50,95 @@ if ($userPodcasts !== []) {
    {$userPodcastTitle}
    - HTML - , - 'uri' => route_to('notification-list', $userPodcast->id), - ]; - } -} else { - $noNotificationsText = lang('Notifications.no_notifications'); - $items[] = [ - 'type' => 'html', - 'content' => esc(<< route_to('notification-list', $userPodcast->id), + ]; + } + } else { + $noNotificationsText = lang('Notifications.no_notifications'); + $items[] = [ + 'type' => 'html', + 'content' => esc(<<{$noNotificationsText} - HTML), - ]; -} -?> - - + CODE_SAMPLE), + ]; + } + ?> + + + username) ?> +
    actor_id ? icon('check-fill', [ - 'class' => 'ml-2 bg-accent-base text-accent-contrast rounded-full', - ]) : ''; - $userPodcastTitle = esc($userPodcast->title); + $interactButtons = ''; + foreach (user()->podcasts as $userPodcast) { + $checkMark = interact_as_actor_id() === $userPodcast->actor_id ? icon('check', 'ml-2 bg-accent-base text-accent-contrast rounded-full') : ''; + $userPodcastTitle = esc($userPodcast->title); - $interactButtons .= <<
    {$userPodcastTitle}{$checkMark}
    - HTML; -} + CODE_SAMPLE; + } -$interactAsText = lang('Common.choose_interact'); -$interactAsRoute = route_to('interact-as-actor'); -$csrfField = csrf_field(); + $interactAsText = lang('Common.choose_interact'); + $route = route_to('interact-as-actor'); + $csrfField = csrf_field(); -$menuItems = [ - [ - 'type' => 'link', - 'title' => lang('Navigation.account.my-account'), - 'uri' => route_to('my-account'), - ], - [ - 'type' => 'link', - 'title' => lang('Navigation.account.change-password'), - 'uri' => route_to('change-password'), - ], - [ - 'type' => 'separator', - ], - [ - 'type' => 'link', - 'title' => lang('Navigation.account.logout'), - 'uri' => route_to('logout'), - ], -]; + $menuItems = [ + [ + 'type' => 'link', + 'title' => lang('Navigation.account.my-account'), + 'uri' => route_to('my-account'), + ], + [ + 'type' => 'link', + 'title' => lang('Navigation.account.change-password'), + 'uri' => route_to('change-password'), + ], + [ + 'type' => 'separator', + ], + [ + 'type' => 'link', + 'title' => lang('Navigation.account.logout'), + 'uri' => route_to('logout'), + ], + ]; -if ($userPodcasts !== []) { - $menuItems = array_merge([ - [ - 'type' => 'html', - 'content' => esc(<<podcasts !== []) { + $menuItems = array_merge([ + [ + 'type' => 'html', + 'content' => esc(<< {$interactAsText} -
    + {$csrfField} {$interactButtons}
    - HTML), - ], - [ - 'type' => 'separator', - ], - ], $menuItems); -} -?> - + CODE_SAMPLE), + ], + [ + 'type' => 'separator', + ], + ], $menuItems); + } + ?> +
    \ No newline at end of file diff --git a/themes/cp_admin/_partials/_nav_menu.php b/themes/cp_admin/_partials/_nav_menu.php deleted file mode 100644 index a646b81c..00000000 --- a/themes/cp_admin/_partials/_nav_menu.php +++ /dev/null @@ -1,65 +0,0 @@ - diff --git a/themes/cp_admin/_partials/_user_info.php b/themes/cp_admin/_partials/_user_info.php index 6bb3aebb..61871f6a 100644 --- a/themes/cp_admin/_partials/_user_info.php +++ b/themes/cp_admin/_partials/_user_info.php @@ -1,11 +1,3 @@ -
    -
    - -
    -
    - username) ?> -
    -
    @@ -14,12 +6,20 @@ email ?>
    +
    +
    + +
    +
    + username) ?> +
    +
    - getGroups()) ?> + roles) ?>
    @@ -27,6 +27,6 @@
    - getPermissions()) ?> + permissions) ?>
    diff --git a/themes/cp_admin/_sidebar.php b/themes/cp_admin/_sidebar.php index 76c80c5e..f557e5e9 100644 --- a/themes/cp_admin/_sidebar.php +++ b/themes/cp_admin/_sidebar.php @@ -1,105 +1,56 @@ [ - 'icon' => 'dashboard-fill', // @icon("dashboard-fill") + 'icon' => 'dashboard', 'items' => ['admin'], ], 'podcasts' => [ - 'icon' => 'mic-fill', // @icon("mic-fill") - 'items' => ['podcast-list', 'podcast-create', 'all-podcast-imports', 'podcast-imports-add'], - 'items-permissions' => [ - 'podcast-create' => 'podcasts.create', - 'all-podcast-imports' => 'podcasts.import', - 'podcast-imports-add' => 'podcasts.import', - ], - 'add-cta' => 'podcast-create', - 'count-route' => 'podcast-list', - ], - 'plugins' => [ - 'icon' => 'puzzle-fill', // @icon("puzzle-fill") - 'items' => ['plugins-installed'], - 'items-labels' => [ - 'plugins-installed' => lang('Navigation.plugins-installed') . ' (' . service('plugins')->getInstalledCount() . ')', - ], - 'items-permissions' => [ - 'plugins-installed' => 'plugins.manage', - ], - 'count' => service('plugins')->getActiveCount(), - 'count-route' => 'plugins-installed', + 'icon' => 'mic', + 'items' => ['podcast-list', 'podcast-create', 'podcast-import'], ], 'persons' => [ - 'icon' => 'folder-user-fill', // @icon("folder-user-fill") - 'items' => ['person-list', 'person-create'], - 'items-permissions' => [ - 'person-list' => 'persons.manage', - 'person-create' => 'persons.manage', - ], - 'add-cta' => 'person-create', - 'count' => (new PersonModel())->countAllResults(), - 'count-route' => 'person-list', + 'icon' => 'folder-user', + 'items' => ['person-list', 'person-create'], ], 'fediverse' => [ - 'icon' => 'rocket-2-fill', // @icon("rocket-2-fill") - 'items' => ['fediverse-blocked-actors', 'fediverse-blocked-domains'], - 'items-permissions' => [ - 'fediverse-blocked-actors' => 'fediverse.manage-blocks', - 'fediverse-blocked-domains' => 'fediverse.manage-blocks', - ], + 'icon' => 'star-smile', + 'items' => ['fediverse-blocked-actors', 'fediverse-blocked-domains'], ], 'users' => [ - 'icon' => 'group-fill', // @icon("group-fill") - 'items' => ['user-list', 'user-create'], - 'items-permissions' => [ - 'user-list' => 'users.manage', - 'user-create' => 'users.manage', - ], - 'add-cta' => 'user-create', - 'count' => (new UserModel())->countAllResults(), - 'count-route' => 'user-list', + 'icon' => 'group', + 'items' => ['user-list', 'user-create'], ], 'pages' => [ - 'icon' => 'pages-fill', // @icon("pages-fill") - 'items' => ['page-list', 'page-create'], - 'items-permissions' => [ - 'page-list' => 'pages.manage', - 'page-create' => 'pages.manage', - ], - 'add-cta' => 'page-create', - 'count' => (new PageModel())->countAllResults(), - 'count-route' => 'page-list', + 'icon' => 'pages', + 'items' => ['page-list', 'page-create'], + ], 'settings' => [ - 'icon' => 'settings-3-fill', // @icon("settings-3-fill") - 'items' => ['settings-general', 'settings-theme', 'admin-about'], - 'items-permissions' => [ - 'settings-general' => 'admin.settings', - 'settings-theme' => 'admin.settings', - 'admin-about' => 'admin.settings', - ], + 'icon' => 'settings', + 'items' => ['settings-general', 'settings-theme'], ], -]; +]; ?> -foreach (plugins()->getActivePlugins() as $plugin) { - $route = route_to('plugins-view', $plugin->getVendor(), $plugin->getPackage()); - $navigation['plugins']['items'][] = $route; - $navigation['plugins']['items-labels'][$route] = $plugin->getTitle(); - $navigation['plugins']['items-permissions'][$route] = 'plugins.manage'; -} - -if (auth()->user()->can('podcasts.view')) { - $navigation['podcasts']['count'] = (new PodcastModel())->countAllResults(); -} else { - $navigation['podcasts']['count'] = count(get_user_podcasts(auth()->user())); -} ?> - - - $navigation, - 'langKey' => 'Navigation', -]) ?> + diff --git a/themes/cp_admin/contributor/create.php b/themes/cp_admin/contributor/add.php similarity index 57% rename from themes/cp_admin/contributor/create.php rename to themes/cp_admin/contributor/add.php index 123036f1..ef2325bb 100644 --- a/themes/cp_admin/contributor/create.php +++ b/themes/cp_admin/contributor/add.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> +title)]) ?> +endSection() ?> + section('pageTitle') ?> title)]) ?> endSection() ?> @@ -10,24 +14,23 @@
    - + required="true" /> - + required="true" /> - + diff --git a/themes/cp_admin/contributor/edit.php b/themes/cp_admin/contributor/edit.php index 33eb9101..edfed841 100644 --- a/themes/cp_admin/contributor/edit.php +++ b/themes/cp_admin/contributor/edit.php @@ -1,25 +1,29 @@ extend('_layout') ?> +section('title') ?> +username)]) ?> +endSection() ?> + section('pageTitle') ?> -username)]) ?> +username)]) ?> endSection() ?> section('content') ?> -
    + - + required="true" /> - + diff --git a/themes/cp_admin/contributor/list.php b/themes/cp_admin/contributor/list.php index d8546fa1..6ad44137 100644 --- a/themes/cp_admin/contributor/list.php +++ b/themes/cp_admin/contributor/list.php @@ -1,12 +1,15 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> section('headerRight') ?> - - + endSection() ?> @@ -16,29 +19,21 @@ [ [ 'header' => lang('Contributor.list.username'), - 'cell' => function ($contributor) { + 'cell' => function ($contributor) { return esc($contributor->username); }, ], [ 'header' => lang('Contributor.list.role'), - 'cell' => function ($contributor, $podcast): string { - $role = get_group_info(get_podcast_group($contributor, $podcast->id), $podcast->id)['title']; - - if ($podcast->created_by === $contributor->id) { - $role = '
    ' . icon('shield-user-fill') . '' . $role . '
    '; - } - - return $role; + 'cell' => function ($contributor): string { + return lang('Contributor.roles.' . $contributor->podcast_role); }, ], [ 'header' => lang('Common.actions'), - 'cell' => function ($contributor, $podcast) { - // @icon("pencil-fill") - // @icon("delete-bin-fill") - return '' . lang('Contributor.edit') . '' . - '' . lang('Contributor.remove') . ''; + 'cell' => function ($contributor, $podcast) { + return '' . + ''; }, ], ], diff --git a/themes/cp_admin/contributor/remove.php b/themes/cp_admin/contributor/remove.php deleted file mode 100644 index 0f4fdea6..00000000 --- a/themes/cp_admin/contributor/remove.php +++ /dev/null @@ -1,31 +0,0 @@ -extend('_layout') ?> - -section('pageTitle') ?> - $contributor->username, -]) ?> -endSection() ?> - -section('content') ?> - -
    - - - $contributor->username, - 'podcastTitle' => $podcast->title, -]) ?> - - $contributor->username, - 'podcastTitle' => $podcast->title, -]) ?> - -
    - - -
    - -
    - -endSection() ?> diff --git a/themes/cp_admin/contributor/view.php b/themes/cp_admin/contributor/view.php index fe0fa793..71bd3b1e 100644 --- a/themes/cp_admin/contributor/view.php +++ b/themes/cp_admin/contributor/view.php @@ -1,8 +1,15 @@ extend('_layout') ?> +section('title') ?> + esc($contributor->username), + 'podcastTitle' => esc($podcast->title), +]) ?> +endSection() ?> + section('pageTitle') ?> esc($contributor->username), + 'username' => esc($contributor->username), 'podcastTitle' => esc($podcast->title), ]) ?> endSection() ?> diff --git a/themes/cp_admin/dashboard.php b/themes/cp_admin/dashboard.php index 6a8a3bac..e3f6222c 100644 --- a/themes/cp_admin/dashboard.php +++ b/themes/cp_admin/dashboard.php @@ -1,36 +1,36 @@ + extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> section('content') ?> -
    - - + - - + - - + % + 'totalStorage' => $storageData['limit'], + ]) ?>">%
    - - - 'w-8 pl-2 text-2xl rounded-r-full rounded-tl-lg text-accent-contrast bg-accent-base', - ]) ?> + published_at, $episode->publication_status, 'text-sm'); ?>
    @@ -19,61 +17,59 @@ title) ?>
- + 'link', + 'type' => 'link', 'title' => lang('Episode.go_to_page'), - 'uri' => route_to('episode', esc($episode->podcast->handle), esc($episode->slug)), + 'uri' => route_to('episode', esc($episode->podcast->handle), esc($episode->slug)), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Episode.edit'), - 'uri' => route_to('episode-edit', $episode->podcast->id, $episode->id), + 'uri' => route_to('episode-edit', $episode->podcast->id, $episode->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Episode.embed.title'), - 'uri' => route_to('embed-add', $episode->podcast->id, $episode->id), + 'uri' => route_to('embed-add', $episode->podcast->id, $episode->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Person.persons'), - 'uri' => route_to('episode-persons-manage', $episode->podcast->id, $episode->id), + 'uri' => route_to('episode-persons-manage', $episode->podcast->id, $episode->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('VideoClip.list.title'), - 'uri' => route_to('video-clips-list', $episode->podcast->id, $episode->id), + 'uri' => route_to('video-clips-list', $episode->podcast->id, $episode->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Soundbite.list.title'), - 'uri' => route_to('soundbites-list', $episode->podcast->id, $episode->id), + 'uri' => route_to('soundbites-list', $episode->podcast->id, $episode->id), ], [ 'type' => 'separator', ], ]; -if ($episode->published_at === null) { - $items[] = [ - 'type' => 'link', - 'title' => lang('Episode.delete'), - 'uri' => route_to('episode-delete', $episode->podcast->id, $episode->id), - 'class' => 'font-semibold text-red-600', - ]; -} else { - $label = lang('Episode.delete'); - $icon = icon('forbid-fill', [ - 'class' => 'mr-2', - ]); - $title = lang('Episode.messages.unpublishBeforeDeleteTip'); - $items[] = [ - 'type' => 'html', - 'content' => esc(<<published_at === null) { + $items[] = [ + 'type' => 'link', + 'title' => lang('Episode.delete'), + 'uri' => route_to('episode-delete', $episode->podcast->id, $episode->id), + 'class' => 'font-semibold text-red-600', + ]; + } else { + $label = lang('Episode.delete'); + $icon = icon('forbid', 'mr-2'); + $title = lang('Episode.messages.unpublishBeforeDeleteTip'); + $items[] = [ + 'type' => 'html', + 'content' => esc(<<{$icon}{$label} - HTML), - ]; -} ?> - + CODE_SAMPLE), + ]; + } ?> + \ No newline at end of file diff --git a/themes/cp_admin/episode/_sidebar.php b/themes/cp_admin/episode/_sidebar.php index fd0ef42b..fc3291e8 100644 --- a/themes/cp_admin/episode/_sidebar.php +++ b/themes/cp_admin/episode/_sidebar.php @@ -1,50 +1,18 @@ [ - 'icon' => 'dashboard-fill', // @icon("dashboard-fill") - 'items' => ['episode-view', 'episode-edit', 'episode-persons-manage', 'embed-add'], - 'items-permissions' => [ - 'episode-view' => 'episodes.view', - 'episode-edit' => 'episodes.edit', - 'episode-persons-manage' => 'episodes.manage-persons', - 'embed-add' => 'episodes.edit', - ], - ], - 'plugins' => [ - 'icon' => 'puzzle-fill', // @icon("puzzle-fill") - 'items' => [], - 'items-labels' => [], - 'items-permissions' => [], + 'icon' => 'dashboard', + 'items' => ['episode-view', 'episode-edit', 'episode-persons-manage', 'embed-add'], ], 'clips' => [ - 'icon' => 'clapperboard-fill', // @icon("clapperboard-fill") - 'items' => ['video-clips-list', 'video-clips-create', 'soundbites-list', 'soundbites-create'], - 'items-permissions' => [ - 'video-clips-list' => 'episodes.manage-clips', - 'video-clips-create' => 'episodes.manage-clips', - 'soundbites-list' => 'episodes.manage-clips', - 'soundbites-create' => 'episodes.manage-clips', - ], - 'count' => $episode->getClipCount(), - 'count-route' => 'video-clips-list', - 'add-cta' => 'video-clips-create', + 'icon' => 'clapperboard', + 'items' => ['video-clips-list', 'video-clips-create', 'soundbites-list', 'soundbites-create'], ], -]; +]; ?> -foreach (plugins()->getPluginsWithEpisodeSettings() as $plugin) { - $route = route_to('plugins-settings-episode', $plugin->getVendor(), $plugin->getPackage(), $podcast->id, $episode->id); - $episodeNavigation['plugins']['items'][] = $route; - $episodeNavigation['plugins']['items-labels'][$route] = $plugin->getTitle(); - $episodeNavigation['plugins']['items-permissions'][$route] = 'episodes.edit'; -} - -?> - - - 'mr-2', - ]) ?> + + <?= esc($podcast->title) ?>getPluginsWithEpisodeSettings() as $plugin) {
is_premium): ?> - 'absolute pl-1 text-xl rounded-r-full rounded-tl-lg left-4 top-4 text-accent-contrast bg-accent-base', - ]) ?> + getPluginsWithEpisodeSettings() as $plugin) {
- - $episodeNavigation, - 'langKey' => 'EpisodeNavigation', - 'podcastId' => $podcast->id, - 'episodeId' => $episode->id, -]) ?> + diff --git a/themes/cp_admin/episode/create.php b/themes/cp_admin/episode/create.php index bac39db6..4953d28b 100644 --- a/themes/cp_admin/episode/create.php +++ b/themes/cp_admin/episode/create.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -11,143 +15,148 @@ - + - - - - +
+ + + handle) . '/episodes') . '/' ?> + + +
- -
- + + + hint="" + isChecked="true" > + + + - + + + + - -
+ isChecked="true" > + + + - + + + - - + - - - - + - + + + + + - - + label="" + hint="" /> + -
(' . lang('Common.optional') . - ')' ?> + ')' . + hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?>
/> @@ -157,12 +166,12 @@
- - + +
- - + +
@@ -173,7 +182,8 @@ (' . lang('Common.optional') . - ')' ?> + ')' . + hint_tooltip(lang('Episode.form.chapters_hint'), 'ml-1') ?>
/> @@ -183,29 +193,34 @@
- - + +
- - + +
- + - + - + - + - - + diff --git a/themes/cp_admin/episode/delete.php b/themes/cp_admin/episode/delete.php index 7121d222..786ae3ff 100644 --- a/themes/cp_admin/episode/delete.php +++ b/themes/cp_admin/episode/delete.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -9,13 +13,13 @@
- + - +
- - + +
diff --git a/themes/cp_admin/episode/edit.php b/themes/cp_admin/episode/edit.php index ab57b79d..ab7d6a44 100644 --- a/themes/cp_admin/episode/edit.php +++ b/themes/cp_admin/episode/edit.php @@ -1,11 +1,15 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> section('headerRight') ?> - + endSection() ?> @@ -15,151 +19,147 @@ - + - - - - + required="true" + data-slugify="title" /> - +
+ + + handle) . '/episodes') . '/' ?> + + +
- -
- + + + hint="" + isChecked="type === 'full' ? 'true' : 'false' ?>" > + + + - + + + + + isChecked="parental_advisory === null ? 'true' : 'false' ?>" > + + + -
+ - - - + - - - - + - + + + + + - - + -
(' . lang('Common.optional') . - ')' ?> + ')' . + hint_tooltip(lang('Episode.form.transcript_hint'), 'ml-1') ?>
transcript_remote_url ? '' : 'checked' ?> /> @@ -172,40 +172,37 @@ transcript) : ?>
transcript->file_url, - icon('file-download-fill', [ - 'class' => 'mr-1 text-skin-muted text-xl', - ]) . lang('Episode.form.transcript_download'), - [ - 'class' => 'flex-1 font-semibold hover:underline inline-flex items-center text-xs', - 'download' => '', - ], - ) . + $episode->transcript->file_url, + icon('file-download', 'mr-1 text-skin-muted text-xl') . lang('Episode.form.transcript_download'), + [ + 'class' => 'flex-1 font-semibold hover:underline inline-flex items-center text-xs', + 'download' => '', + ], + ) . anchor( route_to( 'transcript-delete', $podcast->id, $episode->id, ), - icon('delete-bin-fill', [ - 'class' => 'mx-auto', - ]), + icon('delete-bin', 'mx-auto'), [ - 'class' => 'p-1 text-sm bg-red-100 rounded-full text-red-700 hover:text-red-900', + 'class' => + 'p-1 text-sm bg-red-100 rounded-full text-red-700 hover:text-red-900 focus:ring-accent', 'data-tooltip' => 'bottom', - 'title' => lang( + 'title' => lang( 'Episode.form.transcript_file_delete', ), ], ) ?>
- - + +
- - + +
@@ -216,7 +213,8 @@ (' . lang('Common.optional') . - ')' ?> + ')' . + hint_tooltip(lang('Episode.form.chapters_hint'), 'ml-1') ?>
chapters_remote_url ? '' : 'checked' ?> /> @@ -229,63 +227,65 @@ chapters) : ?>
chapters->file_url, - icon('file-download-fill', [ - 'class' => 'mr-1 text-skin-muted text-xl', - ]) . lang('Episode.form.chapters_download'), - [ - 'class' => 'flex-1 font-semibold hover:underline inline-flex items-center text-xs', - 'download' => '', - ], - ) . + $episode->chapters->file_url, + icon('file-download', 'mr-1 text-skin-muted text-xl') . lang('Episode.form.chapters_download'), + [ + 'class' => 'flex-1 font-semibold hover:underline inline-flex items-center text-xs', + 'download' => '', + ], + ) . anchor( route_to( 'chapters-delete', $podcast->id, $episode->id, ), - icon('delete-bin-fill', [ - 'class' => 'mx-auto', - ]), + icon('delete-bin', 'mx-auto'), [ - 'class' => 'text-sm p-1 bg-red-100 rounded-full text-red-700 hover:text-red-900', + 'class' => + 'text-sm p-1 bg-red-100 rounded-full text-red-700 hover:text-red-900 focus:ring-accent', 'data-tooltip' => 'bottom', - 'title' => lang( + 'title' => lang( 'Episode.form.chapters_file_delete', ), ], ) ?>
- - + +
- - + +
- + - + - + - + published_at === null): ?> - - + - - + diff --git a/themes/cp_admin/episode/embed.php b/themes/cp_admin/episode/embed.php index d64e65e4..f633a04a 100644 --- a/themes/cp_admin/episode/embed.php +++ b/themes/cp_admin/episode/embed.php @@ -1,11 +1,9 @@ -height; - -?> - extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -29,15 +27,13 @@ $embedHeight = config('Embed')->height;
- embed_url}\">") ?>" /> - - + embed_url}\">") ?>" /> +
- - - + +
endSection() ?> diff --git a/themes/cp_admin/episode/list.php b/themes/cp_admin/episode/list.php index 7c6f6e80..ff82cdfe 100644 --- a/themes/cp_admin/episode/list.php +++ b/themes/cp_admin/episode/list.php @@ -1,12 +1,15 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> section('headerRight') ?> - - + endSection() ?> @@ -19,38 +22,33 @@ ]) ?>
$pager->getDetails()['currentPage'], - 'pageCount' => $pager->getDetails()['pageCount'], + 'pageCount' => $pager->getDetails()['pageCount'], ]) ?>

- 'text-xl', - ]) ?> +
- lang('Episode.list.episode'), - 'cell' => function ($episode, $podcast) { + 'cell' => function ($episode, $podcast) { $premiumBadge = ''; if ($episode->is_premium) { - $premiumBadge = icon('exchange-dollar-fill', [ - 'class' => 'absolute left-0 w-8 pl-2 text-2xl rounded-r-full rounded-tl-lg top-2 text-accent-contrast bg-accent-base', - ]); + $premiumBadge = ''; } - return '
' . - '
' . + return '
' . + '
' . '
'; }, ], [ 'header' => lang('Episode.list.visibility'), - 'cell' => function ($episode): string { + 'cell' => function ($episode): string { return publication_pill( $episode->published_at, $episode->publication_status, - 'text-sm', ); }, ], - [ - 'header' => lang('Episode.list.downloads'), - 'cell' => function ($episode): string { - return downloads_abbr($episode->downloads_count); - }, - ], [ 'header' => lang('Episode.list.comments'), - 'cell' => function ($episode): int { + 'cell' => function ($episode): int { return $episode->comments_count; }, ], [ 'header' => lang('Episode.list.actions'), - 'cell' => function ($episode, $podcast) { + 'cell' => function ($episode, $podcast) { $items = [ [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Episode.go_to_page'), - 'uri' => route_to('episode', esc($podcast->handle), esc($episode->slug)), + 'uri' => route_to('episode', esc($podcast->handle), esc($episode->slug)), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Episode.edit'), - 'uri' => route_to('episode-edit', $podcast->id, $episode->id), + 'uri' => route_to('episode-edit', $podcast->id, $episode->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Episode.embed.title'), - 'uri' => route_to('embed-add', $podcast->id, $episode->id), + 'uri' => route_to('embed-add', $podcast->id, $episode->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Person.persons'), - 'uri' => route_to('episode-persons-manage', $podcast->id, $episode->id), + 'uri' => route_to('episode-persons-manage', $podcast->id, $episode->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('VideoClip.list.title'), - 'uri' => route_to('video-clips-list', $episode->podcast->id, $episode->id), + 'uri' => route_to('video-clips-list', $episode->podcast->id, $episode->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Soundbite.list.title'), - 'uri' => route_to('soundbites-list', $podcast->id, $episode->id), + 'uri' => route_to('soundbites-list', $podcast->id, $episode->id), ], [ 'type' => 'separator', @@ -140,32 +131,32 @@ ]; if ($episode->published_at === null) { $items[] = [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Episode.delete'), - 'uri' => route_to('episode-delete', $podcast->id, $episode->id), + 'uri' => route_to('episode-delete', $podcast->id, $episode->id), 'class' => 'font-semibold text-red-600', ]; } else { $label = lang('Episode.delete'); - $icon = icon('forbid-fill'); + $icon = icon('forbid'); $title = lang('Episode.messages.unpublishBeforeDeleteTip'); $items[] = [ - 'type' => 'html', - 'content' => esc(<< 'html', + 'content' => esc(<<{$icon}{$label} - HTML), + CODE_SAMPLE), ]; } - return '' . - ''; + ''; }, ], ], $episodes, 'mb-6 mt-4', - $podcast, + $podcast ) ?> links() ?> diff --git a/themes/cp_admin/episode/persons.php b/themes/cp_admin/episode/persons.php index 0a182c70..05e0a619 100644 --- a/themes/cp_admin/episode/persons.php +++ b/themes/cp_admin/episode/persons.php @@ -1,12 +1,15 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> (persons) ?>) endSection() ?> section('headerRight') ?> - - + endSection() ?> section('content') ?> @@ -14,35 +17,36 @@
- - - - + - +
@@ -50,11 +54,11 @@ [ [ 'header' => lang('Person.episode_form.persons'), - 'cell' => function ($person) { + 'cell' => function ($person) { return '
' . '' . esc($person->full_name) . '' . + '">' . esc($person->full_name) . '' . '
' . esc($person->full_name) . implode( @@ -81,14 +85,13 @@ ], [ 'header' => lang('Common.actions'), - 'cell' => function ($person): string { - // @icon("delete-bin-fill") - return '' . lang('Person.episode_form.remove') . ''; + 'cell' => function ($person): string { + return ''; }, ], ], $episode->persons, - 'max-w-xl mt-6', + 'max-w-xl mt-6' ) ?> endSection() ?> diff --git a/themes/cp_admin/episode/publish.php b/themes/cp_admin/episode/publish.php index c06d60cc..50cc5049 100644 --- a/themes/cp_admin/episode/publish.php +++ b/themes/cp_admin/episode/publish.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -8,11 +12,9 @@ id, $episode->id), - icon('arrow-left-line', [ - 'class' => 'mr-2 text-lg', - ]) . lang('Episode.publish_form.back_to_episode_dashboard'), + icon('arrow-left', 'mr-2 text-lg') . lang('Episode.publish_form.back_to_episode_dashboard'), [ - 'class' => 'inline-flex items-center font-semibold mr-4 text-sm', + 'class' => 'inline-flex items-center font-semibold mr-4 text-sm focus:ring-accent', ], ) ?> @@ -35,7 +37,7 @@
- +
title) ?> number, - $episode->season_number, - 'text-xs font-semibold text-skin-muted !no-underline border px-1 border-gray-500', - true, - ) ?> + $episode->number, + $episode->season_number, + 'text-xs font-semibold text-skin-muted !no-underline border px-1 border-gray-500', + true, + ) ?>
- 'mr-1 text-xl opacity-40', - ]) ?>0 - 'mr-1 text-xl opacity-40', - ]) ?>0 - 'mr-1 text-xl opacity-40', - ]) ?>0 + 0 + 0 + 0
@@ -78,18 +74,18 @@ - +
/> - +
-
@@ -97,11 +93,11 @@ - +
- - + +
diff --git a/themes/cp_admin/episode/publish_date_edit.php b/themes/cp_admin/episode/publish_date_edit.php index 281f9f32..7346e659 100644 --- a/themes/cp_admin/episode/publish_date_edit.php +++ b/themes/cp_admin/episode/publish_date_edit.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -8,9 +12,7 @@ id, $episode->id), - icon('arrow-left-line', [ - 'class' => 'mr-2 text-lg', - ]) . lang('Episode.publish_form.back_to_episode_dashboard'), + icon('arrow-left', 'mr-2 text-lg') . lang('Episode.publish_form.back_to_episode_dashboard'), [ 'class' => 'inline-flex items-center font-semibold mr-4 text-sm', ], @@ -20,16 +22,16 @@ - - + diff --git a/themes/cp_admin/episode/publish_edit.php b/themes/cp_admin/episode/publish_edit.php index 0d9ccf49..216d1e70 100644 --- a/themes/cp_admin/episode/publish_edit.php +++ b/themes/cp_admin/episode/publish_edit.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -8,9 +12,7 @@ id, $episode->id), - icon('arrow-left-line', [ - 'class' => 'mr-2 text-lg', - ]) . lang('Episode.publish_form.back_to_episode_dashboard'), + icon('arrow-left', 'mr-2 text-lg') . lang('Episode.publish_form.back_to_episode_dashboard'), [ 'class' => 'inline-flex items-center font-semibold mr-4 text-sm', ], @@ -37,7 +39,7 @@
- +
title) ?> number, - $episode->season_number, - 'text-xs font-semibold text-skin-muted !no-underline border px-1 border-gray-500', - true, - ) ?> + $episode->number, + $episode->season_number, + 'text-xs font-semibold text-skin-muted !no-underline border px-1 border-gray-500', + true, + ) ?>
published_at) ?> @@ -65,35 +67,29 @@
- 'mr-1 text-xl opacity-40', - ]) ?>0 - 'mr-1 text-xl opacity-40', - ]) ?>0 - 'mr-1 text-xl opacity-40', - ]) ?>0 + 0 + 0 + 0
publication_status === 'published'): ?>
- + 'Episode.publish_form.publication_date', + ) ?> +
/> - +
-
@@ -101,11 +97,11 @@
- +
- - + +
diff --git a/themes/cp_admin/episode/soundbites_list.php b/themes/cp_admin/episode/soundbites_list.php index bff27821..8a7c090f 100644 --- a/themes/cp_admin/episode/soundbites_list.php +++ b/themes/cp_admin/episode/soundbites_list.php @@ -1,12 +1,15 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> section('headerRight') ?> - - + endSection() ?> section('content') ?> @@ -15,21 +18,21 @@ [ [ 'header' => lang('Soundbite.list.soundbite'), - 'cell' => function ($soundbite): string { + 'cell' => function ($soundbite): string { return '
' . esc($soundbite->title) . '' . format_duration((int) $soundbite->duration) . '
'; }, ], [ 'header' => lang('Common.actions'), - 'cell' => function ($soundbite): string { - return '' . - 'id . '-menu" labelledby="more-dropdown-' . $soundbite->id . '" offsetY="-24" items="' . esc(json_encode([ [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('Soundbite.delete'), - 'uri' => route_to('soundbites-delete', $soundbite->podcast_id, $soundbite->episode_id, $soundbite->id), + 'uri' => route_to('soundbites-delete', $soundbite->podcast_id, $soundbite->episode_id, $soundbite->id), 'class' => 'font-semibold text-red-600', ], ])) . '" />'; diff --git a/themes/cp_admin/episode/soundbites_new.php b/themes/cp_admin/episode/soundbites_new.php index a3114777..f5609494 100644 --- a/themes/cp_admin/episode/soundbites_new.php +++ b/themes/cp_admin/episode/soundbites_new.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -10,13 +14,13 @@
- - + @@ -24,8 +28,7 @@ - - + diff --git a/themes/cp_admin/episode/unpublish.php b/themes/cp_admin/episode/unpublish.php index 5d6d0048..e0fb7aa8 100644 --- a/themes/cp_admin/episode/unpublish.php +++ b/themes/cp_admin/episode/unpublish.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -9,13 +13,13 @@
- + - +
- - + +
diff --git a/themes/cp_admin/episode/video_clip.php b/themes/cp_admin/episode/video_clip.php index 40dbebc6..cc536f20 100644 --- a/themes/cp_admin/episode/video_clip.php +++ b/themes/cp_admin/episode/video_clip.php @@ -1,5 +1,11 @@ extend('_layout') ?> +section('title') ?> + esc($videoClip->title), +]) ?> +endSection() ?> + section('pageTitle') ?> esc($videoClip->title), diff --git a/themes/cp_admin/episode/video_clips_list.php b/themes/cp_admin/episode/video_clips_list.php index b6fa6958..c55fcb54 100644 --- a/themes/cp_admin/episode/video_clips_list.php +++ b/themes/cp_admin/episode/video_clips_list.php @@ -6,13 +6,16 @@ use CodeIgniter\I18n\Time; ?> extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> section('headerRight') ?> - - + endSection() ?> section('content') ?> @@ -20,66 +23,60 @@ use CodeIgniter\I18n\Time; [ [ 'header' => lang('VideoClip.list.status.label'), - 'cell' => function ($videoClip): string { + 'cell' => function ($videoClip): string { $pillVariantMap = [ - 'queued' => 'default', - 'pending' => 'warning', - 'running' => 'primary', + 'queued' => 'default', + 'pending' => 'warning', + 'running' => 'primary', 'canceled' => 'default', - 'failed' => 'danger', - 'passed' => 'success', + 'failed' => 'danger', + 'passed' => 'success', ]; $pillIconMap = [ - 'queued' => 'timer-fill', // @icon("timer-fill") - 'pending' => 'pause-fill', // @icon("pause-fill") - 'running' => 'loader-fill', // @icon("loader-fill") - 'canceled' => 'forbid-fill', // @icon("forbid-fill") - 'failed' => 'close-fill', // @icon("close-fill") - 'passed' => 'check-fill', // @icon("check-fill") + 'queued' => 'timer', + 'pending' => 'pause', + 'running' => 'loader', + 'canceled' => 'forbid', + 'failed' => 'close', + 'passed' => 'check', ]; $pillIconClassMap = [ - 'queued' => '', - 'pending' => '', - 'running' => 'animate-spin', + 'queued' => '', + 'pending' => '', + 'running' => 'animate-spin', 'canceled' => '', - 'failed' => '', - 'passed' => '', + 'failed' => '', + 'passed' => '', ]; - return '' . lang('VideoClip.list.status.' . $videoClip->status) . ''; + return '' . lang('VideoClip.list.status.' . $videoClip->status) . ''; }, ], [ 'header' => lang('VideoClip.list.clip'), - 'cell' => function ($videoClip): string { + 'cell' => function ($videoClip): string { $formatClass = [ 'landscape' => 'aspect-video', - 'portrait' => 'aspect-[9/16]', - 'squared' => 'aspect-square', + 'portrait' => 'aspect-[9/16]', + 'squared' => 'aspect-square', ]; - return '
' . icon('play-fill') . '
#' . $videoClip->id . ' – ' . esc($videoClip->title) . 'by ' . esc($videoClip->user->username) . '
' . format_duration((int) $videoClip->duration) . '
'; + return '
#' . $videoClip->id . ' – ' . esc($videoClip->title) . 'by ' . esc($videoClip->user->username) . '
' . format_duration((int) $videoClip->duration) . '
'; }, ], [ 'header' => lang('VideoClip.list.duration'), - 'cell' => function (VideoClip $videoClip): string { + 'cell' => function (VideoClip $videoClip): string { $duration = ''; if ($videoClip->job_started_at !== null) { if ($videoClip->job_ended_at !== null) { $duration = '
' . - '
' . icon('timer-fill', [ - 'class' => 'text-sm text-gray-400', - ]) . format_duration((int) $videoClip->job_duration, true) . '
' . - '
' . icon('calendar-fill', [ - 'class' => 'text-sm text-gray-400', - ]) . relative_time($videoClip->job_ended_at) . '
' . + '
' . format_duration((int) $videoClip->job_duration, true) . '
' . + '
' . relative_time($videoClip->job_ended_at) . '
' . '
'; } else { - $duration = '
' . icon('timer-fill', [ - 'class' => 'text-sm text-gray-400', - ]) . format_duration(($videoClip->job_started_at->difference(Time::now()))->getSeconds(), true) . '
'; + $duration = '
' . format_duration(($videoClip->job_started_at->difference(Time::now()))->getSeconds(), true) . '
'; } } @@ -88,37 +85,36 @@ use CodeIgniter\I18n\Time; ], [ 'header' => lang('Common.actions'), - 'cell' => function ($videoClip): string { + 'cell' => function ($videoClip): string { $downloadButton = ''; if ($videoClip->media) { helper('misc'); $filename = 'clip-' . slugify($videoClip->title) . "-{$videoClip->start_time}-{$videoClip->end_time}"; - // @icon("import-fill") - $downloadButton = '' . lang('VideoClip.download_clip') . ''; + $downloadButton = '' . lang('VideoClip.download_clip') . ''; } return '
' . $downloadButton . - '' . - 'id . '-menu" labelledby="more-dropdown-' . $videoClip->id . '" offsetY="-24" items="' . esc(json_encode([ [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('VideoClip.go_to_page'), - 'uri' => route_to('video-clip', $videoClip->podcast_id, $videoClip->episode_id, $videoClip->id), + 'uri' => route_to('video-clip', $videoClip->podcast_id, $videoClip->episode_id, $videoClip->id), ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('VideoClip.retry'), - 'uri' => route_to('video-clip-retry', $videoClip->podcast_id, $videoClip->episode_id, $videoClip->id), + 'uri' => route_to('video-clip-retry', $videoClip->podcast_id, $videoClip->episode_id, $videoClip->id), ], [ 'type' => 'separator', ], [ - 'type' => 'link', + 'type' => 'link', 'title' => lang('VideoClip.delete'), - 'uri' => route_to('video-clip-delete', $videoClip->podcast_id, $videoClip->episode_id, $videoClip->id), + 'uri' => route_to('video-clip-delete', $videoClip->podcast_id, $videoClip->episode_id, $videoClip->id), 'class' => 'font-semibold text-red-600', ], ])) . '" />' . @@ -127,7 +123,7 @@ use CodeIgniter\I18n\Time; ], ], $videoClips, - 'mb-6', + 'mb-6' ) ?> links() ?> diff --git a/themes/cp_admin/episode/video_clips_new.php b/themes/cp_admin/episode/video_clips_new.php index 24f0e1e9..3f3ca52a 100644 --- a/themes/cp_admin/episode/video_clips_new.php +++ b/themes/cp_admin/episode/video_clips_new.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -13,7 +17,7 @@ <?= $episode->cover->description ?> - + @@ -23,48 +27,47 @@
- - +
- - + - + + required="true" + hint="">
themes as $themeName => $colors): ?> - + required="true" + isChecked="" + style="--color-accent-base: ; --color-background-preview: ">
-
- - + +
diff --git a/themes/cp_admin/episode/video_clips_requirements.php b/themes/cp_admin/episode/video_clips_requirements.php index d1b41435..f9c714aa 100644 --- a/themes/cp_admin/episode/video_clips_requirements.php +++ b/themes/cp_admin/episode/video_clips_requirements.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -8,20 +12,14 @@
- 'flex-shrink-0 text-xl text-orange-600', - ]) ?> +

$value): ?> -
'mr-1 text-white rounded-full bg-pine-500', - ]) ?>
+
-
'mr-1 text-white bg-red-500 rounded-full', - ]) ?>
+
diff --git a/themes/cp_admin/episode/view.php b/themes/cp_admin/episode/view.php index c6392a36..6357011e 100644 --- a/themes/cp_admin/episode/view.php +++ b/themes/cp_admin/episode/view.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> +title) ?> +endSection() ?> + section('pageTitle') ?> title) ?> endSection() ?> @@ -8,19 +12,18 @@ published_at, $episode->publication_status, - 'text-sm align-middle', + 'text-sm ml-2 align-middle', ) ?> endSection() ?> section('headerRight') ?> publication_status === 'published'): ?> - - +> id, @@ -37,21 +40,21 @@
- + - +
diff --git a/themes/cp_admin/fediverse/blocked_actors.php b/themes/cp_admin/fediverse/blocked_actors.php index 7232de3d..f8ddb350 100644 --- a/themes/cp_admin/fediverse/blocked_actors.php +++ b/themes/cp_admin/fediverse/blocked_actors.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -10,25 +14,21 @@
- - + + lang('Fediverse.list.actor'), - 'cell' => function ($blockedActor) { + 'cell' => function ($blockedActor) { return esc($blockedActor->username); }, ], [ 'header' => lang('Common.actions'), - 'cell' => function ($blockedActor) { + 'cell' => function ($blockedActor) { return '
' . @@ -36,13 +36,13 @@ $blockedActor->id . '" />' . csrf_field() . - '' . lang('Fediverse.list.unblock') . '' . + '' . '
'; }, ], ], $blockedActors, - 'mt-8', + 'mt-8' ) ?> diff --git a/themes/cp_admin/fediverse/blocked_domains.php b/themes/cp_admin/fediverse/blocked_domains.php index 51a2049b..2a80d81e 100644 --- a/themes/cp_admin/fediverse/blocked_domains.php +++ b/themes/cp_admin/fediverse/blocked_domains.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -10,24 +14,21 @@
- - + + lang('Fediverse.list.actor'), - 'cell' => function ($blockedDomain) { + 'cell' => function ($blockedDomain) { return esc($blockedDomain->name); }, ], [ 'header' => lang('Common.actions'), - 'cell' => function ($blockedDomain) { + 'cell' => function ($blockedDomain) { return '
' . @@ -35,13 +36,13 @@ esc($blockedDomain->name) . '" />' . csrf_field() . - '' . lang('Fediverse.list.unblock') . '' . + '' . '
'; }, ], ], $blockedDomains, - 'mt-8', + 'mt-8' ) ?> endSection() ?> diff --git a/themes/cp_admin/import/_queue_table.php b/themes/cp_admin/import/_queue_table.php deleted file mode 100644 index 742fd10b..00000000 --- a/themes/cp_admin/import/_queue_table.php +++ /dev/null @@ -1,146 +0,0 @@ - - - lang('PodcastImport.queue.status.label'), - 'cell' => function (PodcastImportTask $importTask) { - $pillVariantMap = [ - 'queued' => 'default', - 'pending' => 'warning', - 'running' => 'primary', - 'canceled' => 'default', - 'failed' => 'danger', - 'passed' => 'success', - ]; - - $pillIconMap = [ - 'queued' => 'timer-fill', // @icon("timer-fill") - 'pending' => 'pause-fill', // @icon("pause-fill") - 'running' => 'loader-fill', // @icon("loader-fill") - 'canceled' => 'forbid-fill', // @icon("forbid-fill") - 'failed' => 'close-fill', // @icon("close-fill") - 'passed' => 'check-fill', // @icon("check-fill") - ]; - - $pillIconClassMap = [ - 'queued' => '', - 'pending' => '', - 'running' => 'animate-spin', - 'canceled' => '', - 'failed' => '', - 'passed' => '', - ]; - - $errorHint = $importTask->status === TaskStatus::Failed ? '' . esc($importTask->error) . '' : ''; - - return '
' . lang('PodcastImport.queue.status.' . $importTask->status->value) . '' . $errorHint . '
'; - }, - ], - [ - 'header' => lang('PodcastImport.queue.feed'), - 'cell' => function (PodcastImportTask $importTask) { - $externalLink = icon('external-link-fill', [ - 'class' => 'ml-1', - ]); - return << - {$importTask->feed_url}{$externalLink} - @{$importTask->handle} -
- HTML; - }, - ], - [ - 'header' => lang('PodcastImport.queue.duration'), - 'cell' => function (PodcastImportTask $importTask) { - $duration = '-'; - if ($importTask->started_at !== null) { - if ($importTask->ended_at !== null) { - $duration = '
' . - '
' . icon('timer-fill', [ - 'class' => 'text-sm text-gray-400', - ]) . format_duration((int) $importTask->getDuration(), true) . '
' . - '
' . icon('calendar-fill', [ - 'class' => 'text-sm text-gray-400', - ]) . relative_time($importTask->ended_at) . '
' . - '
'; - } else { - $duration = '
' . icon('timer-fill', [ - 'class' => 'text-sm text-gray-400', - ]) . format_duration(($importTask->started_at->difference(Time::now()))->getSeconds(), true) . '
'; - } - } - - return $duration; - }, - ], - [ - 'header' => lang('PodcastImport.queue.imported_episodes'), - 'cell' => function (PodcastImportTask $importTask) { - if ($importTask->episodes_count) { - $progressPercentage = (int) ($importTask->getProgress() * 100) . '%'; - $moreInfoHelper = '' . lang('PodcastImport.queue.imported_episodes_hint', [ - 'newlyImportedCount' => $importTask->episodes_newly_imported, - 'alreadyImportedCount' => $importTask->episodes_already_imported, - ]) . ''; - return << - {$progressPercentage} -

- {$importTask->episodes_imported} out of {$importTask->episodes_count} - {$moreInfoHelper} -

-
- HTML; - } - - return '-'; - }, - ], - [ - 'header' => lang('Common.list.actions'), - 'cell' => function (PodcastImportTask $importTask) { - $menuItems = [ - [ - 'type' => 'separator', - ], - [ - 'type' => 'link', - 'title' => lang('PodcastImport.queue.actions.delete'), - 'uri' => route_to('podcast-imports-task-action', $importTask->id, 'delete'), - 'class' => 'font-semibold text-red-600', - ], - ]; - - if ($importTask->status === TaskStatus::Running || $importTask->status === TaskStatus::Queued) { - array_unshift($menuItems, [ - 'type' => 'link', - 'title' => lang('PodcastImport.queue.actions.cancel'), - 'uri' => route_to('podcast-imports-task-action', $importTask->id, 'cancel'), - ]); - } else { - array_unshift($menuItems, [ - 'type' => 'link', - 'title' => lang('PodcastImport.queue.actions.retry'), - 'uri' => route_to('podcast-imports-task-action', $importTask->id, 'retry'), - ], ); - } - - return '
' . - '' . - '' . - '
'; - }, - ], - ], - $podcastImportsQueue, -) ?> diff --git a/themes/cp_admin/import/add_to_queue.php b/themes/cp_admin/import/add_to_queue.php deleted file mode 100644 index 9a706bd7..00000000 --- a/themes/cp_admin/import/add_to_queue.php +++ /dev/null @@ -1,61 +0,0 @@ -extend('_layout') ?> - -section('pageTitle') ?> - -endSection() ?> - -section('content') ?> - -
- - - - - - - - - - - -
- -
- 'absolute inset-0 h-full text-xl opacity-40 left-3', - ]) ?> - -
-
- - - - - -
- - - -
- - -endSection() ?> diff --git a/themes/cp_admin/import/podcast_queue.php b/themes/cp_admin/import/podcast_queue.php deleted file mode 100644 index a1aa7b6e..00000000 --- a/themes/cp_admin/import/podcast_queue.php +++ /dev/null @@ -1,16 +0,0 @@ -extend('_layout') ?> - -section('pageTitle') ?> - -endSection() ?> - -section('headerRight') ?> - - -endSection() ?> - -section('content') ?> - -include('import/_queue_table'); ?> - -endSection() ?> diff --git a/themes/cp_admin/import/podcast_sync.php b/themes/cp_admin/import/podcast_sync.php deleted file mode 100644 index 5a57600e..00000000 --- a/themes/cp_admin/import/podcast_sync.php +++ /dev/null @@ -1,20 +0,0 @@ -extend('_layout') ?> - -section('pageTitle') ?> - -endSection() ?> - -section('content') ?> -
- - - - - -endSection() ?> diff --git a/themes/cp_admin/import/queue.php b/themes/cp_admin/import/queue.php deleted file mode 100644 index 06c96968..00000000 --- a/themes/cp_admin/import/queue.php +++ /dev/null @@ -1,17 +0,0 @@ -extend('_layout') ?> - -section('pageTitle') ?> - -endSection() ?> - -section('headerRight') ?> - - -endSection() ?> - - -section('content') ?> - -include('import/_queue_table'); ?> - -endSection() ?> diff --git a/themes/cp_admin/my_account/change_password.php b/themes/cp_admin/my_account/change_password.php index 7c41193e..cbafc732 100644 --- a/themes/cp_admin/my_account/change_password.php +++ b/themes/cp_admin/my_account/change_password.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -9,18 +13,18 @@
- - - + endSection() ?> diff --git a/themes/cp_admin/my_account/view.php b/themes/cp_admin/my_account/view.php index 46ebb1c8..c329ea71 100644 --- a/themes/cp_admin/my_account/view.php +++ b/themes/cp_admin/my_account/view.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -8,8 +12,7 @@ section('content') ?> auth() - ->user(), + 'user' => user(), ]) ?> endSection() ?> diff --git a/themes/cp_admin/page/create.php b/themes/cp_admin/page/create.php index 64789484..50c6351b 100644 --- a/themes/cp_admin/page/create.php +++ b/themes/cp_admin/page/create.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -10,29 +14,29 @@
- - +
+ + + + + +
- - + diff --git a/themes/cp_admin/page/edit.php b/themes/cp_admin/page/edit.php index 36b65daf..e1864e21 100644 --- a/themes/cp_admin/page/edit.php +++ b/themes/cp_admin/page/edit.php @@ -1,5 +1,9 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> endSection() ?> @@ -10,33 +14,32 @@
- - +
+ + + + + +
- - + diff --git a/themes/cp_admin/page/list.php b/themes/cp_admin/page/list.php index b03b5e20..3d5d1ec0 100644 --- a/themes/cp_admin/page/list.php +++ b/themes/cp_admin/page/list.php @@ -1,12 +1,15 @@ extend('_layout') ?> +section('title') ?> + +endSection() ?> + section('pageTitle') ?> () endSection() ?> section('headerRight') ?> - - + endSection() ?> @@ -16,7 +19,7 @@ [ [ 'header' => lang('Page.page'), - 'cell' => function ($page) { + 'cell' => function ($page) { return '
' . esc($page->title) . '/' . @@ -26,10 +29,10 @@ ], [ 'header' => lang('Common.actions'), - 'cell' => function ($page) { - return '' . lang('Page.go_to_page') . '' . - '' . lang('Page.edit') . '' . - '' . lang('Page.delete') . ''; + 'cell' => function ($page) { + return '' . + '' . + ''; }, ], ], diff --git a/themes/cp_admin/page/view.php b/themes/cp_admin/page/view.php index 74f001f1..abc918ae 100644 --- a/themes/cp_admin/page/view.php +++ b/themes/cp_admin/page/view.php @@ -1,12 +1,15 @@ extend('_layout') ?> +section('title') ?> +title) ?> +endSection() ?> + section('pageTitle') ?> title) ?> endSection() ?> section('headerRight') ?> - - + endSection() ?> section('content') ?> diff --git a/themes/cp_admin/person/_card.php b/themes/cp_admin/person/_card.php index b4506c8c..20408bb5 100644 --- a/themes/cp_admin/person/_card.php +++ b/themes/cp_admin/person/_card.php @@ -2,31 +2,31 @@
- <?= esc($person->full_name) ?> + <?= esc($person->full_name) ?>

full_name) ?>

- -