Merge branch 'kb_migration' into kb_development
This commit is contained in:
commit
1461ab0a2f
37 changed files with 1045 additions and 316 deletions
|
@ -1,31 +1,29 @@
|
||||||
// For more details, see https://aka.ms/devcontainer.json.
|
|
||||||
{
|
{
|
||||||
"name": "Mastodon",
|
"name": "Mastodon",
|
||||||
"dockerComposeFile": "docker-compose.yml",
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
"service": "app",
|
"service": "app",
|
||||||
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||||
|
|
||||||
// Features to add to the dev container. More info: https://containers.dev/features.
|
|
||||||
"features": {
|
"features": {
|
||||||
"ghcr.io/devcontainers/features/sshd:1": {}
|
"ghcr.io/devcontainers/features/sshd:1": {}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
"runServices": ["app", "db", "redis"],
|
||||||
// This can be used to network with other containers or the host.
|
|
||||||
"forwardPorts": [3000, 4000],
|
"forwardPorts": [3000, 4000],
|
||||||
|
|
||||||
// Use 'postCreateCommand' to run commands after the container is created.
|
"containerEnv": {
|
||||||
|
"ES_ENABLED": "",
|
||||||
|
"LIBRE_TRANSLATE_ENDPOINT": ""
|
||||||
|
},
|
||||||
|
|
||||||
"onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
|
"onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
|
||||||
"postCreateCommand": ".devcontainer/post-create.sh",
|
"postCreateCommand": ".devcontainer/post-create.sh",
|
||||||
"waitFor": "postCreateCommand",
|
"waitFor": "postCreateCommand",
|
||||||
|
|
||||||
// Configure tool-specific properties.
|
|
||||||
"customizations": {
|
"customizations": {
|
||||||
// Configure properties specific to VS Code.
|
|
||||||
"vscode": {
|
"vscode": {
|
||||||
// Set *default* container specific settings.json values on container create.
|
|
||||||
"settings": {},
|
"settings": {},
|
||||||
// Add the IDs of extensions you want installed when the container is created.
|
|
||||||
"extensions": ["EditorConfig.EditorConfig", "webben.browserslist"]
|
"extensions": ["EditorConfig.EditorConfig", "webben.browserslist"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
33
CHANGELOG.md
33
CHANGELOG.md
|
@ -8,6 +8,9 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- **Add “Privacy and reach” tab in profile settings** ([Gargron](https://github.com/mastodon/mastodon/pull/26484), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26508))
|
||||||
|
This reorganized scattered privacy and reach settings to a single place, as well as improve their wording.
|
||||||
|
- **Add display of out-of-band hashtags in the web interface** ([Gargron](https://github.com/mastodon/mastodon/pull/26492), [arbolitoloco1](https://github.com/mastodon/mastodon/pull/26497), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26506), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26525))
|
||||||
- **Add role badges to the web interface** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25649), [Gargron](https://github.com/mastodon/mastodon/pull/26281))
|
- **Add role badges to the web interface** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25649), [Gargron](https://github.com/mastodon/mastodon/pull/26281))
|
||||||
- **Add ability to pick domains to forward reports to using the `forward_to_domains` parameter in `POST /api/v1/reports`** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25866))
|
- **Add ability to pick domains to forward reports to using the `forward_to_domains` parameter in `POST /api/v1/reports`** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25866))
|
||||||
The `forward_to_domains` REST API parameter is a list of strings. If it is empty or omitted, the previous behavior is maintained.
|
The `forward_to_domains` REST API parameter is a list of strings. If it is empty or omitted, the previous behavior is maintained.
|
||||||
|
@ -23,8 +26,18 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- **Add optional hCaptcha support** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25019), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25057), [Gargron](https://github.com/mastodon/mastodon/pull/25395), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26388))
|
- **Add optional hCaptcha support** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25019), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25057), [Gargron](https://github.com/mastodon/mastodon/pull/25395), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26388))
|
||||||
- **Add lines to threads in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24549), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24677), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24696), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24711), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24714), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24713), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24715), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24800), [teeerevor](https://github.com/mastodon/mastodon/pull/25706), [renchap](https://github.com/mastodon/mastodon/pull/25807))
|
- **Add lines to threads in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24549), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24677), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24696), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24711), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24714), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24713), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24715), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24800), [teeerevor](https://github.com/mastodon/mastodon/pull/25706), [renchap](https://github.com/mastodon/mastodon/pull/25807))
|
||||||
- **Add new onboarding flow to web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24619), [Gargron](https://github.com/mastodon/mastodon/pull/24646), [Gargron](https://github.com/mastodon/mastodon/pull/24705), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24872), [ThisIsMissEm](https://github.com/mastodon/mastodon/pull/24883), [Gargron](https://github.com/mastodon/mastodon/pull/24954), [stevenjlm](https://github.com/mastodon/mastodon/pull/24959), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25010), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25275), [Gargron](https://github.com/mastodon/mastodon/pull/25559), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25561))
|
- **Add new onboarding flow to web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24619), [Gargron](https://github.com/mastodon/mastodon/pull/24646), [Gargron](https://github.com/mastodon/mastodon/pull/24705), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24872), [ThisIsMissEm](https://github.com/mastodon/mastodon/pull/24883), [Gargron](https://github.com/mastodon/mastodon/pull/24954), [stevenjlm](https://github.com/mastodon/mastodon/pull/24959), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25010), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25275), [Gargron](https://github.com/mastodon/mastodon/pull/25559), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25561))
|
||||||
|
- **Add `S3_DISABLE_CHECKSUM_MODE` environment variable for compatibility with some S3-compatible providers** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26435))
|
||||||
|
- **Add auto-refresh of accounts we get new messages/edits of** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26510))
|
||||||
|
- **Add Elasticsearch cluster health check and indexes mismatch check to dashboard** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26448))
|
||||||
|
- Add support for `indexable` attribute on remote actors ([Gargron](https://github.com/mastodon/mastodon/pull/26485))
|
||||||
|
- Add `DELETE /api/v1/profile/avatar` and `DELETE /api/v1/profile/header` to the REST API ([danielmbrasil](https://github.com/mastodon/mastodon/pull/25124), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26573))
|
||||||
|
- Add `ES_PRESET` option to customize numbers of shards and replicas ([Gargron](https://github.com/mastodon/mastodon/pull/26483), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26489))
|
||||||
|
This can have a value of `single_node_cluster` (default), `small_cluster` (uses one replica) or `large_cluster` (uses one replica and a higher number of shards).
|
||||||
|
- Add missing `instances` option to `tootctl search deploy` ([tribela](https://github.com/mastodon/mastodon/pull/26461))
|
||||||
|
- Add `CACHE_BUSTER_HTTP_METHOD` environment variable ([renchap](https://github.com/mastodon/mastodon/pull/26528), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26542))
|
||||||
|
- Add support for `DB_PASS` when using `DATABASE_URL` ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/26295))
|
||||||
- Add `GET /api/v1/instance/languages` to REST API ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24443))
|
- Add `GET /api/v1/instance/languages` to REST API ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24443))
|
||||||
- Add primary key to `preview_cards_statuses` join table ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25243), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26384))
|
- Add primary key to `preview_cards_statuses` join table ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25243), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26384), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26447))
|
||||||
- Add client-side timeout on resend confirmation button ([Gargron](https://github.com/mastodon/mastodon/pull/26300))
|
- Add client-side timeout on resend confirmation button ([Gargron](https://github.com/mastodon/mastodon/pull/26300))
|
||||||
- Add published date and author to news on the explore screen in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26155))
|
- Add published date and author to news on the explore screen in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26155))
|
||||||
- Add `lang` attribute to various UI components ([c960657](https://github.com/mastodon/mastodon/pull/23869), [c960657](https://github.com/mastodon/mastodon/pull/23891), [c960657](https://github.com/mastodon/mastodon/pull/26111), [c960657](https://github.com/mastodon/mastodon/pull/26149))
|
- Add `lang` attribute to various UI components ([c960657](https://github.com/mastodon/mastodon/pull/23869), [c960657](https://github.com/mastodon/mastodon/pull/23891), [c960657](https://github.com/mastodon/mastodon/pull/26111), [c960657](https://github.com/mastodon/mastodon/pull/26149))
|
||||||
|
@ -43,7 +56,7 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- Add unsubscribe link and headers to e-mails ([Gargron](https://github.com/mastodon/mastodon/pull/25378), [c960657](https://github.com/mastodon/mastodon/pull/26085))
|
- Add unsubscribe link and headers to e-mails ([Gargron](https://github.com/mastodon/mastodon/pull/25378), [c960657](https://github.com/mastodon/mastodon/pull/26085))
|
||||||
- Add logging of websocket send errors ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/25280))
|
- Add logging of websocket send errors ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/25280))
|
||||||
- Add time zone preference ([Gargron](https://github.com/mastodon/mastodon/pull/25342), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26025))
|
- Add time zone preference ([Gargron](https://github.com/mastodon/mastodon/pull/25342), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26025))
|
||||||
- Add `legal` as report category ([Gargron](https://github.com/mastodon/mastodon/pull/23941), [renchap](https://github.com/mastodon/mastodon/pull/25400))
|
- Add `legal` as report category ([Gargron](https://github.com/mastodon/mastodon/pull/23941), [renchap](https://github.com/mastodon/mastodon/pull/25400), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26509))
|
||||||
- Add `data-nosnippet` so Google doesn't use trending posts in snippets for `/` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25279))
|
- Add `data-nosnippet` so Google doesn't use trending posts in snippets for `/` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25279))
|
||||||
- Add card with who invited you to join when displaying rules on sign-up ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23475))
|
- Add card with who invited you to join when displaying rules on sign-up ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23475))
|
||||||
- Add missing primary keys to `accounts_tags` and `statuses_tags` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25210))
|
- Add missing primary keys to `accounts_tags` and `statuses_tags` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25210))
|
||||||
|
@ -80,11 +93,12 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- **Change hashtags to be displayed separately when they are the last line of a post** ([renchap](https://github.com/mastodon/mastodon/pull/26499))
|
||||||
- **Change reblogs to be excluded from "Posts and replies" tab in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/26302))
|
- **Change reblogs to be excluded from "Posts and replies" tab in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/26302))
|
||||||
- **Change interaction modal in web interface** ([Gargron, ClearlyClaire](https://github.com/mastodon/mastodon/pull/26075), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26269), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26268), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26267))
|
- **Change interaction modal in web interface** ([Gargron, ClearlyClaire](https://github.com/mastodon/mastodon/pull/26075), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26269), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26268), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26267), [mgmn](https://github.com/mastodon/mastodon/pull/26459))
|
||||||
- **Change design of link previews in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/26136), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26151), [Gargron](https://github.com/mastodon/mastodon/pull/26153), [Gargron](https://github.com/mastodon/mastodon/pull/26250), [Gargron](https://github.com/mastodon/mastodon/pull/26287), [Gargron](https://github.com/mastodon/mastodon/pull/26286), [c960657](https://github.com/mastodon/mastodon/pull/26184))
|
- **Change design of link previews in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/26136), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26151), [Gargron](https://github.com/mastodon/mastodon/pull/26153), [Gargron](https://github.com/mastodon/mastodon/pull/26250), [Gargron](https://github.com/mastodon/mastodon/pull/26287), [Gargron](https://github.com/mastodon/mastodon/pull/26286), [c960657](https://github.com/mastodon/mastodon/pull/26184))
|
||||||
- **Change "direct message" nomenclature to "private mention" in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24248))
|
- **Change "direct message" nomenclature to "private mention" in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24248))
|
||||||
- **Change translation feature to cover Content Warnings, poll options and media descriptions** ([c960657](https://github.com/mastodon/mastodon/pull/24175), [S-H-GAMELINKS](https://github.com/mastodon/mastodon/pull/25251), [c960657](https://github.com/mastodon/mastodon/pull/26168))
|
- **Change translation feature to cover Content Warnings, poll options and media descriptions** ([c960657](https://github.com/mastodon/mastodon/pull/24175), [S-H-GAMELINKS](https://github.com/mastodon/mastodon/pull/25251), [c960657](https://github.com/mastodon/mastodon/pull/26168), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26452))
|
||||||
- **Change account search to match by text when opted-in** ([jsgoldstein](https://github.com/mastodon/mastodon/pull/25599), [Gargron](https://github.com/mastodon/mastodon/pull/26378))
|
- **Change account search to match by text when opted-in** ([jsgoldstein](https://github.com/mastodon/mastodon/pull/25599), [Gargron](https://github.com/mastodon/mastodon/pull/26378))
|
||||||
- **Change import feature to be clearer, less error-prone and more reliable** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21054), [mgmn](https://github.com/mastodon/mastodon/pull/24874))
|
- **Change import feature to be clearer, less error-prone and more reliable** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21054), [mgmn](https://github.com/mastodon/mastodon/pull/24874))
|
||||||
- **Change local and federated timelines to be in a single “Live feeds” column** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25641), [Gargron](https://github.com/mastodon/mastodon/pull/25683), [mgmn](https://github.com/mastodon/mastodon/pull/25694), [Plastikmensch](https://github.com/mastodon/mastodon/pull/26247))
|
- **Change local and federated timelines to be in a single “Live feeds” column** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25641), [Gargron](https://github.com/mastodon/mastodon/pull/25683), [mgmn](https://github.com/mastodon/mastodon/pull/25694), [Plastikmensch](https://github.com/mastodon/mastodon/pull/26247))
|
||||||
|
@ -97,7 +111,9 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- **Change replica support to native Rails adapter** ([krainboltgreene](https://github.com/mastodon/mastodon/pull/25693), [Gargron](https://github.com/mastodon/mastodon/pull/25849), [Gargron](https://github.com/mastodon/mastodon/pull/25874), [Gargron](https://github.com/mastodon/mastodon/pull/25851), [Gargron](https://github.com/mastodon/mastodon/pull/25977), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26074), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26326), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26386))
|
- **Change replica support to native Rails adapter** ([krainboltgreene](https://github.com/mastodon/mastodon/pull/25693), [Gargron](https://github.com/mastodon/mastodon/pull/25849), [Gargron](https://github.com/mastodon/mastodon/pull/25874), [Gargron](https://github.com/mastodon/mastodon/pull/25851), [Gargron](https://github.com/mastodon/mastodon/pull/25977), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26074), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26326), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26386))
|
||||||
This is a breaking change, dropping `makara` support, and requiring you to update your database configuration if you are using replicas.
|
This is a breaking change, dropping `makara` support, and requiring you to update your database configuration if you are using replicas.
|
||||||
To tell Mastodon to use a read replica, you can either set the `REPLICA_DB_NAME` environment variable (along with `REPLICA_DB_USER`, `REPLICA_DB_PASS`, `REPLICA_DB_HOST`, and `REPLICA_DB_PORT`, if they differ from the primary database), or the `REPLICA_DATABASE_URL` environment variable if your configuration is based on `DATABASE_URL`.
|
To tell Mastodon to use a read replica, you can either set the `REPLICA_DB_NAME` environment variable (along with `REPLICA_DB_USER`, `REPLICA_DB_PASS`, `REPLICA_DB_HOST`, and `REPLICA_DB_PORT`, if they differ from the primary database), or the `REPLICA_DATABASE_URL` environment variable if your configuration is based on `DATABASE_URL`.
|
||||||
- Change header of hashtag timelines in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26362))
|
- Change follow recommendation materialized view to be faster in most cases ([renchap, ClearlyClaire](https://github.com/mastodon/mastodon/pull/26545))
|
||||||
|
- Change `robots.txt` to block GPTBot ([Foritus](https://github.com/mastodon/mastodon/pull/26396))
|
||||||
|
- Change header of hashtag timelines in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26362), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26416))
|
||||||
- Change streaming `/metrics` to include additional metrics ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/26299))
|
- Change streaming `/metrics` to include additional metrics ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/26299))
|
||||||
- Change indexing frequency from 5 minutes to 1 minute, add locks to schedulers ([Gargron](https://github.com/mastodon/mastodon/pull/26304))
|
- Change indexing frequency from 5 minutes to 1 minute, add locks to schedulers ([Gargron](https://github.com/mastodon/mastodon/pull/26304))
|
||||||
- Change column link to add a better keyboard focus indicator ([teeerevor](https://github.com/mastodon/mastodon/pull/26278))
|
- Change column link to add a better keyboard focus indicator ([teeerevor](https://github.com/mastodon/mastodon/pull/26278))
|
||||||
|
@ -114,7 +130,7 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- Change header backgrounds to use fewer different colors in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25577))
|
- Change header backgrounds to use fewer different colors in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25577))
|
||||||
- Change files to be deleted in batches instead of one-by-one ([Gargron](https://github.com/mastodon/mastodon/pull/23302), [S-H-GAMELINKS](https://github.com/mastodon/mastodon/pull/25586), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25587))
|
- Change files to be deleted in batches instead of one-by-one ([Gargron](https://github.com/mastodon/mastodon/pull/23302), [S-H-GAMELINKS](https://github.com/mastodon/mastodon/pull/25586), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25587))
|
||||||
- Change emoji picker icon ([iparr](https://github.com/mastodon/mastodon/pull/25479))
|
- Change emoji picker icon ([iparr](https://github.com/mastodon/mastodon/pull/25479))
|
||||||
- Change edit profile page ([Gargron](https://github.com/mastodon/mastodon/pull/25413))
|
- Change edit profile page ([Gargron](https://github.com/mastodon/mastodon/pull/25413), [c960657](https://github.com/mastodon/mastodon/pull/26538))
|
||||||
- Change "bot" label to "automated" ([Gargron](https://github.com/mastodon/mastodon/pull/25356))
|
- Change "bot" label to "automated" ([Gargron](https://github.com/mastodon/mastodon/pull/25356))
|
||||||
- Change design of dropdowns in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25107))
|
- Change design of dropdowns in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25107))
|
||||||
- Change wording of “Content cache retention period” setting to highlight destructive implications ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23261))
|
- Change wording of “Content cache retention period” setting to highlight destructive implications ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23261))
|
||||||
|
@ -172,6 +188,9 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- **Fix being unable to load past a full page of filtered posts in Home timeline** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24930))
|
- **Fix being unable to load past a full page of filtered posts in Home timeline** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24930))
|
||||||
- **Fix log-in flow when involving both OAuth and external authentication** ([CSDUMMI](https://github.com/mastodon/mastodon/pull/24073))
|
- **Fix log-in flow when involving both OAuth and external authentication** ([CSDUMMI](https://github.com/mastodon/mastodon/pull/24073))
|
||||||
- **Fix broken links in account gallery** ([c960657](https://github.com/mastodon/mastodon/pull/24218))
|
- **Fix broken links in account gallery** ([c960657](https://github.com/mastodon/mastodon/pull/24218))
|
||||||
|
- **Fix blocking subdomains of an already-blocked domain** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26392))
|
||||||
|
- Fix uploading of video files for which `ffprobe` reports `0/0` average framerate ([NicolaiSoeborg](https://github.com/mastodon/mastodon/pull/26500))
|
||||||
|
- Fix cached posts including stale stats ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26409))
|
||||||
- Fix adding column with default value taking longer on Postgres >= 11 ([Gargron](https://github.com/mastodon/mastodon/pull/26375))
|
- Fix adding column with default value taking longer on Postgres >= 11 ([Gargron](https://github.com/mastodon/mastodon/pull/26375))
|
||||||
- Fix light theme select option for hashtags ([teeerevor](https://github.com/mastodon/mastodon/pull/26311))
|
- Fix light theme select option for hashtags ([teeerevor](https://github.com/mastodon/mastodon/pull/26311))
|
||||||
- Fix AVIF attachments ([c960657](https://github.com/mastodon/mastodon/pull/26264))
|
- Fix AVIF attachments ([c960657](https://github.com/mastodon/mastodon/pull/26264))
|
||||||
|
@ -189,7 +208,7 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- Fix for "follows you" indicator in light web UI not readable ([vmstan](https://github.com/mastodon/mastodon/pull/25993))
|
- Fix for "follows you" indicator in light web UI not readable ([vmstan](https://github.com/mastodon/mastodon/pull/25993))
|
||||||
- Fix incorrect line break between icon and number of reposts & favourites ([edent](https://github.com/mastodon/mastodon/pull/26004))
|
- Fix incorrect line break between icon and number of reposts & favourites ([edent](https://github.com/mastodon/mastodon/pull/26004))
|
||||||
- Fix sounds not being loaded from assets host ([Signez](https://github.com/mastodon/mastodon/pull/25931))
|
- Fix sounds not being loaded from assets host ([Signez](https://github.com/mastodon/mastodon/pull/25931))
|
||||||
- Fix buttons showing inconsistent styles ([teeerevor](https://github.com/mastodon/mastodon/pull/25903), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25965), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26341))
|
- Fix buttons showing inconsistent styles ([teeerevor](https://github.com/mastodon/mastodon/pull/25903), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25965), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26341), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26482))
|
||||||
- Fix trend calculation working on too many items at a time ([Gargron](https://github.com/mastodon/mastodon/pull/25835))
|
- Fix trend calculation working on too many items at a time ([Gargron](https://github.com/mastodon/mastodon/pull/25835))
|
||||||
- Fix dropdowns being disabled for logged out users in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25714), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25964))
|
- Fix dropdowns being disabled for logged out users in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25714), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25964))
|
||||||
- Fix explore page being inaccessible when opted-out of trends in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25716))
|
- Fix explore page being inaccessible when opted-out of trends in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25716))
|
||||||
|
|
|
@ -6,7 +6,7 @@ class InstancesIndex < Chewy::Index
|
||||||
index_scope ::Instance.searchable
|
index_scope ::Instance.searchable
|
||||||
|
|
||||||
root date_detection: false do
|
root date_detection: false do
|
||||||
field :domain, type: 'text', index_prefixes: { min_chars: 1 }
|
field :domain, type: 'text', index_prefixes: { min_chars: 1, max_chars: 5 }
|
||||||
field :accounts_count, type: 'long'
|
field :accounts_count, type: 'long'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
18
app/controllers/api/v1/accounts/circles_controller.rb
Normal file
18
app/controllers/api/v1/accounts/circles_controller.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Accounts::CirclesController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :read, :'read:lists' }
|
||||||
|
before_action :require_user!
|
||||||
|
before_action :set_account
|
||||||
|
|
||||||
|
def index
|
||||||
|
@circles = @account.suspended? ? [] : @account.joined_circles.where(account: current_account)
|
||||||
|
render json: @circles, each_serializer: REST::CircleSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:account_id])
|
||||||
|
end
|
||||||
|
end
|
13
app/controllers/api/v1/profile/avatars_controller.rb
Normal file
13
app/controllers/api/v1/profile/avatars_controller.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Profile::AvatarsController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@account = current_account
|
||||||
|
UpdateAccountService.new.call(@account, { avatar: nil }, raise_error: true)
|
||||||
|
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
|
||||||
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
|
end
|
||||||
|
end
|
13
app/controllers/api/v1/profile/headers_controller.rb
Normal file
13
app/controllers/api/v1/profile/headers_controller.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Profile::HeadersController < Api::BaseController
|
||||||
|
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
|
||||||
|
before_action :require_user!
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@account = current_account
|
||||||
|
UpdateAccountService.new.call(@account, { header: nil }, raise_error: true)
|
||||||
|
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
|
||||||
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
|
end
|
||||||
|
end
|
184
app/javascript/mastodon/components/__tests__/hashtag_bar.tsx
Normal file
184
app/javascript/mastodon/components/__tests__/hashtag_bar.tsx
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
import { fromJS } from 'immutable';
|
||||||
|
|
||||||
|
import type { StatusLike } from '../hashtag_bar';
|
||||||
|
import { computeHashtagBarForStatus } from '../hashtag_bar';
|
||||||
|
|
||||||
|
function createStatus(
|
||||||
|
content: string,
|
||||||
|
hashtags: string[],
|
||||||
|
hasMedia = false,
|
||||||
|
spoilerText?: string,
|
||||||
|
) {
|
||||||
|
return fromJS({
|
||||||
|
tags: hashtags.map((name) => ({ name })),
|
||||||
|
contentHtml: content,
|
||||||
|
media_attachments: hasMedia ? ['fakeMedia'] : [],
|
||||||
|
spoiler_text: spoilerText,
|
||||||
|
}) as unknown as StatusLike; // need to force the type here, as it is not properly defined
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('computeHashtagBarForStatus', () => {
|
||||||
|
it('does nothing when there are no tags', () => {
|
||||||
|
const status = createStatus('<p>Simple text</p>', []);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual([]);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p>Simple text</p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays out of band hashtags in the bar', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p>Simple text <a href="test">#hashtag</a></p>',
|
||||||
|
['hashtag', 'test'],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual(['test']);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p>Simple text <a href="test">#hashtag</a></p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('extract tags from the last line', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p>Simple text</p><p><a href="test">#hashtag</a></p>',
|
||||||
|
['hashtag'],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual(['hashtag']);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p>Simple text</p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not include tags from content', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p>Simple text with a <a href="test">#hashtag</a></p><p><a href="test">#hashtag</a></p>',
|
||||||
|
['hashtag'],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual([]);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p>Simple text with a <a href="test">#hashtag</a></p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with one line status and hashtags', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p><a href="test">#test</a>. And another <a href="test">#hashtag</a></p>',
|
||||||
|
['hashtag', 'test'],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual([]);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p><a href="test">#test</a>. And another <a href="test">#hashtag</a></p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('de-duplicate accentuated characters with case differences', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p>Text</p><p><a href="test">#éaa</a> <a href="test">#Éaa</a></p>',
|
||||||
|
['éaa'],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual(['Éaa']);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p>Text</p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not display in bar a hashtag in content with a case difference', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p>Text <a href="test">#Éaa</a></p><p><a href="test">#éaa</a></p>',
|
||||||
|
['éaa'],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual([]);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p>Text <a href="test">#Éaa</a></p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not modify a status with a line of hashtags only', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p><a href="test">#test</a> <a href="test">#hashtag</a></p>',
|
||||||
|
['test', 'hashtag'],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual([]);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p><a href="test">#test</a> <a href="test">#hashtag</a></p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('puts the hashtags in the bar if a status content has hashtags in the only line and has a media', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p>This is my content! <a href="test">#hashtag</a></p>',
|
||||||
|
['hashtag'],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual([]);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p>This is my content! <a href="test">#hashtag</a></p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('puts the hashtags in the bar if a status content is only hashtags and has a media', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p><a href="test">#test</a> <a href="test">#hashtag</a></p>',
|
||||||
|
['test', 'hashtag'],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual(['test', 'hashtag']);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(`""`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not use the hashtag bar if the status content is only hashtags, has a CW and a media', () => {
|
||||||
|
const status = createStatus(
|
||||||
|
'<p><a href="test">#test</a> <a href="test">#hashtag</a></p>',
|
||||||
|
['test', 'hashtag'],
|
||||||
|
true,
|
||||||
|
'My CW text',
|
||||||
|
);
|
||||||
|
|
||||||
|
const { hashtagsInBar, statusContentProps } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
expect(hashtagsInBar).toEqual([]);
|
||||||
|
expect(statusContentProps.statusContent).toMatchInlineSnapshot(
|
||||||
|
`"<p><a href="test">#test</a> <a href="test">#hashtag</a></p>"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,50 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useMemo, useState, useCallback } from 'react';
|
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
|
|
||||||
const domParser = new DOMParser();
|
|
||||||
|
|
||||||
// About two lines on desktop
|
|
||||||
const VISIBLE_HASHTAGS = 7;
|
|
||||||
|
|
||||||
export const HashtagBar = ({ hashtags, text }) => {
|
|
||||||
const renderedHashtags = useMemo(() => {
|
|
||||||
const body = domParser.parseFromString(text, 'text/html').documentElement;
|
|
||||||
return [].filter.call(body.querySelectorAll('a[href]'), link => link.textContent[0] === '#' || (link.previousSibling?.textContent?.[link.previousSibling.textContent.length - 1] === '#')).map(node => node.textContent);
|
|
||||||
}, [text]);
|
|
||||||
|
|
||||||
const invisibleHashtags = useMemo(() => (
|
|
||||||
hashtags.filter(hashtag => !renderedHashtags.some(textContent => textContent.localeCompare(`#${hashtag.get('name')}`, undefined, { sensitivity: 'accent' }) === 0 || textContent.localeCompare(hashtag.get('name'), undefined, { sensitivity: 'accent' }) === 0))
|
|
||||||
), [hashtags, renderedHashtags]);
|
|
||||||
|
|
||||||
const [expanded, setExpanded] = useState(false);
|
|
||||||
const handleClick = useCallback(() => setExpanded(true), []);
|
|
||||||
|
|
||||||
if (invisibleHashtags.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const revealedHashtags = expanded ? invisibleHashtags : invisibleHashtags.take(VISIBLE_HASHTAGS);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='hashtag-bar'>
|
|
||||||
{revealedHashtags.map(hashtag => (
|
|
||||||
<Link key={hashtag.get('name')} to={`/tags/${hashtag.get('name')}`}>
|
|
||||||
#{hashtag.get('name')}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{!expanded && invisibleHashtags.size > VISIBLE_HASHTAGS && <button className='link-button' onClick={handleClick}><FormattedMessage id='hashtags.and_other' defaultMessage='…and {count, plural, other {# more}}' values={{ count: invisibleHashtags.size - VISIBLE_HASHTAGS }} /></button>}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
HashtagBar.propTypes = {
|
|
||||||
hashtags: ImmutablePropTypes.list,
|
|
||||||
text: PropTypes.string,
|
|
||||||
};
|
|
222
app/javascript/mastodon/components/hashtag_bar.tsx
Normal file
222
app/javascript/mastodon/components/hashtag_bar.tsx
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
import { useState, useCallback } from 'react';
|
||||||
|
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import type { List, Record } from 'immutable';
|
||||||
|
|
||||||
|
import { groupBy, minBy } from 'lodash';
|
||||||
|
|
||||||
|
import { getStatusContent } from './status_content';
|
||||||
|
|
||||||
|
// About two lines on desktop
|
||||||
|
const VISIBLE_HASHTAGS = 7;
|
||||||
|
|
||||||
|
// Those types are not correct, they need to be replaced once this part of the state is typed
|
||||||
|
export type TagLike = Record<{ name: string }>;
|
||||||
|
export type StatusLike = Record<{
|
||||||
|
tags: List<TagLike>;
|
||||||
|
contentHTML: string;
|
||||||
|
media_attachments: List<unknown>;
|
||||||
|
spoiler_text?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
function normalizeHashtag(hashtag: string) {
|
||||||
|
if (hashtag && hashtag.startsWith('#')) return hashtag.slice(1);
|
||||||
|
else return hashtag;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isNodeLinkHashtag(element: Node): element is HTMLLinkElement {
|
||||||
|
return (
|
||||||
|
element instanceof HTMLAnchorElement &&
|
||||||
|
// it may be a <a> starting with a hashtag
|
||||||
|
(element.textContent?.[0] === '#' ||
|
||||||
|
// or a #<a>
|
||||||
|
element.previousSibling?.textContent?.[
|
||||||
|
element.previousSibling.textContent.length - 1
|
||||||
|
] === '#')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes duplicates from an hashtag list, case-insensitive, keeping only the best one
|
||||||
|
* "Best" here is defined by the one with the more casing difference (ie, the most camel-cased one)
|
||||||
|
* @param hashtags The list of hashtags
|
||||||
|
* @returns The input hashtags, but with only 1 occurence of each (case-insensitive)
|
||||||
|
*/
|
||||||
|
function uniqueHashtagsWithCaseHandling(hashtags: string[]) {
|
||||||
|
const groups = groupBy(hashtags, (tag) =>
|
||||||
|
tag.normalize('NFKD').toLowerCase(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Object.values(groups).map((tags) => {
|
||||||
|
if (tags.length === 1) return tags[0];
|
||||||
|
|
||||||
|
// The best match is the one where we have the less difference between upper and lower case letter count
|
||||||
|
const best = minBy(tags, (tag) => {
|
||||||
|
const upperCase = Array.from(tag).reduce(
|
||||||
|
(acc, char) => (acc += char.toUpperCase() === char ? 1 : 0),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
const lowerCase = tag.length - upperCase;
|
||||||
|
|
||||||
|
return Math.abs(lowerCase - upperCase);
|
||||||
|
});
|
||||||
|
|
||||||
|
return best ?? tags[0];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the collator once, this is much more efficient
|
||||||
|
const collator = new Intl.Collator(undefined, { sensitivity: 'accent' });
|
||||||
|
function localeAwareInclude(collection: string[], value: string) {
|
||||||
|
return collection.find((item) => collator.compare(item, value) === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use an intermediate function here to make it easier to test
|
||||||
|
export function computeHashtagBarForStatus(status: StatusLike): {
|
||||||
|
statusContentProps: { statusContent: string };
|
||||||
|
hashtagsInBar: string[];
|
||||||
|
} {
|
||||||
|
let statusContent = getStatusContent(status);
|
||||||
|
|
||||||
|
const tagNames = status
|
||||||
|
.get('tags')
|
||||||
|
.map((tag) => tag.get('name'))
|
||||||
|
.toJS();
|
||||||
|
|
||||||
|
// this is returned if we stop the processing early, it does not change what is displayed
|
||||||
|
const defaultResult = {
|
||||||
|
statusContentProps: { statusContent },
|
||||||
|
hashtagsInBar: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
// return early if this status does not have any tags
|
||||||
|
if (tagNames.length === 0) return defaultResult;
|
||||||
|
|
||||||
|
const template = document.createElement('template');
|
||||||
|
template.innerHTML = statusContent.trim();
|
||||||
|
|
||||||
|
const lastChild = template.content.lastChild;
|
||||||
|
|
||||||
|
if (!lastChild) return defaultResult;
|
||||||
|
|
||||||
|
template.content.removeChild(lastChild);
|
||||||
|
const contentWithoutLastLine = template;
|
||||||
|
|
||||||
|
// First, try to parse
|
||||||
|
const contentHashtags = Array.from(
|
||||||
|
contentWithoutLastLine.content.querySelectorAll<HTMLLinkElement>('a[href]'),
|
||||||
|
).reduce<string[]>((result, link) => {
|
||||||
|
if (isNodeLinkHashtag(link)) {
|
||||||
|
if (link.textContent) result.push(normalizeHashtag(link.textContent));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Now we parse the last line, and try to see if it only contains hashtags
|
||||||
|
const lastLineHashtags: string[] = [];
|
||||||
|
// try to see if the last line is only hashtags
|
||||||
|
let onlyHashtags = true;
|
||||||
|
|
||||||
|
Array.from(lastChild.childNodes).forEach((node) => {
|
||||||
|
if (isNodeLinkHashtag(node) && node.textContent) {
|
||||||
|
const normalized = normalizeHashtag(node.textContent);
|
||||||
|
|
||||||
|
if (!localeAwareInclude(tagNames, normalized)) {
|
||||||
|
// stop here, this is not a real hashtag, so consider it as text
|
||||||
|
onlyHashtags = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!localeAwareInclude(contentHashtags, normalized))
|
||||||
|
// only add it if it does not appear in the rest of the content
|
||||||
|
lastLineHashtags.push(normalized);
|
||||||
|
} else if (node.nodeType !== Node.TEXT_NODE || node.nodeValue?.trim()) {
|
||||||
|
// not a space
|
||||||
|
onlyHashtags = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const hashtagsInBar = tagNames.filter(
|
||||||
|
(tag) =>
|
||||||
|
// the tag does not appear at all in the status content, it is an out-of-band tag
|
||||||
|
!localeAwareInclude(contentHashtags, tag) &&
|
||||||
|
!localeAwareInclude(lastLineHashtags, tag),
|
||||||
|
);
|
||||||
|
|
||||||
|
const isOnlyOneLine = contentWithoutLastLine.content.childElementCount === 0;
|
||||||
|
const hasMedia = status.get('media_attachments').size > 0;
|
||||||
|
const hasSpoiler = !!status.get('spoiler_text');
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- due to https://github.com/microsoft/TypeScript/issues/9998
|
||||||
|
if (onlyHashtags && ((hasMedia && !hasSpoiler) || !isOnlyOneLine)) {
|
||||||
|
// if the last line only contains hashtags, and we either:
|
||||||
|
// - have other content in the status
|
||||||
|
// - dont have other content, but a media and no CW. If it has a CW, then we do not remove the content to avoid having an empty content behind the CW button
|
||||||
|
statusContent = contentWithoutLastLine.innerHTML;
|
||||||
|
// and add the tags to the bar
|
||||||
|
hashtagsInBar.push(...lastLineHashtags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusContentProps: { statusContent },
|
||||||
|
hashtagsInBar: uniqueHashtagsWithCaseHandling(hashtagsInBar),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function will process a status to, at the same time (avoiding parsing it twice):
|
||||||
|
* - build the HashtagBar for this status
|
||||||
|
* - remove the last-line hashtags from the status content
|
||||||
|
* @param status The status to process
|
||||||
|
* @returns Props to be passed to the <StatusContent> component, and the hashtagBar to render
|
||||||
|
*/
|
||||||
|
export function getHashtagBarForStatus(status: StatusLike) {
|
||||||
|
const { statusContentProps, hashtagsInBar } =
|
||||||
|
computeHashtagBarForStatus(status);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusContentProps,
|
||||||
|
hashtagBar: <HashtagBar hashtags={hashtagsInBar} />,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const HashtagBar: React.FC<{
|
||||||
|
hashtags: string[];
|
||||||
|
}> = ({ hashtags }) => {
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
setExpanded(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (hashtags.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const revealedHashtags = expanded
|
||||||
|
? hashtags
|
||||||
|
: hashtags.slice(0, VISIBLE_HASHTAGS - 1);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='hashtag-bar'>
|
||||||
|
{revealedHashtags.map((hashtag) => (
|
||||||
|
<Link key={hashtag} to={`/tags/${hashtag}`}>
|
||||||
|
#{hashtag}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{!expanded && hashtags.length > VISIBLE_HASHTAGS && (
|
||||||
|
<button className='link-button' onClick={handleClick}>
|
||||||
|
<FormattedMessage
|
||||||
|
id='hashtags.and_other'
|
||||||
|
defaultMessage='…and {count, plural, other {# more}}'
|
||||||
|
values={{ count: hashtags.length - VISIBLE_HASHTAGS }}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -23,7 +23,7 @@ import { displayMedia } from '../initial_state';
|
||||||
import { Avatar } from './avatar';
|
import { Avatar } from './avatar';
|
||||||
import { AvatarOverlay } from './avatar_overlay';
|
import { AvatarOverlay } from './avatar_overlay';
|
||||||
import { DisplayName } from './display_name';
|
import { DisplayName } from './display_name';
|
||||||
import { HashtagBar } from './hashtag_bar';
|
import { getHashtagBarForStatus } from './hashtag_bar';
|
||||||
import { RelativeTimestamp } from './relative_timestamp';
|
import { RelativeTimestamp } from './relative_timestamp';
|
||||||
import StatusActionBar from './status_action_bar';
|
import StatusActionBar from './status_action_bar';
|
||||||
import StatusContent from './status_content';
|
import StatusContent from './status_content';
|
||||||
|
@ -582,6 +582,8 @@ class Status extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={handlers}>
|
<HotKeys handlers={handlers}>
|
||||||
<div className={classNames('status__wrapper', `status__wrapper-${status.get('visibility_ex')}`, { 'status__wrapper-reply': !!status.get('in_reply_to_id'), unread, focusable: !this.props.muted })} tabIndex={this.props.muted ? null : 0} data-featured={featured ? 'true' : null} aria-label={textForScreenReader(intl, status, rebloggedByText)} ref={this.handleRef}>
|
<div className={classNames('status__wrapper', `status__wrapper-${status.get('visibility_ex')}`, { 'status__wrapper-reply': !!status.get('in_reply_to_id'), unread, focusable: !this.props.muted })} tabIndex={this.props.muted ? null : 0} data-featured={featured ? 'true' : null} aria-label={textForScreenReader(intl, status, rebloggedByText)} ref={this.handleRef}>
|
||||||
|
@ -614,11 +616,12 @@ class Status extends ImmutablePureComponent {
|
||||||
onTranslate={this.handleTranslate}
|
onTranslate={this.handleTranslate}
|
||||||
collapsible
|
collapsible
|
||||||
onCollapsedToggle={this.handleCollapsedToggle}
|
onCollapsedToggle={this.handleCollapsedToggle}
|
||||||
|
{...statusContentProps}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{(!isCardMediaWithSensitive || !status.get('hidden')) && media}
|
{(!isCardMediaWithSensitive || !status.get('hidden')) && media}
|
||||||
|
|
||||||
<HashtagBar hashtags={status.get('tags')} text={status.get('content')} />
|
{hashtagBar}
|
||||||
|
|
||||||
{emojiReactionsBar}
|
{emojiReactionsBar}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,15 @@ import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_s
|
||||||
|
|
||||||
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
|
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {any} status
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function getStatusContent(status) {
|
||||||
|
return status.getIn(['translation', 'contentHtml']) || status.get('contentHtml');
|
||||||
|
}
|
||||||
|
|
||||||
class TranslateButton extends PureComponent {
|
class TranslateButton extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -65,6 +74,7 @@ class StatusContent extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
status: ImmutablePropTypes.map.isRequired,
|
status: ImmutablePropTypes.map.isRequired,
|
||||||
|
statusContent: PropTypes.string,
|
||||||
expanded: PropTypes.bool,
|
expanded: PropTypes.bool,
|
||||||
onExpandedToggle: PropTypes.func,
|
onExpandedToggle: PropTypes.func,
|
||||||
onTranslate: PropTypes.func,
|
onTranslate: PropTypes.func,
|
||||||
|
@ -225,7 +235,7 @@ class StatusContent extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status, intl } = this.props;
|
const { status, intl, statusContent } = this.props;
|
||||||
|
|
||||||
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
||||||
const renderReadMore = this.props.onClick && status.get('collapsed');
|
const renderReadMore = this.props.onClick && status.get('collapsed');
|
||||||
|
@ -233,7 +243,7 @@ class StatusContent extends PureComponent {
|
||||||
const targetLanguages = this.props.languages?.get(status.get('language') || 'und');
|
const targetLanguages = this.props.languages?.get(status.get('language') || 'und');
|
||||||
const renderTranslate = this.props.onTranslate && this.context.identity.signedIn && ['public', 'unlisted'].includes(status.get('visibility')) && status.get('search_index').trim().length > 0 && targetLanguages?.includes(contentLocale);
|
const renderTranslate = this.props.onTranslate && this.context.identity.signedIn && ['public', 'unlisted'].includes(status.get('visibility')) && status.get('search_index').trim().length > 0 && targetLanguages?.includes(contentLocale);
|
||||||
|
|
||||||
const content = { __html: status.getIn(['translation', 'contentHtml']) || status.get('contentHtml') };
|
const content = { __html: statusContent ?? getStatusContent(status) };
|
||||||
const spoilerContent = { __html: status.getIn(['translation', 'spoilerHtml']) || status.get('spoilerHtml') };
|
const spoilerContent = { __html: status.getIn(['translation', 'spoilerHtml']) || status.get('spoilerHtml') };
|
||||||
const language = status.getIn(['translation', 'language']) || status.get('language');
|
const language = status.getIn(['translation', 'language']) || status.get('language');
|
||||||
const classNames = classnames('status__content', {
|
const classNames = classnames('status__content', {
|
||||||
|
|
|
@ -59,6 +59,7 @@ const messages = defineMessages({
|
||||||
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
|
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
|
||||||
add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' },
|
add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' },
|
||||||
add_or_remove_from_antenna: { id: 'account.add_or_remove_from_antenna', defaultMessage: 'Add or Remove from antennas' },
|
add_or_remove_from_antenna: { id: 'account.add_or_remove_from_antenna', defaultMessage: 'Add or Remove from antennas' },
|
||||||
|
add_or_remove_from_circle: { id: 'account.add_or_remove_from_circle', defaultMessage: 'Add or Remove from circles' },
|
||||||
admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
|
admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
|
||||||
admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' },
|
admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' },
|
||||||
languages: { id: 'account.languages', defaultMessage: 'Change subscribed languages' },
|
languages: { id: 'account.languages', defaultMessage: 'Change subscribed languages' },
|
||||||
|
@ -105,6 +106,7 @@ class Header extends ImmutablePureComponent {
|
||||||
onEndorseToggle: PropTypes.func.isRequired,
|
onEndorseToggle: PropTypes.func.isRequired,
|
||||||
onAddToList: PropTypes.func.isRequired,
|
onAddToList: PropTypes.func.isRequired,
|
||||||
onAddToAntenna: PropTypes.func.isRequired,
|
onAddToAntenna: PropTypes.func.isRequired,
|
||||||
|
onAddToCircle: PropTypes.func.isRequired,
|
||||||
onEditAccountNote: PropTypes.func.isRequired,
|
onEditAccountNote: PropTypes.func.isRequired,
|
||||||
onChangeLanguages: PropTypes.func.isRequired,
|
onChangeLanguages: PropTypes.func.isRequired,
|
||||||
onInteractionModal: PropTypes.func.isRequired,
|
onInteractionModal: PropTypes.func.isRequired,
|
||||||
|
@ -330,6 +332,9 @@ class Header extends ImmutablePureComponent {
|
||||||
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList });
|
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList });
|
||||||
}
|
}
|
||||||
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_antenna), action: this.props.onAddToAntenna });
|
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_antenna), action: this.props.onAddToAntenna });
|
||||||
|
if (account.getIn(['relationship', 'followed_by'])) {
|
||||||
|
menu.push({ text: intl.formatMessage(messages.add_or_remove_from_circle), action: this.props.onAddToCircle });
|
||||||
|
}
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
|
|
||||||
if (account.getIn(['relationship', 'muting'])) {
|
if (account.getIn(['relationship', 'muting'])) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ export default class Header extends ImmutablePureComponent {
|
||||||
onEndorseToggle: PropTypes.func.isRequired,
|
onEndorseToggle: PropTypes.func.isRequired,
|
||||||
onAddToList: PropTypes.func.isRequired,
|
onAddToList: PropTypes.func.isRequired,
|
||||||
onAddToAntenna: PropTypes.func.isRequired,
|
onAddToAntenna: PropTypes.func.isRequired,
|
||||||
|
onAddToCircle: PropTypes.func.isRequired,
|
||||||
onChangeLanguages: PropTypes.func.isRequired,
|
onChangeLanguages: PropTypes.func.isRequired,
|
||||||
onInteractionModal: PropTypes.func.isRequired,
|
onInteractionModal: PropTypes.func.isRequired,
|
||||||
onOpenAvatar: PropTypes.func.isRequired,
|
onOpenAvatar: PropTypes.func.isRequired,
|
||||||
|
@ -101,6 +102,10 @@ export default class Header extends ImmutablePureComponent {
|
||||||
this.props.onAddToAntenna(this.props.account);
|
this.props.onAddToAntenna(this.props.account);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleAddToCircle = () => {
|
||||||
|
this.props.onAddToCircle(this.props.account);
|
||||||
|
};
|
||||||
|
|
||||||
handleEditAccountNote = () => {
|
handleEditAccountNote = () => {
|
||||||
this.props.onEditAccountNote(this.props.account);
|
this.props.onEditAccountNote(this.props.account);
|
||||||
};
|
};
|
||||||
|
@ -144,6 +149,7 @@ export default class Header extends ImmutablePureComponent {
|
||||||
onEndorseToggle={this.handleEndorseToggle}
|
onEndorseToggle={this.handleEndorseToggle}
|
||||||
onAddToList={this.handleAddToList}
|
onAddToList={this.handleAddToList}
|
||||||
onAddToAntenna={this.handleAddToAntenna}
|
onAddToAntenna={this.handleAddToAntenna}
|
||||||
|
onAddToCircle={this.handleAddToCircle}
|
||||||
onEditAccountNote={this.handleEditAccountNote}
|
onEditAccountNote={this.handleEditAccountNote}
|
||||||
onChangeLanguages={this.handleChangeLanguages}
|
onChangeLanguages={this.handleChangeLanguages}
|
||||||
onInteractionModal={this.handleInteractionModal}
|
onInteractionModal={this.handleInteractionModal}
|
||||||
|
|
|
@ -173,6 +173,15 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onAddToCircle (account) {
|
||||||
|
dispatch(openModal({
|
||||||
|
modalType: 'CIRCLE_ADDER',
|
||||||
|
modalProps: {
|
||||||
|
accountId: account.get('id'),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
onChangeLanguages (account) {
|
onChangeLanguages (account) {
|
||||||
dispatch(openModal({
|
dispatch(openModal({
|
||||||
modalType: 'SUBSCRIBED_LANGUAGES',
|
modalType: 'SUBSCRIBED_LANGUAGES',
|
||||||
|
|
|
@ -10,7 +10,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import { AnimatedNumber } from 'mastodon/components/animated_number';
|
import { AnimatedNumber } from 'mastodon/components/animated_number';
|
||||||
import EditedTimestamp from 'mastodon/components/edited_timestamp';
|
import EditedTimestamp from 'mastodon/components/edited_timestamp';
|
||||||
import { HashtagBar } from 'mastodon/components/hashtag_bar';
|
import { getHashtagBarForStatus } from 'mastodon/components/hashtag_bar';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
|
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
|
||||||
|
|
||||||
|
@ -371,6 +371,8 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={outerStyle}>
|
<div style={outerStyle}>
|
||||||
<div ref={this.setRef} className={classNames('detailed-status', { compact })}>
|
<div ref={this.setRef} className={classNames('detailed-status', { compact })}>
|
||||||
|
@ -390,11 +392,12 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||||
expanded={!status.get('hidden')}
|
expanded={!status.get('hidden')}
|
||||||
onExpandedToggle={this.handleExpandedToggle}
|
onExpandedToggle={this.handleExpandedToggle}
|
||||||
onTranslate={this.handleTranslate}
|
onTranslate={this.handleTranslate}
|
||||||
|
{...statusContentProps}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{(!isCardMediaWithSensitive || !status.get('hidden')) && media}
|
{(!isCardMediaWithSensitive || !status.get('hidden')) && media}
|
||||||
|
|
||||||
<HashtagBar hashtags={status.get('tags')} text={status.get('content')} />
|
{hashtagBar}
|
||||||
|
|
||||||
{emojiReactionsBar}
|
{emojiReactionsBar}
|
||||||
|
|
||||||
|
|
|
@ -1,47 +1,47 @@
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
LIST_ADDER_RESET,
|
CIRCLE_ADDER_RESET,
|
||||||
LIST_ADDER_SETUP,
|
CIRCLE_ADDER_SETUP,
|
||||||
LIST_ADDER_LISTS_FETCH_REQUEST,
|
CIRCLE_ADDER_CIRCLES_FETCH_REQUEST,
|
||||||
LIST_ADDER_LISTS_FETCH_SUCCESS,
|
CIRCLE_ADDER_CIRCLES_FETCH_SUCCESS,
|
||||||
LIST_ADDER_LISTS_FETCH_FAIL,
|
CIRCLE_ADDER_CIRCLES_FETCH_FAIL,
|
||||||
LIST_EDITOR_ADD_SUCCESS,
|
CIRCLE_EDITOR_ADD_SUCCESS,
|
||||||
LIST_EDITOR_REMOVE_SUCCESS,
|
CIRCLE_EDITOR_REMOVE_SUCCESS,
|
||||||
} from '../actions/lists';
|
} from '../actions/circles';
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
accountId: null,
|
accountId: null,
|
||||||
|
|
||||||
lists: ImmutableMap({
|
circles: ImmutableMap({
|
||||||
items: ImmutableList(),
|
items: ImmutableList(),
|
||||||
loaded: false,
|
loaded: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function listAdderReducer(state = initialState, action) {
|
export default function circleAdderReducer(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case LIST_ADDER_RESET:
|
case CIRCLE_ADDER_RESET:
|
||||||
return initialState;
|
return initialState;
|
||||||
case LIST_ADDER_SETUP:
|
case CIRCLE_ADDER_SETUP:
|
||||||
return state.withMutations(map => {
|
return state.withMutations(map => {
|
||||||
map.set('accountId', action.account.get('id'));
|
map.set('accountId', action.account.get('id'));
|
||||||
});
|
});
|
||||||
case LIST_ADDER_LISTS_FETCH_REQUEST:
|
case CIRCLE_ADDER_CIRCLES_FETCH_REQUEST:
|
||||||
return state.setIn(['lists', 'isLoading'], true);
|
return state.setIn(['circles', 'isLoading'], true);
|
||||||
case LIST_ADDER_LISTS_FETCH_FAIL:
|
case CIRCLE_ADDER_CIRCLES_FETCH_FAIL:
|
||||||
return state.setIn(['lists', 'isLoading'], false);
|
return state.setIn(['circles', 'isLoading'], false);
|
||||||
case LIST_ADDER_LISTS_FETCH_SUCCESS:
|
case CIRCLE_ADDER_CIRCLES_FETCH_SUCCESS:
|
||||||
return state.update('lists', lists => lists.withMutations(map => {
|
return state.update('circles', circles => circles.withMutations(map => {
|
||||||
map.set('isLoading', false);
|
map.set('isLoading', false);
|
||||||
map.set('loaded', true);
|
map.set('loaded', true);
|
||||||
map.set('items', ImmutableList(action.lists.map(item => item.id)));
|
map.set('items', ImmutableList(action.circles.map(item => item.id)));
|
||||||
}));
|
}));
|
||||||
case LIST_EDITOR_ADD_SUCCESS:
|
case CIRCLE_EDITOR_ADD_SUCCESS:
|
||||||
return state.updateIn(['lists', 'items'], list => list.unshift(action.listId));
|
return state.updateIn(['circles', 'items'], circle => circle.unshift(action.circleId));
|
||||||
case LIST_EDITOR_REMOVE_SUCCESS:
|
case CIRCLE_EDITOR_REMOVE_SUCCESS:
|
||||||
return state.updateIn(['lists', 'items'], list => list.filterNot(item => item === action.listId));
|
return state.updateIn(['circles', 'items'], circle => circle.filterNot(item => item === action.circleId));
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +1,47 @@
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CIRCLE_ADDER_RESET,
|
LIST_ADDER_RESET,
|
||||||
CIRCLE_ADDER_SETUP,
|
LIST_ADDER_SETUP,
|
||||||
CIRCLE_ADDER_CIRCLES_FETCH_REQUEST,
|
LIST_ADDER_LISTS_FETCH_REQUEST,
|
||||||
CIRCLE_ADDER_CIRCLES_FETCH_SUCCESS,
|
LIST_ADDER_LISTS_FETCH_SUCCESS,
|
||||||
CIRCLE_ADDER_CIRCLES_FETCH_FAIL,
|
LIST_ADDER_LISTS_FETCH_FAIL,
|
||||||
CIRCLE_EDITOR_ADD_SUCCESS,
|
LIST_EDITOR_ADD_SUCCESS,
|
||||||
CIRCLE_EDITOR_REMOVE_SUCCESS,
|
LIST_EDITOR_REMOVE_SUCCESS,
|
||||||
} from '../actions/circles';
|
} from '../actions/lists';
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
accountId: null,
|
accountId: null,
|
||||||
|
|
||||||
circles: ImmutableMap({
|
lists: ImmutableMap({
|
||||||
items: ImmutableList(),
|
items: ImmutableList(),
|
||||||
loaded: false,
|
loaded: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function circleAdderReducer(state = initialState, action) {
|
export default function listAdderReducer(state = initialState, action) {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case CIRCLE_ADDER_RESET:
|
case LIST_ADDER_RESET:
|
||||||
return initialState;
|
return initialState;
|
||||||
case CIRCLE_ADDER_SETUP:
|
case LIST_ADDER_SETUP:
|
||||||
return state.withMutations(map => {
|
return state.withMutations(map => {
|
||||||
map.set('accountId', action.account.get('id'));
|
map.set('accountId', action.account.get('id'));
|
||||||
});
|
});
|
||||||
case CIRCLE_ADDER_CIRCLES_FETCH_REQUEST:
|
case LIST_ADDER_LISTS_FETCH_REQUEST:
|
||||||
return state.setIn(['circles', 'isLoading'], true);
|
return state.setIn(['lists', 'isLoading'], true);
|
||||||
case CIRCLE_ADDER_CIRCLES_FETCH_FAIL:
|
case LIST_ADDER_LISTS_FETCH_FAIL:
|
||||||
return state.setIn(['circles', 'isLoading'], false);
|
return state.setIn(['lists', 'isLoading'], false);
|
||||||
case CIRCLE_ADDER_CIRCLES_FETCH_SUCCESS:
|
case LIST_ADDER_LISTS_FETCH_SUCCESS:
|
||||||
return state.update('circles', circles => circles.withMutations(map => {
|
return state.update('lists', lists => lists.withMutations(map => {
|
||||||
map.set('isLoading', false);
|
map.set('isLoading', false);
|
||||||
map.set('loaded', true);
|
map.set('loaded', true);
|
||||||
map.set('items', ImmutableList(action.circles.map(item => item.id)));
|
map.set('items', ImmutableList(action.lists.map(item => item.id)));
|
||||||
}));
|
}));
|
||||||
case CIRCLE_EDITOR_ADD_SUCCESS:
|
case LIST_EDITOR_ADD_SUCCESS:
|
||||||
return state.updateIn(['circles', 'items'], circle => circle.unshift(action.circleId));
|
return state.updateIn(['lists', 'items'], list => list.unshift(action.listId));
|
||||||
case CIRCLE_EDITOR_REMOVE_SUCCESS:
|
case LIST_EDITOR_REMOVE_SUCCESS:
|
||||||
return state.updateIn(['circles', 'items'], circle => circle.filterNot(item => item === action.circleId));
|
return state.updateIn(['lists', 'items'], list => list.filterNot(item => item === action.listId));
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||||
include FormattingHelper
|
include FormattingHelper
|
||||||
|
|
||||||
def perform
|
def perform
|
||||||
|
@account.schedule_refresh_if_stale!
|
||||||
|
|
||||||
dereference_object!
|
dereference_object!
|
||||||
|
|
||||||
case @object['type']
|
case @object['type']
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
class ActivityPub::Activity::Update < ActivityPub::Activity
|
class ActivityPub::Activity::Update < ActivityPub::Activity
|
||||||
def perform
|
def perform
|
||||||
|
@account.schedule_refresh_if_stale!
|
||||||
|
|
||||||
dereference_object!
|
dereference_object!
|
||||||
|
|
||||||
if equals_or_includes_any?(@object['type'], %w(Application Group Organization Person Service))
|
if equals_or_includes_any?(@object['type'], %w(Application Group Organization Person Service))
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
||||||
|
INDEXES = [
|
||||||
|
InstancesIndex,
|
||||||
|
AccountsIndex,
|
||||||
|
TagsIndex,
|
||||||
|
StatusesIndex,
|
||||||
|
].freeze
|
||||||
|
|
||||||
def skip?
|
def skip?
|
||||||
!current_user.can?(:view_devops)
|
!current_user.can?(:view_devops)
|
||||||
end
|
end
|
||||||
|
@ -8,11 +15,15 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
||||||
def pass?
|
def pass?
|
||||||
return true unless Chewy.enabled?
|
return true unless Chewy.enabled?
|
||||||
|
|
||||||
running_version.present? && compatible_version?
|
running_version.present? && compatible_version? && cluster_health['status'] == 'green' && indexes_match? && preset_matches?
|
||||||
|
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
|
||||||
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def message
|
def message
|
||||||
if running_version.present?
|
if running_version.blank?
|
||||||
|
Admin::SystemCheck::Message.new(:elasticsearch_running_check)
|
||||||
|
elsif !compatible_version?
|
||||||
Admin::SystemCheck::Message.new(
|
Admin::SystemCheck::Message.new(
|
||||||
:elasticsearch_version_check,
|
:elasticsearch_version_check,
|
||||||
I18n.t(
|
I18n.t(
|
||||||
|
@ -21,13 +32,32 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
||||||
required_version: required_version
|
required_version: required_version
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
elsif !indexes_match?
|
||||||
|
Admin::SystemCheck::Message.new(
|
||||||
|
:elasticsearch_index_mismatch,
|
||||||
|
mismatched_indexes.join(' ')
|
||||||
|
)
|
||||||
|
elsif cluster_health['status'] == 'red'
|
||||||
|
Admin::SystemCheck::Message.new(:elasticsearch_health_red)
|
||||||
|
elsif cluster_health['number_of_nodes'] < 2 && es_preset != 'single_node_cluster'
|
||||||
|
Admin::SystemCheck::Message.new(:elasticsearch_preset_single_node, nil, 'https://docs.joinmastodon.org/admin/optional/elasticsearch/#scaling')
|
||||||
|
elsif Chewy.client.indices.get_settings['chewy_specifications'].dig('settings', 'index', 'number_of_replicas')&.to_i&.positive? && es_preset == 'single_node_cluster'
|
||||||
|
Admin::SystemCheck::Message.new(:elasticsearch_reset_chewy)
|
||||||
|
elsif cluster_health['status'] == 'yellow'
|
||||||
|
Admin::SystemCheck::Message.new(:elasticsearch_health_yellow)
|
||||||
else
|
else
|
||||||
Admin::SystemCheck::Message.new(:elasticsearch_running_check)
|
Admin::SystemCheck::Message.new(:elasticsearch_preset, nil, 'https://docs.joinmastodon.org/admin/optional/elasticsearch/#scaling')
|
||||||
end
|
end
|
||||||
|
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
|
||||||
|
Admin::SystemCheck::Message.new(:elasticsearch_running_check)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def cluster_health
|
||||||
|
@cluster_health ||= Chewy.client.cluster.health
|
||||||
|
end
|
||||||
|
|
||||||
def running_version
|
def running_version
|
||||||
@running_version ||= begin
|
@running_version ||= begin
|
||||||
Chewy.client.info['version']['number']
|
Chewy.client.info['version']['number']
|
||||||
|
@ -49,5 +79,30 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
||||||
|
|
||||||
Gem::Version.new(running_version) >= Gem::Version.new(required_version) ||
|
Gem::Version.new(running_version) >= Gem::Version.new(required_version) ||
|
||||||
Gem::Version.new(compatible_wire_version) >= Gem::Version.new(required_version)
|
Gem::Version.new(compatible_wire_version) >= Gem::Version.new(required_version)
|
||||||
|
rescue ArgumentError
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def mismatched_indexes
|
||||||
|
@mismatched_indexes ||= INDEXES.filter_map do |klass|
|
||||||
|
klass.index_name if Chewy.client.indices.get_mapping[klass.index_name]&.deep_symbolize_keys != klass.mappings_hash
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def indexes_match?
|
||||||
|
mismatched_indexes.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def es_preset
|
||||||
|
ENV.fetch('ES_PRESET', 'single_node_cluster')
|
||||||
|
end
|
||||||
|
|
||||||
|
def preset_matches?
|
||||||
|
case es_preset
|
||||||
|
when 'single_node_cluster'
|
||||||
|
cluster_health['number_of_nodes'] == 1
|
||||||
|
else
|
||||||
|
cluster_health['number_of_nodes'] > 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,6 +67,8 @@ class Account < ApplicationRecord
|
||||||
trust_level
|
trust_level
|
||||||
)
|
)
|
||||||
|
|
||||||
|
BACKGROUND_REFRESH_INTERVAL = 1.week.freeze
|
||||||
|
|
||||||
USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i
|
USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i
|
||||||
MENTION_RE = %r{(?<=^|[^/[:word:]])@((#{USERNAME_RE})(?:@[[:word:].-]+[[:word:]]+)?)}i
|
MENTION_RE = %r{(?<=^|[^/[:word:]])@((#{USERNAME_RE})(?:@[[:word:].-]+[[:word:]]+)?)}i
|
||||||
URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+}
|
URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+}
|
||||||
|
@ -234,6 +236,12 @@ class Account < ApplicationRecord
|
||||||
last_webfingered_at.nil? || last_webfingered_at <= 1.day.ago
|
last_webfingered_at.nil? || last_webfingered_at <= 1.day.ago
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def schedule_refresh_if_stale!
|
||||||
|
return unless last_webfingered_at.present? && last_webfingered_at <= BACKGROUND_REFRESH_INTERVAL.ago
|
||||||
|
|
||||||
|
AccountRefreshWorker.perform_in(rand(6.hours.to_i), id)
|
||||||
|
end
|
||||||
|
|
||||||
def refresh!
|
def refresh!
|
||||||
ResolveAccountService.new.call(acct) unless local?
|
ResolveAccountService.new.call(acct) unless local?
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,14 +15,11 @@ class AntennaAccount < ApplicationRecord
|
||||||
belongs_to :antenna
|
belongs_to :antenna
|
||||||
belongs_to :account
|
belongs_to :account
|
||||||
|
|
||||||
validate :duplicate_account
|
|
||||||
validate :limit_per_antenna
|
validate :limit_per_antenna
|
||||||
|
|
||||||
private
|
validates :account_id, uniqueness: { scope: :antenna_id }
|
||||||
|
|
||||||
def duplicate_account
|
private
|
||||||
raise Mastodon::ValidationError, I18n.t('antennas.errors.duplicate_account') if AntennaAccount.exists?(antenna_id: antenna_id, account_id: account_id, exclude: exclude)
|
|
||||||
end
|
|
||||||
|
|
||||||
def limit_per_antenna
|
def limit_per_antenna
|
||||||
raise Mastodon::ValidationError, I18n.t('antennas.errors.limit.accounts') if AntennaAccount.where(antenna_id: antenna_id).count >= Antenna::ACCOUNTS_PER_ANTENNA_LIMIT
|
raise Mastodon::ValidationError, I18n.t('antennas.errors.limit.accounts') if AntennaAccount.where(antenna_id: antenna_id).count >= Antenna::ACCOUNTS_PER_ANTENNA_LIMIT
|
||||||
|
|
|
@ -14,14 +14,11 @@
|
||||||
class AntennaDomain < ApplicationRecord
|
class AntennaDomain < ApplicationRecord
|
||||||
belongs_to :antenna
|
belongs_to :antenna
|
||||||
|
|
||||||
validate :duplicate_domain
|
|
||||||
validate :limit_per_antenna
|
validate :limit_per_antenna
|
||||||
|
|
||||||
private
|
validates :name, uniqueness: { scope: :antenna_id }
|
||||||
|
|
||||||
def duplicate_domain
|
private
|
||||||
raise Mastodon::ValidationError, I18n.t('antennas.errors.duplicate_domain') if AntennaDomain.exists?(antenna_id: antenna_id, name: name, exclude: exclude)
|
|
||||||
end
|
|
||||||
|
|
||||||
def limit_per_antenna
|
def limit_per_antenna
|
||||||
raise Mastodon::ValidationError, I18n.t('antennas.errors.limit.domains') if AntennaDomain.where(antenna_id: antenna_id).count >= Antenna::DOMAINS_PER_ANTENNA_LIMIT
|
raise Mastodon::ValidationError, I18n.t('antennas.errors.limit.domains') if AntennaDomain.where(antenna_id: antenna_id).count >= Antenna::DOMAINS_PER_ANTENNA_LIMIT
|
||||||
|
|
|
@ -15,14 +15,11 @@ class AntennaTag < ApplicationRecord
|
||||||
belongs_to :antenna
|
belongs_to :antenna
|
||||||
belongs_to :tag
|
belongs_to :tag
|
||||||
|
|
||||||
validate :duplicate_tag
|
|
||||||
validate :limit_per_antenna
|
validate :limit_per_antenna
|
||||||
|
|
||||||
private
|
validates :tag_id, uniqueness: { scope: :antenna_id }
|
||||||
|
|
||||||
def duplicate_tag
|
private
|
||||||
raise Mastodon::ValidationError, I18n.t('antennas.errors.duplicate_tag') if AntennaTag.exists?(antenna_id: antenna_id, tag_id: tag_id, exclude: exclude)
|
|
||||||
end
|
|
||||||
|
|
||||||
def limit_per_antenna
|
def limit_per_antenna
|
||||||
raise Mastodon::ValidationError, I18n.t('antennas.errors.limit.tags') if AntennaTag.where(antenna_id: antenna_id).count >= Antenna::TAGS_PER_ANTENNA_LIMIT
|
raise Mastodon::ValidationError, I18n.t('antennas.errors.limit.tags') if AntennaTag.where(antenna_id: antenna_id).count >= Antenna::TAGS_PER_ANTENNA_LIMIT
|
||||||
|
|
|
@ -52,6 +52,10 @@ module AccountAssociations
|
||||||
has_many :antenna_accounts, inverse_of: :account, dependent: :destroy
|
has_many :antenna_accounts, inverse_of: :account, dependent: :destroy
|
||||||
has_many :joined_antennas, class_name: 'Antenna', through: :antenna_accounts, source: :antenna
|
has_many :joined_antennas, class_name: 'Antenna', through: :antenna_accounts, source: :antenna
|
||||||
|
|
||||||
|
# Circles (that the account is on, not owned by the account)
|
||||||
|
has_many :circle_accounts, inverse_of: :account, dependent: :destroy
|
||||||
|
has_many :joined_circles, class_name: 'Circle', through: :circle_accounts, source: :circle
|
||||||
|
|
||||||
# Lists (that the account is on, not owned by the account)
|
# Lists (that the account is on, not owned by the account)
|
||||||
has_many :list_accounts, inverse_of: :account, dependent: :destroy
|
has_many :list_accounts, inverse_of: :account, dependent: :destroy
|
||||||
has_many :lists, through: :list_accounts
|
has_many :lists, through: :list_accounts
|
||||||
|
|
14
app/workers/account_refresh_worker.rb
Normal file
14
app/workers/account_refresh_worker.rb
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AccountRefreshWorker
|
||||||
|
include Sidekiq::Worker
|
||||||
|
|
||||||
|
sidekiq_options queue: 'pull', retry: 3, dead: false, lock: :until_executed, lock_ttl: 1.day.to_i
|
||||||
|
|
||||||
|
def perform(account_id)
|
||||||
|
account = Account.find_by(id: account_id)
|
||||||
|
return if account.nil? || account.last_webfingered_at > Account::BACKGROUND_REFRESH_INTERVAL.ago
|
||||||
|
|
||||||
|
ResolveAccountService.new.call(account)
|
||||||
|
end
|
||||||
|
end
|
|
@ -873,6 +873,20 @@ en:
|
||||||
system_checks:
|
system_checks:
|
||||||
database_schema_check:
|
database_schema_check:
|
||||||
message_html: There are pending database migrations. Please run them to ensure the application behaves as expected
|
message_html: There are pending database migrations. Please run them to ensure the application behaves as expected
|
||||||
|
elasticsearch_health_red:
|
||||||
|
message_html: Elasticsearch cluster is unhealthy (red status), search features are unavailable
|
||||||
|
elasticsearch_health_yellow:
|
||||||
|
message_html: Elasticsearch cluster is unhealthy (yellow status), you may want to investigate the reason
|
||||||
|
elasticsearch_index_mismatch:
|
||||||
|
message_html: Elasticsearch index mappings are outdated. Please run <code>tootctl search deploy --only=%{value}</code>
|
||||||
|
elasticsearch_preset:
|
||||||
|
action: See documentation
|
||||||
|
message_html: Your Elasticsearch cluster has more than one node, but Mastodon is not configured to use them.
|
||||||
|
elasticsearch_preset_single_node:
|
||||||
|
action: See documentation
|
||||||
|
message_html: Your Elasticsearch cluster has only one node, <code>ES_PRESET</code> should be set to <code>single_node_cluster</code>.
|
||||||
|
elasticsearch_reset_chewy:
|
||||||
|
message_html: Your Elasticsearch system index is outdated due to a setting change. Please run <code>tootctl search deploy --reset-chewy</code> to update it.
|
||||||
elasticsearch_running_check:
|
elasticsearch_running_check:
|
||||||
message_html: Could not connect to Elasticsearch. Please check that it is running, or disable full-text search
|
message_html: Could not connect to Elasticsearch. Please check that it is running, or disable full-text search
|
||||||
elasticsearch_version_check:
|
elasticsearch_version_check:
|
||||||
|
|
|
@ -1023,8 +1023,6 @@ ja:
|
||||||
keyword: キーワード
|
keyword: キーワード
|
||||||
tag: ハッシュタグ
|
tag: ハッシュタグ
|
||||||
errors:
|
errors:
|
||||||
duplicate_domain: すでに同じドメインが登録されています
|
|
||||||
duplicate_keyword: すでに同じキーワードが登録されています
|
|
||||||
empty_contexts: 絞り込み条件が1つも指定されていないため無効です(除外条件はカウントされません)
|
empty_contexts: 絞り込み条件が1つも指定されていないため無効です(除外条件はカウントされません)
|
||||||
invalid_list_owner: これはあなたのリストではありません
|
invalid_list_owner: これはあなたのリストではありません
|
||||||
limit:
|
limit:
|
||||||
|
|
|
@ -107,6 +107,11 @@ namespace :api, format: false do
|
||||||
resources :endorsements, only: [:index]
|
resources :endorsements, only: [:index]
|
||||||
resources :markers, only: [:index, :create]
|
resources :markers, only: [:index, :create]
|
||||||
|
|
||||||
|
namespace :profile do
|
||||||
|
resource :avatar, only: :destroy
|
||||||
|
resource :header, only: :destroy
|
||||||
|
end
|
||||||
|
|
||||||
namespace :apps do
|
namespace :apps do
|
||||||
get :verify_credentials, to: 'credentials#show'
|
get :verify_credentials, to: 'credentials#show'
|
||||||
end
|
end
|
||||||
|
@ -175,6 +180,7 @@ namespace :api, format: false do
|
||||||
resources :following, only: :index, controller: 'accounts/following_accounts'
|
resources :following, only: :index, controller: 'accounts/following_accounts'
|
||||||
resources :lists, only: :index, controller: 'accounts/lists'
|
resources :lists, only: :index, controller: 'accounts/lists'
|
||||||
resources :antennas, only: :index, controller: 'accounts/antennas'
|
resources :antennas, only: :index, controller: 'accounts/antennas'
|
||||||
|
resources :circles, only: :index, controller: 'accounts/circles'
|
||||||
resources :identity_proofs, only: :index, controller: 'accounts/identity_proofs'
|
resources :identity_proofs, only: :index, controller: 'accounts/identity_proofs'
|
||||||
resources :featured_tags, only: :index, controller: 'accounts/featured_tags'
|
resources :featured_tags, only: :index, controller: 'accounts/featured_tags'
|
||||||
|
|
||||||
|
|
17
db/migrate/20230822041804_add_antenna_elements_uniqueness.rb
Normal file
17
db/migrate/20230822041804_add_antenna_elements_uniqueness.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require Rails.root.join('lib', 'mastodon', 'migration_helpers')
|
||||||
|
|
||||||
|
class AddAntennaElementsUniqueness < ActiveRecord::Migration[7.0]
|
||||||
|
include Mastodon::MigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def change
|
||||||
|
safety_assured do
|
||||||
|
add_index :antenna_accounts, [:antenna_id, :account_id], unique: true
|
||||||
|
add_index :antenna_domains, [:antenna_id, :name], unique: true
|
||||||
|
add_index :antenna_tags, [:antenna_id, :tag_id], unique: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.0].define(version: 2023_08_21_061713) do
|
ActiveRecord::Schema[7.0].define(version: 2023_08_22_041804) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
||||||
|
@ -262,6 +262,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_21_061713) do
|
||||||
t.datetime "created_at", precision: nil, null: false
|
t.datetime "created_at", precision: nil, null: false
|
||||||
t.datetime "updated_at", precision: nil, null: false
|
t.datetime "updated_at", precision: nil, null: false
|
||||||
t.index ["account_id"], name: "index_antenna_accounts_on_account_id"
|
t.index ["account_id"], name: "index_antenna_accounts_on_account_id"
|
||||||
|
t.index ["antenna_id", "account_id"], name: "index_antenna_accounts_on_antenna_id_and_account_id", unique: true
|
||||||
t.index ["antenna_id"], name: "index_antenna_accounts_on_antenna_id"
|
t.index ["antenna_id"], name: "index_antenna_accounts_on_antenna_id"
|
||||||
t.index ["exclude"], name: "index_antenna_accounts_on_exclude"
|
t.index ["exclude"], name: "index_antenna_accounts_on_exclude"
|
||||||
end
|
end
|
||||||
|
@ -272,6 +273,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_21_061713) do
|
||||||
t.boolean "exclude", default: false, null: false
|
t.boolean "exclude", default: false, null: false
|
||||||
t.datetime "created_at", precision: nil, null: false
|
t.datetime "created_at", precision: nil, null: false
|
||||||
t.datetime "updated_at", precision: nil, null: false
|
t.datetime "updated_at", precision: nil, null: false
|
||||||
|
t.index ["antenna_id", "name"], name: "index_antenna_domains_on_antenna_id_and_name", unique: true
|
||||||
t.index ["antenna_id"], name: "index_antenna_domains_on_antenna_id"
|
t.index ["antenna_id"], name: "index_antenna_domains_on_antenna_id"
|
||||||
t.index ["exclude"], name: "index_antenna_domains_on_exclude"
|
t.index ["exclude"], name: "index_antenna_domains_on_exclude"
|
||||||
t.index ["name"], name: "index_antenna_domains_on_name"
|
t.index ["name"], name: "index_antenna_domains_on_name"
|
||||||
|
@ -283,6 +285,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_08_21_061713) do
|
||||||
t.boolean "exclude", default: false, null: false
|
t.boolean "exclude", default: false, null: false
|
||||||
t.datetime "created_at", precision: nil, null: false
|
t.datetime "created_at", precision: nil, null: false
|
||||||
t.datetime "updated_at", precision: nil, null: false
|
t.datetime "updated_at", precision: nil, null: false
|
||||||
|
t.index ["antenna_id", "tag_id"], name: "index_antenna_tags_on_antenna_id_and_tag_id", unique: true
|
||||||
t.index ["antenna_id"], name: "index_antenna_tags_on_antenna_id"
|
t.index ["antenna_id"], name: "index_antenna_tags_on_antenna_id"
|
||||||
t.index ["exclude"], name: "index_antenna_tags_on_exclude"
|
t.index ["exclude"], name: "index_antenna_tags_on_exclude"
|
||||||
t.index ["tag_id"], name: "index_antenna_tags_on_tag_id"
|
t.index ["tag_id"], name: "index_antenna_tags_on_tag_id"
|
||||||
|
|
|
@ -17,7 +17,7 @@ module Mastodon
|
||||||
end
|
end
|
||||||
|
|
||||||
def flags
|
def flags
|
||||||
ENV.fetch('MASTODON_VERSION_FLAGS', '-beta1')
|
ENV.fetch('MASTODON_VERSION_FLAGS', '-beta2')
|
||||||
end
|
end
|
||||||
|
|
||||||
def suffix
|
def suffix
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Fabricator(:antenna_account) do
|
Fabricator(:antenna_account) do
|
||||||
|
antenna { Fabricate.build(:antenna) }
|
||||||
|
account { Fabricate.build(:account) }
|
||||||
exclude false
|
exclude false
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Fabricator(:circle_account)
|
Fabricator(:circle_account) do
|
||||||
|
circle { Fabricate(:circle) }
|
||||||
|
account { Fabricate(:account) }
|
||||||
|
before_create { |circle_account, _| circle_account.account.follow!(circle_account.circle.account) }
|
||||||
|
end
|
||||||
|
|
|
@ -11,7 +11,25 @@ describe Admin::SystemCheck::ElasticsearchCheck do
|
||||||
|
|
||||||
describe 'pass?' do
|
describe 'pass?' do
|
||||||
context 'when chewy is enabled' do
|
context 'when chewy is enabled' do
|
||||||
before { allow(Chewy).to receive(:enabled?).and_return(true) }
|
before do
|
||||||
|
allow(Chewy).to receive(:enabled?).and_return(true)
|
||||||
|
allow(Chewy.client.cluster).to receive(:health).and_return({ 'status' => 'green', 'number_of_nodes' => 1 })
|
||||||
|
allow(Chewy.client.indices).to receive(:get_mapping).and_return({
|
||||||
|
AccountsIndex.index_name => AccountsIndex.mappings_hash.deep_stringify_keys,
|
||||||
|
StatusesIndex.index_name => StatusesIndex.mappings_hash.deep_stringify_keys,
|
||||||
|
InstancesIndex.index_name => InstancesIndex.mappings_hash.deep_stringify_keys,
|
||||||
|
TagsIndex.index_name => TagsIndex.mappings_hash.deep_stringify_keys,
|
||||||
|
})
|
||||||
|
allow(Chewy.client.indices).to receive(:get_settings).and_return({
|
||||||
|
'chewy_specifications' => {
|
||||||
|
'settings' => {
|
||||||
|
'index' => {
|
||||||
|
'number_of_replicas' => 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
context 'when running version is present and high enough' do
|
context 'when running version is present and high enough' do
|
||||||
before do
|
before do
|
||||||
|
@ -67,8 +85,19 @@ describe Admin::SystemCheck::ElasticsearchCheck do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'message' do
|
describe 'message' do
|
||||||
|
before do
|
||||||
|
allow(Chewy).to receive(:enabled?).and_return(true)
|
||||||
|
allow(Chewy.client.cluster).to receive(:health).and_return({ 'status' => 'green', 'number_of_nodes' => 1 })
|
||||||
|
allow(Chewy.client.indices).to receive(:get_mapping).and_return({
|
||||||
|
AccountsIndex.index_name => AccountsIndex.mappings_hash.deep_stringify_keys,
|
||||||
|
StatusesIndex.index_name => StatusesIndex.mappings_hash.deep_stringify_keys,
|
||||||
|
InstancesIndex.index_name => InstancesIndex.mappings_hash.deep_stringify_keys,
|
||||||
|
TagsIndex.index_name => TagsIndex.mappings_hash.deep_stringify_keys,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
context 'when running version is present' do
|
context 'when running version is present' do
|
||||||
before { allow(Chewy.client).to receive(:info).and_return({ 'version' => { 'number' => '999.99.9' } }) }
|
before { allow(Chewy.client).to receive(:info).and_return({ 'version' => { 'number' => '1.2.3' } }) }
|
||||||
|
|
||||||
it 'sends class name symbol to message instance' do
|
it 'sends class name symbol to message instance' do
|
||||||
allow(Admin::SystemCheck::Message).to receive(:new)
|
allow(Admin::SystemCheck::Message).to receive(:new)
|
||||||
|
@ -77,7 +106,7 @@ describe Admin::SystemCheck::ElasticsearchCheck do
|
||||||
check.message
|
check.message
|
||||||
|
|
||||||
expect(Admin::SystemCheck::Message).to have_received(:new)
|
expect(Admin::SystemCheck::Message).to have_received(:new)
|
||||||
.with(:elasticsearch_version_check, 'Elasticsearch 999.99.9 is running while 7.x is required')
|
.with(:elasticsearch_version_check, 'Elasticsearch 1.2.3 is running while 7.x is required')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
98
spec/requests/api/v1/profiles_spec.rb
Normal file
98
spec/requests/api/v1/profiles_spec.rb
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'Deleting profile images' do
|
||||||
|
let(:account) do
|
||||||
|
Fabricate(
|
||||||
|
:account,
|
||||||
|
avatar: fixture_file_upload('avatar.gif', 'image/gif'),
|
||||||
|
header: fixture_file_upload('attachment.jpg', 'image/jpeg')
|
||||||
|
)
|
||||||
|
end
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: account.user.id, scopes: scopes) }
|
||||||
|
let(:scopes) { 'write:accounts' }
|
||||||
|
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||||
|
|
||||||
|
describe 'DELETE /api/v1/profile' do
|
||||||
|
before do
|
||||||
|
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when deleting an avatar' do
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
delete '/api/v1/profile/avatar', headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
delete '/api/v1/profile/avatar', headers: headers
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes the avatar' do
|
||||||
|
delete '/api/v1/profile/avatar', headers: headers
|
||||||
|
|
||||||
|
account.reload
|
||||||
|
|
||||||
|
expect(account.avatar).to_not exist
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not delete the header' do
|
||||||
|
delete '/api/v1/profile/avatar', headers: headers
|
||||||
|
|
||||||
|
account.reload
|
||||||
|
|
||||||
|
expect(account.header).to exist
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'queues up an account update distribution' do
|
||||||
|
delete '/api/v1/profile/avatar', headers: headers
|
||||||
|
|
||||||
|
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when deleting a header' do
|
||||||
|
context 'with wrong scope' do
|
||||||
|
before do
|
||||||
|
delete '/api/v1/profile/header', headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
delete '/api/v1/profile/header', headers: headers
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not delete the avatar' do
|
||||||
|
delete '/api/v1/profile/header', headers: headers
|
||||||
|
|
||||||
|
account.reload
|
||||||
|
|
||||||
|
expect(account.avatar).to exist
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes the header' do
|
||||||
|
delete '/api/v1/profile/header', headers: headers
|
||||||
|
|
||||||
|
account.reload
|
||||||
|
|
||||||
|
expect(account.header).to_not exist
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'queues up an account update distribution' do
|
||||||
|
delete '/api/v1/profile/header', headers: headers
|
||||||
|
|
||||||
|
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
371
yarn.lock
371
yarn.lock
|
@ -1253,10 +1253,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz#1816b5f6948029c5eaacb0703b850ee0cb37d8f8"
|
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz#1816b5f6948029c5eaacb0703b850ee0cb37d8f8"
|
||||||
integrity sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==
|
integrity sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==
|
||||||
|
|
||||||
"@eslint/eslintrc@^2.1.1":
|
"@eslint/eslintrc@^2.1.2":
|
||||||
version "2.1.1"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.1.tgz#18d635e24ad35f7276e8a49d135c7d3ca6a46f93"
|
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396"
|
||||||
integrity sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==
|
integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^6.12.4"
|
ajv "^6.12.4"
|
||||||
debug "^4.3.2"
|
debug "^4.3.2"
|
||||||
|
@ -1268,10 +1268,10 @@
|
||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
"@eslint/js@^8.46.0":
|
"@eslint/js@^8.47.0":
|
||||||
version "8.46.0"
|
version "8.47.0"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.46.0.tgz#3f7802972e8b6fe3f88ed1aabc74ec596c456db6"
|
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.47.0.tgz#5478fdf443ff8158f9de171c704ae45308696c7d"
|
||||||
integrity sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==
|
integrity sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==
|
||||||
|
|
||||||
"@floating-ui/core@^1.3.1":
|
"@floating-ui/core@^1.3.1":
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
|
@ -2580,49 +2580,48 @@
|
||||||
"@types/yargs-parser" "*"
|
"@types/yargs-parser" "*"
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@^6.0.0":
|
"@typescript-eslint/eslint-plugin@^6.0.0":
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.3.0.tgz#e751e148aab7ccaf8a7bfd370f7ce9e6bdd1f3f4"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.0.tgz#53428b616f7d80fe879f45a08f11cc0f0b62cf13"
|
||||||
integrity sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==
|
integrity sha512-62o2Hmc7Gs3p8SLfbXcipjWAa6qk2wZGChXG2JbBtYpwSRmti/9KHLqfbLs9uDigOexG+3PaQ9G2g3201FWLKg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/regexpp" "^4.5.1"
|
"@eslint-community/regexpp" "^4.5.1"
|
||||||
"@typescript-eslint/scope-manager" "6.3.0"
|
"@typescript-eslint/scope-manager" "6.4.0"
|
||||||
"@typescript-eslint/type-utils" "6.3.0"
|
"@typescript-eslint/type-utils" "6.4.0"
|
||||||
"@typescript-eslint/utils" "6.3.0"
|
"@typescript-eslint/utils" "6.4.0"
|
||||||
"@typescript-eslint/visitor-keys" "6.3.0"
|
"@typescript-eslint/visitor-keys" "6.4.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
graphemer "^1.4.0"
|
graphemer "^1.4.0"
|
||||||
ignore "^5.2.4"
|
ignore "^5.2.4"
|
||||||
natural-compare "^1.4.0"
|
natural-compare "^1.4.0"
|
||||||
natural-compare-lite "^1.4.0"
|
|
||||||
semver "^7.5.4"
|
semver "^7.5.4"
|
||||||
ts-api-utils "^1.0.1"
|
ts-api-utils "^1.0.1"
|
||||||
|
|
||||||
"@typescript-eslint/parser@^6.0.0":
|
"@typescript-eslint/parser@^6.0.0":
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.3.0.tgz#359684c443f4f848db3c4f14674f544f169c8f46"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.4.0.tgz#47e7c6e22ff1248e8675d95f488890484de67600"
|
||||||
integrity sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==
|
integrity sha512-I1Ah1irl033uxjxO9Xql7+biL3YD7w9IU8zF+xlzD/YxY6a4b7DYA08PXUUCbm2sEljwJF6ERFy2kTGAGcNilg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/scope-manager" "6.3.0"
|
"@typescript-eslint/scope-manager" "6.4.0"
|
||||||
"@typescript-eslint/types" "6.3.0"
|
"@typescript-eslint/types" "6.4.0"
|
||||||
"@typescript-eslint/typescript-estree" "6.3.0"
|
"@typescript-eslint/typescript-estree" "6.4.0"
|
||||||
"@typescript-eslint/visitor-keys" "6.3.0"
|
"@typescript-eslint/visitor-keys" "6.4.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager@6.3.0":
|
"@typescript-eslint/scope-manager@6.4.0":
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.3.0.tgz#6b74e338c4b88d5e1dfc1a28c570dd5cf8c86b09"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.4.0.tgz#3048e4262ba3eafa4e2e69b08912d9037ec646ae"
|
||||||
integrity sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==
|
integrity sha512-TUS7vaKkPWDVvl7GDNHFQMsMruD+zhkd3SdVW0d7b+7Zo+bd/hXJQ8nsiUZMi1jloWo6c9qt3B7Sqo+flC1nig==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "6.3.0"
|
"@typescript-eslint/types" "6.4.0"
|
||||||
"@typescript-eslint/visitor-keys" "6.3.0"
|
"@typescript-eslint/visitor-keys" "6.4.0"
|
||||||
|
|
||||||
"@typescript-eslint/type-utils@6.3.0":
|
"@typescript-eslint/type-utils@6.4.0":
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.3.0.tgz#3bf89ccd36621ddec1b7f8246afe467c67adc247"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.4.0.tgz#c8ac92716ed6a9d5443aa3e342910355b0796ba0"
|
||||||
integrity sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==
|
integrity sha512-TvqrUFFyGY0cX3WgDHcdl2/mMCWCDv/0thTtx/ODMY1QhEiyFtv/OlLaNIiYLwRpAxAtOLOY9SUf1H3Q3dlwAg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/typescript-estree" "6.3.0"
|
"@typescript-eslint/typescript-estree" "6.4.0"
|
||||||
"@typescript-eslint/utils" "6.3.0"
|
"@typescript-eslint/utils" "6.4.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
ts-api-utils "^1.0.1"
|
ts-api-utils "^1.0.1"
|
||||||
|
|
||||||
|
@ -2631,10 +2630,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.0.tgz#3fcdac7dbf923ec5251545acdd9f1d42d7c4fe32"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.0.tgz#3fcdac7dbf923ec5251545acdd9f1d42d7c4fe32"
|
||||||
integrity sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==
|
integrity sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==
|
||||||
|
|
||||||
"@typescript-eslint/types@6.3.0":
|
"@typescript-eslint/types@6.4.0":
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.3.0.tgz#84517f1427923e714b8418981e493b6635ab4c9d"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.4.0.tgz#5b109a59a805f0d8d375895e42d9e5f0037f66ee"
|
||||||
integrity sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==
|
integrity sha512-+FV9kVFrS7w78YtzkIsNSoYsnOtrYVnKWSTVXoL1761CsCRv5wpDOINgsXpxD67YCLZtVQekDDyaxfjVWUJmmg==
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@5.59.0":
|
"@typescript-eslint/typescript-estree@5.59.0":
|
||||||
version "5.59.0"
|
version "5.59.0"
|
||||||
|
@ -2649,30 +2648,30 @@
|
||||||
semver "^7.3.7"
|
semver "^7.3.7"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@6.3.0":
|
"@typescript-eslint/typescript-estree@6.4.0":
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.3.0.tgz#20e1e10e2f51cdb9e19a2751215cac92c003643c"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.0.tgz#3c58d20632db93fec3d6ab902acbedf593d37276"
|
||||||
integrity sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==
|
integrity sha512-iDPJArf/K2sxvjOR6skeUCNgHR/tCQXBsa+ee1/clRKr3olZjZ/dSkXPZjG6YkPtnW6p5D1egeEPMCW6Gn4yLA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "6.3.0"
|
"@typescript-eslint/types" "6.4.0"
|
||||||
"@typescript-eslint/visitor-keys" "6.3.0"
|
"@typescript-eslint/visitor-keys" "6.4.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
globby "^11.1.0"
|
globby "^11.1.0"
|
||||||
is-glob "^4.0.3"
|
is-glob "^4.0.3"
|
||||||
semver "^7.5.4"
|
semver "^7.5.4"
|
||||||
ts-api-utils "^1.0.1"
|
ts-api-utils "^1.0.1"
|
||||||
|
|
||||||
"@typescript-eslint/utils@6.3.0":
|
"@typescript-eslint/utils@6.4.0":
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.3.0.tgz#0898c5e374372c2092ca1b979ea7ee9cc020ce84"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.4.0.tgz#23e996b693603c5924b1fbb733cc73196256baa5"
|
||||||
integrity sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==
|
integrity sha512-BvvwryBQpECPGo8PwF/y/q+yacg8Hn/2XS+DqL/oRsOPK+RPt29h5Ui5dqOKHDlbXrAeHUTnyG3wZA0KTDxRZw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/eslint-utils" "^4.4.0"
|
"@eslint-community/eslint-utils" "^4.4.0"
|
||||||
"@types/json-schema" "^7.0.12"
|
"@types/json-schema" "^7.0.12"
|
||||||
"@types/semver" "^7.5.0"
|
"@types/semver" "^7.5.0"
|
||||||
"@typescript-eslint/scope-manager" "6.3.0"
|
"@typescript-eslint/scope-manager" "6.4.0"
|
||||||
"@typescript-eslint/types" "6.3.0"
|
"@typescript-eslint/types" "6.4.0"
|
||||||
"@typescript-eslint/typescript-estree" "6.3.0"
|
"@typescript-eslint/typescript-estree" "6.4.0"
|
||||||
semver "^7.5.4"
|
semver "^7.5.4"
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys@5.59.0":
|
"@typescript-eslint/visitor-keys@5.59.0":
|
||||||
|
@ -2683,12 +2682,12 @@
|
||||||
"@typescript-eslint/types" "5.59.0"
|
"@typescript-eslint/types" "5.59.0"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys@6.3.0":
|
"@typescript-eslint/visitor-keys@6.4.0":
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.3.0.tgz#8d09aa3e389ae0971426124c155ac289afbe450a"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.0.tgz#96a426cdb1add28274abd7a34aefe27f8b7d51ef"
|
||||||
integrity sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==
|
integrity sha512-yJSfyT+uJm+JRDWYRYdCm2i+pmvXJSMtPR9Cq5/XQs4QIgNoLcoRtDdzsLbLsFM/c6um6ohQkg/MLxWvoIndJA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "6.3.0"
|
"@typescript-eslint/types" "6.4.0"
|
||||||
eslint-visitor-keys "^3.4.1"
|
eslint-visitor-keys "^3.4.1"
|
||||||
|
|
||||||
"@webassemblyjs/ast@1.9.0":
|
"@webassemblyjs/ast@1.9.0":
|
||||||
|
@ -3280,6 +3279,13 @@ async@^3.2.3:
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
|
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
|
||||||
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
|
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
|
||||||
|
|
||||||
|
asynciterator.prototype@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62"
|
||||||
|
integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==
|
||||||
|
dependencies:
|
||||||
|
has-symbols "^1.0.3"
|
||||||
|
|
||||||
asynckit@^0.4.0:
|
asynckit@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
|
@ -4311,9 +4317,9 @@ core-js@^2.5.0:
|
||||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||||
|
|
||||||
core-js@^3.30.2:
|
core-js@^3.30.2:
|
||||||
version "3.32.0"
|
version "3.32.1"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.32.0.tgz#7643d353d899747ab1f8b03d2803b0312a0fb3b6"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.32.1.tgz#a7d8736a3ed9dd05940c3c4ff32c591bb735be77"
|
||||||
integrity sha512-rd4rYZNlF3WuoYuRIDEmbR/ga9CeuWX9U05umAvgrrZoHY4Z++cp/xwPQMvUpBB4Ag6J8KfD80G0zwCyaSxDww==
|
integrity sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ==
|
||||||
|
|
||||||
core-util-is@~1.0.0:
|
core-util-is@~1.0.0:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
|
@ -5172,7 +5178,7 @@ error-stack-parser@^2.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
stackframe "^1.3.4"
|
stackframe "^1.3.4"
|
||||||
|
|
||||||
es-abstract@^1.17.2, es-abstract@^1.21.2:
|
es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2, es-abstract@^1.21.3:
|
||||||
version "1.22.1"
|
version "1.22.1"
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc"
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc"
|
||||||
integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==
|
integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==
|
||||||
|
@ -5217,46 +5223,6 @@ es-abstract@^1.17.2, es-abstract@^1.21.2:
|
||||||
unbox-primitive "^1.0.2"
|
unbox-primitive "^1.0.2"
|
||||||
which-typed-array "^1.1.10"
|
which-typed-array "^1.1.10"
|
||||||
|
|
||||||
es-abstract@^1.19.0, es-abstract@^1.20.4:
|
|
||||||
version "1.21.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff"
|
|
||||||
integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==
|
|
||||||
dependencies:
|
|
||||||
array-buffer-byte-length "^1.0.0"
|
|
||||||
available-typed-arrays "^1.0.5"
|
|
||||||
call-bind "^1.0.2"
|
|
||||||
es-set-tostringtag "^2.0.1"
|
|
||||||
es-to-primitive "^1.2.1"
|
|
||||||
function.prototype.name "^1.1.5"
|
|
||||||
get-intrinsic "^1.2.0"
|
|
||||||
get-symbol-description "^1.0.0"
|
|
||||||
globalthis "^1.0.3"
|
|
||||||
gopd "^1.0.1"
|
|
||||||
has "^1.0.3"
|
|
||||||
has-property-descriptors "^1.0.0"
|
|
||||||
has-proto "^1.0.1"
|
|
||||||
has-symbols "^1.0.3"
|
|
||||||
internal-slot "^1.0.5"
|
|
||||||
is-array-buffer "^3.0.2"
|
|
||||||
is-callable "^1.2.7"
|
|
||||||
is-negative-zero "^2.0.2"
|
|
||||||
is-regex "^1.1.4"
|
|
||||||
is-shared-array-buffer "^1.0.2"
|
|
||||||
is-string "^1.0.7"
|
|
||||||
is-typed-array "^1.1.10"
|
|
||||||
is-weakref "^1.0.2"
|
|
||||||
object-inspect "^1.12.3"
|
|
||||||
object-keys "^1.1.1"
|
|
||||||
object.assign "^4.1.4"
|
|
||||||
regexp.prototype.flags "^1.4.3"
|
|
||||||
safe-regex-test "^1.0.0"
|
|
||||||
string.prototype.trim "^1.2.7"
|
|
||||||
string.prototype.trimend "^1.0.6"
|
|
||||||
string.prototype.trimstart "^1.0.6"
|
|
||||||
typed-array-length "^1.0.4"
|
|
||||||
unbox-primitive "^1.0.2"
|
|
||||||
which-typed-array "^1.1.9"
|
|
||||||
|
|
||||||
es-array-method-boxes-properly@^1.0.0:
|
es-array-method-boxes-properly@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
|
resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
|
||||||
|
@ -5277,6 +5243,26 @@ es-get-iterator@^1.1.3:
|
||||||
isarray "^2.0.5"
|
isarray "^2.0.5"
|
||||||
stop-iteration-iterator "^1.0.0"
|
stop-iteration-iterator "^1.0.0"
|
||||||
|
|
||||||
|
es-iterator-helpers@^1.0.12:
|
||||||
|
version "1.0.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.13.tgz#72101046ffc19baf9996adc70e6177a26e6e8084"
|
||||||
|
integrity sha512-LK3VGwzvaPWobO8xzXXGRUOGw8Dcjyfk62CsY/wfHN75CwsJPbuypOYJxK6g5RyEL8YDjIWcl6jgd8foO6mmrA==
|
||||||
|
dependencies:
|
||||||
|
asynciterator.prototype "^1.0.0"
|
||||||
|
call-bind "^1.0.2"
|
||||||
|
define-properties "^1.2.0"
|
||||||
|
es-abstract "^1.21.3"
|
||||||
|
es-set-tostringtag "^2.0.1"
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
get-intrinsic "^1.2.1"
|
||||||
|
globalthis "^1.0.3"
|
||||||
|
has-property-descriptors "^1.0.0"
|
||||||
|
has-proto "^1.0.1"
|
||||||
|
has-symbols "^1.0.3"
|
||||||
|
internal-slot "^1.0.5"
|
||||||
|
iterator.prototype "^1.1.0"
|
||||||
|
safe-array-concat "^1.0.0"
|
||||||
|
|
||||||
es-set-tostringtag@^2.0.1:
|
es-set-tostringtag@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
|
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
|
||||||
|
@ -5344,13 +5330,13 @@ eslint-config-prettier@^9.0.0:
|
||||||
integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==
|
integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==
|
||||||
|
|
||||||
eslint-import-resolver-node@^0.3.7:
|
eslint-import-resolver-node@^0.3.7:
|
||||||
version "0.3.7"
|
version "0.3.9"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7"
|
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac"
|
||||||
integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==
|
integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^3.2.7"
|
debug "^3.2.7"
|
||||||
is-core-module "^2.11.0"
|
is-core-module "^2.13.0"
|
||||||
resolve "^1.22.1"
|
resolve "^1.22.4"
|
||||||
|
|
||||||
eslint-import-resolver-typescript@^3.5.5:
|
eslint-import-resolver-typescript@^3.5.5:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
|
@ -5390,9 +5376,9 @@ eslint-plugin-formatjs@^4.10.1:
|
||||||
unicode-emoji-utils "^1.1.1"
|
unicode-emoji-utils "^1.1.1"
|
||||||
|
|
||||||
eslint-plugin-import@~2.28.0:
|
eslint-plugin-import@~2.28.0:
|
||||||
version "2.28.0"
|
version "2.28.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.0.tgz#8d66d6925117b06c4018d491ae84469eb3cb1005"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4"
|
||||||
integrity sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==
|
integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes "^3.1.6"
|
array-includes "^3.1.6"
|
||||||
array.prototype.findlastindex "^1.2.2"
|
array.prototype.findlastindex "^1.2.2"
|
||||||
|
@ -5403,20 +5389,19 @@ eslint-plugin-import@~2.28.0:
|
||||||
eslint-import-resolver-node "^0.3.7"
|
eslint-import-resolver-node "^0.3.7"
|
||||||
eslint-module-utils "^2.8.0"
|
eslint-module-utils "^2.8.0"
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
is-core-module "^2.12.1"
|
is-core-module "^2.13.0"
|
||||||
is-glob "^4.0.3"
|
is-glob "^4.0.3"
|
||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
object.fromentries "^2.0.6"
|
object.fromentries "^2.0.6"
|
||||||
object.groupby "^1.0.0"
|
object.groupby "^1.0.0"
|
||||||
object.values "^1.1.6"
|
object.values "^1.1.6"
|
||||||
resolve "^1.22.3"
|
|
||||||
semver "^6.3.1"
|
semver "^6.3.1"
|
||||||
tsconfig-paths "^3.14.2"
|
tsconfig-paths "^3.14.2"
|
||||||
|
|
||||||
eslint-plugin-jsdoc@^46.1.0:
|
eslint-plugin-jsdoc@^46.1.0:
|
||||||
version "46.4.6"
|
version "46.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz#5226461eda61b5920297cbe02c3b17bc9423cf0b"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.5.0.tgz#02e7945701a01fab76e7ced850d4d1eea63c23c0"
|
||||||
integrity sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==
|
integrity sha512-aulXdA4I1dyWpzyS1Nh/GNoS6PavzeucxEapnMR4JUERowWvaEk2Y4A5irpHAcdXtBBHLVe8WIhdXNjoAlGQgA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@es-joy/jsdoccomment" "~0.40.1"
|
"@es-joy/jsdoccomment" "~0.40.1"
|
||||||
are-docs-informative "^0.0.2"
|
are-docs-informative "^0.0.2"
|
||||||
|
@ -5469,14 +5454,15 @@ eslint-plugin-react-hooks@^4.6.0:
|
||||||
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
|
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
|
||||||
|
|
||||||
eslint-plugin-react@~7.33.0:
|
eslint-plugin-react@~7.33.0:
|
||||||
version "7.33.1"
|
version "7.33.2"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.1.tgz#bc27cccf860ae45413a4a4150bf0977345c1ceab"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608"
|
||||||
integrity sha512-L093k0WAMvr6VhNwReB8VgOq5s2LesZmrpPdKz/kZElQDzqS7G7+DnKoqT+w4JwuiGeAhAvHO0fvy0Eyk4ejDA==
|
integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes "^3.1.6"
|
array-includes "^3.1.6"
|
||||||
array.prototype.flatmap "^1.3.1"
|
array.prototype.flatmap "^1.3.1"
|
||||||
array.prototype.tosorted "^1.1.1"
|
array.prototype.tosorted "^1.1.1"
|
||||||
doctrine "^2.1.0"
|
doctrine "^2.1.0"
|
||||||
|
es-iterator-helpers "^1.0.12"
|
||||||
estraverse "^5.3.0"
|
estraverse "^5.3.0"
|
||||||
jsx-ast-utils "^2.4.1 || ^3.0.0"
|
jsx-ast-utils "^2.4.1 || ^3.0.0"
|
||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
|
@ -5505,20 +5491,20 @@ eslint-scope@^7.2.2:
|
||||||
esrecurse "^4.3.0"
|
esrecurse "^4.3.0"
|
||||||
estraverse "^5.2.0"
|
estraverse "^5.2.0"
|
||||||
|
|
||||||
eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.2:
|
eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3:
|
||||||
version "3.4.2"
|
version "3.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz#8c2095440eca8c933bedcadf16fefa44dbe9ba5f"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||||
integrity sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==
|
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||||
|
|
||||||
eslint@^8.41.0:
|
eslint@^8.41.0:
|
||||||
version "8.46.0"
|
version "8.47.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.46.0.tgz#a06a0ff6974e53e643acc42d1dcf2e7f797b3552"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.47.0.tgz#c95f9b935463fb4fad7005e626c7621052e90806"
|
||||||
integrity sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==
|
integrity sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/eslint-utils" "^4.2.0"
|
"@eslint-community/eslint-utils" "^4.2.0"
|
||||||
"@eslint-community/regexpp" "^4.6.1"
|
"@eslint-community/regexpp" "^4.6.1"
|
||||||
"@eslint/eslintrc" "^2.1.1"
|
"@eslint/eslintrc" "^2.1.2"
|
||||||
"@eslint/js" "^8.46.0"
|
"@eslint/js" "^8.47.0"
|
||||||
"@humanwhocodes/config-array" "^0.11.10"
|
"@humanwhocodes/config-array" "^0.11.10"
|
||||||
"@humanwhocodes/module-importer" "^1.0.1"
|
"@humanwhocodes/module-importer" "^1.0.1"
|
||||||
"@nodelib/fs.walk" "^1.2.8"
|
"@nodelib/fs.walk" "^1.2.8"
|
||||||
|
@ -5529,7 +5515,7 @@ eslint@^8.41.0:
|
||||||
doctrine "^3.0.0"
|
doctrine "^3.0.0"
|
||||||
escape-string-regexp "^4.0.0"
|
escape-string-regexp "^4.0.0"
|
||||||
eslint-scope "^7.2.2"
|
eslint-scope "^7.2.2"
|
||||||
eslint-visitor-keys "^3.4.2"
|
eslint-visitor-keys "^3.4.3"
|
||||||
espree "^9.6.1"
|
espree "^9.6.1"
|
||||||
esquery "^1.4.2"
|
esquery "^1.4.2"
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
|
@ -6274,9 +6260,9 @@ globals@^11.1.0:
|
||||||
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
||||||
|
|
||||||
globals@^13.19.0:
|
globals@^13.19.0:
|
||||||
version "13.20.0"
|
version "13.21.0"
|
||||||
resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82"
|
resolved "https://registry.yarnpkg.com/globals/-/globals-13.21.0.tgz#163aae12f34ef502f5153cfbdd3600f36c63c571"
|
||||||
integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==
|
integrity sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==
|
||||||
dependencies:
|
dependencies:
|
||||||
type-fest "^0.20.2"
|
type-fest "^0.20.2"
|
||||||
|
|
||||||
|
@ -6860,6 +6846,13 @@ is-arrayish@^0.2.1:
|
||||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||||
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
|
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
|
||||||
|
|
||||||
|
is-async-function@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646"
|
||||||
|
integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==
|
||||||
|
dependencies:
|
||||||
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
is-bigint@^1.0.1:
|
is-bigint@^1.0.1:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
|
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
|
||||||
|
@ -6901,20 +6894,13 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
|
||||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
|
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
|
||||||
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
|
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
|
||||||
|
|
||||||
is-core-module@^2.11.0, is-core-module@^2.12.1, is-core-module@^2.13.0, is-core-module@^2.5.0:
|
is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.5.0, is-core-module@^2.9.0:
|
||||||
version "2.13.0"
|
version "2.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db"
|
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db"
|
||||||
integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==
|
integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
|
|
||||||
is-core-module@^2.9.0:
|
|
||||||
version "2.12.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd"
|
|
||||||
integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==
|
|
||||||
dependencies:
|
|
||||||
has "^1.0.3"
|
|
||||||
|
|
||||||
is-data-descriptor@^0.1.4:
|
is-data-descriptor@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
|
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
|
||||||
|
@ -6986,6 +6972,13 @@ is-extglob@^2.1.0, is-extglob@^2.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||||
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
||||||
|
|
||||||
|
is-finalizationregistry@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6"
|
||||||
|
integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==
|
||||||
|
dependencies:
|
||||||
|
call-bind "^1.0.2"
|
||||||
|
|
||||||
is-fullwidth-code-point@^2.0.0:
|
is-fullwidth-code-point@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||||
|
@ -7006,6 +6999,13 @@ is-generator-fn@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
|
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
|
||||||
integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
|
integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
|
||||||
|
|
||||||
|
is-generator-function@^1.0.10:
|
||||||
|
version "1.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
|
||||||
|
integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==
|
||||||
|
dependencies:
|
||||||
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
is-glob@^3.1.0:
|
is-glob@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
|
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
|
||||||
|
@ -7167,15 +7167,11 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
|
||||||
has-symbols "^1.0.2"
|
has-symbols "^1.0.2"
|
||||||
|
|
||||||
is-typed-array@^1.1.10, is-typed-array@^1.1.9:
|
is-typed-array@^1.1.10, is-typed-array@^1.1.9:
|
||||||
version "1.1.10"
|
version "1.1.12"
|
||||||
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f"
|
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a"
|
||||||
integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
|
integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==
|
||||||
dependencies:
|
dependencies:
|
||||||
available-typed-arrays "^1.0.5"
|
which-typed-array "^1.1.11"
|
||||||
call-bind "^1.0.2"
|
|
||||||
for-each "^0.3.3"
|
|
||||||
gopd "^1.0.1"
|
|
||||||
has-tostringtag "^1.0.0"
|
|
||||||
|
|
||||||
is-url@^1.2.4:
|
is-url@^1.2.4:
|
||||||
version "1.2.4"
|
version "1.2.4"
|
||||||
|
@ -7293,6 +7289,17 @@ istanbul-reports@^3.1.3:
|
||||||
html-escaper "^2.0.0"
|
html-escaper "^2.0.0"
|
||||||
istanbul-lib-report "^3.0.0"
|
istanbul-lib-report "^3.0.0"
|
||||||
|
|
||||||
|
iterator.prototype@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.0.tgz#690c88b043d821f783843aaf725d7ac3b62e3b46"
|
||||||
|
integrity sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==
|
||||||
|
dependencies:
|
||||||
|
define-properties "^1.1.4"
|
||||||
|
get-intrinsic "^1.1.3"
|
||||||
|
has-symbols "^1.0.3"
|
||||||
|
has-tostringtag "^1.0.0"
|
||||||
|
reflect.getprototypeof "^1.0.3"
|
||||||
|
|
||||||
jackspeak@^2.0.3:
|
jackspeak@^2.0.3:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.2.1.tgz#655e8cf025d872c9c03d3eb63e8f0c024fef16a6"
|
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.2.1.tgz#655e8cf025d872c9c03d3eb63e8f0c024fef16a6"
|
||||||
|
@ -7873,7 +7880,17 @@ jsonpointer@^5.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"
|
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"
|
||||||
integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==
|
integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==
|
||||||
|
|
||||||
"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3:
|
"jsx-ast-utils@^2.4.1 || ^3.0.0":
|
||||||
|
version "3.3.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a"
|
||||||
|
integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==
|
||||||
|
dependencies:
|
||||||
|
array-includes "^3.1.6"
|
||||||
|
array.prototype.flat "^1.3.1"
|
||||||
|
object.assign "^4.1.4"
|
||||||
|
object.values "^1.1.6"
|
||||||
|
|
||||||
|
jsx-ast-utils@^3.3.3:
|
||||||
version "3.3.3"
|
version "3.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"
|
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"
|
||||||
integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==
|
integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==
|
||||||
|
@ -8569,11 +8586,6 @@ nanomatch@^1.2.9:
|
||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
natural-compare-lite@^1.4.0:
|
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4"
|
|
||||||
integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==
|
|
||||||
|
|
||||||
natural-compare@^1.4.0:
|
natural-compare@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
|
@ -10265,6 +10277,18 @@ redux@^4.0.0, redux@^4.0.4, redux@^4.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.9.2"
|
"@babel/runtime" "^7.9.2"
|
||||||
|
|
||||||
|
reflect.getprototypeof@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz#2738fd896fcc3477ffbd4190b40c2458026b6928"
|
||||||
|
integrity sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==
|
||||||
|
dependencies:
|
||||||
|
call-bind "^1.0.2"
|
||||||
|
define-properties "^1.1.4"
|
||||||
|
es-abstract "^1.20.4"
|
||||||
|
get-intrinsic "^1.1.1"
|
||||||
|
globalthis "^1.0.3"
|
||||||
|
which-builtin-type "^1.1.3"
|
||||||
|
|
||||||
regenerate-unicode-properties@^10.1.0:
|
regenerate-unicode-properties@^10.1.0:
|
||||||
version "10.1.0"
|
version "10.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"
|
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"
|
||||||
|
@ -10442,7 +10466,7 @@ resolve.exports@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800"
|
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800"
|
||||||
integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==
|
integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==
|
||||||
|
|
||||||
resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.3:
|
resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.4:
|
||||||
version "1.22.4"
|
version "1.22.4"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34"
|
||||||
integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==
|
integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==
|
||||||
|
@ -10451,7 +10475,7 @@ resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.3:
|
||||||
path-parse "^1.0.7"
|
path-parse "^1.0.7"
|
||||||
supports-preserve-symlinks-flag "^1.0.0"
|
supports-preserve-symlinks-flag "^1.0.0"
|
||||||
|
|
||||||
resolve@^1.19.0, resolve@^1.22.1:
|
resolve@^1.19.0:
|
||||||
version "1.22.2"
|
version "1.22.2"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
|
||||||
integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
|
integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
|
||||||
|
@ -11309,7 +11333,6 @@ stringz@^2.1.0:
|
||||||
char-regex "^1.0.2"
|
char-regex "^1.0.2"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
name strip-ansi-cjs
|
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
@ -11843,9 +11866,9 @@ trim-newlines@^4.0.2:
|
||||||
integrity sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==
|
integrity sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==
|
||||||
|
|
||||||
ts-api-utils@^1.0.1:
|
ts-api-utils@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.1.tgz#8144e811d44c749cd65b2da305a032510774452d"
|
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.2.tgz#7c094f753b6705ee4faee25c3c684ade52d66d99"
|
||||||
integrity sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==
|
integrity sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==
|
||||||
|
|
||||||
tsconfig-paths@^3.14.2:
|
tsconfig-paths@^3.14.2:
|
||||||
version "3.14.2"
|
version "3.14.2"
|
||||||
|
@ -12562,6 +12585,24 @@ which-boxed-primitive@^1.0.2:
|
||||||
is-string "^1.0.5"
|
is-string "^1.0.5"
|
||||||
is-symbol "^1.0.3"
|
is-symbol "^1.0.3"
|
||||||
|
|
||||||
|
which-builtin-type@^1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b"
|
||||||
|
integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==
|
||||||
|
dependencies:
|
||||||
|
function.prototype.name "^1.1.5"
|
||||||
|
has-tostringtag "^1.0.0"
|
||||||
|
is-async-function "^2.0.0"
|
||||||
|
is-date-object "^1.0.5"
|
||||||
|
is-finalizationregistry "^1.0.2"
|
||||||
|
is-generator-function "^1.0.10"
|
||||||
|
is-regex "^1.1.4"
|
||||||
|
is-weakref "^1.0.2"
|
||||||
|
isarray "^2.0.5"
|
||||||
|
which-boxed-primitive "^1.0.2"
|
||||||
|
which-collection "^1.0.1"
|
||||||
|
which-typed-array "^1.1.9"
|
||||||
|
|
||||||
which-collection@^1.0.1:
|
which-collection@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
|
resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
|
||||||
|
@ -12577,7 +12618,7 @@ which-module@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
|
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
|
||||||
integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
|
integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
|
||||||
|
|
||||||
which-typed-array@^1.1.10:
|
which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.9:
|
||||||
version "1.1.11"
|
version "1.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a"
|
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a"
|
||||||
integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==
|
integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==
|
||||||
|
@ -12588,18 +12629,6 @@ which-typed-array@^1.1.10:
|
||||||
gopd "^1.0.1"
|
gopd "^1.0.1"
|
||||||
has-tostringtag "^1.0.0"
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
which-typed-array@^1.1.9:
|
|
||||||
version "1.1.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
|
|
||||||
integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
|
|
||||||
dependencies:
|
|
||||||
available-typed-arrays "^1.0.5"
|
|
||||||
call-bind "^1.0.2"
|
|
||||||
for-each "^0.3.3"
|
|
||||||
gopd "^1.0.1"
|
|
||||||
has-tostringtag "^1.0.0"
|
|
||||||
is-typed-array "^1.1.10"
|
|
||||||
|
|
||||||
which@^1.2.14, which@^1.2.9, which@^1.3.1:
|
which@^1.2.14, which@^1.2.9, which@^1.3.1:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue