summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormisskey-release-bot[bot] <157398866+misskey-release-bot[bot]@users.noreply.github.com>2025-03-09 03:29:58 +0000
committerGitHub <noreply@github.com>2025-03-09 03:29:58 +0000
commitbef73ff530e84418c8257aff558b677a4aa71064 (patch)
treee2a64f47e2c1c60b34fb240cb85aff308cc3bb59
parentMerge pull request #15585 from misskey-dev/develop (diff)
parentRelease: 2025.3.1 (diff)
downloadmisskey-bef73ff530e84418c8257aff558b677a4aa71064.tar.gz
misskey-bef73ff530e84418c8257aff558b677a4aa71064.tar.bz2
misskey-bef73ff530e84418c8257aff558b677a4aa71064.zip
Merge pull request #15615 from misskey-dev/develop
Release: 2025.3.1
-rw-r--r--.devcontainer/devcontainer.json4
-rwxr-xr-x.devcontainer/init.sh2
-rw-r--r--.github/workflows/api-misskey-js.yml7
-rw-r--r--.github/workflows/get-api-diff.yml9
-rw-r--r--.github/workflows/lint.yml16
-rw-r--r--.github/workflows/locale.yml8
-rw-r--r--.github/workflows/on-release-created.yml8
-rw-r--r--.github/workflows/storybook.yml8
-rw-r--r--.github/workflows/test-backend.yml14
-rw-r--r--.github/workflows/test-federation.yml8
-rw-r--r--.github/workflows/test-frontend.yml14
-rw-r--r--.github/workflows/test-misskey-js.yml7
-rw-r--r--.github/workflows/test-production.yml6
-rw-r--r--.github/workflows/validate-api-json.yml9
-rw-r--r--.npmrc2
-rw-r--r--CHANGELOG.md15
-rw-r--r--Dockerfile22
-rw-r--r--locales/ca-ES.yml10
-rw-r--r--locales/en-US.yml9
-rw-r--r--locales/index.d.ts10
-rw-r--r--locales/it-IT.yml4
-rw-r--r--locales/ja-JP.yml4
-rw-r--r--locales/zh-CN.yml2
-rw-r--r--locales/zh-TW.yml2
-rw-r--r--package.json37
-rw-r--r--packages/backend/migration/1741279404074-system-accounts-fixup.js26
-rw-r--r--packages/backend/migration/1741424411879-user-featured-fixup.js26
-rw-r--r--packages/backend/src/core/FileInfoService.ts1
-rw-r--r--packages/backend/src/core/activitypub/models/ApPersonService.ts2
-rw-r--r--packages/backend/src/server/ActivityPubServerService.ts2
-rw-r--r--packages/backend/src/server/FileServerService.ts2
-rw-r--r--packages/backend/test-federation/compose.tpl.yml7
-rw-r--r--packages/backend/test-federation/compose.yml17
-rw-r--r--packages/frontend-embed/package.json12
-rw-r--r--packages/frontend-shared/package.json4
-rw-r--r--packages/frontend/.storybook/main.ts4
-rw-r--r--packages/frontend/lib/vite-plugin-create-search-index.ts1496
-rw-r--r--packages/frontend/package.json53
-rw-r--r--packages/frontend/src/components/MkDisableSection.vue (renamed from idea/MkDisableSection.vue)5
-rw-r--r--packages/frontend/src/components/MkPageWindow.vue12
-rw-r--r--packages/frontend/src/components/MkSuperMenu.vue208
-rw-r--r--packages/frontend/src/components/global/SearchKeyword.vue14
-rw-r--r--packages/frontend/src/components/global/SearchLabel.vue14
-rw-r--r--packages/frontend/src/components/global/SearchMarker.vue116
-rw-r--r--packages/frontend/src/components/index.ts13
-rw-r--r--packages/frontend/src/pages/settings/2fa.vue126
-rw-r--r--packages/frontend/src/pages/settings/accessibility.vue91
-rw-r--r--packages/frontend/src/pages/settings/appearance.vue287
-rw-r--r--packages/frontend/src/pages/settings/avatar-decoration.vue58
-rw-r--r--packages/frontend/src/pages/settings/drive.vue123
-rw-r--r--packages/frontend/src/pages/settings/email.vue88
-rw-r--r--packages/frontend/src/pages/settings/general.vue492
-rw-r--r--packages/frontend/src/pages/settings/import-export.vue245
-rw-r--r--packages/frontend/src/pages/settings/index.vue41
-rw-r--r--packages/frontend/src/pages/settings/migration.vue6
-rw-r--r--packages/frontend/src/pages/settings/mute-block.vue255
-rw-r--r--packages/frontend/src/pages/settings/other.vue158
-rw-r--r--packages/frontend/src/pages/settings/preferences.vue434
-rw-r--r--packages/frontend/src/pages/settings/privacy.vue313
-rw-r--r--packages/frontend/src/pages/settings/profile.vue227
-rw-r--r--packages/frontend/src/pages/settings/security.vue67
-rw-r--r--packages/frontend/src/pages/settings/sounds.vue70
-rw-r--r--packages/frontend/src/pages/settings/theme.vue106
-rw-r--r--packages/frontend/src/router/definition.ts20
-rw-r--r--packages/frontend/src/scripts/autogen/settings-search-index.ts815
-rw-r--r--packages/frontend/src/ui/_common_/navbar.vue126
-rw-r--r--packages/frontend/src/ui/universal.vue6
-rw-r--r--packages/frontend/vite.config.ts12
-rw-r--r--packages/misskey-js/package.json2
-rw-r--r--pnpm-lock.yaml1872
-rw-r--r--pnpm-workspace.yaml37
-rw-r--r--scripts/changelog-checker/package-lock.json118
-rw-r--r--scripts/changelog-checker/package.json10
-rw-r--r--scripts/dependency-patches/re2.patch13
-rw-r--r--scripts/tarball.mjs2
75 files changed, 5839 insertions, 2652 deletions
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 8dd9d1c704..c506c36f6b 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -7,8 +7,8 @@
"ghcr.io/devcontainers/features/node:1": {
"version": "22.11.0"
},
- "ghcr.io/devcontainers-extra/features/corepack:1": {
- "version": "0.31.0"
+ "ghcr.io/devcontainers-extra/features/pnpm:2": {
+ "version": "10.6.1"
}
},
"forwardPorts": [3000],
diff --git a/.devcontainer/init.sh b/.devcontainer/init.sh
index e02a533c15..216292b082 100755
--- a/.devcontainer/init.sh
+++ b/.devcontainer/init.sh
@@ -7,8 +7,6 @@ sudo apt-get update
sudo apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb
git config --global --add safe.directory /workspace
git submodule update --init
-corepack install
-corepack enable
pnpm config set store-dir /home/node/.local/share/pnpm/store
pnpm install --frozen-lockfile
cp .devcontainer/devcontainer.yml .config/default.yml
diff --git a/.github/workflows/api-misskey-js.yml b/.github/workflows/api-misskey-js.yml
index fdd128be33..1c4bee2095 100644
--- a/.github/workflows/api-misskey-js.yml
+++ b/.github/workflows/api-misskey-js.yml
@@ -9,10 +9,6 @@ on:
paths:
- packages/misskey-js/**
- .github/workflows/api-misskey-js.yml
-
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
report:
@@ -22,7 +18,8 @@ jobs:
- name: Checkout
uses: actions/checkout@v4.2.2
- - run: corepack enable
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Setup Node.js
uses: actions/setup-node@v4.2.0
diff --git a/.github/workflows/get-api-diff.yml b/.github/workflows/get-api-diff.yml
index 2da9647460..3244a39156 100644
--- a/.github/workflows/get-api-diff.yml
+++ b/.github/workflows/get-api-diff.yml
@@ -9,10 +9,6 @@ on:
paths:
- packages/backend/**
- .github/workflows/get-api-diff.yml
-
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
get-from-misskey:
runs-on: ubuntu-latest
@@ -34,14 +30,13 @@ jobs:
with:
ref: ${{ matrix.ref }}
submodules: true
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.2.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index b1d52e8b3b..361bd697e5 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -28,10 +28,6 @@ on:
- packages/misskey-reversi/**
- packages/shared/eslint.config.js
- .github/workflows/lint.yml
-
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
pnpm_install:
runs-on: ubuntu-latest
@@ -40,12 +36,12 @@ jobs:
with:
fetch-depth: 0
submodules: true
- - uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- uses: actions/setup-node@v4.2.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
lint:
@@ -71,12 +67,12 @@ jobs:
with:
fetch-depth: 0
submodules: true
- - uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- uses: actions/setup-node@v4.2.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Restore eslint cache
uses: actions/cache@v4.2.2
@@ -101,12 +97,12 @@ jobs:
with:
fetch-depth: 0
submodules: true
- - uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- uses: actions/setup-node@v4.2.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- run: pnpm --filter misskey-js run build
if: ${{ matrix.workspace == 'backend' || matrix.workspace == 'sw' }}
diff --git a/.github/workflows/locale.yml b/.github/workflows/locale.yml
index 2daeaa3bd7..4c0de376d2 100644
--- a/.github/workflows/locale.yml
+++ b/.github/workflows/locale.yml
@@ -9,10 +9,6 @@ on:
paths:
- locales/**
- .github/workflows/locale.yml
-
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
locale_verify:
runs-on: ubuntu-latest
@@ -22,11 +18,11 @@ jobs:
with:
fetch-depth: 0
submodules: true
- - uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- uses: actions/setup-node@v4.2.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- run: cd locales && node verify.js
diff --git a/.github/workflows/on-release-created.yml b/.github/workflows/on-release-created.yml
index 8e4ad4368b..aa32f2cb3b 100644
--- a/.github/workflows/on-release-created.yml
+++ b/.github/workflows/on-release-created.yml
@@ -6,9 +6,6 @@ on:
workflow_dispatch:
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
publish-misskey-js:
name: Publish misskey-js
@@ -26,8 +23,8 @@ jobs:
- uses: actions/checkout@v4.2.2
with:
submodules: true
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.2.0
with:
@@ -36,7 +33,6 @@ jobs:
registry-url: 'https://registry.npmjs.org'
- name: Publish package
run: |
- corepack enable
pnpm i --frozen-lockfile
pnpm build
pnpm --filter misskey-js publish --access public --no-git-checks --provenance
diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml
index 9e5a79faac..9fdbeab913 100644
--- a/.github/workflows/storybook.yml
+++ b/.github/workflows/storybook.yml
@@ -13,9 +13,6 @@ on:
# This is a waste of chromatic build quota, so we don't run storybook CI on pull requests targets master.
- master
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
build:
# chromatic is not likely to be available for fork repositories, so we disable for fork repositories.
@@ -43,14 +40,13 @@ jobs:
run: |
echo "base=$(git rev-list --parents -n1 HEAD | cut -d" " -f2)" >> $GITHUB_OUTPUT
git checkout $(git rev-list --parents -n1 HEAD | cut -d" " -f3)
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Use Node.js 20.x
uses: actions/setup-node@v4.2.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml
index 2b8092cf45..69652621ca 100644
--- a/.github/workflows/test-backend.yml
+++ b/.github/workflows/test-backend.yml
@@ -18,10 +18,6 @@ on:
- packages/misskey-js/**
- .github/workflows/test-backend.yml
- .github/misskey/test.yml
-
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
unit:
name: Unit tests (backend)
@@ -48,8 +44,8 @@ jobs:
- uses: actions/checkout@v4.2.2
with:
submodules: true
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Install FFmpeg
run: |
for i in {1..3}; do
@@ -70,7 +66,6 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
@@ -111,14 +106,13 @@ jobs:
- uses: actions/checkout@v4.2.2
with:
submodules: true
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.2.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
diff --git a/.github/workflows/test-federation.yml b/.github/workflows/test-federation.yml
index 0b71325de3..93588b54b9 100644
--- a/.github/workflows/test-federation.yml
+++ b/.github/workflows/test-federation.yml
@@ -15,9 +15,6 @@ on:
- packages/misskey-js/**
- .github/workflows/test-federation.yml
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
test:
name: Federation test
@@ -29,8 +26,8 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: true
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Install FFmpeg
run: |
for i in {1..3}; do
@@ -53,7 +50,6 @@ jobs:
cache: 'pnpm'
- name: Build Misskey
run: |
- corepack enable && corepack prepare
pnpm i --frozen-lockfile
pnpm build
- name: Setup
diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml
index e489ebf07c..14a754c190 100644
--- a/.github/workflows/test-frontend.yml
+++ b/.github/workflows/test-frontend.yml
@@ -22,10 +22,6 @@ on:
- packages/backend/**
- .github/workflows/test-frontend.yml
- .github/misskey/test.yml
-
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
vitest:
name: Unit tests (frontend)
@@ -39,14 +35,13 @@ jobs:
- uses: actions/checkout@v4.2.2
with:
submodules: true
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.2.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
@@ -95,14 +90,13 @@ jobs:
# if: ${{ matrix.browser == 'firefox' }}
#- uses: browser-actions/setup-firefox@latest
# if: ${{ matrix.browser == 'firefox' }}
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.2.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Copy Configure
run: cp .github/misskey/test.yml .config
diff --git a/.github/workflows/test-misskey-js.yml b/.github/workflows/test-misskey-js.yml
index 05f757acc1..29b6c6172b 100644
--- a/.github/workflows/test-misskey-js.yml
+++ b/.github/workflows/test-misskey-js.yml
@@ -14,10 +14,6 @@ on:
paths:
- packages/misskey-js/**
- .github/workflows/test-misskey-js.yml
-
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
test:
name: Unit tests (misskey.js)
@@ -33,7 +29,8 @@ jobs:
- name: Checkout
uses: actions/checkout@v4.2.2
- - run: corepack enable
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.2.0
diff --git a/.github/workflows/test-production.yml b/.github/workflows/test-production.yml
index 56e42213ff..205eae2399 100644
--- a/.github/workflows/test-production.yml
+++ b/.github/workflows/test-production.yml
@@ -9,7 +9,6 @@ on:
env:
NODE_ENV: production
- COREPACK_DEFAULT_TO_LATEST: 0
jobs:
production:
@@ -24,14 +23,13 @@ jobs:
- uses: actions/checkout@v4.2.2
with:
submodules: true
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.2.0
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
diff --git a/.github/workflows/validate-api-json.yml b/.github/workflows/validate-api-json.yml
index a8b2402988..f84efa4821 100644
--- a/.github/workflows/validate-api-json.yml
+++ b/.github/workflows/validate-api-json.yml
@@ -12,10 +12,6 @@ on:
paths:
- packages/backend/**
- .github/workflows/validate-api-json.yml
-
-env:
- COREPACK_DEFAULT_TO_LATEST: 0
-
jobs:
validate-api-json:
runs-on: ubuntu-latest
@@ -28,8 +24,8 @@ jobs:
- uses: actions/checkout@v4.2.2
with:
submodules: true
- - name: Install pnpm
- uses: pnpm/action-setup@v4
+ - name: Setup pnpm
+ uses: pnpm/action-setup@v4.1.0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.2.0
with:
@@ -37,7 +33,6 @@ jobs:
cache: 'pnpm'
- name: Install Redocly CLI
run: npm i -g @redocly/cli
- - run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
diff --git a/.npmrc b/.npmrc
index c42da845b4..daebfd5218 100644
--- a/.npmrc
+++ b/.npmrc
@@ -1 +1,3 @@
engine-strict = true
+save-exact = true
+shell-emulator = true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 197de5aec7..e5df6de4e6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,18 @@
+## 2025.3.1
+
+### General
+- pnpmをv10に更新
+- Corepackを削除
+
+### Client
+- Feat: 設定の検索を追加(実験的)
+- Enhance: 設定項目の再配置
+
+### Server
+- Fix: DBマイグレーション際にシステムアカウントのユーザーID判定が正しくない問題を修正
+- Fix: user.featured列が状況によってJSON文字列になっていたのを修正
+
+
## 2025.3.0
### General
diff --git a/Dockerfile b/Dockerfile
index 3bc2044396..9d5596f1f1 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,8 +6,6 @@ ARG NODE_VERSION=22.11.0-bookworm
FROM --platform=$BUILDPLATFORM node:${NODE_VERSION} AS native-builder
-ENV COREPACK_DEFAULT_TO_LATEST=0
-
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
rm -f /etc/apt/apt.conf.d/docker-clean \
@@ -16,8 +14,6 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
&& apt-get install -yqq --no-install-recommends \
build-essential
-RUN corepack enable
-
WORKDIR /misskey
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
@@ -33,6 +29,8 @@ COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bu
ARG NODE_ENV=production
+RUN node -e "console.log(JSON.parse(require('node:fs').readFileSync('./package.json')).packageManager)" | xargs npm install -g
+
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
pnpm i --frozen-lockfile --aggregate-output
@@ -46,14 +44,10 @@ RUN rm -rf .git/
FROM --platform=$TARGETPLATFORM node:${NODE_VERSION} AS target-builder
-ENV COREPACK_DEFAULT_TO_LATEST=0
-
RUN apt-get update \
&& apt-get install -yqq --no-install-recommends \
build-essential
-RUN corepack enable
-
WORKDIR /misskey
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
@@ -65,6 +59,8 @@ COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bu
ARG NODE_ENV=production
+RUN node -e "console.log(JSON.parse(require('node:fs').readFileSync('./package.json')).packageManager)" | xargs npm install -g
+
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
pnpm i --frozen-lockfile --aggregate-output
@@ -72,13 +68,11 @@ FROM --platform=$TARGETPLATFORM node:${NODE_VERSION}-slim AS runner
ARG UID="991"
ARG GID="991"
-ENV COREPACK_DEFAULT_TO_LATEST=0
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ffmpeg tini curl libjemalloc-dev libjemalloc2 \
&& ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so \
- && corepack enable \
&& groupadd -g "${GID}" misskey \
&& useradd -l -u "${UID}" -g "${GID}" -m -d /misskey misskey \
&& find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /u+s -ignore_readdir_race -exec chmod u-s {} \; \
@@ -86,13 +80,13 @@ RUN apt-get update \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists
+# add package.json to add pnpm
+COPY ./package.json ./package.json
+RUN node -e "console.log(JSON.parse(require('node:fs').readFileSync('./package.json')).packageManager)" | xargs npm install -g
+
USER misskey
WORKDIR /misskey
-# add package.json to add pnpm
-COPY --chown=misskey:misskey ./package.json ./package.json
-RUN corepack install
-
COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules
diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml
index 8b52450e95..377d16b147 100644
--- a/locales/ca-ES.yml
+++ b/locales/ca-ES.yml
@@ -111,7 +111,7 @@ followRequests: "Peticions de seguiment"
unfollow: "Deixar de seguir"
followRequestPending: "Sol·licituds de seguiment pendents"
enterEmoji: "Introduir un emoji"
-renote: "Impulsos"
+renote: "Impulsar"
unrenote: "Anul·la l'impuls"
renoted: "S'ha impulsat"
renotedToX: "Impulsat per {name}."
@@ -1114,7 +1114,7 @@ forceShowAds: "Mostra els anuncis sempre "
addMemo: "Afegir recordatori"
editMemo: "Editar recordatori"
reactionsList: "Reaccions"
-renotesList: "Impulsos"
+renotesList: "Llistat d'impulsos "
notificationDisplay: "Notificacions"
leftTop: "Dalt a l'esquerra "
rightTop: "Dalt a la dreta "
@@ -1190,7 +1190,7 @@ pastAnnouncements: "Informes passats"
youHaveUnreadAnnouncements: "Tens informes per llegir."
useSecurityKey: "Segueix les instruccions del teu navegador O dispositiu per fer servir el teu passkey."
replies: "Respostes"
-renotes: "Impulsos"
+renotes: "Impulsar"
loadReplies: "Mostrar les respostes"
loadConversation: "Mostrar la conversació "
pinnedList: "Llista fixada"
@@ -2452,7 +2452,7 @@ _notification:
follow: "Segueix-me"
mention: "Menció"
reply: "Respostes"
- renote: "Renotar"
+ renote: "Impulsar"
quote: "Citar"
reaction: "Reaccions"
pollEnded: "Enquesta terminada"
@@ -2467,7 +2467,7 @@ _notification:
_actions:
followBack: "També et segueix"
reply: "Respondre"
- renote: "Renotar"
+ renote: "Impulsos"
_deck:
alwaysShowMainColumn: "Mostrar sempre la columna principal"
columnAlign: "Alinea les columnes"
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 04ddd2966a..f4c3323691 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -1311,6 +1311,8 @@ federationSpecified: "This server is operated in a whitelist federation. Interac
federationDisabled: "Federation is disabled on this server. You cannot interact with users on other servers."
confirmOnReact: "Confirm when reacting"
reactAreYouSure: "Would you like to add a \"{emoji}\" reaction?"
+markAsSensitiveConfirm: "Do you want to set this media as sensitive?"
+unmarkAsSensitiveConfirm: "Do you want to remove the sensitive designation for this media?"
_accountSettings:
requireSigninToViewContents: "Require sign-in to view contents"
requireSigninToViewContentsDescription1: "Require login to view all notes and other content you have created. This will have the effect of preventing crawlers from collecting your information."
@@ -2594,6 +2596,7 @@ _moderationLogTypes:
deletePage: "Page deleted"
deleteFlash: "Play deleted"
deleteGalleryPost: "Gallery post deleted"
+ updateProxyAccountDescription: "Update the description of the proxy account"
_fileViewer:
title: "File details"
type: "File type"
@@ -2649,7 +2652,7 @@ _dataSaver:
description: "Prevents images/videos from being loaded automatically. Hidden images/videos will be loaded when tapped."
_avatar:
title: "Avatar image"
- description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic."
+ description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic."
_urlPreview:
title: "URL preview thumbnails"
description: "URL preview thumbnail images will no longer be loaded."
@@ -2857,4 +2860,8 @@ _bootErrors:
_search:
searchScopeAll: "All"
searchScopeLocal: "Local"
+ searchScopeServer: "Specific server"
searchScopeUser: "Specific user"
+ pleaseEnterServerHost: "Enter the server host"
+ pleaseSelectUser: "Select user"
+ serverHostPlaceholder: "Example: misskey.example.com"
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 947b577792..6810d204cb 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -4971,7 +4971,7 @@ export interface Locale extends ILocale {
*/
"disableStreamingTimeline": string;
/**
- * 通知をグルーピングして表示する
+ * 通知をグルーピング
*/
"useGroupedNotifications": string;
/**
@@ -5270,6 +5270,14 @@ export interface Locale extends ILocale {
* このメディアのセンシティブ指定を解除しますか?
*/
"unmarkAsSensitiveConfirm": string;
+ /**
+ * 環境設定
+ */
+ "preferences": string;
+ /**
+ * アクセシビリティ
+ */
+ "accessibility": string;
"_accountSettings": {
/**
* コンテンツの表示にログインを必須にする
diff --git a/locales/it-IT.yml b/locales/it-IT.yml
index c3a33139be..5248927035 100644
--- a/locales/it-IT.yml
+++ b/locales/it-IT.yml
@@ -1313,6 +1313,8 @@ confirmOnReact: "Confermare le reazioni"
reactAreYouSure: "Vuoi davvero reagire con {emoji} ?"
markAsSensitiveConfirm: "Vuoi davvero indicare questo contenuto multimediale come esplicito?"
unmarkAsSensitiveConfirm: "Vuoi davvero indicare come non esplicito il contenuto multimediale?"
+preferences: "Preferenze"
+accessibility: "Accessibilità"
_accountSettings:
requireSigninToViewContents: "Per vedere il contenuto, è necessaria l'iscrizione"
requireSigninToViewContentsDescription1: "Richiedere l'iscrizione per visualizzare tutte le Note e gli altri contenuti che hai creato. Probabilmente l'effetto è impedire la raccolta di informazioni da parte dei bot crawler."
@@ -1475,7 +1477,7 @@ _serverSettings:
_accountMigration:
moveFrom: "Migra un altro profilo dentro a questo"
moveFromSub: "Crea un alias verso un altro profilo remoto"
- moveFromLabel: "Profilo da cui migrare #{n}"
+ moveFromLabel: "Profilo da cui migrare n. {n}"
moveFromDescription: "Se desideri spostare i Follower da un altro profilo a questo, devi prima creare un alias qui. Assicurati averlo creato PRIMA di eseguire l'attività! Inserisci l'indirizzo del profilo mittente in questo modo: @persona@vecchia.istanza.it"
moveTo: "Migrare questo profilo verso un un altro"
moveToLabel: "Profilo verso cui migrare"
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index fbe4d98896..7a5d2f795e 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1238,7 +1238,7 @@ releaseToRefresh: "離してリロード"
refreshing: "リロード中"
pullDownToRefresh: "引っ張ってリロード"
disableStreamingTimeline: "タイムラインのリアルタイム更新を無効にする"
-useGroupedNotifications: "通知をグルーピングして表示する"
+useGroupedNotifications: "通知をグルーピング"
signupPendingError: "メールアドレスの確認中に問題が発生しました。リンクの有効期限が切れている可能性があります。"
cwNotationRequired: "「内容を隠す」がオンの場合は注釈の記述が必要です。"
doReaction: "リアクションする"
@@ -1313,6 +1313,8 @@ confirmOnReact: "リアクションする際に確認する"
reactAreYouSure: "\" {emoji} \" をリアクションしますか?"
markAsSensitiveConfirm: "このメディアをセンシティブとして設定しますか?"
unmarkAsSensitiveConfirm: "このメディアのセンシティブ指定を解除しますか?"
+preferences: "環境設定"
+accessibility: "アクセシビリティ"
_accountSettings:
requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index f0df9deee0..f5a9786063 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -1313,6 +1313,8 @@ confirmOnReact: "发送回应前需要确认"
reactAreYouSure: "要用「{emoji}」进行回应吗?"
markAsSensitiveConfirm: "要将此媒体标记为敏感吗?"
unmarkAsSensitiveConfirm: "要将此媒体解除敏感标记吗?"
+preferences: "设置"
+accessibility: "辅助功能"
_accountSettings:
requireSigninToViewContents: "需要登录才能显示内容"
requireSigninToViewContentsDescription1: "您发布的所有帖子将变成需要登入后才会显示。有望防止爬虫收集各种信息。"
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index 7c7e290545..ea4ef49e7f 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -1313,6 +1313,8 @@ confirmOnReact: "反應時確認"
reactAreYouSure: "用「 {emoji} 」反應嗎?"
markAsSensitiveConfirm: "要將這個媒體設定為敏感嗎?"
unmarkAsSensitiveConfirm: "要解除這個媒體的敏感設定嗎?"
+preferences: "環境設定"
+accessibility: "輔助工具"
_accountSettings:
requireSigninToViewContents: "須登入以顯示內容"
requireSigninToViewContentsDescription1: "必須登入才會顯示您建立的貼文等內容。可望有效防止資訊被爬蟲蒐集。"
diff --git a/package.json b/package.json
index a3a5924aff..267dd8adaa 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,12 @@
{
"name": "misskey",
- "version": "2025.3.0",
+ "version": "2025.3.1",
"codename": "nasubi",
"repository": {
"type": "git",
"url": "https://github.com/misskey-dev/misskey.git"
},
- "packageManager": "pnpm@9.15.4",
+ "packageManager": "pnpm@10.6.1",
"workspaces": [
"packages/frontend-shared",
"packages/frontend",
@@ -47,35 +47,44 @@
"cleanall": "pnpm clean-all"
},
"resolutions": {
- "chokidar": "3.6.0",
+ "chokidar": "4.0.3",
"lodash": "4.17.21"
},
"dependencies": {
"cssnano": "7.0.6",
- "execa": "8.0.1",
+ "execa": "9.5.2",
"fast-glob": "3.3.3",
- "ignore-walk": "6.0.5",
+ "ignore-walk": "7.0.0",
"js-yaml": "4.1.0",
- "postcss": "8.5.2",
- "tar": "6.2.1",
+ "postcss": "8.5.3",
+ "tar": "7.4.3",
"terser": "5.39.0",
- "typescript": "5.7.3",
+ "typescript": "5.8.2",
"esbuild": "0.25.0",
"glob": "11.0.1"
},
"devDependencies": {
"@misskey-dev/eslint-plugin": "2.1.0",
- "@types/node": "22.13.4",
- "@typescript-eslint/eslint-plugin": "8.24.0",
- "@typescript-eslint/parser": "8.24.0",
+ "@types/node": "22.13.9",
+ "@typescript-eslint/eslint-plugin": "8.26.0",
+ "@typescript-eslint/parser": "8.26.0",
"cross-env": "7.0.3",
- "cypress": "14.0.3",
- "eslint": "9.20.1",
- "globals": "15.15.0",
+ "cypress": "14.1.0",
+ "eslint": "9.21.0",
+ "globals": "16.0.0",
"ncp": "2.0.0",
+ "pnpm": "10.6.1",
"start-server-and-test": "2.0.10"
},
"optionalDependencies": {
"@tensorflow/tfjs-core": "4.22.0"
+ },
+ "pnpm": {
+ "overrides": {
+ "@aiscript-dev/aiscript-languageserver": "-"
+ },
+ "patchedDependencies": {
+ "re2": "scripts/dependency-patches/re2.patch"
+ }
}
}
diff --git a/packages/backend/migration/1741279404074-system-accounts-fixup.js b/packages/backend/migration/1741279404074-system-accounts-fixup.js
new file mode 100644
index 0000000000..31cab7f5ae
--- /dev/null
+++ b/packages/backend/migration/1741279404074-system-accounts-fixup.js
@@ -0,0 +1,26 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class SystemAccounts1741279404074 {
+ name = 'SystemAccounts1741279404074'
+
+ async up(queryRunner) {
+ const instanceActor = await queryRunner.query(`SELECT "id" FROM "user" WHERE "username" = 'instance.actor' AND "host" IS NULL AND "id" NOT IN (SELECT "userId" FROM "system_account" WHERE "type" = 'actor')`);
+ if (instanceActor.length > 0) {
+ console.warn('instance.actor was incorrect, updating...');
+ await queryRunner.query(`UPDATE "system_account" SET "id" = '${instanceActor[0].id}', "userId" = '${instanceActor[0].id}' WHERE "type" = 'actor'`);
+ }
+
+ const relayActor = await queryRunner.query(`SELECT "id" FROM "user" WHERE "username" = 'relay.actor' AND "host" IS NULL AND "id" NOT IN (SELECT "userId" FROM "system_account" WHERE "type" = 'relay')`);
+ if (relayActor.length > 0) {
+ console.warn('relay.actor was incorrect, updating...');
+ await queryRunner.query(`UPDATE "system_account" SET "id" = '${relayActor[0].id}', "userId" = '${relayActor[0].id}' WHERE "type" = 'relay'`);
+ }
+ }
+
+ async down(queryRunner) {
+ // fixup migration, no down migration
+ }
+}
diff --git a/packages/backend/migration/1741424411879-user-featured-fixup.js b/packages/backend/migration/1741424411879-user-featured-fixup.js
new file mode 100644
index 0000000000..5643a328f0
--- /dev/null
+++ b/packages/backend/migration/1741424411879-user-featured-fixup.js
@@ -0,0 +1,26 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class UserFeaturedFixup1741424411879 {
+ name = 'UserFeaturedFixup1741424411879'
+
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE OR REPLACE FUNCTION pg_temp.extract_ap_id(text) RETURNS text AS $$
+ SELECT
+ CASE
+ WHEN $1 ~ '^https?://' THEN $1
+ WHEN $1 LIKE '{%' THEN COALESCE(jsonb_extract_path_text($1::jsonb, 'id'), null)
+ ELSE null
+ END;
+ $$ LANGUAGE sql IMMUTABLE;`);
+
+ // "host" is NOT NULL is not needed but just in case add it to prevent overwriting irreplaceable data
+ await queryRunner.query(`UPDATE "user" SET "featured" = pg_temp.extract_ap_id("featured") WHERE "host" IS NOT NULL`);
+ }
+
+ async down(queryRunner) {
+ // fixup migration, no down migration
+ }
+}
diff --git a/packages/backend/src/core/FileInfoService.ts b/packages/backend/src/core/FileInfoService.ts
index fc68eb4836..a295e81920 100644
--- a/packages/backend/src/core/FileInfoService.ts
+++ b/packages/backend/src/core/FileInfoService.ts
@@ -268,7 +268,6 @@ export class FileInfoService {
private async *asyncIterateFrames(cwd: string, command: FFmpeg.FfmpegCommand): AsyncGenerator<string, void> {
const watcher = new FSWatcher({
cwd,
- disableGlobbing: true,
});
let finished = false;
command.once('end', () => {
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index 879f1922ca..e52078ed0f 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -560,7 +560,7 @@ export class ApPersonService implements OnModuleInit {
inbox: person.inbox,
sharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox ?? null,
followersUri: person.followers ? getApId(person.followers) : undefined,
- featured: person.featured,
+ featured: person.featured ? getApId(person.featured) : undefined,
emojis: emojiNames,
name: truncate(person.name, nameLength),
tags,
diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts
index 8c4b13a40a..20e985aaf2 100644
--- a/packages/backend/src/server/ActivityPubServerService.ts
+++ b/packages/backend/src/server/ActivityPubServerService.ts
@@ -751,7 +751,7 @@ export class ActivityPubServerService {
});
// follow
- fastify.get<{ Params: { followRequestId: string ; } }>('/follows/:followRequestId', async (request, reply) => {
+ fastify.get<{ Params: { followRequestId: string; } }>('/follows/:followRequestId', async (request, reply) => {
// This may be used before the follow is completed, so we do not
// check if the following exists and only check if the follow request exists.
diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts
index bf0a011699..772c37094c 100644
--- a/packages/backend/src/server/FileServerService.ts
+++ b/packages/backend/src/server/FileServerService.ts
@@ -497,7 +497,7 @@ export class FileServerService {
@bindThis
private async downloadAndDetectTypeFromUrl(url: string): Promise<
- { state: 'remote' ; mime: string; ext: string | null; path: string; cleanup: () => void; filename: string; }
+ { state: 'remote'; mime: string; ext: string | null; path: string; cleanup: () => void; filename: string; }
> {
const [path, cleanup] = await createTemp();
try {
diff --git a/packages/backend/test-federation/compose.tpl.yml b/packages/backend/test-federation/compose.tpl.yml
index 8b270e58f7..25770063d3 100644
--- a/packages/backend/test-federation/compose.tpl.yml
+++ b/packages/backend/test-federation/compose.tpl.yml
@@ -17,7 +17,6 @@ services:
- ./.config/docker.env
environment:
- NODE_ENV=production
- - COREPACK_DEFAULT_TO_LATEST=0
volumes:
- type: bind
source: ../../../built
@@ -76,13 +75,17 @@ services:
target: /misskey/pnpm-workspace.yaml
read_only: true
- type: bind
+ source: ../../../scripts/dependency-patches
+ target: /misskey/scripts/dependency-patches
+ read_only: true
+ - type: bind
source: ./certificates/rootCA.crt
target: /usr/local/share/ca-certificates/rootCA.crt
read_only: true
working_dir: /misskey
command: >
bash -c "
- corepack enable && corepack prepare
+ npm install -g pnpm
pnpm -F backend migrate
pnpm -F backend start
"
diff --git a/packages/backend/test-federation/compose.yml b/packages/backend/test-federation/compose.yml
index ed39109aab..dfa51b940a 100644
--- a/packages/backend/test-federation/compose.yml
+++ b/packages/backend/test-federation/compose.yml
@@ -9,7 +9,7 @@ services:
service: misskey
command: >
bash -c "
- corepack enable && corepack prepare
+ npm install -g pnpm
pnpm -F backend i
pnpm -F misskey-js i
pnpm -F misskey-reversi i
@@ -29,7 +29,6 @@ services:
environment:
- NODE_ENV=development
- NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/rootCA.crt
- - COREPACK_DEFAULT_TO_LATEST=0
volumes:
- type: bind
source: ../package.json
@@ -72,13 +71,17 @@ services:
target: /misskey/pnpm-workspace.yaml
read_only: true
- type: bind
+ source: ../../../scripts/dependency-patches
+ target: /misskey/scripts/dependency-patches
+ read_only: true
+ - type: bind
source: ./certificates/rootCA.crt
target: /usr/local/share/ca-certificates/rootCA.crt
read_only: true
working_dir: /misskey
entrypoint: >
bash -c '
- corepack enable && corepack prepare
+ npm install -g pnpm
pnpm -F misskey-js i --frozen-lockfile
pnpm -F backend i --frozen-lockfile
exec "$0" "$@"
@@ -90,8 +93,6 @@ services:
depends_on:
redis.test:
condition: service_healthy
- environment:
- - COREPACK_DEFAULT_TO_LATEST=0
volumes:
- type: bind
source: ../package.json
@@ -117,10 +118,14 @@ services:
source: ../../../pnpm-workspace.yaml
target: /misskey/pnpm-workspace.yaml
read_only: true
+ - type: bind
+ source: ../../../scripts/dependency-patches
+ target: /misskey/scripts/dependency-patches
+ read_only: true
working_dir: /misskey
command: >
bash -c "
- corepack enable && corepack prepare
+ npm install -g pnpm
pnpm -F backend i --frozen-lockfile
pnpm exec tsc -p ./packages/backend/test-federation
node ./packages/backend/test-federation/built/daemon.js
diff --git a/packages/frontend-embed/package.json b/packages/frontend-embed/package.json
index 1ee4fc2c28..21247e32ab 100644
--- a/packages/frontend-embed/package.json
+++ b/packages/frontend-embed/package.json
@@ -34,7 +34,7 @@
"typescript": "5.8.2",
"uuid": "11.1.0",
"json5": "2.2.3",
- "vite": "6.2.0",
+ "vite": "6.2.1",
"vue": "3.5.13"
},
"devDependencies": {
@@ -48,14 +48,14 @@
"@types/ws": "8.18.0",
"@typescript-eslint/eslint-plugin": "8.26.0",
"@typescript-eslint/parser": "8.26.0",
- "@vitest/coverage-v8": "3.0.7",
+ "@vitest/coverage-v8": "3.0.8",
"@vue/runtime-core": "3.5.13",
- "acorn": "8.14.0",
+ "acorn": "8.14.1",
"cross-env": "7.0.3",
"eslint-plugin-import": "2.31.0",
- "eslint-plugin-vue": "9.33.0",
+ "eslint-plugin-vue": "10.0.0",
"fast-glob": "3.3.3",
- "happy-dom": "17.2.2",
+ "happy-dom": "17.3.0",
"intersection-observer": "0.12.2",
"micromatch": "4.0.8",
"msw": "2.7.3",
@@ -64,7 +64,7 @@
"start-server-and-test": "2.0.10",
"vite-plugin-turbosnap": "1.0.3",
"vue-component-type-helpers": "2.2.8",
- "vue-eslint-parser": "9.4.3",
+ "vue-eslint-parser": "10.1.1",
"vue-tsc": "2.2.8"
}
}
diff --git a/packages/frontend-shared/package.json b/packages/frontend-shared/package.json
index ad9a0bafb6..7a05771ea8 100644
--- a/packages/frontend-shared/package.json
+++ b/packages/frontend-shared/package.json
@@ -25,10 +25,10 @@
"@typescript-eslint/eslint-plugin": "8.26.0",
"@typescript-eslint/parser": "8.26.0",
"esbuild": "0.25.0",
- "eslint-plugin-vue": "9.33.0",
+ "eslint-plugin-vue": "10.0.0",
"nodemon": "3.1.9",
"typescript": "5.8.2",
- "vue-eslint-parser": "9.4.3"
+ "vue-eslint-parser": "10.1.1"
},
"files": [
"js-built"
diff --git a/packages/frontend/.storybook/main.ts b/packages/frontend/.storybook/main.ts
index 9f318cf449..c1119c2523 100644
--- a/packages/frontend/.storybook/main.ts
+++ b/packages/frontend/.storybook/main.ts
@@ -39,6 +39,10 @@ const config = {
if (~replacePluginForIsChromatic) {
config.plugins?.splice(replacePluginForIsChromatic, 1);
}
+
+ //pluginsからcreateSearchIndexを削除、複数あるかもしれないので全て削除
+ config.plugins = config.plugins?.filter((plugin: Plugin) => plugin && plugin.name !== 'createSearchIndex') ?? [];
+
return mergeConfig(config, {
plugins: [
{
diff --git a/packages/frontend/lib/vite-plugin-create-search-index.ts b/packages/frontend/lib/vite-plugin-create-search-index.ts
new file mode 100644
index 0000000000..509eb804cb
--- /dev/null
+++ b/packages/frontend/lib/vite-plugin-create-search-index.ts
@@ -0,0 +1,1496 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { parse as vueSfcParse } from 'vue/compiler-sfc';
+import type { LogOptions, Plugin } from 'vite';
+import fs from 'node:fs';
+import { glob } from 'glob';
+import JSON5 from 'json5';
+import MagicString from 'magic-string';
+import path from 'node:path'
+import { hash, toBase62 } from '../vite.config';
+import { createLogger } from 'vite';
+
+interface VueAstNode {
+ type: number;
+ tag?: string;
+ loc?: {
+ start: { offset: number, line: number, column: number },
+ end: { offset: number, line: number, column: number },
+ source?: string
+ };
+ props?: Array<{
+ name: string;
+ type: number;
+ value?: { content?: string };
+ arg?: { content?: string };
+ exp?: { content?: string; loc?: any };
+ }>;
+ children?: VueAstNode[];
+ content?: any;
+ __markerId?: string;
+ __children?: string[];
+}
+
+export type AnalysisResult = {
+ filePath: string;
+ usage: SearchIndexItem[];
+}
+
+export type SearchIndexItem = {
+ id: string;
+ path?: string;
+ label: string;
+ keywords: string | string[];
+ icon?: string;
+ inlining?: string[];
+ children?: SearchIndexItem[];
+};
+
+export type Options = {
+ targetFilePaths: string[],
+ exportFilePath: string,
+ verbose?: boolean,
+};
+
+// 関連するノードタイプの定数化
+const NODE_TYPES = {
+ ELEMENT: 1,
+ EXPRESSION: 2,
+ TEXT: 3,
+ INTERPOLATION: 5, // Mustache
+};
+
+// マーカー関係を表す型
+interface MarkerRelation {
+ parentId?: string;
+ markerId: string;
+ node: VueAstNode;
+}
+
+// ロガー
+let logger = {
+ info: (msg: string, options?: LogOptions) => { },
+ warn: (msg: string, options?: LogOptions) => { },
+ error: (msg: string, options?: LogOptions) => { },
+};
+let loggerInitialized = false;
+
+function initLogger(options: Options) {
+ if (loggerInitialized) return;
+ loggerInitialized = true;
+ const viteLogger = createLogger(options.verbose ? 'info' : 'warn');
+
+ logger.info = (msg, options) => {
+ msg = `[create-search-index] ${msg}`;
+ viteLogger.info(msg, options);
+ }
+
+ logger.warn = (msg, options) => {
+ msg = `[create-search-index] ${msg}`;
+ viteLogger.warn(msg, options);
+ }
+
+ logger.error = (msg, options) => {
+ msg = `[create-search-index] ${msg}`;
+ viteLogger.error(msg, options);
+ }
+}
+
+/**
+ * 解析結果をTypeScriptファイルとして出力する
+ */
+function outputAnalysisResultAsTS(outputPath: string, analysisResults: AnalysisResult[]): void {
+ logger.info(`Processing ${analysisResults.length} files for output`);
+
+ // 新しいツリー構造を構築
+ const allMarkers = new Map<string, SearchIndexItem>();
+
+ // 1. すべてのマーカーを一旦フラットに収集
+ for (const file of analysisResults) {
+ logger.info(`Processing file: ${file.filePath} with ${file.usage.length} markers`);
+
+ for (const marker of file.usage) {
+ if (marker.id) {
+ // キーワードとchildren処理を共通化
+ const processedMarker = {
+ ...marker,
+ keywords: processMarkerProperty(marker.keywords, 'keywords'),
+ children: processMarkerProperty(marker.children || [], 'children')
+ };
+
+ allMarkers.set(marker.id, processedMarker);
+ }
+ }
+ }
+
+ logger.info(`Collected total ${allMarkers.size} unique markers`);
+
+ // 2. 子マーカーIDの収集
+ const childIds = collectChildIds(allMarkers);
+ logger.info(`Found ${childIds.size} child markers`);
+
+ // 3. ルートマーカーの特定(他の誰かの子でないマーカー)
+ const rootMarkers = identifyRootMarkers(allMarkers, childIds);
+ logger.info(`Found ${rootMarkers.length} root markers`);
+
+ // 4. 子マーカーの参照を解決
+ const resolvedRootMarkers = resolveChildReferences(rootMarkers, allMarkers);
+
+ // 5. デバッグ情報を生成
+ const { totalMarkers, totalChildren } = countMarkers(resolvedRootMarkers);
+ logger.info(`Total markers in tree: ${totalMarkers} (${resolvedRootMarkers.length} roots + ${totalChildren} nested children)`);
+
+ // 6. 結果をTS形式で出力
+ writeOutputFile(outputPath, resolvedRootMarkers);
+}
+
+/**
+ * マーカーのプロパティ(keywordsやchildren)を処理する
+ */
+function processMarkerProperty(propValue: any, propType: 'keywords' | 'children'): any {
+ // 文字列の配列表現を解析
+ if (typeof propValue === 'string' && propValue.startsWith('[') && propValue.endsWith(']')) {
+ try {
+ // JSON5解析を試みる
+ return JSON5.parse(propValue.replace(/'/g, '"'));
+ } catch (e) {
+ // 解析に失敗した場合
+ logger.warn(`Could not parse ${propType}: ${propValue}, using ${propType === 'children' ? 'empty array' : 'as is'}`);
+ return propType === 'children' ? [] : propValue;
+ }
+ }
+
+ return propValue;
+}
+
+/**
+ * 全マーカーから子IDを収集する
+ */
+function collectChildIds(allMarkers: Map<string, SearchIndexItem>): Set<string> {
+ const childIds = new Set<string>();
+
+ allMarkers.forEach((marker, id) => {
+ // 通常のchildren処理
+ const children = marker.children;
+ if (Array.isArray(children)) {
+ children.forEach(childId => {
+ if (typeof childId === 'string') {
+ if (!allMarkers.has(childId)) {
+ logger.warn(`Warning: Child marker ID ${childId} referenced but not found`);
+ } else {
+ childIds.add(childId);
+ }
+ }
+ });
+ }
+
+ // inlining処理を追加
+ if (marker.inlining) {
+ let inliningIds: string[] = [];
+
+ // 文字列の場合は配列に変換
+ if (typeof marker.inlining === 'string') {
+ try {
+ const inliningStr = (marker.inlining as string).trim();
+ if (inliningStr.startsWith('[') && inliningStr.endsWith(']')) {
+ inliningIds = JSON5.parse(inliningStr.replace(/'/g, '"'));
+ logger.info(`Parsed inlining string to array: ${inliningStr} -> ${JSON.stringify(inliningIds)}`);
+ } else {
+ inliningIds = [inliningStr];
+ }
+ } catch (e) {
+ logger.error(`Failed to parse inlining string: ${marker.inlining}`, e);
+ }
+ }
+ // 既に配列の場合
+ else if (Array.isArray(marker.inlining)) {
+ inliningIds = marker.inlining;
+ }
+
+ // inliningで指定されたIDを子セットに追加
+ for (const inlineId of inliningIds) {
+ if (typeof inlineId === 'string') {
+ if (!allMarkers.has(inlineId)) {
+ logger.warn(`Warning: Inlining marker ID ${inlineId} referenced but not found`);
+ } else {
+ // inliningで参照されているマーカーも子として扱う
+ childIds.add(inlineId);
+ logger.info(`Added inlined marker ${inlineId} as child in collectChildIds`);
+ }
+ }
+ }
+ }
+ });
+
+ return childIds;
+}
+
+/**
+ * ルートマーカー(他の子でないマーカー)を特定する
+ */
+function identifyRootMarkers(
+ allMarkers: Map<string, SearchIndexItem>,
+ childIds: Set<string>
+): SearchIndexItem[] {
+ const rootMarkers: SearchIndexItem[] = [];
+
+ allMarkers.forEach((marker, id) => {
+ if (!childIds.has(id)) {
+ rootMarkers.push(marker);
+ logger.info(`Added root marker to output: ${id} with label ${marker.label}`);
+ }
+ });
+
+ return rootMarkers;
+}
+
+/**
+ * 子マーカーの参照をIDから実際のオブジェクトに解決する
+ */
+function resolveChildReferences(
+ rootMarkers: SearchIndexItem[],
+ allMarkers: Map<string, SearchIndexItem>
+): SearchIndexItem[] {
+ function resolveChildrenForMarker(marker: SearchIndexItem): SearchIndexItem {
+ // マーカーのディープコピーを作成
+ const resolvedMarker = { ...marker };
+ // 明示的に子マーカー配列を作成
+ const resolvedChildren: SearchIndexItem[] = [];
+
+ // 通常のchildren処理
+ if (Array.isArray(marker.children)) {
+ for (const childId of marker.children) {
+ if (typeof childId === 'string') {
+ const childMarker = allMarkers.get(childId);
+ if (childMarker) {
+ // 子マーカーの子も再帰的に解決
+ const resolvedChild = resolveChildrenForMarker(childMarker);
+ resolvedChildren.push(resolvedChild);
+ logger.info(`Resolved regular child ${childId} for parent ${marker.id}`);
+ }
+ }
+ }
+ }
+
+ // inlining属性の処理
+ let inliningIds: string[] = [];
+
+ // 文字列の場合は配列に変換。例: "['2fa']" -> ['2fa']
+ if (typeof marker.inlining === 'string') {
+ try {
+ // 文字列形式の配列を実際の配列に変換
+ const inliningStr = (marker.inlining as string).trim();
+ if (inliningStr.startsWith('[') && inliningStr.endsWith(']')) {
+ inliningIds = JSON5.parse(inliningStr.replace(/'/g, '"'));
+ logger.info(`Converted string inlining to array: ${inliningStr} -> ${JSON.stringify(inliningIds)}`);
+ } else {
+ // 単一値の場合は配列に
+ inliningIds = [inliningStr];
+ logger.info(`Converted single string inlining to array: ${inliningStr}`);
+ }
+ } catch (e) {
+ logger.error(`Failed to parse inlining string: ${marker.inlining}`, e);
+ }
+ }
+ // 既に配列の場合はそのまま使用
+ else if (Array.isArray(marker.inlining)) {
+ inliningIds = marker.inlining;
+ }
+
+ // インライン指定されたマーカーを子として追加
+ for (const inlineId of inliningIds) {
+ if (typeof inlineId === 'string') {
+ const inlineMarker = allMarkers.get(inlineId);
+ if (inlineMarker) {
+ // インライン指定されたマーカーを再帰的に解決
+ const resolvedInline = resolveChildrenForMarker(inlineMarker);
+ delete resolvedInline.path
+ resolvedChildren.push(resolvedInline);
+ logger.info(`Added inlined marker ${inlineId} as child to ${marker.id}`);
+ } else {
+ logger.warn(`Inlining target not found: ${inlineId} referenced by ${marker.id}`);
+ }
+ }
+ }
+
+ // 解決した子が存在する場合のみchildrenプロパティを設定
+ if (resolvedChildren.length > 0) {
+ resolvedMarker.children = resolvedChildren;
+ } else {
+ delete resolvedMarker.children;
+ }
+
+ return resolvedMarker;
+ }
+
+ // すべてのルートマーカーの子を解決
+ return rootMarkers.map(marker => resolveChildrenForMarker(marker));
+}
+
+/**
+ * マーカー数を数える(デバッグ用)
+ */
+function countMarkers(markers: SearchIndexItem[]): { totalMarkers: number, totalChildren: number } {
+ let totalMarkers = markers.length;
+ let totalChildren = 0;
+
+ function countNested(items: SearchIndexItem[]): void {
+ for (const marker of items) {
+ if (marker.children && Array.isArray(marker.children)) {
+ totalChildren += marker.children.length;
+ totalMarkers += marker.children.length;
+ countNested(marker.children as SearchIndexItem[]);
+ }
+ }
+ }
+
+ countNested(markers);
+ return { totalMarkers, totalChildren };
+}
+
+/**
+ * 最終的なTypeScriptファイルを出力
+ */
+function writeOutputFile(outputPath: string, resolvedRootMarkers: SearchIndexItem[]): void {
+ try {
+ const tsOutput = generateTypeScriptCode(resolvedRootMarkers);
+ fs.writeFileSync(outputPath, tsOutput, 'utf-8');
+ // 強制的に出力させるためにViteロガーを使わない
+ console.log(`Successfully wrote search index to ${outputPath} with ${resolvedRootMarkers.length} root entries`);
+ } catch (error) {
+ logger.error('[create-search-index]: error writing output: ', error);
+ }
+}
+
+/**
+ * TypeScriptコード生成
+ */
+function generateTypeScriptCode(resolvedRootMarkers: SearchIndexItem[]): string {
+ return `
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+// This file was automatically generated by create-search-index.
+// Do not edit this file.
+
+import { i18n } from '@/i18n.js';
+
+export type SearchIndexItem = {
+ id: string;
+ path?: string;
+ label: string;
+ keywords: string[];
+ icon?: string;
+ children?: SearchIndexItem[];
+};
+
+export const searchIndexes: SearchIndexItem[] = ${customStringify(resolvedRootMarkers)} as const;
+
+export type SearchIndex = typeof searchIndexes;
+`;
+}
+
+/**
+ * オブジェクトを特殊な形式の文字列に変換する
+ * i18n参照を保持しつつ適切な形式に変換
+ */
+function customStringify(obj: any, depth = 0): string {
+ const INDENT_STR = '\t';
+
+ // 配列の処理
+ if (Array.isArray(obj)) {
+ if (obj.length === 0) return '[]';
+ const indent = INDENT_STR.repeat(depth);
+ const childIndent = INDENT_STR.repeat(depth + 1);
+
+ // 配列要素の処理
+ const items = obj.map(item => {
+ // オブジェクト要素
+ if (typeof item === 'object' && item !== null) {
+ return `${childIndent}${customStringify(item, depth + 1)}`;
+ }
+
+ // i18n参照を含む文字列要素
+ if (typeof item === 'string' && item.includes('i18n.ts.')) {
+ return `${childIndent}${item}`; // クォートなしでそのまま出力
+ }
+
+ // その他の要素
+ return `${childIndent}${JSON5.stringify(item)}`;
+ }).join(',\n');
+
+ return `[\n${items},\n${indent}]`;
+ }
+
+ // null または非オブジェクト
+ if (obj === null || typeof obj !== 'object') {
+ return JSON5.stringify(obj);
+ }
+
+ // オブジェクトの処理
+ const indent = INDENT_STR.repeat(depth);
+ const childIndent = INDENT_STR.repeat(depth + 1);
+
+ const entries = Object.entries(obj)
+ // 不要なプロパティを除去
+ .filter(([key, value]) => {
+ if (value === undefined) return false;
+ if (key === 'children' && Array.isArray(value) && value.length === 0) return false;
+ if (key === 'inlining') return false;
+ return true;
+ })
+ // 各プロパティを変換
+ .map(([key, value]) => {
+ // 子要素配列の特殊処理
+ if (key === 'children' && Array.isArray(value) && value.length > 0) {
+ return `${childIndent}${key}: ${customStringify(value, depth + 1)}`;
+ }
+
+ // ラベルやその他プロパティを処理
+ return `${childIndent}${key}: ${formatSpecialProperty(key, value)}`;
+ });
+
+ if (entries.length === 0) return '{}';
+ return `{\n${entries.join(',\n')},\n${indent}}`;
+}
+
+/**
+ * 特殊プロパティの書式設定
+ */
+function formatSpecialProperty(key: string, value: any): string {
+ // 値がundefinedの場合は空文字列を返す
+ if (value === undefined) {
+ return '""';
+ }
+
+ // childrenが配列の場合は特別に処理
+ if (key === 'children' && Array.isArray(value)) {
+ return customStringify(value);
+ }
+
+ // keywordsが配列の場合、特別に処理
+ if (key === 'keywords' && Array.isArray(value)) {
+ return `[${formatArrayForOutput(value)}]`;
+ }
+
+ // 文字列値の場合の特別処理
+ if (typeof value === 'string') {
+ // i18n.ts 参照を含む場合 - クォートなしでそのまま出力
+ if (isI18nReference(value)) {
+ logger.info(`Preserving i18n reference in output: ${value}`);
+ return value;
+ }
+
+ // keywords が配列リテラルの形式の場合
+ if (key === 'keywords' && value.startsWith('[') && value.endsWith(']')) {
+ return value;
+ }
+ }
+
+ // 上記以外は通常の JSON5 文字列として返す
+ return JSON5.stringify(value);
+}
+
+/**
+ * 配列式の文字列表現を生成
+ */
+function formatArrayForOutput(items: any[]): string {
+ return items.map(item => {
+ // i18n.ts. 参照の文字列はそのままJavaScript式として出力
+ if (typeof item === 'string' && isI18nReference(item)) {
+ logger.info(`Preserving i18n reference in array: ${item}`);
+ return item; // クォートなしでそのまま
+ }
+
+ // その他の値はJSON5形式で文字列化
+ return JSON5.stringify(item);
+ }).join(', ');
+}
+
+/**
+ * 要素ノードからテキスト内容を抽出する
+ * 各抽出方法を分離して可読性を向上
+ */
+function extractElementText(node: VueAstNode): string | null {
+ if (!node) return null;
+
+ logger.info(`Extracting text from node type=${node.type}, tag=${node.tag || 'unknown'}`);
+
+ // 1. 直接コンテンツの抽出を試行
+ const directContent = extractDirectContent(node);
+ if (directContent) return directContent;
+
+ // 子要素がない場合は終了
+ if (!node.children || !Array.isArray(node.children)) {
+ return null;
+ }
+
+ // 2. インターポレーションノードを検索
+ const interpolationContent = extractInterpolationContent(node.children);
+ if (interpolationContent) return interpolationContent;
+
+ // 3. 式ノードを検索
+ const expressionContent = extractExpressionContent(node.children);
+ if (expressionContent) return expressionContent;
+
+ // 4. テキストノードを検索
+ const textContent = extractTextContent(node.children);
+ if (textContent) return textContent;
+
+ // 5. 再帰的に子ノードを探索
+ return extractNestedContent(node.children);
+}
+/**
+ * ノードから直接コンテンツを抽出
+ */
+function extractDirectContent(node: VueAstNode): string | null {
+ if (!node.content) return null;
+
+ const content = typeof node.content === 'string'
+ ? node.content.trim()
+ : (node.content.content ? node.content.content.trim() : null);
+
+ if (!content) return null;
+
+ logger.info(`Direct node content found: ${content}`);
+
+ // Mustache構文のチェック
+ const mustachePattern = /^\s*{{\s*(.*?)\s*}}\s*$/;
+ const mustacheMatch = content.match(mustachePattern);
+
+ if (mustacheMatch && mustacheMatch[1] && isI18nReference(mustacheMatch[1])) {
+ const extractedContent = mustacheMatch[1].trim();
+ logger.info(`Extracted i18n reference from mustache: ${extractedContent}`);
+ return extractedContent;
+ }
+
+ // 直接i18n参照を含む場合
+ if (isI18nReference(content)) {
+ logger.info(`Direct i18n reference found: ${content}`);
+ return content;
+ }
+
+ // その他のコンテンツ
+ return content;
+}
+
+/**
+ * インターポレーションノード(Mustache)からコンテンツを抽出
+ */
+function extractInterpolationContent(children: VueAstNode[]): string | null {
+ for (const child of children) {
+ if (child.type === NODE_TYPES.INTERPOLATION) {
+ logger.info(`Found interpolation node (Mustache): ${JSON.stringify(child.content).substring(0, 100)}...`);
+
+ if (child.content && child.content.type === 4 && child.content.content) {
+ const content = child.content.content.trim();
+ logger.info(`Interpolation content: ${content}`);
+
+ if (isI18nReference(content)) {
+ return content;
+ }
+ } else if (child.content && typeof child.content === 'object') {
+ // オブジェクト形式のcontentを探索
+ logger.info(`Complex interpolation node: ${JSON.stringify(child.content).substring(0, 100)}...`);
+
+ if (child.content.content) {
+ const content = child.content.content.trim();
+
+ if (isI18nReference(content)) {
+ logger.info(`Found i18n reference in complex interpolation: ${content}`);
+ return content;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+}
+
+/**
+ * 式ノードからコンテンツを抽出
+ */
+function extractExpressionContent(children: VueAstNode[]): string | null {
+ // i18n.ts. 参照パターンを持つものを優先
+ for (const child of children) {
+ if (child.type === NODE_TYPES.EXPRESSION && child.content) {
+ const expr = child.content.trim();
+
+ if (isI18nReference(expr)) {
+ logger.info(`Found i18n reference in expression node: ${expr}`);
+ return expr;
+ }
+ }
+ }
+
+ // その他の式
+ for (const child of children) {
+ if (child.type === NODE_TYPES.EXPRESSION && child.content) {
+ const expr = child.content.trim();
+ logger.info(`Found expression: ${expr}`);
+ return expr;
+ }
+ }
+
+ return null;
+}
+
+/**
+ * テキストノードからコンテンツを抽出
+ */
+function extractTextContent(children: VueAstNode[]): string | null {
+ for (const child of children) {
+ if (child.type === NODE_TYPES.TEXT && child.content) {
+ const text = child.content.trim();
+
+ if (text) {
+ logger.info(`Found text node: ${text}`);
+
+ // Mustache構文のチェック
+ const mustachePattern = /^\s*{{\s*(.*?)\s*}}\s*$/;
+ const mustacheMatch = text.match(mustachePattern);
+
+ if (mustacheMatch && mustacheMatch[1] && isI18nReference(mustacheMatch[1])) {
+ logger.info(`Extracted i18n ref from text mustache: ${mustacheMatch[1]}`);
+ return mustacheMatch[1].trim();
+ }
+
+ return text;
+ }
+ }
+ }
+
+ return null;
+}
+
+/**
+ * 子ノードを再帰的に探索してコンテンツを抽出
+ */
+function extractNestedContent(children: VueAstNode[]): string | null {
+ for (const child of children) {
+ if (child.children && Array.isArray(child.children) && child.children.length > 0) {
+ const nestedContent = extractElementText(child);
+
+ if (nestedContent) {
+ logger.info(`Found nested content: ${nestedContent}`);
+ return nestedContent;
+ }
+ } else if (child.type === NODE_TYPES.ELEMENT) {
+ // childrenがなくても内部を調査
+ const nestedContent = extractElementText(child);
+
+ if (nestedContent) {
+ logger.info(`Found content in childless element: ${nestedContent}`);
+ return nestedContent;
+ }
+ }
+ }
+
+ return null;
+}
+
+
+/**
+ * SearchLabelとSearchKeywordを探して抽出する関数
+ */
+function extractLabelsAndKeywords(nodes: VueAstNode[]): { label: string | null, keywords: any[] } {
+ let label: string | null = null;
+ const keywords: any[] = [];
+
+ logger.info(`Extracting labels and keywords from ${nodes.length} nodes`);
+
+ // 再帰的にSearchLabelとSearchKeywordを探索(ネストされたSearchMarkerは処理しない)
+ function findComponents(nodes: VueAstNode[]) {
+ for (const node of nodes) {
+ if (node.type === NODE_TYPES.ELEMENT) {
+ logger.info(`Checking element: ${node.tag}`);
+
+ // SearchMarkerの場合は、その子要素は別スコープなのでスキップ
+ if (node.tag === 'SearchMarker') {
+ logger.info(`Found nested SearchMarker - skipping its content to maintain scope isolation`);
+ continue; // このSearchMarkerの中身は処理しない (スコープ分離)
+ }
+
+ // SearchLabelの処理
+ if (node.tag === 'SearchLabel') {
+ logger.info(`Found SearchLabel node, structure: ${JSON.stringify(node).substring(0, 200)}...`);
+
+ // まず完全なノード内容の抽出を試みる
+ const content = extractElementText(node);
+ if (content) {
+ label = content;
+ logger.info(`SearchLabel content extracted: ${content}`);
+ } else {
+ logger.info(`SearchLabel found but extraction failed, trying direct children inspection`);
+
+ // バックアップ: 子直接確認 - type=5のMustacheインターポレーションを重点的に確認
+ if (node.children && Array.isArray(node.children)) {
+ for (const child of node.children) {
+ // Mustacheインターポレーション
+ if (child.type === NODE_TYPES.INTERPOLATION && child.content) {
+ // content内の式を取り出す
+ const expression = child.content.content ||
+ (child.content.type === 4 ? child.content.content : null) ||
+ JSON.stringify(child.content);
+
+ logger.info(`Interpolation expression: ${expression}`);
+ if (typeof expression === 'string' && isI18nReference(expression)) {
+ label = expression.trim();
+ logger.info(`Found i18n in interpolation: ${label}`);
+ break;
+ }
+ }
+ // 式ノード
+ else if (child.type === NODE_TYPES.EXPRESSION && child.content && isI18nReference(child.content)) {
+ label = child.content.trim();
+ logger.info(`Found i18n in expression: ${label}`);
+ break;
+ }
+ // テキストノードでもMustache構文を探す
+ else if (child.type === NODE_TYPES.TEXT && child.content) {
+ const mustacheMatch = child.content.trim().match(/^\s*{{\s*(.*?)\s*}}\s*$/);
+ if (mustacheMatch && mustacheMatch[1] && isI18nReference(mustacheMatch[1])) {
+ label = mustacheMatch[1].trim();
+ logger.info(`Found i18n in text mustache: ${label}`);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ // SearchKeywordの処理
+ else if (node.tag === 'SearchKeyword') {
+ logger.info(`Found SearchKeyword node`);
+
+ // まず完全なノード内容の抽出を試みる
+ const content = extractElementText(node);
+ if (content) {
+ keywords.push(content);
+ logger.info(`SearchKeyword content extracted: ${content}`);
+ } else {
+ logger.info(`SearchKeyword found but extraction failed, trying direct children inspection`);
+
+ // バックアップ: 子直接確認 - type=5のMustacheインターポレーションを重点的に確認
+ if (node.children && Array.isArray(node.children)) {
+ for (const child of node.children) {
+ // Mustacheインターポレーション
+ if (child.type === NODE_TYPES.INTERPOLATION && child.content) {
+ // content内の式を取り出す
+ const expression = child.content.content ||
+ (child.content.type === 4 ? child.content.content : null) ||
+ JSON.stringify(child.content);
+
+ logger.info(`Keyword interpolation: ${expression}`);
+ if (typeof expression === 'string' && isI18nReference(expression)) {
+ const keyword = expression.trim();
+ keywords.push(keyword);
+ logger.info(`Found i18n keyword in interpolation: ${keyword}`);
+ break;
+ }
+ }
+ // 式ノード
+ else if (child.type === NODE_TYPES.EXPRESSION && child.content && isI18nReference(child.content)) {
+ const keyword = child.content.trim();
+ keywords.push(keyword);
+ logger.info(`Found i18n keyword in expression: ${keyword}`);
+ break;
+ }
+ // テキストノードでもMustache構文を探す
+ else if (child.type === NODE_TYPES.TEXT && child.content) {
+ const mustacheMatch = child.content.trim().match(/^\s*{{\s*(.*?)\s*}}\s*$/);
+ if (mustacheMatch && mustacheMatch[1] && isI18nReference(mustacheMatch[1])) {
+ const keyword = mustacheMatch[1].trim();
+ keywords.push(keyword);
+ logger.info(`Found i18n keyword in text mustache: ${keyword}`);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 子要素を再帰的に調査(ただしSearchMarkerは除外)
+ if (node.children && Array.isArray(node.children)) {
+ findComponents(node.children);
+ }
+ }
+ }
+ }
+
+ findComponents(nodes);
+
+ // デバッグ情報
+ logger.info(`Extraction completed: label=${label}, keywords=[${keywords.join(', ')}]`);
+ return { label, keywords };
+}
+
+
+function extractUsageInfoFromTemplateAst(
+ templateAst: any,
+ id: string,
+): SearchIndexItem[] {
+ const allMarkers: SearchIndexItem[] = [];
+ const markerMap = new Map<string, SearchIndexItem>();
+ const childrenIds = new Set<string>();
+ const normalizedId = id.replace(/\\/g, '/');
+
+ if (!templateAst) return allMarkers;
+
+ // マーカーの基本情報を収集
+ function collectMarkers(node: VueAstNode, parentId: string | null = null) {
+ if (node.type === 1 && node.tag === 'SearchMarker') {
+ // マーカーID取得
+ const markerIdProp = node.props?.find((p: any) => p.name === 'markerId');
+ const markerId = markerIdProp?.value?.content ||
+ node.__markerId;
+
+ // SearchMarkerにマーカーIDがない場合はエラー
+ if (markerId == null) {
+ logger.error(`Marker ID not found for node: ${JSON.stringify(node)}`);
+ throw new Error(`Marker ID not found in file ${id}`);
+ }
+
+ // マーカー基本情報
+ const markerInfo: SearchIndexItem = {
+ id: markerId,
+ children: [],
+ label: '', // デフォルト値
+ keywords: [],
+ };
+
+ // 静的プロパティを取得
+ if (node.props && Array.isArray(node.props)) {
+ for (const prop of node.props) {
+ if (prop.type === 6 && prop.name && prop.name !== 'markerId') {
+ if (prop.name === 'path') markerInfo.path = prop.value?.content || '';
+ else if (prop.name === 'icon') markerInfo.icon = prop.value?.content || '';
+ else if (prop.name === 'label') markerInfo.label = prop.value?.content || '';
+ }
+ }
+ }
+
+ // バインドプロパティを取得
+ const bindings = extractNodeBindings(node);
+ if (bindings.path) markerInfo.path = bindings.path;
+ if (bindings.icon) markerInfo.icon = bindings.icon;
+ if (bindings.label) markerInfo.label = bindings.label;
+ if (bindings.children) markerInfo.children = bindings.children;
+ if (bindings.inlining) {
+ markerInfo.inlining = bindings.inlining;
+ logger.info(`Added inlining ${JSON.stringify(bindings.inlining)} to marker ${markerId}`);
+ }
+ if (bindings.keywords) {
+ if (Array.isArray(bindings.keywords)) {
+ markerInfo.keywords = bindings.keywords;
+ } else {
+ markerInfo.keywords = bindings.keywords || [];
+ }
+ }
+
+ //pathがない場合はファイルパスを設定
+ if (markerInfo.path == null && parentId == null) {
+ markerInfo.path = normalizedId.match(/.*(\/(admin|settings)\/[^\/]+)\.vue$/)?.[1];
+ }
+
+ // SearchLabelとSearchKeywordを抽出 (AST全体を探索)
+ if (node.children && Array.isArray(node.children)) {
+ logger.info(`Processing marker ${markerId} for labels and keywords`);
+ const extracted = extractLabelsAndKeywords(node.children);
+
+ // SearchLabelからのラベル取得は最優先で適用
+ if (extracted.label) {
+ markerInfo.label = extracted.label;
+ logger.info(`Using extracted label for ${markerId}: ${extracted.label}`);
+ } else if (markerInfo.label) {
+ logger.info(`Using existing label for ${markerId}: ${markerInfo.label}`);
+ } else {
+ markerInfo.label = 'Unnamed marker';
+ logger.info(`No label found for ${markerId}, using default`);
+ }
+
+ // SearchKeywordからのキーワード取得を追加
+ if (extracted.keywords.length > 0) {
+ const existingKeywords = Array.isArray(markerInfo.keywords) ?
+ [...markerInfo.keywords] :
+ (markerInfo.keywords ? [markerInfo.keywords] : []);
+
+ // i18n参照のキーワードは最優先で追加
+ const combinedKeywords = [...existingKeywords];
+ for (const kw of extracted.keywords) {
+ combinedKeywords.push(kw);
+ logger.info(`Added extracted keyword to ${markerId}: ${kw}`);
+ }
+
+ markerInfo.keywords = combinedKeywords;
+ }
+ }
+
+ // マーカーを登録
+ markerMap.set(markerId, markerInfo);
+ allMarkers.push(markerInfo);
+
+ // 親子関係を記録
+ if (parentId) {
+ const parent = markerMap.get(parentId);
+ if (parent) {
+ childrenIds.add(markerId);
+ }
+ }
+
+ // 子ノードを処理
+ if (node.children && Array.isArray(node.children)) {
+ node.children.forEach((child: VueAstNode) => {
+ collectMarkers(child, markerId);
+ });
+ }
+
+ return markerId;
+ }
+ // SearchMarkerでない場合は再帰的に子ノードを処理
+ else if (node.children && Array.isArray(node.children)) {
+ node.children.forEach((child: VueAstNode) => {
+ collectMarkers(child, parentId);
+ });
+ }
+
+ return null;
+ }
+
+ // AST解析開始
+ collectMarkers(templateAst);
+ return allMarkers;
+}
+
+// バインドプロパティの処理を修正する関数
+function extractNodeBindings(node: VueAstNode): Record<keyof SearchIndexItem, any> {
+ const bindings: Record<string, any> = {};
+
+ if (!node.props || !Array.isArray(node.props)) return bindings;
+
+ // バインド式を収集
+ for (const prop of node.props) {
+ if (prop.type === 7 && prop.name === 'bind' && prop.arg?.content) {
+ const propName = prop.arg.content;
+ const propContent = prop.exp?.content || '';
+
+ logger.info(`Processing bind prop ${propName}: ${propContent}`);
+
+ // inliningプロパティの処理を追加
+ if (propName === 'inlining') {
+ try {
+ const content = propContent.trim();
+
+ // 配列式の場合
+ if (content.startsWith('[') && content.endsWith(']')) {
+ // 配列要素を解析
+ const elements = parseArrayExpression(content);
+ if (elements.length > 0) {
+ bindings.inlining = elements;
+ logger.info(`Parsed inlining array: ${JSON5.stringify(elements)}`);
+ } else {
+ bindings.inlining = [];
+ }
+ }
+ // 文字列の場合は配列に変換
+ else if (content) {
+ bindings.inlining = [content]; // 単一の値を配列に
+ logger.info(`Converting inlining to array: [${content}]`);
+ }
+ } catch (e) {
+ logger.error(`Failed to parse inlining binding: ${propContent}`, e);
+ }
+ }
+ // keywordsの特殊処理
+ if (propName === 'keywords') {
+ try {
+ const content = propContent.trim();
+
+ // 配列式の場合
+ if (content.startsWith('[') && content.endsWith(']')) {
+ // i18n参照や特殊な式を保持するため、各要素を個別に解析
+ const elements = parseArrayExpression(content);
+ if (elements.length > 0) {
+ bindings.keywords = elements;
+ logger.info(`Parsed keywords array: ${JSON5.stringify(elements)}`);
+ } else {
+ bindings.keywords = [];
+ logger.info('Empty keywords array');
+ }
+ }
+ // その他の式(非配列)
+ else if (content) {
+ bindings.keywords = content; // 式をそのまま保持
+ logger.info(`Keeping keywords as expression: ${content}`);
+ } else {
+ bindings.keywords = [];
+ logger.info('No keywords provided');
+ }
+ } catch (e) {
+ logger.error(`Failed to parse keywords binding: ${propContent}`, e);
+ // エラーが起きても何らかの値を設定
+ bindings.keywords = propContent || [];
+ }
+ }
+ // その他のプロパティ
+ else if (propName === 'label') {
+ // ラベルの場合も式として保持
+ bindings[propName] = propContent;
+ logger.info(`Set label from bind expression: ${propContent}`);
+ }
+ else {
+ bindings[propName] = propContent;
+ }
+ }
+ }
+
+ return bindings;
+}
+
+// 配列式をパースする補助関数(文字列リテラル処理を改善)
+function parseArrayExpression(expr: string): any[] {
+ try {
+ // 単純なケースはJSON5でパースを試みる
+ return JSON5.parse(expr.replace(/'/g, '"'));
+ } catch (e) {
+ // 複雑なケース(i18n.ts.xxx などの式を含む場合)は手動パース
+ logger.info(`Complex array expression, trying manual parsing: ${expr}`);
+
+ // "["と"]"を取り除く
+ const content = expr.substring(1, expr.length - 1).trim();
+ if (!content) return [];
+
+ const result: any[] = [];
+ let currentItem = '';
+ let depth = 0;
+ let inString = false;
+ let stringChar = '';
+
+ // カンマで区切る(ただし文字列内や入れ子の配列内のカンマは無視)
+ for (let i = 0; i < content.length; i++) {
+ const char = content[i];
+
+ if (inString) {
+ if (char === stringChar && content[i - 1] !== '\\') {
+ inString = false;
+ }
+ currentItem += char;
+ } else if (char === '"' || char === "'") {
+ inString = true;
+ stringChar = char;
+ currentItem += char;
+ } else if (char === '[') {
+ depth++;
+ currentItem += char;
+ } else if (char === ']') {
+ depth--;
+ currentItem += char;
+ } else if (char === ',' && depth === 0) {
+ // 項目の区切りを検出
+ const trimmed = currentItem.trim();
+
+ // 純粋な文字列リテラルの場合、実際の値に変換
+ if ((trimmed.startsWith("'") && trimmed.endsWith("'")) ||
+ (trimmed.startsWith('"') && trimmed.endsWith('"'))) {
+ try {
+ result.push(JSON5.parse(trimmed));
+ } catch (err) {
+ result.push(trimmed);
+ }
+ } else {
+ // それ以外の式はそのまま(i18n.ts.xxx など)
+ result.push(trimmed);
+ }
+
+ currentItem = '';
+ } else {
+ currentItem += char;
+ }
+ }
+
+ // 最後の項目を処理
+ if (currentItem.trim()) {
+ const trimmed = currentItem.trim();
+
+ // 純粋な文字列リテラルの場合、実際の値に変換
+ if ((trimmed.startsWith("'") && trimmed.endsWith("'")) ||
+ (trimmed.startsWith('"') && trimmed.endsWith('"'))) {
+ try {
+ result.push(JSON5.parse(trimmed));
+ } catch (err) {
+ result.push(trimmed);
+ }
+ } else {
+ // それ以外の式はそのまま(i18n.ts.xxx など)
+ result.push(trimmed);
+ }
+ }
+
+ logger.info(`Parsed complex array expression: ${expr} -> ${JSON.stringify(result)}`);
+ return result;
+ }
+}
+
+export async function analyzeVueProps(options: Options & {
+ transformedCodeCache: Record<string, string>,
+}): Promise<void> {
+ initLogger(options);
+
+ const allMarkers: SearchIndexItem[] = [];
+
+ // 対象ファイルパスを glob で展開
+ const filePaths = options.targetFilePaths.reduce<string[]>((acc, filePathPattern) => {
+ const matchedFiles = glob.sync(filePathPattern);
+ return [...acc, ...matchedFiles];
+ }, []);
+
+ logger.info(`Found ${filePaths.length} matching files to analyze`);
+
+ for (const filePath of filePaths) {
+ const absolutePath = path.join(process.cwd(), filePath);
+ const id = absolutePath.replace(/\\/g, '/'); // 絶対パスに変換
+ const code = options.transformedCodeCache[id]; // options 経由でキャッシュ参照
+ if (!code) { // キャッシュミスの場合
+ logger.error(`Error: No cached code found for: ${id}.`); // エラーログ
+ throw new Error(`No cached code found for: ${id}.`); // エラーを投げる
+ }
+
+ try {
+ const { descriptor, errors } = vueSfcParse(options.transformedCodeCache[id], {
+ filename: filePath,
+ });
+
+ if (errors.length > 0) {
+ logger.error(`Compile Error: ${filePath}, ${errors}`);
+ continue; // エラーが発生したファイルはスキップ
+ }
+
+ const fileMarkers = extractUsageInfoFromTemplateAst(descriptor.template?.ast, id);
+
+ if (fileMarkers && fileMarkers.length > 0) {
+ allMarkers.push(...fileMarkers); // すべてのマーカーを収集
+ logger.info(`Successfully extracted ${fileMarkers.length} markers from ${filePath}`);
+ } else {
+ logger.info(`No markers found in ${filePath}`);
+ }
+ } catch (error) {
+ logger.error(`Error analyzing file ${filePath}:`, error);
+ }
+ }
+
+ // 収集したすべてのマーカー情報を使用
+ const analysisResult: AnalysisResult[] = [
+ {
+ filePath: "combined-markers", // すべてのファイルのマーカーを1つのエントリとして扱う
+ usage: allMarkers,
+ }
+ ];
+
+ outputAnalysisResultAsTS(options.exportFilePath, analysisResult); // すべてのマーカー情報を渡す
+}
+
+interface MarkerRelation {
+ parentId?: string;
+ markerId: string;
+ node: VueAstNode;
+}
+
+async function processVueFile(
+ code: string,
+ id: string,
+ options: Options,
+ transformedCodeCache: Record<string, string>
+): Promise<{
+ code: string,
+ map: any,
+ transformedCodeCache: Record<string, string>
+}> {
+ const normalizedId = id.replace(/\\/g, '/'); // ファイルパスを正規化
+ // すでにキャッシュに存在する場合は、そのまま返す
+ if (transformedCodeCache[normalizedId] && transformedCodeCache[normalizedId].includes('markerId=')) {
+ logger.info(`Using cached version for ${id}`);
+ return {
+ code: transformedCodeCache[normalizedId],
+ map: null,
+ transformedCodeCache
+ };
+ }
+
+ const s = new MagicString(code); // magic-string のインスタンスを作成
+ const parsed = vueSfcParse(code, { filename: id });
+ if (!parsed.descriptor.template) {
+ return {
+ code,
+ map: null,
+ transformedCodeCache
+ };
+ }
+ const ast = parsed.descriptor.template.ast; // テンプレート AST を取得
+ const markerRelations: MarkerRelation[] = []; // MarkerRelation 配列を初期化
+
+ if (ast) {
+ function traverse(node: any, currentParent?: any) {
+ if (node.type === 1 && node.tag === 'SearchMarker') {
+ // 行番号はコード先頭からの改行数で取得
+ const lineNumber = code.slice(0, node.loc.start.offset).split('\n').length;
+ // ファイルパスと行番号からハッシュ値を生成
+ // この際実行環境で差が出ないようにファイルパスを正規化
+ const idKey = id.replace(/\\/g, '/').split('packages/frontend/')[1]
+ const generatedMarkerId = toBase62(hash(`${idKey}:${lineNumber}`));
+
+ const props = node.props || [];
+ const hasMarkerIdProp = props.some((prop: any) => prop.type === 6 && prop.name === 'markerId');
+ const nodeMarkerId = hasMarkerIdProp
+ ? props.find((prop: any) => prop.type === 6 && prop.name === 'markerId')?.value?.content as string
+ : generatedMarkerId;
+ node.__markerId = nodeMarkerId;
+
+ // 子マーカーの場合、親ノードに __children を設定しておく
+ if (currentParent && currentParent.type === 1 && currentParent.tag === 'SearchMarker') {
+ currentParent.__children = currentParent.__children || [];
+ currentParent.__children.push(nodeMarkerId);
+ }
+
+ const parentMarkerId = currentParent && currentParent.__markerId;
+ markerRelations.push({
+ parentId: parentMarkerId,
+ markerId: nodeMarkerId,
+ node: node,
+ });
+
+ if (!hasMarkerIdProp) {
+ const nodeStart = node.loc.start.offset;
+ let endOfStartTag;
+
+ if (node.children && node.children.length > 0) {
+ // 子要素がある場合、最初の子要素の開始位置を基準にする
+ endOfStartTag = code.lastIndexOf('>', node.children[0].loc.start.offset);
+ } else if (node.loc.end.offset > nodeStart) {
+ // 子要素がない場合、自身の終了位置から逆算
+ const nodeSource = code.substring(nodeStart, node.loc.end.offset);
+ // 自己終了タグか通常の終了タグかを判断
+ if (nodeSource.includes('/>')) {
+ endOfStartTag = code.indexOf('/>', nodeStart) - 1;
+ } else {
+ endOfStartTag = code.indexOf('>', nodeStart);
+ }
+ }
+
+ if (endOfStartTag !== undefined && endOfStartTag !== -1) {
+ // markerId が既に存在しないことを確認
+ const tagText = code.substring(nodeStart, endOfStartTag + 1);
+ const markerIdRegex = /\s+markerId\s*=\s*["'][^"']*["']/;
+
+ if (!markerIdRegex.test(tagText)) {
+ s.appendRight(endOfStartTag, ` markerId="${generatedMarkerId}" data-in-app-search-marker-id="${generatedMarkerId}"`);
+ logger.info(`Adding markerId="${generatedMarkerId}" to ${id}:${lineNumber}`);
+ } else {
+ logger.info(`markerId already exists in ${id}:${lineNumber}`);
+ }
+ }
+ }
+ }
+
+ const newParent = node.type === 1 && node.tag === 'SearchMarker' ? node : currentParent;
+ if (node.children && Array.isArray(node.children)) {
+ node.children.forEach(child => traverse(child, newParent));
+ }
+ }
+
+ traverse(ast); // AST を traverse (1段階目: ID 生成と親子関係記録)
+
+ // 2段階目: :children 属性の追加
+ // 最初に親マーカーごとに子マーカーIDを集約する処理を追加
+ const parentChildrenMap = new Map<string, string[]>();
+
+ // 1. まず親ごとのすべての子マーカーIDを収集
+ markerRelations.forEach(relation => {
+ if (relation.parentId) {
+ if (!parentChildrenMap.has(relation.parentId)) {
+ parentChildrenMap.set(relation.parentId, []);
+ }
+ parentChildrenMap.get(relation.parentId)?.push(relation.markerId);
+ }
+ });
+
+ // 2. 親ごとにまとめて :children 属性を処理
+ for (const [parentId, childIds] of parentChildrenMap.entries()) {
+ const parentRelation = markerRelations.find(r => r.markerId === parentId);
+ if (!parentRelation || !parentRelation.node) continue;
+
+ const parentNode = parentRelation.node;
+ const childrenProp = parentNode.props?.find((prop: any) => prop.type === 7 && prop.name === 'bind' && prop.arg?.content === 'children');
+
+ // 親ノードの開始位置を特定
+ const parentNodeStart = parentNode.loc!.start.offset;
+ const endOfParentStartTag = parentNode.children && parentNode.children.length > 0
+ ? code.lastIndexOf('>', parentNode.children[0].loc!.start.offset)
+ : code.indexOf('>', parentNodeStart);
+
+ if (endOfParentStartTag === -1) continue;
+
+ // 親タグのテキストを取得
+ const parentTagText = code.substring(parentNodeStart, endOfParentStartTag + 1);
+
+ if (childrenProp) {
+ // AST で :children 属性が検出された場合、それを更新
+ try {
+ const childrenStart = code.indexOf('[', childrenProp.exp!.loc.start.offset);
+ const childrenEnd = code.indexOf(']', childrenProp.exp!.loc.start.offset);
+ if (childrenStart !== -1 && childrenEnd !== -1) {
+ const childrenArrayStr = code.slice(childrenStart, childrenEnd + 1);
+ let childrenArray = JSON5.parse(childrenArrayStr.replace(/'/g, '"'));
+
+ // 新しいIDを追加(重複は除外)
+ const newIds = childIds.filter(id => !childrenArray.includes(id));
+ if (newIds.length > 0) {
+ childrenArray = [...childrenArray, ...newIds];
+ const updatedChildrenArrayStr = JSON5.stringify(childrenArray).replace(/"/g, "'");
+ s.overwrite(childrenStart, childrenEnd + 1, updatedChildrenArrayStr);
+ logger.info(`Added ${newIds.length} child markerIds to existing :children in ${id}`);
+ }
+ }
+ } catch (e) {
+ logger.error('Error updating :children attribute:', e);
+ }
+ } else {
+ // AST では検出されなかった場合、タグテキストを調べる
+ const childrenRegex = /:children\s*=\s*["']\[(.*?)\]["']/;
+ const childrenMatch = parentTagText.match(childrenRegex);
+
+ if (childrenMatch) {
+ // テキストから :children 属性値を解析して更新
+ try {
+ const childrenContent = childrenMatch[1];
+ const childrenArrayStr = `[${childrenContent}]`;
+ const childrenArray = JSON5.parse(childrenArrayStr.replace(/'/g, '"'));
+
+ // 新しいIDを追加(重複は除外)
+ const newIds = childIds.filter(id => !childrenArray.includes(id));
+ if (newIds.length > 0) {
+ childrenArray.push(...newIds);
+
+ // :children="[...]" の位置を特定して上書き
+ const attrStart = parentTagText.indexOf(':children=');
+ if (attrStart > -1) {
+ const attrValueStart = parentTagText.indexOf('[', attrStart);
+ const attrValueEnd = parentTagText.indexOf(']', attrValueStart) + 1;
+ if (attrValueStart > -1 && attrValueEnd > -1) {
+ const absoluteStart = parentNodeStart + attrValueStart;
+ const absoluteEnd = parentNodeStart + attrValueEnd;
+ const updatedArrayStr = JSON5.stringify(childrenArray).replace(/"/g, "'");
+ s.overwrite(absoluteStart, absoluteEnd, updatedArrayStr);
+ logger.info(`Updated existing :children in tag text for ${id}`);
+ }
+ }
+ }
+ } catch (e) {
+ logger.error('Error updating :children in tag text:', e);
+ }
+ } else {
+ // :children 属性がまだない場合、新規作成
+ s.appendRight(endOfParentStartTag, ` :children="${JSON5.stringify(childIds).replace(/"/g, "'")}"`);
+ logger.info(`Created new :children attribute with ${childIds.length} markerIds in ${id}`);
+ }
+ }
+ }
+ }
+
+ const transformedCode = s.toString(); // 変換後のコードを取得
+ transformedCodeCache[normalizedId] = transformedCode; // 変換後のコードをキャッシュに保存
+
+ return {
+ code: transformedCode, // 変更後のコードを返す
+ map: s.generateMap({ source: id, includeContent: true }), // ソースマップも生成 (sourceMap: true が必要)
+ transformedCodeCache // キャッシュも返す
+ };
+}
+
+
+// Rollup プラグインとして export
+export default function pluginCreateSearchIndex(options: Options): Plugin {
+ let transformedCodeCache: Record<string, string> = {}; // キャッシュオブジェクトをプラグインスコープで定義
+ const isDevServer = process.env.NODE_ENV === 'development'; // 開発サーバーかどうか
+
+ initLogger(options); // ロガーを初期化
+
+ return {
+ name: 'createSearchIndex',
+ enforce: 'pre',
+
+ async buildStart() {
+ if (!isDevServer) {
+ return;
+ }
+
+ const filePaths = options.targetFilePaths.reduce<string[]>((acc, filePathPattern) => {
+ const matchedFiles = glob.sync(filePathPattern);
+ return [...acc, ...matchedFiles];
+ }, []);
+
+ for (const filePath of filePaths) {
+ const id = path.resolve(filePath); // 絶対パスに変換
+ const code = fs.readFileSync(filePath, 'utf-8'); // ファイル内容を読み込む
+ const { transformedCodeCache: newCache } = await processVueFile(code, id, options, transformedCodeCache); // processVueFile 関数を呼び出す
+ transformedCodeCache = newCache; // キャッシュを更新
+ }
+
+ await analyzeVueProps({ ...options, transformedCodeCache }); // 開発サーバー起動時にも analyzeVueProps を実行
+ },
+
+ async transform(code, id) {
+ if (!id.endsWith('.vue')) {
+ return;
+ }
+
+ // targetFilePaths にマッチするファイルのみ処理を行う
+ // glob パターンでマッチング
+ let isMatch = false; // isMatch の初期値を false に設定
+ for (const pattern of options.targetFilePaths) { // パターンごとにマッチング確認
+ const globbedFiles = glob.sync(pattern);
+ for (const globbedFile of globbedFiles) {
+ const normalizedGlobbedFile = path.resolve(globbedFile); // glob 結果を絶対パスに
+ const normalizedId = path.resolve(id); // id を絶対パスに
+ if (normalizedGlobbedFile === normalizedId) { // 絶対パス同士で比較
+ isMatch = true;
+ break; // マッチしたらループを抜ける
+ }
+ }
+ if (isMatch) break; // いずれかのパターンでマッチしたら、outer loop も抜ける
+ }
+
+
+ if (!isMatch) {
+ return;
+ }
+
+ const transformed = await processVueFile(code, id, options, transformedCodeCache);
+ transformedCodeCache = transformed.transformedCodeCache; // キャッシュを更新
+ if (isDevServer) {
+ await analyzeVueProps({ ...options, transformedCodeCache }); // analyzeVueProps を呼び出す
+ }
+ return transformed;
+ },
+
+ async writeBundle() {
+ await analyzeVueProps({ ...options, transformedCodeCache }); // ビルド時にも analyzeVueProps を実行
+ },
+ };
+}
+
+// i18n参照を検出するためのヘルパー関数を追加
+function isI18nReference(text: string | null | undefined): boolean {
+ if (!text) return false;
+ // ドット記法(i18n.ts.something)
+ const dotPattern = /i18n\.ts\.\w+/;
+ // ブラケット記法(i18n.ts['something'])
+ const bracketPattern = /i18n\.ts\[['"][^'"]+['"]\]/;
+ return dotPattern.test(text) || bracketPattern.test(text);
+}
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index 2bf7728d0a..88b57e57ab 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -51,6 +51,7 @@
"insert-text-at-cursor": "0.3.0",
"is-file-animated": "1.0.2",
"json5": "2.2.3",
+ "magic-string": "0.30.17",
"matter-js": "0.20.0",
"mfm-js": "0.24.0",
"misskey-bubble-game": "workspace:*",
@@ -72,30 +73,30 @@
"typescript": "5.8.2",
"uuid": "11.1.0",
"v-code-diff": "1.13.1",
- "vite": "6.2.0",
+ "vite": "6.2.1",
"vue": "3.5.13",
"vuedraggable": "next"
},
"devDependencies": {
"@misskey-dev/summaly": "5.2.0",
- "@storybook/addon-actions": "8.6.3",
- "@storybook/addon-essentials": "8.6.3",
- "@storybook/addon-interactions": "8.6.3",
- "@storybook/addon-links": "8.6.3",
- "@storybook/addon-mdx-gfm": "8.6.3",
- "@storybook/addon-storysource": "8.6.3",
- "@storybook/blocks": "8.6.3",
- "@storybook/components": "8.6.3",
- "@storybook/core-events": "8.6.3",
- "@storybook/manager-api": "8.6.3",
- "@storybook/preview-api": "8.6.3",
- "@storybook/react": "8.6.3",
- "@storybook/react-vite": "8.6.3",
- "@storybook/test": "8.6.3",
- "@storybook/theming": "8.6.3",
- "@storybook/types": "8.6.3",
- "@storybook/vue3": "8.6.3",
- "@storybook/vue3-vite": "8.6.3",
+ "@storybook/addon-actions": "8.6.4",
+ "@storybook/addon-essentials": "8.6.4",
+ "@storybook/addon-interactions": "8.6.4",
+ "@storybook/addon-links": "8.6.4",
+ "@storybook/addon-mdx-gfm": "8.6.4",
+ "@storybook/addon-storysource": "8.6.4",
+ "@storybook/blocks": "8.6.4",
+ "@storybook/components": "8.6.4",
+ "@storybook/core-events": "8.6.4",
+ "@storybook/manager-api": "8.6.4",
+ "@storybook/preview-api": "8.6.4",
+ "@storybook/react": "8.6.4",
+ "@storybook/react-vite": "8.6.4",
+ "@storybook/test": "8.6.4",
+ "@storybook/theming": "8.6.4",
+ "@storybook/types": "8.6.4",
+ "@storybook/vue3": "8.6.4",
+ "@storybook/vue3-vite": "8.6.4",
"@testing-library/vue": "8.1.0",
"@types/canvas-confetti": "1.9.0",
"@types/estree": "1.0.6",
@@ -110,15 +111,15 @@
"@types/ws": "8.18.0",
"@typescript-eslint/eslint-plugin": "8.26.0",
"@typescript-eslint/parser": "8.26.0",
- "@vitest/coverage-v8": "3.0.7",
+ "@vitest/coverage-v8": "3.0.8",
"@vue/runtime-core": "3.5.13",
- "acorn": "8.14.0",
+ "acorn": "8.14.1",
"cross-env": "7.0.3",
"cypress": "14.1.0",
"eslint-plugin-import": "2.31.0",
- "eslint-plugin-vue": "9.33.0",
+ "eslint-plugin-vue": "10.0.0",
"fast-glob": "3.3.3",
- "happy-dom": "17.2.2",
+ "happy-dom": "17.3.0",
"intersection-observer": "0.12.2",
"micromatch": "4.0.8",
"msw": "2.7.3",
@@ -129,13 +130,13 @@
"react-dom": "19.0.0",
"seedrandom": "3.0.5",
"start-server-and-test": "2.0.10",
- "storybook": "8.6.3",
+ "storybook": "8.6.4",
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
"vite-plugin-turbosnap": "1.0.3",
- "vitest": "3.0.7",
+ "vitest": "3.0.8",
"vitest-fetch-mock": "0.4.5",
"vue-component-type-helpers": "2.2.8",
- "vue-eslint-parser": "9.4.3",
+ "vue-eslint-parser": "10.1.1",
"vue-tsc": "2.2.8"
}
}
diff --git a/idea/MkDisableSection.vue b/packages/frontend/src/components/MkDisableSection.vue
index 360705071b..bd7ecf225d 100644
--- a/idea/MkDisableSection.vue
+++ b/packages/frontend/src/components/MkDisableSection.vue
@@ -24,7 +24,8 @@ defineProps<{
}
.disabled {
- opacity: 0.7;
+ opacity: 0.3;
+ filter: saturate(0.5);
}
.cover {
@@ -34,7 +35,7 @@ defineProps<{
width: 100%;
height: 100%;
cursor: not-allowed;
- --color: color(from var(--MI_THEME-error) srgb r g b / 0.25);
+ --color: light-dark(rgba(0, 0, 0, 0.05), rgba(255, 255, 255, 0.05));
background-size: auto auto;
background-image: repeating-linear-gradient(135deg, transparent, transparent 10px, var(--color) 4px, var(--color) 14px);
}
diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue
index e725d2a15d..c3fc1961eb 100644
--- a/packages/frontend/src/components/MkPageWindow.vue
+++ b/packages/frontend/src/components/MkPageWindow.vue
@@ -91,6 +91,14 @@ const buttonsRight = computed(() => {
});
const reloadCount = ref(0);
+function getSearchMarker(path: string) {
+ const hash = path.split('#')[1];
+ if (hash == null) return null;
+ return hash;
+}
+
+const searchMarkerId = ref<string | null>(getSearchMarker(props.initialPath));
+
windowRouter.addListener('push', ctx => {
history.value.push({ path: ctx.path, key: ctx.key });
});
@@ -101,7 +109,8 @@ windowRouter.addListener('replace', ctx => {
});
windowRouter.addListener('change', ctx => {
- console.log('windowRouter: change', ctx.path);
+ if (_DEV_) console.log('windowRouter: change', ctx.path);
+ searchMarkerId.value = getSearchMarker(ctx.path);
analytics.page({
path: ctx.path,
title: ctx.path,
@@ -111,6 +120,7 @@ windowRouter.addListener('change', ctx => {
windowRouter.init();
provide('router', windowRouter);
+provide('inAppSearchMarkerId', searchMarkerId);
provideMetadataReceiver((metadataGetter) => {
const info = metadataGetter();
pageMetadata.value = info;
diff --git a/packages/frontend/src/components/MkSuperMenu.vue b/packages/frontend/src/components/MkSuperMenu.vue
index 397aa68ed6..d8dec3aa2f 100644
--- a/packages/frontend/src/components/MkSuperMenu.vue
+++ b/packages/frontend/src/components/MkSuperMenu.vue
@@ -4,27 +4,60 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="rrevdjwu" :class="{ grid }">
- <div v-for="group in def" class="group">
- <div v-if="group.title" class="title">{{ group.title }}</div>
+<div ref="rootEl" class="rrevdjwu" :class="{ grid }">
+ <MkInput
+ v-model="search"
+ :placeholder="i18n.ts.search"
+ type="search"
+ style="margin-bottom: 16px;"
+ @keydown="searchOnKeyDown"
+ >
+ <template #prefix><i class="ti ti-search"></i></template>
+ </MkInput>
- <div class="items">
- <template v-for="(item, i) in group.items">
- <a v-if="item.type === 'a'" :href="item.href" :target="item.target" class="_button item" :class="{ danger: item.danger, active: item.active }">
- <span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
- <span class="text">{{ item.text }}</span>
- </a>
- <button v-else-if="item.type === 'button'" class="_button item" :class="{ danger: item.danger, active: item.active }" :disabled="item.active" @click="ev => item.action(ev)">
- <span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
- <span class="text">{{ item.text }}</span>
- </button>
- <MkA v-else :to="item.to" class="_button item" :class="{ danger: item.danger, active: item.active }">
- <span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
- <span class="text">{{ item.text }}</span>
- </MkA>
- </template>
+ <template v-if="search == ''">
+ <div v-for="group in def" class="group">
+ <div v-if="group.title" class="title">{{ group.title }}</div>
+
+ <div class="items">
+ <template v-for="(item, i) in group.items">
+ <a v-if="item.type === 'a'" :href="item.href" :target="item.target" class="_button item" :class="{ danger: item.danger, active: item.active }">
+ <span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
+ <span class="text">{{ item.text }}</span>
+ </a>
+ <button v-else-if="item.type === 'button'" class="_button item" :class="{ danger: item.danger, active: item.active }" :disabled="item.active" @click="ev => item.action(ev)">
+ <span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
+ <span class="text">{{ item.text }}</span>
+ </button>
+ <MkA v-else :to="item.to" class="_button item" :class="{ danger: item.danger, active: item.active }">
+ <span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
+ <span class="text">{{ item.text }}</span>
+ </MkA>
+ </template>
+ </div>
+ </div>
+ </template>
+ <template v-else>
+ <div v-for="item, index in searchResult">
+ <MkA
+ :to="item.path + '#' + item.id"
+ class="_button searchResultItem"
+ :class="{ selected: searchSelectedIndex !== null && searchSelectedIndex === index }"
+ >
+ <span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
+ <span class="text">
+ <template v-if="item.isRoot">
+ {{ item.label }}
+ </template>
+ <template v-else>
+ <span style="opacity: 0.7; font-size: 90%;">{{ item.parentLabels.join(' > ') }}</span>
+ <br>
+ <span>{{ item.label }}</span>
+ </template>
+ </span>
+ </MkA>
</div>
- </div>
+ </template>
</div>
</template>
@@ -58,10 +91,98 @@ export type SuperMenuDef = {
</script>
<script lang="ts" setup>
-defineProps<{
+import { useTemplateRef, ref, watch, nextTick } from 'vue';
+import type { SearchIndexItem } from '@/scripts/autogen/settings-search-index.js';
+import MkInput from '@/components/MkInput.vue';
+import { i18n } from '@/i18n.js';
+import { getScrollContainer } from '@@/js/scroll.js';
+import { useRouter } from '@/router/supplier.js';
+
+const props = defineProps<{
def: SuperMenuDef[];
grid?: boolean;
+ searchIndex: SearchIndexItem[];
}>();
+
+const router = useRouter();
+const rootEl = useTemplateRef('rootEl');
+
+const search = ref('');
+const searchSelectedIndex = ref<null | number>(null);
+const searchResult = ref<{
+ id: string;
+ path: string;
+ label: string;
+ icon?: string;
+ isRoot: boolean;
+ parentLabels: string[];
+}[]>([]);
+
+watch(search, (value) => {
+ searchResult.value = [];
+ searchSelectedIndex.value = null;
+
+ if (value === '') {
+ return;
+ }
+
+ const dive = (items: SearchIndexItem[], parents: SearchIndexItem[] = []) => {
+ for (const item of items) {
+ const matched =
+ item.label.includes(value.toLowerCase()) ||
+ item.keywords.some((x) => x.toLowerCase().includes(value.toLowerCase()));
+
+ if (matched) {
+ searchResult.value.push({
+ id: item.id,
+ path: item.path ?? parents.find((x) => x.path != null)?.path,
+ label: item.label,
+ parentLabels: parents.map((x) => x.label).toReversed(),
+ icon: item.icon ?? parents.find((x) => x.icon != null)?.icon,
+ isRoot: parents.length === 0,
+ });
+ }
+
+ if (item.children) {
+ dive(item.children, [item, ...parents]);
+ }
+ }
+ };
+
+ dive(props.searchIndex);
+});
+
+function searchOnKeyDown(ev: KeyboardEvent) {
+ if (ev.isComposing) return;
+
+ if (ev.key === 'Enter' && searchSelectedIndex.value != null) {
+ ev.preventDefault();
+ router.push(searchResult.value[searchSelectedIndex.value].path + '#' + searchResult.value[searchSelectedIndex.value].id);
+ } else if (ev.key === 'ArrowDown') {
+ ev.preventDefault();
+ const current = searchSelectedIndex.value ?? -1;
+ searchSelectedIndex.value = current + 1 >= searchResult.value.length ? 0 : current + 1;
+ } else if (ev.key === 'ArrowUp') {
+ ev.preventDefault();
+ const current = searchSelectedIndex.value ?? 0;
+ searchSelectedIndex.value = current - 1 < 0 ? searchResult.value.length - 1 : current - 1;
+ }
+
+ if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp') {
+ nextTick(() => {
+ if (!rootEl.value) return;
+ const selectedEl = rootEl.value.querySelector<HTMLElement>('.searchResultItem.selected');
+ if (selectedEl != null) {
+ const scrollContainer = getScrollContainer(selectedEl);
+ if (!scrollContainer) return;
+ scrollContainer.scrollTo({
+ top: selectedEl.offsetTop - scrollContainer.clientHeight / 2 + selectedEl.clientHeight / 2,
+ behavior: 'instant',
+ });
+ }
+ });
+ }
+}
</script>
<style lang="scss" scoped>
@@ -184,5 +305,52 @@ defineProps<{
}
}
}
+
+ .searchResultItem {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ box-sizing: border-box;
+ padding: 9px 16px 9px 8px;
+ border-radius: 9px;
+ font-size: 0.9em;
+
+ &:hover {
+ text-decoration: none;
+ background: var(--MI_THEME-panelHighlight);
+ }
+
+ &.selected {
+ outline: 2px solid var(--MI_THEME-focus);
+ }
+
+ &:focus-visible,
+ &.selected {
+ outline-offset: -2px;
+ }
+
+ &.active {
+ color: var(--MI_THEME-accent);
+ background: var(--MI_THEME-accentedBg);
+ }
+
+ &.danger {
+ color: var(--MI_THEME-error);
+ }
+
+ > .icon {
+ width: 32px;
+ margin-right: 2px;
+ flex-shrink: 0;
+ text-align: center;
+ opacity: 0.8;
+ }
+
+ > .text {
+ white-space: normal;
+ padding-right: 12px;
+ flex-shrink: 1;
+ }
+ }
}
</style>
diff --git a/packages/frontend/src/components/global/SearchKeyword.vue b/packages/frontend/src/components/global/SearchKeyword.vue
new file mode 100644
index 0000000000..27a284faf0
--- /dev/null
+++ b/packages/frontend/src/components/global/SearchKeyword.vue
@@ -0,0 +1,14 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<slot></slot>
+</template>
+
+<script lang="ts" setup>
+</script>
+
+<style lang="scss" module>
+</style>
diff --git a/packages/frontend/src/components/global/SearchLabel.vue b/packages/frontend/src/components/global/SearchLabel.vue
new file mode 100644
index 0000000000..27a284faf0
--- /dev/null
+++ b/packages/frontend/src/components/global/SearchLabel.vue
@@ -0,0 +1,14 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<slot></slot>
+</template>
+
+<script lang="ts" setup>
+</script>
+
+<style lang="scss" module>
+</style>
diff --git a/packages/frontend/src/components/global/SearchMarker.vue b/packages/frontend/src/components/global/SearchMarker.vue
new file mode 100644
index 0000000000..c5ec626cf4
--- /dev/null
+++ b/packages/frontend/src/components/global/SearchMarker.vue
@@ -0,0 +1,116 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<div ref="root" :class="[$style.root, { [$style.highlighted]: highlighted }]">
+ <slot></slot>
+</div>
+</template>
+
+<script lang="ts" setup>
+import {
+ onActivated,
+ onDeactivated,
+ onMounted,
+ onBeforeUnmount,
+ watch,
+ computed,
+ ref,
+ useTemplateRef,
+ inject,
+} from 'vue';
+import type { Ref } from 'vue';
+
+const props = defineProps<{
+ markerId?: string;
+ label?: string;
+ icon?: string;
+ keywords?: string[];
+ children?: string[];
+ inlining?: string[];
+}>();
+
+const rootEl = useTemplateRef('root');
+const rootElMutationObserver = new MutationObserver(() => {
+ checkChildren();
+});
+const injectedSearchMarkerId = inject<Ref<string | null>>('inAppSearchMarkerId');
+const searchMarkerId = computed(() => injectedSearchMarkerId?.value ?? window.location.hash.slice(1));
+const highlighted = ref(props.markerId === searchMarkerId.value);
+
+function checkChildren() {
+ if (props.children?.includes(searchMarkerId.value)) {
+ const el = document.querySelector(`[data-in-app-search-marker-id="${searchMarkerId.value}"]`);
+ highlighted.value = el == null;
+ }
+}
+
+watch([
+ searchMarkerId,
+ () => props.children,
+], () => {
+ if (props.children != null && props.children.length > 0) {
+ checkChildren();
+ }
+}, { flush: 'post' });
+
+function init() {
+ checkChildren();
+
+ if (highlighted.value) {
+ rootEl.value?.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center',
+ });
+ }
+
+ if (rootEl.value != null) {
+ rootElMutationObserver.observe(rootEl.value, {
+ childList: true,
+ subtree: true,
+ });
+ }
+}
+
+function dispose() {
+ rootElMutationObserver.disconnect();
+}
+
+onMounted(init);
+onActivated(init);
+onDeactivated(dispose);
+onBeforeUnmount(dispose);
+</script>
+
+<style lang="scss" module>
+.root {
+ position: relative;
+}
+
+.highlighted {
+ &::after {
+ content: '';
+ position: absolute;
+ top: -8px;
+ left: -8px;
+ width: calc(100% + 16px);
+ height: calc(100% + 16px);
+ border-radius: 6px;
+ animation: blink 1s 3.5;
+ pointer-events: none;
+ }
+}
+
+@keyframes blink {
+ 0%, 100% {
+ background: color(from var(--MI_THEME-accent) srgb r g b / 0.05);
+ border: 1px solid color(from var(--MI_THEME-accent) srgb r g b / 0.7);
+ }
+ 50% {
+ background: transparent;
+ border: 1px solid transparent;
+ }
+}
+</style>
diff --git a/packages/frontend/src/components/index.ts b/packages/frontend/src/components/index.ts
index 0252bf0252..ebbad3e5b8 100644
--- a/packages/frontend/src/components/index.ts
+++ b/packages/frontend/src/components/index.ts
@@ -3,8 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import type { App } from 'vue';
-
import Mfm from './global/MkMfm.js';
import MkA from './global/MkA.vue';
import MkAcct from './global/MkAcct.vue';
@@ -26,6 +24,11 @@ import MkSpacer from './global/MkSpacer.vue';
import MkFooterSpacer from './global/MkFooterSpacer.vue';
import MkStickyContainer from './global/MkStickyContainer.vue';
import MkLazy from './global/MkLazy.vue';
+import SearchMarker from './global/SearchMarker.vue';
+import SearchLabel from './global/SearchLabel.vue';
+import SearchKeyword from './global/SearchKeyword.vue';
+
+import type { App } from 'vue';
export default function(app: App) {
for (const [key, value] of Object.entries(components)) {
@@ -55,6 +58,9 @@ export const components = {
MkFooterSpacer: MkFooterSpacer,
MkStickyContainer: MkStickyContainer,
MkLazy: MkLazy,
+ SearchMarker: SearchMarker,
+ SearchLabel: SearchLabel,
+ SearchKeyword: SearchKeyword,
};
declare module '@vue/runtime-core' {
@@ -80,5 +86,8 @@ declare module '@vue/runtime-core' {
MkFooterSpacer: typeof MkFooterSpacer;
MkStickyContainer: typeof MkStickyContainer;
MkLazy: typeof MkLazy;
+ SearchMarker: typeof SearchMarker;
+ SearchLabel: typeof SearchLabel;
+ SearchKeyword: typeof SearchKeyword;
}
}
diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue
index 776f59dda3..806599e801 100644
--- a/packages/frontend/src/pages/settings/2fa.vue
+++ b/packages/frontend/src/pages/settings/2fa.vue
@@ -4,74 +4,82 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<FormSection :first="first">
- <template #label>{{ i18n.ts['2fa'] }}</template>
+<SearchMarker markerId="2fa" :keywords="['2fa']">
+ <FormSection :first="first">
+ <template #label><SearchLabel>{{ i18n.ts['2fa'] }}</SearchLabel></template>
- <div v-if="$i" class="_gaps_s">
- <MkInfo v-if="$i.twoFactorEnabled && $i.twoFactorBackupCodesStock === 'partial'" warn>
- {{ i18n.ts._2fa.backupCodeUsedWarning }}
- </MkInfo>
- <MkInfo v-if="$i.twoFactorEnabled && $i.twoFactorBackupCodesStock === 'none'" warn>
- {{ i18n.ts._2fa.backupCodesExhaustedWarning }}
- </MkInfo>
+ <div v-if="$i" class="_gaps_s">
+ <MkInfo v-if="$i.twoFactorEnabled && $i.twoFactorBackupCodesStock === 'partial'" warn>
+ {{ i18n.ts._2fa.backupCodeUsedWarning }}
+ </MkInfo>
+ <MkInfo v-if="$i.twoFactorEnabled && $i.twoFactorBackupCodesStock === 'none'" warn>
+ {{ i18n.ts._2fa.backupCodesExhaustedWarning }}
+ </MkInfo>
- <MkFolder :defaultOpen="true">
- <template #icon><i class="ti ti-shield-lock"></i></template>
- <template #label>{{ i18n.ts.totp }}</template>
- <template #caption>{{ i18n.ts.totpDescription }}</template>
- <template #suffix><i v-if="$i.twoFactorEnabled" class="ti ti-check" style="color: var(--MI_THEME-success)"></i></template>
+ <SearchMarker :keywords="['totp', 'app']">
+ <MkFolder :defaultOpen="true">
+ <template #icon><i class="ti ti-shield-lock"></i></template>
+ <template #label><SearchLabel>{{ i18n.ts.totp }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.totpDescription }}</SearchKeyword></template>
+ <template #suffix><i v-if="$i.twoFactorEnabled" class="ti ti-check" style="color: var(--MI_THEME-success)"></i></template>
- <div v-if="$i.twoFactorEnabled" class="_gaps_s">
- <div v-text="i18n.ts._2fa.alreadyRegistered"/>
- <template v-if="$i.securityKeysList.length > 0">
- <MkButton @click="renewTOTP">{{ i18n.ts._2fa.renewTOTP }}</MkButton>
- <MkInfo>{{ i18n.ts._2fa.whyTOTPOnlyRenew }}</MkInfo>
- </template>
- <MkButton v-else danger @click="unregisterTOTP">{{ i18n.ts.unregister }}</MkButton>
- </div>
+ <div v-if="$i.twoFactorEnabled" class="_gaps_s">
+ <div v-text="i18n.ts._2fa.alreadyRegistered"/>
+ <template v-if="$i.securityKeysList.length > 0">
+ <MkButton @click="renewTOTP">{{ i18n.ts._2fa.renewTOTP }}</MkButton>
+ <MkInfo>{{ i18n.ts._2fa.whyTOTPOnlyRenew }}</MkInfo>
+ </template>
+ <MkButton v-else danger @click="unregisterTOTP">{{ i18n.ts.unregister }}</MkButton>
+ </div>
- <div v-else-if="!$i.twoFactorEnabled" class="_gaps_s">
- <MkButton primary gradate @click="registerTOTP">{{ i18n.ts._2fa.registerTOTP }}</MkButton>
- <MkLink url="https://misskey-hub.net/docs/for-users/stepped-guides/how-to-enable-2fa/" target="_blank"><i class="ti ti-help-circle"></i> {{ i18n.ts.learnMore }}</MkLink>
- </div>
- </MkFolder>
+ <div v-else-if="!$i.twoFactorEnabled" class="_gaps_s">
+ <MkButton primary gradate @click="registerTOTP">{{ i18n.ts._2fa.registerTOTP }}</MkButton>
+ <MkLink url="https://misskey-hub.net/docs/for-users/stepped-guides/how-to-enable-2fa/" target="_blank"><i class="ti ti-help-circle"></i> {{ i18n.ts.learnMore }}</MkLink>
+ </div>
+ </MkFolder>
+ </SearchMarker>
- <MkFolder>
- <template #icon><i class="ti ti-key"></i></template>
- <template #label>{{ i18n.ts.securityKeyAndPasskey }}</template>
- <div class="_gaps_s">
- <MkInfo>
- {{ i18n.ts._2fa.securityKeyInfo }}
- </MkInfo>
+ <SearchMarker :keywords="['security', 'key', 'passkey']">
+ <MkFolder>
+ <template #icon><i class="ti ti-key"></i></template>
+ <template #label><SearchLabel>{{ i18n.ts.securityKeyAndPasskey }}</SearchLabel></template>
+ <div class="_gaps_s">
+ <MkInfo>
+ {{ i18n.ts._2fa.securityKeyInfo }}
+ </MkInfo>
- <MkInfo v-if="!webAuthnSupported()" warn>
- {{ i18n.ts._2fa.securityKeyNotSupported }}
- </MkInfo>
+ <MkInfo v-if="!webAuthnSupported()" warn>
+ {{ i18n.ts._2fa.securityKeyNotSupported }}
+ </MkInfo>
- <MkInfo v-else-if="webAuthnSupported() && !$i.twoFactorEnabled" warn>
- {{ i18n.ts._2fa.registerTOTPBeforeKey }}
- </MkInfo>
+ <MkInfo v-else-if="webAuthnSupported() && !$i.twoFactorEnabled" warn>
+ {{ i18n.ts._2fa.registerTOTPBeforeKey }}
+ </MkInfo>
- <template v-else>
- <MkButton primary @click="addSecurityKey">{{ i18n.ts._2fa.registerSecurityKey }}</MkButton>
- <MkFolder v-for="key in $i.securityKeysList" :key="key.id">
- <template #label>{{ key.name }}</template>
- <template #suffix><I18n :src="i18n.ts.lastUsedAt"><template #t><MkTime :time="key.lastUsed"/></template></I18n></template>
- <div class="_buttons">
- <MkButton @click="renameKey(key)"><i class="ti ti-forms"></i> {{ i18n.ts.rename }}</MkButton>
- <MkButton danger @click="unregisterKey(key)"><i class="ti ti-trash"></i> {{ i18n.ts.unregister }}</MkButton>
- </div>
- </MkFolder>
- </template>
- </div>
- </MkFolder>
+ <template v-else>
+ <MkButton primary @click="addSecurityKey">{{ i18n.ts._2fa.registerSecurityKey }}</MkButton>
+ <MkFolder v-for="key in $i.securityKeysList" :key="key.id">
+ <template #label>{{ key.name }}</template>
+ <template #suffix><I18n :src="i18n.ts.lastUsedAt"><template #t><MkTime :time="key.lastUsed"/></template></I18n></template>
+ <div class="_buttons">
+ <MkButton @click="renameKey(key)"><i class="ti ti-forms"></i> {{ i18n.ts.rename }}</MkButton>
+ <MkButton danger @click="unregisterKey(key)"><i class="ti ti-trash"></i> {{ i18n.ts.unregister }}</MkButton>
+ </div>
+ </MkFolder>
+ </template>
+ </div>
+ </MkFolder>
+ </SearchMarker>
- <MkSwitch :disabled="!$i.twoFactorEnabled || $i.securityKeysList.length === 0" :modelValue="usePasswordLessLogin" @update:modelValue="v => updatePasswordLessLogin(v)">
- <template #label>{{ i18n.ts.passwordLessLogin }}</template>
- <template #caption>{{ i18n.ts.passwordLessLoginDescription }}</template>
- </MkSwitch>
- </div>
-</FormSection>
+ <SearchMarker :keywords="['password', 'less', 'key', 'passkey', 'login', 'signin']">
+ <MkSwitch :disabled="!$i.twoFactorEnabled || $i.securityKeysList.length === 0" :modelValue="usePasswordLessLogin" @update:modelValue="v => updatePasswordLessLogin(v)">
+ <template #label><SearchLabel>{{ i18n.ts.passwordLessLogin }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.passwordLessLoginDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+ </FormSection>
+</SearchMarker>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/pages/settings/accessibility.vue b/packages/frontend/src/pages/settings/accessibility.vue
new file mode 100644
index 0000000000..b703be1fe1
--- /dev/null
+++ b/packages/frontend/src/pages/settings/accessibility.vue
@@ -0,0 +1,91 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<SearchMarker path="/settings/accessibility" :label="i18n.ts.accessibility" :keywords="['accessibility']" icon="ti ti-accessible">
+ <div class="_gaps_m">
+ <div class="_gaps_s">
+ <SearchMarker :keywords="['animation', 'motion', 'reduce']">
+ <MkSwitch v-model="reduceAnimation">
+ <template #label><SearchLabel>{{ i18n.ts.reduceUiAnimation }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['disable', 'animation', 'image', 'photo', 'picture', 'media', 'thumbnail', 'gif']">
+ <MkSwitch v-model="disableShowingAnimatedImages">
+ <template #label><SearchLabel>{{ i18n.ts.disableShowingAnimatedImages }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['mfm', 'enable', 'show', 'animated']">
+ <MkSwitch v-model="animatedMfm">
+ <template #label><SearchLabel>{{ i18n.ts.enableAnimatedMfm }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['swipe', 'horizontal', 'tab']">
+ <MkSwitch v-model="enableHorizontalSwipe">
+ <template #label><SearchLabel>{{ i18n.ts.enableHorizontalSwipe }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['keep', 'screen', 'display', 'on']">
+ <MkSwitch v-model="keepScreenOn">
+ <template #label><SearchLabel>{{ i18n.ts.keepScreenOn }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['native', 'system', 'video', 'audio', 'player', 'media']">
+ <MkSwitch v-model="useNativeUIForVideoAudioPlayer">
+ <template #label><SearchLabel>{{ i18n.ts.useNativeUIForVideoAudioPlayer }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+
+ <SearchMarker :keywords="['contextmenu', 'system', 'native']">
+ <MkSelect v-model="contextMenu">
+ <template #label><SearchLabel>{{ i18n.ts._contextMenu.title }}</SearchLabel></template>
+ <option value="app">{{ i18n.ts._contextMenu.app }}</option>
+ <option value="appWithShift">{{ i18n.ts._contextMenu.appWithShift }}</option>
+ <option value="native">{{ i18n.ts._contextMenu.native }}</option>
+ </MkSelect>
+ </SearchMarker>
+ </div>
+</SearchMarker>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref, watch } from 'vue';
+import MkSwitch from '@/components/MkSwitch.vue';
+import MkSelect from '@/components/MkSelect.vue';
+import { defaultStore } from '@/store.js';
+import { reloadAsk } from '@/scripts/reload-ask.js';
+import { i18n } from '@/i18n.js';
+import { definePageMetadata } from '@/scripts/page-metadata.js';
+
+const reduceAnimation = computed(defaultStore.makeGetterSetter('animation', v => !v, v => !v));
+const animatedMfm = computed(defaultStore.makeGetterSetter('animatedMfm'));
+const disableShowingAnimatedImages = computed(defaultStore.makeGetterSetter('disableShowingAnimatedImages'));
+const keepScreenOn = computed(defaultStore.makeGetterSetter('keepScreenOn'));
+const enableHorizontalSwipe = computed(defaultStore.makeGetterSetter('enableHorizontalSwipe'));
+const useNativeUIForVideoAudioPlayer = computed(defaultStore.makeGetterSetter('useNativeUIForVideoAudioPlayer'));
+const contextMenu = computed(defaultStore.makeGetterSetter('contextMenu'));
+
+watch([
+ keepScreenOn,
+ contextMenu,
+], async () => {
+ await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
+});
+
+const headerActions = computed(() => []);
+
+const headerTabs = computed(() => []);
+
+definePageMetadata(() => ({
+ title: i18n.ts.accessibility,
+ icon: 'ti ti-accessible',
+}));
+</script>
diff --git a/packages/frontend/src/pages/settings/appearance.vue b/packages/frontend/src/pages/settings/appearance.vue
new file mode 100644
index 0000000000..465c2a38c2
--- /dev/null
+++ b/packages/frontend/src/pages/settings/appearance.vue
@@ -0,0 +1,287 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<SearchMarker path="/settings/appearance" :label="i18n.ts.appearance" :keywords="['appearance']" icon="ti ti-device-desktop">
+ <div class="_gaps_m">
+ <FormSection first>
+ <div class="_gaps_m">
+ <div class="_gaps_s">
+ <SearchMarker :keywords="['blur']">
+ <MkSwitch v-model="useBlurEffect">
+ <template #label><SearchLabel>{{ i18n.ts.useBlurEffect }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['blur', 'modal']">
+ <MkSwitch v-model="useBlurEffectForModal">
+ <template #label><SearchLabel>{{ i18n.ts.useBlurEffectForModal }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['highlight', 'sensitive', 'nsfw', 'image', 'photo', 'picture', 'media', 'thumbnail']">
+ <MkSwitch v-model="highlightSensitiveMedia">
+ <template #label><SearchLabel>{{ i18n.ts.highlightSensitiveMedia }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['avatar', 'icon', 'square']">
+ <MkSwitch v-model="squareAvatars">
+ <template #label><SearchLabel>{{ i18n.ts.squareAvatars }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['avatar', 'icon', 'decoration', 'show']">
+ <MkSwitch v-model="showAvatarDecorations">
+ <template #label><SearchLabel>{{ i18n.ts.showAvatarDecorations }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['note', 'timeline', 'gap']">
+ <MkSwitch v-model="showGapBetweenNotesInTimeline">
+ <template #label><SearchLabel>{{ i18n.ts.showGapBetweenNotesInTimeline }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['font', 'system', 'native']">
+ <MkSwitch v-model="useSystemFont">
+ <template #label><SearchLabel>{{ i18n.ts.useSystemFont }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['effect', 'show']">
+ <MkSwitch v-model="enableSeasonalScreenEffect">
+ <template #label><SearchLabel>{{ i18n.ts.seasonalScreenEffect }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+
+ <SearchMarker :keywords="['menu', 'style', 'popup', 'drawer']">
+ <MkSelect v-model="menuStyle">
+ <template #label><SearchLabel>{{ i18n.ts.menuStyle }}</SearchLabel></template>
+ <option value="auto">{{ i18n.ts.auto }}</option>
+ <option value="popup">{{ i18n.ts.popup }}</option>
+ <option value="drawer">{{ i18n.ts.drawer }}</option>
+ </MkSelect>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['emoji', 'style', 'native', 'system', 'fluent', 'twemoji']">
+ <div>
+ <MkRadios v-model="emojiStyle">
+ <template #label><SearchLabel>{{ i18n.ts.emojiStyle }}</SearchLabel></template>
+ <option value="native">{{ i18n.ts.native }}</option>
+ <option value="fluentEmoji">Fluent Emoji</option>
+ <option value="twemoji">Twemoji</option>
+ </MkRadios>
+ <div style="margin: 8px 0 0 0; font-size: 1.5em;"><Mfm :key="emojiStyle" text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></div>
+ </div>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['font', 'size']">
+ <MkRadios v-model="fontSize">
+ <template #label><SearchLabel>{{ i18n.ts.fontSize }}</SearchLabel></template>
+ <option :value="null"><span style="font-size: 14px;">Aa</span></option>
+ <option value="1"><span style="font-size: 15px;">Aa</span></option>
+ <option value="2"><span style="font-size: 16px;">Aa</span></option>
+ <option value="3"><span style="font-size: 17px;">Aa</span></option>
+ </MkRadios>
+ </SearchMarker>
+ </div>
+ </FormSection>
+
+ <SearchMarker :keywords="['note', 'display']">
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.displayOfNote }}</SearchLabel></template>
+
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['reaction', 'size', 'scale', 'display']">
+ <MkRadios v-model="reactionsDisplaySize">
+ <template #label><SearchLabel>{{ i18n.ts.reactionsDisplaySize }}</SearchLabel></template>
+ <option value="small">{{ i18n.ts.small }}</option>
+ <option value="medium">{{ i18n.ts.medium }}</option>
+ <option value="large">{{ i18n.ts.large }}</option>
+ </MkRadios>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['reaction', 'size', 'scale', 'display', 'width', 'limit']">
+ <MkSwitch v-model="limitWidthOfReaction">
+ <template #label><SearchLabel>{{ i18n.ts.limitWidthOfReaction }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['attachment', 'image', 'photo', 'picture', 'media', 'thumbnail', 'list', 'size', 'height']">
+ <MkRadios v-model="mediaListWithOneImageAppearance">
+ <template #label><SearchLabel>{{ i18n.ts.mediaListWithOneImageAppearance }}</SearchLabel></template>
+ <option value="expand">{{ i18n.ts.default }}</option>
+ <option value="16_9">{{ i18n.tsx.limitTo({ x: '16:9' }) }}</option>
+ <option value="1_1">{{ i18n.tsx.limitTo({ x: '1:1' }) }}</option>
+ <option value="2_3">{{ i18n.tsx.limitTo({ x: '2:3' }) }}</option>
+ </MkRadios>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['ticker', 'information', 'label', 'instance', 'server', 'host', 'federation']">
+ <MkSelect v-if="instance.federation !== 'none'" v-model="instanceTicker">
+ <template #label><SearchLabel>{{ i18n.ts.instanceTicker }}</SearchLabel></template>
+ <option value="none">{{ i18n.ts._instanceTicker.none }}</option>
+ <option value="remote">{{ i18n.ts._instanceTicker.remote }}</option>
+ <option value="always">{{ i18n.ts._instanceTicker.always }}</option>
+ </MkSelect>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['attachment', 'image', 'photo', 'picture', 'media', 'thumbnail', 'nsfw', 'sensitive', 'display', 'show', 'hide', 'visibility']">
+ <MkSelect v-model="nsfw">
+ <template #label><SearchLabel>{{ i18n.ts.displayOfSensitiveMedia }}</SearchLabel></template>
+ <option value="respect">{{ i18n.ts._displayOfSensitiveMedia.respect }}</option>
+ <option value="ignore">{{ i18n.ts._displayOfSensitiveMedia.ignore }}</option>
+ <option value="force">{{ i18n.ts._displayOfSensitiveMedia.force }}</option>
+ </MkSelect>
+ </SearchMarker>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['notification', 'display']">
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.notificationDisplay }}</SearchLabel></template>
+
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['position']">
+ <MkRadios v-model="notificationPosition">
+ <template #label><SearchLabel>{{ i18n.ts.position }}</SearchLabel></template>
+ <option value="leftTop"><i class="ti ti-align-box-left-top"></i> {{ i18n.ts.leftTop }}</option>
+ <option value="rightTop"><i class="ti ti-align-box-right-top"></i> {{ i18n.ts.rightTop }}</option>
+ <option value="leftBottom"><i class="ti ti-align-box-left-bottom"></i> {{ i18n.ts.leftBottom }}</option>
+ <option value="rightBottom"><i class="ti ti-align-box-right-bottom"></i> {{ i18n.ts.rightBottom }}</option>
+ </MkRadios>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['stack', 'axis', 'direction']">
+ <MkRadios v-model="notificationStackAxis">
+ <template #label><SearchLabel>{{ i18n.ts.stackAxis }}</SearchLabel></template>
+ <option value="vertical"><i class="ti ti-carousel-vertical"></i> {{ i18n.ts.vertical }}</option>
+ <option value="horizontal"><i class="ti ti-carousel-horizontal"></i> {{ i18n.ts.horizontal }}</option>
+ </MkRadios>
+ </SearchMarker>
+
+ <MkButton @click="testNotification">{{ i18n.ts._notification.checkNotificationBehavior }}</MkButton>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <FormSection>
+ <FormLink to="/settings/custom-css"><template #icon><i class="ti ti-code"></i></template>{{ i18n.ts.customCss }}</FormLink>
+ </FormSection>
+ </div>
+</SearchMarker>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref, watch } from 'vue';
+import * as Misskey from 'misskey-js';
+import MkSwitch from '@/components/MkSwitch.vue';
+import MkSelect from '@/components/MkSelect.vue';
+import MkRadios from '@/components/MkRadios.vue';
+import { defaultStore } from '@/store.js';
+import { reloadAsk } from '@/scripts/reload-ask.js';
+import { i18n } from '@/i18n.js';
+import { definePageMetadata } from '@/scripts/page-metadata.js';
+import { miLocalStorage } from '@/local-storage.js';
+import FormLink from '@/components/form/link.vue';
+import { globalEvents } from '@/events.js';
+import { claimAchievement } from '@/scripts/achievements.js';
+import MkButton from '@/components/MkButton.vue';
+import FormSection from '@/components/form/section.vue';
+import { instance } from '@/instance.js';
+
+const fontSize = ref(miLocalStorage.getItem('fontSize'));
+const useSystemFont = ref(miLocalStorage.getItem('useSystemFont') != null);
+
+const showAvatarDecorations = computed(defaultStore.makeGetterSetter('showAvatarDecorations'));
+const emojiStyle = computed(defaultStore.makeGetterSetter('emojiStyle'));
+const menuStyle = computed(defaultStore.makeGetterSetter('menuStyle'));
+const useBlurEffectForModal = computed(defaultStore.makeGetterSetter('useBlurEffectForModal'));
+const useBlurEffect = computed(defaultStore.makeGetterSetter('useBlurEffect'));
+const highlightSensitiveMedia = computed(defaultStore.makeGetterSetter('highlightSensitiveMedia'));
+const squareAvatars = computed(defaultStore.makeGetterSetter('squareAvatars'));
+const enableSeasonalScreenEffect = computed(defaultStore.makeGetterSetter('enableSeasonalScreenEffect'));
+const showGapBetweenNotesInTimeline = computed(defaultStore.makeGetterSetter('showGapBetweenNotesInTimeline'));
+const mediaListWithOneImageAppearance = computed(defaultStore.makeGetterSetter('mediaListWithOneImageAppearance'));
+const reactionsDisplaySize = computed(defaultStore.makeGetterSetter('reactionsDisplaySize'));
+const limitWidthOfReaction = computed(defaultStore.makeGetterSetter('limitWidthOfReaction'));
+const notificationPosition = computed(defaultStore.makeGetterSetter('notificationPosition'));
+const notificationStackAxis = computed(defaultStore.makeGetterSetter('notificationStackAxis'));
+const nsfw = computed(defaultStore.makeGetterSetter('nsfw'));
+const instanceTicker = computed(defaultStore.makeGetterSetter('instanceTicker'));
+
+watch(fontSize, () => {
+ if (fontSize.value == null) {
+ miLocalStorage.removeItem('fontSize');
+ } else {
+ miLocalStorage.setItem('fontSize', fontSize.value);
+ }
+});
+
+watch(useSystemFont, () => {
+ if (useSystemFont.value) {
+ miLocalStorage.setItem('useSystemFont', 't');
+ } else {
+ miLocalStorage.removeItem('useSystemFont');
+ }
+});
+
+watch([
+ fontSize,
+ useSystemFont,
+ squareAvatars,
+ highlightSensitiveMedia,
+ enableSeasonalScreenEffect,
+ showGapBetweenNotesInTimeline,
+ mediaListWithOneImageAppearance,
+ reactionsDisplaySize,
+ limitWidthOfReaction,
+ mediaListWithOneImageAppearance,
+ reactionsDisplaySize,
+ limitWidthOfReaction,
+ instanceTicker,
+], async () => {
+ await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
+});
+
+let smashCount = 0;
+let smashTimer: number | null = null;
+
+function testNotification(): void {
+ const notification: Misskey.entities.Notification = {
+ id: Math.random().toString(),
+ createdAt: new Date().toUTCString(),
+ isRead: false,
+ type: 'test',
+ };
+
+ globalEvents.emit('clientNotification', notification);
+
+ // セルフ通知破壊 実績関連
+ smashCount++;
+ if (smashCount >= 10) {
+ claimAchievement('smashTestNotificationButton');
+ smashCount = 0;
+ }
+ if (smashTimer) {
+ clearTimeout(smashTimer);
+ }
+ smashTimer = window.setTimeout(() => {
+ smashCount = 0;
+ }, 300);
+}
+
+const headerActions = computed(() => []);
+
+const headerTabs = computed(() => []);
+
+definePageMetadata(() => ({
+ title: i18n.ts.appearance,
+ icon: 'ti ti-device-desktop',
+}));
+</script>
diff --git a/packages/frontend/src/pages/settings/avatar-decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.vue
index 9fca306f9f..79be2b9b1e 100644
--- a/packages/frontend/src/pages/settings/avatar-decoration.vue
+++ b/packages/frontend/src/pages/settings/avatar-decoration.vue
@@ -4,44 +4,46 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div>
- <div v-if="!loading" class="_gaps">
- <MkInfo>{{ i18n.tsx._profile.avatarDecorationMax({ max: $i.policies.avatarDecorationLimit }) }} ({{ i18n.tsx.remainingN({ n: $i.policies.avatarDecorationLimit - $i.avatarDecorations.length }) }})</MkInfo>
+<SearchMarker path="/settings/avatar-decoration" :label="i18n.ts.avatarDecorations" :keywords="['avatar', 'icon', 'decoration']" icon="ti ti-sparkles">
+ <div>
+ <div v-if="!loading" class="_gaps">
+ <MkInfo>{{ i18n.tsx._profile.avatarDecorationMax({ max: $i.policies.avatarDecorationLimit }) }} ({{ i18n.tsx.remainingN({ n: $i.policies.avatarDecorationLimit - $i.avatarDecorations.length }) }})</MkInfo>
- <MkAvatar :class="$style.avatar" :user="$i" forceShowDecoration/>
+ <MkAvatar :class="$style.avatar" :user="$i" forceShowDecoration/>
- <div v-if="$i.avatarDecorations.length > 0" v-panel :class="$style.current" class="_gaps_s">
- <div>{{ i18n.ts.inUse }}</div>
+ <div v-if="$i.avatarDecorations.length > 0" v-panel :class="$style.current" class="_gaps_s">
+ <div>{{ i18n.ts.inUse }}</div>
+
+ <div :class="$style.decorations">
+ <XDecoration
+ v-for="(avatarDecoration, i) in $i.avatarDecorations"
+ :decoration="avatarDecorations.find(d => d.id === avatarDecoration.id)"
+ :angle="avatarDecoration.angle"
+ :flipH="avatarDecoration.flipH"
+ :offsetX="avatarDecoration.offsetX"
+ :offsetY="avatarDecoration.offsetY"
+ :active="true"
+ @click="openDecoration(avatarDecoration, i)"
+ />
+ </div>
+
+ <MkButton danger @click="detachAllDecorations">{{ i18n.ts.detachAll }}</MkButton>
+ </div>
<div :class="$style.decorations">
<XDecoration
- v-for="(avatarDecoration, i) in $i.avatarDecorations"
- :decoration="avatarDecorations.find(d => d.id === avatarDecoration.id)"
- :angle="avatarDecoration.angle"
- :flipH="avatarDecoration.flipH"
- :offsetX="avatarDecoration.offsetX"
- :offsetY="avatarDecoration.offsetY"
- :active="true"
- @click="openDecoration(avatarDecoration, i)"
+ v-for="avatarDecoration in avatarDecorations"
+ :key="avatarDecoration.id"
+ :decoration="avatarDecoration"
+ @click="openDecoration(avatarDecoration)"
/>
</div>
-
- <MkButton danger @click="detachAllDecorations">{{ i18n.ts.detachAll }}</MkButton>
</div>
-
- <div :class="$style.decorations">
- <XDecoration
- v-for="avatarDecoration in avatarDecorations"
- :key="avatarDecoration.id"
- :decoration="avatarDecoration"
- @click="openDecoration(avatarDecoration)"
- />
+ <div v-else>
+ <MkLoading/>
</div>
</div>
- <div v-else>
- <MkLoading/>
- </div>
-</div>
+</SearchMarker>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/pages/settings/drive.vue b/packages/frontend/src/pages/settings/drive.vue
index 0e66b93f1c..0138aac1c5 100644
--- a/packages/frontend/src/pages/settings/drive.vue
+++ b/packages/frontend/src/pages/settings/drive.vue
@@ -4,60 +4,81 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m">
- <FormSection v-if="!fetching" first>
- <template #label>{{ i18n.ts.usageAmount }}</template>
+<SearchMarker path="/settings/drive" :label="i18n.ts.drive" :keywords="['drive']" icon="ti ti-cloud">
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['capacity', 'usage']">
+ <FormSection first>
+ <template #label><SearchLabel>{{ i18n.ts.usageAmount }}</SearchLabel></template>
- <div class="_gaps_m">
- <div>
- <div :class="$style.meter"><div :class="$style.meterValue" :style="meterStyle"></div></div>
- </div>
- <FormSplit>
- <MkKeyValue>
- <template #key>{{ i18n.ts.capacity }}</template>
- <template #value>{{ bytes(capacity, 1) }}</template>
- </MkKeyValue>
- <MkKeyValue>
- <template #key>{{ i18n.ts.inUse }}</template>
- <template #value>{{ bytes(usage, 1) }}</template>
- </MkKeyValue>
- </FormSplit>
- </div>
- </FormSection>
+ <div v-if="!fetching" class="_gaps_m">
+ <div>
+ <div :class="$style.meter"><div :class="$style.meterValue" :style="meterStyle"></div></div>
+ </div>
+ <FormSplit>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.capacity }}</template>
+ <template #value>{{ bytes(capacity, 1) }}</template>
+ </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.inUse }}</template>
+ <template #value>{{ bytes(usage, 1) }}</template>
+ </MkKeyValue>
+ </FormSplit>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['statistics', 'usage']">
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.statistics }}</SearchLabel></template>
+ <MkChart src="per-user-drive" :args="{ user: $i }" span="day" :limit="7 * 5" :bar="true" :stacked="true" :detailed="false" :aspectRatio="6"/>
+ </FormSection>
+ </SearchMarker>
+
+ <FormSection>
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['default', 'upload', 'folder']">
+ <FormLink @click="chooseUploadFolder()">
+ <SearchLabel>{{ i18n.ts.uploadFolder }}</SearchLabel>
+ <template #suffix>{{ uploadFolder ? uploadFolder.name : '-' }}</template>
+ <template #suffixIcon><i class="ti ti-folder"></i></template>
+ </FormLink>
+ </SearchMarker>
+
+ <FormLink to="/settings/drive/cleaner">
+ {{ i18n.ts.drivecleaner }}
+ </FormLink>
- <FormSection>
- <template #label>{{ i18n.ts.statistics }}</template>
- <MkChart src="per-user-drive" :args="{ user: $i }" span="day" :limit="7 * 5" :bar="true" :stacked="true" :detailed="false" :aspectRatio="6"/>
- </FormSection>
+ <SearchMarker :keywords="['keep', 'original', 'raw', 'upload']">
+ <MkSwitch v-model="keepOriginalUploading">
+ <template #label><SearchLabel>{{ i18n.ts.keepOriginalUploading }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.keepOriginalUploadingDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
- <FormSection>
- <div class="_gaps_m">
- <FormLink @click="chooseUploadFolder()">
- {{ i18n.ts.uploadFolder }}
- <template #suffix>{{ uploadFolder ? uploadFolder.name : '-' }}</template>
- <template #suffixIcon><i class="ti ti-folder"></i></template>
- </FormLink>
- <FormLink to="/settings/drive/cleaner">
- {{ i18n.ts.drivecleaner }}
- </FormLink>
- <MkSwitch v-model="keepOriginalUploading">
- <template #label>{{ i18n.ts.keepOriginalUploading }}</template>
- <template #caption>{{ i18n.ts.keepOriginalUploadingDescription }}</template>
- </MkSwitch>
- <MkSwitch v-model="keepOriginalFilename">
- <template #label>{{ i18n.ts.keepOriginalFilename }}</template>
- <template #caption>{{ i18n.ts.keepOriginalFilenameDescription }}</template>
- </MkSwitch>
- <MkSwitch v-model="alwaysMarkNsfw" @update:modelValue="saveProfile()">
- <template #label>{{ i18n.ts.alwaysMarkSensitive }}</template>
- </MkSwitch>
- <MkSwitch v-model="autoSensitive" @update:modelValue="saveProfile()">
- <template #label>{{ i18n.ts.enableAutoSensitive }}<span class="_beta">{{ i18n.ts.beta }}</span></template>
- <template #caption>{{ i18n.ts.enableAutoSensitiveDescription }}</template>
- </MkSwitch>
- </div>
- </FormSection>
-</div>
+ <SearchMarker :keywords="['keep', 'original', 'filename']">
+ <MkSwitch v-model="keepOriginalFilename">
+ <template #label><SearchLabel>{{ i18n.ts.keepOriginalFilename }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.keepOriginalFilenameDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['always', 'default', 'mark', 'nsfw', 'sensitive', 'media', 'file']">
+ <MkSwitch v-model="alwaysMarkNsfw" @update:modelValue="saveProfile()">
+ <template #label><SearchLabel>{{ i18n.ts.alwaysMarkSensitive }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['auto', 'nsfw', 'sensitive', 'media', 'file']">
+ <MkSwitch v-model="autoSensitive" @update:modelValue="saveProfile()">
+ <template #label><SearchLabel>{{ i18n.ts.enableAutoSensitive }}</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.enableAutoSensitiveDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+ </FormSection>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/pages/settings/email.vue b/packages/frontend/src/pages/settings/email.vue
index d452f249b6..e7a8fc5634 100644
--- a/packages/frontend/src/pages/settings/email.vue
+++ b/packages/frontend/src/pages/settings/email.vue
@@ -4,47 +4,58 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div v-if="instance.enableEmail" class="_gaps_m">
- <FormSection first>
- <template #label>{{ i18n.ts.emailAddress }}</template>
- <MkInput v-model="emailAddress" type="email" manualSave>
- <template #prefix><i class="ti ti-mail"></i></template>
- <template v-if="$i.email && !$i.emailVerified" #caption>{{ i18n.ts.verificationEmailSent }}</template>
- <template v-else-if="emailAddress === $i.email && $i.emailVerified" #caption><i class="ti ti-check" style="color: var(--MI_THEME-success);"></i> {{ i18n.ts.emailVerified }}</template>
- </MkInput>
- </FormSection>
+<SearchMarker path="/settings/email" :label="i18n.ts.email" :keywords="['email']" icon="ti ti-mail">
+ <div class="_gaps_m">
+ <MkInfo v-if="!instance.enableEmail">{{ i18n.ts.emailNotSupported }}</MkInfo>
- <FormSection>
- <MkSwitch :modelValue="$i.receiveAnnouncementEmail" @update:modelValue="onChangeReceiveAnnouncementEmail">
- {{ i18n.ts.receiveAnnouncementFromInstance }}
- </MkSwitch>
- </FormSection>
+ <MkDisableSection :disabled="!instance.enableEmail">
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['email', 'address']">
+ <FormSection first>
+ <template #label><SearchLabel>{{ i18n.ts.emailAddress }}</SearchLabel></template>
+ <MkInput v-model="emailAddress" type="email" manualSave>
+ <template #prefix><i class="ti ti-mail"></i></template>
+ <template v-if="$i.email && !$i.emailVerified" #caption>{{ i18n.ts.verificationEmailSent }}</template>
+ <template v-else-if="emailAddress === $i.email && $i.emailVerified" #caption><i class="ti ti-check" style="color: var(--MI_THEME-success);"></i> {{ i18n.ts.emailVerified }}</template>
+ </MkInput>
+ </FormSection>
+ </SearchMarker>
- <FormSection>
- <template #label>{{ i18n.ts.emailNotification }}</template>
+ <FormSection>
+ <SearchMarker :keywords="['announcement', 'email']">
+ <MkSwitch :modelValue="$i.receiveAnnouncementEmail" @update:modelValue="onChangeReceiveAnnouncementEmail">
+ <template #label><SearchLabel>{{ i18n.ts.receiveAnnouncementFromInstance }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </FormSection>
- <div class="_gaps_s">
- <MkSwitch v-model="emailNotification_mention">
- {{ i18n.ts._notification._types.mention }}
- </MkSwitch>
- <MkSwitch v-model="emailNotification_reply">
- {{ i18n.ts._notification._types.reply }}
- </MkSwitch>
- <MkSwitch v-model="emailNotification_quote">
- {{ i18n.ts._notification._types.quote }}
- </MkSwitch>
- <MkSwitch v-model="emailNotification_follow">
- {{ i18n.ts._notification._types.follow }}
- </MkSwitch>
- <MkSwitch v-model="emailNotification_receiveFollowRequest">
- {{ i18n.ts._notification._types.receiveFollowRequest }}
- </MkSwitch>
- </div>
- </FormSection>
-</div>
-<div v-if="!instance.enableEmail" class="_gaps_m">
- <MkInfo>{{ i18n.ts.emailNotSupported }}</MkInfo>
-</div>
+ <SearchMarker :keywords="['notification', 'email']">
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.emailNotification }}</SearchLabel></template>
+
+ <div class="_gaps_s">
+ <MkSwitch v-model="emailNotification_mention">
+ {{ i18n.ts._notification._types.mention }}
+ </MkSwitch>
+ <MkSwitch v-model="emailNotification_reply">
+ {{ i18n.ts._notification._types.reply }}
+ </MkSwitch>
+ <MkSwitch v-model="emailNotification_quote">
+ {{ i18n.ts._notification._types.quote }}
+ </MkSwitch>
+ <MkSwitch v-model="emailNotification_follow">
+ {{ i18n.ts._notification._types.follow }}
+ </MkSwitch>
+ <MkSwitch v-model="emailNotification_receiveFollowRequest">
+ {{ i18n.ts._notification._types.receiveFollowRequest }}
+ </MkSwitch>
+ </div>
+ </FormSection>
+ </SearchMarker>
+ </div>
+ </MkDisableSection>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
@@ -53,6 +64,7 @@ import FormSection from '@/components/form/section.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkInput from '@/components/MkInput.vue';
import MkSwitch from '@/components/MkSwitch.vue';
+import MkDisableSection from '@/components/MkDisableSection.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { signinRequired } from '@/account.js';
diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue
deleted file mode 100644
index 4449d6169f..0000000000
--- a/packages/frontend/src/pages/settings/general.vue
+++ /dev/null
@@ -1,492 +0,0 @@
-<!--
-SPDX-FileCopyrightText: syuilo and misskey-project
-SPDX-License-Identifier: AGPL-3.0-only
--->
-
-<template>
-<div class="_gaps_m">
- <MkSelect v-model="lang">
- <template #label>{{ i18n.ts.uiLanguage }}</template>
- <option v-for="x in langs" :key="x[0]" :value="x[0]">{{ x[1] }}</option>
- <template #caption>
- <I18n :src="i18n.ts.i18nInfo" tag="span">
- <template #link>
- <MkLink url="https://crowdin.com/project/misskey">Crowdin</MkLink>
- </template>
- </I18n>
- </template>
- </MkSelect>
-
- <MkRadios v-model="overridedDeviceKind">
- <template #label>{{ i18n.ts.overridedDeviceKind }}</template>
- <option :value="null">{{ i18n.ts.auto }}</option>
- <option value="smartphone"><i class="ti ti-device-mobile"/> {{ i18n.ts.smartphone }}</option>
- <option value="tablet"><i class="ti ti-device-tablet"/> {{ i18n.ts.tablet }}</option>
- <option value="desktop"><i class="ti ti-device-desktop"/> {{ i18n.ts.desktop }}</option>
- </MkRadios>
-
- <FormSection>
- <div class="_gaps_s">
- <MkSwitch v-model="showFixedPostForm">{{ i18n.ts.showFixedPostForm }}</MkSwitch>
- <MkSwitch v-model="showFixedPostFormInChannel">{{ i18n.ts.showFixedPostFormInChannel }}</MkSwitch>
- <MkFolder>
- <template #label>{{ i18n.ts.pinnedList }}</template>
- <!-- 複数ピン止め管理できるようにしたいけどめんどいので一旦ひとつのみ -->
- <MkButton v-if="defaultStore.reactiveState.pinnedUserLists.value.length === 0" @click="setPinnedList()">{{ i18n.ts.add }}</MkButton>
- <MkButton v-else danger @click="removePinnedList()"><i class="ti ti-trash"></i> {{ i18n.ts.remove }}</MkButton>
- </MkFolder>
- </div>
- </FormSection>
-
- <FormSection>
- <template #label>{{ i18n.ts.displayOfNote }}</template>
-
- <div class="_gaps_m">
- <div class="_gaps_s">
- <MkSwitch v-model="collapseRenotes">
- <template #label>{{ i18n.ts.collapseRenotes }}</template>
- <template #caption>{{ i18n.ts.collapseRenotesDescription }}</template>
- </MkSwitch>
- <MkSwitch v-model="showNoteActionsOnlyHover">{{ i18n.ts.showNoteActionsOnlyHover }}</MkSwitch>
- <MkSwitch v-model="showClipButtonInNoteFooter">{{ i18n.ts.showClipButtonInNoteFooter }}</MkSwitch>
- <MkSwitch v-model="advancedMfm">{{ i18n.ts.enableAdvancedMfm }}</MkSwitch>
- <MkSwitch v-if="advancedMfm" v-model="animatedMfm">{{ i18n.ts.enableAnimatedMfm }}</MkSwitch>
- <MkSwitch v-if="advancedMfm" v-model="enableQuickAddMfmFunction">{{ i18n.ts.enableQuickAddMfmFunction }}</MkSwitch>
- <MkSwitch v-model="showReactionsCount">{{ i18n.ts.showReactionsCount }}</MkSwitch>
- <MkSwitch v-model="showGapBetweenNotesInTimeline">{{ i18n.ts.showGapBetweenNotesInTimeline }}</MkSwitch>
- <MkSwitch v-model="loadRawImages">{{ i18n.ts.loadRawImages }}</MkSwitch>
- <MkRadios v-model="reactionsDisplaySize">
- <template #label>{{ i18n.ts.reactionsDisplaySize }}</template>
- <option value="small">{{ i18n.ts.small }}</option>
- <option value="medium">{{ i18n.ts.medium }}</option>
- <option value="large">{{ i18n.ts.large }}</option>
- </MkRadios>
- <MkSwitch v-model="limitWidthOfReaction">{{ i18n.ts.limitWidthOfReaction }}</MkSwitch>
- </div>
-
- <MkSelect v-if="instance.federation !== 'none'" v-model="instanceTicker">
- <template #label>{{ i18n.ts.instanceTicker }}</template>
- <option value="none">{{ i18n.ts._instanceTicker.none }}</option>
- <option value="remote">{{ i18n.ts._instanceTicker.remote }}</option>
- <option value="always">{{ i18n.ts._instanceTicker.always }}</option>
- </MkSelect>
-
- <MkSelect v-model="nsfw">
- <template #label>{{ i18n.ts.displayOfSensitiveMedia }}</template>
- <option value="respect">{{ i18n.ts._displayOfSensitiveMedia.respect }}</option>
- <option value="ignore">{{ i18n.ts._displayOfSensitiveMedia.ignore }}</option>
- <option value="force">{{ i18n.ts._displayOfSensitiveMedia.force }}</option>
- </MkSelect>
-
- <MkRadios v-model="mediaListWithOneImageAppearance">
- <template #label>{{ i18n.ts.mediaListWithOneImageAppearance }}</template>
- <option value="expand">{{ i18n.ts.default }}</option>
- <option value="16_9">{{ i18n.tsx.limitTo({ x: '16:9' }) }}</option>
- <option value="1_1">{{ i18n.tsx.limitTo({ x: '1:1' }) }}</option>
- <option value="2_3">{{ i18n.tsx.limitTo({ x: '2:3' }) }}</option>
- </MkRadios>
- </div>
- </FormSection>
-
- <FormSection>
- <template #label>{{ i18n.ts.notificationDisplay }}</template>
-
- <div class="_gaps_m">
- <MkSwitch v-model="useGroupedNotifications">{{ i18n.ts.useGroupedNotifications }}</MkSwitch>
-
- <MkRadios v-model="notificationPosition">
- <template #label>{{ i18n.ts.position }}</template>
- <option value="leftTop"><i class="ti ti-align-box-left-top"></i> {{ i18n.ts.leftTop }}</option>
- <option value="rightTop"><i class="ti ti-align-box-right-top"></i> {{ i18n.ts.rightTop }}</option>
- <option value="leftBottom"><i class="ti ti-align-box-left-bottom"></i> {{ i18n.ts.leftBottom }}</option>
- <option value="rightBottom"><i class="ti ti-align-box-right-bottom"></i> {{ i18n.ts.rightBottom }}</option>
- </MkRadios>
-
- <MkRadios v-model="notificationStackAxis">
- <template #label>{{ i18n.ts.stackAxis }}</template>
- <option value="vertical"><i class="ti ti-carousel-vertical"></i> {{ i18n.ts.vertical }}</option>
- <option value="horizontal"><i class="ti ti-carousel-horizontal"></i> {{ i18n.ts.horizontal }}</option>
- </MkRadios>
-
- <MkButton @click="testNotification">{{ i18n.ts._notification.checkNotificationBehavior }}</MkButton>
- </div>
- </FormSection>
-
- <FormSection>
- <template #label>{{ i18n.ts.appearance }}</template>
-
- <div class="_gaps_m">
- <div class="_gaps_s">
- <MkSwitch v-model="reduceAnimation">{{ i18n.ts.reduceUiAnimation }}</MkSwitch>
- <MkSwitch v-model="useBlurEffect">{{ i18n.ts.useBlurEffect }}</MkSwitch>
- <MkSwitch v-model="useBlurEffectForModal">{{ i18n.ts.useBlurEffectForModal }}</MkSwitch>
- <MkSwitch v-model="disableShowingAnimatedImages">{{ i18n.ts.disableShowingAnimatedImages }}</MkSwitch>
- <MkSwitch v-model="highlightSensitiveMedia">{{ i18n.ts.highlightSensitiveMedia }}</MkSwitch>
- <MkSwitch v-model="squareAvatars">{{ i18n.ts.squareAvatars }}</MkSwitch>
- <MkSwitch v-model="showAvatarDecorations">{{ i18n.ts.showAvatarDecorations }}</MkSwitch>
- <MkSwitch v-model="useSystemFont">{{ i18n.ts.useSystemFont }}</MkSwitch>
- <MkSwitch v-model="forceShowAds">{{ i18n.ts.forceShowAds }}</MkSwitch>
- <MkSwitch v-model="enableSeasonalScreenEffect">{{ i18n.ts.seasonalScreenEffect }}</MkSwitch>
- <MkSwitch v-model="useNativeUIForVideoAudioPlayer">{{ i18n.ts.useNativeUIForVideoAudioPlayer }}</MkSwitch>
- </div>
-
- <MkSelect v-model="menuStyle">
- <template #label>{{ i18n.ts.menuStyle }}</template>
- <option value="auto">{{ i18n.ts.auto }}</option>
- <option value="popup">{{ i18n.ts.popup }}</option>
- <option value="drawer">{{ i18n.ts.drawer }}</option>
- </MkSelect>
-
- <div>
- <MkRadios v-model="emojiStyle">
- <template #label>{{ i18n.ts.emojiStyle }}</template>
- <option value="native">{{ i18n.ts.native }}</option>
- <option value="fluentEmoji">Fluent Emoji</option>
- <option value="twemoji">Twemoji</option>
- </MkRadios>
- <div style="margin: 8px 0 0 0; font-size: 1.5em;"><Mfm :key="emojiStyle" text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></div>
- </div>
-
- <MkRadios v-model="fontSize">
- <template #label>{{ i18n.ts.fontSize }}</template>
- <option :value="null"><span style="font-size: 14px;">Aa</span></option>
- <option value="1"><span style="font-size: 15px;">Aa</span></option>
- <option value="2"><span style="font-size: 16px;">Aa</span></option>
- <option value="3"><span style="font-size: 17px;">Aa</span></option>
- </MkRadios>
- </div>
- </FormSection>
-
- <FormSection>
- <template #label>{{ i18n.ts.behavior }}</template>
-
- <div class="_gaps_m">
- <div class="_gaps_s">
- <MkSwitch v-model="imageNewTab">{{ i18n.ts.openImageInNewTab }}</MkSwitch>
- <MkSwitch v-model="useReactionPickerForContextMenu">{{ i18n.ts.useReactionPickerForContextMenu }}</MkSwitch>
- <MkSwitch v-model="enableInfiniteScroll">{{ i18n.ts.enableInfiniteScroll }}</MkSwitch>
- <MkSwitch v-model="keepScreenOn">{{ i18n.ts.keepScreenOn }}</MkSwitch>
- <MkSwitch v-model="disableStreamingTimeline">{{ i18n.ts.disableStreamingTimeline }}</MkSwitch>
- <MkSwitch v-model="enableHorizontalSwipe">{{ i18n.ts.enableHorizontalSwipe }}</MkSwitch>
- <MkSwitch v-model="alwaysConfirmFollow">{{ i18n.ts.alwaysConfirmFollow }}</MkSwitch>
- <MkSwitch v-model="confirmWhenRevealingSensitiveMedia">{{ i18n.ts.confirmWhenRevealingSensitiveMedia }}</MkSwitch>
- <MkSwitch v-model="confirmOnReact">{{ i18n.ts.confirmOnReact }}</MkSwitch>
- </div>
- <MkSelect v-model="serverDisconnectedBehavior">
- <template #label>{{ i18n.ts.whenServerDisconnected }}</template>
- <option value="reload">{{ i18n.ts._serverDisconnectedBehavior.reload }}</option>
- <option value="dialog">{{ i18n.ts._serverDisconnectedBehavior.dialog }}</option>
- <option value="quiet">{{ i18n.ts._serverDisconnectedBehavior.quiet }}</option>
- </MkSelect>
- <MkSelect v-model="contextMenu">
- <template #label>{{ i18n.ts._contextMenu.title }}</template>
- <option value="app">{{ i18n.ts._contextMenu.app }}</option>
- <option value="appWithShift">{{ i18n.ts._contextMenu.appWithShift }}</option>
- <option value="native">{{ i18n.ts._contextMenu.native }}</option>
- </MkSelect>
- <MkRange v-model="numberOfPageCache" :min="1" :max="10" :step="1" easing>
- <template #label>{{ i18n.ts.numberOfPageCache }}</template>
- <template #caption>{{ i18n.ts.numberOfPageCacheDescription }}</template>
- </MkRange>
-
- <MkFolder>
- <template #label>{{ i18n.ts.dataSaver }}</template>
-
- <div class="_gaps_m">
- <MkInfo>{{ i18n.ts.reloadRequiredToApplySettings }}</MkInfo>
-
- <div class="_buttons">
- <MkButton inline @click="enableAllDataSaver">{{ i18n.ts.enableAll }}</MkButton>
- <MkButton inline @click="disableAllDataSaver">{{ i18n.ts.disableAll }}</MkButton>
- </div>
- <div class="_gaps_m">
- <MkSwitch v-model="dataSaver.media">
- {{ i18n.ts._dataSaver._media.title }}
- <template #caption>{{ i18n.ts._dataSaver._media.description }}</template>
- </MkSwitch>
- <MkSwitch v-model="dataSaver.avatar">
- {{ i18n.ts._dataSaver._avatar.title }}
- <template #caption>{{ i18n.ts._dataSaver._avatar.description }}</template>
- </MkSwitch>
- <MkSwitch v-model="dataSaver.urlPreview">
- {{ i18n.ts._dataSaver._urlPreview.title }}
- <template #caption>{{ i18n.ts._dataSaver._urlPreview.description }}</template>
- </MkSwitch>
- <MkSwitch v-model="dataSaver.code">
- {{ i18n.ts._dataSaver._code.title }}
- <template #caption>{{ i18n.ts._dataSaver._code.description }}</template>
- </MkSwitch>
- </div>
- </div>
- </MkFolder>
- </div>
- </FormSection>
-
- <FormSection>
- <template #label>{{ i18n.ts.other }}</template>
-
- <div class="_gaps">
- <MkRadios v-model="hemisphere">
- <template #label>{{ i18n.ts.hemisphere }}</template>
- <option value="N">{{ i18n.ts._hemisphere.N }}</option>
- <option value="S">{{ i18n.ts._hemisphere.S }}</option>
- <template #caption>{{ i18n.ts._hemisphere.caption }}</template>
- </MkRadios>
- <MkFolder>
- <template #label>{{ i18n.ts.additionalEmojiDictionary }}</template>
- <div class="_buttons">
- <template v-for="lang in emojiIndexLangs" :key="lang">
- <MkButton v-if="defaultStore.reactiveState.additionalUnicodeEmojiIndexes.value[lang]" danger @click="removeEmojiIndex(lang)"><i class="ti ti-trash"></i> {{ i18n.ts.remove }} ({{ getEmojiIndexLangName(lang) }})</MkButton>
- <MkButton v-else @click="downloadEmojiIndex(lang)"><i class="ti ti-download"></i> {{ getEmojiIndexLangName(lang) }}{{ defaultStore.reactiveState.additionalUnicodeEmojiIndexes.value[lang] ? ` (${ i18n.ts.installed })` : '' }}</MkButton>
- </template>
- </div>
- </MkFolder>
- <FormLink to="/settings/deck">{{ i18n.ts.deck }}</FormLink>
- <FormLink to="/settings/custom-css"><template #icon><i class="ti ti-code"></i></template>{{ i18n.ts.customCss }}</FormLink>
- </div>
- </FormSection>
-</div>
-</template>
-
-<script lang="ts" setup>
-import { computed, ref, watch } from 'vue';
-import * as Misskey from 'misskey-js';
-import { langs } from '@@/js/config.js';
-import MkSwitch from '@/components/MkSwitch.vue';
-import MkSelect from '@/components/MkSelect.vue';
-import MkRadios from '@/components/MkRadios.vue';
-import MkRange from '@/components/MkRange.vue';
-import MkFolder from '@/components/MkFolder.vue';
-import MkButton from '@/components/MkButton.vue';
-import FormSection from '@/components/form/section.vue';
-import FormLink from '@/components/form/link.vue';
-import MkLink from '@/components/MkLink.vue';
-import MkInfo from '@/components/MkInfo.vue';
-import { defaultStore } from '@/store.js';
-import * as os from '@/os.js';
-import { instance } from '@/instance.js';
-import { misskeyApi } from '@/scripts/misskey-api.js';
-import { reloadAsk } from '@/scripts/reload-ask.js';
-import { i18n } from '@/i18n.js';
-import { definePageMetadata } from '@/scripts/page-metadata.js';
-import { miLocalStorage } from '@/local-storage.js';
-import { globalEvents } from '@/events.js';
-import { claimAchievement } from '@/scripts/achievements.js';
-
-const lang = ref(miLocalStorage.getItem('lang'));
-const fontSize = ref(miLocalStorage.getItem('fontSize'));
-const useSystemFont = ref(miLocalStorage.getItem('useSystemFont') != null);
-const dataSaver = ref(defaultStore.state.dataSaver);
-
-const hemisphere = computed(defaultStore.makeGetterSetter('hemisphere'));
-const overridedDeviceKind = computed(defaultStore.makeGetterSetter('overridedDeviceKind'));
-const serverDisconnectedBehavior = computed(defaultStore.makeGetterSetter('serverDisconnectedBehavior'));
-const showNoteActionsOnlyHover = computed(defaultStore.makeGetterSetter('showNoteActionsOnlyHover'));
-const showClipButtonInNoteFooter = computed(defaultStore.makeGetterSetter('showClipButtonInNoteFooter'));
-const reactionsDisplaySize = computed(defaultStore.makeGetterSetter('reactionsDisplaySize'));
-const limitWidthOfReaction = computed(defaultStore.makeGetterSetter('limitWidthOfReaction'));
-const collapseRenotes = computed(defaultStore.makeGetterSetter('collapseRenotes'));
-const reduceAnimation = computed(defaultStore.makeGetterSetter('animation', v => !v, v => !v));
-const useBlurEffectForModal = computed(defaultStore.makeGetterSetter('useBlurEffectForModal'));
-const useBlurEffect = computed(defaultStore.makeGetterSetter('useBlurEffect'));
-const showGapBetweenNotesInTimeline = computed(defaultStore.makeGetterSetter('showGapBetweenNotesInTimeline'));
-const animatedMfm = computed(defaultStore.makeGetterSetter('animatedMfm'));
-const advancedMfm = computed(defaultStore.makeGetterSetter('advancedMfm'));
-const showReactionsCount = computed(defaultStore.makeGetterSetter('showReactionsCount'));
-const enableQuickAddMfmFunction = computed(defaultStore.makeGetterSetter('enableQuickAddMfmFunction'));
-const emojiStyle = computed(defaultStore.makeGetterSetter('emojiStyle'));
-const menuStyle = computed(defaultStore.makeGetterSetter('menuStyle'));
-const disableShowingAnimatedImages = computed(defaultStore.makeGetterSetter('disableShowingAnimatedImages'));
-const forceShowAds = computed(defaultStore.makeGetterSetter('forceShowAds'));
-const loadRawImages = computed(defaultStore.makeGetterSetter('loadRawImages'));
-const highlightSensitiveMedia = computed(defaultStore.makeGetterSetter('highlightSensitiveMedia'));
-const imageNewTab = computed(defaultStore.makeGetterSetter('imageNewTab'));
-const nsfw = computed(defaultStore.makeGetterSetter('nsfw'));
-const showFixedPostForm = computed(defaultStore.makeGetterSetter('showFixedPostForm'));
-const showFixedPostFormInChannel = computed(defaultStore.makeGetterSetter('showFixedPostFormInChannel'));
-const numberOfPageCache = computed(defaultStore.makeGetterSetter('numberOfPageCache'));
-const instanceTicker = computed(defaultStore.makeGetterSetter('instanceTicker'));
-const enableInfiniteScroll = computed(defaultStore.makeGetterSetter('enableInfiniteScroll'));
-const useReactionPickerForContextMenu = computed(defaultStore.makeGetterSetter('useReactionPickerForContextMenu'));
-const squareAvatars = computed(defaultStore.makeGetterSetter('squareAvatars'));
-const showAvatarDecorations = computed(defaultStore.makeGetterSetter('showAvatarDecorations'));
-const mediaListWithOneImageAppearance = computed(defaultStore.makeGetterSetter('mediaListWithOneImageAppearance'));
-const notificationPosition = computed(defaultStore.makeGetterSetter('notificationPosition'));
-const notificationStackAxis = computed(defaultStore.makeGetterSetter('notificationStackAxis'));
-const keepScreenOn = computed(defaultStore.makeGetterSetter('keepScreenOn'));
-const disableStreamingTimeline = computed(defaultStore.makeGetterSetter('disableStreamingTimeline'));
-const useGroupedNotifications = computed(defaultStore.makeGetterSetter('useGroupedNotifications'));
-const enableSeasonalScreenEffect = computed(defaultStore.makeGetterSetter('enableSeasonalScreenEffect'));
-const enableHorizontalSwipe = computed(defaultStore.makeGetterSetter('enableHorizontalSwipe'));
-const useNativeUIForVideoAudioPlayer = computed(defaultStore.makeGetterSetter('useNativeUIForVideoAudioPlayer'));
-const alwaysConfirmFollow = computed(defaultStore.makeGetterSetter('alwaysConfirmFollow'));
-const confirmWhenRevealingSensitiveMedia = computed(defaultStore.makeGetterSetter('confirmWhenRevealingSensitiveMedia'));
-const confirmOnReact = computed(defaultStore.makeGetterSetter('confirmOnReact'));
-const contextMenu = computed(defaultStore.makeGetterSetter('contextMenu'));
-
-watch(lang, () => {
- miLocalStorage.setItem('lang', lang.value as string);
- miLocalStorage.removeItem('locale');
- miLocalStorage.removeItem('localeVersion');
-});
-
-watch(fontSize, () => {
- if (fontSize.value == null) {
- miLocalStorage.removeItem('fontSize');
- } else {
- miLocalStorage.setItem('fontSize', fontSize.value);
- }
-});
-
-watch(useSystemFont, () => {
- if (useSystemFont.value) {
- miLocalStorage.setItem('useSystemFont', 't');
- } else {
- miLocalStorage.removeItem('useSystemFont');
- }
-});
-
-watch([
- hemisphere,
- lang,
- fontSize,
- useSystemFont,
- enableInfiniteScroll,
- squareAvatars,
- showNoteActionsOnlyHover,
- showGapBetweenNotesInTimeline,
- instanceTicker,
- overridedDeviceKind,
- mediaListWithOneImageAppearance,
- reactionsDisplaySize,
- limitWidthOfReaction,
- highlightSensitiveMedia,
- keepScreenOn,
- disableStreamingTimeline,
- enableSeasonalScreenEffect,
- alwaysConfirmFollow,
- confirmWhenRevealingSensitiveMedia,
- contextMenu,
-], async () => {
- await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
-});
-
-const emojiIndexLangs = ['en-US', 'ja-JP', 'ja-JP_hira'] as const;
-
-function getEmojiIndexLangName(targetLang: typeof emojiIndexLangs[number]) {
- if (langs.find(x => x[0] === targetLang)) {
- return langs.find(x => x[0] === targetLang)![1];
- } else {
- // 絵文字辞書限定の言語定義
- switch (targetLang) {
- case 'ja-JP_hira': return 'ひらがな';
- default: return targetLang;
- }
- }
-}
-
-function downloadEmojiIndex(lang: typeof emojiIndexLangs[number]) {
- async function main() {
- const currentIndexes = defaultStore.state.additionalUnicodeEmojiIndexes;
-
- function download() {
- switch (lang) {
- case 'en-US': return import('../../unicode-emoji-indexes/en-US.json').then(x => x.default);
- case 'ja-JP': return import('../../unicode-emoji-indexes/ja-JP.json').then(x => x.default);
- case 'ja-JP_hira': return import('../../unicode-emoji-indexes/ja-JP_hira.json').then(x => x.default);
- default: throw new Error('unrecognized lang: ' + lang);
- }
- }
-
- currentIndexes[lang] = await download();
- await defaultStore.set('additionalUnicodeEmojiIndexes', currentIndexes);
- }
-
- os.promiseDialog(main());
-}
-
-function removeEmojiIndex(lang: string) {
- async function main() {
- const currentIndexes = defaultStore.state.additionalUnicodeEmojiIndexes;
- delete currentIndexes[lang];
- await defaultStore.set('additionalUnicodeEmojiIndexes', currentIndexes);
- }
-
- os.promiseDialog(main());
-}
-
-async function setPinnedList() {
- const lists = await misskeyApi('users/lists/list');
- const { canceled, result: list } = await os.select({
- title: i18n.ts.selectList,
- items: lists.map(x => ({
- value: x, text: x.name,
- })),
- });
- if (canceled) return;
-
- defaultStore.set('pinnedUserLists', [list]);
-}
-
-function removePinnedList() {
- defaultStore.set('pinnedUserLists', []);
-}
-
-let smashCount = 0;
-let smashTimer: number | null = null;
-
-function testNotification(): void {
- const notification: Misskey.entities.Notification = {
- id: Math.random().toString(),
- createdAt: new Date().toUTCString(),
- isRead: false,
- type: 'test',
- };
-
- globalEvents.emit('clientNotification', notification);
-
- // セルフ通知破壊 実績関連
- smashCount++;
- if (smashCount >= 10) {
- claimAchievement('smashTestNotificationButton');
- smashCount = 0;
- }
- if (smashTimer) {
- clearTimeout(smashTimer);
- }
- smashTimer = window.setTimeout(() => {
- smashCount = 0;
- }, 300);
-}
-
-function enableAllDataSaver() {
- const g = { ...defaultStore.state.dataSaver };
-
- Object.keys(g).forEach((key) => { g[key] = true; });
-
- dataSaver.value = g;
-}
-
-function disableAllDataSaver() {
- const g = { ...defaultStore.state.dataSaver };
-
- Object.keys(g).forEach((key) => { g[key] = false; });
-
- dataSaver.value = g;
-}
-
-watch(dataSaver, (to) => {
- defaultStore.set('dataSaver', to);
-}, {
- deep: true,
-});
-
-const headerActions = computed(() => []);
-
-const headerTabs = computed(() => []);
-
-definePageMetadata(() => ({
- title: i18n.ts.general,
- icon: 'ti ti-adjustments',
-}));
-</script>
diff --git a/packages/frontend/src/pages/settings/import-export.vue b/packages/frontend/src/pages/settings/import-export.vue
index 5acbc50756..6b67a9a1a8 100644
--- a/packages/frontend/src/pages/settings/import-export.vue
+++ b/packages/frontend/src/pages/settings/import-export.vue
@@ -4,118 +4,143 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m">
- <FormSection first>
- <template #label><i class="ti ti-pencil"></i> {{ i18n.ts._exportOrImport.allNotes }}</template>
- <MkFolder>
- <template #label>{{ i18n.ts.export }}</template>
- <template #icon><i class="ti ti-download"></i></template>
- <MkButton primary :class="$style.button" inline @click="exportNotes()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
- </MkFolder>
- </FormSection>
- <FormSection>
- <template #label><i class="ti ti-star"></i> {{ i18n.ts._exportOrImport.favoritedNotes }}</template>
- <MkFolder>
- <template #label>{{ i18n.ts.export }}</template>
- <template #icon><i class="ti ti-download"></i></template>
- <MkButton primary :class="$style.button" inline @click="exportFavorites()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
- </MkFolder>
- </FormSection>
- <FormSection>
- <template #label><i class="ti ti-star"></i> {{ i18n.ts._exportOrImport.clips }}</template>
- <MkFolder>
- <template #label>{{ i18n.ts.export }}</template>
- <template #icon><i class="ti ti-download"></i></template>
- <MkButton primary :class="$style.button" inline @click="exportClips()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
- </MkFolder>
- </FormSection>
- <FormSection>
- <template #label><i class="ti ti-users"></i> {{ i18n.ts._exportOrImport.followingList }}</template>
- <div class="_gaps_s">
- <MkFolder>
- <template #label>{{ i18n.ts.export }}</template>
- <template #icon><i class="ti ti-download"></i></template>
+<SearchMarker path="/settings/import-export" :label="i18n.ts.importAndExport" :keywords="['import', 'export', 'data']" icon="ti ti-package">
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['notes']">
+ <FormSection first>
+ <template #label><i class="ti ti-pencil"></i> <SearchLabel>{{ i18n.ts._exportOrImport.allNotes }}</SearchLabel></template>
+ <MkFolder>
+ <template #label>{{ i18n.ts.export }}</template>
+ <template #icon><i class="ti ti-download"></i></template>
+ <MkButton primary :class="$style.button" inline @click="exportNotes()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ </MkFolder>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['favorite', 'notes']">
+ <FormSection>
+ <template #label><i class="ti ti-star"></i> <SearchLabel>{{ i18n.ts._exportOrImport.favoritedNotes }}</SearchLabel></template>
+ <MkFolder>
+ <template #label>{{ i18n.ts.export }}</template>
+ <template #icon><i class="ti ti-download"></i></template>
+ <MkButton primary :class="$style.button" inline @click="exportFavorites()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ </MkFolder>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['clip', 'notes']">
+ <FormSection>
+ <template #label><i class="ti ti-star"></i> <SearchLabel>{{ i18n.ts._exportOrImport.clips }}</SearchLabel></template>
+ <MkFolder>
+ <template #label>{{ i18n.ts.export }}</template>
+ <template #icon><i class="ti ti-download"></i></template>
+ <MkButton primary :class="$style.button" inline @click="exportClips()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ </MkFolder>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['following', 'users']">
+ <FormSection>
+ <template #label><i class="ti ti-users"></i> <SearchLabel>{{ i18n.ts._exportOrImport.followingList }}</SearchLabel></template>
+ <div class="_gaps_s">
+ <MkFolder>
+ <template #label>{{ i18n.ts.export }}</template>
+ <template #icon><i class="ti ti-download"></i></template>
+ <div class="_gaps_s">
+ <MkSwitch v-model="excludeMutingUsers">
+ {{ i18n.ts._exportOrImport.excludeMutingUsers }}
+ </MkSwitch>
+ <MkSwitch v-model="excludeInactiveUsers">
+ {{ i18n.ts._exportOrImport.excludeInactiveUsers }}
+ </MkSwitch>
+ <MkButton primary :class="$style.button" inline @click="exportFollowing()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ </div>
+ </MkFolder>
+ <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportFollowing">
+ <template #label>{{ i18n.ts.import }}</template>
+ <template #icon><i class="ti ti-upload"></i></template>
+ <MkSwitch v-model="withReplies">
+ {{ i18n.ts._exportOrImport.withReplies }}
+ </MkSwitch>
+ <MkButton primary :class="$style.button" inline @click="importFollowing($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
+ </MkFolder>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['user', 'lists']">
+ <FormSection>
+ <template #label><i class="ti ti-users"></i> <SearchLabel>{{ i18n.ts._exportOrImport.userLists }}</SearchLabel></template>
+ <div class="_gaps_s">
+ <MkFolder>
+ <template #label>{{ i18n.ts.export }}</template>
+ <template #icon><i class="ti ti-download"></i></template>
+ <MkButton primary :class="$style.button" inline @click="exportUserLists()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ </MkFolder>
+ <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportUserLists">
+ <template #label>{{ i18n.ts.import }}</template>
+ <template #icon><i class="ti ti-upload"></i></template>
+ <MkButton primary :class="$style.button" inline @click="importUserLists($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
+ </MkFolder>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['mute', 'users']">
+ <FormSection>
+ <template #label><i class="ti ti-user-off"></i> <SearchLabel>{{ i18n.ts._exportOrImport.muteList }}</SearchLabel></template>
+ <div class="_gaps_s">
+ <MkFolder>
+ <template #label>{{ i18n.ts.export }}</template>
+ <template #icon><i class="ti ti-download"></i></template>
+ <MkButton primary :class="$style.button" inline @click="exportMuting()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ </MkFolder>
+ <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportMuting">
+ <template #label>{{ i18n.ts.import }}</template>
+ <template #icon><i class="ti ti-upload"></i></template>
+ <MkButton primary :class="$style.button" inline @click="importMuting($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
+ </MkFolder>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['block', 'users']">
+ <FormSection>
+ <template #label><i class="ti ti-user-off"></i> <SearchLabel>{{ i18n.ts._exportOrImport.blockingList }}</SearchLabel></template>
+ <div class="_gaps_s">
+ <MkFolder>
+ <template #label>{{ i18n.ts.export }}</template>
+ <template #icon><i class="ti ti-download"></i></template>
+ <MkButton primary :class="$style.button" inline @click="exportBlocking()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ </MkFolder>
+ <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportBlocking">
+ <template #label>{{ i18n.ts.import }}</template>
+ <template #icon><i class="ti ti-upload"></i></template>
+ <MkButton primary :class="$style.button" inline @click="importBlocking($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
+ </MkFolder>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['antennas']">
+ <FormSection>
+ <template #label><i class="ti ti-antenna"></i> <SearchLabel>{{ i18n.ts.antennas }}</SearchLabel></template>
<div class="_gaps_s">
- <MkSwitch v-model="excludeMutingUsers">
- {{ i18n.ts._exportOrImport.excludeMutingUsers }}
- </MkSwitch>
- <MkSwitch v-model="excludeInactiveUsers">
- {{ i18n.ts._exportOrImport.excludeInactiveUsers }}
- </MkSwitch>
- <MkButton primary :class="$style.button" inline @click="exportFollowing()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ <MkFolder>
+ <template #label>{{ i18n.ts.export }}</template>
+ <template #icon><i class="ti ti-download"></i></template>
+ <MkButton primary :class="$style.button" inline @click="exportAntennas()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
+ </MkFolder>
+ <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportAntennas">
+ <template #label>{{ i18n.ts.import }}</template>
+ <template #icon><i class="ti ti-upload"></i></template>
+ <MkButton primary :class="$style.button" inline @click="importAntennas($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
+ </MkFolder>
</div>
- </MkFolder>
- <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportFollowing">
- <template #label>{{ i18n.ts.import }}</template>
- <template #icon><i class="ti ti-upload"></i></template>
- <MkSwitch v-model="withReplies">
- {{ i18n.ts._exportOrImport.withReplies }}
- </MkSwitch>
- <MkButton primary :class="$style.button" inline @click="importFollowing($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
- </MkFolder>
- </div>
- </FormSection>
- <FormSection>
- <template #label><i class="ti ti-users"></i> {{ i18n.ts._exportOrImport.userLists }}</template>
- <div class="_gaps_s">
- <MkFolder>
- <template #label>{{ i18n.ts.export }}</template>
- <template #icon><i class="ti ti-download"></i></template>
- <MkButton primary :class="$style.button" inline @click="exportUserLists()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
- </MkFolder>
- <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportUserLists">
- <template #label>{{ i18n.ts.import }}</template>
- <template #icon><i class="ti ti-upload"></i></template>
- <MkButton primary :class="$style.button" inline @click="importUserLists($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
- </MkFolder>
- </div>
- </FormSection>
- <FormSection>
- <template #label><i class="ti ti-user-off"></i> {{ i18n.ts._exportOrImport.muteList }}</template>
- <div class="_gaps_s">
- <MkFolder>
- <template #label>{{ i18n.ts.export }}</template>
- <template #icon><i class="ti ti-download"></i></template>
- <MkButton primary :class="$style.button" inline @click="exportMuting()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
- </MkFolder>
- <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportMuting">
- <template #label>{{ i18n.ts.import }}</template>
- <template #icon><i class="ti ti-upload"></i></template>
- <MkButton primary :class="$style.button" inline @click="importMuting($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
- </MkFolder>
- </div>
- </FormSection>
- <FormSection>
- <template #label><i class="ti ti-user-off"></i> {{ i18n.ts._exportOrImport.blockingList }}</template>
- <div class="_gaps_s">
- <MkFolder>
- <template #label>{{ i18n.ts.export }}</template>
- <template #icon><i class="ti ti-download"></i></template>
- <MkButton primary :class="$style.button" inline @click="exportBlocking()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
- </MkFolder>
- <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportBlocking">
- <template #label>{{ i18n.ts.import }}</template>
- <template #icon><i class="ti ti-upload"></i></template>
- <MkButton primary :class="$style.button" inline @click="importBlocking($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
- </MkFolder>
- </div>
- </FormSection>
- <FormSection>
- <template #label><i class="ti ti-antenna"></i> {{ i18n.ts.antennas }}</template>
- <div class="_gaps_s">
- <MkFolder>
- <template #label>{{ i18n.ts.export }}</template>
- <template #icon><i class="ti ti-download"></i></template>
- <MkButton primary :class="$style.button" inline @click="exportAntennas()"><i class="ti ti-download"></i> {{ i18n.ts.export }}</MkButton>
- </MkFolder>
- <MkFolder v-if="$i && !$i.movedTo && $i.policies.canImportAntennas">
- <template #label>{{ i18n.ts.import }}</template>
- <template #icon><i class="ti ti-upload"></i></template>
- <MkButton primary :class="$style.button" inline @click="importAntennas($event)"><i class="ti ti-upload"></i> {{ i18n.ts.import }}</MkButton>
- </MkFolder>
- </div>
- </FormSection>
-</div>
+ </FormSection>
+ </SearchMarker>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue
index bc6d6d0261..458605d545 100644
--- a/packages/frontend/src/pages/settings/index.vue
+++ b/packages/frontend/src/pages/settings/index.vue
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="!narrow || currentPage?.route.name == null" class="nav">
<div class="baaadecd">
<MkInfo v-if="emailNotConfigured" warn class="info">{{ i18n.ts.emailNotConfiguredWarning }} <MkA to="/settings/email" class="_link">{{ i18n.ts.configure }}</MkA></MkInfo>
- <MkSuperMenu :def="menuDef" :grid="narrow"></MkSuperMenu>
+ <MkSuperMenu :def="menuDef" :grid="narrow" :searchIndex="SETTING_INDEX"></MkSuperMenu>
</div>
</div>
<div v-if="!(narrow && currentPage?.route.name == null)" class="main">
@@ -29,6 +29,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<script setup lang="ts">
import { computed, onActivated, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue';
+import type { PageMetadata } from '@/scripts/page-metadata.js';
+import type { SuperMenuDef } from '@/components/MkSuperMenu.vue';
import { i18n } from '@/i18n.js';
import MkInfo from '@/components/MkInfo.vue';
import MkSuperMenu from '@/components/MkSuperMenu.vue';
@@ -38,8 +40,9 @@ import { instance } from '@/instance.js';
import { definePageMetadata, provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js';
import * as os from '@/os.js';
import { useRouter } from '@/router/supplier.js';
-import type { PageMetadata } from '@/scripts/page-metadata.js';
-import type { SuperMenuDef } from '@/components/MkSuperMenu.vue';
+import { searchIndexes } from '@/scripts/autogen/settings-search-index.js';
+
+const SETTING_INDEX = searchIndexes; // TODO: lazy load
const indexInfo = {
title: i18n.ts.settings,
@@ -63,7 +66,6 @@ const ro = new ResizeObserver((entries, observer) => {
});
const menuDef = computed<SuperMenuDef[]>(() => [{
- title: i18n.ts.basicSettings,
items: [{
icon: 'ti ti-user',
text: i18n.ts.profile,
@@ -101,40 +103,38 @@ const menuDef = computed<SuperMenuDef[]>(() => [{
active: currentPage.value?.route.name === 'security',
}],
}, {
- title: i18n.ts.clientSettings,
items: [{
icon: 'ti ti-adjustments',
- text: i18n.ts.general,
- to: '/settings/general',
- active: currentPage.value?.route.name === 'general',
+ text: i18n.ts.preferences,
+ to: '/settings/preferences',
+ active: currentPage.value?.route.name === 'preferences',
}, {
icon: 'ti ti-palette',
text: i18n.ts.theme,
to: '/settings/theme',
active: currentPage.value?.route.name === 'theme',
}, {
- icon: 'ti ti-menu-2',
- text: i18n.ts.navbar,
- to: '/settings/navbar',
- active: currentPage.value?.route.name === 'navbar',
- }, {
- icon: 'ti ti-equal-double',
- text: i18n.ts.statusbar,
- to: '/settings/statusbar',
- active: currentPage.value?.route.name === 'statusbar',
+ icon: 'ti ti-device-desktop',
+ text: i18n.ts.appearance,
+ to: '/settings/appearance',
+ active: currentPage.value?.route.name === 'appearance',
}, {
icon: 'ti ti-music',
text: i18n.ts.sounds,
to: '/settings/sounds',
active: currentPage.value?.route.name === 'sounds',
}, {
+ icon: 'ti ti-accessible',
+ text: i18n.ts.accessibility,
+ to: '/settings/accessibility',
+ active: currentPage.value?.route.name === 'accessibility',
+ }, {
icon: 'ti ti-plug',
text: i18n.ts.plugins,
to: '/settings/plugin',
active: currentPage.value?.route.name === 'plugin',
}],
}, {
- title: i18n.ts.otherSettings,
items: [{
icon: 'ti ti-badges',
text: i18n.ts.roles,
@@ -161,11 +161,6 @@ const menuDef = computed<SuperMenuDef[]>(() => [{
to: '/settings/import-export',
active: currentPage.value?.route.name === 'import-export',
}, {
- icon: 'ti ti-plane',
- text: `${i18n.ts.accountMigration}`,
- to: '/settings/migration',
- active: currentPage.value?.route.name === 'migration',
- }, {
icon: 'ti ti-dots',
text: i18n.ts.other,
to: '/settings/other',
diff --git a/packages/frontend/src/pages/settings/migration.vue b/packages/frontend/src/pages/settings/migration.vue
index ddc23945dd..1c00d64d73 100644
--- a/packages/frontend/src/pages/settings/migration.vue
+++ b/packages/frontend/src/pages/settings/migration.vue
@@ -68,7 +68,6 @@ import MkUserInfo from '@/components/MkUserInfo.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { i18n } from '@/i18n.js';
-import { definePageMetadata } from '@/scripts/page-metadata.js';
import { signinRequired } from '@/account.js';
import { unisonReload } from '@/scripts/unison-reload.js';
@@ -120,11 +119,6 @@ async function save(): Promise<void> {
}
init();
-
-definePageMetadata(() => ({
- title: i18n.ts.accountMigration,
- icon: 'ti ti-plane',
-}));
</script>
<style lang="scss">
diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue
index 491676e0d0..4aac2a25bd 100644
--- a/packages/frontend/src/pages/settings/mute-block.vue
+++ b/packages/frontend/src/pages/settings/mute-block.vue
@@ -4,132 +4,171 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m">
- <MkFolder>
- <template #icon><i class="ti ti-message-off"></i></template>
- <template #label>{{ i18n.ts.wordMute }}</template>
+<SearchMarker path="/settings/mute-block" :label="i18n.ts.muteAndBlock" icon="ti ti-ban" :keywords="['mute', 'block']">
+ <div class="_gaps_m">
+ <SearchMarker
+ :label="i18n.ts.wordMute"
+ :keywords="['note', 'word', 'soft', 'mute', 'hide']"
+ >
+ <MkFolder>
+ <template #icon><i class="ti ti-message-off"></i></template>
+ <template #label>{{ i18n.ts.wordMute }}</template>
- <div class="_gaps_m">
- <MkInfo>{{ i18n.ts.wordMuteDescription }}</MkInfo>
- <MkSwitch v-model="showSoftWordMutedWord">{{ i18n.ts.showMutedWord }}</MkSwitch>
- <XWordMute :muted="$i.mutedWords" @save="saveMutedWords"/>
- </div>
- </MkFolder>
+ <div class="_gaps_m">
+ <MkInfo>{{ i18n.ts.wordMuteDescription }}</MkInfo>
- <MkFolder>
- <template #icon><i class="ti ti-message-off"></i></template>
- <template #label>{{ i18n.ts.hardWordMute }}</template>
+ <SearchMarker
+ :label="i18n.ts.showMutedWord"
+ :keywords="['show']"
+ >
+ <MkSwitch v-model="showSoftWordMutedWord">{{ i18n.ts.showMutedWord }}</MkSwitch>
+ </SearchMarker>
- <div class="_gaps_m">
- <MkInfo>{{ i18n.ts.hardWordMuteDescription }}</MkInfo>
- <XWordMute :muted="$i.hardMutedWords" @save="saveHardMutedWords"/>
- </div>
- </MkFolder>
+ <XWordMute :muted="$i.mutedWords" @save="saveMutedWords"/>
+ </div>
+ </MkFolder>
+ </SearchMarker>
- <MkFolder v-if="instance.federation !== 'none'">
- <template #icon><i class="ti ti-planet-off"></i></template>
- <template #label>{{ i18n.ts.instanceMute }}</template>
+ <SearchMarker
+ :label="i18n.ts.hardWordMute"
+ :keywords="['note', 'word', 'hard', 'mute', 'hide']"
+ >
+ <MkFolder>
+ <template #icon><i class="ti ti-message-off"></i></template>
+ <template #label>{{ i18n.ts.hardWordMute }}</template>
- <XInstanceMute/>
- </MkFolder>
+ <div class="_gaps_m">
+ <MkInfo>{{ i18n.ts.hardWordMuteDescription }}</MkInfo>
+ <XWordMute :muted="$i.hardMutedWords" @save="saveHardMutedWords"/>
+ </div>
+ </MkFolder>
+ </SearchMarker>
- <MkFolder>
- <template #icon><i class="ti ti-repeat-off"></i></template>
- <template #label>{{ i18n.ts.mutedUsers }} ({{ i18n.ts.renote }})</template>
+ <SearchMarker
+ :label="i18n.ts.instanceMute"
+ :keywords="['note', 'server', 'instance', 'host', 'federation', 'mute', 'hide']"
+ >
+ <MkFolder v-if="instance.federation !== 'none'">
+ <template #icon><i class="ti ti-planet-off"></i></template>
+ <template #label>{{ i18n.ts.instanceMute }}</template>
- <MkPagination :pagination="renoteMutingPagination">
- <template #empty>
- <div class="_fullinfo">
- <img :src="infoImageUrl" class="_ghost"/>
- <div>{{ i18n.ts.noUsers }}</div>
- </div>
- </template>
+ <XInstanceMute/>
+ </MkFolder>
+ </SearchMarker>
- <template #default="{ items }">
- <div class="_gaps_s">
- <div v-for="item in items" :key="item.mutee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedRenoteMuteItems.includes(item.id) }]">
- <div :class="$style.userItemMain">
- <MkA :class="$style.userItemMainBody" :to="userPage(item.mutee)">
- <MkUserCardMini :user="item.mutee"/>
- </MkA>
- <button class="_button" :class="$style.userToggle" @click="toggleRenoteMuteItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
- <button class="_button" :class="$style.remove" @click="unrenoteMute(item.mutee, $event)"><i class="ti ti-x"></i></button>
- </div>
- <div v-if="expandedRenoteMuteItems.includes(item.id)" :class="$style.userItemSub">
- <div>Muted at: <MkTime :time="item.createdAt" mode="detail"/></div>
+ <SearchMarker
+ :label="`${i18n.ts.mutedUsers} (${ i18n.ts.renote })`"
+ :keywords="['renote', 'mute', 'hide', 'user']"
+ >
+ <MkFolder>
+ <template #icon><i class="ti ti-repeat-off"></i></template>
+ <template #label>{{ i18n.ts.mutedUsers }} ({{ i18n.ts.renote }})</template>
+
+ <MkPagination :pagination="renoteMutingPagination">
+ <template #empty>
+ <div class="_fullinfo">
+ <img :src="infoImageUrl" class="_ghost"/>
+ <div>{{ i18n.ts.noUsers }}</div>
</div>
- </div>
- </div>
- </template>
- </MkPagination>
- </MkFolder>
+ </template>
- <MkFolder>
- <template #icon><i class="ti ti-eye-off"></i></template>
- <template #label>{{ i18n.ts.mutedUsers }}</template>
+ <template #default="{ items }">
+ <div class="_gaps_s">
+ <div v-for="item in items" :key="item.mutee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedRenoteMuteItems.includes(item.id) }]">
+ <div :class="$style.userItemMain">
+ <MkA :class="$style.userItemMainBody" :to="userPage(item.mutee)">
+ <MkUserCardMini :user="item.mutee"/>
+ </MkA>
+ <button class="_button" :class="$style.userToggle" @click="toggleRenoteMuteItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
+ <button class="_button" :class="$style.remove" @click="unrenoteMute(item.mutee, $event)"><i class="ti ti-x"></i></button>
+ </div>
+ <div v-if="expandedRenoteMuteItems.includes(item.id)" :class="$style.userItemSub">
+ <div>Muted at: <MkTime :time="item.createdAt" mode="detail"/></div>
+ </div>
+ </div>
+ </div>
+ </template>
+ </MkPagination>
+ </MkFolder>
+ </SearchMarker>
- <MkPagination :pagination="mutingPagination">
- <template #empty>
- <div class="_fullinfo">
- <img :src="infoImageUrl" class="_ghost"/>
- <div>{{ i18n.ts.noUsers }}</div>
- </div>
- </template>
+ <SearchMarker
+ :label="i18n.ts.mutedUsers"
+ :keywords="['note', 'mute', 'hide', 'user']"
+ >
+ <MkFolder>
+ <template #icon><i class="ti ti-eye-off"></i></template>
+ <template #label>{{ i18n.ts.mutedUsers }}</template>
- <template #default="{ items }">
- <div class="_gaps_s">
- <div v-for="item in items" :key="item.mutee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedMuteItems.includes(item.id) }]">
- <div :class="$style.userItemMain">
- <MkA :class="$style.userItemMainBody" :to="userPage(item.mutee)">
- <MkUserCardMini :user="item.mutee"/>
- </MkA>
- <button class="_button" :class="$style.userToggle" @click="toggleMuteItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
- <button class="_button" :class="$style.remove" @click="unmute(item.mutee, $event)"><i class="ti ti-x"></i></button>
+ <MkPagination :pagination="mutingPagination">
+ <template #empty>
+ <div class="_fullinfo">
+ <img :src="infoImageUrl" class="_ghost"/>
+ <div>{{ i18n.ts.noUsers }}</div>
</div>
- <div v-if="expandedMuteItems.includes(item.id)" :class="$style.userItemSub">
- <div>Muted at: <MkTime :time="item.createdAt" mode="detail"/></div>
- <div v-if="item.expiresAt">Period: {{ new Date(item.expiresAt).toLocaleString() }}</div>
- <div v-else>Period: {{ i18n.ts.indefinitely }}</div>
+ </template>
+
+ <template #default="{ items }">
+ <div class="_gaps_s">
+ <div v-for="item in items" :key="item.mutee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedMuteItems.includes(item.id) }]">
+ <div :class="$style.userItemMain">
+ <MkA :class="$style.userItemMainBody" :to="userPage(item.mutee)">
+ <MkUserCardMini :user="item.mutee"/>
+ </MkA>
+ <button class="_button" :class="$style.userToggle" @click="toggleMuteItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
+ <button class="_button" :class="$style.remove" @click="unmute(item.mutee, $event)"><i class="ti ti-x"></i></button>
+ </div>
+ <div v-if="expandedMuteItems.includes(item.id)" :class="$style.userItemSub">
+ <div>Muted at: <MkTime :time="item.createdAt" mode="detail"/></div>
+ <div v-if="item.expiresAt">Period: {{ new Date(item.expiresAt).toLocaleString() }}</div>
+ <div v-else>Period: {{ i18n.ts.indefinitely }}</div>
+ </div>
+ </div>
</div>
- </div>
- </div>
- </template>
- </MkPagination>
- </MkFolder>
+ </template>
+ </MkPagination>
+ </MkFolder>
+ </SearchMarker>
- <MkFolder>
- <template #icon><i class="ti ti-ban"></i></template>
- <template #label>{{ i18n.ts.blockedUsers }}</template>
+ <SearchMarker
+ :label="i18n.ts.blockedUsers"
+ :keywords="['block', 'user']"
+ >
+ <MkFolder>
+ <template #icon><i class="ti ti-ban"></i></template>
+ <template #label>{{ i18n.ts.blockedUsers }}</template>
- <MkPagination :pagination="blockingPagination">
- <template #empty>
- <div class="_fullinfo">
- <img :src="infoImageUrl" class="_ghost"/>
- <div>{{ i18n.ts.noUsers }}</div>
- </div>
- </template>
-
- <template #default="{ items }">
- <div class="_gaps_s">
- <div v-for="item in items" :key="item.blockee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedBlockItems.includes(item.id) }]">
- <div :class="$style.userItemMain">
- <MkA :class="$style.userItemMainBody" :to="userPage(item.blockee)">
- <MkUserCardMini :user="item.blockee"/>
- </MkA>
- <button class="_button" :class="$style.userToggle" @click="toggleBlockItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
- <button class="_button" :class="$style.remove" @click="unblock(item.blockee, $event)"><i class="ti ti-x"></i></button>
+ <MkPagination :pagination="blockingPagination">
+ <template #empty>
+ <div class="_fullinfo">
+ <img :src="infoImageUrl" class="_ghost"/>
+ <div>{{ i18n.ts.noUsers }}</div>
</div>
- <div v-if="expandedBlockItems.includes(item.id)" :class="$style.userItemSub">
- <div>Blocked at: <MkTime :time="item.createdAt" mode="detail"/></div>
- <div v-if="item.expiresAt">Period: {{ new Date(item.expiresAt).toLocaleString() }}</div>
- <div v-else>Period: {{ i18n.ts.indefinitely }}</div>
+ </template>
+
+ <template #default="{ items }">
+ <div class="_gaps_s">
+ <div v-for="item in items" :key="item.blockee.id" :class="[$style.userItem, { [$style.userItemOpend]: expandedBlockItems.includes(item.id) }]">
+ <div :class="$style.userItemMain">
+ <MkA :class="$style.userItemMainBody" :to="userPage(item.blockee)">
+ <MkUserCardMini :user="item.blockee"/>
+ </MkA>
+ <button class="_button" :class="$style.userToggle" @click="toggleBlockItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
+ <button class="_button" :class="$style.remove" @click="unblock(item.blockee, $event)"><i class="ti ti-x"></i></button>
+ </div>
+ <div v-if="expandedBlockItems.includes(item.id)" :class="$style.userItemSub">
+ <div>Blocked at: <MkTime :time="item.createdAt" mode="detail"/></div>
+ <div v-if="item.expiresAt">Period: {{ new Date(item.expiresAt).toLocaleString() }}</div>
+ <div v-else>Period: {{ i18n.ts.indefinitely }}</div>
+ </div>
+ </div>
</div>
- </div>
- </div>
- </template>
- </MkPagination>
- </MkFolder>
-</div>
+ </template>
+ </MkPagination>
+ </MkFolder>
+ </SearchMarker>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue
index 4a52e59d02..9742c548e7 100644
--- a/packages/frontend/src/pages/settings/other.vue
+++ b/packages/frontend/src/pages/settings/other.vue
@@ -4,91 +4,111 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m">
- <!--
- <MkSwitch v-model="$i.injectFeaturedNote" @update:model-value="onChangeInjectFeaturedNote">
- <template #label>{{ i18n.ts.showFeaturedNotesInTimeline }}</template>
- </MkSwitch>
- -->
+<SearchMarker path="/settings/other" :label="i18n.ts.other" :keywords="['other']" icon="ti ti-dots">
+ <div class="_gaps_m">
+ <!--
+ <MkSwitch v-model="$i.injectFeaturedNote" @update:model-value="onChangeInjectFeaturedNote">
+ <template #label>{{ i18n.ts.showFeaturedNotesInTimeline }}</template>
+ </MkSwitch>
+ -->
- <!--
- <MkSwitch v-model="reportError">{{ i18n.ts.sendErrorReports }}<template #caption>{{ i18n.ts.sendErrorReportsDescription }}</template></MkSwitch>
- -->
+ <!--
+ <MkSwitch v-model="reportError">{{ i18n.ts.sendErrorReports }}<template #caption>{{ i18n.ts.sendErrorReportsDescription }}</template></MkSwitch>
+ -->
- <FormSection first>
- <div class="_gaps_s">
- <MkFolder>
- <template #icon><i class="ti ti-info-circle"></i></template>
- <template #label>{{ i18n.ts.accountInfo }}</template>
+ <FormSection first>
+ <div class="_gaps_s">
+ <SearchMarker :keywords="['account', 'info']">
+ <MkFolder>
+ <template #icon><i class="ti ti-info-circle"></i></template>
+ <template #label><SearchLabel>{{ i18n.ts.accountInfo }}</SearchLabel></template>
- <div class="_gaps_m">
- <MkKeyValue>
- <template #key>ID</template>
- <template #value><span class="_monospace">{{ $i.id }}</span></template>
- </MkKeyValue>
+ <div class="_gaps_m">
+ <MkKeyValue>
+ <template #key>ID</template>
+ <template #value><span class="_monospace">{{ $i.id }}</span></template>
+ </MkKeyValue>
- <MkKeyValue>
- <template #key>{{ i18n.ts.registeredDate }}</template>
- <template #value><MkTime :time="$i.createdAt" mode="detail"/></template>
- </MkKeyValue>
- </div>
- </MkFolder>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.registeredDate }}</template>
+ <template #value><MkTime :time="$i.createdAt" mode="detail"/></template>
+ </MkKeyValue>
+ </div>
+ </MkFolder>
+ </SearchMarker>
- <MkFolder>
- <template #icon><i class="ti ti-alert-triangle"></i></template>
- <template #label>{{ i18n.ts.closeAccount }}</template>
+ <SearchMarker :keywords="['account', 'move', 'migration']">
+ <MkFolder>
+ <template #icon><i class="ti ti-plane"></i></template>
+ <template #label><SearchLabel>{{ i18n.ts.accountMigration }}</SearchLabel></template>
- <div class="_gaps_m">
- <FormInfo warn>{{ i18n.ts._accountDelete.mayTakeTime }}</FormInfo>
- <FormInfo>{{ i18n.ts._accountDelete.sendEmail }}</FormInfo>
- <MkButton v-if="!$i.isDeleted" danger @click="deleteAccount">{{ i18n.ts._accountDelete.requestAccountDelete }}</MkButton>
- <MkButton v-else disabled>{{ i18n.ts._accountDelete.inProgress }}</MkButton>
- </div>
- </MkFolder>
+ <XMigration/>
+ </MkFolder>
+ </SearchMarker>
- <MkFolder>
- <template #icon><i class="ti ti-flask"></i></template>
- <template #label>{{ i18n.ts.experimentalFeatures }}</template>
+ <SearchMarker :keywords="['account', 'close', 'delete']">
+ <MkFolder>
+ <template #icon><i class="ti ti-alert-triangle"></i></template>
+ <template #label><SearchLabel>{{ i18n.ts.closeAccount }}</SearchLabel></template>
- <div class="_gaps_m">
- <MkSwitch v-model="enableCondensedLine">
- <template #label>Enable condensed line</template>
- </MkSwitch>
- <MkSwitch v-model="skipNoteRender">
- <template #label>Enable note render skipping</template>
- </MkSwitch>
- </div>
- </MkFolder>
+ <div class="_gaps_m">
+ <FormInfo warn>{{ i18n.ts._accountDelete.mayTakeTime }}</FormInfo>
+ <FormInfo>{{ i18n.ts._accountDelete.sendEmail }}</FormInfo>
+ <MkButton v-if="!$i.isDeleted" danger @click="deleteAccount"><SearchKeyword>{{ i18n.ts._accountDelete.requestAccountDelete }}</SearchKeyword></MkButton>
+ <MkButton v-else disabled>{{ i18n.ts._accountDelete.inProgress }}</MkButton>
+ </div>
+ </MkFolder>
+ </SearchMarker>
- <MkFolder>
- <template #icon><i class="ti ti-code"></i></template>
- <template #label>{{ i18n.ts.developer }}</template>
+ <SearchMarker :keywords="['experimental', 'feature', 'flags']">
+ <MkFolder>
+ <template #icon><i class="ti ti-flask"></i></template>
+ <template #label><SearchLabel>{{ i18n.ts.experimentalFeatures }}</SearchLabel></template>
- <div class="_gaps_m">
- <MkSwitch v-model="devMode">
- <template #label>{{ i18n.ts.devMode }}</template>
- </MkSwitch>
- </div>
- </MkFolder>
- </div>
- </FormSection>
+ <div class="_gaps_m">
+ <MkSwitch v-model="enableCondensedLine">
+ <template #label>Enable condensed line</template>
+ </MkSwitch>
+ <MkSwitch v-model="skipNoteRender">
+ <template #label>Enable note render skipping</template>
+ </MkSwitch>
+ </div>
+ </MkFolder>
+ </SearchMarker>
- <FormSection>
- <FormLink to="/registry"><template #icon><i class="ti ti-adjustments"></i></template>{{ i18n.ts.registry }}</FormLink>
- </FormSection>
+ <SearchMarker :keywords="['developer', 'mode', 'debug']">
+ <MkFolder>
+ <template #icon><i class="ti ti-code"></i></template>
+ <template #label><SearchLabel>{{ i18n.ts.developer }}</SearchLabel></template>
- <FormSection>
- <div class="_gaps_s">
- <MkSwitch v-model="defaultWithReplies">{{ i18n.ts.withRepliesByDefaultForNewlyFollowed }}</MkSwitch>
- <MkButton danger @click="updateRepliesAll(true)"><i class="ti ti-messages"></i> {{ i18n.ts.showRepliesToOthersInTimelineAll }}</MkButton>
- <MkButton danger @click="updateRepliesAll(false)"><i class="ti ti-messages-off"></i> {{ i18n.ts.hideRepliesToOthersInTimelineAll }}</MkButton>
- </div>
- </FormSection>
-</div>
+ <div class="_gaps_m">
+ <MkSwitch v-model="devMode">
+ <template #label>{{ i18n.ts.devMode }}</template>
+ </MkSwitch>
+ </div>
+ </MkFolder>
+ </SearchMarker>
+ </div>
+ </FormSection>
+
+ <FormSection>
+ <FormLink to="/registry"><template #icon><i class="ti ti-adjustments"></i></template>{{ i18n.ts.registry }}</FormLink>
+ </FormSection>
+
+ <FormSection>
+ <div class="_gaps_s">
+ <MkSwitch v-model="defaultWithReplies">{{ i18n.ts.withRepliesByDefaultForNewlyFollowed }}</MkSwitch>
+ <MkButton danger @click="updateRepliesAll(true)"><i class="ti ti-messages"></i> {{ i18n.ts.showRepliesToOthersInTimelineAll }}</MkButton>
+ <MkButton danger @click="updateRepliesAll(false)"><i class="ti ti-messages-off"></i> {{ i18n.ts.hideRepliesToOthersInTimelineAll }}</MkButton>
+ </div>
+ </FormSection>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
import { computed, watch } from 'vue';
+import XMigration from './migration.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import FormLink from '@/components/form/link.vue';
import MkFolder from '@/components/MkFolder.vue';
diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue
new file mode 100644
index 0000000000..fe718bfa69
--- /dev/null
+++ b/packages/frontend/src/pages/settings/preferences.vue
@@ -0,0 +1,434 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<SearchMarker path="/settings/preferences" :label="i18n.ts.preferences" :keywords="['general', 'preferences']" icon="ti ti-adjustments">
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['language']">
+ <MkSelect v-model="lang">
+ <template #label><SearchLabel>{{ i18n.ts.uiLanguage }}</SearchLabel></template>
+ <option v-for="x in langs" :key="x[0]" :value="x[0]">{{ x[1] }}</option>
+ <template #caption>
+ <I18n :src="i18n.ts.i18nInfo" tag="span">
+ <template #link>
+ <MkLink url="https://crowdin.com/project/misskey">Crowdin</MkLink>
+ </template>
+ </I18n>
+ </template>
+ </MkSelect>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['device', 'type', 'kind', 'smartphone', 'tablet', 'desktop']">
+ <MkRadios v-model="overridedDeviceKind">
+ <template #label><SearchLabel>{{ i18n.ts.overridedDeviceKind }}</SearchLabel></template>
+ <option :value="null">{{ i18n.ts.auto }}</option>
+ <option value="smartphone"><i class="ti ti-device-mobile"/> {{ i18n.ts.smartphone }}</option>
+ <option value="tablet"><i class="ti ti-device-tablet"/> {{ i18n.ts.tablet }}</option>
+ <option value="desktop"><i class="ti ti-device-desktop"/> {{ i18n.ts.desktop }}</option>
+ </MkRadios>
+ </SearchMarker>
+
+ <FormSection>
+ <div class="_gaps_s">
+ <SearchMarker :keywords="['post', 'form', 'timeline']">
+ <MkSwitch v-model="showFixedPostForm">
+ <template #label><SearchLabel>{{ i18n.ts.showFixedPostForm }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['post', 'form', 'timeline', 'channel']">
+ <MkSwitch v-model="showFixedPostFormInChannel">
+ <template #label><SearchLabel>{{ i18n.ts.showFixedPostFormInChannel }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['pinned', 'list']">
+ <MkFolder>
+ <template #label><SearchLabel>{{ i18n.ts.pinnedList }}</SearchLabel></template>
+ <!-- 複数ピン止め管理できるようにしたいけどめんどいので一旦ひとつのみ -->
+ <MkButton v-if="defaultStore.reactiveState.pinnedUserLists.value.length === 0" @click="setPinnedList()">{{ i18n.ts.add }}</MkButton>
+ <MkButton v-else danger @click="removePinnedList()"><i class="ti ti-trash"></i> {{ i18n.ts.remove }}</MkButton>
+ </MkFolder>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['mfm', 'enable', 'show', 'advanced', 'picker', 'form', 'function', 'fn']">
+ <MkSwitch v-model="enableQuickAddMfmFunction">
+ <template #label><SearchLabel>{{ i18n.ts.enableQuickAddMfmFunction }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+ </FormSection>
+
+ <SearchMarker :keywords="['note']">
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.note }}</SearchLabel></template>
+
+ <div class="_gaps_m">
+ <div class="_gaps_s">
+ <SearchMarker :keywords="['renote']">
+ <MkSwitch v-model="collapseRenotes">
+ <template #label><SearchLabel>{{ i18n.ts.collapseRenotes }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.collapseRenotesDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['hover', 'show', 'footer', 'action']">
+ <MkSwitch v-model="showNoteActionsOnlyHover">
+ <template #label><SearchLabel>{{ i18n.ts.showNoteActionsOnlyHover }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['footer', 'action', 'clip', 'show']">
+ <MkSwitch v-model="showClipButtonInNoteFooter">
+ <template #label><SearchLabel>{{ i18n.ts.showClipButtonInNoteFooter }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['mfm', 'enable', 'show', 'advanced']">
+ <MkSwitch v-model="advancedMfm">
+ <template #label><SearchLabel>{{ i18n.ts.enableAdvancedMfm }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['reaction', 'count', 'show']">
+ <MkSwitch v-model="showReactionsCount">
+ <template #label><SearchLabel>{{ i18n.ts.showReactionsCount }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['image', 'photo', 'picture', 'media', 'thumbnail', 'quality', 'raw', 'attachment']">
+ <MkSwitch v-model="loadRawImages">
+ <template #label><SearchLabel>{{ i18n.ts.loadRawImages }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['notification']">
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.notifications }}</SearchLabel></template>
+
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['group']">
+ <MkSwitch v-model="useGroupedNotifications">
+ <template #label><SearchLabel>{{ i18n.ts.useGroupedNotifications }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['behavior']">
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.behavior }}</SearchLabel></template>
+
+ <div class="_gaps_m">
+ <div class="_gaps_s">
+ <SearchMarker :keywords="['image', 'photo', 'picture', 'media', 'thumbnail', 'new', 'tab']">
+ <MkSwitch v-model="imageNewTab">
+ <template #label><SearchLabel>{{ i18n.ts.openImageInNewTab }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['reaction', 'picker', 'contextmenu', 'open']">
+ <MkSwitch v-model="useReactionPickerForContextMenu">
+ <template #label><SearchLabel>{{ i18n.ts.useReactionPickerForContextMenu }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['load', 'auto', 'more']">
+ <MkSwitch v-model="enableInfiniteScroll">
+ <template #label><SearchLabel>{{ i18n.ts.enableInfiniteScroll }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['disable', 'streaming', 'timeline']">
+ <MkSwitch v-model="disableStreamingTimeline">
+ <template #label><SearchLabel>{{ i18n.ts.disableStreamingTimeline }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['follow', 'confirm', 'always']">
+ <MkSwitch v-model="alwaysConfirmFollow">
+ <template #label><SearchLabel>{{ i18n.ts.alwaysConfirmFollow }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['sensitive', 'nsfw', 'media', 'image', 'photo', 'picture', 'attachment', 'confirm']">
+ <MkSwitch v-model="confirmWhenRevealingSensitiveMedia">
+ <template #label><SearchLabel>{{ i18n.ts.confirmWhenRevealingSensitiveMedia }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['reaction', 'confirm']">
+ <MkSwitch v-model="confirmOnReact">
+ <template #label><SearchLabel>{{ i18n.ts.confirmOnReact }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+
+ <SearchMarker :keywords="['server', 'disconnect', 'reconnect', 'reload', 'streaming']">
+ <MkSelect v-model="serverDisconnectedBehavior">
+ <template #label><SearchLabel>{{ i18n.ts.whenServerDisconnected }}</SearchLabel></template>
+ <option value="reload">{{ i18n.ts._serverDisconnectedBehavior.reload }}</option>
+ <option value="dialog">{{ i18n.ts._serverDisconnectedBehavior.dialog }}</option>
+ <option value="quiet">{{ i18n.ts._serverDisconnectedBehavior.quiet }}</option>
+ </MkSelect>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['cache', 'page']">
+ <MkRange v-model="numberOfPageCache" :min="1" :max="10" :step="1" easing>
+ <template #label><SearchLabel>{{ i18n.ts.numberOfPageCache }}</SearchLabel></template>
+ <template #caption>{{ i18n.ts.numberOfPageCacheDescription }}</template>
+ </MkRange>
+ </SearchMarker>
+
+ <SearchMarker :label="i18n.ts.dataSaver" :keywords="['datasaver']">
+ <MkFolder>
+ <template #label><SearchLabel>{{ i18n.ts.dataSaver }}</SearchLabel></template>
+
+ <div class="_gaps_m">
+ <MkInfo>{{ i18n.ts.reloadRequiredToApplySettings }}</MkInfo>
+
+ <div class="_buttons">
+ <MkButton inline @click="enableAllDataSaver">{{ i18n.ts.enableAll }}</MkButton>
+ <MkButton inline @click="disableAllDataSaver">{{ i18n.ts.disableAll }}</MkButton>
+ </div>
+ <div class="_gaps_m">
+ <MkSwitch v-model="dataSaver.media">
+ {{ i18n.ts._dataSaver._media.title }}
+ <template #caption>{{ i18n.ts._dataSaver._media.description }}</template>
+ </MkSwitch>
+ <MkSwitch v-model="dataSaver.avatar">
+ {{ i18n.ts._dataSaver._avatar.title }}
+ <template #caption>{{ i18n.ts._dataSaver._avatar.description }}</template>
+ </MkSwitch>
+ <MkSwitch v-model="dataSaver.urlPreview">
+ {{ i18n.ts._dataSaver._urlPreview.title }}
+ <template #caption>{{ i18n.ts._dataSaver._urlPreview.description }}</template>
+ </MkSwitch>
+ <MkSwitch v-model="dataSaver.code">
+ {{ i18n.ts._dataSaver._code.title }}
+ <template #caption>{{ i18n.ts._dataSaver._code.description }}</template>
+ </MkSwitch>
+ </div>
+ </div>
+ </MkFolder>
+ </SearchMarker>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <SearchMarker>
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.other }}</SearchLabel></template>
+
+ <div class="_gaps">
+ <SearchMarker :keywords="['ad', 'show']">
+ <MkSwitch v-model="forceShowAds">
+ <template #label><SearchLabel>{{ i18n.ts.forceShowAds }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker>
+ <MkRadios v-model="hemisphere">
+ <template #label><SearchLabel>{{ i18n.ts.hemisphere }}</SearchLabel></template>
+ <option value="N">{{ i18n.ts._hemisphere.N }}</option>
+ <option value="S">{{ i18n.ts._hemisphere.S }}</option>
+ <template #caption>{{ i18n.ts._hemisphere.caption }}</template>
+ </MkRadios>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['emoji', 'dictionary', 'additional', 'extra']">
+ <MkFolder>
+ <template #label><SearchLabel>{{ i18n.ts.additionalEmojiDictionary }}</SearchLabel></template>
+ <div class="_buttons">
+ <template v-for="lang in emojiIndexLangs" :key="lang">
+ <MkButton v-if="defaultStore.reactiveState.additionalUnicodeEmojiIndexes.value[lang]" danger @click="removeEmojiIndex(lang)"><i class="ti ti-trash"></i> {{ i18n.ts.remove }} ({{ getEmojiIndexLangName(lang) }})</MkButton>
+ <MkButton v-else @click="downloadEmojiIndex(lang)"><i class="ti ti-download"></i> {{ getEmojiIndexLangName(lang) }}{{ defaultStore.reactiveState.additionalUnicodeEmojiIndexes.value[lang] ? ` (${ i18n.ts.installed })` : '' }}</MkButton>
+ </template>
+ </div>
+ </MkFolder>
+ </SearchMarker>
+
+ <FormLink to="/settings/navbar">{{ i18n.ts.navbar }}</FormLink>
+ <FormLink to="/settings/statusbar">{{ i18n.ts.statusbar }}</FormLink>
+ </div>
+ </FormSection>
+ </SearchMarker>
+
+ <FormSection>
+ <div class="_gaps">
+ <FormLink to="/settings/deck">{{ i18n.ts.deck }}</FormLink>
+ </div>
+ </FormSection>
+ </div>
+</SearchMarker>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref, watch } from 'vue';
+import * as Misskey from 'misskey-js';
+import { langs } from '@@/js/config.js';
+import MkSwitch from '@/components/MkSwitch.vue';
+import MkSelect from '@/components/MkSelect.vue';
+import MkRadios from '@/components/MkRadios.vue';
+import MkRange from '@/components/MkRange.vue';
+import MkFolder from '@/components/MkFolder.vue';
+import MkButton from '@/components/MkButton.vue';
+import FormSection from '@/components/form/section.vue';
+import FormLink from '@/components/form/link.vue';
+import MkLink from '@/components/MkLink.vue';
+import MkInfo from '@/components/MkInfo.vue';
+import { defaultStore } from '@/store.js';
+import * as os from '@/os.js';
+import { instance } from '@/instance.js';
+import { misskeyApi } from '@/scripts/misskey-api.js';
+import { reloadAsk } from '@/scripts/reload-ask.js';
+import { i18n } from '@/i18n.js';
+import { definePageMetadata } from '@/scripts/page-metadata.js';
+import { miLocalStorage } from '@/local-storage.js';
+
+const lang = ref(miLocalStorage.getItem('lang'));
+const dataSaver = ref(defaultStore.state.dataSaver);
+
+const hemisphere = computed(defaultStore.makeGetterSetter('hemisphere'));
+const overridedDeviceKind = computed(defaultStore.makeGetterSetter('overridedDeviceKind'));
+const serverDisconnectedBehavior = computed(defaultStore.makeGetterSetter('serverDisconnectedBehavior'));
+const showNoteActionsOnlyHover = computed(defaultStore.makeGetterSetter('showNoteActionsOnlyHover'));
+const showClipButtonInNoteFooter = computed(defaultStore.makeGetterSetter('showClipButtonInNoteFooter'));
+const collapseRenotes = computed(defaultStore.makeGetterSetter('collapseRenotes'));
+const advancedMfm = computed(defaultStore.makeGetterSetter('advancedMfm'));
+const showReactionsCount = computed(defaultStore.makeGetterSetter('showReactionsCount'));
+const enableQuickAddMfmFunction = computed(defaultStore.makeGetterSetter('enableQuickAddMfmFunction'));
+const forceShowAds = computed(defaultStore.makeGetterSetter('forceShowAds'));
+const loadRawImages = computed(defaultStore.makeGetterSetter('loadRawImages'));
+const imageNewTab = computed(defaultStore.makeGetterSetter('imageNewTab'));
+const showFixedPostForm = computed(defaultStore.makeGetterSetter('showFixedPostForm'));
+const showFixedPostFormInChannel = computed(defaultStore.makeGetterSetter('showFixedPostFormInChannel'));
+const numberOfPageCache = computed(defaultStore.makeGetterSetter('numberOfPageCache'));
+const enableInfiniteScroll = computed(defaultStore.makeGetterSetter('enableInfiniteScroll'));
+const useReactionPickerForContextMenu = computed(defaultStore.makeGetterSetter('useReactionPickerForContextMenu'));
+const disableStreamingTimeline = computed(defaultStore.makeGetterSetter('disableStreamingTimeline'));
+const useGroupedNotifications = computed(defaultStore.makeGetterSetter('useGroupedNotifications'));
+const alwaysConfirmFollow = computed(defaultStore.makeGetterSetter('alwaysConfirmFollow'));
+const confirmWhenRevealingSensitiveMedia = computed(defaultStore.makeGetterSetter('confirmWhenRevealingSensitiveMedia'));
+const confirmOnReact = computed(defaultStore.makeGetterSetter('confirmOnReact'));
+const contextMenu = computed(defaultStore.makeGetterSetter('contextMenu'));
+
+watch(lang, () => {
+ miLocalStorage.setItem('lang', lang.value as string);
+ miLocalStorage.removeItem('locale');
+ miLocalStorage.removeItem('localeVersion');
+});
+
+watch([
+ hemisphere,
+ lang,
+ enableInfiniteScroll,
+ showNoteActionsOnlyHover,
+ overridedDeviceKind,
+ disableStreamingTimeline,
+ alwaysConfirmFollow,
+ confirmWhenRevealingSensitiveMedia,
+ contextMenu,
+], async () => {
+ await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
+});
+
+const emojiIndexLangs = ['en-US', 'ja-JP', 'ja-JP_hira'] as const;
+
+function getEmojiIndexLangName(targetLang: typeof emojiIndexLangs[number]) {
+ if (langs.find(x => x[0] === targetLang)) {
+ return langs.find(x => x[0] === targetLang)![1];
+ } else {
+ // 絵文字辞書限定の言語定義
+ switch (targetLang) {
+ case 'ja-JP_hira': return 'ひらがな';
+ default: return targetLang;
+ }
+ }
+}
+
+function downloadEmojiIndex(lang: typeof emojiIndexLangs[number]) {
+ async function main() {
+ const currentIndexes = defaultStore.state.additionalUnicodeEmojiIndexes;
+
+ function download() {
+ switch (lang) {
+ case 'en-US': return import('../../unicode-emoji-indexes/en-US.json').then(x => x.default);
+ case 'ja-JP': return import('../../unicode-emoji-indexes/ja-JP.json').then(x => x.default);
+ case 'ja-JP_hira': return import('../../unicode-emoji-indexes/ja-JP_hira.json').then(x => x.default);
+ default: throw new Error('unrecognized lang: ' + lang);
+ }
+ }
+
+ currentIndexes[lang] = await download();
+ await defaultStore.set('additionalUnicodeEmojiIndexes', currentIndexes);
+ }
+
+ os.promiseDialog(main());
+}
+
+function removeEmojiIndex(lang: string) {
+ async function main() {
+ const currentIndexes = defaultStore.state.additionalUnicodeEmojiIndexes;
+ delete currentIndexes[lang];
+ await defaultStore.set('additionalUnicodeEmojiIndexes', currentIndexes);
+ }
+
+ os.promiseDialog(main());
+}
+
+async function setPinnedList() {
+ const lists = await misskeyApi('users/lists/list');
+ const { canceled, result: list } = await os.select({
+ title: i18n.ts.selectList,
+ items: lists.map(x => ({
+ value: x, text: x.name,
+ })),
+ });
+ if (canceled) return;
+
+ defaultStore.set('pinnedUserLists', [list]);
+}
+
+function removePinnedList() {
+ defaultStore.set('pinnedUserLists', []);
+}
+
+function enableAllDataSaver() {
+ const g = { ...defaultStore.state.dataSaver };
+
+ Object.keys(g).forEach((key) => { g[key] = true; });
+
+ dataSaver.value = g;
+}
+
+function disableAllDataSaver() {
+ const g = { ...defaultStore.state.dataSaver };
+
+ Object.keys(g).forEach((key) => { g[key] = false; });
+
+ dataSaver.value = g;
+}
+
+watch(dataSaver, (to) => {
+ defaultStore.set('dataSaver', to);
+}, {
+ deep: true,
+});
+
+const headerActions = computed(() => []);
+
+const headerTabs = computed(() => []);
+
+definePageMetadata(() => ({
+ title: i18n.ts.general,
+ icon: 'ti ti-adjustments',
+}));
+</script>
diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue
index 54a5aeb6c1..cd0d54a73b 100644
--- a/packages/frontend/src/pages/settings/privacy.vue
+++ b/packages/frontend/src/pages/settings/privacy.vue
@@ -4,158 +4,208 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m">
- <MkSwitch v-model="isLocked" @update:modelValue="save()">{{ i18n.ts.makeFollowManuallyApprove }}<template #caption>{{ i18n.ts.lockedAccountInfo }}</template></MkSwitch>
- <MkSwitch v-if="isLocked" v-model="autoAcceptFollowed" @update:modelValue="save()">{{ i18n.ts.autoAcceptFollowed }}</MkSwitch>
+<SearchMarker path="/settings/privacy" :label="i18n.ts.privacy" :keywords="['privacy']" icon="ti ti-lock-open">
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['follow', 'lock']">
+ <MkSwitch v-model="isLocked" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.makeFollowManuallyApprove }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.lockedAccountInfo }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
- <MkSwitch v-model="publicReactions" @update:modelValue="save()">
- {{ i18n.ts.makeReactionsPublic }}
- <template #caption>{{ i18n.ts.makeReactionsPublicDescription }}</template>
- </MkSwitch>
+ <MkDisableSection :disabled="!isLocked">
+ <SearchMarker :keywords="['follow', 'auto', 'accept']">
+ <MkSwitch v-model="autoAcceptFollowed" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.autoAcceptFollowed }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </MkDisableSection>
- <MkSelect v-model="followingVisibility" @update:modelValue="save()">
- <template #label>{{ i18n.ts.followingVisibility }}</template>
- <option value="public">{{ i18n.ts._ffVisibility.public }}</option>
- <option value="followers">{{ i18n.ts._ffVisibility.followers }}</option>
- <option value="private">{{ i18n.ts._ffVisibility.private }}</option>
- </MkSelect>
+ <SearchMarker :keywords="['reaction', 'public']">
+ <MkSwitch v-model="publicReactions" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.makeReactionsPublic }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.makeReactionsPublicDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
- <MkSelect v-model="followersVisibility" @update:modelValue="save()">
- <template #label>{{ i18n.ts.followersVisibility }}</template>
- <option value="public">{{ i18n.ts._ffVisibility.public }}</option>
- <option value="followers">{{ i18n.ts._ffVisibility.followers }}</option>
- <option value="private">{{ i18n.ts._ffVisibility.private }}</option>
- </MkSelect>
+ <SearchMarker :keywords="['following', 'visibility']">
+ <MkSelect v-model="followingVisibility" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.followingVisibility }}</SearchLabel></template>
+ <option value="public">{{ i18n.ts._ffVisibility.public }}</option>
+ <option value="followers">{{ i18n.ts._ffVisibility.followers }}</option>
+ <option value="private">{{ i18n.ts._ffVisibility.private }}</option>
+ </MkSelect>
+ </SearchMarker>
- <MkSwitch v-model="hideOnlineStatus" @update:modelValue="save()">
- {{ i18n.ts.hideOnlineStatus }}
- <template #caption>{{ i18n.ts.hideOnlineStatusDescription }}</template>
- </MkSwitch>
- <MkSwitch v-model="noCrawle" @update:modelValue="save()">
- {{ i18n.ts.noCrawle }}
- <template #caption>{{ i18n.ts.noCrawleDescription }}</template>
- </MkSwitch>
- <MkSwitch v-model="preventAiLearning" @update:modelValue="save()">
- {{ i18n.ts.preventAiLearning }}
- <template #caption>{{ i18n.ts.preventAiLearningDescription }}</template>
- </MkSwitch>
- <MkSwitch v-model="isExplorable" @update:modelValue="save()">
- {{ i18n.ts.makeExplorable }}
- <template #caption>{{ i18n.ts.makeExplorableDescription }}</template>
- </MkSwitch>
+ <SearchMarker :keywords="['follower', 'visibility']">
+ <MkSelect v-model="followersVisibility" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.followersVisibility }}</SearchLabel></template>
+ <option value="public">{{ i18n.ts._ffVisibility.public }}</option>
+ <option value="followers">{{ i18n.ts._ffVisibility.followers }}</option>
+ <option value="private">{{ i18n.ts._ffVisibility.private }}</option>
+ </MkSelect>
+ </SearchMarker>
- <FormSection>
- <template #label>{{ i18n.ts.lockdown }}<span class="_beta">{{ i18n.ts.beta }}</span></template>
+ <SearchMarker :keywords="['online', 'status']">
+ <MkSwitch v-model="hideOnlineStatus" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.hideOnlineStatus }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.hideOnlineStatusDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
- <div class="_gaps_m">
- <MkSwitch :modelValue="requireSigninToViewContents" @update:modelValue="update_requireSigninToViewContents">
- {{ i18n.ts._accountSettings.requireSigninToViewContents }}
- <template #caption>
- <div>{{ i18n.ts._accountSettings.requireSigninToViewContentsDescription1 }}</div>
- <div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription2 }}</div>
- <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription3 }}</div>
- </template>
+ <SearchMarker :keywords="['crawle', 'index', 'search']">
+ <MkSwitch v-model="noCrawle" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.noCrawle }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.noCrawleDescription }}</SearchKeyword></template>
</MkSwitch>
+ </SearchMarker>
- <FormSlot>
- <template #label>{{ i18n.ts._accountSettings.makeNotesFollowersOnlyBefore }}</template>
+ <SearchMarker :keywords="['crawle', 'ai']">
+ <MkSwitch v-model="preventAiLearning" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.preventAiLearning }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.preventAiLearningDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
- <div class="_gaps_s">
- <MkSelect :modelValue="makeNotesFollowersOnlyBefore_type" @update:modelValue="makeNotesFollowersOnlyBefore = $event === 'relative' ? -604800 : $event === 'absolute' ? Math.floor(Date.now() / 1000) : null">
- <option :value="null">{{ i18n.ts.none }}</option>
- <option value="relative">{{ i18n.ts._accountSettings.notesHavePassedSpecifiedPeriod }}</option>
- <option value="absolute">{{ i18n.ts._accountSettings.notesOlderThanSpecifiedDateAndTime }}</option>
- </MkSelect>
+ <SearchMarker :keywords="['explore']">
+ <MkSwitch v-model="isExplorable" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.makeExplorable }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.makeExplorableDescription }}</SearchKeyword></template>
+ </MkSwitch>
+ </SearchMarker>
- <MkSelect v-if="makeNotesFollowersOnlyBefore_type === 'relative'" v-model="makeNotesFollowersOnlyBefore">
- <option :value="-3600">{{ i18n.ts.oneHour }}</option>
- <option :value="-86400">{{ i18n.ts.oneDay }}</option>
- <option :value="-259200">{{ i18n.ts.threeDays }}</option>
- <option :value="-604800">{{ i18n.ts.oneWeek }}</option>
- <option :value="-2592000">{{ i18n.ts.oneMonth }}</option>
- <option :value="-7776000">{{ i18n.ts.threeMonths }}</option>
- <option :value="-31104000">{{ i18n.ts.oneYear }}</option>
- </MkSelect>
+ <SearchMarker :keywords="['lockdown']">
+ <FormSection>
+ <template #label><SearchLabel>{{ i18n.ts.lockdown }}</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
- <MkInput
- v-if="makeNotesFollowersOnlyBefore_type === 'absolute'"
- :modelValue="formatDateTimeString(new Date(makeNotesFollowersOnlyBefore * 1000), 'yyyy-MM-dd')"
- type="date"
- :manualSave="true"
- @update:modelValue="makeNotesFollowersOnlyBefore = Math.floor(new Date($event).getTime() / 1000)"
- >
- </MkInput>
- </div>
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['login', 'signin']">
+ <MkSwitch :modelValue="requireSigninToViewContents" @update:modelValue="update_requireSigninToViewContents">
+ <template #label><SearchLabel>{{ i18n.ts._accountSettings.requireSigninToViewContents }}</SearchLabel></template>
+ <template #caption>
+ <div>{{ i18n.ts._accountSettings.requireSigninToViewContentsDescription1 }}</div>
+ <div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription2 }}</div>
+ <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription3 }}</div>
+ </template>
+ </MkSwitch>
+ </SearchMarker>
- <template #caption>
- <div>{{ i18n.ts._accountSettings.makeNotesFollowersOnlyBeforeDescription }}</div>
- <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div>
- </template>
- </FormSlot>
+ <SearchMarker :keywords="['follower']">
+ <FormSlot>
+ <template #label><SearchLabel>{{ i18n.ts._accountSettings.makeNotesFollowersOnlyBefore }}</SearchLabel></template>
- <FormSlot>
- <template #label>{{ i18n.ts._accountSettings.makeNotesHiddenBefore }}</template>
+ <div class="_gaps_s">
+ <MkSelect :modelValue="makeNotesFollowersOnlyBefore_type" @update:modelValue="makeNotesFollowersOnlyBefore = $event === 'relative' ? -604800 : $event === 'absolute' ? Math.floor(Date.now() / 1000) : null">
+ <option :value="null">{{ i18n.ts.none }}</option>
+ <option value="relative">{{ i18n.ts._accountSettings.notesHavePassedSpecifiedPeriod }}</option>
+ <option value="absolute">{{ i18n.ts._accountSettings.notesOlderThanSpecifiedDateAndTime }}</option>
+ </MkSelect>
- <div class="_gaps_s">
- <MkSelect :modelValue="makeNotesHiddenBefore_type" @update:modelValue="makeNotesHiddenBefore = $event === 'relative' ? -604800 : $event === 'absolute' ? Math.floor(Date.now() / 1000) : null">
- <option :value="null">{{ i18n.ts.none }}</option>
- <option value="relative">{{ i18n.ts._accountSettings.notesHavePassedSpecifiedPeriod }}</option>
- <option value="absolute">{{ i18n.ts._accountSettings.notesOlderThanSpecifiedDateAndTime }}</option>
- </MkSelect>
+ <MkSelect v-if="makeNotesFollowersOnlyBefore_type === 'relative'" v-model="makeNotesFollowersOnlyBefore">
+ <option :value="-3600">{{ i18n.ts.oneHour }}</option>
+ <option :value="-86400">{{ i18n.ts.oneDay }}</option>
+ <option :value="-259200">{{ i18n.ts.threeDays }}</option>
+ <option :value="-604800">{{ i18n.ts.oneWeek }}</option>
+ <option :value="-2592000">{{ i18n.ts.oneMonth }}</option>
+ <option :value="-7776000">{{ i18n.ts.threeMonths }}</option>
+ <option :value="-31104000">{{ i18n.ts.oneYear }}</option>
+ </MkSelect>
- <MkSelect v-if="makeNotesHiddenBefore_type === 'relative'" v-model="makeNotesHiddenBefore">
- <option :value="-3600">{{ i18n.ts.oneHour }}</option>
- <option :value="-86400">{{ i18n.ts.oneDay }}</option>
- <option :value="-259200">{{ i18n.ts.threeDays }}</option>
- <option :value="-604800">{{ i18n.ts.oneWeek }}</option>
- <option :value="-2592000">{{ i18n.ts.oneMonth }}</option>
- <option :value="-7776000">{{ i18n.ts.threeMonths }}</option>
- <option :value="-31104000">{{ i18n.ts.oneYear }}</option>
- </MkSelect>
+ <MkInput
+ v-if="makeNotesFollowersOnlyBefore_type === 'absolute'"
+ :modelValue="formatDateTimeString(new Date(makeNotesFollowersOnlyBefore * 1000), 'yyyy-MM-dd')"
+ type="date"
+ :manualSave="true"
+ @update:modelValue="makeNotesFollowersOnlyBefore = Math.floor(new Date($event).getTime() / 1000)"
+ >
+ </MkInput>
+ </div>
- <MkInput
- v-if="makeNotesHiddenBefore_type === 'absolute'"
- :modelValue="formatDateTimeString(new Date(makeNotesHiddenBefore * 1000), 'yyyy-MM-dd')"
- type="date"
- :manualSave="true"
- @update:modelValue="makeNotesHiddenBefore = Math.floor(new Date($event).getTime() / 1000)"
- >
- </MkInput>
- </div>
+ <template #caption>
+ <div><SearchKeyword>{{ i18n.ts._accountSettings.makeNotesFollowersOnlyBeforeDescription }}</SearchKeyword></div>
+ <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div>
+ </template>
+ </FormSlot>
+ </SearchMarker>
- <template #caption>
- <div>{{ i18n.ts._accountSettings.makeNotesHiddenBeforeDescription }}</div>
- <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div>
- </template>
- </FormSlot>
- </div>
- </FormSection>
+ <SearchMarker :keywords="['hidden']">
+ <FormSlot>
+ <template #label><SearchLabel>{{ i18n.ts._accountSettings.makeNotesHiddenBefore }}</SearchLabel></template>
- <FormSection>
- <div class="_gaps_m">
- <MkSwitch v-model="rememberNoteVisibility" @update:modelValue="save()">{{ i18n.ts.rememberNoteVisibility }}</MkSwitch>
- <MkFolder v-if="!rememberNoteVisibility">
- <template #label>{{ i18n.ts.defaultNoteVisibility }}</template>
- <template v-if="defaultNoteVisibility === 'public'" #suffix>{{ i18n.ts._visibility.public }}</template>
- <template v-else-if="defaultNoteVisibility === 'home'" #suffix>{{ i18n.ts._visibility.home }}</template>
- <template v-else-if="defaultNoteVisibility === 'followers'" #suffix>{{ i18n.ts._visibility.followers }}</template>
- <template v-else-if="defaultNoteVisibility === 'specified'" #suffix>{{ i18n.ts._visibility.specified }}</template>
+ <div class="_gaps_s">
+ <MkSelect :modelValue="makeNotesHiddenBefore_type" @update:modelValue="makeNotesHiddenBefore = $event === 'relative' ? -604800 : $event === 'absolute' ? Math.floor(Date.now() / 1000) : null">
+ <option :value="null">{{ i18n.ts.none }}</option>
+ <option value="relative">{{ i18n.ts._accountSettings.notesHavePassedSpecifiedPeriod }}</option>
+ <option value="absolute">{{ i18n.ts._accountSettings.notesOlderThanSpecifiedDateAndTime }}</option>
+ </MkSelect>
- <div class="_gaps_m">
- <MkSelect v-model="defaultNoteVisibility">
- <option value="public">{{ i18n.ts._visibility.public }}</option>
- <option value="home">{{ i18n.ts._visibility.home }}</option>
- <option value="followers">{{ i18n.ts._visibility.followers }}</option>
- <option value="specified">{{ i18n.ts._visibility.specified }}</option>
- </MkSelect>
- <MkSwitch v-model="defaultNoteLocalOnly">{{ i18n.ts._visibility.disableFederation }}</MkSwitch>
+ <MkSelect v-if="makeNotesHiddenBefore_type === 'relative'" v-model="makeNotesHiddenBefore">
+ <option :value="-3600">{{ i18n.ts.oneHour }}</option>
+ <option :value="-86400">{{ i18n.ts.oneDay }}</option>
+ <option :value="-259200">{{ i18n.ts.threeDays }}</option>
+ <option :value="-604800">{{ i18n.ts.oneWeek }}</option>
+ <option :value="-2592000">{{ i18n.ts.oneMonth }}</option>
+ <option :value="-7776000">{{ i18n.ts.threeMonths }}</option>
+ <option :value="-31104000">{{ i18n.ts.oneYear }}</option>
+ </MkSelect>
+
+ <MkInput
+ v-if="makeNotesHiddenBefore_type === 'absolute'"
+ :modelValue="formatDateTimeString(new Date(makeNotesHiddenBefore * 1000), 'yyyy-MM-dd')"
+ type="date"
+ :manualSave="true"
+ @update:modelValue="makeNotesHiddenBefore = Math.floor(new Date($event).getTime() / 1000)"
+ >
+ </MkInput>
+ </div>
+
+ <template #caption>
+ <div><SearchKeyword>{{ i18n.ts._accountSettings.makeNotesHiddenBeforeDescription }}</SearchKeyword></div>
+ <div v-if="instance.federation !== 'none'"><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div>
+ </template>
+ </FormSlot>
+ </SearchMarker>
</div>
- </MkFolder>
- </div>
- </FormSection>
+ </FormSection>
+ </SearchMarker>
+
+ <FormSection>
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['remember', 'keep', 'note', 'visibility']">
+ <MkSwitch v-model="rememberNoteVisibility" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.rememberNoteVisibility }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
- <MkSwitch v-model="keepCw" @update:modelValue="save()">{{ i18n.ts.keepCw }}</MkSwitch>
-</div>
+ <SearchMarker :keywords="['default', 'note', 'visibility']">
+ <MkFolder v-if="!rememberNoteVisibility">
+ <template #label><SearchLabel>{{ i18n.ts.defaultNoteVisibility }}</SearchLabel></template>
+ <template v-if="defaultNoteVisibility === 'public'" #suffix>{{ i18n.ts._visibility.public }}</template>
+ <template v-else-if="defaultNoteVisibility === 'home'" #suffix>{{ i18n.ts._visibility.home }}</template>
+ <template v-else-if="defaultNoteVisibility === 'followers'" #suffix>{{ i18n.ts._visibility.followers }}</template>
+ <template v-else-if="defaultNoteVisibility === 'specified'" #suffix>{{ i18n.ts._visibility.specified }}</template>
+
+ <div class="_gaps_m">
+ <MkSelect v-model="defaultNoteVisibility">
+ <option value="public">{{ i18n.ts._visibility.public }}</option>
+ <option value="home">{{ i18n.ts._visibility.home }}</option>
+ <option value="followers">{{ i18n.ts._visibility.followers }}</option>
+ <option value="specified">{{ i18n.ts._visibility.specified }}</option>
+ </MkSelect>
+ <MkSwitch v-model="defaultNoteLocalOnly">{{ i18n.ts._visibility.disableFederation }}</MkSwitch>
+ </div>
+ </MkFolder>
+ </SearchMarker>
+ </div>
+ </FormSection>
+
+ <SearchMarker :keywords="['remember', 'keep', 'note', 'cw']">
+ <MkSwitch v-model="keepCw" @update:modelValue="save()">
+ <template #label><SearchLabel>{{ i18n.ts.keepCw }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
@@ -174,6 +224,7 @@ import FormSlot from '@/components/form/slot.vue';
import { formatDateTimeString } from '@/scripts/format-time-string.js';
import MkInput from '@/components/MkInput.vue';
import * as os from '@/os.js';
+import MkDisableSection from '@/components/MkDisableSection.vue';
const $i = signinRequired();
diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue
index 561894d2b7..51148a1f72 100644
--- a/packages/frontend/src/pages/settings/profile.vue
+++ b/packages/frontend/src/pages/settings/profile.vue
@@ -4,115 +4,152 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m">
- <div class="_panel">
- <div :class="$style.banner" :style="{ backgroundImage: $i.bannerUrl ? `url(${ $i.bannerUrl })` : null }">
- <MkButton primary rounded :class="$style.bannerEdit" @click="changeBanner">{{ i18n.ts._profile.changeBanner }}</MkButton>
- </div>
- <div :class="$style.avatarContainer">
- <MkAvatar :class="$style.avatar" :user="$i" forceShowDecoration @click="changeAvatar"/>
- <div class="_buttonsCenter">
- <MkButton primary rounded @click="changeAvatar">{{ i18n.ts._profile.changeAvatar }}</MkButton>
- <MkButton primary rounded link to="/settings/avatar-decoration">{{ i18n.ts.decorate }} <i class="ti ti-sparkles"></i></MkButton>
+<SearchMarker path="/settings/profile" :label="i18n.ts.profile" :keywords="['profile']" icon="ti ti-user">
+ <div class="_gaps_m">
+ <div class="_panel">
+ <div :class="$style.banner" :style="{ backgroundImage: $i.bannerUrl ? `url(${ $i.bannerUrl })` : null }">
+ <div :class="$style.bannerEdit">
+ <SearchMarker :keywords="['banner', 'change']">
+ <MkButton primary rounded @click="changeBanner"><SearchLabel>{{ i18n.ts._profile.changeBanner }}</SearchLabel></MkButton>
+ </SearchMarker>
+ </div>
+ </div>
+ <div :class="$style.avatarContainer">
+ <MkAvatar :class="$style.avatar" :user="$i" forceShowDecoration @click="changeAvatar"/>
+ <div class="_buttonsCenter">
+ <SearchMarker :keywords="['avatar', 'icon', 'change']">
+ <MkButton primary rounded @click="changeAvatar"><SearchLabel>{{ i18n.ts._profile.changeAvatar }}</SearchLabel></MkButton>
+ </SearchMarker>
+ <MkButton primary rounded link to="/settings/avatar-decoration">{{ i18n.ts.decorate }} <i class="ti ti-sparkles"></i></MkButton>
+ </div>
</div>
</div>
- </div>
-
- <MkInput v-model="profile.name" :max="30" manualSave :mfmAutocomplete="['emoji']">
- <template #label>{{ i18n.ts._profile.name }}</template>
- </MkInput>
- <MkTextarea v-model="profile.description" :max="500" tall manualSave mfmAutocomplete :mfmPreview="true">
- <template #label>{{ i18n.ts._profile.description }}</template>
- <template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template>
- </MkTextarea>
+ <SearchMarker :keywords="['name']">
+ <MkInput v-model="profile.name" :max="30" manualSave :mfmAutocomplete="['emoji']">
+ <template #label><SearchLabel>{{ i18n.ts._profile.name }}</SearchLabel></template>
+ </MkInput>
+ </SearchMarker>
- <MkInput v-model="profile.location" manualSave>
- <template #label>{{ i18n.ts.location }}</template>
- <template #prefix><i class="ti ti-map-pin"></i></template>
- </MkInput>
+ <SearchMarker :keywords="['description', 'bio']">
+ <MkTextarea v-model="profile.description" :max="500" tall manualSave mfmAutocomplete :mfmPreview="true">
+ <template #label><SearchLabel>{{ i18n.ts._profile.description }}</SearchLabel></template>
+ <template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template>
+ </MkTextarea>
+ </SearchMarker>
- <MkInput v-model="profile.birthday" type="date" manualSave>
- <template #label>{{ i18n.ts.birthday }}</template>
- <template #prefix><i class="ti ti-cake"></i></template>
- </MkInput>
+ <SearchMarker :keywords="['location', 'locale']">
+ <MkInput v-model="profile.location" manualSave>
+ <template #label><SearchLabel>{{ i18n.ts.location }}</SearchLabel></template>
+ <template #prefix><i class="ti ti-map-pin"></i></template>
+ </MkInput>
+ </SearchMarker>
- <MkSelect v-model="profile.lang">
- <template #label>{{ i18n.ts.language }}</template>
- <option v-for="x in Object.keys(langmap)" :key="x" :value="x">{{ langmap[x].nativeName }}</option>
- </MkSelect>
-
- <FormSlot>
- <MkFolder>
- <template #icon><i class="ti ti-list"></i></template>
- <template #label>{{ i18n.ts._profile.metadataEdit }}</template>
- <template #footer>
- <div class="_buttons">
- <MkButton primary @click="saveFields"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
- <MkButton :disabled="fields.length >= 16" @click="addField"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
- <MkButton v-if="!fieldEditMode" :disabled="fields.length <= 1" danger @click="fieldEditMode = !fieldEditMode"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
- <MkButton v-else @click="fieldEditMode = !fieldEditMode"><i class="ti ti-arrows-sort"></i> {{ i18n.ts.rearrange }}</MkButton>
- </div>
- </template>
+ <SearchMarker :keywords="['birthday', 'birthdate', 'age']">
+ <MkInput v-model="profile.birthday" type="date" manualSave>
+ <template #label><SearchLabel>{{ i18n.ts.birthday }}</SearchLabel></template>
+ <template #prefix><i class="ti ti-cake"></i></template>
+ </MkInput>
+ </SearchMarker>
- <div :class="$style.metadataRoot" class="_gaps_s">
- <MkInfo>{{ i18n.ts._profile.verifiedLinkDescription }}</MkInfo>
+ <SearchMarker :keywords="['language', 'locale']">
+ <MkSelect v-model="profile.lang">
+ <template #label><SearchLabel>{{ i18n.ts.language }}</SearchLabel></template>
+ <option v-for="x in Object.keys(langmap)" :key="x" :value="x">{{ langmap[x].nativeName }}</option>
+ </MkSelect>
+ </SearchMarker>
- <Sortable
- v-model="fields"
- class="_gaps_s"
- itemKey="id"
- :animation="150"
- :handle="'.' + $style.dragItemHandle"
- @start="e => e.item.classList.add('active')"
- @end="e => e.item.classList.remove('active')"
- >
- <template #item="{element, index}">
- <div v-panel :class="$style.fieldDragItem">
- <button v-if="!fieldEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button>
- <button v-if="fieldEditMode" :disabled="fields.length <= 1" class="_button" :class="$style.dragItemRemove" @click="deleteField(index)"><i class="ti ti-x"></i></button>
- <div :class="$style.dragItemForm">
- <FormSplit :minWidth="200">
- <MkInput v-model="element.name" small :placeholder="i18n.ts._profile.metadataLabel">
- </MkInput>
- <MkInput v-model="element.value" small :placeholder="i18n.ts._profile.metadataContent">
- </MkInput>
- </FormSplit>
- </div>
+ <SearchMarker :keywords="['metadata']">
+ <FormSlot>
+ <MkFolder>
+ <template #icon><i class="ti ti-list"></i></template>
+ <template #label><SearchLabel>{{ i18n.ts._profile.metadataEdit }}</SearchLabel></template>
+ <template #footer>
+ <div class="_buttons">
+ <MkButton primary @click="saveFields"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
+ <MkButton :disabled="fields.length >= 16" @click="addField"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
+ <MkButton v-if="!fieldEditMode" :disabled="fields.length <= 1" danger @click="fieldEditMode = !fieldEditMode"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
+ <MkButton v-else @click="fieldEditMode = !fieldEditMode"><i class="ti ti-arrows-sort"></i> {{ i18n.ts.rearrange }}</MkButton>
</div>
</template>
- </Sortable>
- </div>
- </MkFolder>
- <template #caption>{{ i18n.ts._profile.metadataDescription }}</template>
- </FormSlot>
- <MkInput v-model="profile.followedMessage" :max="200" manualSave :mfmPreview="false">
- <template #label>{{ i18n.ts._profile.followedMessage }}<span class="_beta">{{ i18n.ts.beta }}</span></template>
- <template #caption>
- <div>{{ i18n.ts._profile.followedMessageDescription }}</div>
- <div>{{ i18n.ts._profile.followedMessageDescriptionForLockedAccount }}</div>
- </template>
- </MkInput>
+ <div :class="$style.metadataRoot" class="_gaps_s">
+ <MkInfo>{{ i18n.ts._profile.verifiedLinkDescription }}</MkInfo>
- <MkSelect v-model="reactionAcceptance">
- <template #label>{{ i18n.ts.reactionAcceptance }}</template>
- <option :value="null">{{ i18n.ts.all }}</option>
- <option value="likeOnlyForRemote">{{ i18n.ts.likeOnlyForRemote }}</option>
- <option value="nonSensitiveOnly">{{ i18n.ts.nonSensitiveOnly }}</option>
- <option value="nonSensitiveOnlyForLocalLikeOnlyForRemote">{{ i18n.ts.nonSensitiveOnlyForLocalLikeOnlyForRemote }}</option>
- <option value="likeOnly">{{ i18n.ts.likeOnly }}</option>
- </MkSelect>
+ <Sortable
+ v-model="fields"
+ class="_gaps_s"
+ itemKey="id"
+ :animation="150"
+ :handle="'.' + $style.dragItemHandle"
+ @start="e => e.item.classList.add('active')"
+ @end="e => e.item.classList.remove('active')"
+ >
+ <template #item="{element, index}">
+ <div v-panel :class="$style.fieldDragItem">
+ <button v-if="!fieldEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button>
+ <button v-if="fieldEditMode" :disabled="fields.length <= 1" class="_button" :class="$style.dragItemRemove" @click="deleteField(index)"><i class="ti ti-x"></i></button>
+ <div :class="$style.dragItemForm">
+ <FormSplit :minWidth="200">
+ <MkInput v-model="element.name" small :placeholder="i18n.ts._profile.metadataLabel">
+ </MkInput>
+ <MkInput v-model="element.value" small :placeholder="i18n.ts._profile.metadataContent">
+ </MkInput>
+ </FormSplit>
+ </div>
+ </div>
+ </template>
+ </Sortable>
+ </div>
+ </MkFolder>
+ <template #caption>{{ i18n.ts._profile.metadataDescription }}</template>
+ </FormSlot>
+ </SearchMarker>
- <MkFolder>
- <template #label>{{ i18n.ts.advancedSettings }}</template>
+ <SearchMarker :keywords="['follow', 'message']">
+ <MkInput v-model="profile.followedMessage" :max="200" manualSave :mfmPreview="false">
+ <template #label><SearchLabel>{{ i18n.ts._profile.followedMessage }}</SearchLabel><span class="_beta">{{ i18n.ts.beta }}</span></template>
+ <template #caption>
+ <div><SearchKeyword>{{ i18n.ts._profile.followedMessageDescription }}</SearchKeyword></div>
+ <div>{{ i18n.ts._profile.followedMessageDescriptionForLockedAccount }}</div>
+ </template>
+ </MkInput>
+ </SearchMarker>
- <div class="_gaps_m">
- <MkSwitch v-model="profile.isCat">{{ i18n.ts.flagAsCat }}<template #caption>{{ i18n.ts.flagAsCatDescription }}</template></MkSwitch>
- <MkSwitch v-model="profile.isBot">{{ i18n.ts.flagAsBot }}<template #caption>{{ i18n.ts.flagAsBotDescription }}</template></MkSwitch>
- </div>
- </MkFolder>
-</div>
+ <SearchMarker :keywords="['reaction']">
+ <MkSelect v-model="reactionAcceptance">
+ <template #label><SearchLabel>{{ i18n.ts.reactionAcceptance }}</SearchLabel></template>
+ <option :value="null">{{ i18n.ts.all }}</option>
+ <option value="likeOnlyForRemote">{{ i18n.ts.likeOnlyForRemote }}</option>
+ <option value="nonSensitiveOnly">{{ i18n.ts.nonSensitiveOnly }}</option>
+ <option value="nonSensitiveOnlyForLocalLikeOnlyForRemote">{{ i18n.ts.nonSensitiveOnlyForLocalLikeOnlyForRemote }}</option>
+ <option value="likeOnly">{{ i18n.ts.likeOnly }}</option>
+ </MkSelect>
+ </SearchMarker>
+
+ <SearchMarker>
+ <MkFolder>
+ <template #label><SearchLabel>{{ i18n.ts.advancedSettings }}</SearchLabel></template>
+
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['cat']">
+ <MkSwitch v-model="profile.isCat">
+ <template #label><SearchLabel>{{ i18n.ts.flagAsCat }}</SearchLabel></template>
+ <template #caption>{{ i18n.ts.flagAsCatDescription }}</template>
+ </MkSwitch>
+ </SearchMarker>
+
+ <SearchMarker :keywords="['bot']">
+ <MkSwitch v-model="profile.isBot">
+ <template #label><SearchLabel>{{ i18n.ts.flagAsBot }}</SearchLabel></template>
+ <template #caption>{{ i18n.ts.flagAsBotDescription }}</template>
+ </MkSwitch>
+ </SearchMarker>
+ </div>
+ </MkFolder>
+ </SearchMarker>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/pages/settings/security.vue b/packages/frontend/src/pages/settings/security.vue
index 8f9d4f858b..f365146e0a 100644
--- a/packages/frontend/src/pages/settings/security.vue
+++ b/packages/frontend/src/pages/settings/security.vue
@@ -4,39 +4,48 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m">
- <FormSection first>
- <template #label>{{ i18n.ts.password }}</template>
- <MkButton primary @click="change()">{{ i18n.ts.changePassword }}</MkButton>
- </FormSection>
+<SearchMarker path="/settings/security" :label="i18n.ts.security" :keywords="['security']" icon="ti ti-lock" :inlining="['2fa']">
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['password']">
+ <FormSection first>
+ <template #label><SearchLabel>{{ i18n.ts.password }}</SearchLabel></template>
- <X2fa/>
+ <SearchMarker>
+ <MkButton primary @click="change()">
+ <SearchLabel>{{ i18n.ts.changePassword }}</SearchLabel>
+ </MkButton>
+ </SearchMarker>
+ </FormSection>
+ </SearchMarker>
- <FormSection>
- <template #label>{{ i18n.ts.signinHistory }}</template>
- <MkPagination :pagination="pagination" disableAutoLoad>
- <template #default="{items}">
- <div>
- <div v-for="item in items" :key="item.id" v-panel class="timnmucd">
- <header>
- <i v-if="item.success" class="ti ti-check icon succ"></i>
- <i v-else class="ti ti-circle-x icon fail"></i>
- <code class="ip _monospace">{{ item.ip }}</code>
- <MkTime :time="item.createdAt" class="time"/>
- </header>
+ <X2fa/>
+
+ <FormSection>
+ <template #label>{{ i18n.ts.signinHistory }}</template>
+ <MkPagination :pagination="pagination" disableAutoLoad>
+ <template #default="{items}">
+ <div>
+ <div v-for="item in items" :key="item.id" v-panel class="timnmucd">
+ <header>
+ <i v-if="item.success" class="ti ti-check icon succ"></i>
+ <i v-else class="ti ti-circle-x icon fail"></i>
+ <code class="ip _monospace">{{ item.ip }}</code>
+ <MkTime :time="item.createdAt" class="time"/>
+ </header>
+ </div>
</div>
- </div>
- </template>
- </MkPagination>
- </FormSection>
+ </template>
+ </MkPagination>
+ </FormSection>
- <FormSection>
- <FormSlot>
- <MkButton danger @click="regenerateToken"><i class="ti ti-refresh"></i> {{ i18n.ts.regenerateLoginToken }}</MkButton>
- <template #caption>{{ i18n.ts.regenerateLoginTokenDescription }}</template>
- </FormSlot>
- </FormSection>
-</div>
+ <FormSection>
+ <FormSlot>
+ <MkButton danger @click="regenerateToken"><i class="ti ti-refresh"></i> {{ i18n.ts.regenerateLoginToken }}</MkButton>
+ <template #caption>{{ i18n.ts.regenerateLoginTokenDescription }}</template>
+ </FormSlot>
+ </FormSection>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/pages/settings/sounds.vue b/packages/frontend/src/pages/settings/sounds.vue
index bf461f173b..1df2d89277 100644
--- a/packages/frontend/src/pages/settings/sounds.vue
+++ b/packages/frontend/src/pages/settings/sounds.vue
@@ -4,43 +4,53 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m">
- <MkSwitch v-model="notUseSound">
- <template #label>{{ i18n.ts.notUseSound }}</template>
- </MkSwitch>
- <MkSwitch v-model="useSoundOnlyWhenActive">
- <template #label>{{ i18n.ts.useSoundOnlyWhenActive }}</template>
- </MkSwitch>
- <MkRange v-model="masterVolume" :min="0" :max="1" :step="0.05" :textConverter="(v) => `${Math.floor(v * 100)}%`">
- <template #label>{{ i18n.ts.masterVolume }}</template>
- </MkRange>
+<SearchMarker path="/settings/sounds" :label="i18n.ts.sounds" :keywords="['sounds']" icon="ti ti-music">
+ <div class="_gaps_m">
+ <SearchMarker :keywords="['mute']">
+ <MkSwitch v-model="notUseSound">
+ <template #label><SearchLabel>{{ i18n.ts.notUseSound }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
- <FormSection>
- <template #label>{{ i18n.ts.sounds }}</template>
- <div class="_gaps_s">
- <MkFolder v-for="type in operationTypes" :key="type">
- <template #label>{{ i18n.ts._sfx[type] }}</template>
- <template #suffix>{{ getSoundTypeName(sounds[type].type) }}</template>
- <Suspense>
- <template #default>
- <XSound :type="sounds[type].type" :volume="sounds[type].volume" :fileId="sounds[type].fileId" :fileUrl="sounds[type].fileUrl" @update="(res) => updated(type, res)"/>
- </template>
- <template #fallback>
- <MkLoading/>
- </template>
- </Suspense>
- </MkFolder>
- </div>
- </FormSection>
+ <SearchMarker :keywords="['active', 'mute']">
+ <MkSwitch v-model="useSoundOnlyWhenActive">
+ <template #label><SearchLabel>{{ i18n.ts.useSoundOnlyWhenActive }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
- <MkButton danger @click="reset()"><i class="ti ti-reload"></i> {{ i18n.ts.default }}</MkButton>
-</div>
+ <SearchMarker :keywords="['volume', 'master']">
+ <MkRange v-model="masterVolume" :min="0" :max="1" :step="0.05" :textConverter="(v) => `${Math.floor(v * 100)}%`">
+ <template #label><SearchLabel>{{ i18n.ts.masterVolume }}</SearchLabel></template>
+ </MkRange>
+ </SearchMarker>
+
+ <FormSection>
+ <template #label>{{ i18n.ts.sounds }}</template>
+ <div class="_gaps_s">
+ <MkFolder v-for="type in operationTypes" :key="type">
+ <template #label>{{ i18n.ts._sfx[type] }}</template>
+ <template #suffix>{{ getSoundTypeName(sounds[type].type) }}</template>
+ <Suspense>
+ <template #default>
+ <XSound :type="sounds[type].type" :volume="sounds[type].volume" :fileId="sounds[type].fileId" :fileUrl="sounds[type].fileUrl" @update="(res) => updated(type, res)"/>
+ </template>
+ <template #fallback>
+ <MkLoading/>
+ </template>
+ </Suspense>
+ </MkFolder>
+ </div>
+ </FormSection>
+
+ <MkButton danger @click="reset()"><i class="ti ti-reload"></i> {{ i18n.ts.default }}</MkButton>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
-import type { Ref } from 'vue';
import XSound from './sounds.sound.vue';
+import type { Ref } from 'vue';
import type { SoundType, OperationType } from '@/scripts/sound.js';
import type { SoundStore } from '@/store.js';
import MkRange from '@/components/MkRange.vue';
diff --git a/packages/frontend/src/pages/settings/theme.vue b/packages/frontend/src/pages/settings/theme.vue
index fcf5b3cd9b..b0e4ce13d5 100644
--- a/packages/frontend/src/pages/settings/theme.vue
+++ b/packages/frontend/src/pages/settings/theme.vue
@@ -4,56 +4,72 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div class="_gaps_m rsljpzjq">
- <div v-adaptive-border class="rfqxtzch _panel">
- <div class="toggle">
- <div class="toggleWrapper">
- <input id="dn" v-model="darkMode" type="checkbox" class="dn"/>
- <label for="dn" class="toggle">
- <span class="before">{{ i18n.ts.light }}</span>
- <span class="after">{{ i18n.ts.dark }}</span>
- <span class="toggle__handler">
- <span class="crater crater--1"></span>
- <span class="crater crater--2"></span>
- <span class="crater crater--3"></span>
- </span>
- <span class="star star--1"></span>
- <span class="star star--2"></span>
- <span class="star star--3"></span>
- <span class="star star--4"></span>
- <span class="star star--5"></span>
- <span class="star star--6"></span>
- </label>
+<SearchMarker path="/settings/theme" :label="i18n.ts.theme" :keywords="['theme']" icon="ti ti-palette">
+ <div class="_gaps_m rsljpzjq">
+ <div v-adaptive-border class="rfqxtzch _panel">
+ <div class="toggle">
+ <div class="toggleWrapper">
+ <input id="dn" v-model="darkMode" type="checkbox" class="dn"/>
+ <label for="dn" class="toggle">
+ <span class="before">{{ i18n.ts.light }}</span>
+ <span class="after">{{ i18n.ts.dark }}</span>
+ <span class="toggle__handler">
+ <span class="crater crater--1"></span>
+ <span class="crater crater--2"></span>
+ <span class="crater crater--3"></span>
+ </span>
+ <span class="star star--1"></span>
+ <span class="star star--2"></span>
+ <span class="star star--3"></span>
+ <span class="star star--4"></span>
+ <span class="star star--5"></span>
+ <span class="star star--6"></span>
+ </label>
+ </div>
+ </div>
+ <div class="sync">
+ <SearchMarker :keywords="['sync', 'device', 'dark', 'light', 'mode']">
+ <MkSwitch v-model="syncDeviceDarkMode">
+ <template #label><SearchLabel>{{ i18n.ts.syncDeviceDarkMode }}</SearchLabel></template>
+ </MkSwitch>
+ </SearchMarker>
</div>
</div>
- <div class="sync">
- <MkSwitch v-model="syncDeviceDarkMode">{{ i18n.ts.syncDeviceDarkMode }}</MkSwitch>
- </div>
- </div>
-
- <div class="selects">
- <MkSelect v-model="lightThemeId" large class="select" :items="lightThemeSelectorItems">
- <template #label>{{ i18n.ts.themeForLightMode }}</template>
- <template #prefix><i class="ti ti-sun"></i></template>
- </MkSelect>
- <MkSelect v-model="darkThemeId" large class="select" :items="darkThemeSelectorItems">
- <template #label>{{ i18n.ts.themeForDarkMode }}</template>
- <template #prefix><i class="ti ti-moon"></i></template>
- </MkSelect>
- </div>
- <FormSection>
- <div class="_formLinksGrid">
- <FormLink to="/settings/theme/manage"><template #icon><i class="ti ti-tool"></i></template>{{ i18n.ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink>
- <FormLink to="https://assets.misskey.io/theme/list" external><template #icon><i class="ti ti-world"></i></template>{{ i18n.ts._theme.explore }}</FormLink>
- <FormLink to="/settings/theme/install"><template #icon><i class="ti ti-download"></i></template>{{ i18n.ts._theme.install }}</FormLink>
- <FormLink to="/theme-editor"><template #icon><i class="ti ti-paint"></i></template>{{ i18n.ts._theme.make }}</FormLink>
+ <div class="selects">
+ <div class="select">
+ <SearchMarker :keywords="['light', 'theme']">
+ <MkSelect v-model="lightThemeId" large :items="lightThemeSelectorItems">
+ <template #label><SearchLabel>{{ i18n.ts.themeForLightMode }}</SearchLabel></template>
+ <template #prefix><i class="ti ti-sun"></i></template>
+ </MkSelect>
+ </SearchMarker>
+ </div>
+ <div class="select">
+ <SearchMarker :keywords="['dark', 'theme']">
+ <MkSelect v-model="darkThemeId" large :items="darkThemeSelectorItems">
+ <template #label><SearchLabel>{{ i18n.ts.themeForDarkMode }}</SearchLabel></template>
+ <template #prefix><i class="ti ti-moon"></i></template>
+ </MkSelect>
+ </SearchMarker>
+ </div>
</div>
- </FormSection>
- <MkButton v-if="wallpaper == null" @click="setWallpaper">{{ i18n.ts.setWallpaper }}</MkButton>
- <MkButton v-else @click="wallpaper = null">{{ i18n.ts.removeWallpaper }}</MkButton>
-</div>
+ <FormSection>
+ <div class="_formLinksGrid">
+ <FormLink to="/settings/theme/manage"><template #icon><i class="ti ti-tool"></i></template>{{ i18n.ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink>
+ <FormLink to="https://assets.misskey.io/theme/list" external><template #icon><i class="ti ti-world"></i></template>{{ i18n.ts._theme.explore }}</FormLink>
+ <FormLink to="/settings/theme/install"><template #icon><i class="ti ti-download"></i></template>{{ i18n.ts._theme.install }}</FormLink>
+ <FormLink to="/theme-editor"><template #icon><i class="ti ti-paint"></i></template>{{ i18n.ts._theme.make }}</FormLink>
+ </div>
+ </FormSection>
+
+ <SearchMarker :keywords="['wallpaper']">
+ <MkButton v-if="wallpaper == null" @click="setWallpaper"><SearchLabel>{{ i18n.ts.setWallpaper }}</SearchLabel></MkButton>
+ <MkButton v-else @click="wallpaper = null">{{ i18n.ts.removeWallpaper }}</MkButton>
+ </SearchMarker>
+ </div>
+</SearchMarker>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/router/definition.ts b/packages/frontend/src/router/definition.ts
index d2a4484c45..c6ee128f5f 100644
--- a/packages/frontend/src/router/definition.ts
+++ b/packages/frontend/src/router/definition.ts
@@ -90,9 +90,9 @@ const routes: RouteDef[] = [{
name: 'security',
component: page(() => import('@/pages/settings/security.vue')),
}, {
- path: '/general',
- name: 'general',
- component: page(() => import('@/pages/settings/general.vue')),
+ path: '/preferences',
+ name: 'preferences',
+ component: page(() => import('@/pages/settings/preferences.vue')),
}, {
path: '/theme/install',
name: 'theme',
@@ -106,6 +106,10 @@ const routes: RouteDef[] = [{
name: 'theme',
component: page(() => import('@/pages/settings/theme.vue')),
}, {
+ path: '/appearance',
+ name: 'appearance',
+ component: page(() => import('@/pages/settings/appearance.vue')),
+ }, {
path: '/navbar',
name: 'navbar',
component: page(() => import('@/pages/settings/navbar.vue')),
@@ -118,6 +122,10 @@ const routes: RouteDef[] = [{
name: 'sounds',
component: page(() => import('@/pages/settings/sounds.vue')),
}, {
+ path: '/accessibility',
+ name: 'accessibility',
+ component: page(() => import('@/pages/settings/accessibility.vue')),
+ }, {
path: '/plugin/install',
name: 'plugin',
component: page(() => import('@/pages/settings/plugin.install.vue')),
@@ -162,12 +170,8 @@ const routes: RouteDef[] = [{
name: 'preferences-backups',
component: page(() => import('@/pages/settings/preferences-backups.vue')),
}, {
- path: '/migration',
- name: 'migration',
- component: page(() => import('@/pages/settings/migration.vue')),
- }, {
path: '/custom-css',
- name: 'general',
+ name: 'preferences',
component: page(() => import('@/pages/settings/custom-css.vue')),
}, {
path: '/accounts',
diff --git a/packages/frontend/src/scripts/autogen/settings-search-index.ts b/packages/frontend/src/scripts/autogen/settings-search-index.ts
new file mode 100644
index 0000000000..c62272b271
--- /dev/null
+++ b/packages/frontend/src/scripts/autogen/settings-search-index.ts
@@ -0,0 +1,815 @@
+
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+// This file was automatically generated by create-search-index.
+// Do not edit this file.
+
+import { i18n } from '@/i18n.js';
+
+export type SearchIndexItem = {
+ id: string;
+ path?: string;
+ label: string;
+ keywords: string[];
+ icon?: string;
+ children?: SearchIndexItem[];
+};
+
+export const searchIndexes: SearchIndexItem[] = [
+ {
+ id: 'flXd1LC7r',
+ children: [
+ {
+ id: 'hB11H5oul',
+ label: i18n.ts.syncDeviceDarkMode,
+ keywords: ['sync', 'device', 'dark', 'light', 'mode'],
+ },
+ {
+ id: 'fDbLtIKeo',
+ label: i18n.ts.themeForLightMode,
+ keywords: ['light', 'theme'],
+ },
+ {
+ id: 'eLOwK5Ia2',
+ label: i18n.ts.themeForDarkMode,
+ keywords: ['dark', 'theme'],
+ },
+ {
+ id: 'ujvMfyzUr',
+ label: i18n.ts.setWallpaper,
+ keywords: ['wallpaper'],
+ },
+ ],
+ label: i18n.ts.theme,
+ keywords: ['theme'],
+ path: '/settings/theme',
+ icon: 'ti ti-palette',
+ },
+ {
+ id: '6fFIRXUww',
+ children: [
+ {
+ id: 'nO7NnzqiC',
+ label: i18n.ts.notUseSound,
+ keywords: ['mute'],
+ },
+ {
+ id: 'xy5OOBB4A',
+ label: i18n.ts.useSoundOnlyWhenActive,
+ keywords: ['active', 'mute'],
+ },
+ {
+ id: '9MxYVIf7k',
+ label: i18n.ts.masterVolume,
+ keywords: ['volume', 'master'],
+ },
+ ],
+ label: i18n.ts.sounds,
+ keywords: ['sounds'],
+ path: '/settings/sounds',
+ icon: 'ti ti-music',
+ },
+ {
+ id: '5BjnxMfYV',
+ children: [
+ {
+ id: '3UqdSCaFw',
+ children: [
+ {
+ id: '75QPEg57v',
+ label: i18n.ts.changePassword,
+ keywords: [],
+ },
+ ],
+ label: i18n.ts.password,
+ keywords: ['password'],
+ },
+ {
+ id: '2fa',
+ children: [
+ {
+ id: 'qCXM0HtJ7',
+ label: i18n.ts.totp,
+ keywords: ['totp', 'app', i18n.ts.totpDescription],
+ },
+ {
+ id: '3g1RePuD9',
+ label: i18n.ts.securityKeyAndPasskey,
+ keywords: ['security', 'key', 'passkey'],
+ },
+ {
+ id: 'pFRud5u8k',
+ label: i18n.ts.passwordLessLogin,
+ keywords: ['password', 'less', 'key', 'passkey', 'login', 'signin', i18n.ts.passwordLessLoginDescription],
+ },
+ ],
+ label: i18n.ts['2fa'],
+ keywords: ['2fa'],
+ },
+ ],
+ label: i18n.ts.security,
+ keywords: ['security'],
+ path: '/settings/security',
+ icon: 'ti ti-lock',
+ },
+ {
+ id: 'w4L6myH61',
+ children: [
+ {
+ id: 'ru8DrOn3J',
+ label: i18n.ts._profile.changeBanner,
+ keywords: ['banner', 'change'],
+ },
+ {
+ id: 'CCnD8Apnu',
+ label: i18n.ts._profile.changeAvatar,
+ keywords: ['avatar', 'icon', 'change'],
+ },
+ {
+ id: 'yFEVCJxFX',
+ label: i18n.ts._profile.name,
+ keywords: ['name'],
+ },
+ {
+ id: '2O1S5reaB',
+ label: i18n.ts._profile.description,
+ keywords: ['description', 'bio'],
+ },
+ {
+ id: 'pWi4OLS8g',
+ label: i18n.ts.location,
+ keywords: ['location', 'locale'],
+ },
+ {
+ id: 'oLO5X6Wtw',
+ label: i18n.ts.birthday,
+ keywords: ['birthday', 'birthdate', 'age'],
+ },
+ {
+ id: 'm2trKwPgq',
+ label: i18n.ts.language,
+ keywords: ['language', 'locale'],
+ },
+ {
+ id: 'kfDZxCDp9',
+ label: i18n.ts._profile.metadataEdit,
+ keywords: ['metadata'],
+ },
+ {
+ id: 'uPt3MFymp',
+ label: i18n.ts._profile.followedMessage,
+ keywords: ['follow', 'message', i18n.ts._profile.followedMessageDescription],
+ },
+ {
+ id: 'wuGg0tBjw',
+ label: i18n.ts.reactionAcceptance,
+ keywords: ['reaction'],
+ },
+ {
+ id: 'EezPpmMnf',
+ children: [
+ {
+ id: 'f2cRLh8ad',
+ label: i18n.ts.flagAsCat,
+ keywords: ['cat'],
+ },
+ {
+ id: 'eVoViiF3h',
+ label: i18n.ts.flagAsBot,
+ keywords: ['bot'],
+ },
+ ],
+ label: i18n.ts.advancedSettings,
+ keywords: [],
+ },
+ ],
+ label: i18n.ts.profile,
+ keywords: ['profile'],
+ path: '/settings/profile',
+ icon: 'ti ti-user',
+ },
+ {
+ id: '2rp9ka5Ht',
+ children: [
+ {
+ id: 'qBUSKPxLW',
+ label: i18n.ts.makeFollowManuallyApprove,
+ keywords: ['follow', 'lock', i18n.ts.lockedAccountInfo],
+ },
+ {
+ id: '3LZBlZCej',
+ label: i18n.ts.autoAcceptFollowed,
+ keywords: ['follow', 'auto', 'accept'],
+ },
+ {
+ id: '9gOp28wKG',
+ label: i18n.ts.makeReactionsPublic,
+ keywords: ['reaction', 'public', i18n.ts.makeReactionsPublicDescription],
+ },
+ {
+ id: 'CjAkqMhct',
+ label: i18n.ts.followingVisibility,
+ keywords: ['following', 'visibility'],
+ },
+ {
+ id: '4nEwI6LYt',
+ label: i18n.ts.followersVisibility,
+ keywords: ['follower', 'visibility'],
+ },
+ {
+ id: 'naMp37wTL',
+ label: i18n.ts.hideOnlineStatus,
+ keywords: ['online', 'status', i18n.ts.hideOnlineStatusDescription],
+ },
+ {
+ id: 'p0dCVR0UP',
+ label: i18n.ts.noCrawle,
+ keywords: ['crawle', 'index', 'search', i18n.ts.noCrawleDescription],
+ },
+ {
+ id: 'aceURmNPq',
+ label: i18n.ts.preventAiLearning,
+ keywords: ['crawle', 'ai', i18n.ts.preventAiLearningDescription],
+ },
+ {
+ id: 'ahABA0j7u',
+ label: i18n.ts.makeExplorable,
+ keywords: ['explore', i18n.ts.makeExplorableDescription],
+ },
+ {
+ id: 'cyeDbLN8N',
+ children: [
+ {
+ id: 'xEYlOghao',
+ label: i18n.ts._accountSettings.requireSigninToViewContents,
+ keywords: ['login', 'signin'],
+ },
+ {
+ id: 'sMmYFCS60',
+ label: i18n.ts._accountSettings.makeNotesFollowersOnlyBefore,
+ keywords: ['follower', i18n.ts._accountSettings.makeNotesFollowersOnlyBeforeDescription],
+ },
+ {
+ id: '2prkeWRSd',
+ label: i18n.ts._accountSettings.makeNotesHiddenBefore,
+ keywords: ['hidden', i18n.ts._accountSettings.makeNotesHiddenBeforeDescription],
+ },
+ ],
+ label: i18n.ts.lockdown,
+ keywords: ['lockdown'],
+ },
+ {
+ id: '37QLEyrtk',
+ label: i18n.ts.rememberNoteVisibility,
+ keywords: ['remember', 'keep', 'note', 'visibility'],
+ },
+ {
+ id: 'rhKwScbVS',
+ label: i18n.ts.defaultNoteVisibility,
+ keywords: ['default', 'note', 'visibility'],
+ },
+ {
+ id: '3EmXVyevo',
+ label: i18n.ts.keepCw,
+ keywords: ['remember', 'keep', 'note', 'cw'],
+ },
+ ],
+ label: i18n.ts.privacy,
+ keywords: ['privacy'],
+ path: '/settings/privacy',
+ icon: 'ti ti-lock-open',
+ },
+ {
+ id: '3yCAv0IsZ',
+ children: [
+ {
+ id: 'x1GWSQnPw',
+ label: i18n.ts.uiLanguage,
+ keywords: ['language'],
+ },
+ {
+ id: 'EOSa4rtt3',
+ label: i18n.ts.overridedDeviceKind,
+ keywords: ['device', 'type', 'kind', 'smartphone', 'tablet', 'desktop'],
+ },
+ {
+ id: 'm9LhX8BG8',
+ label: i18n.ts.showFixedPostForm,
+ keywords: ['post', 'form', 'timeline'],
+ },
+ {
+ id: '9ra14w32V',
+ label: i18n.ts.showFixedPostFormInChannel,
+ keywords: ['post', 'form', 'timeline', 'channel'],
+ },
+ {
+ id: '84MdeDWL1',
+ label: i18n.ts.pinnedList,
+ keywords: ['pinned', 'list'],
+ },
+ {
+ id: 'fYdWhBbrN',
+ label: i18n.ts.enableQuickAddMfmFunction,
+ keywords: ['mfm', 'enable', 'show', 'advanced', 'picker', 'form', 'function', 'fn'],
+ },
+ {
+ id: '4huRldNp5',
+ children: [
+ {
+ id: 'puIqj1a8b',
+ label: i18n.ts.collapseRenotes,
+ keywords: ['renote', i18n.ts.collapseRenotesDescription],
+ },
+ {
+ id: 'wqpOC22Zm',
+ label: i18n.ts.showNoteActionsOnlyHover,
+ keywords: ['hover', 'show', 'footer', 'action'],
+ },
+ {
+ id: 'cjfAtxMzP',
+ label: i18n.ts.showClipButtonInNoteFooter,
+ keywords: ['footer', 'action', 'clip', 'show'],
+ },
+ {
+ id: 'khzxoCjtp',
+ label: i18n.ts.enableAdvancedMfm,
+ keywords: ['mfm', 'enable', 'show', 'advanced'],
+ },
+ {
+ id: 'uJkoVjTmF',
+ label: i18n.ts.showReactionsCount,
+ keywords: ['reaction', 'count', 'show'],
+ },
+ {
+ id: '9gTCaLkIf',
+ label: i18n.ts.loadRawImages,
+ keywords: ['image', 'photo', 'picture', 'media', 'thumbnail', 'quality', 'raw', 'attachment'],
+ },
+ ],
+ label: i18n.ts.note,
+ keywords: ['note'],
+ },
+ {
+ id: '5G6O6qdis',
+ children: [
+ {
+ id: 'sYTvqUbhP',
+ label: i18n.ts.useGroupedNotifications,
+ keywords: ['group'],
+ },
+ ],
+ label: i18n.ts.notifications,
+ keywords: ['notification'],
+ },
+ {
+ id: 'c3xhLyXZ5',
+ children: [
+ {
+ id: 'FbhoeuRAD',
+ label: i18n.ts.openImageInNewTab,
+ keywords: ['image', 'photo', 'picture', 'media', 'thumbnail', 'new', 'tab'],
+ },
+ {
+ id: 'qixh85g2N',
+ label: i18n.ts.useReactionPickerForContextMenu,
+ keywords: ['reaction', 'picker', 'contextmenu', 'open'],
+ },
+ {
+ id: 'd2H4E5ys6',
+ label: i18n.ts.enableInfiniteScroll,
+ keywords: ['load', 'auto', 'more'],
+ },
+ {
+ id: 'jC7LtTnmc',
+ label: i18n.ts.disableStreamingTimeline,
+ keywords: ['disable', 'streaming', 'timeline'],
+ },
+ {
+ id: '8xazEqlgZ',
+ label: i18n.ts.alwaysConfirmFollow,
+ keywords: ['follow', 'confirm', 'always'],
+ },
+ {
+ id: 'wZqrDQZar',
+ label: i18n.ts.confirmWhenRevealingSensitiveMedia,
+ keywords: ['sensitive', 'nsfw', 'media', 'image', 'photo', 'picture', 'attachment', 'confirm'],
+ },
+ {
+ id: '5QTUzrpT3',
+ label: i18n.ts.confirmOnReact,
+ keywords: ['reaction', 'confirm'],
+ },
+ {
+ id: 'nygexkaUk',
+ label: i18n.ts.whenServerDisconnected,
+ keywords: ['server', 'disconnect', 'reconnect', 'reload', 'streaming'],
+ },
+ {
+ id: 'whKYKvaQB',
+ label: i18n.ts.numberOfPageCache,
+ keywords: ['cache', 'page'],
+ },
+ {
+ id: 'lBbtAg0Hm',
+ label: i18n.ts.dataSaver,
+ keywords: ['datasaver'],
+ },
+ ],
+ label: i18n.ts.behavior,
+ keywords: ['behavior'],
+ },
+ {
+ id: 'y2v7CV9zs',
+ children: [
+ {
+ id: 'k1qTdyfzM',
+ label: i18n.ts.forceShowAds,
+ keywords: ['ad', 'show'],
+ },
+ {
+ id: 'e9As4Us48',
+ label: i18n.ts.hemisphere,
+ keywords: [],
+ },
+ {
+ id: 'zvM13vl26',
+ label: i18n.ts.additionalEmojiDictionary,
+ keywords: ['emoji', 'dictionary', 'additional', 'extra'],
+ },
+ ],
+ label: i18n.ts.other,
+ keywords: [],
+ },
+ ],
+ label: i18n.ts.preferences,
+ keywords: ['general', 'preferences'],
+ path: '/settings/preferences',
+ icon: 'ti ti-adjustments',
+ },
+ {
+ id: 'F1uK9ssiY',
+ children: [
+ {
+ id: 'msAcN6u3S',
+ label: i18n.ts.accountInfo,
+ keywords: ['account', 'info'],
+ },
+ {
+ id: 'ts8DgdnZV',
+ label: i18n.ts.accountMigration,
+ keywords: ['account', 'move', 'migration'],
+ },
+ {
+ id: '4BG7nBECm',
+ label: i18n.ts.closeAccount,
+ keywords: ['account', 'close', 'delete', i18n.ts._accountDelete.requestAccountDelete],
+ },
+ {
+ id: '2qI6ruPgi',
+ label: i18n.ts.experimentalFeatures,
+ keywords: ['experimental', 'feature', 'flags'],
+ },
+ {
+ id: 'cIeaax47o',
+ label: i18n.ts.developer,
+ keywords: ['developer', 'mode', 'debug'],
+ },
+ ],
+ label: i18n.ts.other,
+ keywords: ['other'],
+ path: '/settings/other',
+ icon: 'ti ti-dots',
+ },
+ {
+ id: '3icEvyv2D',
+ children: [
+ {
+ id: 'Tyt3gZTy',
+ children: [
+ {
+ id: '9b7ZURyAt',
+ label: i18n.ts.showMutedWord,
+ keywords: ['show'],
+ },
+ ],
+ label: i18n.ts.wordMute,
+ keywords: ['note', 'word', 'soft', 'mute', 'hide'],
+ },
+ {
+ id: 'kdMk41II0',
+ label: i18n.ts.hardWordMute,
+ keywords: ['note', 'word', 'hard', 'mute', 'hide'],
+ },
+ {
+ id: 'mjORQamAK',
+ label: i18n.ts.instanceMute,
+ keywords: ['note', 'server', 'instance', 'host', 'federation', 'mute', 'hide'],
+ },
+ {
+ id: '1ZT7S9FZd',
+ label: `${i18n.ts.mutedUsers} (${ i18n.ts.renote })`,
+ keywords: ['renote', 'mute', 'hide', 'user'],
+ },
+ {
+ id: 'ANrPit3kQ',
+ label: i18n.ts.mutedUsers,
+ keywords: ['note', 'mute', 'hide', 'user'],
+ },
+ {
+ id: 'bPAE4lfno',
+ label: i18n.ts.blockedUsers,
+ keywords: ['block', 'user'],
+ },
+ ],
+ label: i18n.ts.muteAndBlock,
+ keywords: ['mute', 'block'],
+ path: '/settings/mute-block',
+ icon: 'ti ti-ban',
+ },
+ {
+ id: 'qE2vLlMkF',
+ children: [
+ {
+ id: 'hPPEzjvZC',
+ label: i18n.ts._exportOrImport.allNotes,
+ keywords: ['notes'],
+ },
+ {
+ id: 'AFaeHsCUB',
+ label: i18n.ts._exportOrImport.favoritedNotes,
+ keywords: ['favorite', 'notes'],
+ },
+ {
+ id: 'xyCPmQiRo',
+ label: i18n.ts._exportOrImport.clips,
+ keywords: ['clip', 'notes'],
+ },
+ {
+ id: 'Ch7hWAGUy',
+ label: i18n.ts._exportOrImport.followingList,
+ keywords: ['following', 'users'],
+ },
+ {
+ id: 'AwPgFboEx',
+ label: i18n.ts._exportOrImport.userLists,
+ keywords: ['user', 'lists'],
+ },
+ {
+ id: 'nporiHshC',
+ label: i18n.ts._exportOrImport.muteList,
+ keywords: ['mute', 'users'],
+ },
+ {
+ id: 'BsCzR7vNw',
+ label: i18n.ts._exportOrImport.blockingList,
+ keywords: ['block', 'users'],
+ },
+ {
+ id: 'dvf4IgYrQ',
+ label: i18n.ts.antennas,
+ keywords: ['antennas'],
+ },
+ ],
+ label: i18n.ts.importAndExport,
+ keywords: ['import', 'export', 'data'],
+ path: '/settings/import-export',
+ icon: 'ti ti-package',
+ },
+ {
+ id: '3Tcxw4Fwl',
+ children: [
+ {
+ id: 'iIai9O65I',
+ label: i18n.ts.emailAddress,
+ keywords: ['email', 'address'],
+ },
+ {
+ id: 'i6cC6oi0m',
+ label: i18n.ts.receiveAnnouncementFromInstance,
+ keywords: ['announcement', 'email'],
+ },
+ {
+ id: 'C1YTinP11',
+ label: i18n.ts.emailNotification,
+ keywords: ['notification', 'email'],
+ },
+ ],
+ label: i18n.ts.email,
+ keywords: ['email'],
+ path: '/settings/email',
+ icon: 'ti ti-mail',
+ },
+ {
+ id: 'tnYoppRiv',
+ children: [
+ {
+ id: 'ncIq6TAR2',
+ label: i18n.ts.usageAmount,
+ keywords: ['capacity', 'usage'],
+ },
+ {
+ id: '2c4CQSvSr',
+ label: i18n.ts.statistics,
+ keywords: ['statistics', 'usage'],
+ },
+ {
+ id: 'pepHELHMt',
+ label: i18n.ts.uploadFolder,
+ keywords: ['default', 'upload', 'folder'],
+ },
+ {
+ id: 'xqOWrABxV',
+ label: i18n.ts.keepOriginalUploading,
+ keywords: ['keep', 'original', 'raw', 'upload', i18n.ts.keepOriginalUploadingDescription],
+ },
+ {
+ id: 'oqUiI5w0s',
+ label: i18n.ts.keepOriginalFilename,
+ keywords: ['keep', 'original', 'filename', i18n.ts.keepOriginalFilenameDescription],
+ },
+ {
+ id: 'Aszkikq9n',
+ label: i18n.ts.alwaysMarkSensitive,
+ keywords: ['always', 'default', 'mark', 'nsfw', 'sensitive', 'media', 'file'],
+ },
+ {
+ id: 'iGlVjsfVj',
+ label: i18n.ts.enableAutoSensitive,
+ keywords: ['auto', 'nsfw', 'sensitive', 'media', 'file', i18n.ts.enableAutoSensitiveDescription],
+ },
+ ],
+ label: i18n.ts.drive,
+ keywords: ['drive'],
+ path: '/settings/drive',
+ icon: 'ti ti-cloud',
+ },
+ {
+ id: 'gtaOSdIJB',
+ label: i18n.ts.avatarDecorations,
+ keywords: ['avatar', 'icon', 'decoration'],
+ path: '/settings/avatar-decoration',
+ icon: 'ti ti-sparkles',
+ },
+ {
+ id: 'AqPvMgn3A',
+ children: [
+ {
+ id: 'j5gTtuMWP',
+ label: i18n.ts.useBlurEffect,
+ keywords: ['blur'],
+ },
+ {
+ id: 'vbZvyLDC1',
+ label: i18n.ts.useBlurEffectForModal,
+ keywords: ['blur', 'modal'],
+ },
+ {
+ id: '6fLNMTwNt',
+ label: i18n.ts.highlightSensitiveMedia,
+ keywords: ['highlight', 'sensitive', 'nsfw', 'image', 'photo', 'picture', 'media', 'thumbnail'],
+ },
+ {
+ id: 'hhvF8Z4pF',
+ label: i18n.ts.squareAvatars,
+ keywords: ['avatar', 'icon', 'square'],
+ },
+ {
+ id: 'DsS2CwjYE',
+ label: i18n.ts.showAvatarDecorations,
+ keywords: ['avatar', 'icon', 'decoration', 'show'],
+ },
+ {
+ id: 'pWZ0ypy2g',
+ label: i18n.ts.showGapBetweenNotesInTimeline,
+ keywords: ['note', 'timeline', 'gap'],
+ },
+ {
+ id: 'AfRMcC6IM',
+ label: i18n.ts.useSystemFont,
+ keywords: ['font', 'system', 'native'],
+ },
+ {
+ id: 'jD0qbxlzN',
+ label: i18n.ts.seasonalScreenEffect,
+ keywords: ['effect', 'show'],
+ },
+ {
+ id: 'EdYo3hOK',
+ label: i18n.ts.menuStyle,
+ keywords: ['menu', 'style', 'popup', 'drawer'],
+ },
+ {
+ id: '9mSlX0EkD',
+ label: i18n.ts.emojiStyle,
+ keywords: ['emoji', 'style', 'native', 'system', 'fluent', 'twemoji'],
+ },
+ {
+ id: '44UmMwmUe',
+ label: i18n.ts.fontSize,
+ keywords: ['font', 'size'],
+ },
+ {
+ id: 'vFB0pLzck',
+ children: [
+ {
+ id: 'pc7IpPEU4',
+ label: i18n.ts.reactionsDisplaySize,
+ keywords: ['reaction', 'size', 'scale', 'display'],
+ },
+ {
+ id: 'siOW5aSwp',
+ label: i18n.ts.limitWidthOfReaction,
+ keywords: ['reaction', 'size', 'scale', 'display', 'width', 'limit'],
+ },
+ {
+ id: 'dDUvhk13F',
+ label: i18n.ts.mediaListWithOneImageAppearance,
+ keywords: ['attachment', 'image', 'photo', 'picture', 'media', 'thumbnail', 'list', 'size', 'height'],
+ },
+ {
+ id: 'CLxNL1Rp0',
+ label: i18n.ts.instanceTicker,
+ keywords: ['ticker', 'information', 'label', 'instance', 'server', 'host', 'federation'],
+ },
+ {
+ id: 'dP2KWDYzD',
+ label: i18n.ts.displayOfSensitiveMedia,
+ keywords: ['attachment', 'image', 'photo', 'picture', 'media', 'thumbnail', 'nsfw', 'sensitive', 'display', 'show', 'hide', 'visibility'],
+ },
+ ],
+ label: i18n.ts.displayOfNote,
+ keywords: ['note', 'display'],
+ },
+ {
+ id: 'dVOzi22IW',
+ children: [
+ {
+ id: 'aoF4ufUwn',
+ label: i18n.ts.position,
+ keywords: ['position'],
+ },
+ {
+ id: 'sKK2XSS69',
+ label: i18n.ts.stackAxis,
+ keywords: ['stack', 'axis', 'direction'],
+ },
+ ],
+ label: i18n.ts.notificationDisplay,
+ keywords: ['notification', 'display'],
+ },
+ ],
+ label: i18n.ts.appearance,
+ keywords: ['appearance'],
+ path: '/settings/appearance',
+ icon: 'ti ti-device-desktop',
+ },
+ {
+ id: 'f08Mi1Uwn',
+ children: [
+ {
+ id: '7ov7ceoij',
+ label: i18n.ts.reduceUiAnimation,
+ keywords: ['animation', 'motion', 'reduce'],
+ },
+ {
+ id: 'RhYwm8At',
+ label: i18n.ts.disableShowingAnimatedImages,
+ keywords: ['disable', 'animation', 'image', 'photo', 'picture', 'media', 'thumbnail', 'gif'],
+ },
+ {
+ id: '5mZxz2cru',
+ label: i18n.ts.enableAnimatedMfm,
+ keywords: ['mfm', 'enable', 'show', 'animated'],
+ },
+ {
+ id: 'bgjamYEis',
+ label: i18n.ts.enableHorizontalSwipe,
+ keywords: ['swipe', 'horizontal', 'tab'],
+ },
+ {
+ id: 'yPEpJigqY',
+ label: i18n.ts.keepScreenOn,
+ keywords: ['keep', 'screen', 'display', 'on'],
+ },
+ {
+ id: 'oxwiGKMu0',
+ label: i18n.ts.useNativeUIForVideoAudioPlayer,
+ keywords: ['native', 'system', 'video', 'audio', 'player', 'media'],
+ },
+ {
+ id: 'n90tffyiU',
+ label: i18n.ts._contextMenu.title,
+ keywords: ['contextmenu', 'system', 'native'],
+ },
+ ],
+ label: i18n.ts.accessibility,
+ keywords: ['accessibility'],
+ path: '/settings/accessibility',
+ icon: 'ti ti-accessible',
+ },
+] as const;
+
+export type SearchIndex = typeof searchIndexes;
diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue
index 9724905e02..fec8666dc1 100644
--- a/packages/frontend/src/ui/_common_/navbar.vue
+++ b/packages/frontend/src/ui/_common_/navbar.vue
@@ -56,21 +56,35 @@ SPDX-License-Identifier: AGPL-3.0-only
</button>
</div>
</div>
- <button v-if="!forceIconOnly" class="_button" :class="$style.toggleButton" @click="toggleIconOnly">
- <!--
- <svg viewBox="0 0 16 48" :class="$style.toggleButtonShape">
- <g transform="matrix(0.333333,0,0,0.222222,0.000895785,13.3333)">
- <path d="M23.935,-24C37.223,-24 47.995,-7.842 47.995,12.09C47.995,34.077 47.995,62.07 47.995,84.034C47.995,93.573 45.469,102.721 40.972,109.466C36.475,116.211 30.377,120 24.018,120L23.997,120C10.743,120 -0.003,136.118 -0.003,156C-0.003,156 -0.003,156 -0.003,156L-0.003,-60L-0.003,-59.901C-0.003,-50.379 2.519,-41.248 7.007,-34.515C11.496,-27.782 17.584,-24 23.931,-24C23.932,-24 23.934,-24 23.935,-24Z" style="fill:var(--MI_THEME-navBg);"/>
- </g>
- </svg>
- -->
- <svg viewBox="0 0 16 64" :class="$style.toggleButtonShape">
- <g transform="matrix(0.333333,0,0,0.222222,0.000895785,21.3333)">
- <path d="M47.488,7.995C47.79,10.11 47.943,12.266 47.943,14.429C47.997,26.989 47.997,84 47.997,84C47.997,84 44.018,118.246 23.997,133.5C-0.374,152.07 -0.003,192 -0.003,192L-0.003,-96C-0.003,-96 0.151,-56.216 23.997,-37.5C40.861,-24.265 46.043,-1.243 47.488,7.995Z" style="fill:var(--MI_THEME-navBg);"/>
- </g>
- </svg>
- <i :class="'ti ' + `ti-chevron-${ iconOnly ? 'right' : 'left' }`" style="font-size: 12px; margin-left: -8px;"></i>
- </button>
+
+ <!--
+ <svg viewBox="0 0 16 48" :class="$style.subButtonShape">
+ <g transform="matrix(0.333333,0,0,0.222222,0.000895785,13.3333)">
+ <path d="M23.935,-24C37.223,-24 47.995,-7.842 47.995,12.09C47.995,34.077 47.995,62.07 47.995,84.034C47.995,93.573 45.469,102.721 40.972,109.466C36.475,116.211 30.377,120 24.018,120L23.997,120C10.743,120 -0.003,136.118 -0.003,156C-0.003,156 -0.003,156 -0.003,156L-0.003,-60L-0.003,-59.901C-0.003,-50.379 2.519,-41.248 7.007,-34.515C11.496,-27.782 17.584,-24 23.931,-24C23.932,-24 23.934,-24 23.935,-24Z" style="fill:var(--MI_THEME-navBg);"/>
+ </g>
+ </svg>
+ -->
+
+ <div :class="$style.subButtons">
+ <div :class="[$style.subButton, $style.menuEditButton]">
+ <svg viewBox="0 0 16 64" :class="$style.subButtonShape">
+ <g transform="matrix(0.333333,0,0,0.222222,0.000895785,21.3333)">
+ <path d="M47.488,7.995C47.79,10.11 47.943,12.266 47.943,14.429C47.997,26.989 47.997,84 47.997,84C47.997,84 44.018,118.246 23.997,133.5C-0.374,152.07 -0.003,192 -0.003,192L-0.003,-96C-0.003,-96 0.151,-56.216 23.997,-37.5C40.861,-24.265 46.043,-1.243 47.488,7.995Z" style="fill:var(--MI_THEME-navBg);"/>
+ </g>
+ </svg>
+ <button class="_button" :class="$style.subButtonClickable" @click="menuEdit"><i :class="$style.subButtonIcon" class="ti ti-settings-2"></i></button>
+ </div>
+ <div v-if="!forceIconOnly" :class="$style.subButtonGapFill"></div>
+ <div v-if="!forceIconOnly" :class="$style.subButtonGapFillDivider"></div>
+ <div v-if="!forceIconOnly" :class="[$style.subButton, $style.toggleButton]">
+ <svg viewBox="0 0 16 64" :class="$style.subButtonShape">
+ <g transform="matrix(0.333333,0,0,0.222222,0.000895785,21.3333)">
+ <path d="M47.488,7.995C47.79,10.11 47.943,12.266 47.943,14.429C47.997,26.989 47.997,84 47.997,84C47.997,84 44.018,118.246 23.997,133.5C-0.374,152.07 -0.003,192 -0.003,192L-0.003,-96C-0.003,-96 0.151,-56.216 23.997,-37.5C40.861,-24.265 46.043,-1.243 47.488,7.995Z" style="fill:var(--MI_THEME-navBg);"/>
+ </g>
+ </svg>
+ <button class="_button" :class="$style.subButtonClickable" @click="toggleIconOnly"><i v-if="iconOnly" class="ti ti-chevron-right" :class="$style.subButtonIcon"></i><i v-else class="ti ti-chevron-left" :class="$style.subButtonIcon"></i></button>
+ </div>
+ </div>
</div>
</template>
@@ -84,6 +98,9 @@ import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js';
import { getHTMLElementOrNull } from '@/scripts/get-dom-node-or-null.js';
+import { useRouter } from '@/router/supplier.js';
+
+const router = useRouter();
const forceIconOnly = ref(window.innerWidth <= 1279);
const iconOnly = computed(() => {
@@ -128,6 +145,10 @@ function more(ev: MouseEvent) {
closed: () => dispose(),
});
}
+
+function menuEdit() {
+ router.push('/settings/navbar');
+}
</script>
<style lang="scss" module>
@@ -136,6 +157,8 @@ function more(ev: MouseEvent) {
--nav-icon-only-width: 80px;
--nav-bg-transparent: color(from var(--MI_THEME-navBg) srgb r g b / 0.5);
+ --subButtonWidth: 20px;
+
flex: 0 0 var(--nav-width);
width: var(--nav-width);
box-sizing: border-box;
@@ -171,23 +194,80 @@ function more(ev: MouseEvent) {
direction: ltr;
}
-.toggleButton {
+.subButtons {
position: fixed;
- bottom: 20px;
left: var(--nav-width);
+ bottom: 80px;
z-index: 1001;
- width: 16px;
- height: 64px;
box-sizing: border-box;
}
-.toggleButtonShape {
+.subButton {
+ display: block;
+ position: relative;
+ z-index: 1002;
+ width: var(--subButtonWidth);
+ height: 50px;
+ box-sizing: border-box;
+ align-content: center;
+}
+
+.subButtonShape {
position: absolute;
z-index: -1;
top: 0;
+ bottom: 0;
left: 0;
- width: 16px;
+ margin: auto;
+ width: var(--subButtonWidth);
+ height: calc(var(--subButtonWidth) * 4);
+}
+
+.subButtonClickable {
+ position: absolute;
+ display: block;
+ max-width: unset;
+ width: 24px;
+ height: 42px;
+ top: 0;
+ bottom: 0;
+ left: -4px;
+ margin: auto;
+ font-size: 10px;
+
+ &:hover {
+ color: var(--MI_THEME-fgHighlighted);
+
+ .subButtonIcon {
+ opacity: 1;
+ }
+ }
+}
+
+.subButtonIcon {
+ margin-left: -4px;
+ opacity: 0.7;
+}
+
+.subButtonGapFill {
+ position: relative;
+ z-index: 1001;
+ width: var(--subButtonWidth);
height: 64px;
+ margin-top: -32px;
+ margin-bottom: -32px;
+ pointer-events: none;
+ background: var(--MI_THEME-navBg);
+}
+
+.subButtonGapFillDivider {
+ position: relative;
+ z-index: 1010;
+ margin-left: -2px;
+ width: 14px;
+ height: 1px;
+ background: var(--MI_THEME-divider);
+ pointer-events: none;
}
.root:not(.iconOnly) {
@@ -419,7 +499,7 @@ function more(ev: MouseEvent) {
font-size: 0.9em;
}
- .toggleButton {
+ .subButtons {
left: var(--nav-width);
}
}
@@ -623,7 +703,7 @@ function more(ev: MouseEvent) {
}
}
- .toggleButton {
+ .subButtons {
left: var(--nav-icon-only-width);
}
}
diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue
index 9fff5efe51..25f47a2d55 100644
--- a/packages/frontend/src/ui/universal.vue
+++ b/packages/frontend/src/ui/universal.vue
@@ -96,12 +96,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { defineAsyncComponent, provide, onMounted, computed, ref, watch, shallowRef } from 'vue';
-import type { Ref } from 'vue';
import { instanceName } from '@@/js/config.js';
import { CURRENT_STICKY_BOTTOM } from '@@/js/const.js';
import { isLink } from '@@/js/is-link.js';
import XCommon from './_common_/common.vue';
+import type { Ref } from 'vue';
import type MkStickyContainer from '@/components/global/MkStickyContainer.vue';
+import type { PageMetadata } from '@/scripts/page-metadata.js';
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue';
import * as os from '@/os.js';
import { defaultStore } from '@/store.js';
@@ -109,7 +110,6 @@ import { navbarItemDef } from '@/navbar.js';
import { i18n } from '@/i18n.js';
import { $i } from '@/account.js';
import { provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js';
-import type { PageMetadata } from '@/scripts/page-metadata.js';
import { deviceKind } from '@/scripts/device-kind.js';
import { miLocalStorage } from '@/local-storage.js';
import { useScrollPositionManager } from '@/nirax.js';
@@ -331,6 +331,8 @@ $widgets-hide-threshold: 1090px;
overflow-y: scroll;
overscroll-behavior: contain;
background: var(--MI_THEME-bg);
+ scroll-padding-top: 60px; // TODO: ちゃんと計算する
+ scroll-padding-bottom: 60px; // TODO: ちゃんと計算する
}
.widgets {
diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts
index d1b7c410dc..1c094e272b 100644
--- a/packages/frontend/vite.config.ts
+++ b/packages/frontend/vite.config.ts
@@ -10,6 +10,7 @@ import meta from '../../package.json';
import packageInfo from './package.json' with { type: 'json' };
import pluginUnwindCssModuleClassName from './lib/rollup-plugin-unwind-css-module-class-name.js';
import pluginJson5 from './vite.json5.js';
+import pluginCreateSearchIndex from './lib/vite-plugin-create-search-index.js';
const url = process.env.NODE_ENV === 'development' ? yaml.load(await fsp.readFile('../../.config/default.yml', 'utf-8')).url : null;
const host = url ? (new URL(url)).hostname : undefined;
@@ -34,7 +35,7 @@ const externalPackages = [
},
];
-const hash = (str: string, seed = 0): number => {
+export const hash = (str: string, seed = 0): number => {
let h1 = 0xdeadbeef ^ seed,
h2 = 0x41c6ce57 ^ seed;
for (let i = 0, ch; i < str.length; i++) {
@@ -49,9 +50,9 @@ const hash = (str: string, seed = 0): number => {
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
};
-const BASE62_DIGITS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+export const BASE62_DIGITS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-function toBase62(n: number): string {
+export function toBase62(n: number): string {
if (n === 0) {
return '0';
}
@@ -83,6 +84,11 @@ export function getConfig(): UserConfig {
},
plugins: [
+ pluginCreateSearchIndex({
+ targetFilePaths: ['src/pages/settings/*.vue'],
+ exportFilePath: './src/scripts/autogen/settings-search-index.ts',
+ verbose: process.env.FRONTEND_SEARCH_INDEX_VERBOSE === 'true',
+ }),
pluginVue(),
pluginUnwindCssModuleClassName(),
pluginJson5(),
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index 8a91f8ea38..eb8e7c479b 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
{
"type": "module",
"name": "misskey-js",
- "version": "2025.3.0",
+ "version": "2025.3.1",
"description": "Misskey SDK for JavaScript",
"license": "MIT",
"main": "./built/index.js",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e5096d59e7..4d11b5ac49 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5,8 +5,14 @@ settings:
excludeLinksFromLockfile: false
overrides:
- chokidar: 3.6.0
+ chokidar: 4.0.3
lodash: 4.17.21
+ '@aiscript-dev/aiscript-languageserver': '-'
+
+patchedDependencies:
+ re2:
+ hash: 018babd22b7ce951bcd10d6246f1e541a7ac7ba212f7fa8985e774ece67d08e1
+ path: scripts/dependency-patches/re2.patch
importers:
@@ -14,13 +20,13 @@ importers:
dependencies:
cssnano:
specifier: 7.0.6
- version: 7.0.6(postcss@8.5.2)
+ version: 7.0.6(postcss@8.5.3)
esbuild:
specifier: 0.25.0
version: 0.25.0
execa:
- specifier: 8.0.1
- version: 8.0.1
+ specifier: 9.5.2
+ version: 9.5.2
fast-glob:
specifier: 3.3.3
version: 3.3.3
@@ -28,58 +34,61 @@ importers:
specifier: 11.0.1
version: 11.0.1
ignore-walk:
- specifier: 6.0.5
- version: 6.0.5
+ specifier: 7.0.0
+ version: 7.0.0
js-yaml:
specifier: 4.1.0
version: 4.1.0
postcss:
- specifier: 8.5.2
- version: 8.5.2
+ specifier: 8.5.3
+ version: 8.5.3
tar:
- specifier: 6.2.1
- version: 6.2.1
+ specifier: 7.4.3
+ version: 7.4.3
terser:
specifier: 5.39.0
version: 5.39.0
typescript:
- specifier: 5.7.3
- version: 5.7.3
- optionalDependencies:
- '@tensorflow/tfjs-core':
- specifier: 4.22.0
- version: 4.22.0(encoding@0.1.13)
+ specifier: 5.8.2
+ version: 5.8.2
devDependencies:
'@misskey-dev/eslint-plugin':
specifier: 2.1.0
- version: 2.1.0(@eslint/compat@1.1.1)(@stylistic/eslint-plugin@2.13.0(eslint@9.20.1)(typescript@5.7.3))(@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1)(typescript@5.7.3))(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1))(eslint@9.20.1)(globals@15.15.0)
+ version: 2.1.0(@eslint/compat@1.1.1)(@stylistic/eslint-plugin@2.13.0(eslint@9.21.0)(typescript@5.8.2))(@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2))(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0))(eslint@9.21.0)(globals@16.0.0)
'@types/node':
- specifier: 22.13.4
- version: 22.13.4
+ specifier: 22.13.9
+ version: 22.13.9
'@typescript-eslint/eslint-plugin':
- specifier: 8.24.0
- version: 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1)(typescript@5.7.3)
+ specifier: 8.26.0
+ version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/parser':
- specifier: 8.24.0
- version: 8.24.0(eslint@9.20.1)(typescript@5.7.3)
+ specifier: 8.26.0
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
cross-env:
specifier: 7.0.3
version: 7.0.3
cypress:
- specifier: 14.0.3
- version: 14.0.3
+ specifier: 14.1.0
+ version: 14.1.0
eslint:
- specifier: 9.20.1
- version: 9.20.1
+ specifier: 9.21.0
+ version: 9.21.0
globals:
- specifier: 15.15.0
- version: 15.15.0
+ specifier: 16.0.0
+ version: 16.0.0
ncp:
specifier: 2.0.0
version: 2.0.0
+ pnpm:
+ specifier: 10.6.1
+ version: 10.6.1
start-server-and-test:
specifier: 2.0.10
version: 2.0.10
+ optionalDependencies:
+ '@tensorflow/tfjs-core':
+ specifier: 4.22.0
+ version: 4.22.0(encoding@0.1.13)
packages/backend:
dependencies:
@@ -163,7 +172,7 @@ importers:
version: 2.5.0
'@swc/cli':
specifier: 0.6.0
- version: 0.6.0(@swc/core@1.10.16)(chokidar@3.6.0)
+ version: 0.6.0(@swc/core@1.10.16)(chokidar@4.0.3)
'@swc/core':
specifier: 1.10.16
version: 1.10.16
@@ -207,8 +216,8 @@ importers:
specifier: 1.1.0
version: 1.1.0
chokidar:
- specifier: 3.6.0
- version: 3.6.0
+ specifier: 4.0.3
+ version: 4.0.3
cli-highlight:
specifier: 2.1.11
version: 2.1.11
@@ -367,7 +376,7 @@ importers:
version: 3.4.1
re2:
specifier: 1.21.4
- version: 1.21.4
+ version: 1.21.4(patch_hash=018babd22b7ce951bcd10d6246f1e541a7ac7ba212f7fa8985e774ece67d08e1)
redis-lock:
specifier: 0.1.4
version: 0.1.4
@@ -437,94 +446,6 @@ importers:
xev:
specifier: 3.0.2
version: 3.0.2
- optionalDependencies:
- '@swc/core-android-arm64':
- specifier: 1.3.11
- version: 1.3.11
- '@swc/core-darwin-arm64':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-darwin-x64':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-freebsd-x64':
- specifier: 1.3.11
- version: 1.3.11
- '@swc/core-linux-arm-gnueabihf':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-linux-arm64-gnu':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-linux-arm64-musl':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-linux-x64-gnu':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-linux-x64-musl':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-win32-arm64-msvc':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-win32-ia32-msvc':
- specifier: 1.10.16
- version: 1.10.16
- '@swc/core-win32-x64-msvc':
- specifier: 1.10.16
- version: 1.10.16
- '@tensorflow/tfjs':
- specifier: 4.22.0
- version: 4.22.0(encoding@0.1.13)(seedrandom@3.0.5)
- '@tensorflow/tfjs-node':
- specifier: 4.22.0
- version: 4.22.0(encoding@0.1.13)(seedrandom@3.0.5)
- bufferutil:
- specifier: 4.0.9
- version: 4.0.9
- slacc-android-arm-eabi:
- specifier: 0.0.10
- version: 0.0.10
- slacc-android-arm64:
- specifier: 0.0.10
- version: 0.0.10
- slacc-darwin-arm64:
- specifier: 0.0.10
- version: 0.0.10
- slacc-darwin-universal:
- specifier: 0.0.10
- version: 0.0.10
- slacc-darwin-x64:
- specifier: 0.0.10
- version: 0.0.10
- slacc-freebsd-x64:
- specifier: 0.0.10
- version: 0.0.10
- slacc-linux-arm-gnueabihf:
- specifier: 0.0.10
- version: 0.0.10
- slacc-linux-arm64-gnu:
- specifier: 0.0.10
- version: 0.0.10
- slacc-linux-arm64-musl:
- specifier: 0.0.10
- version: 0.0.10
- slacc-linux-x64-gnu:
- specifier: 0.0.10
- version: 0.0.10
- slacc-linux-x64-musl:
- specifier: 0.0.10
- version: 0.0.10
- slacc-win32-arm64-msvc:
- specifier: 0.0.10
- version: 0.0.10
- slacc-win32-x64-msvc:
- specifier: 0.0.10
- version: 0.0.10
- utf-8-validate:
- specifier: 6.0.5
- version: 6.0.5
devDependencies:
'@jest/globals':
specifier: 29.7.0
@@ -648,10 +569,10 @@ importers:
version: 8.5.14
'@typescript-eslint/eslint-plugin':
specifier: 8.24.0
- version: 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1)(typescript@5.7.3)
+ version: 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)(typescript@5.7.3)
'@typescript-eslint/parser':
specifier: 8.24.0
- version: 8.24.0(eslint@9.20.1)(typescript@5.7.3)
+ version: 8.24.0(eslint@9.21.0)(typescript@5.7.3)
aws-sdk-client-mock:
specifier: 4.1.0
version: 4.1.0
@@ -660,7 +581,7 @@ importers:
version: 7.0.3
eslint-plugin-import:
specifier: 2.31.0
- version: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1)
+ version: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)
execa:
specifier: 8.0.1
version: 8.0.1
@@ -682,6 +603,94 @@ importers:
simple-oauth2:
specifier: 5.1.0
version: 5.1.0
+ optionalDependencies:
+ '@swc/core-android-arm64':
+ specifier: 1.3.11
+ version: 1.3.11
+ '@swc/core-darwin-arm64':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-darwin-x64':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-freebsd-x64':
+ specifier: 1.3.11
+ version: 1.3.11
+ '@swc/core-linux-arm-gnueabihf':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-linux-arm64-gnu':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-linux-arm64-musl':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-linux-x64-gnu':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-linux-x64-musl':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-win32-arm64-msvc':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-win32-ia32-msvc':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@swc/core-win32-x64-msvc':
+ specifier: 1.10.16
+ version: 1.10.16
+ '@tensorflow/tfjs':
+ specifier: 4.22.0
+ version: 4.22.0(encoding@0.1.13)(seedrandom@3.0.5)
+ '@tensorflow/tfjs-node':
+ specifier: 4.22.0
+ version: 4.22.0(encoding@0.1.13)(seedrandom@3.0.5)
+ bufferutil:
+ specifier: 4.0.9
+ version: 4.0.9
+ slacc-android-arm-eabi:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-android-arm64:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-darwin-arm64:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-darwin-universal:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-darwin-x64:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-freebsd-x64:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-linux-arm-gnueabihf:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-linux-arm64-gnu:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-linux-arm64-musl:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-linux-x64-gnu:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-linux-x64-musl:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-win32-arm64-msvc:
+ specifier: 0.0.10
+ version: 0.0.10
+ slacc-win32-x64-msvc:
+ specifier: 0.0.10
+ version: 0.0.10
+ utf-8-validate:
+ specifier: 6.0.5
+ version: 6.0.5
packages/frontend:
dependencies:
@@ -720,7 +729,7 @@ importers:
version: 15.1.1
'@vitejs/plugin-vue':
specifier: 5.2.1
- version: 5.2.1(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))
+ version: 5.2.1(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))
'@vue/compiler-sfc':
specifier: 3.5.13
version: 3.5.13
@@ -790,6 +799,9 @@ importers:
json5:
specifier: 2.2.3
version: 2.2.3
+ magic-string:
+ specifier: 0.30.17
+ version: 0.30.17
matter-js:
specifier: 0.20.0
version: 0.20.0
@@ -854,8 +866,8 @@ importers:
specifier: 1.13.1
version: 1.13.1(vue@3.5.13(typescript@5.8.2))
vite:
- specifier: 6.2.0
- version: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ specifier: 6.2.1
+ version: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
vue:
specifier: 3.5.13
version: 3.5.13(typescript@5.8.2)
@@ -867,59 +879,59 @@ importers:
specifier: 5.2.0
version: 5.2.0
'@storybook/addon-actions':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/addon-essentials':
- specifier: 8.6.3
- version: 8.6.3(@types/react@18.0.28)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(@types/react@18.0.28)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/addon-interactions':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/addon-links':
- specifier: 8.6.3
- version: 8.6.3(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/addon-mdx-gfm':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/addon-storysource':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/blocks':
- specifier: 8.6.3
- version: 8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/components':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/core-events':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/manager-api':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/preview-api':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/react':
- specifier: 8.6.3
- version: 8.6.3(@storybook/test@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)
+ specifier: 8.6.4
+ version: 8.6.4(@storybook/test@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)
'@storybook/react-vite':
- specifier: 8.6.3
- version: 8.6.3(@storybook/test@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.9)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
+ specifier: 8.6.4
+ version: 8.6.4(@storybook/test@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.9)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
'@storybook/test':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/theming':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/types':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/vue3':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vue@3.5.13(typescript@5.8.2))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vue@3.5.13(typescript@5.8.2))
'@storybook/vue3-vite':
- specifier: 8.6.3
- version: 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))
+ specifier: 8.6.4
+ version: 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))
'@testing-library/vue':
specifier: 8.1.0
version: 8.1.0(@vue/compiler-sfc@3.5.13)(@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
@@ -958,19 +970,19 @@ importers:
version: 8.18.0
'@typescript-eslint/eslint-plugin':
specifier: 8.26.0
- version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/parser':
specifier: 8.26.0
- version: 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
'@vitest/coverage-v8':
- specifier: 3.0.7
- version: 3.0.7(vitest@3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
+ specifier: 3.0.8
+ version: 3.0.8(vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
'@vue/runtime-core':
specifier: 3.5.13
version: 3.5.13
acorn:
- specifier: 8.14.0
- version: 8.14.0
+ specifier: 8.14.1
+ version: 8.14.1
cross-env:
specifier: 7.0.3
version: 7.0.3
@@ -979,16 +991,16 @@ importers:
version: 14.1.0
eslint-plugin-import:
specifier: 2.31.0
- version: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)
+ version: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)
eslint-plugin-vue:
- specifier: 9.33.0
- version: 9.33.0(eslint@9.20.1)
+ specifier: 10.0.0
+ version: 10.0.0(eslint@9.21.0)(vue-eslint-parser@10.1.1(eslint@9.21.0))
fast-glob:
specifier: 3.3.3
version: 3.3.3
happy-dom:
- specifier: 17.2.2
- version: 17.2.2
+ specifier: 17.3.0
+ version: 17.3.0
intersection-observer:
specifier: 0.12.2
version: 0.12.2
@@ -1020,26 +1032,26 @@ importers:
specifier: 2.0.10
version: 2.0.10
storybook:
- specifier: 8.6.3
- version: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ specifier: 8.6.4
+ version: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
storybook-addon-misskey-theme:
specifier: github:misskey-dev/storybook-addon-misskey-theme
- version: https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/components@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/core-events@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/manager-api@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/preview-api@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/theming@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/types@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ version: https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/components@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/core-events@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/manager-api@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/preview-api@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/theming@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/types@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
vite-plugin-turbosnap:
specifier: 1.0.3
version: 1.0.3
vitest:
- specifier: 3.0.7
- version: 3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ specifier: 3.0.8
+ version: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
vitest-fetch-mock:
specifier: 0.4.5
- version: 0.4.5(vitest@3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
+ version: 0.4.5(vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
vue-component-type-helpers:
specifier: 2.2.8
version: 2.2.8
vue-eslint-parser:
- specifier: 9.4.3
- version: 9.4.3(eslint@9.20.1)
+ specifier: 10.1.1
+ version: 10.1.1(eslint@9.21.0)
vue-tsc:
specifier: 2.2.8
version: 2.2.8(typescript@5.8.2)
@@ -1066,7 +1078,7 @@ importers:
version: 15.1.1
'@vitejs/plugin-vue':
specifier: 5.2.1
- version: 5.2.1(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))
+ version: 5.2.1(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))
'@vue/compiler-sfc':
specifier: 3.5.13
version: 3.5.13
@@ -1119,8 +1131,8 @@ importers:
specifier: 11.1.0
version: 11.1.0
vite:
- specifier: 6.2.0
- version: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ specifier: 6.2.1
+ version: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
vue:
specifier: 3.5.13
version: 3.5.13(typescript@5.8.2)
@@ -1151,34 +1163,34 @@ importers:
version: 8.18.0
'@typescript-eslint/eslint-plugin':
specifier: 8.26.0
- version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/parser':
specifier: 8.26.0
- version: 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
'@vitest/coverage-v8':
- specifier: 3.0.7
- version: 3.0.7(vitest@3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
+ specifier: 3.0.8
+ version: 3.0.8(vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
'@vue/runtime-core':
specifier: 3.5.13
version: 3.5.13
acorn:
- specifier: 8.14.0
- version: 8.14.0
+ specifier: 8.14.1
+ version: 8.14.1
cross-env:
specifier: 7.0.3
version: 7.0.3
eslint-plugin-import:
specifier: 2.31.0
- version: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)
+ version: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)
eslint-plugin-vue:
- specifier: 9.33.0
- version: 9.33.0(eslint@9.20.1)
+ specifier: 10.0.0
+ version: 10.0.0(eslint@9.21.0)(vue-eslint-parser@10.1.1(eslint@9.21.0))
fast-glob:
specifier: 3.3.3
version: 3.3.3
happy-dom:
- specifier: 17.2.2
- version: 17.2.2
+ specifier: 17.3.0
+ version: 17.3.0
intersection-observer:
specifier: 0.12.2
version: 0.12.2
@@ -1204,8 +1216,8 @@ importers:
specifier: 2.2.8
version: 2.2.8
vue-eslint-parser:
- specifier: 9.4.3
- version: 9.4.3(eslint@9.20.1)
+ specifier: 10.1.1
+ version: 10.1.1(eslint@9.21.0)
vue-tsc:
specifier: 2.2.8
version: 2.2.8(typescript@5.8.2)
@@ -1224,16 +1236,16 @@ importers:
version: 22.13.9
'@typescript-eslint/eslint-plugin':
specifier: 8.26.0
- version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/parser':
specifier: 8.26.0
- version: 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
esbuild:
specifier: 0.25.0
version: 0.25.0
eslint-plugin-vue:
- specifier: 9.33.0
- version: 9.33.0(eslint@9.20.1)
+ specifier: 10.0.0
+ version: 10.0.0(eslint@9.21.0)(vue-eslint-parser@10.1.1(eslint@9.21.0))
nodemon:
specifier: 3.1.9
version: 3.1.9
@@ -1241,8 +1253,8 @@ importers:
specifier: 5.8.2
version: 5.8.2
vue-eslint-parser:
- specifier: 9.4.3
- version: 9.4.3(eslint@9.20.1)
+ specifier: 10.1.1
+ version: 10.1.1(eslint@9.21.0)
packages/misskey-bubble-game:
dependencies:
@@ -1267,10 +1279,10 @@ importers:
version: 3.0.8
'@typescript-eslint/eslint-plugin':
specifier: 8.26.0
- version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/parser':
specifier: 8.26.0
- version: 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
esbuild:
specifier: 0.25.0
version: 0.25.0
@@ -1313,10 +1325,10 @@ importers:
version: 22.13.9
'@typescript-eslint/eslint-plugin':
specifier: 8.26.0
- version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/parser':
specifier: 8.26.0
- version: 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
esbuild:
specifier: 0.25.0
version: 0.25.0
@@ -1361,10 +1373,10 @@ importers:
version: 22.13.9
'@typescript-eslint/eslint-plugin':
specifier: 8.26.0
- version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/parser':
specifier: 8.26.0
- version: 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
openapi-types:
specifier: 12.1.3
version: 12.1.3
@@ -1392,10 +1404,10 @@ importers:
version: 22.13.9
'@typescript-eslint/eslint-plugin':
specifier: 8.26.0
- version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/parser':
specifier: 8.26.0
- version: 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
esbuild:
specifier: 0.25.0
version: 0.25.0
@@ -1426,13 +1438,13 @@ importers:
devDependencies:
'@typescript-eslint/parser':
specifier: 8.26.0
- version: 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ version: 8.26.0(eslint@9.21.0)(typescript@5.8.2)
'@typescript/lib-webworker':
specifier: npm:@types/serviceworker@0.0.74
version: '@types/serviceworker@0.0.74'
eslint-plugin-import:
specifier: 2.31.0
- version: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)
+ version: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)
nodemon:
specifier: 3.1.9
version: 3.1.9
@@ -1445,11 +1457,6 @@ packages:
'@adobe/css-tools@4.4.0':
resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==}
- '@aiscript-dev/aiscript-languageserver@https://github.com/aiscript-dev/aiscript-languageserver/releases/download/0.1.6/aiscript-dev-aiscript-languageserver-0.1.6.tgz':
- resolution: {tarball: https://github.com/aiscript-dev/aiscript-languageserver/releases/download/0.1.6/aiscript-dev-aiscript-languageserver-0.1.6.tgz}
- version: 0.1.6
- hasBin: true
-
'@ampproject/remapping@2.3.0':
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
@@ -1645,10 +1652,6 @@ packages:
resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==}
engines: {node: '>=6.9.0'}
- '@babel/compat-data@7.23.5':
- resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==}
- engines: {node: '>=6.9.0'}
-
'@babel/compat-data@7.24.7':
resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==}
engines: {node: '>=6.9.0'}
@@ -1689,10 +1692,6 @@ packages:
resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==}
engines: {node: '>=6.9.0'}
- '@babel/helper-module-imports@7.22.15':
- resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
- engines: {node: '>=6.9.0'}
-
'@babel/helper-module-imports@7.24.7':
resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==}
engines: {node: '>=6.9.0'}
@@ -1713,10 +1712,6 @@ packages:
resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
engines: {node: '>=6.9.0'}
- '@babel/helper-simple-access@7.22.5':
- resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
- engines: {node: '>=6.9.0'}
-
'@babel/helper-simple-access@7.24.7':
resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==}
engines: {node: '>=6.9.0'}
@@ -1737,10 +1732,6 @@ packages:
resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
engines: {node: '>=6.9.0'}
- '@babel/helper-validator-option@7.23.5':
- resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
- engines: {node: '>=6.9.0'}
-
'@babel/helper-validator-option@7.24.7':
resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==}
engines: {node: '>=6.9.0'}
@@ -2143,32 +2134,28 @@ packages:
resolution: {integrity: sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/config-array@0.19.1':
- resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/core@0.10.0':
- resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==}
+ '@eslint/config-array@0.19.2':
+ resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/core@0.11.0':
- resolution: {integrity: sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==}
+ '@eslint/core@0.12.0':
+ resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/eslintrc@3.2.0':
- resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==}
+ '@eslint/eslintrc@3.3.0':
+ resolution: {integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/js@9.20.0':
- resolution: {integrity: sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==}
+ '@eslint/js@9.21.0':
+ resolution: {integrity: sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/object-schema@2.1.5':
- resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==}
+ '@eslint/object-schema@2.1.6':
+ resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/plugin-kit@0.2.5':
- resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==}
+ '@eslint/plugin-kit@0.2.7':
+ resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@fastify/accept-negotiator@2.0.0':
@@ -2277,8 +2264,8 @@ packages:
resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
engines: {node: '>=18.18'}
- '@humanwhocodes/retry@0.4.1':
- resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==}
+ '@humanwhocodes/retry@0.4.2':
+ resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==}
engines: {node: '>=18.18'}
'@img/sharp-darwin-arm64@0.33.5':
@@ -2413,6 +2400,10 @@ packages:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
+ '@isaacs/fs-minipass@4.0.1':
+ resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
+ engines: {node: '>=18.0.0'}
+
'@istanbuljs/load-nyc-config@1.1.0':
resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
engines: {node: '>=8'}
@@ -3619,120 +3610,120 @@ packages:
'@sqltools/formatter@1.2.5':
resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==}
- '@storybook/addon-actions@8.6.3':
- resolution: {integrity: sha512-0UrVqRoZFRFCqjtR8ODacpJNqi47qDUnsnB5F7e93U9ihSrH2edOBBX6frl11XKYA23rzq7jtnviFTVOpWpG7Q==}
+ '@storybook/addon-actions@8.6.4':
+ resolution: {integrity: sha512-mCcyfkeb19fJX0dpQqqZCnWBwjVn0/27xcpR0mbm/KW2wTByU6bKFFujgrHsX3ONl97IcIaUnmwwUwBr1ebZXw==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-backgrounds@8.6.3':
- resolution: {integrity: sha512-2mmMpMyUsS8rti2guMR4rk4h5YBLNHidxUqTm+U4nITZFfCXNP76To9hfTczpLTvUEpPxSbPG0sCIeHFaw4NRQ==}
+ '@storybook/addon-backgrounds@8.6.4':
+ resolution: {integrity: sha512-lRYGumlYdd1RptQJvOTRMx/q2pDmg2MO5GX4la7VfI8KrUyeuC1ZOSRDEcXeTuAZWJztqmtymg6bB7cAAoxCFA==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-controls@8.6.3':
- resolution: {integrity: sha512-j4Oof3nwjyiO6oNP1bJ98Sz1iZlYhdcgHX284yd0wBO91Q5B2GoCeqyCE+yRCh752ZnnYG1gazJrHmiG6gKxVg==}
+ '@storybook/addon-controls@8.6.4':
+ resolution: {integrity: sha512-oMMP9Bj0RMfYmaitjFt6oBSjKH4titUqP+wE6PrZ3v+Om56f4buqfNKXRf80As2OrsZn0pjj95muWzVVHqIhyQ==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-docs@8.6.3':
- resolution: {integrity: sha512-FRABH+r2huMpAK8iUQiFlYZtYenbqtudX3fNKFK9b38eV1R14kWggVG02lsa6upXbzxWVbMLUdOqaZJHxNbO/A==}
+ '@storybook/addon-docs@8.6.4':
+ resolution: {integrity: sha512-+kbcjvEAH0Xs+k+raAwfC0WmJilWhxBYnLLeazP3m5AkVI3sIjbzuuZ78NR0DCdRkw9BpuuXMHv5o4tIvLIUlw==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-essentials@8.6.3':
- resolution: {integrity: sha512-tH+MwkZ6UwRWyhGdq8izVZAZHGWdeiBY1wpIwdceP1Rl2j9s11Gbddb/JlmiXrC+f/Oiylxghaf7EIksVVqLQQ==}
+ '@storybook/addon-essentials@8.6.4':
+ resolution: {integrity: sha512-3pF0ZDl5EICqe0eOupPQq6PxeupwkLsfTWANuuJUYTJur82kvJd3Chb7P9vqw0A0QBx6106mL6PIyjrFJJMhLg==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-highlight@8.6.3':
- resolution: {integrity: sha512-LYZsgZt5q3EZBkZjUEELh/5+TDnUP0njuQ5g6skyKil6vj9+2RI4/Vjodp+ni5+xct5aDhXavRyUnPRfclX/Cg==}
+ '@storybook/addon-highlight@8.6.4':
+ resolution: {integrity: sha512-jFREXnSE/7VuBR8kbluN+DBVkMXEV7MGuCe8Ytb1/D2Q0ohgJe395dfVgEgSMXErOwsn//NV/NgJp6JNXH2DrA==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-interactions@8.6.3':
- resolution: {integrity: sha512-cDvxuMcjoQdtimNrT4BM9AK0qZJhA0Ep/CWPcVK1bAFzqlzBbe//UZa5It/AeC4EMYAr5rFY+LWEli3YPeOnjQ==}
+ '@storybook/addon-interactions@8.6.4':
+ resolution: {integrity: sha512-MZAAZjyvmJXCvM35zEiPpXz7vK+fimovt+WZKAMayAbXy5fT+7El0c9dDyTQ2norNKNj9QU/8hiU/1zARSUELQ==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-links@8.6.3':
- resolution: {integrity: sha512-3wGiMZxWbgdjEgymUrCVG5PwU0vAYF9EiSHsGxiSxje69l08GLD6s7FTLx0HwvuyiNFcigLcuF45XZnB252RtA==}
+ '@storybook/addon-links@8.6.4':
+ resolution: {integrity: sha512-TaSIteYLJ12+dVBk7fW96ZvNIFizKs+Vo/YuNAe4xTzFJRrjLkFj9htLVi/dusMfn7lYo5DHIns08LuM+po1Dg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
- storybook: ^8.6.3
+ storybook: ^8.6.4
peerDependenciesMeta:
react:
optional: true
- '@storybook/addon-mdx-gfm@8.6.3':
- resolution: {integrity: sha512-SNHrYeGLqV1Ym1tDWQpDYU83o0R/cDRsFT4O1kiHTkb/QFZ3XZw1oq2bn02Bvt3LZTJ8KYiT3Iqf1mYWjcDkMQ==}
+ '@storybook/addon-mdx-gfm@8.6.4':
+ resolution: {integrity: sha512-9ipDU8pNnf0PiCTYaPtm7QLfhskYRE7S9vzZ0PDGwdlIDd2TdkAUZt8dys7zg9t4/Rc5UGWpGDEJ5O7v1H/OGw==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-measure@8.6.3':
- resolution: {integrity: sha512-FC/3pqM2adSnwyPOd9AxEoZD5XWCMKAk16urQFQ0M4+IzRUdf2OV8cc7aM/oZiBX36+q/UCcUWm2SbQ5nzNJpg==}
+ '@storybook/addon-measure@8.6.4':
+ resolution: {integrity: sha512-IpVL1rTy1tO8sy140eU3GdVB1QJ6J62+V6GSstcmqTLxDJQk5jFfg7hVbPEAZZ2sPFmeyceP9AMoBBo0EB355A==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-outline@8.6.3':
- resolution: {integrity: sha512-YklKHRkoDLSWawIIBrEI69RAWEdvhkYCOv+fMLu9zBeVPnkwbtIjXN/I+UJwPCm6jlxeEwEUAvbPWZMMf+BkPQ==}
+ '@storybook/addon-outline@8.6.4':
+ resolution: {integrity: sha512-28nAslKTy0zWMdxAZcipMDYrEp1TkXVooAsqMGY5AMXMiORi1ObjhmjTLhVt1dXp+aDg0X+M3B6PqoingmHhqQ==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-storysource@8.6.3':
- resolution: {integrity: sha512-Pwp3Xy/HIMLhaK4Qf+ZgZSnMWvmpvn7bKbbCjuyMHmGFA81lT4NlF+HaBp2IRio85Nk9zOF2wduuH1xaoBuSfQ==}
+ '@storybook/addon-storysource@8.6.4':
+ resolution: {integrity: sha512-b9azhM6ur+W2QZI+xp1NY7sTVJqWqGR1bgi8gFC/4vA//sXD17+S03GX84Wb8HWGGZheDvRKh41Ob2ebMUxHdg==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-toolbars@8.6.3':
- resolution: {integrity: sha512-GTC1GPrFNfWvvBaQQnGuL7ZfGK5Q+3ZovwQA9tnPu7QZEwea/4CXvUyQh1u0NwqrFZkrabOad1XvYfpRuCPGSA==}
+ '@storybook/addon-toolbars@8.6.4':
+ resolution: {integrity: sha512-PU2lvgwCKDn93zpp5MEog103UUmSSugcxDf18xaoa9D15Qtr+YuQHd2hXbxA7+dnYL9lA7MLYsstfxE91ieM4Q==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/addon-viewport@8.6.3':
- resolution: {integrity: sha512-AixZKiQdBVs7ePj5iV0U1IY2jvH0G7wQJwBRTOq4qC1FKiOsZEYmrwc3wLUBUlVqyenXFKN+H40r4VhPzzSfLw==}
+ '@storybook/addon-viewport@8.6.4':
+ resolution: {integrity: sha512-O5Ij+SRVg6grY6JOL5lOpsFyopZxuZEl2GHfh2SUf9hfowNS0QAgFpJupqXkwZzRSrlf9uKrLkjB6ulLgN2gOQ==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/blocks@8.6.3':
- resolution: {integrity: sha512-Ieu6kwqdeAcrLzcX2QIqnCd0XWZi46i4eem8W54JRiOMQMYUpZ7onbciRAP58qxEWrZWqgxPS+tiCTaJe48VVQ==}
+ '@storybook/blocks@8.6.4':
+ resolution: {integrity: sha512-+oPXwT3KzJzsdkQuGEzBqOKTIFlb6qmlCWWbDwAnP0SEqYHoTVRTAIa44icFP0EZeIe+ypFVAm1E7kWTLmw1hQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
- storybook: ^8.6.3
+ storybook: ^8.6.4
peerDependenciesMeta:
react:
optional: true
react-dom:
optional: true
- '@storybook/builder-vite@8.6.3':
- resolution: {integrity: sha512-v/nlBeT7Avn1ld2GHY5dtm1+TKREvtQ+DEcKK5iOWfv2259WqUp0dGnF4fbHcsNCtFurkA/P2uqJ9vc0xOIVUg==}
+ '@storybook/builder-vite@8.6.4':
+ resolution: {integrity: sha512-FuSP2GhWVVTt6NdX0UJHhPOqhu09X4apSk+KWUf3aITRIJg9gbPYtJDBmxv1vXQEgvfCDdYBYbeG1khiO/Ghfw==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
vite: ^4.0.0 || ^5.0.0 || ^6.0.0
- '@storybook/components@8.6.3':
- resolution: {integrity: sha512-q5DQkV+E/j0KfF818RywgqEHjaZTg71q5YY4z0UO8CRSzDQ/VYF6L76oc69corbkJtYAk/GqaYJllzrWykS4sg==}
+ '@storybook/components@8.6.4':
+ resolution: {integrity: sha512-91VEVFWOgHkEFoNFMk6gs1AuOE9Yp7N283BXQOW+AgP+atpzED6t/fIBPGqJ2ewAuzLJ+cFOrasSzoNwVfg3Jg==}
peerDependencies:
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
- '@storybook/core-events@8.6.3':
- resolution: {integrity: sha512-+UCkypJKcrITCuA84IITcn1RI1gxXGl72e0KszfFYgsSkJpDMvxSU2RwVqJSORBe5GU3XOIR3FaNngbkO3nXMg==}
+ '@storybook/core-events@8.6.4':
+ resolution: {integrity: sha512-m2fux7Z/XZXS3Hpq0PHOSj6U8hpTrvmXs2OmH4CtKoDdTy8iFVBW+Q2057Klwvp37y8dF01jPn1lSAG1nkSpYQ==}
peerDependencies:
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
- '@storybook/core@8.6.3':
- resolution: {integrity: sha512-0iMTfmo3UFCa1hFJLtThnRIppkIpGPyTL3MElhORP1t5l9lCUq5am0ymbi/TeCbsJPjE86FjeO0NinokL9iQiw==}
+ '@storybook/core@8.6.4':
+ resolution: {integrity: sha512-glDbjEBi3wokw1T+KQtl93irHO9N0LCwgylWfWVXYDdQjUJ7pGRQGnw73gPX7Ds9tg3myXFC83GjmY94UYSMbA==}
peerDependencies:
prettier: ^2 || ^3
peerDependenciesMeta:
prettier:
optional: true
- '@storybook/csf-plugin@8.6.3':
- resolution: {integrity: sha512-0QDLBcMOxSEt1yH28cvIsoiaIokIxDDShMnxVJHWk/7+KZ3xe4lZBfKCWZspZoJmrxgz10gLRifj1b3ysIFlyA==}
+ '@storybook/csf-plugin@8.6.4':
+ resolution: {integrity: sha512-7UpEp4PFTy1iKjZiRaYMG7zvnpLIRPyD0+lUJUlLYG4UIemV3onvnIi1Je1tSZ4hfTup+ulom7JLztVSHZGRMg==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
'@storybook/global@5.0.0':
resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==}
@@ -3744,49 +3735,49 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
- '@storybook/instrumenter@8.6.3':
- resolution: {integrity: sha512-Y5n6JWCWdOqok08Hgklsc98TBoqROhAhBRSzNWuIaLsRhz8EziXQtuEkWqmVbyYOys25iTZiK3S8+QQkOzGrBw==}
+ '@storybook/instrumenter@8.6.4':
+ resolution: {integrity: sha512-8OtIWLhayTUdqJEeXiPm6l3LTdSkWgQzzV2l2HIe4Adedeot+Rkwu6XHmyRDpnb0+Ish6zmMDqtJBxC2PQsy6Q==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/manager-api@8.6.3':
- resolution: {integrity: sha512-7m9MQELc6XpuKIuliqMiQWzl8yVWpUDwTcpr+rTT7l3OfRzw7Y00UFct2tI03YG6EXsxsykw8EmueMQhe0lG5Q==}
+ '@storybook/manager-api@8.6.4':
+ resolution: {integrity: sha512-w/Nn/VznfbIg2oezDfzZNwSTDY5kBZbzxVBHLCnIcyu2AKt2Yto3pfGi60SikFcTrsClaAKT7D92kMQ9qdQNQQ==}
peerDependencies:
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
- '@storybook/preview-api@8.6.3':
- resolution: {integrity: sha512-y2Ic6eHBQD/AwaCHctKOJ4tOM1r7/mPXfhGh0I+Qf8kZPlDTgQcJ6Z7/Ruma1L+ijXPBWouDaPw51gipcX+t9Q==}
+ '@storybook/preview-api@8.6.4':
+ resolution: {integrity: sha512-5HBfxggzxGz0dg2c61NpPiQJav7UAmzsQlzmI5SzWOS6lkaylcDG8giwKzASVCXVWBxNji9qIDFM++UH090aDg==}
peerDependencies:
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
- '@storybook/react-dom-shim@8.6.3':
- resolution: {integrity: sha512-vE3LA2TxbzDF1Fso2IgvUtoHc+8a6laKhuJdx8frP5A8M1KGOBfuEPFCCcE49Q90HUlDgwb/zQl1GNq/QjLgWQ==}
+ '@storybook/react-dom-shim@8.6.4':
+ resolution: {integrity: sha512-kTGJ3aFdmfCFzYaDFGmZWfTXr9xhbUaf0tJ6+nEjc4tME6mFwMI+tTUT6U/J6mJhZuc2DjvIRA7bM0x77dIDqw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/react-vite@8.6.3':
- resolution: {integrity: sha512-A/cA0wM/mMfFcJH7dxhWSbVg9aE2zZKNDioyEbiB042CgrLW3zQ6dvQvA5ohFhsPWZ6GVAyc+r3x0JE55aXxWQ==}
+ '@storybook/react-vite@8.6.4':
+ resolution: {integrity: sha512-MEmD6sP2tUI/SYCXCeWGTs8umZj+N0e3DHXCQUz0nCsJH7kuCTTipOTBQvr/GuEstNd7BNG5k8aLIRrXLjAvdA==}
engines: {node: '>=18.0.0'}
peerDependencies:
- '@storybook/test': 8.6.3
+ '@storybook/test': 8.6.4
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
- storybook: ^8.6.3
+ storybook: ^8.6.4
vite: ^4.0.0 || ^5.0.0 || ^6.0.0
peerDependenciesMeta:
'@storybook/test':
optional: true
- '@storybook/react@8.6.3':
- resolution: {integrity: sha512-B4WYRWU2Y71UWl4CG3+mcB7duNln9finJyDB8Y1o2CYWUxgEo+3Bnp3k7NUr++tYVkZI1H+28UWeX0rpCkvReQ==}
+ '@storybook/react@8.6.4':
+ resolution: {integrity: sha512-pfv4hMhu3AScOh0l86uIzmXLSQ0XA/e0reIVwQcxKht6miaKArhx9GkS4mMp6SO23ZoV5G/nfLgUaMVPVE0ZPg==}
engines: {node: '>=18.0.0'}
peerDependencies:
- '@storybook/test': 8.6.3
+ '@storybook/test': 8.6.4
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
- storybook: ^8.6.3
+ storybook: ^8.6.4
typescript: '>= 4.2.x'
peerDependenciesMeta:
'@storybook/test':
@@ -3794,38 +3785,38 @@ packages:
typescript:
optional: true
- '@storybook/source-loader@8.6.3':
- resolution: {integrity: sha512-I6vDK5mwLLHgBqh0OVn2zAZbZ8Xa3L/+w1tNN4v6HuAjW1DU6rdBtxvjTFjxTDqyvSptxL1AvVsFF62hN7GsuQ==}
+ '@storybook/source-loader@8.6.4':
+ resolution: {integrity: sha512-1lwX+X4dH/KNt5hsOjSGuARIaQzwMnRBdZCqIfVFwjcP0qUAIBFVTsD6R4YemJ1HkV8zjX6Zs8Ubf99M84VtPQ==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/test@8.6.3':
- resolution: {integrity: sha512-UimvhV/PmYoXCwIbGpkyqQfMhjdH2GaHJbV6BWr7M7BHA3kUS6zYJAm2V2CC5SYcmyj7FejLB4tgL7FmLXB6hA==}
+ '@storybook/test@8.6.4':
+ resolution: {integrity: sha512-JPjfbaMMuCBT47pg3/MDD9vYFF5OGPAOWEB9nJWJ9IjYAb2Nd8OYJQIDoYJQNT+aLkTVLtvzGnVNwdxpouAJcQ==}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
- '@storybook/theming@8.6.3':
- resolution: {integrity: sha512-sDcWnnko73KOCIc9stQyec9KvTmGOuMswqeKtWh0ha/wsgYB6G2/2j1xOheFmWKPitOsbwgvqtjCP7bRE68uIA==}
+ '@storybook/theming@8.6.4':
+ resolution: {integrity: sha512-g9Ns4uenC9oAWETaJ/tEKEIPMdS+CqjNWZz5Wbw1bLNhXwADZgKrVqawzZi64+bYYtQ+i8VCTjPoFa6s2eHiDQ==}
peerDependencies:
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
- '@storybook/types@8.6.3':
- resolution: {integrity: sha512-lU2PO4SBhgtDru7TH/18jFNY7I5aFPdmd7BpZk1dkHuOgklOKUU2yC6VtRoRu8cJUmhzuUXET/K/FHOx95c4dw==}
+ '@storybook/types@8.6.4':
+ resolution: {integrity: sha512-6VJat4/2Ne2tuz3s0iOHpMpW3/zdHGDAxGTSgJCxcgElNQgceI8dlhTwB0b3B6WyoG2tSt9DgbGa/TdfZhSAPg==}
peerDependencies:
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
- '@storybook/vue3-vite@8.6.3':
- resolution: {integrity: sha512-7LVIDjujXsML5KqDrj03u96C78aYkk4zw+y/enYMZGtc0mZ0mJEYKEJy8GhraqZGEU21Ni+ckeCttgt31S0UPQ==}
+ '@storybook/vue3-vite@8.6.4':
+ resolution: {integrity: sha512-zmWfSc3DfJzh1DkdiKrQW9XHfBnnlauCroBfvKjo7v91eLXi2GTH2U6CUJR0d7jJ7TJh5dKN6JOQINtk/PKxKg==}
engines: {node: '>=18.0.0'}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
vite: ^4.0.0 || ^5.0.0 || ^6.0.0
- '@storybook/vue3@8.6.3':
- resolution: {integrity: sha512-QMvAlX20+Yq37vkcR7VP21+f1yj+HoS5j6nvQZnfp36rs08KVnXBTF8KtnbjAqBA1KFdZgSXMtB4fWxvCHGLbA==}
+ '@storybook/vue3@8.6.4':
+ resolution: {integrity: sha512-Vrgnonk3sSZZHciJ/0Ey+cnOEDlqucnLks1iJ1QKrka//Y+rtIzfHhcGs7HnF0VxtFpajNPSNM4MYj59USjiXQ==}
engines: {node: '>=18.0.0'}
peerDependencies:
- storybook: ^8.6.3
+ storybook: ^8.6.4
vue: ^3.0.0
'@stylistic/eslint-plugin@2.13.0':
@@ -3840,7 +3831,7 @@ packages:
hasBin: true
peerDependencies:
'@swc/core': ^1.2.66
- chokidar: 3.6.0
+ chokidar: 4.0.3
peerDependenciesMeta:
chokidar:
optional: true
@@ -4470,11 +4461,11 @@ packages:
vite: ^5.0.0 || ^6.0.0
vue: ^3.2.25
- '@vitest/coverage-v8@3.0.7':
- resolution: {integrity: sha512-Av8WgBJLTrfLOer0uy3CxjlVuWK4CzcLBndW1Nm2vI+3hZ2ozHututkfc7Blu1u6waeQ7J8gzPK/AsBRnWA5mQ==}
+ '@vitest/coverage-v8@3.0.8':
+ resolution: {integrity: sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==}
peerDependencies:
- '@vitest/browser': 3.0.7
- vitest: 3.0.7
+ '@vitest/browser': 3.0.8
+ vitest: 3.0.8
peerDependenciesMeta:
'@vitest/browser':
optional: true
@@ -4482,11 +4473,11 @@ packages:
'@vitest/expect@2.0.5':
resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==}
- '@vitest/expect@3.0.7':
- resolution: {integrity: sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw==}
+ '@vitest/expect@3.0.8':
+ resolution: {integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==}
- '@vitest/mocker@3.0.7':
- resolution: {integrity: sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w==}
+ '@vitest/mocker@3.0.8':
+ resolution: {integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==}
peerDependencies:
msw: ^2.4.9
vite: ^5.0.0 || ^6.0.0
@@ -4502,20 +4493,20 @@ packages:
'@vitest/pretty-format@2.1.1':
resolution: {integrity: sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==}
- '@vitest/pretty-format@3.0.7':
- resolution: {integrity: sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg==}
+ '@vitest/pretty-format@3.0.8':
+ resolution: {integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==}
- '@vitest/runner@3.0.7':
- resolution: {integrity: sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g==}
+ '@vitest/runner@3.0.8':
+ resolution: {integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==}
- '@vitest/snapshot@3.0.7':
- resolution: {integrity: sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA==}
+ '@vitest/snapshot@3.0.8':
+ resolution: {integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==}
'@vitest/spy@2.0.5':
resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==}
- '@vitest/spy@3.0.7':
- resolution: {integrity: sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w==}
+ '@vitest/spy@3.0.8':
+ resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==}
'@vitest/utils@2.0.5':
resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==}
@@ -4523,8 +4514,8 @@ packages:
'@vitest/utils@2.1.1':
resolution: {integrity: sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==}
- '@vitest/utils@3.0.7':
- resolution: {integrity: sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg==}
+ '@vitest/utils@3.0.8':
+ resolution: {integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==}
'@volar/language-core@2.2.0':
resolution: {integrity: sha512-a8WG9+4OdeNDW4ywABZIM6S6UN7em8uIlM/BZ2pWQUYrVmX+m8sj/X+QadvO+Li/t/LjAqbWJQtVgxdpEWLALQ==}
@@ -4677,8 +4668,8 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
- acorn@8.14.0:
- resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
+ acorn@8.14.1:
+ resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==}
engines: {node: '>=0.4.0'}
hasBin: true
@@ -5020,10 +5011,6 @@ packages:
resolution: {integrity: sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw==}
engines: {node: '>=12'}
- binary-extensions@2.2.0:
- resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
- engines: {node: '>=8'}
-
bl@4.1.0:
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
@@ -5065,11 +5052,6 @@ packages:
browser-assert@1.2.1:
resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==}
- browserslist@4.23.0:
- resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==}
- engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
- hasBin: true
-
browserslist@4.24.4:
resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -5146,9 +5128,6 @@ packages:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
- call-bind@1.0.2:
- resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
-
call-bind@1.0.7:
resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
engines: {node: '>= 0.4'}
@@ -5281,9 +5260,9 @@ packages:
resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==}
engines: {node: '>=18.17'}
- chokidar@3.6.0:
- resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
- engines: {node: '>= 8.10.0'}
+ chokidar@4.0.3:
+ resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
+ engines: {node: '>= 14.16.0'}
chownr@1.1.4:
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
@@ -5292,6 +5271,10 @@ packages:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
engines: {node: '>=10'}
+ chownr@3.0.0:
+ resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
+ engines: {node: '>=18'}
+
chromatic@11.27.0:
resolution: {integrity: sha512-jQ2ufjS+ePpg+NtcPI9B2eOi+pAzlRd2nhd1LgNMsVCC9Bzf5t8mJtyd8v2AUuJS0LdX0QVBgkOnlNv9xviHzA==}
hasBin: true
@@ -5604,11 +5587,6 @@ packages:
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
- cypress@14.0.3:
- resolution: {integrity: sha512-yIdvobANw3kS+KF/t5vwjjPNufBA8ux7iQHaWxPTkUw2yCKI72m9mKM24eOwE84Wk4ALPsSvEcGbDrwgmhr4RA==}
- engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
- hasBin: true
-
cypress@14.1.0:
resolution: {integrity: sha512-pPPj8Uu9NwjaaiXAEcjYZZmgsq6v9Zs1Nw6a+zRF+ANgYSNhH4S32SjFRsvMcuOHR/8dp4GBJhBPqIPSs+TxaA==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -5925,9 +5903,6 @@ packages:
engines: {node: '>=0.10.0'}
hasBin: true
- electron-to-chromium@1.4.686:
- resolution: {integrity: sha512-3avY1B+vUzNxEgkBDpKOP8WarvUAEwpRaiCL0He5OKWEFxzaOFiq4WoZEZe7qh0ReS7DiWoHMnYoQCKxNZNzSg==}
-
electron-to-chromium@1.5.83:
resolution: {integrity: sha512-LcUDPqSt+V0QmI47XLzZrz5OqILSMGsPFkDYus22rIbgorSvBYEFqq854ltTmUdHkY92FSdAAvsh4jWEULMdfQ==}
@@ -6121,19 +6096,16 @@ packages:
'@typescript-eslint/parser':
optional: true
- eslint-plugin-vue@9.33.0:
- resolution: {integrity: sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==}
- engines: {node: ^14.17.0 || >=16.0.0}
+ eslint-plugin-vue@10.0.0:
+ resolution: {integrity: sha512-XKckedtajqwmaX6u1VnECmZ6xJt+YvlmMzBPZd+/sI3ub2lpYZyFnsyWo7c3nMOQKJQudeyk1lw/JxdgeKT64w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
+ eslint: ^8.57.0 || ^9.0.0
+ vue-eslint-parser: ^10.0.0
eslint-rule-docs@1.1.235:
resolution: {integrity: sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==}
- eslint-scope@7.2.2:
- resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
eslint-scope@8.2.0:
resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -6146,8 +6118,8 @@ packages:
resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- eslint@9.20.1:
- resolution: {integrity: sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==}
+ eslint@9.21.0:
+ resolution: {integrity: sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
peerDependencies:
@@ -6160,10 +6132,6 @@ packages:
resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- espree@9.6.1:
- resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
@@ -6641,16 +6609,12 @@ packages:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
- globals@13.24.0:
- resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
- engines: {node: '>=8'}
-
globals@14.0.0:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
- globals@15.15.0:
- resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
+ globals@16.0.0:
+ resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==}
engines: {node: '>=18'}
globalthis@1.0.3:
@@ -6697,8 +6661,8 @@ packages:
resolution: {integrity: sha512-n0QrmT9lD81rbpKsyhnlz3DgnMZlaOkJPpgi746doA+HvaMC79bdWkwjrNnGJRvDrWTI8iOcJiVTJ5CdT/AZRw==}
engines: {node: '>=18.0.0'}
- happy-dom@17.2.2:
- resolution: {integrity: sha512-3I1/CrNi780sdOhuhUnFtgTWhloSc3quSZwsylI41jycx8o97M6Y4aQAu0phSexGusT7+59BxATh4L4xiY0HcA==}
+ happy-dom@17.3.0:
+ resolution: {integrity: sha512-dTwlpUHrhE0usQOd1Df9k461SOYQUWNl0G31mXCDj+N9//oPcDb+cchrSJzrXN6qxZ5sZSrLf5AfY702Zvddfw==}
engines: {node: '>=18.0.0'}
hard-rejection@2.1.0:
@@ -6901,9 +6865,9 @@ packages:
ignore-by-default@1.0.1:
resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==}
- ignore-walk@6.0.5:
- resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ ignore-walk@7.0.0:
+ resolution: {integrity: sha512-T4gbf83A4NH95zvhVYZc+qWocBBGlpzUXLPGurJggw/WIOwicfXJChLDP/iBZnN5WqROSu5Bm3hhle4z8a8YGQ==}
+ engines: {node: ^18.17.0 || >=20.5.0}
ignore@5.3.1:
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
@@ -7026,10 +6990,6 @@ packages:
is-bigint@1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
- is-binary-path@2.1.0:
- resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
- engines: {node: '>=8'}
-
is-boolean-object@1.1.2:
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
engines: {node: '>= 0.4'}
@@ -7686,9 +7646,6 @@ packages:
resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
engines: {node: '>=12'}
- magic-string@0.30.11:
- resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
-
magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
@@ -8008,10 +7965,6 @@ packages:
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
engines: {node: '>=8'}
- minipass@7.0.4:
- resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
- engines: {node: '>=16 || 14 >=14.17'}
-
minipass@7.1.2:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -8020,6 +7973,10 @@ packages:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'}
+ minizlib@3.0.1:
+ resolution: {integrity: sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==}
+ engines: {node: '>= 18'}
+
mkdirp-classic@0.5.3:
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
@@ -8037,6 +7994,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ mkdirp@3.0.1:
+ resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
+ engines: {node: '>=10'}
+ hasBin: true
+
mnemonist@0.39.8:
resolution: {integrity: sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==}
@@ -8201,9 +8163,6 @@ packages:
node-int64@0.4.0:
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
- node-releases@2.0.14:
- resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
-
node-releases@2.0.19:
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
@@ -8645,6 +8604,11 @@ packages:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
+ pnpm@10.6.1:
+ resolution: {integrity: sha512-QO4Jr0B/qfu1+/uOHLQPu3TArww+EOkiTXtTx2WFKGFbLJJFDnTPrZHjotyv485AUNgL2nHXV3VtLOK2YhPpow==}
+ engines: {node: '>=18.12'}
+ hasBin: true
+
polished@4.2.2:
resolution: {integrity: sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==}
engines: {node: '>=10'}
@@ -8826,10 +8790,6 @@ packages:
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
- postcss@8.5.2:
- resolution: {integrity: sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==}
- engines: {node: ^10 || ^12 || >=14}
-
postcss@8.5.3:
resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
engines: {node: ^10 || ^12 || >=14}
@@ -9151,9 +9111,9 @@ packages:
readdir-glob@1.1.2:
resolution: {integrity: sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==}
- readdirp@3.6.0:
- resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
- engines: {node: '>=8.10.0'}
+ readdirp@4.1.2:
+ resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
+ engines: {node: '>= 14.18.0'}
real-require@0.2.0:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
@@ -9303,6 +9263,10 @@ packages:
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
+ rimraf@5.0.10:
+ resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==}
+ hasBin: true
+
rollup@4.34.9:
resolution: {integrity: sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -9403,11 +9367,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
- semver@7.6.0:
- resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==}
- engines: {node: '>=10'}
- hasBin: true
-
semver@7.6.3:
resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
engines: {node: '>=10'}
@@ -9726,8 +9685,8 @@ packages:
react-dom:
optional: true
- storybook@8.6.3:
- resolution: {integrity: sha512-Vbmd8/FXp6X0AOMak6arcg3WdkHj+2AYJTNHbCPVHsCEbnREyRZIG+Eq5/Ffmy6byiz+4OAX5HwsHGSMR6Xmow==}
+ storybook@8.6.4:
+ resolution: {integrity: sha512-XXh1Acvf1r3BQX0BDLQw6yhZ7yUGvYxIcKOBuMdetnX7iXtczipJTfw0uyFwk0ltkKEE9PpJvivYmARF3u64VQ==}
hasBin: true
peerDependencies:
prettier: ^2 || ^3
@@ -9921,6 +9880,10 @@ packages:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
+ tar@7.4.3:
+ resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
+ engines: {node: '>=18'}
+
taskkill@5.0.0:
resolution: {integrity: sha512-+HRtZ40Vc+6YfCDWCeAsixwxJgMbPY4HHuTgzPYH3JXvqHWUlsCfy+ylXlAKhFNcuLp4xVeWeFBUhDk+7KYUvQ==}
engines: {node: '>=14.16'}
@@ -10130,10 +10093,6 @@ packages:
resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==}
engines: {node: '>=10'}
- type-fest@0.20.2:
- resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
- engines: {node: '>=10'}
-
type-fest@0.21.3:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
@@ -10351,12 +10310,6 @@ packages:
resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
engines: {node: '>=8'}
- update-browserslist-db@1.0.13:
- resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
- hasBin: true
- peerDependencies:
- browserslist: '>= 4.21.0'
-
update-browserslist-db@1.1.2:
resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==}
hasBin: true
@@ -10429,16 +10382,16 @@ packages:
vfile@6.0.1:
resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==}
- vite-node@3.0.7:
- resolution: {integrity: sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A==}
+ vite-node@3.0.8:
+ resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
vite-plugin-turbosnap@1.0.3:
resolution: {integrity: sha512-p4D8CFVhZS412SyQX125qxyzOgIFouwOcvjZWk6bQbNPR1wtaEzFT6jZxAjf1dejlGqa6fqHcuCvQea6EWUkUA==}
- vite@6.2.0:
- resolution: {integrity: sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==}
+ vite@6.2.1:
+ resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
@@ -10483,16 +10436,16 @@ packages:
peerDependencies:
vitest: '>=2.0.0'
- vitest@3.0.7:
- resolution: {integrity: sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg==}
+ vitest@3.0.8:
+ resolution: {integrity: sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@types/debug': ^4.1.12
'@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
- '@vitest/browser': 3.0.7
- '@vitest/ui': 3.0.7
+ '@vitest/browser': 3.0.8
+ '@vitest/ui': 3.0.8
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -10526,16 +10479,9 @@ packages:
vscode-languageserver-protocol@3.17.5:
resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}
- vscode-languageserver-textdocument@1.0.11:
- resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==}
-
vscode-languageserver-types@3.17.5:
resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}
- vscode-languageserver@9.0.1:
- resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
- hasBin: true
-
vscode-uri@3.0.8:
resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
@@ -10572,11 +10518,11 @@ packages:
peerDependencies:
vue: '>=2'
- vue-eslint-parser@9.4.3:
- resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==}
- engines: {node: ^14.17.0 || >=16.0.0}
+ vue-eslint-parser@10.1.1:
+ resolution: {integrity: sha512-bh2Z/Au5slro9QJ3neFYLanZtb1jH+W2bKqGHXAoYD4vZgNG3KeotL7JpPv5xzY4UXUXJl7TrIsnzECH63kd3Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- eslint: '>=6.0.0'
+ eslint: ^8.57.0 || ^9.0.0
vue-inbrowser-compiler-independent-utils@4.71.1:
resolution: {integrity: sha512-K3wt3iVmNGaFEOUR4JIThQRWfqokxLfnPslD41FDZB2ajXp789+wCqJyGYlIFsvEQ2P61PInw6/ph5iiqg51gg==}
@@ -10788,6 +10734,10 @@ packages:
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+ yallist@5.0.0:
+ resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
+ engines: {node: '>=18'}
+
yargs-parser@18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
@@ -10842,14 +10792,6 @@ snapshots:
'@adobe/css-tools@4.4.0': {}
- '@aiscript-dev/aiscript-languageserver@https://github.com/aiscript-dev/aiscript-languageserver/releases/download/0.1.6/aiscript-dev-aiscript-languageserver-0.1.6.tgz':
- dependencies:
- seedrandom: 3.0.5
- stringz: 2.1.0
- uuid: 9.0.1
- vscode-languageserver: 9.0.1
- vscode-languageserver-textdocument: 1.0.11
-
'@ampproject/remapping@2.3.0':
dependencies:
'@jridgewell/gen-mapping': 0.3.5
@@ -11375,8 +11317,6 @@ snapshots:
'@babel/highlight': 7.24.7
picocolors: 1.1.1
- '@babel/compat-data@7.23.5': {}
-
'@babel/compat-data@7.24.7': {}
'@babel/core@7.23.5':
@@ -11435,9 +11375,9 @@ snapshots:
'@babel/helper-compilation-targets@7.22.15':
dependencies:
- '@babel/compat-data': 7.23.5
- '@babel/helper-validator-option': 7.23.5
- browserslist: 4.23.0
+ '@babel/compat-data': 7.24.7
+ '@babel/helper-validator-option': 7.24.7
+ browserslist: 4.24.4
lru-cache: 5.1.1
semver: 6.3.1
@@ -11462,10 +11402,6 @@ snapshots:
dependencies:
'@babel/types': 7.25.6
- '@babel/helper-module-imports@7.22.15':
- dependencies:
- '@babel/types': 7.25.6
-
'@babel/helper-module-imports@7.24.7':
dependencies:
'@babel/traverse': 7.24.7
@@ -11477,10 +11413,12 @@ snapshots:
dependencies:
'@babel/core': 7.23.5
'@babel/helper-environment-visitor': 7.24.7
- '@babel/helper-module-imports': 7.22.15
- '@babel/helper-simple-access': 7.22.5
+ '@babel/helper-module-imports': 7.24.7
+ '@babel/helper-simple-access': 7.24.7
'@babel/helper-split-export-declaration': 7.24.7
'@babel/helper-validator-identifier': 7.24.7
+ transitivePeerDependencies:
+ - supports-color
'@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7)':
dependencies:
@@ -11495,10 +11433,6 @@ snapshots:
'@babel/helper-plugin-utils@7.22.5': {}
- '@babel/helper-simple-access@7.22.5':
- dependencies:
- '@babel/types': 7.25.6
-
'@babel/helper-simple-access@7.24.7':
dependencies:
'@babel/traverse': 7.24.7
@@ -11516,8 +11450,6 @@ snapshots:
'@babel/helper-validator-identifier@7.24.7': {}
- '@babel/helper-validator-option@7.23.5': {}
-
'@babel/helper-validator-option@7.24.7': {}
'@babel/helpers@7.23.5':
@@ -11911,32 +11843,28 @@ snapshots:
'@esbuild/win32-x64@0.25.0':
optional: true
- '@eslint-community/eslint-utils@4.4.0(eslint@9.20.1)':
+ '@eslint-community/eslint-utils@4.4.0(eslint@9.21.0)':
dependencies:
- eslint: 9.20.1
+ eslint: 9.21.0
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
'@eslint/compat@1.1.1': {}
- '@eslint/config-array@0.19.1':
+ '@eslint/config-array@0.19.2':
dependencies:
- '@eslint/object-schema': 2.1.5
+ '@eslint/object-schema': 2.1.6
debug: 4.4.0(supports-color@8.1.1)
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
- '@eslint/core@0.10.0':
+ '@eslint/core@0.12.0':
dependencies:
'@types/json-schema': 7.0.15
- '@eslint/core@0.11.0':
- dependencies:
- '@types/json-schema': 7.0.15
-
- '@eslint/eslintrc@3.2.0':
+ '@eslint/eslintrc@3.3.0':
dependencies:
ajv: 6.12.6
debug: 4.4.0(supports-color@8.1.1)
@@ -11950,13 +11878,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/js@9.20.0': {}
+ '@eslint/js@9.21.0': {}
- '@eslint/object-schema@2.1.5': {}
+ '@eslint/object-schema@2.1.6': {}
- '@eslint/plugin-kit@0.2.5':
+ '@eslint/plugin-kit@0.2.7':
dependencies:
- '@eslint/core': 0.10.0
+ '@eslint/core': 0.12.0
levn: 0.4.1
'@fastify/accept-negotiator@2.0.0': {}
@@ -12099,7 +12027,7 @@ snapshots:
'@humanwhocodes/retry@0.3.0': {}
- '@humanwhocodes/retry@0.4.1': {}
+ '@humanwhocodes/retry@0.4.2': {}
'@img/sharp-darwin-arm64@0.33.5':
optionalDependencies:
@@ -12213,6 +12141,10 @@ snapshots:
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
+ '@isaacs/fs-minipass@4.0.1':
+ dependencies:
+ minipass: 7.1.2
+
'@istanbuljs/load-nyc-config@1.1.0':
dependencies:
camelcase: 5.3.1
@@ -12389,12 +12321,12 @@ snapshots:
'@types/yargs': 17.0.19
chalk: 4.1.2
- '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
+ '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
dependencies:
glob: 10.4.5
magic-string: 0.27.0
react-docgen-typescript: 2.2.2(typescript@5.8.2)
- vite: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
optionalDependencies:
typescript: 5.8.2
@@ -12495,15 +12427,15 @@ snapshots:
'@misskey-dev/browser-image-resizer@2024.1.0': {}
- '@misskey-dev/eslint-plugin@2.1.0(@eslint/compat@1.1.1)(@stylistic/eslint-plugin@2.13.0(eslint@9.20.1)(typescript@5.7.3))(@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1)(typescript@5.7.3))(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1))(eslint@9.20.1)(globals@15.15.0)':
+ '@misskey-dev/eslint-plugin@2.1.0(@eslint/compat@1.1.1)(@stylistic/eslint-plugin@2.13.0(eslint@9.21.0)(typescript@5.8.2))(@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2))(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0))(eslint@9.21.0)(globals@16.0.0)':
dependencies:
'@eslint/compat': 1.1.1
- '@stylistic/eslint-plugin': 2.13.0(eslint@9.20.1)(typescript@5.7.3)
- '@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1)(typescript@5.7.3)
- '@typescript-eslint/parser': 8.24.0(eslint@9.20.1)(typescript@5.7.3)
- eslint: 9.20.1
- eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1)
- globals: 15.15.0
+ '@stylistic/eslint-plugin': 2.13.0(eslint@9.21.0)(typescript@5.8.2)
+ '@typescript-eslint/eslint-plugin': 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)
+ '@typescript-eslint/parser': 8.26.0(eslint@9.21.0)(typescript@5.8.2)
+ eslint: 9.21.0
+ eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)
+ globals: 16.0.0
'@misskey-dev/sharp-read-bmp@1.2.0':
dependencies:
@@ -13119,7 +13051,7 @@ snapshots:
'@rollup/plugin-replace@6.0.2(rollup@4.34.9)':
dependencies:
'@rollup/pluginutils': 5.1.4(rollup@4.34.9)
- magic-string: 0.30.11
+ magic-string: 0.30.17
optionalDependencies:
rollup: 4.34.9
@@ -13757,144 +13689,144 @@ snapshots:
'@sqltools/formatter@1.2.5': {}
- '@storybook/addon-actions@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-actions@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
'@types/uuid': 9.0.8
dequal: 2.0.3
polished: 4.2.2
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
uuid: 9.0.1
- '@storybook/addon-backgrounds@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-backgrounds@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
memoizerific: 1.11.3
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
- '@storybook/addon-controls@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-controls@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
dequal: 2.0.3
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
- '@storybook/addon-docs@8.6.3(@types/react@18.0.28)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-docs@8.6.4(@types/react@18.0.28)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@mdx-js/react': 3.0.1(@types/react@18.0.28)(react@19.0.0)
- '@storybook/blocks': 8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/csf-plugin': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/react-dom-shim': 8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/blocks': 8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/csf-plugin': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/react-dom-shim': 8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
transitivePeerDependencies:
- '@types/react'
- '@storybook/addon-essentials@8.6.3(@types/react@18.0.28)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-essentials@8.6.4(@types/react@18.0.28)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- '@storybook/addon-actions': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/addon-backgrounds': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/addon-controls': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/addon-docs': 8.6.3(@types/react@18.0.28)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/addon-highlight': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/addon-measure': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/addon-outline': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/addon-toolbars': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/addon-viewport': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ '@storybook/addon-actions': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/addon-backgrounds': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/addon-controls': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/addon-docs': 8.6.4(@types/react@18.0.28)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/addon-highlight': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/addon-measure': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/addon-outline': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/addon-toolbars': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/addon-viewport': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
transitivePeerDependencies:
- '@types/react'
- '@storybook/addon-highlight@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-highlight@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/addon-interactions@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-interactions@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
- '@storybook/instrumenter': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/test': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/instrumenter': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/test': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
polished: 4.2.2
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
- '@storybook/addon-links@8.6.3(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-links@8.6.4(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
optionalDependencies:
react: 19.0.0
- '@storybook/addon-mdx-gfm@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-mdx-gfm@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
remark-gfm: 4.0.0
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
transitivePeerDependencies:
- supports-color
- '@storybook/addon-measure@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-measure@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
tiny-invariant: 1.3.3
- '@storybook/addon-outline@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-outline@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
- '@storybook/addon-storysource@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-storysource@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- '@storybook/source-loader': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/source-loader': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
estraverse: 5.3.0
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
tiny-invariant: 1.3.3
- '@storybook/addon-toolbars@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-toolbars@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/addon-viewport@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/addon-viewport@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
memoizerific: 1.11.3
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/blocks@8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/blocks@8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/icons': 1.2.12(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
optionalDependencies:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@storybook/builder-vite@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
+ '@storybook/builder-vite@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
dependencies:
- '@storybook/csf-plugin': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/csf-plugin': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
browser-assert: 1.2.1
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
- vite: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
- '@storybook/components@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/components@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/core-events@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/core-events@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/core@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(utf-8-validate@6.0.5)':
+ '@storybook/core@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(utf-8-validate@6.0.5)':
dependencies:
- '@storybook/theming': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/theming': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
better-opn: 3.0.2
browser-assert: 1.2.1
esbuild: 0.25.0
@@ -13913,9 +13845,9 @@ snapshots:
- supports-color
- utf-8-validate
- '@storybook/csf-plugin@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/csf-plugin@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
unplugin: 1.4.0
'@storybook/global@5.0.0': {}
@@ -13925,121 +13857,121 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- '@storybook/instrumenter@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/instrumenter@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
'@vitest/utils': 2.1.1
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/manager-api@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/manager-api@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/preview-api@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/preview-api@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/react-dom-shim@8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/react-dom-shim@8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/react-vite@8.6.3(@storybook/test@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.9)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
+ '@storybook/react-vite@8.6.4(@storybook/test@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(rollup@4.34.9)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
dependencies:
- '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
+ '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
'@rollup/pluginutils': 5.1.4(rollup@4.34.9)
- '@storybook/builder-vite': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
- '@storybook/react': 8.6.3(@storybook/test@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)
+ '@storybook/builder-vite': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
+ '@storybook/react': 8.6.4(@storybook/test@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)
find-up: 5.0.0
magic-string: 0.30.17
react: 19.0.0
react-docgen: 7.0.1
react-dom: 19.0.0(react@19.0.0)
resolve: 1.22.8
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
tsconfig-paths: 4.2.0
- vite: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
optionalDependencies:
- '@storybook/test': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/test': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
transitivePeerDependencies:
- rollup
- supports-color
- typescript
- '@storybook/react@8.6.3(@storybook/test@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)':
+ '@storybook/react@8.6.4(@storybook/test@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(typescript@5.8.2)':
dependencies:
- '@storybook/components': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/components': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/global': 5.0.0
- '@storybook/manager-api': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/preview-api': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/react-dom-shim': 8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/theming': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/manager-api': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/preview-api': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/react-dom-shim': 8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/theming': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
optionalDependencies:
- '@storybook/test': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/test': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
typescript: 5.8.2
- '@storybook/source-loader@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/source-loader@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
es-toolkit: 1.27.0
estraverse: 5.3.0
prettier: 3.5.3
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/test@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/test@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
'@storybook/global': 5.0.0
- '@storybook/instrumenter': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/instrumenter': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@testing-library/dom': 10.4.0
'@testing-library/jest-dom': 6.5.0
'@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0)
'@vitest/expect': 2.0.5
'@vitest/spy': 2.0.5
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/theming@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/theming@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/types@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
+ '@storybook/types@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))':
dependencies:
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
- '@storybook/vue3-vite@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))':
+ '@storybook/vue3-vite@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))':
dependencies:
- '@storybook/builder-vite': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
- '@storybook/vue3': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vue@3.5.13(typescript@5.8.2))
+ '@storybook/builder-vite': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
+ '@storybook/vue3': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vue@3.5.13(typescript@5.8.2))
find-package-json: 1.2.0
magic-string: 0.30.17
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
typescript: 5.8.2
- vite: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
vue-component-meta: 2.0.16(typescript@5.8.2)
vue-docgen-api: 4.75.1(vue@3.5.13(typescript@5.8.2))
transitivePeerDependencies:
- vue
- '@storybook/vue3@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vue@3.5.13(typescript@5.8.2))':
+ '@storybook/vue3@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(vue@3.5.13(typescript@5.8.2))':
dependencies:
- '@storybook/components': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/components': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@storybook/global': 5.0.0
- '@storybook/manager-api': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/preview-api': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/theming': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/manager-api': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/preview-api': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/theming': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
'@vue/compiler-core': 3.5.13
- storybook: 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
+ storybook: 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)
ts-dedent: 2.2.0
type-fest: 2.19.0
vue: 3.5.13(typescript@5.8.2)
vue-component-type-helpers: 2.2.8
- '@stylistic/eslint-plugin@2.13.0(eslint@9.20.1)(typescript@5.7.3)':
+ '@stylistic/eslint-plugin@2.13.0(eslint@9.21.0)(typescript@5.8.2)':
dependencies:
- '@typescript-eslint/utils': 8.26.0(eslint@9.20.1)(typescript@5.7.3)
- eslint: 9.20.1
+ '@typescript-eslint/utils': 8.26.0(eslint@9.21.0)(typescript@5.8.2)
+ eslint: 9.21.0
eslint-visitor-keys: 4.2.0
espree: 10.3.0
estraverse: 5.3.0
@@ -14048,7 +13980,7 @@ snapshots:
- supports-color
- typescript
- '@swc/cli@0.6.0(@swc/core@1.10.16)(chokidar@3.6.0)':
+ '@swc/cli@0.6.0(@swc/core@1.10.16)(chokidar@4.0.3)':
dependencies:
'@swc/core': 1.10.16
'@swc/counter': 0.1.3
@@ -14061,7 +13993,7 @@ snapshots:
slash: 3.0.0
source-map: 0.7.4
optionalDependencies:
- chokidar: 3.6.0
+ chokidar: 4.0.3
'@swc/core-android-arm64@1.3.11':
dependencies:
@@ -14624,15 +14556,15 @@ snapshots:
'@types/node': 22.13.9
optional: true
- '@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1)(typescript@5.7.3)':
+ '@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)(typescript@5.7.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.24.0(eslint@9.20.1)(typescript@5.7.3)
+ '@typescript-eslint/parser': 8.24.0(eslint@9.21.0)(typescript@5.7.3)
'@typescript-eslint/scope-manager': 8.24.0
- '@typescript-eslint/type-utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3)
- '@typescript-eslint/utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3)
+ '@typescript-eslint/type-utils': 8.24.0(eslint@9.21.0)(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.24.0(eslint@9.21.0)(typescript@5.7.3)
'@typescript-eslint/visitor-keys': 8.24.0
- eslint: 9.20.1
+ eslint: 9.21.0
graphemer: 1.4.0
ignore: 5.3.1
natural-compare: 1.4.0
@@ -14641,15 +14573,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1)(typescript@5.8.2)':
+ '@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ '@typescript-eslint/parser': 8.26.0(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/scope-manager': 8.26.0
- '@typescript-eslint/type-utils': 8.26.0(eslint@9.20.1)(typescript@5.8.2)
- '@typescript-eslint/utils': 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ '@typescript-eslint/type-utils': 8.26.0(eslint@9.21.0)(typescript@5.8.2)
+ '@typescript-eslint/utils': 8.26.0(eslint@9.21.0)(typescript@5.8.2)
'@typescript-eslint/visitor-keys': 8.26.0
- eslint: 9.20.1
+ eslint: 9.21.0
graphemer: 1.4.0
ignore: 5.3.1
natural-compare: 1.4.0
@@ -14658,26 +14590,26 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3)':
+ '@typescript-eslint/parser@8.24.0(eslint@9.21.0)(typescript@5.7.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.24.0
'@typescript-eslint/types': 8.24.0
'@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3)
'@typescript-eslint/visitor-keys': 8.24.0
debug: 4.4.0(supports-color@8.1.1)
- eslint: 9.20.1
+ eslint: 9.21.0
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2)':
+ '@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2)':
dependencies:
'@typescript-eslint/scope-manager': 8.26.0
'@typescript-eslint/types': 8.26.0
'@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2)
'@typescript-eslint/visitor-keys': 8.26.0
debug: 4.4.0(supports-color@8.1.1)
- eslint: 9.20.1
+ eslint: 9.21.0
typescript: 5.8.2
transitivePeerDependencies:
- supports-color
@@ -14692,23 +14624,23 @@ snapshots:
'@typescript-eslint/types': 8.26.0
'@typescript-eslint/visitor-keys': 8.26.0
- '@typescript-eslint/type-utils@8.24.0(eslint@9.20.1)(typescript@5.7.3)':
+ '@typescript-eslint/type-utils@8.24.0(eslint@9.21.0)(typescript@5.7.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3)
- '@typescript-eslint/utils': 8.24.0(eslint@9.20.1)(typescript@5.7.3)
+ '@typescript-eslint/utils': 8.24.0(eslint@9.21.0)(typescript@5.7.3)
debug: 4.4.0(supports-color@8.1.1)
- eslint: 9.20.1
+ eslint: 9.21.0
ts-api-utils: 2.0.1(typescript@5.7.3)
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/type-utils@8.26.0(eslint@9.20.1)(typescript@5.8.2)':
+ '@typescript-eslint/type-utils@8.26.0(eslint@9.21.0)(typescript@5.8.2)':
dependencies:
'@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2)
- '@typescript-eslint/utils': 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ '@typescript-eslint/utils': 8.26.0(eslint@9.21.0)(typescript@5.8.2)
debug: 4.4.0(supports-color@8.1.1)
- eslint: 9.20.1
+ eslint: 9.21.0
ts-api-utils: 2.0.1(typescript@5.8.2)
typescript: 5.8.2
transitivePeerDependencies:
@@ -14732,20 +14664,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/typescript-estree@8.26.0(typescript@5.7.3)':
- dependencies:
- '@typescript-eslint/types': 8.26.0
- '@typescript-eslint/visitor-keys': 8.26.0
- debug: 4.4.0(supports-color@8.1.1)
- fast-glob: 3.3.3
- is-glob: 4.0.3
- minimatch: 9.0.4
- semver: 7.6.3
- ts-api-utils: 2.0.1(typescript@5.7.3)
- typescript: 5.7.3
- transitivePeerDependencies:
- - supports-color
-
'@typescript-eslint/typescript-estree@8.26.0(typescript@5.8.2)':
dependencies:
'@typescript-eslint/types': 8.26.0
@@ -14760,35 +14678,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.24.0(eslint@9.20.1)(typescript@5.7.3)':
+ '@typescript-eslint/utils@8.24.0(eslint@9.21.0)(typescript@5.7.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.20.1)
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.21.0)
'@typescript-eslint/scope-manager': 8.24.0
'@typescript-eslint/types': 8.24.0
'@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3)
- eslint: 9.20.1
+ eslint: 9.21.0
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.26.0(eslint@9.20.1)(typescript@5.7.3)':
+ '@typescript-eslint/utils@8.26.0(eslint@9.21.0)(typescript@5.8.2)':
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.20.1)
- '@typescript-eslint/scope-manager': 8.26.0
- '@typescript-eslint/types': 8.26.0
- '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.7.3)
- eslint: 9.20.1
- typescript: 5.7.3
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/utils@8.26.0(eslint@9.20.1)(typescript@5.8.2)':
- dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.20.1)
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.21.0)
'@typescript-eslint/scope-manager': 8.26.0
'@typescript-eslint/types': 8.26.0
'@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2)
- eslint: 9.20.1
+ eslint: 9.21.0
typescript: 5.8.2
transitivePeerDependencies:
- supports-color
@@ -14805,12 +14712,12 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
- '@vitejs/plugin-vue@5.2.1(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))':
+ '@vitejs/plugin-vue@5.2.1(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))(vue@3.5.13(typescript@5.8.2))':
dependencies:
- vite: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
vue: 3.5.13(typescript@5.8.2)
- '@vitest/coverage-v8@3.0.7(vitest@3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
+ '@vitest/coverage-v8@3.0.8(vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 1.0.2
@@ -14824,7 +14731,7 @@ snapshots:
std-env: 3.8.0
test-exclude: 7.0.1
tinyrainbow: 2.0.0
- vitest: 3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
transitivePeerDependencies:
- supports-color
@@ -14835,21 +14742,21 @@ snapshots:
chai: 5.2.0
tinyrainbow: 1.2.0
- '@vitest/expect@3.0.7':
+ '@vitest/expect@3.0.8':
dependencies:
- '@vitest/spy': 3.0.7
- '@vitest/utils': 3.0.7
+ '@vitest/spy': 3.0.8
+ '@vitest/utils': 3.0.8
chai: 5.2.0
tinyrainbow: 2.0.0
- '@vitest/mocker@3.0.7(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
+ '@vitest/mocker@3.0.8(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))':
dependencies:
- '@vitest/spy': 3.0.7
+ '@vitest/spy': 3.0.8
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
msw: 2.7.3(@types/node@22.13.9)(typescript@5.8.2)
- vite: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
'@vitest/pretty-format@2.0.5':
dependencies:
@@ -14859,18 +14766,18 @@ snapshots:
dependencies:
tinyrainbow: 1.2.0
- '@vitest/pretty-format@3.0.7':
+ '@vitest/pretty-format@3.0.8':
dependencies:
tinyrainbow: 2.0.0
- '@vitest/runner@3.0.7':
+ '@vitest/runner@3.0.8':
dependencies:
- '@vitest/utils': 3.0.7
+ '@vitest/utils': 3.0.8
pathe: 2.0.3
- '@vitest/snapshot@3.0.7':
+ '@vitest/snapshot@3.0.8':
dependencies:
- '@vitest/pretty-format': 3.0.7
+ '@vitest/pretty-format': 3.0.8
magic-string: 0.30.17
pathe: 2.0.3
@@ -14878,7 +14785,7 @@ snapshots:
dependencies:
tinyspy: 3.0.2
- '@vitest/spy@3.0.7':
+ '@vitest/spy@3.0.8':
dependencies:
tinyspy: 3.0.2
@@ -14895,9 +14802,9 @@ snapshots:
loupe: 3.1.3
tinyrainbow: 1.2.0
- '@vitest/utils@3.0.7':
+ '@vitest/utils@3.0.8':
dependencies:
- '@vitest/pretty-format': 3.0.7
+ '@vitest/pretty-format': 3.0.8
loupe: 3.1.3
tinyrainbow: 2.0.0
@@ -14947,8 +14854,8 @@ snapshots:
'@vue/compiler-ssr': 3.5.13
'@vue/shared': 3.5.13
estree-walker: 2.0.2
- magic-string: 0.30.11
- postcss: 8.5.2
+ magic-string: 0.30.17
+ postcss: 8.5.3
source-map-js: 1.2.1
'@vue/compiler-ssr@3.5.13':
@@ -15103,17 +15010,17 @@ snapshots:
mime-types: 2.1.35
negotiator: 0.6.3
- acorn-import-attributes@1.9.5(acorn@8.14.0):
+ acorn-import-attributes@1.9.5(acorn@8.14.1):
dependencies:
- acorn: 8.14.0
+ acorn: 8.14.1
- acorn-jsx@5.3.2(acorn@8.14.0):
+ acorn-jsx@5.3.2(acorn@8.14.1):
dependencies:
- acorn: 8.14.0
+ acorn: 8.14.1
acorn@7.4.1: {}
- acorn@8.14.0: {}
+ acorn@8.14.1: {}
adm-zip@0.5.10:
optional: true
@@ -15150,7 +15057,6 @@ snapshots:
aiscript-vscode@https://codeload.github.com/aiscript-dev/aiscript-vscode/tar.gz/c3cde89e79a41d93540cf8a48cd619c3f2dcb1b7:
dependencies:
- '@aiscript-dev/aiscript-languageserver': https://github.com/aiscript-dev/aiscript-languageserver/releases/download/0.1.6/aiscript-dev-aiscript-languageserver-0.1.6.tgz
vscode-languageclient: 9.0.1
ajv-draft-04@1.0.0(ajv@8.13.0):
@@ -15529,8 +15435,6 @@ snapshots:
execa: 5.1.1
find-versions: 5.1.0
- binary-extensions@2.2.0: {}
-
bl@4.1.0:
dependencies:
buffer: 5.7.1
@@ -15589,13 +15493,6 @@ snapshots:
browser-assert@1.2.1: {}
- browserslist@4.23.0:
- dependencies:
- caniuse-lite: 1.0.30001591
- electron-to-chromium: 1.4.686
- node-releases: 2.0.14
- update-browserslist-db: 1.0.13(browserslist@4.23.0)
-
browserslist@4.24.4:
dependencies:
caniuse-lite: 1.0.30001695
@@ -15701,11 +15598,6 @@ snapshots:
es-errors: 1.3.0
function-bind: 1.1.2
- call-bind@1.0.2:
- dependencies:
- function-bind: 1.1.2
- get-intrinsic: 1.2.4
-
call-bind@1.0.7:
dependencies:
es-define-property: 1.0.0
@@ -15849,23 +15741,17 @@ snapshots:
undici: 6.19.8
whatwg-mimetype: 4.0.0
- chokidar@3.6.0:
+ chokidar@4.0.3:
dependencies:
- anymatch: 3.1.3
- braces: 3.0.3
- glob-parent: 5.1.2
- is-binary-path: 2.1.0
- is-glob: 4.0.3
- normalize-path: 3.0.0
- readdirp: 3.6.0
- optionalDependencies:
- fsevents: 2.3.3
+ readdirp: 4.1.2
chownr@1.1.4:
optional: true
chownr@2.0.0: {}
+ chownr@3.0.0: {}
+
chromatic@11.27.0: {}
ci-info@3.7.1: {}
@@ -16120,9 +16006,9 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
- css-declaration-sorter@7.2.0(postcss@8.5.2):
+ css-declaration-sorter@7.2.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
css-select@5.1.0:
dependencies:
@@ -16148,49 +16034,49 @@ snapshots:
cssesc@3.0.0: {}
- cssnano-preset-default@7.0.6(postcss@8.5.2):
+ cssnano-preset-default@7.0.6(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
- css-declaration-sorter: 7.2.0(postcss@8.5.2)
- cssnano-utils: 5.0.0(postcss@8.5.2)
- postcss: 8.5.2
- postcss-calc: 10.1.0(postcss@8.5.2)
- postcss-colormin: 7.0.2(postcss@8.5.2)
- postcss-convert-values: 7.0.4(postcss@8.5.2)
- postcss-discard-comments: 7.0.3(postcss@8.5.2)
- postcss-discard-duplicates: 7.0.1(postcss@8.5.2)
- postcss-discard-empty: 7.0.0(postcss@8.5.2)
- postcss-discard-overridden: 7.0.0(postcss@8.5.2)
- postcss-merge-longhand: 7.0.4(postcss@8.5.2)
- postcss-merge-rules: 7.0.4(postcss@8.5.2)
- postcss-minify-font-values: 7.0.0(postcss@8.5.2)
- postcss-minify-gradients: 7.0.0(postcss@8.5.2)
- postcss-minify-params: 7.0.2(postcss@8.5.2)
- postcss-minify-selectors: 7.0.4(postcss@8.5.2)
- postcss-normalize-charset: 7.0.0(postcss@8.5.2)
- postcss-normalize-display-values: 7.0.0(postcss@8.5.2)
- postcss-normalize-positions: 7.0.0(postcss@8.5.2)
- postcss-normalize-repeat-style: 7.0.0(postcss@8.5.2)
- postcss-normalize-string: 7.0.0(postcss@8.5.2)
- postcss-normalize-timing-functions: 7.0.0(postcss@8.5.2)
- postcss-normalize-unicode: 7.0.2(postcss@8.5.2)
- postcss-normalize-url: 7.0.0(postcss@8.5.2)
- postcss-normalize-whitespace: 7.0.0(postcss@8.5.2)
- postcss-ordered-values: 7.0.1(postcss@8.5.2)
- postcss-reduce-initial: 7.0.2(postcss@8.5.2)
- postcss-reduce-transforms: 7.0.0(postcss@8.5.2)
- postcss-svgo: 7.0.1(postcss@8.5.2)
- postcss-unique-selectors: 7.0.3(postcss@8.5.2)
+ css-declaration-sorter: 7.2.0(postcss@8.5.3)
+ cssnano-utils: 5.0.0(postcss@8.5.3)
+ postcss: 8.5.3
+ postcss-calc: 10.1.0(postcss@8.5.3)
+ postcss-colormin: 7.0.2(postcss@8.5.3)
+ postcss-convert-values: 7.0.4(postcss@8.5.3)
+ postcss-discard-comments: 7.0.3(postcss@8.5.3)
+ postcss-discard-duplicates: 7.0.1(postcss@8.5.3)
+ postcss-discard-empty: 7.0.0(postcss@8.5.3)
+ postcss-discard-overridden: 7.0.0(postcss@8.5.3)
+ postcss-merge-longhand: 7.0.4(postcss@8.5.3)
+ postcss-merge-rules: 7.0.4(postcss@8.5.3)
+ postcss-minify-font-values: 7.0.0(postcss@8.5.3)
+ postcss-minify-gradients: 7.0.0(postcss@8.5.3)
+ postcss-minify-params: 7.0.2(postcss@8.5.3)
+ postcss-minify-selectors: 7.0.4(postcss@8.5.3)
+ postcss-normalize-charset: 7.0.0(postcss@8.5.3)
+ postcss-normalize-display-values: 7.0.0(postcss@8.5.3)
+ postcss-normalize-positions: 7.0.0(postcss@8.5.3)
+ postcss-normalize-repeat-style: 7.0.0(postcss@8.5.3)
+ postcss-normalize-string: 7.0.0(postcss@8.5.3)
+ postcss-normalize-timing-functions: 7.0.0(postcss@8.5.3)
+ postcss-normalize-unicode: 7.0.2(postcss@8.5.3)
+ postcss-normalize-url: 7.0.0(postcss@8.5.3)
+ postcss-normalize-whitespace: 7.0.0(postcss@8.5.3)
+ postcss-ordered-values: 7.0.1(postcss@8.5.3)
+ postcss-reduce-initial: 7.0.2(postcss@8.5.3)
+ postcss-reduce-transforms: 7.0.0(postcss@8.5.3)
+ postcss-svgo: 7.0.1(postcss@8.5.3)
+ postcss-unique-selectors: 7.0.3(postcss@8.5.3)
- cssnano-utils@5.0.0(postcss@8.5.2):
+ cssnano-utils@5.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
- cssnano@7.0.6(postcss@8.5.2):
+ cssnano@7.0.6(postcss@8.5.3):
dependencies:
- cssnano-preset-default: 7.0.6(postcss@8.5.2)
+ cssnano-preset-default: 7.0.6(postcss@8.5.3)
lilconfig: 3.1.3
- postcss: 8.5.2
+ postcss: 8.5.3
csso@5.0.5:
dependencies:
@@ -16203,52 +16089,6 @@ snapshots:
csstype@3.1.3: {}
- cypress@14.0.3:
- dependencies:
- '@cypress/request': 3.0.7
- '@cypress/xvfb': 1.2.4(supports-color@8.1.1)
- '@types/sinonjs__fake-timers': 8.1.1
- '@types/sizzle': 2.3.3
- arch: 2.2.0
- blob-util: 2.0.2
- bluebird: 3.7.2
- buffer: 5.7.1
- cachedir: 2.3.0
- chalk: 4.1.2
- check-more-types: 2.24.0
- ci-info: 4.1.0
- cli-cursor: 3.1.0
- cli-table3: 0.6.3
- commander: 6.2.1
- common-tags: 1.8.2
- dayjs: 1.11.10
- debug: 4.4.0(supports-color@8.1.1)
- enquirer: 2.3.6
- eventemitter2: 6.4.7
- execa: 4.1.0
- executable: 4.1.1
- extract-zip: 2.0.1(supports-color@8.1.1)
- figures: 3.2.0
- fs-extra: 9.1.0
- getos: 3.2.1
- is-installed-globally: 0.4.0
- lazy-ass: 1.6.0
- listr2: 3.14.0(enquirer@2.3.6)
- lodash: 4.17.21
- log-symbols: 4.1.0
- minimist: 1.2.8
- ospath: 1.2.2
- pretty-bytes: 5.6.0
- process: 0.11.10
- proxy-from-env: 1.0.0
- request-progress: 3.0.0
- semver: 7.6.3
- supports-color: 8.1.1
- tmp: 0.2.3
- tree-kill: 1.2.2
- untildify: 4.0.0
- yauzl: 2.10.0
-
cypress@14.1.0:
dependencies:
'@cypress/request': 3.0.7
@@ -16407,7 +16247,7 @@ snapshots:
deep-equal@2.2.0:
dependencies:
- call-bind: 1.0.2
+ call-bind: 1.0.7
es-get-iterator: 1.1.3
get-intrinsic: 1.2.4
is-arguments: 1.1.1
@@ -16423,7 +16263,7 @@ snapshots:
side-channel: 1.0.6
which-boxed-primitive: 1.0.2
which-collection: 1.0.1
- which-typed-array: 1.1.11
+ which-typed-array: 1.1.15
deep-extend@0.6.0:
optional: true
@@ -16440,7 +16280,7 @@ snapshots:
dependencies:
es-define-property: 1.0.0
es-errors: 1.3.0
- gopd: 1.0.1
+ gopd: 1.2.0
define-lazy-prop@2.0.0: {}
@@ -16587,8 +16427,6 @@ snapshots:
dependencies:
jake: 10.8.5
- electron-to-chromium@1.4.686: {}
-
electron-to-chromium@1.5.83: {}
emittery@0.13.1: {}
@@ -16859,27 +16697,27 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@8.24.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0):
dependencies:
debug: 3.2.7(supports-color@8.1.1)
optionalDependencies:
- '@typescript-eslint/parser': 8.24.0(eslint@9.20.1)(typescript@5.7.3)
- eslint: 9.20.1
+ '@typescript-eslint/parser': 8.24.0(eslint@9.21.0)(typescript@5.7.3)
+ eslint: 9.21.0
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0):
dependencies:
debug: 3.2.7(supports-color@8.1.1)
optionalDependencies:
- '@typescript-eslint/parser': 8.26.0(eslint@9.20.1)(typescript@5.8.2)
- eslint: 9.20.1
+ '@typescript-eslint/parser': 8.26.0(eslint@9.21.0)(typescript@5.8.2)
+ eslint: 9.21.0
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint@9.20.1):
+ eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.8
@@ -16888,9 +16726,9 @@ snapshots:
array.prototype.flatmap: 1.3.2
debug: 3.2.7(supports-color@8.1.1)
doctrine: 2.1.0
- eslint: 9.20.1
+ eslint: 9.21.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.24.0(eslint@9.20.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.24.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -16902,13 +16740,13 @@ snapshots:
string.prototype.trimend: 1.0.8
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.24.0(eslint@9.20.1)(typescript@5.7.3)
+ '@typescript-eslint/parser': 8.24.0(eslint@9.21.0)(typescript@5.7.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint@9.20.1):
+ eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.8
@@ -16917,9 +16755,9 @@ snapshots:
array.prototype.flatmap: 1.3.2
debug: 3.2.7(supports-color@8.1.1)
doctrine: 2.1.0
- eslint: 9.20.1
+ eslint: 9.21.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.26.0(eslint@9.20.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -16931,33 +16769,25 @@ snapshots:
string.prototype.trimend: 1.0.8
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.26.0(eslint@9.20.1)(typescript@5.8.2)
+ '@typescript-eslint/parser': 8.26.0(eslint@9.21.0)(typescript@5.8.2)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-vue@9.33.0(eslint@9.20.1):
+ eslint-plugin-vue@10.0.0(eslint@9.21.0)(vue-eslint-parser@10.1.1(eslint@9.21.0)):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.20.1)
- eslint: 9.20.1
- globals: 13.24.0
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.21.0)
+ eslint: 9.21.0
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 6.1.2
semver: 7.6.3
- vue-eslint-parser: 9.4.3(eslint@9.20.1)
+ vue-eslint-parser: 10.1.1(eslint@9.21.0)
xml-name-validator: 4.0.0
- transitivePeerDependencies:
- - supports-color
eslint-rule-docs@1.1.235: {}
- eslint-scope@7.2.2:
- dependencies:
- esrecurse: 4.3.0
- estraverse: 5.3.0
-
eslint-scope@8.2.0:
dependencies:
esrecurse: 4.3.0
@@ -16967,18 +16797,18 @@ snapshots:
eslint-visitor-keys@4.2.0: {}
- eslint@9.20.1:
+ eslint@9.21.0:
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@9.20.1)
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.21.0)
'@eslint-community/regexpp': 4.12.1
- '@eslint/config-array': 0.19.1
- '@eslint/core': 0.11.0
- '@eslint/eslintrc': 3.2.0
- '@eslint/js': 9.20.0
- '@eslint/plugin-kit': 0.2.5
+ '@eslint/config-array': 0.19.2
+ '@eslint/core': 0.12.0
+ '@eslint/eslintrc': 3.3.0
+ '@eslint/js': 9.21.0
+ '@eslint/plugin-kit': 0.2.7
'@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
- '@humanwhocodes/retry': 0.4.1
+ '@humanwhocodes/retry': 0.4.2
'@types/estree': 1.0.6
'@types/json-schema': 7.0.15
ajv: 6.12.6
@@ -17008,16 +16838,10 @@ snapshots:
espree@10.3.0:
dependencies:
- acorn: 8.14.0
- acorn-jsx: 5.3.2(acorn@8.14.0)
+ acorn: 8.14.1
+ acorn-jsx: 5.3.2(acorn@8.14.1)
eslint-visitor-keys: 4.2.0
- espree@9.6.1:
- dependencies:
- acorn: 8.14.0
- acorn-jsx: 5.3.2(acorn@8.14.0)
- eslint-visitor-keys: 3.4.3
-
esprima@4.0.1: {}
esquery@1.6.0:
@@ -17074,7 +16898,7 @@ snapshots:
execa@5.1.1:
dependencies:
- cross-spawn: 7.0.3
+ cross-spawn: 7.0.6
get-stream: 6.0.1
human-signals: 2.1.0
is-stream: 2.0.1
@@ -17438,7 +17262,7 @@ snapshots:
foreground-child@3.1.1:
dependencies:
- cross-spawn: 7.0.3
+ cross-spawn: 7.0.6
signal-exit: 4.1.0
forever-agent@0.6.1: {}
@@ -17616,7 +17440,7 @@ snapshots:
foreground-child: 3.1.1
jackspeak: 2.3.6
minimatch: 9.0.4
- minipass: 7.0.4
+ minipass: 7.1.2
path-scurry: 1.10.1
glob@10.4.5:
@@ -17660,13 +17484,9 @@ snapshots:
globals@11.12.0: {}
- globals@13.24.0:
- dependencies:
- type-fest: 0.20.2
-
globals@14.0.0: {}
- globals@15.15.0: {}
+ globals@16.0.0: {}
globalthis@1.0.3:
dependencies:
@@ -17731,7 +17551,7 @@ snapshots:
webidl-conversions: 7.0.0
whatwg-mimetype: 3.0.0
- happy-dom@17.2.2:
+ happy-dom@17.3.0:
dependencies:
webidl-conversions: 7.0.0
whatwg-mimetype: 3.0.0
@@ -17938,7 +17758,7 @@ snapshots:
ignore-by-default@1.0.1: {}
- ignore-walk@6.0.5:
+ ignore-walk@7.0.0:
dependencies:
minimatch: 9.0.4
@@ -17953,8 +17773,8 @@ snapshots:
import-in-the-middle@1.11.2:
dependencies:
- acorn: 8.14.0
- acorn-import-attributes: 1.9.5(acorn@8.14.0)
+ acorn: 8.14.1
+ acorn-import-attributes: 1.9.5(acorn@8.14.1)
cjs-module-lexer: 1.2.2
module-details-from-path: 1.0.3
@@ -18044,9 +17864,9 @@ snapshots:
is-array-buffer@3.0.2:
dependencies:
- call-bind: 1.0.2
+ call-bind: 1.0.7
get-intrinsic: 1.2.4
- is-typed-array: 1.1.10
+ is-typed-array: 1.1.13
is-array-buffer@3.0.4:
dependencies:
@@ -18061,10 +17881,6 @@ snapshots:
dependencies:
has-bigints: 1.0.2
- is-binary-path@2.1.0:
- dependencies:
- binary-extensions: 2.2.0
-
is-boolean-object@1.1.2:
dependencies:
call-bind: 1.0.7
@@ -18142,14 +17958,14 @@ snapshots:
is-regex@1.1.4:
dependencies:
- call-bind: 1.0.2
+ call-bind: 1.0.7
has-tostringtag: 1.0.2
is-set@2.0.2: {}
is-shared-array-buffer@1.0.2:
dependencies:
- call-bind: 1.0.2
+ call-bind: 1.0.7
is-shared-array-buffer@1.0.3:
dependencies:
@@ -18175,10 +17991,10 @@ snapshots:
is-typed-array@1.1.10:
dependencies:
- available-typed-arrays: 1.0.5
- call-bind: 1.0.2
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.7
for-each: 0.3.3
- gopd: 1.0.1
+ gopd: 1.2.0
has-tostringtag: 1.0.2
is-typed-array@1.1.13:
@@ -18968,10 +18784,6 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
- magic-string@0.30.11:
- dependencies:
- '@jridgewell/sourcemap-codec': 1.5.0
-
magic-string@0.30.17:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
@@ -19467,8 +19279,6 @@ snapshots:
minipass@5.0.0: {}
- minipass@7.0.4: {}
-
minipass@7.1.2: {}
minizlib@2.1.2:
@@ -19476,6 +19286,11 @@ snapshots:
minipass: 3.3.6
yallist: 4.0.0
+ minizlib@3.0.1:
+ dependencies:
+ minipass: 7.1.2
+ rimraf: 5.0.10
+
mkdirp-classic@0.5.3:
optional: true
@@ -19487,6 +19302,8 @@ snapshots:
mkdirp@2.1.6: {}
+ mkdirp@3.0.1: {}
+
mnemonist@0.39.8:
dependencies:
obliterator: 2.0.4
@@ -19667,15 +19484,13 @@ snapshots:
node-int64@0.4.0: {}
- node-releases@2.0.14: {}
-
node-releases@2.0.19: {}
nodemailer@6.10.0: {}
nodemon@3.1.9:
dependencies:
- chokidar: 3.6.0
+ chokidar: 4.0.3
debug: 4.3.7(supports-color@5.5.0)
ignore-by-default: 1.0.1
minimatch: 3.1.2
@@ -19780,7 +19595,7 @@ snapshots:
object.assign@4.1.4:
dependencies:
- call-bind: 1.0.2
+ call-bind: 1.0.7
define-properties: 1.2.0
has-symbols: 1.0.3
object-keys: 1.1.1
@@ -20111,148 +19926,150 @@ snapshots:
pngjs@5.0.0: {}
+ pnpm@10.6.1: {}
+
polished@4.2.2:
dependencies:
'@babel/runtime': 7.23.4
possible-typed-array-names@1.0.0: {}
- postcss-calc@10.1.0(postcss@8.5.2):
+ postcss-calc@10.1.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-selector-parser: 7.0.0
postcss-value-parser: 4.2.0
- postcss-colormin@7.0.2(postcss@8.5.2):
+ postcss-colormin@7.0.2(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
caniuse-api: 3.0.0
colord: 2.9.3
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-convert-values@7.0.4(postcss@8.5.2):
+ postcss-convert-values@7.0.4(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-discard-comments@7.0.3(postcss@8.5.2):
+ postcss-discard-comments@7.0.3(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-selector-parser: 6.1.2
- postcss-discard-duplicates@7.0.1(postcss@8.5.2):
+ postcss-discard-duplicates@7.0.1(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
- postcss-discard-empty@7.0.0(postcss@8.5.2):
+ postcss-discard-empty@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
- postcss-discard-overridden@7.0.0(postcss@8.5.2):
+ postcss-discard-overridden@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
- postcss-merge-longhand@7.0.4(postcss@8.5.2):
+ postcss-merge-longhand@7.0.4(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- stylehacks: 7.0.4(postcss@8.5.2)
+ stylehacks: 7.0.4(postcss@8.5.3)
- postcss-merge-rules@7.0.4(postcss@8.5.2):
+ postcss-merge-rules@7.0.4(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
caniuse-api: 3.0.0
- cssnano-utils: 5.0.0(postcss@8.5.2)
- postcss: 8.5.2
+ cssnano-utils: 5.0.0(postcss@8.5.3)
+ postcss: 8.5.3
postcss-selector-parser: 6.1.2
- postcss-minify-font-values@7.0.0(postcss@8.5.2):
+ postcss-minify-font-values@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-minify-gradients@7.0.0(postcss@8.5.2):
+ postcss-minify-gradients@7.0.0(postcss@8.5.3):
dependencies:
colord: 2.9.3
- cssnano-utils: 5.0.0(postcss@8.5.2)
- postcss: 8.5.2
+ cssnano-utils: 5.0.0(postcss@8.5.3)
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-minify-params@7.0.2(postcss@8.5.2):
+ postcss-minify-params@7.0.2(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
- cssnano-utils: 5.0.0(postcss@8.5.2)
- postcss: 8.5.2
+ cssnano-utils: 5.0.0(postcss@8.5.3)
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-minify-selectors@7.0.4(postcss@8.5.2):
+ postcss-minify-selectors@7.0.4(postcss@8.5.3):
dependencies:
cssesc: 3.0.0
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-selector-parser: 6.1.2
- postcss-normalize-charset@7.0.0(postcss@8.5.2):
+ postcss-normalize-charset@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
- postcss-normalize-display-values@7.0.0(postcss@8.5.2):
+ postcss-normalize-display-values@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-positions@7.0.0(postcss@8.5.2):
+ postcss-normalize-positions@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-repeat-style@7.0.0(postcss@8.5.2):
+ postcss-normalize-repeat-style@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-string@7.0.0(postcss@8.5.2):
+ postcss-normalize-string@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-timing-functions@7.0.0(postcss@8.5.2):
+ postcss-normalize-timing-functions@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-unicode@7.0.2(postcss@8.5.2):
+ postcss-normalize-unicode@7.0.2(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-url@7.0.0(postcss@8.5.2):
+ postcss-normalize-url@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-whitespace@7.0.0(postcss@8.5.2):
+ postcss-normalize-whitespace@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-ordered-values@7.0.1(postcss@8.5.2):
+ postcss-ordered-values@7.0.1(postcss@8.5.3):
dependencies:
- cssnano-utils: 5.0.0(postcss@8.5.2)
- postcss: 8.5.2
+ cssnano-utils: 5.0.0(postcss@8.5.3)
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-reduce-initial@7.0.2(postcss@8.5.2):
+ postcss-reduce-initial@7.0.2(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
caniuse-api: 3.0.0
- postcss: 8.5.2
+ postcss: 8.5.3
- postcss-reduce-transforms@7.0.0(postcss@8.5.2):
+ postcss-reduce-transforms@7.0.0(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-selector-parser@6.1.2:
@@ -20265,25 +20082,19 @@ snapshots:
cssesc: 3.0.0
util-deprecate: 1.0.2
- postcss-svgo@7.0.1(postcss@8.5.2):
+ postcss-svgo@7.0.1(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-value-parser: 4.2.0
svgo: 3.3.2
- postcss-unique-selectors@7.0.3(postcss@8.5.2):
+ postcss-unique-selectors@7.0.3(postcss@8.5.3):
dependencies:
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-selector-parser: 6.1.2
postcss-value-parser@4.2.0: {}
- postcss@8.5.2:
- dependencies:
- nanoid: 3.3.8
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
postcss@8.5.3:
dependencies:
nanoid: 3.3.8
@@ -20573,7 +20384,7 @@ snapshots:
dependencies:
setimmediate: 1.0.5
- re2@1.21.4:
+ re2@1.21.4(patch_hash=018babd22b7ce951bcd10d6246f1e541a7ac7ba212f7fa8985e774ece67d08e1):
dependencies:
install-artifact-from-github: 1.3.5
nan: 2.20.0
@@ -20651,9 +20462,7 @@ snapshots:
dependencies:
minimatch: 5.1.2
- readdirp@3.6.0:
- dependencies:
- picomatch: 2.3.1
+ readdirp@4.1.2: {}
real-require@0.2.0: {}
@@ -20702,7 +20511,7 @@ snapshots:
regexp.prototype.flags@1.5.0:
dependencies:
- call-bind: 1.0.2
+ call-bind: 1.0.7
define-properties: 1.2.0
functions-have-names: 1.2.3
@@ -20812,6 +20621,10 @@ snapshots:
glob: 7.2.3
optional: true
+ rimraf@5.0.10:
+ dependencies:
+ glob: 10.4.5
+
rollup@4.34.9:
dependencies:
'@types/estree': 1.0.6
@@ -20897,11 +20710,11 @@ snapshots:
htmlparser2: 8.0.1
is-plain-object: 5.0.0
parse-srcset: 1.0.2
- postcss: 8.5.2
+ postcss: 8.5.3
sass@1.85.1:
dependencies:
- chokidar: 3.6.0
+ chokidar: 4.0.3
immutable: 5.0.3
source-map-js: 1.2.1
optionalDependencies:
@@ -20939,10 +20752,6 @@ snapshots:
dependencies:
lru-cache: 6.0.0
- semver@7.6.0:
- dependencies:
- lru-cache: 6.0.0
-
semver@7.6.3: {}
send@0.19.0:
@@ -20982,7 +20791,7 @@ snapshots:
es-errors: 1.3.0
function-bind: 1.1.2
get-intrinsic: 1.2.4
- gopd: 1.0.1
+ gopd: 1.2.0
has-property-descriptors: 1.0.2
set-function-name@2.0.2:
@@ -21296,22 +21105,22 @@ snapshots:
dependencies:
internal-slot: 1.0.5
- storybook-addon-misskey-theme@https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/components@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/core-events@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/manager-api@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/preview-api@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/theming@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/types@8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
+ storybook-addon-misskey-theme@https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/components@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/core-events@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/manager-api@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/preview-api@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/theming@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(@storybook/types@8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5)))(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
- '@storybook/blocks': 8.6.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/components': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/core-events': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/manager-api': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/preview-api': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/theming': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
- '@storybook/types': 8.6.3(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/blocks': 8.6.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/components': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/core-events': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/manager-api': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/preview-api': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/theming': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
+ '@storybook/types': 8.6.4(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))
optionalDependencies:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5):
+ storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5):
dependencies:
- '@storybook/core': 8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(storybook@8.6.3(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(utf-8-validate@6.0.5)
+ '@storybook/core': 8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(storybook@8.6.4(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.5))(utf-8-validate@6.0.5)
optionalDependencies:
prettier: 3.5.3
transitivePeerDependencies:
@@ -21461,10 +21270,10 @@ snapshots:
'@tokenizer/token': 0.3.0
peek-readable: 5.3.1
- stylehacks@7.0.4(postcss@8.5.2):
+ stylehacks@7.0.4(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
- postcss: 8.5.2
+ postcss: 8.5.3
postcss-selector-parser: 6.1.2
supports-color@5.5.0:
@@ -21540,6 +21349,15 @@ snapshots:
mkdirp: 1.0.4
yallist: 4.0.0
+ tar@7.4.3:
+ dependencies:
+ '@isaacs/fs-minipass': 4.0.1
+ chownr: 3.0.0
+ minipass: 7.1.2
+ minizlib: 3.0.1
+ mkdirp: 3.0.1
+ yallist: 5.0.0
+
taskkill@5.0.0:
dependencies:
execa: 6.1.0
@@ -21547,7 +21365,7 @@ snapshots:
terser@5.39.0:
dependencies:
'@jridgewell/source-map': 0.3.6
- acorn: 8.14.0
+ acorn: 8.14.1
commander: 2.20.3
source-map-support: 0.5.21
@@ -21675,7 +21493,7 @@ snapshots:
tsc-alias@1.8.10:
dependencies:
- chokidar: 3.6.0
+ chokidar: 4.0.3
commander: 9.5.0
globby: 11.1.0
mylas: 2.1.13
@@ -21684,7 +21502,7 @@ snapshots:
tsc-alias@1.8.11:
dependencies:
- chokidar: 3.6.0
+ chokidar: 4.0.3
commander: 9.5.0
globby: 11.1.0
mylas: 2.1.13
@@ -21739,8 +21557,6 @@ snapshots:
type-fest@0.18.1: {}
- type-fest@0.20.2: {}
-
type-fest@0.21.3: {}
type-fest@0.6.0: {}
@@ -21760,7 +21576,7 @@ snapshots:
dependencies:
call-bind: 1.0.7
get-intrinsic: 1.2.4
- is-typed-array: 1.1.10
+ is-typed-array: 1.1.13
typed-array-buffer@1.0.2:
dependencies:
@@ -21773,30 +21589,30 @@ snapshots:
call-bind: 1.0.7
for-each: 0.3.3
has-proto: 1.0.1
- is-typed-array: 1.1.10
+ is-typed-array: 1.1.13
typed-array-byte-length@1.0.1:
dependencies:
call-bind: 1.0.7
for-each: 0.3.3
- gopd: 1.0.1
+ gopd: 1.2.0
has-proto: 1.0.3
is-typed-array: 1.1.13
typed-array-byte-offset@1.0.0:
dependencies:
- available-typed-arrays: 1.0.5
+ available-typed-arrays: 1.0.7
call-bind: 1.0.7
for-each: 0.3.3
has-proto: 1.0.1
- is-typed-array: 1.1.10
+ is-typed-array: 1.1.13
typed-array-byte-offset@1.0.2:
dependencies:
available-typed-arrays: 1.0.7
call-bind: 1.0.7
for-each: 0.3.3
- gopd: 1.0.1
+ gopd: 1.2.0
has-proto: 1.0.3
is-typed-array: 1.1.13
@@ -21804,13 +21620,13 @@ snapshots:
dependencies:
call-bind: 1.0.7
for-each: 0.3.3
- is-typed-array: 1.1.10
+ is-typed-array: 1.1.13
typed-array-length@1.0.6:
dependencies:
call-bind: 1.0.7
for-each: 0.3.3
- gopd: 1.0.1
+ gopd: 1.2.0
has-proto: 1.0.3
is-typed-array: 1.1.13
possible-typed-array-names: 1.0.0
@@ -21931,19 +21747,13 @@ snapshots:
unplugin@1.4.0:
dependencies:
- acorn: 8.14.0
- chokidar: 3.6.0
+ acorn: 8.14.1
+ chokidar: 4.0.3
webpack-sources: 3.2.3
webpack-virtual-modules: 0.5.0
untildify@4.0.0: {}
- update-browserslist-db@1.0.13(browserslist@4.23.0):
- dependencies:
- browserslist: 4.23.0
- escalade: 3.1.1
- picocolors: 1.1.1
-
update-browserslist-db@1.1.2(browserslist@4.24.4):
dependencies:
browserslist: 4.24.4
@@ -22022,13 +21832,13 @@ snapshots:
unist-util-stringify-position: 4.0.0
vfile-message: 4.0.2
- vite-node@3.0.7(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3):
+ vite-node@3.0.8(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3):
dependencies:
cac: 6.7.14
debug: 4.4.0(supports-color@8.1.1)
es-module-lexer: 1.6.0
pathe: 2.0.3
- vite: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -22045,7 +21855,7 @@ snapshots:
vite-plugin-turbosnap@1.0.3: {}
- vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3):
+ vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3):
dependencies:
esbuild: 0.25.0
postcss: 8.5.3
@@ -22057,19 +21867,19 @@ snapshots:
terser: 5.39.0
tsx: 4.19.3
- vitest-fetch-mock@0.4.5(vitest@3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)):
+ vitest-fetch-mock@0.4.5(vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)):
dependencies:
- vitest: 3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
- vitest@3.0.7(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.2.2)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3):
+ vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.9)(happy-dom@17.3.0)(jsdom@26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3):
dependencies:
- '@vitest/expect': 3.0.7
- '@vitest/mocker': 3.0.7(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(vite@6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
- '@vitest/pretty-format': 3.0.7
- '@vitest/runner': 3.0.7
- '@vitest/snapshot': 3.0.7
- '@vitest/spy': 3.0.7
- '@vitest/utils': 3.0.7
+ '@vitest/expect': 3.0.8
+ '@vitest/mocker': 3.0.8(msw@2.7.3(@types/node@22.13.9)(typescript@5.8.2))(vite@6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3))
+ '@vitest/pretty-format': 3.0.8
+ '@vitest/runner': 3.0.8
+ '@vitest/snapshot': 3.0.8
+ '@vitest/spy': 3.0.8
+ '@vitest/utils': 3.0.8
chai: 5.2.0
debug: 4.4.0(supports-color@8.1.1)
expect-type: 1.1.0
@@ -22080,13 +21890,13 @@ snapshots:
tinyexec: 0.3.2
tinypool: 1.0.2
tinyrainbow: 2.0.0
- vite: 6.2.0(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
- vite-node: 3.0.7(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite: 6.2.1(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
+ vite-node: 3.0.8(@types/node@22.13.9)(sass@1.85.1)(terser@5.39.0)(tsx@4.19.3)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.12
'@types/node': 22.13.9
- happy-dom: 17.2.2
+ happy-dom: 17.3.0
jsdom: 26.0.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5)
transitivePeerDependencies:
- jiti
@@ -22117,14 +21927,8 @@ snapshots:
vscode-jsonrpc: 8.2.0
vscode-languageserver-types: 3.17.5
- vscode-languageserver-textdocument@1.0.11: {}
-
vscode-languageserver-types@3.17.5: {}
- vscode-languageserver@9.0.1:
- dependencies:
- vscode-languageserver-protocol: 3.17.5
-
vscode-uri@3.0.8: {}
vue-component-meta@2.0.16(typescript@5.8.2):
@@ -22161,16 +21965,16 @@ snapshots:
vue: 3.5.13(typescript@5.8.2)
vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.13(typescript@5.8.2))
- vue-eslint-parser@9.4.3(eslint@9.20.1):
+ vue-eslint-parser@10.1.1(eslint@9.21.0):
dependencies:
- debug: 4.3.5
- eslint: 9.20.1
- eslint-scope: 7.2.2
- eslint-visitor-keys: 3.4.3
- espree: 9.6.1
+ debug: 4.4.0(supports-color@8.1.1)
+ eslint: 9.21.0
+ eslint-scope: 8.2.0
+ eslint-visitor-keys: 4.2.0
+ espree: 10.3.0
esquery: 1.6.0
lodash: 4.17.21
- semver: 7.6.0
+ semver: 7.6.3
transitivePeerDependencies:
- supports-color
@@ -22290,10 +22094,10 @@ snapshots:
which-typed-array@1.1.11:
dependencies:
- available-typed-arrays: 1.0.5
- call-bind: 1.0.2
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.7
for-each: 0.3.3
- gopd: 1.0.1
+ gopd: 1.2.0
has-tostringtag: 1.0.2
which-typed-array@1.1.15:
@@ -22301,7 +22105,7 @@ snapshots:
available-typed-arrays: 1.0.7
call-bind: 1.0.7
for-each: 0.3.3
- gopd: 1.0.1
+ gopd: 1.2.0
has-tostringtag: 1.0.2
which@1.3.1:
@@ -22394,6 +22198,8 @@ snapshots:
yallist@4.0.0: {}
+ yallist@5.0.0: {}
+
yargs-parser@18.1.3:
dependencies:
camelcase: 5.3.1
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index d222614eda..68e4f0adc1 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,10 +1,29 @@
packages:
- - 'packages/backend'
- - 'packages/frontend-shared'
- - 'packages/frontend'
- - 'packages/frontend-embed'
- - 'packages/sw'
- - 'packages/misskey-js'
- - 'packages/misskey-js/generator'
- - 'packages/misskey-reversi'
- - 'packages/misskey-bubble-game'
+ - packages/backend
+ - packages/frontend-shared
+ - packages/frontend
+ - packages/frontend-embed
+ - packages/sw
+ - packages/misskey-js
+ - packages/misskey-js/generator
+ - packages/misskey-reversi
+ - packages/misskey-bubble-game
+onlyBuiltDependencies:
+ - '@nestjs/core'
+ - '@parcel/watcher'
+ - '@sentry/profiling-node'
+ - '@swc/core'
+ - '@tensorflow/tfjs-node'
+ - bufferutil
+ - canvas
+ - core-js
+ - cypress
+ - esbuild
+ - msgpackr-extract
+ - msw
+ - nice-napi
+ - re2
+ - sharp
+ - utf-8-validate
+ - v-code-diff
+ - vue-demi
diff --git a/scripts/changelog-checker/package-lock.json b/scripts/changelog-checker/package-lock.json
index d017475fc8..2a1524f768 100644
--- a/scripts/changelog-checker/package-lock.json
+++ b/scripts/changelog-checker/package-lock.json
@@ -9,16 +9,16 @@
"version": "1.0.0",
"devDependencies": {
"@types/mdast": "4.0.4",
- "@types/node": "22.13.7",
- "@vitest/coverage-v8": "3.0.7",
+ "@types/node": "22.13.9",
+ "@vitest/coverage-v8": "3.0.8",
"mdast-util-to-string": "4.0.0",
"remark": "15.0.1",
"remark-parse": "11.0.0",
"typescript": "5.8.2",
"unified": "11.0.5",
- "vite": "6.2.0",
- "vite-node": "3.0.7",
- "vitest": "3.0.7"
+ "vite": "6.2.1",
+ "vite-node": "3.0.8",
+ "vitest": "3.0.8"
}
},
"node_modules/@ampproject/remapping": {
@@ -909,9 +909,9 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "22.13.7",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.7.tgz",
- "integrity": "sha512-oU2q+BsQldB9lYxHNp/5aZO+/Bs0Usa74Abo9mAKulz4ahQyXRHK6UVKYIN8KSC8HXwhWSi7b49JnX+txuac0w==",
+ "version": "22.13.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz",
+ "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -925,9 +925,9 @@
"dev": true
},
"node_modules/@vitest/coverage-v8": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.7.tgz",
- "integrity": "sha512-Av8WgBJLTrfLOer0uy3CxjlVuWK4CzcLBndW1Nm2vI+3hZ2ozHututkfc7Blu1u6waeQ7J8gzPK/AsBRnWA5mQ==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.8.tgz",
+ "integrity": "sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -948,8 +948,8 @@
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "@vitest/browser": "3.0.7",
- "vitest": "3.0.7"
+ "@vitest/browser": "3.0.8",
+ "vitest": "3.0.8"
},
"peerDependenciesMeta": {
"@vitest/browser": {
@@ -958,14 +958,14 @@
}
},
"node_modules/@vitest/expect": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.7.tgz",
- "integrity": "sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.8.tgz",
+ "integrity": "sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "3.0.7",
- "@vitest/utils": "3.0.7",
+ "@vitest/spy": "3.0.8",
+ "@vitest/utils": "3.0.8",
"chai": "^5.2.0",
"tinyrainbow": "^2.0.0"
},
@@ -974,13 +974,13 @@
}
},
"node_modules/@vitest/mocker": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.7.tgz",
- "integrity": "sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.8.tgz",
+ "integrity": "sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "3.0.7",
+ "@vitest/spy": "3.0.8",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.17"
},
@@ -1001,9 +1001,9 @@
}
},
"node_modules/@vitest/pretty-format": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.7.tgz",
- "integrity": "sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.8.tgz",
+ "integrity": "sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1014,13 +1014,13 @@
}
},
"node_modules/@vitest/runner": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.7.tgz",
- "integrity": "sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.8.tgz",
+ "integrity": "sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "3.0.7",
+ "@vitest/utils": "3.0.8",
"pathe": "^2.0.3"
},
"funding": {
@@ -1028,13 +1028,13 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.7.tgz",
- "integrity": "sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.8.tgz",
+ "integrity": "sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "3.0.7",
+ "@vitest/pretty-format": "3.0.8",
"magic-string": "^0.30.17",
"pathe": "^2.0.3"
},
@@ -1043,9 +1043,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.7.tgz",
- "integrity": "sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.8.tgz",
+ "integrity": "sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1056,13 +1056,13 @@
}
},
"node_modules/@vitest/utils": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.7.tgz",
- "integrity": "sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.8.tgz",
+ "integrity": "sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "3.0.7",
+ "@vitest/pretty-format": "3.0.8",
"loupe": "^3.1.3",
"tinyrainbow": "^2.0.0"
},
@@ -2724,9 +2724,9 @@
}
},
"node_modules/vite": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz",
- "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.1.tgz",
+ "integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2796,9 +2796,9 @@
}
},
"node_modules/vite-node": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.7.tgz",
- "integrity": "sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.8.tgz",
+ "integrity": "sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2819,19 +2819,19 @@
}
},
"node_modules/vitest": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.7.tgz",
- "integrity": "sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.8.tgz",
+ "integrity": "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "3.0.7",
- "@vitest/mocker": "3.0.7",
- "@vitest/pretty-format": "^3.0.7",
- "@vitest/runner": "3.0.7",
- "@vitest/snapshot": "3.0.7",
- "@vitest/spy": "3.0.7",
- "@vitest/utils": "3.0.7",
+ "@vitest/expect": "3.0.8",
+ "@vitest/mocker": "3.0.8",
+ "@vitest/pretty-format": "^3.0.8",
+ "@vitest/runner": "3.0.8",
+ "@vitest/snapshot": "3.0.8",
+ "@vitest/spy": "3.0.8",
+ "@vitest/utils": "3.0.8",
"chai": "^5.2.0",
"debug": "^4.4.0",
"expect-type": "^1.1.0",
@@ -2843,7 +2843,7 @@
"tinypool": "^1.0.2",
"tinyrainbow": "^2.0.0",
"vite": "^5.0.0 || ^6.0.0",
- "vite-node": "3.0.7",
+ "vite-node": "3.0.8",
"why-is-node-running": "^2.3.0"
},
"bin": {
@@ -2859,8 +2859,8 @@
"@edge-runtime/vm": "*",
"@types/debug": "^4.1.12",
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "@vitest/browser": "3.0.7",
- "@vitest/ui": "3.0.7",
+ "@vitest/browser": "3.0.8",
+ "@vitest/ui": "3.0.8",
"happy-dom": "*",
"jsdom": "*"
},
diff --git a/scripts/changelog-checker/package.json b/scripts/changelog-checker/package.json
index a98935ae69..87d48974fb 100644
--- a/scripts/changelog-checker/package.json
+++ b/scripts/changelog-checker/package.json
@@ -10,15 +10,15 @@
},
"devDependencies": {
"@types/mdast": "4.0.4",
- "@types/node": "22.13.7",
- "@vitest/coverage-v8": "3.0.7",
+ "@types/node": "22.13.9",
+ "@vitest/coverage-v8": "3.0.8",
"mdast-util-to-string": "4.0.0",
"remark": "15.0.1",
"remark-parse": "11.0.0",
"typescript": "5.8.2",
"unified": "11.0.5",
- "vite": "6.2.0",
- "vite-node": "3.0.7",
- "vitest": "3.0.7"
+ "vite": "6.2.1",
+ "vite-node": "3.0.8",
+ "vitest": "3.0.8"
}
}
diff --git a/scripts/dependency-patches/re2.patch b/scripts/dependency-patches/re2.patch
new file mode 100644
index 0000000000..3e7ec9f56f
--- /dev/null
+++ b/scripts/dependency-patches/re2.patch
@@ -0,0 +1,13 @@
+diff --git a/package.json b/package.json
+index a56ab59ef647288ee6028abd2b1780eaa92ebc9d..ec2c43e63f3134b6d54d616b2ef715447f873bbe 100644
+--- a/package.json
++++ b/package.json
+@@ -28,7 +28,7 @@
+ "test": "node tests/tests.js",
+ "ts-test": "tsc",
+ "save-to-github": "save-to-github-cache --artifact build/Release/re2.node",
+- "install": "install-from-cache --artifact build/Release/re2.node --host-var RE2_DOWNLOAD_MIRROR --skip-path-var RE2_DOWNLOAD_SKIP_PATH --skip-ver-var RE2_DOWNLOAD_SKIP_VER || node-gyp -j max rebuild",
++ "install": "npm_package_github=https://github.com/uhop/node-re2 npm_package_scripts_verify_build=true install-from-cache --artifact build/Release/re2.node --host-var RE2_DOWNLOAD_MIRROR --skip-path-var RE2_DOWNLOAD_SKIP_PATH --skip-ver-var RE2_DOWNLOAD_SKIP_VER || node-gyp -j max rebuild",
+ "verify-build": "node scripts/verify-build.js",
+ "build:dev": "node-gyp -j max build --debug",
+ "build": "node-gyp -j max build",
diff --git a/scripts/tarball.mjs b/scripts/tarball.mjs
index e9d8900aca..fddbe3b04a 100644
--- a/scripts/tarball.mjs
+++ b/scripts/tarball.mjs
@@ -9,7 +9,7 @@ import { resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import glob from 'fast-glob';
import walk from 'ignore-walk';
-import Pack from 'tar/lib/pack.js';
+import { Pack } from 'tar/pack';
import meta from '../package.json' with { type: "json" };
const cwd = fileURLToPath(new URL('..', import.meta.url));