mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-25 17:10:43 +00:00
commit
41048638a2
80 changed files with 2839 additions and 2583 deletions
4
.github/workflows/api-misskey-js.yml
vendored
4
.github/workflows/api-misskey-js.yml
vendored
|
|
@ -19,10 +19,10 @@ jobs:
|
|||
uses: actions/checkout@v6.0.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
2
.github/workflows/changelog-check.yml
vendored
2
.github/workflows/changelog-check.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
- name: Checkout head
|
||||
uses: actions/checkout@v6.0.2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
|
||||
- name: setup node
|
||||
id: setup-node
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: pnpm
|
||||
|
|
|
|||
4
.github/workflows/get-api-diff.yml
vendored
4
.github/workflows/get-api-diff.yml
vendored
|
|
@ -30,9 +30,9 @@ jobs:
|
|||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/get-backend-memory.yml
vendored
4
.github/workflows/get-backend-memory.yml
vendored
|
|
@ -45,9 +45,9 @@ jobs:
|
|||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
12
.github/workflows/lint.yml
vendored
12
.github/workflows/lint.yml
vendored
|
|
@ -41,8 +41,8 @@ jobs:
|
|||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
@ -74,8 +74,8 @@ jobs:
|
|||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
@ -105,8 +105,8 @@ jobs:
|
|||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/locale.yml
vendored
4
.github/workflows/locale.yml
vendored
|
|
@ -21,8 +21,8 @@ jobs:
|
|||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
cache: "pnpm"
|
||||
|
|
|
|||
4
.github/workflows/on-release-created.yml
vendored
4
.github/workflows/on-release-created.yml
vendored
|
|
@ -20,9 +20,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/storybook.yml
vendored
4
.github/workflows/storybook.yml
vendored
|
|
@ -37,9 +37,9 @@ jobs:
|
|||
if: github.event_name == 'pull_request_target'
|
||||
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
14
.github/workflows/test-backend.yml
vendored
14
.github/workflows/test-backend.yml
vendored
|
|
@ -49,7 +49,7 @@ jobs:
|
|||
ports:
|
||||
- 56312:6379
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.36.0
|
||||
image: getmeili/meilisearch:v1.38.2
|
||||
ports:
|
||||
- 57712:7700
|
||||
env:
|
||||
|
|
@ -61,7 +61,7 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
|
@ -93,7 +93,7 @@ jobs:
|
|||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
|
@ -140,9 +140,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
|
@ -184,12 +184,12 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/test-federation.yml
vendored
4
.github/workflows/test-federation.yml
vendored
|
|
@ -36,7 +36,7 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
|
@ -68,7 +68,7 @@ jobs:
|
|||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
8
.github/workflows/test-frontend.yml
vendored
8
.github/workflows/test-frontend.yml
vendored
|
|
@ -32,9 +32,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
@ -86,9 +86,9 @@ jobs:
|
|||
#- uses: browser-actions/setup-firefox@latest
|
||||
# if: ${{ matrix.browser == 'firefox' }}
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/test-misskey-js.yml
vendored
4
.github/workflows/test-misskey-js.yml
vendored
|
|
@ -25,10 +25,10 @@ jobs:
|
|||
uses: actions/checkout@v6.0.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/test-production.yml
vendored
4
.github/workflows/test-production.yml
vendored
|
|
@ -20,9 +20,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
4
.github/workflows/validate-api-json.yml
vendored
4
.github/workflows/validate-api-json.yml
vendored
|
|
@ -21,9 +21,9 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.2.0
|
||||
uses: actions/setup-node@v6.3.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -1,3 +1,21 @@
|
|||
## 2026.3.2
|
||||
|
||||
### General
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: アプリ内ウィンドウの初期サイズを画面サイズに応じて自動で調整するように
|
||||
- Fix: 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正
|
||||
- Fix: ウィンドウのタイトルをクリックしても最前面に出ないことがある問題を修正
|
||||
|
||||
### Server
|
||||
- Fix: 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなどを行った場合のイベントが流れない問題を修正
|
||||
- Fix: 署名付きGETリクエストにおいてAcceptヘッダを署名の対象から除外(Acceptヘッダを正規化するCDNやリバースプロキシを使用している際に挙動がおかしくなる問題を修正)
|
||||
- Fix: WebSocket接続におけるノートの非表示ロジックを修正
|
||||
- Fix: チャンネルミュートを有効にしている際に、一部のタイムラインやノート一覧が空になる問題を修正
|
||||
- Fix: 初期読込時に必要なフロントエンドのアセットがすべて読み込まれていない問題を修正
|
||||
|
||||
|
||||
## 2026.3.1
|
||||
|
||||
### General
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# syntax = docker/dockerfile:1.20
|
||||
# syntax = docker/dockerfile:1.21
|
||||
|
||||
ARG NODE_VERSION=22.21.1-bookworm
|
||||
ARG NODE_VERSION=22.22.0-bookworm
|
||||
|
||||
# build assets & compile TypeScript
|
||||
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ noJobs: "No hi ha feines"
|
|||
federating: "Federant"
|
||||
blocked: "Bloquejat"
|
||||
suspended: "Anul·lar subscripció "
|
||||
all: "tot"
|
||||
all: "Tot"
|
||||
subscribing: "Subscrit a"
|
||||
publishing: "S'està publicant"
|
||||
notResponding: "Sense resposta"
|
||||
|
|
@ -3401,11 +3401,9 @@ _imageEffector:
|
|||
threshold: "Llindar"
|
||||
centerX: "Centre de X"
|
||||
centerY: "Centre de Y"
|
||||
zoomLinesSmoothing: "Suavitzat"
|
||||
zoomLinesSmoothingDescription: "Els paràmetres de suavitzat i amplada de línia en augmentar no es poden fer servir junts."
|
||||
zoomLinesThreshold: "Amplada de línia a l'augmentar "
|
||||
density: "Densitat"
|
||||
zoomLinesOutlineThickness: "Amplada de les vores exteriors"
|
||||
zoomLinesMaskSize: "Diàmetre del centre"
|
||||
zoomLinesBlack: "Obscurir"
|
||||
circle: "Cercle"
|
||||
drafts: "Esborrany "
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ reactions: "Reakce"
|
|||
reactionSettingDescription2: "Přetažením změníte pořadí, kliknutím smažete, zmáčkněte \"+\" k přidání"
|
||||
rememberNoteVisibility: "Zapamatovat nastavení zobrazení poznámky"
|
||||
attachCancel: "Odstranit přílohu"
|
||||
deleteFile: "Smazat soubor"
|
||||
markAsSensitive: "Označit jako NSFW"
|
||||
unmarkAsSensitive: "Odznačit jako NSFW"
|
||||
enterFileName: "Zadejte název souboru"
|
||||
|
|
@ -205,6 +206,7 @@ blockThisInstance: "Blokovat tuto instanci"
|
|||
silenceThisInstance: "Utišit tuto instanci"
|
||||
operations: "Operace"
|
||||
software: "Software"
|
||||
softwareName: "Software"
|
||||
version: "Verze"
|
||||
metadata: "Metadata"
|
||||
withNFiles: "{n} soubor(ů)"
|
||||
|
|
@ -231,6 +233,7 @@ noteDeleteConfirm: "Jste si jistí že chcete smazat tuhle poznámku?"
|
|||
pinLimitExceeded: "Nemůžete připnout další poznámky."
|
||||
done: "Hotovo"
|
||||
processing: "Zpracovávám"
|
||||
preprocessing: "Připravuji..."
|
||||
preview: "Náhled"
|
||||
default: "Výchozí"
|
||||
defaultValueIs: "Základní hodnota: {value}"
|
||||
|
|
@ -265,6 +268,7 @@ removed: "Smazáno"
|
|||
removeAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
|
||||
deleteAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
|
||||
resetAreYouSure: "Opravdu resetovat?"
|
||||
areYouSure: "Jste si jistí?"
|
||||
saved: "Uloženo"
|
||||
upload: "Nahrát soubory"
|
||||
keepOriginalUploading: "Ponechat originální obrázek"
|
||||
|
|
@ -275,9 +279,12 @@ uploadFromUrl: "Nahrát z URL adresy"
|
|||
uploadFromUrlDescription: "URL adresa souboru, který chcete nahrát"
|
||||
uploadFromUrlRequested: "Upload zažádán"
|
||||
uploadFromUrlMayTakeTime: "Může trvat nějakou dobu, dokud nebude dokončeno nahrávání."
|
||||
uploadNFiles: "Uploadovat {n} souborů"
|
||||
explore: "Objevovat"
|
||||
messageRead: "Přečtené"
|
||||
readAllChatMessages: "Označit všechny zprávy za přečtené"
|
||||
noMoreHistory: "To je vše"
|
||||
startChat: "Začít chat"
|
||||
nUsersRead: "přečteno {n} uživateli"
|
||||
agreeTo: "Souhlasím s {0}"
|
||||
agree: "Souhlasím"
|
||||
|
|
@ -308,12 +315,15 @@ selectFile: "Vybrat soubor"
|
|||
selectFiles: "Vybrat soubory"
|
||||
selectFolder: "Vyberte složku"
|
||||
selectFolders: "Vyberte složky"
|
||||
fileNotSelected: "Nebyl vybrán žádný soubor"
|
||||
renameFile: "Přejmenovat soubor"
|
||||
folderName: "Název složky"
|
||||
createFolder: "Vytvořit složku"
|
||||
renameFolder: "Přejmenovat složku"
|
||||
deleteFolder: "Odstranit složku"
|
||||
folder: "Složka "
|
||||
addFile: "Přidat soubor"
|
||||
showFile: "Procházet soubory"
|
||||
emptyDrive: "Váš disk je prázdný"
|
||||
emptyFolder: "Tato složka je prázdná"
|
||||
unableToDelete: "Nelze smazat"
|
||||
|
|
@ -424,6 +434,7 @@ totp: "Ověřovací aplikace"
|
|||
totpDescription: "Použít ověřovací aplikaci pro použití jednorázových hesel"
|
||||
moderator: "Moderátor"
|
||||
moderation: "Moderování"
|
||||
moderationNote: "Poznámka moderátora"
|
||||
nUsersMentioned: "{n} uživatelů zmínilo"
|
||||
securityKeyAndPasskey: "Bezpečnostní klíče a tokeny"
|
||||
securityKey: "Bezpečnostní klíč"
|
||||
|
|
@ -479,7 +490,9 @@ uiLanguage: "Jazyk uživatelského rozhraní"
|
|||
aboutX: "O {x}"
|
||||
emojiStyle: "Styl emoji"
|
||||
native: "Výchozí"
|
||||
menuStyle: "Styl nabídky"
|
||||
style: "Vzhled"
|
||||
drawer: "Boční menu"
|
||||
popup: "Vyskakovací okno"
|
||||
showNoteActionsOnlyHover: "Zobrazit akce poznámky jenom při naběhnutí myši"
|
||||
noHistory: "Žádná historie"
|
||||
|
|
@ -535,6 +548,7 @@ deleteAll: "Smazat vše"
|
|||
showFixedPostForm: "Zobrazit formulář pro nové příspěvky nad časovou osou"
|
||||
showFixedPostFormInChannel: "Zobrazit vkládací formulář na vrcholu časové osy (Kanály)"
|
||||
newNoteRecived: "Jsou k dispozici nové poznámky"
|
||||
newNote: "Nová poznámka"
|
||||
sounds: "Zvuky"
|
||||
sound: "Zvuky"
|
||||
listen: "Poslouchat"
|
||||
|
|
@ -614,6 +628,7 @@ medium: "Střední"
|
|||
small: "Malé"
|
||||
generateAccessToken: "Vygenerovat přístupový token"
|
||||
permission: "Oprávnění"
|
||||
adminPermission: "Administrátorská práva"
|
||||
enableAll: "Povolit vše"
|
||||
disableAll: "Vypnout vše"
|
||||
tokenRequested: "Povolit přístup k účtu"
|
||||
|
|
@ -889,6 +904,9 @@ oneHour: "1 hodina"
|
|||
oneDay: "1 den"
|
||||
oneWeek: "1 týden"
|
||||
oneMonth: "1 měsíc"
|
||||
threeMonths: "3 měsíce"
|
||||
oneYear: "1 rok"
|
||||
threeDays: "3 dny"
|
||||
reflectMayTakeTime: "Může trvat nějakou dobu, než se projeví změny."
|
||||
failedToFetchAccountInformation: "Nepodařily se načíst informace o účtě"
|
||||
rateLimitExceeded: "Překročení rychlostního limitu"
|
||||
|
|
@ -1026,6 +1044,8 @@ showClipButtonInNoteFooter: "Přidat \"Připnout\" do akčního menu poznámky"
|
|||
noteIdOrUrl: "ID nebo URL poznámky"
|
||||
video: "Video"
|
||||
videos: "Videa"
|
||||
audio: "Zvuk"
|
||||
audioFiles: "Zvuk"
|
||||
dataSaver: "Spořič dat"
|
||||
accountMigration: "Migrace účtu"
|
||||
accountMoved: "Tenhle uživatel se přesunul na nový účet:"
|
||||
|
|
@ -1053,6 +1073,8 @@ preservedUsernames: "Rezervované uživatelské jména"
|
|||
preservedUsernamesDescription: "Seznam uživatelských jmén na rezervaci oddělené mezerama. Tyhle jména se potom nebudou moc použít při normálním procesu vytvoření účtu ale můžou být použiti manuálně administratorém. Existujících účtů se to nedotkne."
|
||||
createNoteFromTheFile: "Vytvořit poznámku z tohodle souboru"
|
||||
archive: "Archiv"
|
||||
archived: "Archivované"
|
||||
unarchive: "Obnovit"
|
||||
channelArchiveConfirmTitle: "Opravdu chcete archivovat {name}?"
|
||||
channelArchiveConfirmDescription: "Archivovaný kanál se objeví v seznamu kanálů nebo ve výsledcích hledání. Nové poznámky se nedají vložit do seznamu."
|
||||
thisChannelArchived: "Tenhle kanál je archivovaný"
|
||||
|
|
@ -1099,6 +1121,7 @@ doYouAgree: "Souhlasíte?"
|
|||
beSureToReadThisAsItIsImportant: "Přečtěte si prosím tyto důležité informace."
|
||||
iHaveReadXCarefullyAndAgree: "Přečetl jsem si text \"{x}\" a souhlasím s ním."
|
||||
icon: "Avatar"
|
||||
forYou: "Pro vás"
|
||||
replies: "Odpovědět"
|
||||
renotes: "Přeposlat"
|
||||
sourceCode: "Zdrojový kód"
|
||||
|
|
|
|||
|
|
@ -3401,11 +3401,7 @@ _imageEffector:
|
|||
threshold: "Schwellenwert"
|
||||
centerX: "Zentrum X"
|
||||
centerY: "Zentrum Y"
|
||||
zoomLinesSmoothing: "Glättung"
|
||||
zoomLinesSmoothingDescription: "Die Einstellungen für die Glättung und für die Breite der Konzentrationslinien können nicht gleichzeitig verwendet werden."
|
||||
zoomLinesThreshold: "Breite der Konzentrationslinien"
|
||||
zoomLinesMaskSize: "Mitteldurchmesser"
|
||||
zoomLinesBlack: "Schwarz machen"
|
||||
circle: "Kreisförmig"
|
||||
drafts: "Entwurf"
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -3401,11 +3401,7 @@ _imageEffector:
|
|||
threshold: "Threshold"
|
||||
centerX: "Center X"
|
||||
centerY: "Center Y"
|
||||
zoomLinesSmoothing: "Smoothing"
|
||||
zoomLinesSmoothingDescription: "Smoothing and zoom line width cannot be used together."
|
||||
zoomLinesThreshold: "Zoom line width"
|
||||
zoomLinesMaskSize: "Center diameter"
|
||||
zoomLinesBlack: "Make black"
|
||||
circle: "Circular"
|
||||
drafts: "Drafts"
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -3401,11 +3401,9 @@ _imageEffector:
|
|||
threshold: "Umbral"
|
||||
centerX: "Centrar X"
|
||||
centerY: "Centrar Y"
|
||||
zoomLinesSmoothing: "Suavizado"
|
||||
zoomLinesSmoothingDescription: "El suavizado y el ancho de línea de zoom no se pueden utilizar juntos."
|
||||
zoomLinesThreshold: "Ancho de línea del zoom"
|
||||
density: "Densidad"
|
||||
zoomLinesOutlineThickness: "Grosor del borde"
|
||||
zoomLinesMaskSize: "Diámetro del centro"
|
||||
zoomLinesBlack: "Cambiar color de las líneas de impacto a negro."
|
||||
circle: "Círculo"
|
||||
drafts: "Borrador"
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -3401,11 +3401,9 @@ _imageEffector:
|
|||
threshold: "Soglia"
|
||||
centerX: "Centro orizzontale"
|
||||
centerY: "Centro verticale"
|
||||
zoomLinesSmoothing: "Levigatura"
|
||||
zoomLinesSmoothingDescription: "Non si possono usare insieme la levigatura e la larghezza della linea centrale."
|
||||
zoomLinesThreshold: "Limite delle linee zoom"
|
||||
density: "Densità"
|
||||
zoomLinesOutlineThickness: "Spessore del bordo"
|
||||
zoomLinesMaskSize: "Ampiezza del diametro"
|
||||
zoomLinesBlack: "Bande nere"
|
||||
circle: "Circolare"
|
||||
drafts: "Bozze"
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -3512,11 +3512,9 @@ _imageEffector:
|
|||
threshold: "しきい値"
|
||||
centerX: "中心X"
|
||||
centerY: "中心Y"
|
||||
zoomLinesSmoothing: "スムージング"
|
||||
zoomLinesSmoothingDescription: "スムージングと集中線の幅の設定は併用できません。"
|
||||
zoomLinesThreshold: "集中線の幅"
|
||||
density: "密度"
|
||||
zoomLinesOutlineThickness: "線の影の太さ"
|
||||
zoomLinesMaskSize: "中心径"
|
||||
zoomLinesBlack: "黒色にする"
|
||||
circle: "円形"
|
||||
|
||||
drafts: "下書き"
|
||||
|
|
|
|||
|
|
@ -1466,17 +1466,17 @@ _chat:
|
|||
newMessage: "새로운 메시지"
|
||||
individualChat: "개인 대화"
|
||||
individualChat_description: "특정 유저와 일대일 채팅을 할 수 있습니다."
|
||||
roomChat: "룸 채팅"
|
||||
roomChat: "그룹 채팅"
|
||||
roomChat_description: "여러 명이 함께 채팅할 수 있습니다.\n또한, 개인 채팅을 허용하지 않은 유저와도 상대방이 수락하면 채팅을 할 수 있습니다."
|
||||
createRoom: "룸을 생성"
|
||||
createRoom: "방 만들기"
|
||||
inviteUserToChat: "유저를 초대하여 채팅을 시작하세요"
|
||||
yourRooms: "생성한 룸"
|
||||
joiningRooms: "참가 중인 룸"
|
||||
yourRooms: "만들어진 방"
|
||||
joiningRooms: "참가 중인 방"
|
||||
invitations: "초대"
|
||||
noInvitations: "초대장이 없습니다"
|
||||
history: "이력"
|
||||
noHistory: "기록이 없습니다"
|
||||
noRooms: "룸이 없습니다"
|
||||
noRooms: "방이 없습니다"
|
||||
inviteUser: "유저를 초대"
|
||||
sentInvitations: "초대를 보내기"
|
||||
join: "참여"
|
||||
|
|
@ -1487,14 +1487,14 @@ _chat:
|
|||
home: "홈"
|
||||
send: "전송"
|
||||
newline: "줄바꿈"
|
||||
muteThisRoom: "이 룸을 뮤트"
|
||||
deleteRoom: "룸을 삭제"
|
||||
muteThisRoom: "이 방을 뮤트하기"
|
||||
deleteRoom: "방을 삭제하기"
|
||||
chatNotAvailableForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅이 활성화되어 있지 않습니다."
|
||||
chatIsReadOnlyForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅은 읽기 전용입니다. 새로 쓰거나 채팅 룸을 만들거나 참가할 수 없습니다."
|
||||
chatNotAvailableInOtherAccount: "상대방 계정에서 채팅 기능을 사용할 수 없는 상태입니다."
|
||||
cannotChatWithTheUser: "이 유저와 채팅을 시작할 수 없습니다"
|
||||
cannotChatWithTheUser_description: "채팅을 사용할 수 없는 상태이거나 상대방이 채팅을 열지 않은 상태입니다."
|
||||
youAreNotAMemberOfThisRoomButInvited: "당신은 이 룸의 참가자가 아닙니다만 초대 신청을 받으셨습니다. 참가하려면 초대를 수락해주십시오."
|
||||
youAreNotAMemberOfThisRoomButInvited: "이 방의 참가자가 아니지만 초대를 받았습니다. 참가하려면 초대를 수락하세요."
|
||||
doYouAcceptInvitation: "초대를 수락하시겠습니까?"
|
||||
chatWithThisUser: "채팅하기"
|
||||
thisUserAllowsChatOnlyFromFollowers: "이 유저는 팔로워만 채팅을 할 수 있습니다."
|
||||
|
|
@ -2544,7 +2544,7 @@ _widgets:
|
|||
_userList:
|
||||
chooseList: "리스트 선택"
|
||||
clicker: "클리커"
|
||||
birthdayFollowings: "오늘이 생일인 유저"
|
||||
birthdayFollowings: "곧 생일인 사용자"
|
||||
chat: "채팅하기"
|
||||
_widgetOptions:
|
||||
showHeader: "해더를 표시"
|
||||
|
|
@ -2792,7 +2792,7 @@ _notification:
|
|||
newNote: "새 게시물"
|
||||
unreadAntennaNote: "안테나 {name}"
|
||||
roleAssigned: "역할이 부여 되었습니다."
|
||||
chatRoomInvitationReceived: "채팅 룸에 초대받았습니다"
|
||||
chatRoomInvitationReceived: "채팅방에 초대되었습니다"
|
||||
emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다"
|
||||
achievementEarned: "도전 과제를 달성했습니다"
|
||||
testNotification: "알림 테스트"
|
||||
|
|
@ -2823,7 +2823,7 @@ _notification:
|
|||
receiveFollowRequest: "팔로우 요청을 받았을 때"
|
||||
followRequestAccepted: "팔로우 요청이 승인되었을 때"
|
||||
roleAssigned: "역할이 부여됨"
|
||||
chatRoomInvitationReceived: "채팅 룸에 초대받음"
|
||||
chatRoomInvitationReceived: "채팅방에 초대됨"
|
||||
achievementEarned: "도전 과제 획득"
|
||||
exportCompleted: "추출을 성공함"
|
||||
login: "로그인"
|
||||
|
|
@ -2977,7 +2977,7 @@ _moderationLogTypes:
|
|||
deletePage: "페이지를 삭제"
|
||||
deleteFlash: "Play를 삭제"
|
||||
deleteGalleryPost: "갤러리 게시물을 삭제"
|
||||
deleteChatRoom: "채팅 룸 삭제"
|
||||
deleteChatRoom: "채팅방 삭제하기"
|
||||
updateProxyAccountDescription: "프록시 계정의 설명 업데이트"
|
||||
_fileViewer:
|
||||
title: "파일 상세"
|
||||
|
|
@ -3401,11 +3401,9 @@ _imageEffector:
|
|||
threshold: "한계 값"
|
||||
centerX: "X축 중심"
|
||||
centerY: "Y축 중심"
|
||||
zoomLinesSmoothing: "다듬기"
|
||||
zoomLinesSmoothingDescription: "다듬기와 집중선 폭 설정은 같이 쓸 수 없습니다."
|
||||
zoomLinesThreshold: "집중선 폭"
|
||||
density: "밀도"
|
||||
zoomLinesOutlineThickness: "선 그림자의 굵기"
|
||||
zoomLinesMaskSize: "중앙 값"
|
||||
zoomLinesBlack: "검은색으로 하기"
|
||||
circle: "원형"
|
||||
drafts: "초안"
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -3289,11 +3289,7 @@ _imageEffector:
|
|||
threshold: "Limiar"
|
||||
centerX: "Centralizar X"
|
||||
centerY: "Centralizar Y"
|
||||
zoomLinesSmoothing: "Suavização"
|
||||
zoomLinesSmoothingDescription: "Suavização e largura das linhas de zoom não podem ser utilizados simultaneamente."
|
||||
zoomLinesThreshold: "Largura das linhas de zoom"
|
||||
zoomLinesMaskSize: "Diâmetro do centro"
|
||||
zoomLinesBlack: "Linhas pretas"
|
||||
circle: "Circular"
|
||||
drafts: "Rascunhos"
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -3401,11 +3401,7 @@ _imageEffector:
|
|||
threshold: "เทรชโฮลด์"
|
||||
centerX: "กลาง X"
|
||||
centerY: "กลาง Y"
|
||||
zoomLinesSmoothing: "ทำให้สมูธ"
|
||||
zoomLinesSmoothingDescription: "ตั้งให้สมูธไม่สามารถใช้ร่วมกับตั้งความกว้างเส้นรวมศูนย์ได้"
|
||||
zoomLinesThreshold: "ความกว้างเส้นรวมศูนย์"
|
||||
zoomLinesMaskSize: "ขนาดพื้นที่ตรงกลาง"
|
||||
zoomLinesBlack: "ทำให้ดำ"
|
||||
circle: "ทรงกลม"
|
||||
drafts: "ร่าง"
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ files: "Dosyalar"
|
|||
download: "İndir"
|
||||
driveFileDeleteConfirm: "“{name}” dosyasını silmek istediğinden emin misin? Bu dosyaya ekli tüm notlar da silinecek."
|
||||
unfollowConfirm: "{name} kullanıcısını cidden takipden çıkmak istiyor musun?"
|
||||
cancelFollowRequestConfirm: "{name} adlı kişiye gönderdiğiniz takip isteğini iptal etmek ister misiniz?"
|
||||
rejectFollowRequestConfirm: "{name} adlı kullanıcının takip isteğini reddetmek istiyor musunuz?"
|
||||
exportRequested: "Dışa aktarma işlemi talep ettin. Bu işlem biraz zaman alabilir. İşlem tamamlandığında Drive'ına eklenecek."
|
||||
importRequested: "İçe aktarma talebinde bulundun. Bu işlem biraz zaman alabilir."
|
||||
lists: "Listeler"
|
||||
|
|
@ -253,6 +255,7 @@ noteDeleteConfirm: "Bu notu silmek istediğinden emin misin?"
|
|||
pinLimitExceeded: "Artık daha fazla not sabitleyemezsin"
|
||||
done: "Tamam"
|
||||
processing: "İşleniyor..."
|
||||
preprocessing: "Hazırlık aşamasında"
|
||||
preview: "Önizleme"
|
||||
default: "Varsayılan"
|
||||
defaultValueIs: "Varsayılan: {value}"
|
||||
|
|
@ -301,6 +304,7 @@ uploadFromUrlMayTakeTime: "Yükleme işleminin tamamlanması biraz zaman alabili
|
|||
uploadNFiles: "{n} dosya yükle"
|
||||
explore: "Keşfet"
|
||||
messageRead: "Oku"
|
||||
readAllChatMessages: "Tüm mesajları okundu olarak işaretle"
|
||||
noMoreHistory: "Daha fazla geçmiş bilgisi yok."
|
||||
startChat: "Sohbete başla"
|
||||
nUsersRead: "{n} tarafından okundu"
|
||||
|
|
@ -333,6 +337,7 @@ fileName: "Dosya adı"
|
|||
selectFile: "Dosya seçin"
|
||||
selectFiles: "Dosyaları seçin"
|
||||
selectFolder: "Klasör seçin"
|
||||
unselectFolder: "Klasör seçimini kaldır"
|
||||
selectFolders: "Klasörleri seçin"
|
||||
fileNotSelected: "Hiç dosya seçilmedi"
|
||||
renameFile: "Dosyayı yeniden adlandır"
|
||||
|
|
@ -345,6 +350,7 @@ addFile: "Bir dosya ekle"
|
|||
showFile: "Dosyaları göster"
|
||||
emptyDrive: "Drive boş"
|
||||
emptyFolder: "Bu klasör boş"
|
||||
dropHereToUpload: "Yüklemek için dosyalarınızı buraya sürükleyin."
|
||||
unableToDelete: "Silinemiyor"
|
||||
inputNewFileName: "Yeni bir dosya adı girin"
|
||||
inputNewDescription: "Yeni alternatif metin girin"
|
||||
|
|
@ -537,6 +543,7 @@ regenerate: "Yeniden oluştur"
|
|||
fontSize: "Yazı tipi boyutu"
|
||||
mediaListWithOneImageAppearance: "Tek bir resim içeren medya listelerinin yüksekliği"
|
||||
limitTo: "{x} ile sınırlandır"
|
||||
showMediaListByGridInWideArea: "Ekran genişliği geniş olduğunda, medya listesi yatay olarak görüntülenecektir."
|
||||
noFollowRequests: "Bekleyen takip istekleri yok."
|
||||
openImageInNewTab: "Görüntüleri yeni sekmede aç"
|
||||
dashboard: "Gösterge paneli"
|
||||
|
|
@ -772,6 +779,7 @@ lockedAccountInfo: "Notunuzun görünürlüğünü “Yalnızca takipçiler” o
|
|||
alwaysMarkSensitive: "Varsayılan olarak hassas olarak işaretle"
|
||||
loadRawImages: "Küçük resimleri göstermek yerine orijinal resimleri yükle"
|
||||
disableShowingAnimatedImages: "Animasyonlu görüntüleri oynatmayın"
|
||||
disableShowingAnimatedImages_caption: "Bu ayara rağmen animasyonlu görüntüler oynatılmıyorsa, bunun nedeni tarayıcınızın veya işletim sisteminizin erişilebilirlik ayarları veya güç tasarrufu ayarlarından kaynaklanan parazit olabilir."
|
||||
highlightSensitiveMedia: "Hassas medyayı vurgulayın"
|
||||
verificationEmailSent: "Doğrulama e-postası gönderildi. Doğrulamayı tamamlamak için e-postadaki bağlantıyı takip edin."
|
||||
notSet: "Ayarlı değil"
|
||||
|
|
@ -1018,6 +1026,9 @@ pushNotificationAlreadySubscribed: "Push bildirimleri zaten açık"
|
|||
pushNotificationNotSupported: "Push bildirimleri sunucu veya tarayıcı tarafından desteklenmiyor"
|
||||
sendPushNotificationReadMessage: "Okunduktan sonra push bildirimlerini silin"
|
||||
sendPushNotificationReadMessageCaption: "Bu, cihazınızın güç tüketimini artırabilir."
|
||||
pleaseAllowPushNotification: "Lütfen tarayıcı ayarlarınızdan bildirimlere izin verin."
|
||||
browserPushNotificationDisabled: "Bildirim gönderme izni alınamadı."
|
||||
browserPushNotificationDisabledDescription: "{serverName} sunucusundan bildirim gönderme izniniz yok. Lütfen tarayıcı ayarlarınızdan bildirimlere izin verin ve tekrar deneyin."
|
||||
windowMaximize: "Maksimize et"
|
||||
windowMinimize: "Minimize et"
|
||||
windowRestore: "Geri yükle"
|
||||
|
|
@ -1168,6 +1179,7 @@ installed: "Yüklendi"
|
|||
branding: "Markalaşma"
|
||||
enableServerMachineStats: "Sunucu donanım istatistiklerini yayınla"
|
||||
enableIdenticonGeneration: "Kullanıcı identicon oluşturmayı etkinleştir"
|
||||
showRoleBadgesOfRemoteUsers: "Uzaktan kullanıcılara verilen rol rozetlerini görüntüle"
|
||||
turnOffToImprovePerformance: "Devre dışı bırakma, daha yüksek performansa yol açabilir."
|
||||
createInviteCode: "Davet Kodu oluştur"
|
||||
createWithOptions: "Seçeneklerle oluştur"
|
||||
|
|
@ -1316,6 +1328,7 @@ acknowledgeNotesAndEnable: "Önlemleri anladıktan sonra açın."
|
|||
federationSpecified: "Bu sunucu, beyaz liste federasyonunda çalıştırılmaktadır. Yönetici tarafından belirlenen sunucular dışında diğer sunucularla etkileşim kurmak yasaktır."
|
||||
federationDisabled: "Bu sunucuda federasyon devre dışıdır. Diğer sunuculardaki kullanıcılarla etkileşim kuramazsınız."
|
||||
draft: "Taslaklar"
|
||||
draftsAndScheduledNotes: "Taslaklar ve planlanmış gönderiler"
|
||||
confirmOnReact: "Tepki verirken onaylayın"
|
||||
reactAreYouSure: "“{emoji}” tepkisini eklemek ister misin?"
|
||||
markAsSensitiveConfirm: "Bu medyayı hassas olarak ayarlamak ister misin?"
|
||||
|
|
@ -1344,6 +1357,7 @@ textCount: "Karakter sayısı"
|
|||
information: "Hakkında"
|
||||
chat: "Sohbet"
|
||||
directMessage: "Kullanıcıyla sohbet et"
|
||||
directMessage_short: "Mesaj"
|
||||
migrateOldSettings: "Eski istemci ayarlarını taşıma"
|
||||
migrateOldSettings_description: "Bu işlem otomatik olarak yapılmalıdır, ancak herhangi bir nedenle geçiş başarısız olursa, geçiş işlemini manuel olarak kendin başlatabilirsin. Mevcut yapılandırma bilgileri üzerine yazılacaktır."
|
||||
compress: "Sıkıştır"
|
||||
|
|
@ -1371,6 +1385,8 @@ redisplayAllTips: "Tüm “İpucu & Püf Nokta” tekrar göster"
|
|||
hideAllTips: "Tüm “İpucu & Püf Nokta” gizle"
|
||||
defaultImageCompressionLevel: "Varsayılan görüntü sıkıştırma düzeyi"
|
||||
defaultImageCompressionLevel_description: "Düşük seviye görüntü kalitesini korur ancak dosya boyutunu artırır.<br>Yüksek seviye dosya boyutunu azaltır ancak görüntü kalitesini düşürür."
|
||||
defaultCompressionLevel: "Varsayılan sıkıştırma seviyesi"
|
||||
defaultCompressionLevel_description: "Ayarı düşürmek kaliteyi koruyacak ancak dosya boyutunu artıracaktır. <br> Ayarı yükseltmek dosya boyutunu küçültecek ancak kaliteyi düşürecektir."
|
||||
inMinutes: "Dakika(lar)"
|
||||
inDays: "Gün(ler)"
|
||||
safeModeEnabled: "Güvenli mod etkinleştirildi"
|
||||
|
|
@ -1378,21 +1394,74 @@ pluginsAreDisabledBecauseSafeMode: "Güvenli mod etkinleştirildiği için tüm
|
|||
customCssIsDisabledBecauseSafeMode: "Güvenli mod etkin olduğu için özel CSS uygulanmıyor."
|
||||
themeIsDefaultBecauseSafeMode: "Güvenli mod etkinken, varsayılan tema kullanılır. Güvenli modu devre dışı bırakmak bu değişiklikleri geri alır."
|
||||
thankYouForTestingBeta: "Beta sürümünü test ettiğin için teşekkür ederiz!"
|
||||
createUserSpecifiedNote: "Kullanıcı tarafından belirtilen notlar oluşturun"
|
||||
schedulePost: "Bir gönderi planla"
|
||||
scheduleToPostOnX: "{x} için bir gönderi planla"
|
||||
scheduledToPostOnX: "{x} için bir gönderi planlandı."
|
||||
schedule: "rezervasyon"
|
||||
scheduled: "rezervasyon"
|
||||
widgets: "Widget'lar"
|
||||
deviceInfo: "Cihaz Bilgileri"
|
||||
deviceInfoDescription: "Teknik bir sorunuz olduğunda, aşağıdaki bilgileri eklemeniz sorunun çözülmesine yardımcı olabilir."
|
||||
youAreAdmin: "Siz yöneticisiniz."
|
||||
frame: "Çerçeve"
|
||||
presets: "Ön ayar"
|
||||
zeroPadding: "Sıfır doldurma"
|
||||
nothingToConfigure: "Ayarlar seçeneği bulunmamaktadır."
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "Dosya başlığı"
|
||||
filename: "Dosya adı"
|
||||
filename_without_ext: "Uzantısız dosya adları"
|
||||
year: "Çekim yılı"
|
||||
month: "Çekim ayı"
|
||||
day: "Çekim tarihi"
|
||||
hour: "Fotoğrafın çekildiği zaman (saat)"
|
||||
minute: "Çekim süresi (dakika)"
|
||||
second: "Çekim süresi (saniye)"
|
||||
camera_model: "Kamera Adı"
|
||||
camera_lens_model: "Lens adı"
|
||||
camera_mm: "Odak uzaklığı"
|
||||
camera_mm_35: "Genişlik (35mm)"
|
||||
camera_f: "açıklık"
|
||||
camera_s: "Enstantane hızı"
|
||||
camera_iso: "ISO hassasiyeti"
|
||||
gps_lat: "Enlem"
|
||||
gps_long: "Boylam"
|
||||
_imageFrameEditor:
|
||||
title: "Düzenleme kareleri"
|
||||
tip: "Görselleri, meta verileri içeren çerçeveler ve etiketler ekleyerek süsleyebilirsiniz."
|
||||
header: "Başlık"
|
||||
footer: "Alt bilgi"
|
||||
borderThickness: "jantın genişliği"
|
||||
labelThickness: "Etiket genişliği"
|
||||
labelScale: "Etiket ölçeği"
|
||||
centered: "Merkezlenmiş"
|
||||
captionMain: "Altyazı (büyük)"
|
||||
captionSub: "Altyazı (küçük)"
|
||||
availableVariables: "Mevcut değişkenler"
|
||||
withQrCode: "2 boyutlu kod"
|
||||
backgroundColor: "Arka Plan Rengi "
|
||||
textColor: "Metin Rengi "
|
||||
font: "Yazı tipi"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
quitWithoutSaveConfirm: "Kaydedilmemiş değişiklikleri silmek ister misin?"
|
||||
failedToLoadImage: "Görüntü yükleme başarısız oldu "
|
||||
_compression:
|
||||
_quality:
|
||||
high: "Yüksek Kalite "
|
||||
medium: "Orta Kalite"
|
||||
low: "Düşük Kalite "
|
||||
_size:
|
||||
large: "Büyük Boyut"
|
||||
medium: "Orta Boyut"
|
||||
small: "Küçük Boyut"
|
||||
_order:
|
||||
newest: "Önce yeni"
|
||||
oldest: "Önce eski"
|
||||
_chat:
|
||||
messages: "Mesaj"
|
||||
noMessagesYet: "Henüz mesaj yok"
|
||||
newMessage: "Yeni mesaj"
|
||||
individualChat: "Özel Sohbet"
|
||||
|
|
@ -1481,6 +1550,11 @@ _settings:
|
|||
showUrlPreview: "URL önizlemesi"
|
||||
showAvailableReactionsFirstInNote: "Mevcut tepkileri en üstte göster."
|
||||
showPageTabBarBottom: "Sayfa sekme çubuğunu aşağıda göster"
|
||||
emojiPaletteBanner: "Emoji seçiciye kalıcı olarak bir palet olarak görüntülenecek ön ayarları kaydedebilir veya seçicinin nasıl görüntüleneceğini özelleştirebilirsiniz."
|
||||
enableAnimatedImages: "Hareketli görüntüleri etkinleştirin"
|
||||
settingsPersistence_title: "Ayarların kalıcılığı"
|
||||
settingsPersistence_description1: "Ayarların kalıcı olarak saklanmasını etkinleştirmek, yapılandırma bilgilerinin kaybolmasını önler."
|
||||
settingsPersistence_description2: "Ortamınıza bağlı olarak bu özelliği etkinleştirmek mümkün olmayabilir."
|
||||
_chat:
|
||||
showSenderName: "Gönderenin adını göster"
|
||||
sendOnEnter: "Enter tuşuna basarak gönderin"
|
||||
|
|
@ -1489,6 +1563,8 @@ _preferencesProfile:
|
|||
profileNameDescription: "Bu cihazı tanımlayan bir ad belirle."
|
||||
profileNameDescription2: "Örnek: “Ana bilgisayar”, “Akıllı telefon”"
|
||||
manageProfiles: "Profilleri Yönet"
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "Aynı profili birden fazla cihazda kullanmak önerilmez."
|
||||
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "Birden fazla cihazda senkronize etmek istediğiniz ayarlarınız varsa, lütfen her bir ayar için \"Birden fazla cihazda senkronize et\" seçeneğini etkinleştirin."
|
||||
_preferencesBackup:
|
||||
autoBackup: "Otomatik yedekleme"
|
||||
restoreFromBackup: "Yedeklemeden geri yükle"
|
||||
|
|
@ -1498,6 +1574,7 @@ _preferencesBackup:
|
|||
youNeedToNameYourProfileToEnableAutoBackup: "Otomatik yedeklemeyi etkinleştirmek için bir profil adı ayarlanmalıdır."
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "Bu cihazda ayarların otomatik yedeklemesi etkinleştirilmemiş."
|
||||
backupFound: "Ayarların yedeği bulundu"
|
||||
forceBackup: "Ayarların zorunlu yedeklenmesi"
|
||||
_accountSettings:
|
||||
requireSigninToViewContents: "İçeriği görüntülemek için oturum açmanız gerekir."
|
||||
requireSigninToViewContentsDescription1: "Oluşturduğun tüm notları ve diğer içeriği görüntülemek için oturum açman gerekir. Bu, tarayıcıların bilgilerini toplamasına engel olacaktır."
|
||||
|
|
@ -2003,6 +2080,7 @@ _role:
|
|||
canManageAvatarDecorations: "Avatar süslerini yönet"
|
||||
driveCapacity: "Drive kapasitesi"
|
||||
maxFileSize: "Yükleyebileceğin maksimum dosya boyutu"
|
||||
maxFileSize_caption: "Önceki aşamada ters proxy veya CDN gibi başka yapılandırma ayarları da olabilir."
|
||||
alwaysMarkNsfw: "Dosyaları her zaman NSFW olarak işaretle"
|
||||
canUpdateBioMedia: "Bir simge veya banner görüntüsünü düzenleyebilir"
|
||||
pinMax: "Sabitlenmiş notların maksimum sayısı"
|
||||
|
|
@ -2030,6 +2108,7 @@ _role:
|
|||
uploadableFileTypes_caption: "İzin verilen MIME/dosya türlerini belirtir. Birden fazla MIME türü, yeni bir satırla ayırarak belirtilebilir ve joker karakterler yıldız işareti (*) ile belirtilebilir. (örneğin, image/*)"
|
||||
uploadableFileTypes_caption2: "Bazı dosya türleri algılanamayabilir. Bu tür dosyalara izin vermek için, spesifikasyona {x} ekle."
|
||||
noteDraftLimit: "Sunucu notlarının olası taslak sayısı"
|
||||
scheduledNoteLimit: "Aynı anda oluşturulabilecek planlanmış gönderi sayısı"
|
||||
watermarkAvailable: "Filigran işlevinin kullanılabilirliği"
|
||||
_condition:
|
||||
roleAssignedTo: "Manuel rollere atanmış"
|
||||
|
|
@ -2420,6 +2499,7 @@ _auth:
|
|||
scopeUser: "Aşağıdaki kullanıcı olarak çalıştırın"
|
||||
pleaseLogin: "Uygulamaları yetkilendirmek için lütfen giriş yapın."
|
||||
byClickingYouWillBeRedirectedToThisUrl: "Erişim izni verildiğinde, otomatik olarak aşağıdaki URL'ye yönlendirileceksin."
|
||||
alreadyAuthorized: "Bu uygulamaya zaten erişim izinleri verilmiş durumda."
|
||||
_antennaSources:
|
||||
all: "Tüm notlar"
|
||||
homeTimeline: "Takip edilen kullanıcıların notları"
|
||||
|
|
@ -2468,11 +2548,40 @@ _widgets:
|
|||
chat: "Sohbet"
|
||||
_widgetOptions:
|
||||
showHeader: "Başlığı göster"
|
||||
transparent: "Arka planı şeffaf yapın"
|
||||
height: "Yükseklik"
|
||||
_button:
|
||||
colored: "Renkli"
|
||||
_clock:
|
||||
size: "Boyut"
|
||||
thickness: "İğne kalınlığı"
|
||||
thicknessThin: "İnce"
|
||||
thicknessMedium: "Normal"
|
||||
thicknessThick: "Kalın"
|
||||
graduations: "Kadran ölçeği"
|
||||
graduationDots: "Nokta"
|
||||
graduationArabic: "Arap rakamları"
|
||||
fadeGraduations: "ölçeği soluklaştır"
|
||||
sAnimation: "İkinci el animasyon"
|
||||
sAnimationElastic: "Gerçek"
|
||||
sAnimationEaseOut: "Düz"
|
||||
twentyFour: "24 saat ekran"
|
||||
labelTime: "Zaman"
|
||||
labelTz: "Zaman Dilimi"
|
||||
labelTimeAndTz: "Zaman ve Saat Dilimi"
|
||||
timezone: "Zaman Dilimi "
|
||||
showMs: "Milisaniye cinsinden göster"
|
||||
showLabel: "Etiketi Göster"
|
||||
_jobQueue:
|
||||
sound: "Sesleri Çal"
|
||||
_rss:
|
||||
url: "RSS beslemesi URL'si"
|
||||
refreshIntervalSec: "Güncelleme aralığı (saniye)"
|
||||
maxEntries: "Görüntülenecek maksimum öğe sayısı"
|
||||
_rssTicker:
|
||||
shuffle: "Görüntüleme sırasını karıştır"
|
||||
duration: "Kaydırma yazısı hızı (saniye)"
|
||||
reverse: "Geriye doğru kaydır"
|
||||
_birthdayFollowings:
|
||||
period: "Süre"
|
||||
_cw:
|
||||
|
|
@ -2519,9 +2628,20 @@ _postForm:
|
|||
replyPlaceholder: "Bu notu yanıtla..."
|
||||
quotePlaceholder: "Bu notu alıntı yap..."
|
||||
channelPlaceholder: "Bir kanala gönder..."
|
||||
showHowToUse: "Form açıklamasını göster"
|
||||
_howToUse:
|
||||
content_title: "Metin"
|
||||
content_description: "Yayınlamak istediğiniz içeriği girin."
|
||||
toolbar_title: "Araç Çubuğu"
|
||||
toolbar_description: "Dosya ve anket ekleyebilir, açıklamalar ve etiketler ekleyebilir, emoji ve bahsetme mesajları ekleyebilirsiniz."
|
||||
account_title: "Hesap Menüsü"
|
||||
account_description: "Paylaşım yaptığınız hesabı değiştirebilir ve hesabınıza kaydedilmiş taslak ve planlanmış paylaşımların listesini görüntüleyebilirsiniz."
|
||||
visibility_title: "Görünürlük"
|
||||
visibility_description: "Notlarınıza kimlerin erişebileceğinin kapsamını belirleyebilirsiniz."
|
||||
menu_title: "Menü"
|
||||
menu_description: "Taslak olarak kaydetme, gönderi planlama ve tepki ayarlama gibi diğer işlemleri de gerçekleştirebilirsiniz."
|
||||
submit_title: "Gönder düğmesi"
|
||||
submit_description: "Bir not paylaşacağım. Ctrl + Enter / Cmd + Enter tuşlarını kullanarak da paylaşım yapabilirsiniz."
|
||||
_placeholders:
|
||||
a: "Ne yapıyorsun?"
|
||||
b: "Çevrende neler oluyor?"
|
||||
|
|
@ -2667,6 +2787,8 @@ _notification:
|
|||
youReceivedFollowRequest: "Bir takip isteği aldınız."
|
||||
yourFollowRequestAccepted: "Takip isteğin kabul edildi."
|
||||
pollEnded: "Anket sonuçları açıklandı."
|
||||
scheduledNotePosted: "Rezervasyon defteri yayınlandı."
|
||||
scheduledNotePostFailed: "Rezervasyon defterine gönderilemedi"
|
||||
newNote: "Yeni not"
|
||||
unreadAntennaNote: "{name} anteni"
|
||||
roleAssigned: "Verilen rol"
|
||||
|
|
@ -2696,6 +2818,8 @@ _notification:
|
|||
quote: "Alıntılar"
|
||||
reaction: "Tepki"
|
||||
pollEnded: "Anketler sona eriyor"
|
||||
scheduledNotePosted: "Planlanan gönderi başarılı"
|
||||
scheduledNotePostFailed: "Planlanan gönderi başarısız oldu"
|
||||
receiveFollowRequest: "Takip istekleri alındı"
|
||||
followRequestAccepted: "Kabul edilen takip istekleri"
|
||||
roleAssigned: "Verilen rol"
|
||||
|
|
@ -2735,6 +2859,14 @@ _deck:
|
|||
usedAsMinWidthWhenFlexible: "“Otomatik genişlik ayarı” seçeneği etkinleştirildiğinde, bunun için minimum genişlik kullanılacak."
|
||||
flexible: "Otomatik genişlik ayarı"
|
||||
enableSyncBetweenDevicesForProfiles: "Cihazlar arasında profil bilgilerinin senkronizasyonunu etkinleştir"
|
||||
showHowToUse: "Kullanıcı arayüzü açıklamasını görüntüle"
|
||||
_howToUse:
|
||||
addColumn_title: "Sütun ekle"
|
||||
addColumn_description: "Sütun türlerini seçip ekleyebilirsiniz."
|
||||
settings_title: "Arayüz Yapılandırması"
|
||||
settings_description: "Sekme kullanıcı arayüzünü ayrıntılı olarak yapılandırabilirsiniz."
|
||||
switchProfile_title: "Profili Değiştir"
|
||||
switchProfile_description: "Kullanıcı arayüzü düzenlerini profil olarak kaydedebilir ve istediğiniz zaman bunlar arasında geçiş yapabilirsiniz."
|
||||
_columns:
|
||||
main: "Ana"
|
||||
widgets: "Widget'lar"
|
||||
|
|
@ -2795,6 +2927,8 @@ _abuseReport:
|
|||
notifiedWebhook: "Kullanılacak webhook"
|
||||
deleteConfirm: "Bildirim alıcısını silmek istediğinden emin misin?"
|
||||
_moderationLogTypes:
|
||||
clearQueue: "Kuyruğu temizle"
|
||||
promoteQueue: "Sıraya alınmış işi yeniden deneyin."
|
||||
createRole: "Rol oluşturuldu"
|
||||
deleteRole: "Rol silindi"
|
||||
updateRole: "Rol güncellendi"
|
||||
|
|
@ -3189,10 +3323,13 @@ _watermarkEditor:
|
|||
title: "Filigranı Düzenle"
|
||||
cover: "Her şeyi örtün"
|
||||
repeat: "her yere yayılmış"
|
||||
preserveBoundingRect: "Döndürme sırasında dışarı çıkmayacak şekilde ayarlayın."
|
||||
opacity: "Opaklık"
|
||||
scale: "Boyut"
|
||||
text: "Metin"
|
||||
qr: "2 boyutlu kod"
|
||||
position: "Pozisyon"
|
||||
margin: "Kenar"
|
||||
type: "Tür"
|
||||
image: "Görseller"
|
||||
advanced: "Gelişmiş"
|
||||
|
|
@ -3207,16 +3344,21 @@ _watermarkEditor:
|
|||
polkadotSubDotOpacity: "İkincil noktanın opaklığı"
|
||||
polkadotSubDotRadius: "İkincil noktanın boyutu"
|
||||
polkadotSubDotDivisions: "Alt nokta sayısı."
|
||||
leaveBlankToAccountUrl: "Boş bırakılması durumunda hesap URL'si görüntülenecektir."
|
||||
failedToLoadImage: "Görüntü yükleme başarısız oldu "
|
||||
_imageEffector:
|
||||
title: "Effektler"
|
||||
addEffect: "Efektler Ekle"
|
||||
discardChangesConfirm: "Cidden çıkmak istiyor musun? Kaydedilmemiş değişikliklerin var."
|
||||
failedToLoadImage: "Görüntü yükleme başarısız oldu "
|
||||
_fxs:
|
||||
chromaticAberration: "Renk Sapması"
|
||||
glitch: "Bozulma"
|
||||
mirror: "Ayna"
|
||||
invert: "Renkleri Ters Çevir"
|
||||
grayscale: "Gri tonlama"
|
||||
blur: "Bulanıklık"
|
||||
pixelate: "Mozaik"
|
||||
colorAdjust: "Renk Düzeltme"
|
||||
colorClamp: "Renk Sıkıştırma"
|
||||
colorClampAdvanced: "Renk Sıkıştırma (Gelişmiş)"
|
||||
|
|
@ -3228,10 +3370,13 @@ _imageEffector:
|
|||
checker: "Denetleyici"
|
||||
blockNoise: "Gürültüyü Engelle"
|
||||
tearing: "Yırtılma"
|
||||
fill: "Doldur"
|
||||
_fxProps:
|
||||
angle: "Açı"
|
||||
scale: "Boyut"
|
||||
size: "Boyut"
|
||||
radius: "Yarıçap"
|
||||
samples: "Örnek sayısı"
|
||||
offset: "Pozisyon"
|
||||
color: "Renk"
|
||||
opacity: "Opaklık"
|
||||
|
|
@ -3256,11 +3401,10 @@ _imageEffector:
|
|||
threshold: "Eşik"
|
||||
centerX: "Merkez X"
|
||||
centerY: "Merkez Y"
|
||||
zoomLinesSmoothing: "Düzeltme"
|
||||
zoomLinesSmoothingDescription: "Düzeltme ve yakınlaştırma çizgi genişliği birlikte kullanılamaz."
|
||||
zoomLinesThreshold: "Zoom çizgi genişliği"
|
||||
density: "Yoğunluk"
|
||||
zoomLinesOutlineThickness: "çizgi gölge kalınlığı"
|
||||
zoomLinesMaskSize: "Merkez çapı"
|
||||
zoomLinesBlack: "Siyah yap"
|
||||
circle: "Dairesel"
|
||||
drafts: "Taslaklar"
|
||||
_drafts:
|
||||
select: "Taslak Seç"
|
||||
|
|
@ -3276,6 +3420,22 @@ _drafts:
|
|||
restoreFromDraft: "Taslaktan geri yükle"
|
||||
restore: "Geri yükle"
|
||||
listDrafts: "Taslaklar Listesi"
|
||||
schedule: "Planlanmış Gönderi"
|
||||
listScheduledNotes: "Planlanmış gönderilerin listesi"
|
||||
cancelSchedule: "Rezervasyonu iptal et"
|
||||
qr: "2 boyutlu kod"
|
||||
_qr:
|
||||
showTabTitle: "Ekran"
|
||||
readTabTitle: "Okumak"
|
||||
shareTitle: "{name}{acct}"
|
||||
shareText: "Beni Fediverse'te takip edin!"
|
||||
chooseCamera: "Kamera Seç"
|
||||
cannotToggleFlash: "Işık seçeneği mevcut değil."
|
||||
turnOnFlash: "Işığı açın"
|
||||
turnOffFlash: "Işığı kapatın"
|
||||
startQr: "Özgeçmiş Kodu Okuyucu"
|
||||
stopQr: "Kod okuyucuyu durdurun"
|
||||
noQrCodeFound: "QR kodu bulunamadı"
|
||||
scanFile: "Cihazdaki görüntüyü tarayın"
|
||||
raw: "Metin"
|
||||
mfm: "MFM"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
_lang_: "Tiếng Việt "
|
||||
_lang_: "Tiếng Việt"
|
||||
headlineMisskey: "Mạng xã hội liên hợp"
|
||||
introMisskey: "Xin chào! Misskey là một nền tảng tiểu blog phi tập trung mã nguồn mở.\nViết \"tút\" để chia sẻ những suy nghĩ của bạn 📡\nBằng \"biểu cảm\", bạn có thể bày tỏ nhanh chóng cảm xúc của bạn với các tút 👍\nHãy khám phá một thế giới mới! 🚀"
|
||||
poweredByMisskeyDescription: "{name} là một trong những chủ máy của <b>Misskey</b> là nền tảng mã nguồn mở"
|
||||
|
|
@ -576,6 +576,7 @@ showFixedPostForm: "Hiện khung soạn tút ở phía trên bảng tin"
|
|||
showFixedPostFormInChannel: "Hiển thị mẫu bài đăng ở phía trên bản tin"
|
||||
withRepliesByDefaultForNewlyFollowed: "Mặc định hiển thị trả lời từ những người dùng mới theo dõi trong dòng thời gian"
|
||||
newNoteRecived: "Đã nhận tút mới"
|
||||
newNote: "Ghi chú mới"
|
||||
sounds: "Âm thanh"
|
||||
sound: "Âm thanh"
|
||||
notificationSoundSettings: "Cài đặt âm thanh thông báo"
|
||||
|
|
@ -848,7 +849,7 @@ hideOnlineStatus: "Ẩn trạng thái online"
|
|||
hideOnlineStatusDescription: "Ẩn trạng thái online của bạn làm giảm sự tiện lợi của một số tính năng như tìm kiếm."
|
||||
online: "Online"
|
||||
active: "Hoạt động"
|
||||
offline: "Offline"
|
||||
offline: "Ngoại tuyến"
|
||||
notRecommended: "Không đề xuất"
|
||||
botProtection: "Bảo vệ Bot"
|
||||
instanceBlocking: "Máy chủ đã chặn"
|
||||
|
|
@ -1220,6 +1221,7 @@ information: "Giới thiệu"
|
|||
chat: "Trò chuyện"
|
||||
migrateOldSettings: "Di chuyển cài đặt cũ"
|
||||
migrateOldSettings_description: "Thông thường, quá trình này diễn ra tự động, nhưng nếu vì lý do nào đó mà quá trình di chuyển không thành công, bạn có thể kích hoạt thủ công quy trình di chuyển, quá trình này sẽ ghi đè lên thông tin cấu hình hiện tại của bạn."
|
||||
driveAboutTip: "Trong Drive, danh sách các tệp bạn đã tải lên trước đây sẽ được hiển thị.<br>\nBạn có thể sử dụng lại chúng khi đính kèm vào ghi chú, hoặc tải lên trước các tệp để đăng sau.<br>\n<b>Lưu ý rằng nếu bạn xóa một tệp, tệp đó cũng sẽ biến mất khỏi tất cả những nơi đã sử dụng tệp đó (ghi chú, trang, ảnh đại diện, biểu ngữ, v.v.).</b><br>\nBạn cũng có thể tạo các thư mục để sắp xếp chúng."
|
||||
inMinutes: "phút"
|
||||
inDays: "ngày"
|
||||
widgets: "Tiện ích"
|
||||
|
|
|
|||
|
|
@ -3401,11 +3401,9 @@ _imageEffector:
|
|||
threshold: "阈值"
|
||||
centerX: "中心 X "
|
||||
centerY: "中心 Y"
|
||||
zoomLinesSmoothing: "平滑"
|
||||
zoomLinesSmoothingDescription: "平滑和集中线宽度设置不能同时使用。"
|
||||
zoomLinesThreshold: "集中线宽度"
|
||||
density: "密度"
|
||||
zoomLinesOutlineThickness: "线条阴影粗细"
|
||||
zoomLinesMaskSize: "中心直径"
|
||||
zoomLinesBlack: "变成黑色"
|
||||
circle: "圆形"
|
||||
drafts: "草稿"
|
||||
_drafts:
|
||||
|
|
|
|||
|
|
@ -3401,11 +3401,9 @@ _imageEffector:
|
|||
threshold: "閾值"
|
||||
centerX: "X中心座標"
|
||||
centerY: "Y中心座標"
|
||||
zoomLinesSmoothing: "平滑化"
|
||||
zoomLinesSmoothingDescription: "平滑化與集中線寬度設定不能同時使用。"
|
||||
zoomLinesThreshold: "集中線的寬度"
|
||||
density: "密度"
|
||||
zoomLinesOutlineThickness: "線條陰影的粗細"
|
||||
zoomLinesMaskSize: "中心直徑"
|
||||
zoomLinesBlack: "變成黑色"
|
||||
circle: "圓形"
|
||||
drafts: "草稿\n"
|
||||
_drafts:
|
||||
|
|
|
|||
24
package.json
24
package.json
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "misskey",
|
||||
"version": "2026.3.1",
|
||||
"version": "2026.3.2",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/misskey-dev/misskey.git"
|
||||
},
|
||||
"packageManager": "pnpm@10.30.3",
|
||||
"packageManager": "pnpm@10.32.1",
|
||||
"workspaces": [
|
||||
"packages/misskey-js",
|
||||
"packages/i18n",
|
||||
|
|
@ -53,29 +53,29 @@
|
|||
"cleanall": "pnpm clean-all"
|
||||
},
|
||||
"dependencies": {
|
||||
"cssnano": "7.1.2",
|
||||
"esbuild": "0.27.3",
|
||||
"cssnano": "7.1.3",
|
||||
"esbuild": "0.27.4",
|
||||
"execa": "9.6.1",
|
||||
"ignore-walk": "8.0.0",
|
||||
"js-yaml": "4.1.1",
|
||||
"postcss": "8.5.6",
|
||||
"tar": "7.5.10",
|
||||
"postcss": "8.5.8",
|
||||
"tar": "7.5.11",
|
||||
"terser": "5.46.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.39.3",
|
||||
"@eslint/js": "9.39.4",
|
||||
"@misskey-dev/eslint-plugin": "2.1.0",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/node": "24.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@types/node": "24.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260116.1",
|
||||
"cross-env": "10.1.0",
|
||||
"cypress": "15.11.0",
|
||||
"eslint": "9.39.3",
|
||||
"eslint": "9.39.4",
|
||||
"globals": "17.4.0",
|
||||
"ncp": "2.0.0",
|
||||
"pnpm": "10.30.3",
|
||||
"pnpm": "10.32.1",
|
||||
"start-server-and-test": "2.1.5",
|
||||
"typescript": "5.9.3"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@
|
|||
"utf-8-validate": "6.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.1000.0",
|
||||
"@aws-sdk/lib-storage": "3.1000.0",
|
||||
"@aws-sdk/client-s3": "3.1008.0",
|
||||
"@aws-sdk/lib-storage": "3.1008.0",
|
||||
"@discordapp/twemoji": "16.0.1",
|
||||
"@fastify/accepts": "5.0.4",
|
||||
"@fastify/cors": "11.2.0",
|
||||
|
|
@ -83,16 +83,16 @@
|
|||
"@kitajs/html": "4.2.13",
|
||||
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
||||
"@misskey-dev/summaly": "5.2.5",
|
||||
"@napi-rs/canvas": "0.1.95",
|
||||
"@nestjs/common": "11.1.14",
|
||||
"@nestjs/core": "11.1.14",
|
||||
"@nestjs/testing": "11.1.14",
|
||||
"@napi-rs/canvas": "0.1.96",
|
||||
"@nestjs/common": "11.1.16",
|
||||
"@nestjs/core": "11.1.16",
|
||||
"@nestjs/testing": "11.1.16",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sentry/node": "10.40.0",
|
||||
"@sentry/profiling-node": "10.40.0",
|
||||
"@simplewebauthn/server": "13.2.3",
|
||||
"@sinonjs/fake-timers": "15.1.0",
|
||||
"@smithy/node-http-handler": "4.4.12",
|
||||
"@sentry/node": "10.43.0",
|
||||
"@sentry/profiling-node": "10.43.0",
|
||||
"@simplewebauthn/server": "13.3.0",
|
||||
"@sinonjs/fake-timers": "15.1.1",
|
||||
"@smithy/node-http-handler": "4.4.16",
|
||||
"@swc/cli": "0.8.0",
|
||||
"@swc/core": "1.15.18",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
"bcryptjs": "3.0.3",
|
||||
"blurhash": "2.0.5",
|
||||
"body-parser": "2.2.2",
|
||||
"bullmq": "5.70.1",
|
||||
"bullmq": "5.71.0",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"chalk": "5.6.2",
|
||||
"chalk-template": "1.1.2",
|
||||
|
|
@ -112,10 +112,10 @@
|
|||
"content-disposition": "1.0.1",
|
||||
"date-fns": "4.1.0",
|
||||
"deep-email-validator": "0.1.21",
|
||||
"fastify": "5.8.1",
|
||||
"fastify": "5.8.2",
|
||||
"fastify-raw-body": "5.0.0",
|
||||
"feed": "5.2.0",
|
||||
"file-type": "21.3.0",
|
||||
"file-type": "21.3.2",
|
||||
"fluent-ffmpeg": "2.1.3",
|
||||
"form-data": "4.0.5",
|
||||
"got": "14.6.6",
|
||||
|
|
@ -138,14 +138,14 @@
|
|||
"nanoid": "5.1.6",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "3.3.2",
|
||||
"node-html-parser": "7.0.2",
|
||||
"nodemailer": "8.0.1",
|
||||
"node-html-parser": "7.1.0",
|
||||
"nodemailer": "8.0.2",
|
||||
"nsfwjs": "4.2.0",
|
||||
"oauth2orize": "1.12.0",
|
||||
"oauth2orize-pkce": "0.1.2",
|
||||
"os-utils": "0.0.14",
|
||||
"otpauth": "9.5.0",
|
||||
"pg": "8.19.0",
|
||||
"pg": "8.20.0",
|
||||
"pkce-challenge": "6.0.0",
|
||||
"probe-image-size": "7.2.3",
|
||||
"promise-limit": "2.7.0",
|
||||
|
|
@ -164,7 +164,7 @@
|
|||
"slacc": "0.0.10",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"systeminformation": "5.31.1",
|
||||
"systeminformation": "5.31.4",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tmp": "0.2.5",
|
||||
"tsc-alias": "1.8.16",
|
||||
|
|
@ -178,8 +178,8 @@
|
|||
"devDependencies": {
|
||||
"@jest/globals": "29.7.0",
|
||||
"@kitajs/ts-html-plugin": "4.1.4",
|
||||
"@nestjs/platform-express": "11.1.14",
|
||||
"@sentry/vue": "10.40.0",
|
||||
"@nestjs/platform-express": "11.1.16",
|
||||
"@sentry/vue": "10.43.0",
|
||||
"@simplewebauthn/types": "12.0.0",
|
||||
"@swc/jest": "0.2.39",
|
||||
"@types/accepts": "1.3.7",
|
||||
|
|
@ -193,7 +193,7 @@
|
|||
"@types/jsonld": "1.5.15",
|
||||
"@types/mime-types": "3.0.1",
|
||||
"@types/ms": "2.1.0",
|
||||
"@types/node": "24.11.0",
|
||||
"@types/node": "24.12.0",
|
||||
"@types/nodemailer": "7.0.11",
|
||||
"@types/oauth2orize": "1.11.5",
|
||||
"@types/oauth2orize-pkce": "0.1.2",
|
||||
|
|
@ -202,7 +202,7 @@
|
|||
"@types/random-seed": "0.3.5",
|
||||
"@types/ratelimiter": "3.4.6",
|
||||
"@types/rename": "1.0.7",
|
||||
"@types/sanitize-html": "2.16.0",
|
||||
"@types/sanitize-html": "2.16.1",
|
||||
"@types/semver": "7.7.1",
|
||||
"@types/simple-oauth2": "5.0.8",
|
||||
"@types/sinonjs__fake-timers": "15.0.1",
|
||||
|
|
@ -212,10 +212,10 @@
|
|||
"@types/vary": "1.1.3",
|
||||
"@types/web-push": "3.6.4",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"aws-sdk-client-mock": "4.1.0",
|
||||
"cbor": "10.0.11",
|
||||
"cbor": "10.0.12",
|
||||
"cross-env": "10.1.0",
|
||||
"esbuild-plugin-swc": "1.0.1",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { type FastifyServerOptions } from 'fastify';
|
|||
import type * as Sentry from '@sentry/node';
|
||||
import type * as SentryVue from '@sentry/vue';
|
||||
import type { RedisOptions } from 'ioredis';
|
||||
import type { ManifestChunk } from 'vite';
|
||||
|
||||
type RedisOptionsSource = Partial<RedisOptions> & {
|
||||
host: string;
|
||||
|
|
@ -189,9 +188,7 @@ export type Config = {
|
|||
authUrl: string;
|
||||
driveUrl: string;
|
||||
userAgent: string;
|
||||
frontendEntry: ManifestChunk;
|
||||
frontendManifestExists: boolean;
|
||||
frontendEmbedEntry: ManifestChunk;
|
||||
frontendEmbedManifestExists: boolean;
|
||||
mediaProxy: string;
|
||||
externalMediaProxyEnabled: boolean;
|
||||
|
|
@ -250,12 +247,6 @@ export function loadConfig(): Config {
|
|||
|
||||
const frontendManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json'));
|
||||
const frontendEmbedManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json'));
|
||||
const frontendManifest = frontendManifestExists ?
|
||||
JSON.parse(fs.readFileSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json'), 'utf-8'))
|
||||
: { 'src/_boot_.ts': { file: null } };
|
||||
const frontendEmbedManifest = frontendEmbedManifestExists ?
|
||||
JSON.parse(fs.readFileSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json'), 'utf-8'))
|
||||
: { 'src/boot.ts': { file: null } };
|
||||
|
||||
const config = JSON.parse(fs.readFileSync(compiledConfigFilePath, 'utf-8')) as Source;
|
||||
|
||||
|
|
@ -337,9 +328,7 @@ export function loadConfig(): Config {
|
|||
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
|
||||
: null,
|
||||
userAgent: `Misskey/${version} (${config.url})`,
|
||||
frontendEntry: frontendManifest['src/_boot_.ts'],
|
||||
frontendManifestExists: frontendManifestExists,
|
||||
frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'],
|
||||
frontendEmbedManifestExists: frontendEmbedManifestExists,
|
||||
perChannelMaxNoteCacheCount: config.perChannelMaxNoteCacheCount ?? 1000,
|
||||
perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500,
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export class ApRequestCreator {
|
|||
}, args.additionalHeaders),
|
||||
};
|
||||
|
||||
const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
|
||||
const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host']);
|
||||
|
||||
return {
|
||||
request,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointServ
|
|||
import { MiLocalUser } from '@/models/User.js';
|
||||
import { ChannelMutingService } from '@/core/ChannelMutingService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { Brackets } from 'typeorm';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes', 'channels'],
|
||||
|
|
@ -132,7 +133,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
.then(x => x.map(x => x.id).filter(x => x !== ps.channelId));
|
||||
if (mutingChannelIds.length > 0) {
|
||||
query.andWhere('note.channelId NOT IN (:...mutingChannelIds)', { mutingChannelIds });
|
||||
query.andWhere('note.renoteChannelId NOT IN (:...mutingChannelIds)', { mutingChannelIds });
|
||||
query.andWhere(new Brackets(qb => {
|
||||
qb.orWhere('note.renoteChannelId IS NULL');
|
||||
qb.orWhere('note.renoteChannelId NOT IN (:...mutingChannelIds)', { mutingChannelIds });
|
||||
}));
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
|
|
|||
|
|
@ -177,7 +177,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
.andWhere('note.channelId IS NULL')
|
||||
.andWhere('note.userId IN (:...meOrFolloweeIds)', { meOrFolloweeIds: meOrFolloweeIds });
|
||||
if (mutingChannelIds.length > 0) {
|
||||
qb.andWhere('note.renoteChannelId NOT IN (:...mutingChannelIds)', { mutingChannelIds });
|
||||
qb.andWhere(new Brackets(qb2 => {
|
||||
qb2.orWhere('note.renoteChannelId IS NULL');
|
||||
qb2.orWhere('note.renoteChannelId NOT IN (:...mutingChannelIds)', { mutingChannelIds });
|
||||
}));
|
||||
}
|
||||
}));
|
||||
} else if (followingChannelIds.length > 0) {
|
||||
|
|
|
|||
|
|
@ -185,7 +185,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
if (ps.withChannelNotes) {
|
||||
query.andWhere(new Brackets(qb => {
|
||||
if (mutingChannelIds.length > 0) {
|
||||
qb.andWhere('note.channelId NOT IN (:...mutingChannelIds)', { mutingChannelIds: mutingChannelIds });
|
||||
qb.andWhere(new Brackets(qb2 => {
|
||||
qb2.orWhere('note.channelId IS NULL');
|
||||
qb2.orWhere('note.channelId NOT IN (:...mutingChannelIds)', { mutingChannelIds });
|
||||
}));
|
||||
}
|
||||
|
||||
if (!isSelf) {
|
||||
|
|
|
|||
|
|
@ -4,23 +4,19 @@
|
|||
*/
|
||||
|
||||
import * as WebSocket from 'ws';
|
||||
import type { MiUser } from '@/models/User.js';
|
||||
import type { MiAccessToken } from '@/models/AccessToken.js';
|
||||
import { NotificationService } from '@/core/NotificationService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { CacheService } from '@/core/CacheService.js';
|
||||
import { MiFollowing, MiUserProfile } from '@/models/_.js';
|
||||
import type { GlobalEvents, StreamEventEmitter } from '@/core/GlobalEventService.js';
|
||||
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
|
||||
import { ChannelMutingService } from '@/core/ChannelMutingService.js';
|
||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||
import { isJsonObject } from '@/misc/json-value.js';
|
||||
import type { EventEmitter } from 'events';
|
||||
import type Channel from './channel.js';
|
||||
import type { ChannelConstructor } from './channel.js';
|
||||
import type { ChannelRequest } from './channel.js';
|
||||
import { ContextIdFactory, ModuleRef, REQUEST } from '@nestjs/core';
|
||||
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||
import { isJsonObject } from '@/misc/json-value.js';
|
||||
import type { JsonObject, JsonValue } from '@/misc/json-value.js';
|
||||
import { ChannelMutingService } from '@/core/ChannelMutingService.js';
|
||||
import { ChannelFollowingService } from '@/core/ChannelFollowingService.js';
|
||||
import type { GlobalEvents, StreamEventEmitter } from '@/core/GlobalEventService.js';
|
||||
import { MiFollowing, MiUserProfile } from '@/models/_.js';
|
||||
import { CacheService } from '@/core/CacheService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { NotificationService } from '@/core/NotificationService.js';
|
||||
import type { MiAccessToken } from '@/models/AccessToken.js';
|
||||
import type { MiUser } from '@/models/User.js';
|
||||
import { MainChannel } from '@/server/api/stream/channels/main.js';
|
||||
import { HomeTimelineChannel } from '@/server/api/stream/channels/home-timeline.js';
|
||||
import { LocalTimelineChannel } from '@/server/api/stream/channels/local-timeline.js';
|
||||
|
|
@ -39,13 +35,17 @@ import { ChatUserChannel } from '@/server/api/stream/channels/chat-user.js';
|
|||
import { ChatRoomChannel } from '@/server/api/stream/channels/chat-room.js';
|
||||
import { ReversiChannel } from '@/server/api/stream/channels/reversi.js';
|
||||
import { ReversiGameChannel } from '@/server/api/stream/channels/reversi-game.js';
|
||||
import type { ChannelRequest } from './channel.js';
|
||||
import type { ChannelConstructor } from './channel.js';
|
||||
import type Channel from './channel.js';
|
||||
import type { EventEmitter } from 'events';
|
||||
|
||||
const MAX_CHANNELS_PER_CONNECTION = 32;
|
||||
|
||||
/**
|
||||
* Main stream connection
|
||||
*/
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
|
||||
@Injectable({ scope: Scope.TRANSIENT })
|
||||
export default class Connection {
|
||||
public user?: MiUser;
|
||||
|
|
@ -206,12 +206,17 @@ export default class Connection {
|
|||
|
||||
@bindThis
|
||||
private async onNoteStreamMessage(data: GlobalEvents['note']['payload']) {
|
||||
if (data.body.visibility === 'specified' && !data.body.visibleUserIds.includes(this.user!.id)) {
|
||||
return;
|
||||
}
|
||||
// 自分自身ではないかつ
|
||||
if (data.body.userId !== this.user?.id) {
|
||||
// 公開範囲が指名で自分が含まれてない
|
||||
if (data.body.visibility === 'specified' && (this.user == null || !data.body.visibleUserIds.includes(this.user.id))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.body.visibility === 'followers' && !Object.hasOwn(this.following, data.body.userId)) {
|
||||
return;
|
||||
// 公開範囲がフォロワーで自分がフォロワーでない
|
||||
if (data.body.visibility === 'followers' && !Object.hasOwn(this.following, data.body.userId)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.sendMessageToWs('noteUpdated', {
|
||||
|
|
|
|||
|
|
@ -6,16 +6,11 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { deepClone } from '@/misc/clone.js';
|
||||
import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import type { MiUser } from '@/models/User.js';
|
||||
|
||||
type HiddenLayer = 'note' | 'renote' | 'renoteRenote';
|
||||
|
||||
type LockdownCheckResult =
|
||||
| { shouldSkip: true }
|
||||
| { shouldSkip: false; hiddenLayers: Set<HiddenLayer> };
|
||||
|
||||
/** Streamにおいて、ノートを隠す(hideNote)を適用するためのService */
|
||||
@Injectable()
|
||||
export class NoteStreamingHidingService {
|
||||
|
|
@ -23,110 +18,52 @@ export class NoteStreamingHidingService {
|
|||
private noteEntityService: NoteEntityService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* ノートの可視性を判定する
|
||||
*
|
||||
* @param note - 判定対象のノート
|
||||
* @param meId - 閲覧者のユーザーID(未ログインの場合はnull)
|
||||
* @returns shouldSkip: true の場合はノートを流さない、false の場合は hiddenLayers に基づいて隠す
|
||||
*/
|
||||
@bindThis
|
||||
public async shouldHide(
|
||||
note: Packed<'Note'>,
|
||||
meId: MiUser['id'] | null,
|
||||
): Promise<LockdownCheckResult> {
|
||||
const hiddenLayers = new Set<HiddenLayer>();
|
||||
private collectRenoteChain(note: Packed<'Note'>): Packed<'Note'>[] {
|
||||
const renoteChain: Packed<'Note'>[] = [];
|
||||
|
||||
// 1階層目: note自体
|
||||
const shouldHideThisNote = await this.noteEntityService.shouldHideNote(note, meId);
|
||||
if (shouldHideThisNote) {
|
||||
if (isRenotePacked(note) && isQuotePacked(note)) {
|
||||
// 引用リノートの場合、内容を隠して流す
|
||||
hiddenLayers.add('note');
|
||||
} else if (isRenotePacked(note)) {
|
||||
// 純粋リノートの場合、流さない
|
||||
return { shouldSkip: true };
|
||||
} else {
|
||||
// 通常ノートの場合、内容を隠して流す
|
||||
hiddenLayers.add('note');
|
||||
}
|
||||
for (let current: Packed<'Note'> | null | undefined = note; current != null; current = current.renote) {
|
||||
renoteChain.push(current);
|
||||
}
|
||||
|
||||
// 2階層目: note.renote
|
||||
if (isRenotePacked(note) && note.renote) {
|
||||
const shouldHideRenote = await this.noteEntityService.shouldHideNote(note.renote, meId);
|
||||
if (shouldHideRenote) {
|
||||
if (isQuotePacked(note)) {
|
||||
// noteが引用リノートの場合、renote部分だけ隠す
|
||||
hiddenLayers.add('renote');
|
||||
} else {
|
||||
// noteが純粋リノートの場合、流さない
|
||||
return { shouldSkip: true };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3階層目: note.renote.renote
|
||||
if (isRenotePacked(note) && note.renote &&
|
||||
isRenotePacked(note.renote) && note.renote.renote) {
|
||||
const shouldHideRenoteRenote = await this.noteEntityService.shouldHideNote(note.renote.renote, meId);
|
||||
if (shouldHideRenoteRenote) {
|
||||
if (isQuotePacked(note.renote)) {
|
||||
// note.renoteが引用リノートの場合、renote.renote部分だけ隠す
|
||||
hiddenLayers.add('renoteRenote');
|
||||
} else {
|
||||
// note.renoteが純粋リノートの場合、note.renoteの意味がなくなるので流さない
|
||||
return { shouldSkip: true };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { shouldSkip: false, hiddenLayers };
|
||||
return renoteChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* hiddenLayersに基づいてノートの内容を隠す。
|
||||
* ストリーミング配信用にノートの内容を隠す(あるいはそもそも送信しない)判定及び処理を行う。
|
||||
*
|
||||
* この処理は渡された `note` を直接変更します。
|
||||
* 隠す処理が必要な場合は元のノートをクローンして変更を適用したものを返し、
|
||||
* 送信すべきでない場合は `null` を返す。
|
||||
* 変更が不要な場合は元のノートの参照をそのまま返す。
|
||||
*
|
||||
* @param note - 処理対象のノート
|
||||
* @param hiddenLayers - 隠す階層のセット
|
||||
* @param meId - 閲覧者のユーザー ID (未ログインの場合は `null`)
|
||||
* @returns 配信するノートオブジェクト、または配信スキップの場合は `null`
|
||||
*/
|
||||
@bindThis
|
||||
public applyHiding(
|
||||
note: Packed<'Note'>,
|
||||
hiddenLayers: Set<HiddenLayer>,
|
||||
): void {
|
||||
if (hiddenLayers.has('note')) {
|
||||
this.noteEntityService.hideNote(note);
|
||||
}
|
||||
if (hiddenLayers.has('renote') && note.renote) {
|
||||
this.noteEntityService.hideNote(note.renote);
|
||||
}
|
||||
if (hiddenLayers.has('renoteRenote') && note.renote && note.renote.renote) {
|
||||
this.noteEntityService.hideNote(note.renote.renote);
|
||||
}
|
||||
}
|
||||
public async filter(note: Packed<'Note'>, meId: MiUser['id'] | null): Promise<Packed<'Note'> | null> {
|
||||
const renoteChain = this.collectRenoteChain(note);
|
||||
const shouldHide = await Promise.all(renoteChain.map(n => this.noteEntityService.shouldHideNote(n, meId)));
|
||||
|
||||
/**
|
||||
* ストリーミング配信用にノートを隠す(あるいはそもそも送信しない)の判定及び処理を行う。
|
||||
*
|
||||
* この処理は渡された `note` を直接変更します。
|
||||
*
|
||||
* @param note - 処理対象のノート(必要に応じて内容が隠される)
|
||||
* @param meId - 閲覧者のユーザーID(未ログインの場合はnull)
|
||||
* @returns shouldSkip: true の場合はノートを流さない
|
||||
*/
|
||||
@bindThis
|
||||
public async processHiding(
|
||||
note: Packed<'Note'>,
|
||||
meId: MiUser['id'] | null,
|
||||
): Promise<{ shouldSkip: boolean }> {
|
||||
const result = await this.shouldHide(note, meId);
|
||||
if (result.shouldSkip) {
|
||||
return { shouldSkip: true };
|
||||
if (!shouldHide.some(h => h)) {
|
||||
// 隠す必要がない場合は元のノートをそのまま返す
|
||||
return note;
|
||||
}
|
||||
this.applyHiding(note, result.hiddenLayers);
|
||||
return { shouldSkip: false };
|
||||
|
||||
if (renoteChain.some(n => isRenotePacked(n) && !isQuotePacked(n))) {
|
||||
// 純粋リノートの場合は配信をスキップする
|
||||
return null;
|
||||
}
|
||||
|
||||
const clonedNote = deepClone(note);
|
||||
let currentCloned = clonedNote;
|
||||
|
||||
for (let i = 0; i < renoteChain.length; i++) {
|
||||
if (shouldHide[i]) {
|
||||
this.noteEntityService.hideNote(currentCloned);
|
||||
}
|
||||
currentCloned = currentCloned.renote!;
|
||||
}
|
||||
|
||||
return clonedNote;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,13 +62,14 @@ export class AntennaChannel extends Channel {
|
|||
@bindThis
|
||||
private async onEvent(data: GlobalEvents['antenna']['payload']) {
|
||||
if (data.type === 'note') {
|
||||
const note = await this.noteEntityService.pack(data.body.id, this.user, { detail: true });
|
||||
let note = await this.noteEntityService.pack(data.body.id, this.user, { detail: true });
|
||||
|
||||
if (!this.isNoteVisibleForMe(note)) return;
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -53,8 +53,10 @@ export class ChannelChannel extends Channel {
|
|||
if (!this.isNoteVisibleForMe(note)) return;
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
// eslint-disable-next-line no-param-reassign -- これ以降元の Note オブジェクトは見てはいけないので、いっそ再代入した方が安全
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -62,8 +62,10 @@ export class GlobalTimelineChannel extends Channel {
|
|||
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
// eslint-disable-next-line no-param-reassign -- これ以降元の Note オブジェクトは見てはいけないので、いっそ再代入した方が安全
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -59,8 +59,10 @@ export class HashtagChannel extends Channel {
|
|||
if (note.reply && note.reply.user.requireSigninToViewContents && this.user == null) return;
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
// eslint-disable-next-line no-param-reassign -- これ以降元の Note オブジェクトは見てはいけないので、いっそ再代入した方が安全
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -82,8 +82,10 @@ export class HomeTimelineChannel extends Channel {
|
|||
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
// eslint-disable-next-line no-param-reassign -- これ以降元の Note オブジェクトは見てはいけないので、いっそ再代入した方が安全
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -101,8 +101,10 @@ export class HybridTimelineChannel extends Channel {
|
|||
}
|
||||
}
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
// eslint-disable-next-line no-param-reassign -- これ以降元の Note オブジェクトは見てはいけないので、いっそ再代入した方が安全
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -72,8 +72,10 @@ export class LocalTimelineChannel extends Channel {
|
|||
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
// eslint-disable-next-line no-param-reassign -- これ以降元の Note オブジェクトは見てはいけないので、いっそ再代入した方が安全
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export class RoleTimelineChannel extends Channel {
|
|||
@bindThis
|
||||
private async onEvent(data: GlobalEvents['roleTimeline']['payload']) {
|
||||
if (data.type === 'note') {
|
||||
const note = data.body;
|
||||
let note = data.body;
|
||||
|
||||
if (!(await this.roleservice.isExplorable({ id: this.roleId }))) {
|
||||
return;
|
||||
|
|
@ -56,8 +56,9 @@ export class RoleTimelineChannel extends Channel {
|
|||
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -117,8 +117,10 @@ export class UserListChannel extends Channel {
|
|||
|
||||
if (this.isNoteMutedOrBlocked(note)) return;
|
||||
|
||||
const { shouldSkip } = await this.noteStreamingHidingService.processHiding(note, this.user?.id ?? null);
|
||||
if (shouldSkip) return;
|
||||
const filtered = await this.noteStreamingHidingService.filter(note, this.user?.id ?? null);
|
||||
if (!filtered) return;
|
||||
// eslint-disable-next-line no-param-reassign -- これ以降元の Note オブジェクトは見てはいけないので、いっそ再代入した方が安全
|
||||
note = filtered;
|
||||
|
||||
if (this.user) {
|
||||
if (isRenotePacked(note) && !isQuotePacked(note)) {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { dirname } from 'node:path';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { promises as fsp } from 'node:fs';
|
||||
import { promises as fsp, existsSync } from 'node:fs';
|
||||
import { languages } from 'i18n/const';
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
|
|
@ -13,21 +13,34 @@ import { bindThis } from '@/decorators.js';
|
|||
import { htmlSafeJsonStringify } from '@/misc/json-stringify-html-safe.js';
|
||||
import { MetaEntityService } from '@/core/entities/MetaEntityService.js';
|
||||
import type { FastifyReply } from 'fastify';
|
||||
import type { Manifest } from 'vite';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { MiMeta } from '@/models/Meta.js';
|
||||
import type { CommonData } from './views/_.js';
|
||||
import type { CommonData, ViteFiles } from './views/_.js';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
|
||||
const frontendVitePublic = `${_dirname}/../../../../frontend/public/`;
|
||||
const frontendEmbedVitePublic = `${_dirname}/../../../../frontend-embed/public/`;
|
||||
let rootDir = _dirname;
|
||||
// 見つかるまで上に遡る
|
||||
while (!existsSync(resolve(rootDir, 'packages'))) {
|
||||
const parentDir = dirname(rootDir);
|
||||
if (parentDir === rootDir) {
|
||||
throw new Error('Cannot find root directory');
|
||||
}
|
||||
rootDir = parentDir;
|
||||
}
|
||||
|
||||
const frontendViteBuilt = resolve(rootDir, 'built/_frontend_vite_');
|
||||
const frontendEmbedViteBuilt = resolve(rootDir, 'built/_frontend_embed_vite_');
|
||||
|
||||
@Injectable()
|
||||
export class HtmlTemplateService {
|
||||
private frontendBootloadersFetched = false;
|
||||
private frontendAssetsFetched = false;
|
||||
public frontendViteFiles: ViteFiles | null = null;
|
||||
public frontendBootloaderJs: string | null = null;
|
||||
public frontendBootloaderCss: string | null = null;
|
||||
public frontendEmbedViteFiles: ViteFiles | null = null;
|
||||
public frontendEmbedBootloaderJs: string | null = null;
|
||||
public frontendEmbedBootloaderCss: string | null = null;
|
||||
|
||||
|
|
@ -42,18 +55,92 @@ export class HtmlTemplateService {
|
|||
) {
|
||||
}
|
||||
|
||||
// 初期ロードで読み込むべきファイルのパスを収集する。
|
||||
// See https://ja.vite.dev/guide/backend-integration
|
||||
@bindThis
|
||||
private async prepareFrontendBootloaders() {
|
||||
if (this.frontendBootloadersFetched) return;
|
||||
this.frontendBootloadersFetched = true;
|
||||
private collectViteAssetFiles(manifest: Manifest): ViteFiles {
|
||||
const entryFile = Object.values(manifest).find((chunk) => chunk.isEntry);
|
||||
if (!entryFile) return {
|
||||
entryJs: null,
|
||||
css: [],
|
||||
modulePreloads: [],
|
||||
};
|
||||
|
||||
const [bootJs, bootCss, embedBootJs, embedBootCss] = await Promise.all([
|
||||
fsp.readFile(`${frontendVitePublic}loader/boot.js`, 'utf-8').catch(() => null),
|
||||
fsp.readFile(`${frontendVitePublic}loader/style.css`, 'utf-8').catch(() => null),
|
||||
fsp.readFile(`${frontendEmbedVitePublic}loader/boot.js`, 'utf-8').catch(() => null),
|
||||
fsp.readFile(`${frontendEmbedVitePublic}loader/style.css`, 'utf-8').catch(() => null),
|
||||
const seenChunkIds = new Set<string>();
|
||||
const cssFiles = new Set<string>();
|
||||
const modulePreloads = new Set<string>();
|
||||
|
||||
if (entryFile.css) {
|
||||
entryFile.css.forEach((css) => cssFiles.add(css));
|
||||
}
|
||||
|
||||
if (entryFile.imports != null && Array.isArray(entryFile.imports)) {
|
||||
function collectImports(imports: string[], recursive = false) {
|
||||
for (const importId of imports) {
|
||||
if (seenChunkIds.has(importId)) continue;
|
||||
seenChunkIds.add(importId);
|
||||
|
||||
const importedChunk = manifest[importId];
|
||||
if (!importedChunk) return;
|
||||
|
||||
if (importedChunk.css) {
|
||||
importedChunk.css.forEach((css) => cssFiles.add(css));
|
||||
}
|
||||
|
||||
if (importedChunk.imports != null && Array.isArray(importedChunk.imports)) {
|
||||
collectImports(importedChunk.imports, true);
|
||||
}
|
||||
|
||||
if (!recursive) {
|
||||
modulePreloads.add(importedChunk.file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectImports(entryFile.imports);
|
||||
}
|
||||
|
||||
return {
|
||||
entryJs: entryFile.file,
|
||||
css: Array.from(cssFiles),
|
||||
modulePreloads: Array.from(modulePreloads),
|
||||
};
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private async prepareFrontendAssets() {
|
||||
if (this.frontendAssetsFetched) return;
|
||||
this.frontendAssetsFetched = true;
|
||||
|
||||
const [
|
||||
bootJs,
|
||||
bootCss,
|
||||
embedBootJs,
|
||||
embedBootCss,
|
||||
] = await Promise.all([
|
||||
fsp.readFile(resolve(frontendViteBuilt, 'loader/boot.js'), 'utf-8').catch(() => null),
|
||||
fsp.readFile(resolve(frontendViteBuilt, 'loader/style.css'), 'utf-8').catch(() => null),
|
||||
fsp.readFile(resolve(frontendEmbedViteBuilt, 'loader/boot.js'), 'utf-8').catch(() => null),
|
||||
fsp.readFile(resolve(frontendEmbedViteBuilt, 'loader/style.css'), 'utf-8').catch(() => null),
|
||||
]);
|
||||
|
||||
let feViteManifest: Manifest | null = null;
|
||||
let embedFeViteManifest: Manifest | null = null;
|
||||
|
||||
if (this.config.frontendManifestExists) {
|
||||
const manifestContent = await fsp.readFile(resolve(frontendViteBuilt, 'manifest.json'), 'utf-8').catch(() => null);
|
||||
feViteManifest = manifestContent ? JSON.parse(manifestContent) : null;
|
||||
}
|
||||
|
||||
if (this.config.frontendEmbedManifestExists) {
|
||||
const manifestContent = await fsp.readFile(resolve(frontendEmbedViteBuilt, 'manifest.json'), 'utf-8').catch(() => null);
|
||||
embedFeViteManifest = manifestContent ? JSON.parse(manifestContent) : null;
|
||||
}
|
||||
|
||||
if (feViteManifest != null) {
|
||||
this.frontendViteFiles = this.collectViteAssetFiles(feViteManifest);
|
||||
}
|
||||
|
||||
if (bootJs != null) {
|
||||
this.frontendBootloaderJs = bootJs;
|
||||
}
|
||||
|
|
@ -62,6 +149,10 @@ export class HtmlTemplateService {
|
|||
this.frontendBootloaderCss = bootCss;
|
||||
}
|
||||
|
||||
if (embedFeViteManifest != null) {
|
||||
this.frontendEmbedViteFiles = this.collectViteAssetFiles(embedFeViteManifest);
|
||||
}
|
||||
|
||||
if (embedBootJs != null) {
|
||||
this.frontendEmbedBootloaderJs = embedBootJs;
|
||||
}
|
||||
|
|
@ -73,7 +164,7 @@ export class HtmlTemplateService {
|
|||
|
||||
@bindThis
|
||||
public async getCommonData(): Promise<CommonData> {
|
||||
await this.prepareFrontendBootloaders();
|
||||
await this.prepareFrontendAssets();
|
||||
|
||||
return {
|
||||
version: this.config.version,
|
||||
|
|
@ -90,8 +181,10 @@ export class HtmlTemplateService {
|
|||
metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(this.meta)),
|
||||
now: Date.now(),
|
||||
federationEnabled: this.meta.federation !== 'none',
|
||||
frontendViteFiles: this.frontendViteFiles,
|
||||
frontendBootloaderJs: this.frontendBootloaderJs,
|
||||
frontendBootloaderCss: this.frontendBootloaderCss,
|
||||
frontendEmbedViteFiles: this.frontendEmbedViteFiles,
|
||||
frontendEmbedBootloaderJs: this.frontendEmbedBootloaderJs,
|
||||
frontendEmbedBootloaderCss: this.frontendEmbedBootloaderCss,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@ export type MinimumCommonData = {
|
|||
config: Config;
|
||||
};
|
||||
|
||||
export type ViteFiles = {
|
||||
entryJs: string | null;
|
||||
css: string[];
|
||||
modulePreloads: string[];
|
||||
};
|
||||
|
||||
export type CommonData = MinimumCommonData & {
|
||||
langs: string[];
|
||||
instanceName: string;
|
||||
|
|
@ -36,8 +42,10 @@ export type CommonData = MinimumCommonData & {
|
|||
instanceUrl: string;
|
||||
now: number;
|
||||
federationEnabled: boolean;
|
||||
frontendViteFiles: ViteFiles | null;
|
||||
frontendBootloaderJs: string | null;
|
||||
frontendBootloaderCss: string | null;
|
||||
frontendEmbedViteFiles: ViteFiles | null;
|
||||
frontendEmbedBootloaderJs: string | null;
|
||||
frontendEmbedBootloaderCss: string | null;
|
||||
metaJson?: string;
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ export function BaseEmbed(props: PropsWithChildren<CommonProps<{
|
|||
<link rel="icon" href={props.icon ?? '/favicon.ico'} />
|
||||
<link rel="apple-touch-icon" href={props.appleTouchIcon ?? '/apple-touch-icon.png'} />
|
||||
|
||||
{!props.config.frontendEmbedManifestExists ? <script type="module" src="/embed_vite/@vite/client"></script> : null}
|
||||
{props.frontendEmbedViteFiles == null ? <script type="module" src="/embed_vite/@vite/client"></script> : null}
|
||||
|
||||
{props.config.frontendEmbedEntry.css != null ? props.config.frontendEmbedEntry.css.map((href) => (
|
||||
{(props.frontendEmbedViteFiles?.css ?? []).map((href) => (
|
||||
<link rel="stylesheet" href={`/embed_vite/${href}`} />
|
||||
)) : null}
|
||||
))}
|
||||
|
||||
{props.titleSlot ?? <title safe>{props.title || 'Misskey'}</title>}
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ export function BaseEmbed(props: PropsWithChildren<CommonProps<{
|
|||
|
||||
<script>
|
||||
const VERSION = '{props.version}';
|
||||
const CLIENT_ENTRY = {JSON.stringify(props.config.frontendEmbedEntry.file)};
|
||||
const CLIENT_ENTRY = {JSON.stringify(props.frontendEmbedViteFiles?.entryJs ?? null)};
|
||||
const LANGS = {JSON.stringify(props.langs)};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ export function Layout(props: PropsWithChildren<CommonProps<{
|
|||
{props.infoImageUrl != null ? <link rel="prefetch" as="image" href={props.infoImageUrl} /> : null}
|
||||
{props.notFoundImageUrl != null ? <link rel="prefetch" as="image" href={props.notFoundImageUrl} /> : null}
|
||||
|
||||
{!props.config.frontendManifestExists ? <script type="module" src="/vite/@vite/client"></script> : null}
|
||||
{props.frontendViteFiles == null ? <script type="module" src="/vite/@vite/client"></script> : null}
|
||||
|
||||
{props.config.frontendEntry.css != null ? props.config.frontendEntry.css.map((href) => (
|
||||
{(props.frontendViteFiles?.css ?? []).map((href) => (
|
||||
<link rel="stylesheet" href={`/vite/${href}`} />
|
||||
)) : null}
|
||||
))}
|
||||
|
||||
{props.titleSlot ?? <title safe>{props.title || 'Misskey'}</title>}
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ export function Layout(props: PropsWithChildren<CommonProps<{
|
|||
|
||||
<script>
|
||||
const VERSION = '{props.version}';
|
||||
const CLIENT_ENTRY = {JSON.stringify(props.config.frontendEntry.file)};
|
||||
const CLIENT_ENTRY = {JSON.stringify(props.frontendViteFiles?.entryJs ?? null)};
|
||||
const LANGS = {JSON.stringify(props.langs)};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
services:
|
||||
nginx:
|
||||
image: nginx:1.27
|
||||
image: nginx:1.29
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./certificates/rootCA.crt
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/estree": "1.0.8",
|
||||
"@types/node": "24.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@types/node": "24.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"rollup": "4.59.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
"@rollup/plugin-replace": "6.0.3",
|
||||
"@rollup/pluginutils": "5.3.0",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"@vitejs/plugin-vue": "6.0.4",
|
||||
"@vitejs/plugin-vue": "6.0.5",
|
||||
"buraha": "0.0.1",
|
||||
"estree-walker": "3.0.3",
|
||||
"frontend-shared": "workspace:*",
|
||||
|
|
@ -26,12 +26,12 @@
|
|||
"misskey-js": "workspace:*",
|
||||
"punycode.js": "2.3.1",
|
||||
"rollup": "4.59.0",
|
||||
"sass": "1.97.3",
|
||||
"sass": "1.98.0",
|
||||
"shiki": "3.23.0",
|
||||
"tinycolor2": "1.6.0",
|
||||
"uuid": "13.0.0",
|
||||
"vite": "7.3.1",
|
||||
"vue": "3.5.29"
|
||||
"vue": "3.5.30"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@misskey-dev/summaly": "5.2.5",
|
||||
|
|
@ -39,19 +39,19 @@
|
|||
"@testing-library/vue": "8.1.0",
|
||||
"@types/estree": "1.0.8",
|
||||
"@types/micromatch": "4.0.10",
|
||||
"@types/node": "24.11.0",
|
||||
"@types/node": "24.12.0",
|
||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@vitest/coverage-v8": "4.0.18",
|
||||
"@vue/runtime-core": "3.5.29",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"@vitest/coverage-v8": "4.1.0",
|
||||
"@vue/runtime-core": "3.5.30",
|
||||
"acorn": "8.16.0",
|
||||
"cross-env": "10.1.0",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-vue": "10.8.0",
|
||||
"happy-dom": "20.7.0",
|
||||
"happy-dom": "20.8.4",
|
||||
"intersection-observer": "0.12.2",
|
||||
"micromatch": "4.0.8",
|
||||
"msw": "2.12.10",
|
||||
|
|
|
|||
|
|
@ -79,3 +79,9 @@ export const MFM_PARAMS: Record<typeof MFM_TAGS[number], string[]> = {
|
|||
ruby: [],
|
||||
unixtime: [],
|
||||
};
|
||||
|
||||
/**
|
||||
* デフォルトの絵文字。UIの演出などでも使用されるため空にしてはいけない
|
||||
* (絵文字パレットのデフォルト絵文字を空にする等の場合は、preferenceのdefinition側の値を空にすること)
|
||||
*/
|
||||
export const DEFAULT_EMOJIS = ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'];
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@
|
|||
"lint": "pnpm typecheck && pnpm eslint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"esbuild": "0.27.3",
|
||||
"@types/node": "24.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"esbuild": "0.27.4",
|
||||
"eslint-plugin-vue": "10.8.0",
|
||||
"nodemon": "3.1.14",
|
||||
"vue-eslint-parser": "10.4.0"
|
||||
|
|
@ -35,6 +35,6 @@
|
|||
"dependencies": {
|
||||
"i18n": "workspace:*",
|
||||
"misskey-js": "workspace:*",
|
||||
"vue": "3.5.29"
|
||||
"vue": "3.5.30"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@
|
|||
"@rollup/plugin-json": "6.1.0",
|
||||
"@rollup/plugin-replace": "6.0.3",
|
||||
"@rollup/pluginutils": "5.3.0",
|
||||
"@sentry/vue": "10.40.0",
|
||||
"@sentry/vue": "10.43.0",
|
||||
"@syuilo/aiscript": "1.2.1",
|
||||
"@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"@vitejs/plugin-vue": "6.0.4",
|
||||
"@vitejs/plugin-vue": "6.0.5",
|
||||
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.16",
|
||||
"analytics": "0.8.19",
|
||||
"broadcast-channel": "7.3.0",
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
"date-fns": "4.1.0",
|
||||
"eventemitter3": "5.0.4",
|
||||
"execa": "9.6.1",
|
||||
"exifreader": "4.36.2",
|
||||
"exifreader": "4.37.0",
|
||||
"frontend-shared": "workspace:*",
|
||||
"i18n": "workspace:*",
|
||||
"icons-subsetter": "workspace:*",
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
"is-file-animated": "1.0.2",
|
||||
"json5": "2.2.3",
|
||||
"matter-js": "0.20.0",
|
||||
"mediabunny": "1.35.1",
|
||||
"mediabunny": "1.39.2",
|
||||
"mfm-js": "0.25.0",
|
||||
"misskey-bubble-game": "workspace:*",
|
||||
"misskey-js": "workspace:*",
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
"qr-scanner": "1.4.2",
|
||||
"rollup": "4.59.0",
|
||||
"sanitize-html": "2.17.1",
|
||||
"sass": "1.97.3",
|
||||
"sass": "1.98.0",
|
||||
"shiki": "3.23.0",
|
||||
"textarea-caret": "3.1.0",
|
||||
"three": "0.183.2",
|
||||
|
|
@ -74,28 +74,28 @@
|
|||
"tinycolor2": "1.6.0",
|
||||
"v-code-diff": "1.13.1",
|
||||
"vite": "7.3.1",
|
||||
"vue": "3.5.29",
|
||||
"vue": "3.5.30",
|
||||
"wanakana": "5.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@misskey-dev/summaly": "5.2.5",
|
||||
"@storybook/addon-essentials": "8.6.17",
|
||||
"@storybook/addon-interactions": "8.6.17",
|
||||
"@storybook/addon-links": "10.2.13",
|
||||
"@storybook/addon-mdx-gfm": "8.6.17",
|
||||
"@storybook/addon-storysource": "8.6.17",
|
||||
"@storybook/blocks": "8.6.17",
|
||||
"@storybook/components": "8.6.17",
|
||||
"@storybook/core-events": "8.6.17",
|
||||
"@storybook/manager-api": "8.6.17",
|
||||
"@storybook/preview-api": "8.6.17",
|
||||
"@storybook/react": "10.2.13",
|
||||
"@storybook/react-vite": "10.2.13",
|
||||
"@storybook/test": "8.6.17",
|
||||
"@storybook/theming": "8.6.17",
|
||||
"@storybook/types": "8.6.17",
|
||||
"@storybook/vue3": "10.2.13",
|
||||
"@storybook/vue3-vite": "10.2.13",
|
||||
"@storybook/addon-essentials": "8.6.18",
|
||||
"@storybook/addon-interactions": "8.6.18",
|
||||
"@storybook/addon-links": "10.2.17",
|
||||
"@storybook/addon-mdx-gfm": "8.6.18",
|
||||
"@storybook/addon-storysource": "8.6.18",
|
||||
"@storybook/blocks": "8.6.18",
|
||||
"@storybook/components": "8.6.18",
|
||||
"@storybook/core-events": "8.6.18",
|
||||
"@storybook/manager-api": "8.6.18",
|
||||
"@storybook/preview-api": "8.6.18",
|
||||
"@storybook/react": "10.2.17",
|
||||
"@storybook/react-vite": "10.2.17",
|
||||
"@storybook/test": "8.6.18",
|
||||
"@storybook/theming": "8.6.18",
|
||||
"@storybook/types": "8.6.18",
|
||||
"@storybook/vue3": "10.2.17",
|
||||
"@storybook/vue3-vite": "10.2.17",
|
||||
"@tabler/icons-webfont": "3.35.0",
|
||||
"@testing-library/vue": "8.1.0",
|
||||
"@types/canvas-confetti": "1.9.0",
|
||||
|
|
@ -103,17 +103,17 @@
|
|||
"@types/insert-text-at-cursor": "0.3.2",
|
||||
"@types/matter-js": "0.20.2",
|
||||
"@types/micromatch": "4.0.10",
|
||||
"@types/node": "24.11.0",
|
||||
"@types/node": "24.12.0",
|
||||
"@types/punycode.js": "npm:@types/punycode@2.1.4",
|
||||
"@types/sanitize-html": "2.16.0",
|
||||
"@types/sanitize-html": "2.16.1",
|
||||
"@types/seedrandom": "3.0.8",
|
||||
"@types/textarea-caret": "3.0.4",
|
||||
"@types/throttle-debounce": "5.0.2",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@vitest/coverage-v8": "4.0.18",
|
||||
"@vue/compiler-core": "3.5.29",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"@vitest/coverage-v8": "4.1.0",
|
||||
"@vue/compiler-core": "3.5.30",
|
||||
"acorn": "8.16.0",
|
||||
"astring": "1.9.0",
|
||||
"cross-env": "10.1.0",
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-vue": "10.8.0",
|
||||
"estree-walker": "3.0.3",
|
||||
"happy-dom": "20.7.0",
|
||||
"happy-dom": "20.8.4",
|
||||
"intersection-observer": "0.12.2",
|
||||
"magic-string": "0.30.21",
|
||||
"micromatch": "4.0.8",
|
||||
|
|
@ -134,12 +134,12 @@
|
|||
"react-dom": "19.2.4",
|
||||
"seedrandom": "3.0.5",
|
||||
"start-server-and-test": "2.1.5",
|
||||
"storybook": "10.2.13",
|
||||
"storybook": "10.2.17",
|
||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||
"tsx": "4.21.0",
|
||||
"vite-plugin-glsl": "1.5.5",
|
||||
"vite-plugin-turbosnap": "1.0.3",
|
||||
"vitest": "4.0.18",
|
||||
"vitest": "4.1.0",
|
||||
"vitest-fetch-mock": "0.4.5",
|
||||
"vue-component-type-helpers": "3.2.5",
|
||||
"vue-eslint-parser": "10.4.0",
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<MkWindow
|
||||
ref="window"
|
||||
:initialWidth="800"
|
||||
:initialHeight="500"
|
||||
:canResize="true"
|
||||
@closed="emit('closed')"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<MkWindow
|
||||
ref="windowEl"
|
||||
:initialWidth="500"
|
||||
:initialHeight="500"
|
||||
:canResize="true"
|
||||
:closeButton="true"
|
||||
:buttonsLeft="buttonsLeft"
|
||||
|
|
|
|||
|
|
@ -106,7 +106,9 @@ async function toggleReaction() {
|
|||
reaction: props.reaction,
|
||||
}).then(() => {
|
||||
const emoji = customEmojisMap.get(emojiName.value);
|
||||
if (emoji == null) return;
|
||||
if (emoji == null && getUnicodeEmojiOrNull(props.reaction) == null) {
|
||||
return;
|
||||
}
|
||||
noteEvents.emit(`reacted:${props.noteId}`, {
|
||||
userId: me.id,
|
||||
reaction: props.reaction,
|
||||
|
|
@ -138,7 +140,9 @@ async function toggleReaction() {
|
|||
reaction: props.reaction,
|
||||
}).then(() => {
|
||||
const emoji = customEmojisMap.get(emojiName.value);
|
||||
if (emoji == null) return;
|
||||
if (emoji == null && getUnicodeEmojiOrNull(props.reaction) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
noteEvents.emit(`reacted:${props.noteId}`, {
|
||||
userId: me.id,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@afterLeave="emit('closed')"
|
||||
>
|
||||
<div v-if="showing" ref="rootEl" :class="[$style.root, { [$style.maximized]: maximized }]">
|
||||
<div :class="$style.body" class="_shadow" @mousedown="onBodyMousedown" @keydown="onKeydown">
|
||||
<div :class="$style.body" class="_shadow" @pointerdown="onBodyPointerDown" @keydown="onKeydown">
|
||||
<div :class="[$style.header, { [$style.mini]: mini }]" @contextmenu.prevent.stop="onContextmenu">
|
||||
<span :class="$style.headerLeft">
|
||||
<template v-if="!minimized">
|
||||
|
|
@ -106,8 +106,8 @@ function capturePointer(evt: PointerEvent) {
|
|||
}
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
initialWidth: number;
|
||||
initialHeight: number | null;
|
||||
initialWidth?: number | null;
|
||||
initialHeight?: number | null;
|
||||
canResize?: boolean;
|
||||
closeButton?: boolean;
|
||||
mini?: boolean;
|
||||
|
|
@ -116,7 +116,7 @@ const props = withDefaults(defineProps<{
|
|||
buttonsLeft?: WindowButton[];
|
||||
buttonsRight?: WindowButton[];
|
||||
}>(), {
|
||||
initialWidth: 400,
|
||||
initialWidth: null,
|
||||
initialHeight: null,
|
||||
canResize: false,
|
||||
closeButton: true,
|
||||
|
|
@ -131,6 +131,12 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const INITIAL_WINDOW_WIDTH_RATIO = 0.5;
|
||||
const INITIAL_WINDOW_HEIGHT_RATIO = 0.75;
|
||||
const INITIAL_WINDOW_WIDTH_MIN = 400; // スクリーンの最小幅に合わせるのはapplyTransormWidthの担当
|
||||
const INITIAL_WINDOW_WIDTH_MAX = 1000; // 画面幅いっぱいに広がるのを防止するための最大幅
|
||||
const INITIAL_WINDOW_HEIGHT_MIN = 500; // スクリーンの最小幅に合わせるのはapplyTransormHeightの担当
|
||||
|
||||
provide('inWindow', true);
|
||||
|
||||
const rootEl = useTemplateRef('rootEl');
|
||||
|
|
@ -216,7 +222,7 @@ function unMinimize() {
|
|||
if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px';
|
||||
}
|
||||
|
||||
function onBodyMousedown() {
|
||||
function onBodyPointerDown() {
|
||||
top();
|
||||
}
|
||||
|
||||
|
|
@ -484,8 +490,14 @@ function onBrowserResize() {
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
applyTransformWidth(props.initialWidth);
|
||||
if (props.initialHeight) applyTransformHeight(props.initialHeight);
|
||||
let initialWidth = props.initialWidth;
|
||||
let initialHeight = props.initialHeight;
|
||||
|
||||
if (initialWidth == null) initialWidth = Math.min(Math.max(Math.round(window.innerWidth * INITIAL_WINDOW_WIDTH_RATIO), INITIAL_WINDOW_WIDTH_MIN), INITIAL_WINDOW_WIDTH_MAX);
|
||||
if (initialHeight == null) initialHeight = Math.max(Math.round(window.innerHeight * INITIAL_WINDOW_HEIGHT_RATIO), INITIAL_WINDOW_HEIGHT_MIN);
|
||||
|
||||
applyTransformWidth(initialWidth);
|
||||
applyTransformHeight(initialHeight);
|
||||
|
||||
if (rootEl.value) {
|
||||
applyTransformTop((window.innerHeight / 2) - (rootEl.value.offsetHeight / 2));
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ import { definePage } from '@/page.js';
|
|||
import { claimAchievement, claimedAchievements } from '@/utility/achievements.js';
|
||||
import { $i } from '@/i.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
import { DEFAULT_EMOJIS } from '@@/js/const.js';
|
||||
|
||||
const patronsWithIcon = [{
|
||||
name: 'カイヤン',
|
||||
|
|
@ -429,7 +430,12 @@ const containerEl = useTemplateRef('containerEl');
|
|||
|
||||
function iconLoaded() {
|
||||
if (containerEl.value == null) return;
|
||||
const emojis = prefer.s.emojiPalettes[0].emojis;
|
||||
const emojis = prefer.s.emojiPalettes[0]?.emojis ?? [];
|
||||
|
||||
if (emojis.length < DEFAULT_EMOJIS.length) {
|
||||
emojis.push(...DEFAULT_EMOJIS.slice(0, DEFAULT_EMOJIS.length - emojis.length));
|
||||
}
|
||||
|
||||
const containerWidth = containerEl.value.offsetWidth;
|
||||
for (let i = 0; i < 32; i++) {
|
||||
easterEggEmojis.value.push({
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { hemisphere } from '@@/js/intl-const.js';
|
||||
import { DEFAULT_EMOJIS } from '@@/js/const.js';
|
||||
import { prefersReducedMotion } from '@@/js/config.js';
|
||||
import { definePreferences } from './manager.js';
|
||||
import type { Theme } from '@/theme.js';
|
||||
|
|
@ -103,7 +104,7 @@ export const PREF_DEF = definePreferences({
|
|||
default: () => [{
|
||||
id: genId(),
|
||||
name: '',
|
||||
emojis: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'],
|
||||
emojis: DEFAULT_EMOJIS,
|
||||
}] as {
|
||||
id: string;
|
||||
name: string;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ const float PI = 3.141592653589793;
|
|||
const float TWO_PI = 6.283185307179586;
|
||||
const float HALF_PI = 1.5707963267948966;
|
||||
|
||||
const float goldenAngle = 2.39996323;
|
||||
const int sampleCount = 256;
|
||||
const float sampleCountF = float(sampleCount);
|
||||
|
||||
in vec2 in_uv;
|
||||
uniform sampler2D in_texture;
|
||||
uniform vec2 in_resolution;
|
||||
|
|
@ -18,7 +22,6 @@ uniform vec2 u_scale;
|
|||
uniform bool u_ellipse;
|
||||
uniform float u_angle;
|
||||
uniform float u_radius;
|
||||
uniform int u_samples;
|
||||
out vec4 out_color;
|
||||
|
||||
float rand(vec2 value) {
|
||||
|
|
@ -51,17 +54,7 @@ void main() {
|
|||
|
||||
vec4 result = vec4(0.0);
|
||||
float totalSamples = 0.0;
|
||||
|
||||
// Make blur radius resolution-independent by using a percentage of image size
|
||||
float referenceSize = min(in_resolution.x, in_resolution.y);
|
||||
float normalizedRadius = u_radius / 100.0;
|
||||
float radiusPx = normalizedRadius * referenceSize;
|
||||
vec2 texelSize = 1.0 / in_resolution;
|
||||
|
||||
int sampleCount = max(u_samples, 1);
|
||||
float sampleCountF = float(sampleCount);
|
||||
float jitter = rand(in_uv * in_resolution);
|
||||
float goldenAngle = 2.39996323;
|
||||
float jitter = rand(in_uv);
|
||||
|
||||
// Sample in a circular pattern to avoid axis-aligned artifacts
|
||||
for (int i = 0; i < sampleCount; i++) {
|
||||
|
|
@ -69,15 +62,11 @@ void main() {
|
|||
float radius = sqrt((fi + 0.5) / sampleCountF);
|
||||
float theta = (fi + jitter) * goldenAngle;
|
||||
vec2 direction = vec2(cos(theta), sin(theta));
|
||||
vec2 offset = direction * (radiusPx * radius) * texelSize;
|
||||
vec2 sampleUV = in_uv + offset;
|
||||
|
||||
if (sampleUV.x >= 0.0 && sampleUV.x <= 1.0 && sampleUV.y >= 0.0 && sampleUV.y <= 1.0) {
|
||||
float weight = exp(-radius * radius * 4.0);
|
||||
result += texture(in_texture, sampleUV) * weight;
|
||||
totalSamples += weight;
|
||||
}
|
||||
vec2 offset = direction * (u_radius * radius);
|
||||
float weight = exp(-radius * radius * 4.0);
|
||||
result += texture(in_texture, in_uv + offset) * weight;
|
||||
totalSamples += weight;
|
||||
}
|
||||
|
||||
out_color = totalSamples > 0.0 ? result / totalSamples : texture(in_texture, in_uv);
|
||||
out_color = result / totalSamples;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ export const fn = defineImageCompositorFunction<{
|
|||
gl.uniform1i(u.ellipse, params.ellipse ? 1 : 0);
|
||||
gl.uniform1f(u.angle, params.angle / 2);
|
||||
gl.uniform1f(u.radius, params.radius);
|
||||
gl.uniform1i(u.samples, 256);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -84,10 +83,10 @@ export const uiDefinition = {
|
|||
radius: {
|
||||
label: i18n.ts._imageEffector._fxProps.strength,
|
||||
type: 'number',
|
||||
default: 10.0,
|
||||
default: 0.15,
|
||||
min: 0.0,
|
||||
max: 20.0,
|
||||
step: 0.5,
|
||||
max: 0.3,
|
||||
step: 0.01,
|
||||
},
|
||||
},
|
||||
} satisfies ImageEffectorUiDefinition<typeof fn>;
|
||||
|
|
|
|||
|
|
@ -14,12 +14,15 @@ uniform sampler2D in_texture;
|
|||
uniform vec2 in_resolution;
|
||||
uniform vec2 u_pos;
|
||||
uniform float u_frequency;
|
||||
uniform bool u_thresholdEnabled;
|
||||
uniform float u_threshold;
|
||||
uniform float u_outlineThickness;
|
||||
uniform float u_maskSize;
|
||||
uniform bool u_black;
|
||||
out vec4 out_color;
|
||||
|
||||
float remap(float value, float inputMin, float inputMax, float outputMin, float outputMax) {
|
||||
return outputMin + (outputMax - outputMin) * ((value - inputMin) / (inputMax - inputMin));
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 in_color = texture(in_texture, in_uv);
|
||||
vec2 centeredUv = (in_uv - vec2(0.5, 0.5));
|
||||
|
|
@ -33,16 +36,19 @@ void main() {
|
|||
float noiseY = (noiseUV.y + seed) * u_frequency;
|
||||
float noise = (1.0 + snoise(vec3(noiseX, noiseY, time))) / 2.0;
|
||||
|
||||
float t = noise;
|
||||
if (u_thresholdEnabled) t = t < u_threshold ? 1.0 : 0.0;
|
||||
if (noise < u_threshold) {
|
||||
out_color = in_color;
|
||||
} else {
|
||||
float n = remap(noise, u_threshold, 1.0, 0.0, 1.0);
|
||||
|
||||
// TODO: マスクの形自体も揺らぎを与える
|
||||
float d = distance(uv * vec2(2.0, 2.0), u_pos * vec2(2.0, 2.0));
|
||||
float mask = d < u_maskSize ? 0.0 : ((d - u_maskSize) * (1.0 + (u_maskSize * 2.0)));
|
||||
out_color = vec4(
|
||||
mix(in_color.r, u_black ? 0.0 : 1.0, t * mask),
|
||||
mix(in_color.g, u_black ? 0.0 : 1.0, t * mask),
|
||||
mix(in_color.b, u_black ? 0.0 : 1.0, t * mask),
|
||||
in_color.a
|
||||
);
|
||||
// TODO: マスクの形自体も揺らぎを与える
|
||||
float d = distance(uv * vec2(2.0, 2.0), u_pos * vec2(2.0, 2.0));
|
||||
float mask = d < u_maskSize ? 0.0 : ((d - u_maskSize) * (1.0 + (u_maskSize * 2.0)));
|
||||
out_color = vec4(
|
||||
mix(in_color.r, n < u_outlineThickness ? 0.0 : 1.0, mask),
|
||||
mix(in_color.g, n < u_outlineThickness ? 0.0 : 1.0, mask),
|
||||
mix(in_color.b, n < u_outlineThickness ? 0.0 : 1.0, mask),
|
||||
in_color.a
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,20 +12,17 @@ export const fn = defineImageCompositorFunction<{
|
|||
x: number;
|
||||
y: number;
|
||||
frequency: number;
|
||||
smoothing: boolean;
|
||||
threshold: number;
|
||||
density: number;
|
||||
outlineThickness: number;
|
||||
maskSize: number;
|
||||
black: boolean;
|
||||
}>({
|
||||
shader,
|
||||
main: ({ gl, u, params }) => {
|
||||
gl.uniform2f(u.pos, params.x / 2, params.y / 2);
|
||||
gl.uniform1f(u.frequency, params.frequency * params.frequency);
|
||||
// thresholdの調整が有効な間はsmoothingが利用できない
|
||||
gl.uniform1i(u.thresholdEnabled, params.smoothing ? 0 : 1);
|
||||
gl.uniform1f(u.threshold, params.threshold);
|
||||
gl.uniform1f(u.threshold, 1.0 - params.density);
|
||||
gl.uniform1f(u.outlineThickness, params.outlineThickness);
|
||||
gl.uniform1f(u.maskSize, params.maskSize);
|
||||
gl.uniform1i(u.black, params.black ? 1 : 0);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -56,20 +53,22 @@ export const uiDefinition = {
|
|||
max: 15.0,
|
||||
step: 0.1,
|
||||
},
|
||||
smoothing: {
|
||||
label: i18n.ts._imageEffector._fxProps.zoomLinesSmoothing,
|
||||
caption: i18n.ts._imageEffector._fxProps.zoomLinesSmoothingDescription,
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
threshold: {
|
||||
label: i18n.ts._imageEffector._fxProps.zoomLinesThreshold,
|
||||
density: {
|
||||
label: i18n.ts._imageEffector._fxProps.density,
|
||||
type: 'number',
|
||||
default: 0.5,
|
||||
min: 0.0,
|
||||
max: 1.0,
|
||||
step: 0.01,
|
||||
},
|
||||
outlineThickness: {
|
||||
label: i18n.ts._imageEffector._fxProps.zoomLinesOutlineThickness,
|
||||
type: 'number',
|
||||
default: 0.25,
|
||||
min: 0.0,
|
||||
max: 1.0,
|
||||
step: 0.01,
|
||||
},
|
||||
maskSize: {
|
||||
label: i18n.ts._imageEffector._fxProps.zoomLinesMaskSize,
|
||||
type: 'number',
|
||||
|
|
@ -78,10 +77,5 @@ export const uiDefinition = {
|
|||
max: 1.0,
|
||||
step: 0.01,
|
||||
},
|
||||
black: {
|
||||
label: i18n.ts._imageEffector._fxProps.zoomLinesBlack,
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
} satisfies ImageEffectorUiDefinition<typeof fn>;
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@
|
|||
],
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/node": "24.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@types/node": "24.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"chokidar": "5.0.0",
|
||||
"esbuild": "0.27.3",
|
||||
"esbuild": "0.27.4",
|
||||
"execa": "9.6.1",
|
||||
"nodemon": "3.1.14",
|
||||
"tsx": "4.21.0"
|
||||
|
|
|
|||
|
|
@ -13109,25 +13109,17 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"centerY": string;
|
||||
/**
|
||||
* スムージング
|
||||
* 密度
|
||||
*/
|
||||
"zoomLinesSmoothing": string;
|
||||
"density": string;
|
||||
/**
|
||||
* スムージングと集中線の幅の設定は併用できません。
|
||||
* 線の影の太さ
|
||||
*/
|
||||
"zoomLinesSmoothingDescription": string;
|
||||
/**
|
||||
* 集中線の幅
|
||||
*/
|
||||
"zoomLinesThreshold": string;
|
||||
"zoomLinesOutlineThickness": string;
|
||||
/**
|
||||
* 中心径
|
||||
*/
|
||||
"zoomLinesMaskSize": string;
|
||||
/**
|
||||
* 黒色にする
|
||||
*/
|
||||
"zoomLinesBlack": string;
|
||||
/**
|
||||
* 円形
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@
|
|||
"lint": "pnpm typecheck && pnpm eslint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.11.0",
|
||||
"@types/node": "24.12.0",
|
||||
"@types/wawoff2": "1.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1"
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tabler/icons-webfont": "3.35.0",
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/matter-js": "0.20.2",
|
||||
"@types/node": "24.11.0",
|
||||
"@types/node": "24.12.0",
|
||||
"@types/seedrandom": "3.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"esbuild": "0.27.3",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"esbuild": "0.27.4",
|
||||
"execa": "9.6.1",
|
||||
"nodemon": "3.1.14"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@readme/openapi-parser": "5.5.0",
|
||||
"@types/node": "24.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@types/node": "24.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"openapi-types": "12.1.3",
|
||||
"openapi-typescript": "7.13.0",
|
||||
"ts-case-convert": "2.1.0",
|
||||
"tsx": "4.21.0",
|
||||
"eslint": "9.39.3"
|
||||
"eslint": "9.39.4"
|
||||
},
|
||||
"files": [
|
||||
"built"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"type": "module",
|
||||
"name": "misskey-js",
|
||||
"version": "2026.3.1",
|
||||
"version": "2026.3.2",
|
||||
"description": "Misskey SDK for JavaScript",
|
||||
"license": "MIT",
|
||||
"main": "./built/index.js",
|
||||
|
|
@ -37,17 +37,17 @@
|
|||
"directory": "packages/misskey-js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/api-extractor": "7.57.6",
|
||||
"@types/node": "24.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@vitest/coverage-v8": "4.0.18",
|
||||
"esbuild": "0.27.3",
|
||||
"@microsoft/api-extractor": "7.57.7",
|
||||
"@types/node": "24.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"@vitest/coverage-v8": "4.1.0",
|
||||
"esbuild": "0.27.4",
|
||||
"execa": "9.6.1",
|
||||
"ncp": "2.0.0",
|
||||
"nodemon": "3.1.14",
|
||||
"tsd": "0.33.0",
|
||||
"vitest": "4.0.18",
|
||||
"vitest": "4.1.0",
|
||||
"vitest-websocket-mock": "0.5.0"
|
||||
},
|
||||
"files": [
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@
|
|||
"lint": "pnpm typecheck && pnpm eslint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "24.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"esbuild": "0.27.3",
|
||||
"@types/node": "24.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.57.0",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"esbuild": "0.27.4",
|
||||
"execa": "9.6.1",
|
||||
"nodemon": "3.1.14"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"i18n": "workspace:*",
|
||||
"esbuild": "0.27.3",
|
||||
"esbuild": "0.27.4",
|
||||
"idb-keyval": "6.2.2",
|
||||
"misskey-js": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.57.0",
|
||||
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.74",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"nodemon": "3.1.14"
|
||||
|
|
|
|||
3978
pnpm-lock.yaml
generated
3978
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
210
scripts/changelog-checker/package-lock.json
generated
210
scripts/changelog-checker/package-lock.json
generated
|
|
@ -9,8 +9,8 @@
|
|||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@types/mdast": "4.0.4",
|
||||
"@types/node": "24.11.0",
|
||||
"@vitest/coverage-v8": "4.0.18",
|
||||
"@types/node": "24.12.0",
|
||||
"@vitest/coverage-v8": "4.1.0",
|
||||
"mdast-util-to-string": "4.0.0",
|
||||
"remark": "15.0.1",
|
||||
"remark-parse": "11.0.0",
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
"unified": "11.0.5",
|
||||
"vite": "7.3.1",
|
||||
"vite-node": "5.3.0",
|
||||
"vitest": "4.0.18"
|
||||
"vitest": "4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
|
|
@ -42,13 +42,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
|
||||
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
|
||||
"version": "7.29.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
|
||||
"integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.28.5"
|
||||
"@babel/types": "^7.29.0"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
|
|
@ -58,9 +58,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
|
||||
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
|
||||
"integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
@ -917,9 +917,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.11.0.tgz",
|
||||
"integrity": "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==",
|
||||
"version": "24.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
|
||||
"integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
@ -933,29 +933,29 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@vitest/coverage-v8": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.18.tgz",
|
||||
"integrity": "sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.0.tgz",
|
||||
"integrity": "sha512-nDWulKeik2bL2Va/Wl4x7DLuTKAXa906iRFooIRPR+huHkcvp9QDkPQ2RJdmjOFrqOqvNfoSQLF68deE3xC3CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@bcoe/v8-coverage": "^1.0.2",
|
||||
"@vitest/utils": "4.0.18",
|
||||
"ast-v8-to-istanbul": "^0.3.10",
|
||||
"@vitest/utils": "4.1.0",
|
||||
"ast-v8-to-istanbul": "^1.0.0",
|
||||
"istanbul-lib-coverage": "^3.2.2",
|
||||
"istanbul-lib-report": "^3.0.1",
|
||||
"istanbul-reports": "^3.2.0",
|
||||
"magicast": "^0.5.1",
|
||||
"magicast": "^0.5.2",
|
||||
"obug": "^2.1.1",
|
||||
"std-env": "^3.10.0",
|
||||
"std-env": "^4.0.0-rc.1",
|
||||
"tinyrainbow": "^3.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vitest/browser": "4.0.18",
|
||||
"vitest": "4.0.18"
|
||||
"@vitest/browser": "4.1.0",
|
||||
"vitest": "4.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vitest/browser": {
|
||||
|
|
@ -964,17 +964,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz",
|
||||
"integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz",
|
||||
"integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"@standard-schema/spec": "^1.1.0",
|
||||
"@types/chai": "^5.2.2",
|
||||
"@vitest/spy": "4.0.18",
|
||||
"@vitest/utils": "4.0.18",
|
||||
"chai": "^6.2.1",
|
||||
"@vitest/spy": "4.1.0",
|
||||
"@vitest/utils": "4.1.0",
|
||||
"chai": "^6.2.2",
|
||||
"tinyrainbow": "^3.0.3"
|
||||
},
|
||||
"funding": {
|
||||
|
|
@ -982,13 +982,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/mocker": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz",
|
||||
"integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz",
|
||||
"integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/spy": "4.0.18",
|
||||
"@vitest/spy": "4.1.0",
|
||||
"estree-walker": "^3.0.3",
|
||||
"magic-string": "^0.30.21"
|
||||
},
|
||||
|
|
@ -997,7 +997,7 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"msw": "^2.4.9",
|
||||
"vite": "^6.0.0 || ^7.0.0-0"
|
||||
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"msw": {
|
||||
|
|
@ -1009,9 +1009,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/pretty-format": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz",
|
||||
"integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz",
|
||||
"integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
@ -1022,13 +1022,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/runner": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz",
|
||||
"integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz",
|
||||
"integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/utils": "4.0.18",
|
||||
"@vitest/utils": "4.1.0",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"funding": {
|
||||
|
|
@ -1036,13 +1036,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/snapshot": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz",
|
||||
"integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz",
|
||||
"integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "4.0.18",
|
||||
"@vitest/pretty-format": "4.1.0",
|
||||
"@vitest/utils": "4.1.0",
|
||||
"magic-string": "^0.30.21",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
|
|
@ -1051,9 +1052,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/spy": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz",
|
||||
"integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz",
|
||||
"integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
|
|
@ -1061,13 +1062,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vitest/utils": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz",
|
||||
"integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz",
|
||||
"integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "4.0.18",
|
||||
"@vitest/pretty-format": "4.1.0",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"tinyrainbow": "^3.0.3"
|
||||
},
|
||||
"funding": {
|
||||
|
|
@ -1085,15 +1087,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ast-v8-to-istanbul": {
|
||||
"version": "0.3.10",
|
||||
"resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.10.tgz",
|
||||
"integrity": "sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz",
|
||||
"integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.31",
|
||||
"estree-walker": "^3.0.3",
|
||||
"js-tokens": "^9.0.1"
|
||||
"js-tokens": "^10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bail": {
|
||||
|
|
@ -1135,6 +1137,13 @@
|
|||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
|
|
@ -1189,9 +1198,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/es-module-lexer": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
|
||||
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz",
|
||||
"integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
@ -1361,9 +1370,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
|
||||
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz",
|
||||
"integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
@ -1400,14 +1409,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/magicast": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz",
|
||||
"integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==",
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz",
|
||||
"integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/types": "^7.28.5",
|
||||
"@babel/parser": "^7.29.0",
|
||||
"@babel/types": "^7.29.0",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
|
|
@ -2160,9 +2169,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/std-env": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
|
||||
"integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz",
|
||||
"integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
|
@ -2186,9 +2195,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tinyexec": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
|
||||
"integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz",
|
||||
"integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
|
@ -2213,9 +2222,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/tinyrainbow": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz",
|
||||
"integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz",
|
||||
"integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
|
@ -2455,39 +2464,32 @@
|
|||
"url": "https://opencollective.com/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/vite-node/node_modules/es-module-lexer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz",
|
||||
"integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vitest": {
|
||||
"version": "4.0.18",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz",
|
||||
"integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz",
|
||||
"integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/expect": "4.0.18",
|
||||
"@vitest/mocker": "4.0.18",
|
||||
"@vitest/pretty-format": "4.0.18",
|
||||
"@vitest/runner": "4.0.18",
|
||||
"@vitest/snapshot": "4.0.18",
|
||||
"@vitest/spy": "4.0.18",
|
||||
"@vitest/utils": "4.0.18",
|
||||
"es-module-lexer": "^1.7.0",
|
||||
"expect-type": "^1.2.2",
|
||||
"@vitest/expect": "4.1.0",
|
||||
"@vitest/mocker": "4.1.0",
|
||||
"@vitest/pretty-format": "4.1.0",
|
||||
"@vitest/runner": "4.1.0",
|
||||
"@vitest/snapshot": "4.1.0",
|
||||
"@vitest/spy": "4.1.0",
|
||||
"@vitest/utils": "4.1.0",
|
||||
"es-module-lexer": "^2.0.0",
|
||||
"expect-type": "^1.3.0",
|
||||
"magic-string": "^0.30.21",
|
||||
"obug": "^2.1.1",
|
||||
"pathe": "^2.0.3",
|
||||
"picomatch": "^4.0.3",
|
||||
"std-env": "^3.10.0",
|
||||
"std-env": "^4.0.0-rc.1",
|
||||
"tinybench": "^2.9.0",
|
||||
"tinyexec": "^1.0.2",
|
||||
"tinyglobby": "^0.2.15",
|
||||
"tinyrainbow": "^3.0.3",
|
||||
"vite": "^6.0.0 || ^7.0.0",
|
||||
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0",
|
||||
"why-is-node-running": "^2.3.0"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -2503,12 +2505,13 @@
|
|||
"@edge-runtime/vm": "*",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
|
||||
"@vitest/browser-playwright": "4.0.18",
|
||||
"@vitest/browser-preview": "4.0.18",
|
||||
"@vitest/browser-webdriverio": "4.0.18",
|
||||
"@vitest/ui": "4.0.18",
|
||||
"@vitest/browser-playwright": "4.1.0",
|
||||
"@vitest/browser-preview": "4.1.0",
|
||||
"@vitest/browser-webdriverio": "4.1.0",
|
||||
"@vitest/ui": "4.1.0",
|
||||
"happy-dom": "*",
|
||||
"jsdom": "*"
|
||||
"jsdom": "*",
|
||||
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@edge-runtime/vm": {
|
||||
|
|
@ -2537,6 +2540,9 @@
|
|||
},
|
||||
"jsdom": {
|
||||
"optional": true
|
||||
},
|
||||
"vite": {
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/mdast": "4.0.4",
|
||||
"@types/node": "24.11.0",
|
||||
"@vitest/coverage-v8": "4.0.18",
|
||||
"@types/node": "24.12.0",
|
||||
"@vitest/coverage-v8": "4.1.0",
|
||||
"mdast-util-to-string": "4.0.0",
|
||||
"remark": "15.0.1",
|
||||
"remark-parse": "11.0.0",
|
||||
|
|
@ -19,6 +19,6 @@
|
|||
"unified": "11.0.5",
|
||||
"vite": "7.3.1",
|
||||
"vite-node": "5.3.0",
|
||||
"vitest": "4.0.18"
|
||||
"vitest": "4.1.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue