Merge branch 'develop'

This commit is contained in:
syuilo 2022-07-13 21:59:47 +09:00
commit bce48dfee9
91 changed files with 1209 additions and 881 deletions

View File

@ -9,6 +9,15 @@
You should also include the user name that made the change.
-->
## 12.113.0 (2022/07/13)
### Improvements
- Support <plain> syntax for MFM
### Bugfixes
- Server: Fix crash at startup if TensorFlow is not supported @mei23
- Client: URLエンコードされたルーティングを修正
## 12.112.3 (2022/07/09)
### Improvements

View File

@ -804,6 +804,10 @@ oneDay: "يوم"
oneWeek: "أسبوع"
failedToFetchAccountInformation: "تعذر جلب معلومات الحساب"
file: "الملفات"
reverse: "اقلب"
colored: "ملوّن"
label: "التسمية"
localOnly: "المحلي فقط"
_emailUnavailable:
used: "هذا البريد الإلكتروني مستخدم"
format: "صيغة البريد الإلكتروني غير صالحة"

View File

@ -844,6 +844,10 @@ reflectMayTakeTime: "এটির কাজ দেখা যেতে কিছ
failedToFetchAccountInformation: "অ্যাকাউন্টের তথ্য উদ্ধার করা যায়নি"
rateLimitExceeded: "রেট লিমিট ছাড়িয়ে গেছে "
file: "ফাইলগুলি"
reverse: "উল্টান"
colored: "রঙ্গিন"
label: "লেবেল"
localOnly: "শুধুমাত্র লোকাল"
_emailUnavailable:
used: "এই ইমেইল ঠিকানাটি ইতোমধ্যে ব্যবহৃত হয়েছে"
format: "এই ইমেল ঠিকানাটি সঠিকভাবে লিখা হয়নি"

View File

@ -111,6 +111,14 @@ reactionSettingDescription2: "Arrossega per reordenar, fes clic per suprimir, pr
rememberNoteVisibility: "Recorda la configuració de visibilitat de les notes"
attachCancel: "Eliminar el fitxer adjunt"
markAsSensitive: "Marcar com a NSFW"
unmarkAsSensitive: "Deixar de marcar com a sensible"
enterFileName: "Defineix nom del fitxer"
mute: "Silencia"
unmute: "Deixa de silenciar"
block: "Bloqueja"
unblock: "Desbloqueja"
suspend: "Suspèn"
unsuspend: "Deixa de suspendre"
instances: "Instàncies"
remove: "Eliminar"
nsfw: "NSFW"
@ -148,6 +156,8 @@ _profile:
username: "Nom d'usuari"
_exportOrImport:
followingList: "Seguint"
muteList: "Silencia"
blockingList: "Bloqueja"
userLists: "Llistes"
_pages:
script:

View File

@ -869,6 +869,32 @@ logoutConfirm: "Wirklich abmelden?"
lastActiveDate: "Zuletzt verwendet am"
statusbar: "Statusleiste"
pleaseSelect: "Wähle eine Option"
reverse: "Umkehren"
colored: "Farbig"
refreshInterval: "Aktualisierungsrate"
label: "Beschriftung"
type: "Art"
speed: "Geschwindigkeit"
slow: "Langsam"
fast: "Schnell"
sensitiveMediaDetection: "Erkennung von NSFW-Medien"
localOnly: "Nur Lokal"
remoteOnly: "Nur für fremde Instanzen"
failedToUpload: "Hochladen fehlgeschlagen"
cannotUploadBecauseInappropriate: "Diese Datei kann nicht hochgeladen werden, da Anteile der Datei als möglicherweise NSFW festgestellt wurden."
cannotUploadBecauseNoFreeSpace: "Die Datei konnte nicht hochgeladen werden, da dein Drive-Speicherplatz aufgebraucht ist."
beta: "Beta"
enableAutoSensitive: "NSFW-Automarkierung"
enableAutoSensitiveDescription: "Setzt soweit möglich durch Verwendung von Machine Learning automatisch NSFW-Markierungen für Medien, die NSFW-Anteile beinhalten. Auch wenn du diese Option deaktiviert hast, ist sie möglicherweise auf Instanzebene aktiviert."
activeEmailValidationDescription: "Aktivert strengere Überprüfung von E-Mail-Adressen, d.h. Testen auf Wegwerfadressen und darauf, ob mit der Adresse tatsächlich kommuniziert werden kann. Ist dies deaktiviert, so wird nur das Format der E-Mail überprüft."
_sensitiveMediaDetection:
description: "Ermöglicht eine Erleichterung der Servermoderation durch die automatische Erkennungen von NSFW-Medien unter Verwendung von Machine Learning. Hierdurch wird die Serverlast etwas erhöht."
sensitivity: "Erkennungssensitivität"
sensitivityDescription: "Durch das Senken der Sensitivität kann die Anzahl an Fehlerkennungen (sog. false positives) reduziert werden. Durch ein Erhöhen dieser kann die Anzahl an verpassten Erkennungen (sog. false negatives) reduziert werden."
setSensitiveFlagAutomatically: "Als NSFW markieren"
setSensitiveFlagAutomaticallyDescription: "Die Resultate der internen Erkennung werden beibehalten, auch wenn diese Option deaktiviert ist."
analyzeVideos: "Videoanalyse aktivieren"
analyzeVideosDescription: "Analysiert zusätzlich zu Bildern auch Videos. Die Last des Servers wird hierdurch etwas erhöht."
_emailUnavailable:
used: "Diese Email-Adresse wird bereits verwendet"
format: "Das Format dieser Email-Adresse ist ungültig"

View File

@ -869,6 +869,32 @@ logoutConfirm: "Really log out?"
lastActiveDate: "Last used at"
statusbar: "Status bar"
pleaseSelect: "Select an option"
reverse: "Reverse"
colored: "Colored"
refreshInterval: "Update interval "
label: "Label"
type: "Type"
speed: "Speed"
slow: "Slow"
fast: "Fast"
sensitiveMediaDetection: "Detection of NSFW media"
localOnly: "Local only"
remoteOnly: "Remote only"
failedToUpload: "Upload failed"
cannotUploadBecauseInappropriate: "This file could not be uploaded because parts of it have been detected as potentially NSFW."
cannotUploadBecauseNoFreeSpace: "Upload failed due to lack of Drive capacity."
beta: "Beta"
enableAutoSensitive: "Automatic NSFW-Marking"
enableAutoSensitiveDescription: "Allows automatic detection and marking of NSFW media through Machine Learning where possible. Even if this option is disabled, it may be enabled instance-wide."
activeEmailValidationDescription: "Enables stricter validation of email addresses, which includes checking for disposable addresses and by whether it can actually be communicated with. When unchecked, only the format of the email is validated."
_sensitiveMediaDetection:
description: "Reduces the effort of server moderation through automatically recognizing NSFW media via Machine Learning. This will slightly increase the load on the server."
sensitivity: "Detection sensitivity"
sensitivityDescription: "Reducing the sensitivity will lead to fewer misdetections (false positives) whereas increasing it will lead to fewer missed detections (false negatives)."
setSensitiveFlagAutomatically: "Mark as NSFW"
setSensitiveFlagAutomaticallyDescription: "The results of the internal detection will be retained even if this option is turned off."
analyzeVideos: "Enable analysis of videos"
analyzeVideosDescription: "Analyzes videos in addition to images. This will slightly increase the load on the server."
_emailUnavailable:
used: "This email address is already being used"
format: "The format of this email address is invalid"

View File

@ -861,6 +861,10 @@ document: "Documento"
numberOfPageCache: "Cantidad de páginas cacheadas"
numberOfPageCacheDescription: "Al aumentar el número mejora la conveniencia pero tambien puede aumentar la carga y la memoria a usarse"
logoutConfirm: "¿Cerrar sesión?"
reverse: "Echar de un capirotazo"
colored: "Color"
label: "Etiqueta"
localOnly: "Solo local"
_emailUnavailable:
used: "Ya fue usado"
format: "Formato no válido."

View File

@ -839,6 +839,10 @@ rateLimitExceeded: "Limite de taux dépassée"
cropImage: "Recadrer l'image"
cropImageAsk: "Voulez-vous recadrer cette image ?"
file: "Fichiers"
reverse: "Inverser"
colored: "Coloré"
label: "Étiquette"
localOnly: "Local seulement"
_emailUnavailable:
used: "Non disponible"
format: "Le format de cette adresse de courriel est invalide"

View File

@ -848,6 +848,10 @@ rateLimitExceeded: "Batas sudah terlampaui"
cropImage: "potong gambar"
cropImageAsk: "Ingin memotong gambar?"
file: "Berkas"
reverse: "Balik"
colored: "Diwarnai"
label: "Label"
localOnly: "Hanya lokal"
_emailUnavailable:
used: "Alamat surel ini telah digunakan"
format: "Format tidak valid."

View File

@ -810,6 +810,10 @@ oneHour: "1 ora"
oneDay: "1 giorno"
oneWeek: "1 settimana"
file: "Allegati"
reverse: "Inverti"
colored: "Colorato"
label: "Etichetta"
localOnly: "Soltanto locale"
_emailUnavailable:
used: "Email già in uso"
format: "Formato email non valido"

View File

@ -658,6 +658,7 @@ hide: "隠す"
searchByGoogle: "探す"
indefinitely: "無期限"
file: "ファイル"
colored: "色付き"
_ad:
back: "戻る"
_gallery:

View File

@ -203,6 +203,7 @@ done: "완료"
processing: "처리중"
preview: "미리보기"
default: "기본값"
defaultValueIs: "기본값: {value}"
noCustomEmojis: "이모지가 없습니다"
noJobs: "작업이 없습니다"
federating: "연합 중"
@ -381,6 +382,7 @@ administrator: "관리자"
token: "토큰"
twoStepAuthentication: "2단계 인증"
moderator: "모더레이터"
moderation: "모더레이션"
nUsersMentioned: "{n}명이 언급함"
securityKey: "보안 키"
securityKeyName: "키 이름"
@ -854,9 +856,44 @@ noEmailServerWarning: "메일 서버가 설정되어 있지 않습니다."
thereIsUnresolvedAbuseReportWarning: "해결되지 않은 신고가 있습니다."
recommended: "추천"
check: "체크"
driveCapOverrideLabel: "이 유저의 드라이브 용량을 변경"
driveCapOverrideCaption: "0 이하를 지정하면 해제됩니다."
requireAdminForView: "열람하려면 관리자 계정으로 로그인해야 합니다."
isSystemAccount: "시스템에 의해 자동으로 생성되어 관리되는 계정입니다."
typeToConfirm: "계속하시려면 {x} 을 입력하세요"
deleteAccount: "계정 삭제"
document: "문서"
numberOfPageCache: "페이지 캐시 수"
numberOfPageCacheDescription: "숫자가 클 수록 편리성이 높아지지만, 시스템 자원과 메모리를 더 많이 사용합니다."
logoutConfirm: "로그아웃 하시겠습니까?"
lastActiveDate: "마지막 이용"
pleaseSelect: "선택해 주세요"
reverse: "플립"
colored: "색 입히기"
refreshInterval: "업데이트 주기"
label: "라벨"
type: "종류"
speed: "속도"
slow: "느리게"
fast: "빠르게"
sensitiveMediaDetection: "민감한 미디어 탐지"
localOnly: "로컬에만"
remoteOnly: "리모트만"
failedToUpload: "업로드 실패"
cannotUploadBecauseInappropriate: "이 파일은 부적절한 내용을 포함한다고 판단되어 업로드할 수 없습니다."
cannotUploadBecauseNoFreeSpace: "드라이브 용량이 부족하여 업로드할 수 없습니다."
beta: "베타"
enableAutoSensitive: "자동 NSFW 탐지"
enableAutoSensitiveDescription: "이용 가능할 경우 기계학습을 통해 자동으로 미디어 NSFW를 설정합니다. 이 기능을 해제하더라도, 인스턴스 정책에 따라 자동으로 설정될 수 있습니다."
activeEmailValidationDescription: "유저가 입력한 메일 주소가 일회용 메일인지, 실제로 통신할 수 있는 지 엄격하게 검사합니다. 해제할 경우 이메일 형식에 대해서만 검사합니다."
_sensitiveMediaDetection:
description: "기계학습을 통해 자동으로 민감한 미디어를 탐지하여, 모더레이션에 참고할 수 있도록 합니다. 서버의 부하를 약간 증가시킵니다."
sensitivity: "탐지 민감도"
sensitivityDescription: "민감도가 낮을수록 안전한 미디어가 잘못 탐지될 확률이 줄어들며, 높을수록 민감한 미디어가 탐지되지 않을 확률이 줄어듭니다."
setSensitiveFlagAutomatically: "자동으로 NSFW로 설정하기"
setSensitiveFlagAutomaticallyDescription: "이 설정을 해제해도 탐지 결과는 유지됩니다."
analyzeVideos: "동영상도 같이 확인하기"
analyzeVideosDescription: "사진 뿐만 아니라 동영상의 NSFW 여부도 탐지합니다. 서버의 부하를 약간 증가시킵니다."
_emailUnavailable:
used: "이 메일 주소는 사용중입니다"
format: "형식이 올바르지 않습니다"
@ -1215,6 +1252,7 @@ _widgets:
photos: "사진"
digitalClock: "디지털 시계"
federation: "연합"
instanceCloud: "인스턴스 구름"
postForm: "글 입력란"
slideshow: "슬라이드 쇼"
button: "버튼"
@ -1660,6 +1698,9 @@ _deck:
stackLeft: "왼쪽에 쌓기"
popRight: "오른쪽으로 빼기"
profile: "프로파일"
introduction: "칼럼을 조합해서 나만의 인터페이스를 구성해 보아요!"
introduction2: "나중에라도 화면 우측의 + 버튼을 눌러 새 칼럼을 추가할 수 있습니다."
widgetsIntroduction: "칼럼 메뉴의 \"위젯 편집\"에서 위젯을 추가해 주세요"
_columns:
main: "메인"
widgets: "위젯"

View File

@ -761,6 +761,9 @@ hide: "Ukryj"
searchByGoogle: "Szukaj"
indefinitely: "Nigdy"
file: "Pliki"
reverse: "Odwróć"
colored: "Kolorowe"
label: "Etykieta"
_ffVisibility:
public: "Publikuj"
_ad:

View File

@ -203,6 +203,7 @@ done: "Готово"
processing: "Обработка"
preview: "Предпросмотр"
default: "По умолчанию"
defaultValueIs: "По умолчанию: {value}"
noCustomEmojis: "Собственные эмодзи отсутствуют"
noJobs: "Нет заданий"
federating: "Федерируется"
@ -834,6 +835,16 @@ instanceDefaultLightTheme: "Светлая тема по умолчанию"
instanceDefaultDarkTheme: "Темная тема по умолчанию"
indefinitely: "вечно"
file: "Файлы"
recommended: "Рекомендуем"
check: "Проверить"
driveCapOverrideLabel: "Изменение лимита дискового пространства для этого пользователя"
reverse: "Переворот"
colored: "Выделена цветом"
label: "Метка"
localOnly: "Локально"
_sensitiveMediaDetection:
description: "Машинное обучение может быть использовано для автоматического обнаружения чувствительных медиа для модерации. Нагрузка на сервер увеличивается незначительно."
setSensitiveFlagAutomatically: "Установить флаг NSFW"
_emailUnavailable:
used: "Уже используется"
format: "Неверный формат"

View File

@ -865,6 +865,32 @@ numberOfPageCacheDescription: "Zvýši rýchlosť ale tiež nároky na pamäť."
logoutConfirm: "Naozaj sa chcete odhlásiť?"
statusbar: "Stavový riadok"
pleaseSelect: "Prosím vyberte"
reverse: "Preklopiť"
colored: "Farebné"
refreshInterval: "Interval obnovenia"
label: "Popisok"
type: "Typ"
speed: "Rýchlosť"
slow: "Pomaly"
fast: "Rýchlo"
sensitiveMediaDetection: "Detekcia citlivých médií."
localOnly: "Iba lokálne"
remoteOnly: "Len vzdialené"
failedToUpload: "Nahrávanie zlyhalo"
cannotUploadBecauseInappropriate: "Nemožno nahrať, pretože pravdepodobne obsahuje nevhodný obsah."
cannotUploadBecauseNoFreeSpace: "Nemožno nahrať kvôli nedostatku voľného úložiska."
beta: "Beta"
enableAutoSensitive: "Automatická detekcia NSFW"
enableAutoSensitiveDescription: "Ak je zapnuté, príznak NSFW sa na médiách automaticky nastaví pomocou strojového učenia. Aj keď je táto funkcia vypnutá, v niektorých prípadoch sa môže nastaviť automaticky."
activeEmailValidationDescription: "Dôkladnejšie overí e-mailovú adresu používateľa tým, že zistí, či ide o vyradenú e-mailovú adresu a či sa s ňou dá skutočne komunikovať. Ak nie je začiarknuté, e-mailová adresa sa kontroluje len ako text."
_sensitiveMediaDetection:
description: "Strojové učenie sa použije na automatickú detekciu citlivých médií na účely ich moderovania. Mierne sa zvýši zaťaženie servera."
sensitivity: "Citlivosť detekcie"
sensitivityDescription: "Nižšia citlivosť znižuje počet falošne pozitívnych výsledkov (false positives). Vyššia citlivosť znižuje počet falošne negatívnych výsledkov (false negatives)."
setSensitiveFlagAutomatically: "Nastaviť príznak NSFW"
setSensitiveFlagAutomaticallyDescription: "Aj keď je toto nastavenie vypnuté, výsledok rozhodnutia je interne uložený."
analyzeVideos: "Zapnúť analýzu videa"
analyzeVideosDescription: "Okrem obrázkov zapne detekciu aj pre videá. Zaťaženie servera sa mierne zvýši."
_emailUnavailable:
used: "Táto emailová adresa sa už používa"
format: "Formát emailovej adresy je nesprávny"

View File

@ -795,6 +795,31 @@ whatIsNew: "แสดงการเปลี่ยนแปลง"
translate: "แปลภาษา"
translatedFrom: "แปลมาจาก {x}"
accountDeletionInProgress: "กำลังดำเนินการลบบัญชีอยู่"
usernameInfo: "ชื่อที่ระบุบัญชีของคุณจากผู้อื่นในเซิร์ฟเวอร์นี้ คุณสามารถใช้ตัวอักษร (a~z, A~Z), ตัวเลข (0~9) หรือขีดล่าง (_) ชื่อผู้ใช้ไม่สามารถเปลี่ยนแปลงได้ในภายหลัง"
aiChanMode: "โหมด Ai "
keepCw: "เก็บคำเตือนเนื้อหา"
pubSub: "บัญชีผับ/ย่อย"
lastCommunication: "การสื่อสารครั้งสุดท้ายล่าสุด"
resolved: "คลี่คลายแล้ว"
unresolved: "รอการเฉลย"
breakFollow: "ลบผู้ติดตาม"
itsOn: "เปิดใช้งาน"
itsOff: "ปิดใช้งาน"
emailRequiredForSignup: "จำเป็นต้องการใช้ที่อยู่อีเมลสำหรับการสมัคร"
unread: "ไม่ได้อ่าน"
filter: "กรอง"
controlPanel: "แผงควบคุม"
manageAccounts: "จัดการบัญชี"
makeReactionsPublic: "ตั้งค่าประวัติปฏิกิริยาต่อสาธารณะ"
makeReactionsPublicDescription: "การทำเช่นนี้จะทำให้รายการปฏิกิริยาที่ผ่านมาของคุณจะปรากฏต่อสาธารณะนะ"
classic: "คลาสสิค"
muteThread: "ปิดเสียงเธรด"
unmuteThread: "เปิดเสียงเธรด"
ffVisibility: "การมองเห็นผู้ติดตาม/ผู้ติดตาม"
ffVisibilityDescription: "ช่วยให้คุณสามารถกำหนดค่าได้ว่าใครสามารถดูได้ว่าคุณติดตามใครและใครติดตามคุณบ้าง"
continueThread: "ดูความต่อเนื่องเธรด"
deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?"
incorrectPassword: "รหัสผ่านไม่ถูกต้อง"
searchByGoogle: "ค้นหา"
file: "ไฟล์"
_ffVisibility:

View File

@ -738,6 +738,10 @@ hide: "Сховати"
searchByGoogle: "Пошук"
indefinitely: "Ніколи"
file: "Файли"
reverse: "Перевернути"
colored: "Кольоровий"
label: "Назва"
localOnly: "Локально"
_ffVisibility:
public: "Опублікувати"
_ad:

View File

@ -869,6 +869,32 @@ logoutConfirm: "Bạn có chắc muốn đăng xuất?"
lastActiveDate: "Lần cuối vào"
statusbar: "Thanh trạng thái"
pleaseSelect: "Chọn một lựa chọn"
reverse: "Lật"
colored: "Với màu"
refreshInterval: "Cập nhật nội bộ"
label: "Nhãn"
type: "Loại"
speed: "Tốc độ"
slow: "Chậm"
fast: "Nhanh"
sensitiveMediaDetection: "Tự động phát hiện NSFW"
localOnly: "Chỉ trên máy chủ"
remoteOnly: "Chỉ máy chủ từ xa"
failedToUpload: "Tải lên thất bại"
cannotUploadBecauseInappropriate: "Không thể tải lên tập tin này vì các phần của tập tin đã được phát hiện có khả năng là NSFW."
cannotUploadBecauseNoFreeSpace: "Tải lên không thành công do thiếu dung lượng Drive."
beta: "Beta"
enableAutoSensitive: "Tự động đánh dấu NSFW"
enableAutoSensitiveDescription: "Cho phép tự động phát hiện và đánh dấu media NSFW thông qua học máy, nếu có thể. Ngay cả khi tùy chọn này bị tắt, nó vẫn có thể được bật trên toàn máy chủ."
activeEmailValidationDescription: "Cho phép xác minh địa chỉ email chặt chẽ hơn, bao gồm việc kiểm tra các địa chỉ dùng một lần và xem nó có thực sự được giao tiếp hay không. Khi bỏ chọn, chỉ định dạng của email được xác minh."
_sensitiveMediaDetection:
description: "Giảm nỗ lực kiểm duyệt máy chủ thông qua việc tự động nhận dạng media NSFW thông qua học máy. Điều này sẽ làm tăng một chút áp lực trên máy chủ."
sensitivity: "Phát hiện nhạy cảm"
sensitivityDescription: "Giảm độ nhạy sẽ dẫn đến ít phát hiện sai hơn (dương tính giả), tăng nó sẽ dẫn đến ít phát hiện sai hơn (âm tính giả)."
setSensitiveFlagAutomatically: "Đánh dấu là NSFW"
setSensitiveFlagAutomaticallyDescription: "Kết quả của phát hiện nội bộ sẽ được giữ lại ngay cả khi tùy chọn này bị tắt."
analyzeVideos: "Bật chuẩn đoán video"
analyzeVideosDescription: "Phân tích video bên cạnh hình ảnh. Điều này sẽ làm tăng một chút áp lực trên máy chủ."
_emailUnavailable:
used: "Địa chỉ email đã được sử dụng"
format: "Địa chỉ email không hợp lệ"

View File

@ -381,6 +381,7 @@ administrator: "管理员"
token: "Token (令牌)"
twoStepAuthentication: "两步验证"
moderator: "监察员"
moderation: "管理"
nUsersMentioned: "{n} 被提到"
securityKey: "安全密钥"
securityKeyName: "密钥名称"
@ -851,7 +852,40 @@ noEmailServerWarning: "电子邮件服务器未设置。"
thereIsUnresolvedAbuseReportWarning: "有未解决的报告"
recommended: "推荐"
check: "检查"
driveCapOverrideCaption: "设定为 0 以下则会解除此限制。"
requireAdminForView: "需要使用管理员账户登录才能查看。"
isSystemAccount: "该账号由系统自动创建和管理。"
typeToConfirm: "输入 {x} 以确认操作。"
deleteAccount: "删除账户"
numberOfPageCache: "缓存页数"
numberOfPageCacheDescription: "设置较高的值会更方便用户,但服务器负载和内存使用量会增加。"
logoutConfirm: "是否确认登出?"
lastActiveDate: "最后活跃时间"
statusbar: "状态栏"
pleaseSelect: "请选择"
reverse: "翻转"
colored: "彩色"
refreshInterval: "刷新间隔"
label: "标签"
speed: "速度"
slow: "慢"
fast: "快"
sensitiveMediaDetection: "检测到敏感媒体"
localOnly: "仅限本地"
remoteOnly: "仅远程"
failedToUpload: "上传失败"
cannotUploadBecauseInappropriate: "因为可能含有不适宜的内容,无法上传。"
cannotUploadBecauseNoFreeSpace: "因为已无可用空间,无法上传。"
beta: "测试"
enableAutoSensitive: "自动 NSFW 识别"
_sensitiveMediaDetection:
description: "可以使用机器学习技术自动检测敏感媒体,以便进行审核。服务器负载将略微增加。"
sensitivity: "检测敏感度"
sensitivityDescription: "敏感度较低,则误检(假阳性)会减少;敏感度较高,则漏检(假阴性)会减少。"
setSensitiveFlagAutomatically: "自动设置 NSFW 标签"
setSensitiveFlagAutomaticallyDescription: "即使关闭此配置,识别结果也会在内部保存。"
analyzeVideos: "启用对视频的检测"
analyzeVideosDescription: "除了静止图像之外,还对视频进行分析。服务器负载会略微增加。"
_emailUnavailable:
used: "已经被使用过"
format: "无效的格式"
@ -1210,6 +1244,7 @@ _widgets:
photos: "照片"
digitalClock: "数字时钟"
federation: "联邦宇宙"
instanceCloud: "实例云"
postForm: "投稿窗口"
slideshow: "幻灯片展示"
button: "按钮"

View File

@ -1,7 +1,7 @@
---
_lang_: "繁體中文"
headlineMisskey: "貼文連繫網路"
introMisskey: "歡迎! Misskey是一個開放原始碼且去中心化的社群網路。\n透過「貼文」分享周邊新鮮事並告訴其他人您的想法📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧🚀"
introMisskey: "歡迎! Misskey是一個開放原始碼且去中心化的社群網路。\n透過「貼文」分享周邊新鮮事並告訴其他人您的想法📡\n透過「反應」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧🚀"
monthAndDay: "{month}月 {day}日"
search: "搜尋"
notifications: "通知"
@ -727,7 +727,7 @@ receiveAnnouncementFromInstance: "接收由本實例發出的電郵通知"
emailNotification: "郵件通知"
publish: "發佈"
inChannelSearch: "頻道内搜尋"
useReactionPickerForContextMenu: "點擊右鍵開啟應工具欄"
useReactionPickerForContextMenu: "點擊右鍵開啟應工具欄"
typingUsers: "{users}輸入中..."
jumpToSpecifiedDate: "跳轉到特定日期"
showingPastTimeline: "顯示過往的時間線"
@ -810,8 +810,8 @@ unread: "未讀"
filter: "篩選"
controlPanel: "控制台"
manageAccounts: "管理帳戶"
makeReactionsPublic: "將應設為公開"
makeReactionsPublicDescription: "將您做過的應設為公開可見。"
makeReactionsPublic: "將應設為公開"
makeReactionsPublicDescription: "將您做過的應設為公開可見。"
classic: "經典"
muteThread: "將貼文串設為靜音"
unmuteThread: "將貼文串的靜音解除"
@ -869,6 +869,32 @@ logoutConfirm: "確定要登出嗎?"
lastActiveDate: "上次使用日期及時間"
statusbar: "狀態列"
pleaseSelect: "請選擇"
reverse: "翻轉"
colored: "彩色"
refreshInterval: "更新間隔"
label: "標籤"
type: "類型"
speed: "速度"
slow: "慢"
fast: "快"
sensitiveMediaDetection: "敏感性媒體的檢測"
localOnly: "僅限本地"
remoteOnly: "僅限遠端"
failedToUpload: "上傳失敗"
cannotUploadBecauseInappropriate: "由於判定可能包含不適當的內容,因此無法上船。"
cannotUploadBecauseNoFreeSpace: "由於雲端硬碟沒有可用空間,因此無法上船>"
beta: "Beta"
enableAutoSensitive: "自動NSFW判定"
enableAutoSensitiveDescription: "如果可用,請利用機器學習在媒體上自動設置 NSFW 旗標。 即使關閉此功能,依實例而定也可能會自動設置。"
activeEmailValidationDescription: "積極地驗證用戶的電子郵件地址,判斷它是否為免洗地址,或者它是否可以通信。 若關閉,則只會檢查字元是否正確。"
_sensitiveMediaDetection:
description: "您可以使用機器學習自動檢測敏感媒體並將其用於審核。 伺服器的負荷會稍微增加。"
sensitivity: "檢測敏感度"
sensitivityDescription: "敏感度低時,誤檢測(偽陽性)會減少。敏感度高時,漏檢(偽陰性)會減少。"
setSensitiveFlagAutomatically: "設定 NSFW 旗標"
setSensitiveFlagAutomaticallyDescription: "即使將此設定關閉,判定結果也會保留在內部。"
analyzeVideos: "啟用影片分析"
analyzeVideosDescription: "除了靜止影像以外,也分析影片。伺服器的負荷會稍微增加。"
_emailUnavailable:
used: "已經在使用中"
format: "格式無效"

View File

@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "12.112.3",
"version": "12.113.0",
"codename": "indigo",
"repository": {
"type": "git",
@ -41,7 +41,7 @@
"devDependencies": {
"@types/gulp": "4.0.9",
"@types/gulp-rename": "2.0.1",
"@typescript-eslint/parser": "5.30.0",
"@typescript-eslint/parser": "5.30.6",
"cross-env": "7.0.3",
"cypress": "10.3.0",
"start-server-and-test": "1.14.0",

View File

@ -13,6 +13,9 @@
"chokidar": "^3.3.1",
"lodash": "^4.17.21"
},
"optionalDependencies": {
"@tensorflow/tfjs-node": "3.18.0"
},
"dependencies": {
"@bull-board/koa": "4.0.0",
"@discordapp/twemoji": "14.0.2",
@ -23,7 +26,6 @@
"@peertube/http-signature": "1.6.0",
"@sinonjs/fake-timers": "9.1.2",
"@syuilo/aiscript": "0.11.1",
"@tensorflow/tfjs-node": "3.18.0",
"abort-controller": "3.0.0",
"ajv": "8.11.0",
"archiver": "5.3.1",
@ -37,7 +39,7 @@
"cbor": "8.1.0",
"chalk": "5.0.1",
"chalk-template": "0.4.0",
"chokidar": "3.3.1",
"chokidar": "3.5.3",
"cli-highlight": "2.1.11",
"color-convert": "2.0.1",
"content-disposition": "0.5.4",
@ -67,15 +69,15 @@
"koa-send": "5.0.1",
"koa-slow": "2.1.0",
"koa-views": "7.0.2",
"mfm-js": "0.22.1",
"mfm-js": "0.23.0-canary.1",
"mime-types": "2.1.35",
"misskey-js": "0.0.14",
"mocha": "10.0.0",
"ms": "3.0.0-canary.1",
"multer": "1.4.4",
"nested-property": "4.0.0",
"node-fetch": "3.2.6",
"nodemailer": "6.7.6",
"node-fetch": "3.2.8",
"nodemailer": "6.7.7",
"nsfwjs": "2.4.1",
"os-utils": "0.0.14",
"parse5": "7.0.0",
@ -106,11 +108,11 @@
"style-loader": "3.3.1",
"summaly": "2.7.0",
"syslog-pro": "1.0.0",
"systeminformation": "5.11.22",
"systeminformation": "5.12.0",
"tinycolor2": "1.4.2",
"tmp": "0.2.1",
"ts-loader": "9.3.1",
"ts-node": "10.8.1",
"ts-node": "10.8.2",
"tsc-alias": "1.6.11",
"tsconfig-paths": "4.0.0",
"twemoji-parser": "14.0.0",
@ -135,7 +137,7 @@
"@types/jsdom": "16.2.14",
"@types/jsonld": "1.5.6",
"@types/jsrsasign": "10.5.1",
"@types/koa": "2.13.4",
"@types/koa": "2.13.5",
"@types/koa-bodyparser": "4.3.7",
"@types/koa-cors": "0.0.2",
"@types/koa-favicon": "2.0.21",
@ -147,7 +149,7 @@
"@types/koa__multer": "2.0.4",
"@types/koa__router": "8.0.11",
"@types/mocha": "9.1.1",
"@types/node": "18.0.0",
"@types/node": "18.0.3",
"@types/node-fetch": "3.0.3",
"@types/nodemailer": "6.4.4",
"@types/oauth": "0.9.1",
@ -169,10 +171,10 @@
"@types/web-push": "3.3.2",
"@types/websocket": "1.0.5",
"@types/ws": "8.5.3",
"@typescript-eslint/eslint-plugin": "5.30.0",
"@typescript-eslint/parser": "5.30.0",
"@typescript-eslint/eslint-plugin": "5.30.6",
"@typescript-eslint/parser": "5.30.6",
"cross-env": "7.0.3",
"eslint": "8.18.0",
"eslint": "8.19.0",
"eslint-plugin-import": "2.26.0",
"execa": "6.1.0",
"typescript": "4.7.4"

View File

@ -145,6 +145,12 @@ export function toHtml(nodes: mfm.MfmNode[] | null, mentionedRemoteUsers: IMenti
a.textContent = node.props.content;
return a;
},
plain(node) {
const el = doc.createElement('span');
appendChildren(node.children, el);
return el;
},
};
appendChildren(nodes, doc.body);

View File

@ -8,7 +8,7 @@ import { queueLogger } from '../../logger.js';
import { addFile } from '@/services/drive/add-file.js';
import { format as dateFormat } from 'date-fns';
import { Users, Emojis } from '@/models/index.js';
import { } from '@/queue/types.js';
import { } from '@/queue/types.js';
import { createTemp, createTempDir } from '@/misc/create-temp.js';
import { downloadUrl } from '@/misc/download-url.js';
import config from '@/config/index.js';

View File

@ -1,6 +1,6 @@
import config from '@/config/index.js';
import Resolver from '../resolver.js';
import { IObject, IQuestion, isQuestion } from '../type.js';
import { IObject, IQuestion, isQuestion } from '../type.js';
import { apLogger } from '../logger.js';
import { Notes, Polls } from '@/models/index.js';
import { IPoll } from '@/models/entities/poll.js';

View File

@ -8,7 +8,7 @@ import renderEmoji from './emoji.js';
export const renderLike = async (noteReaction: NoteReaction, note: Note) => {
const reaction = noteReaction.reaction;
const object = {
const object = {
type: 'Like',
id: `${config.url}/likes/${noteReaction.id}`,
actor: `${config.url}/users/${noteReaction.userId}`,

View File

@ -68,11 +68,11 @@ export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise<void>((res
}
try {
UserIps.insert({
UserIps.createQueryBuilder().insert().values({
createdAt: new Date(),
userId: user.id,
ip: ip,
});
}).orIgnore(true).execute();
} catch {
}
}

View File

@ -12,13 +12,15 @@ export async function readNotification(
if (notificationIds.length === 0) return;
// Update documents
await Notifications.update({
const result = await Notifications.update({
id: In(notificationIds),
isRead: false,
}, {
isRead: true,
});
if (result.affected === 0) return;
if (!await Users.getHasUnreadNotification(userId)) return postReadAllNotifications(userId);
else return postReadNotifications(userId, notificationIds);
}

View File

@ -214,7 +214,7 @@ export default define(meta, paramDef, async (ps, _user, token) => {
const newDescription = profileUpdates.description === undefined ? profile.description : profileUpdates.description;
if (newName != null) {
const tokens = mfm.parsePlain(newName);
const tokens = mfm.parseSimple(newName);
emojis = emojis.concat(extractCustomEmojisFromMfm(tokens!));
}

View File

@ -78,6 +78,7 @@ const nodeinfo2 = async () => {
enableEmail: meta.enableEmail,
enableServiceWorker: meta.enableServiceWorker,
proxyAccountName: proxyAccount ? proxyAccount.username : null,
themeColor: meta.themeColor || '#86b300',
},
};
};

View File

@ -2,19 +2,34 @@ import * as fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
import * as nsfw from 'nsfwjs';
import * as tf from '@tensorflow/tfjs-node';
import si from 'systeminformation';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
const REQUIRED_CPU_FLAGS = ['avx2', 'fma'];
let isSupportedCpu: undefined | boolean = undefined;
let model: nsfw.NSFWJS;
export async function detectSensitive(path: string): Promise<nsfw.predictionType[] | null> {
try {
if (isSupportedCpu === undefined) {
const cpuFlags = await getCpuFlags();
isSupportedCpu = REQUIRED_CPU_FLAGS.every(required => cpuFlags.includes(required));
}
if (!isSupportedCpu) {
console.error('This CPU cannot use TensorFlow.');
return null;
}
const tf = await import('@tensorflow/tfjs-node');
if (model == null) model = await nsfw.load(`file://${_dirname}/../../nsfw-model/`, { size: 299 });
const buffer = await fs.promises.readFile(path);
const image = await tf.node.decodeImage(buffer, 3) as tf.Tensor3D;
const image = await tf.node.decodeImage(buffer, 3) as any;
try {
const predictions = await model.classify(image);
return predictions;
@ -26,3 +41,8 @@ export async function detectSensitive(path: string): Promise<nsfw.predictionType
return null;
}
}
async function getCpuFlags(): Promise<string[]> {
const str = await si.cpuFlags();
return str.split(/\s+/);
}

View File

@ -34,7 +34,7 @@ export async function fetchInstanceMetadata(instance: Instance, force = false):
const [favicon, icon, themeColor, name, description] = await Promise.all([
fetchFaviconUrl(instance, dom).catch(() => null),
fetchIconUrl(instance, dom, manifest).catch(() => null),
getThemeColor(dom, manifest).catch(() => null),
getThemeColor(info, dom, manifest).catch(() => null),
getSiteName(info, dom, manifest).catch(() => null),
getDescription(info, dom, manifest).catch(() => null),
]);
@ -208,8 +208,8 @@ async function fetchIconUrl(instance: Instance, doc: DOMWindow['document'] | nul
return null;
}
async function getThemeColor(doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
const themeColor = doc?.querySelector('meta[name="theme-color"]')?.getAttribute('content') || manifest?.theme_color;
async function getThemeColor(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
const themeColor = info?.metadata?.themeColor || doc?.querySelector('meta[name="theme-color"]')?.getAttribute('content') || manifest?.theme_color;
if (themeColor) {
const color = new tinycolor(themeColor);

View File

@ -64,6 +64,7 @@ export async function pushNotification<T extends keyof pushNotificationsTypes>(u
type,
body: type === 'notification' ? truncateNotification(body as Packed<'Notification'>) : body,
userId,
dateTime: (new Date()).getTime(),
}), {
proxy: config.proxy,
}).catch((err: any) => {

View File

@ -730,10 +730,10 @@
"@types/koa-compose" "*"
"@types/node" "*"
"@types/koa@2.13.4":
version "2.13.4"
resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.4.tgz#10620b3f24a8027ef5cbae88b393d1b31205726b"
integrity sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==
"@types/koa@2.13.5":
version "2.13.5"
resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.5.tgz#64b3ca4d54e08c0062e89ec666c9f45443b21a61"
integrity sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA==
dependencies:
"@types/accepts" "*"
"@types/content-disposition" "*"
@ -800,10 +800,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.2.tgz#331b7b9f8621c638284787c5559423822fdffc50"
integrity sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA==
"@types/node@18.0.0":
version "18.0.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a"
integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==
"@types/node@18.0.3":
version "18.0.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.3.tgz#463fc47f13ec0688a33aec75d078a0541a447199"
integrity sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==
"@types/node@^14.11.8":
version "14.17.9"
@ -994,14 +994,14 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.0.tgz#524a11e15c09701733033c96943ecf33f55d9ca1"
integrity sha512-lvhRJ2pGe2V9MEU46ELTdiHgiAFZPKtLhiU5wlnaYpMc2+c1R8fh8i80ZAa665drvjHKUJyRRGg3gEm1If54ow==
"@typescript-eslint/eslint-plugin@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz#9c6017b6c1d04894141b4a87816388967f64c359"
integrity sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==
dependencies:
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/type-utils" "5.30.0"
"@typescript-eslint/utils" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/type-utils" "5.30.6"
"@typescript-eslint/utils" "5.30.6"
debug "^4.3.4"
functional-red-black-tree "^1.0.1"
ignore "^5.2.0"
@ -1009,69 +1009,69 @@
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/parser@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.0.tgz#a2184fb5f8ef2bf1db0ae61a43907e2e32aa1b8f"
integrity sha512-2oYYUws5o2liX6SrFQ5RB88+PuRymaM2EU02/9Ppoyu70vllPnHVO7ioxDdq/ypXHA277R04SVjxvwI8HmZpzA==
"@typescript-eslint/parser@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.6.tgz#add440db038fa9d777e4ebdaf66da9e7fb7abe92"
integrity sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==
dependencies:
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/typescript-estree" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/typescript-estree" "5.30.6"
debug "^4.3.4"
"@typescript-eslint/scope-manager@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.0.tgz#bf585ee801ab4ad84db2f840174e171a6bb002c7"
integrity sha512-3TZxvlQcK5fhTBw5solQucWSJvonXf5yua5nx8OqK94hxdrT7/6W3/CS42MLd/f1BmlmmbGEgQcTHHCktUX5bQ==
"@typescript-eslint/scope-manager@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz#ce1b49ff5ce47f55518d63dbe8fc9181ddbd1a33"
integrity sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/visitor-keys" "5.30.0"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/visitor-keys" "5.30.6"
"@typescript-eslint/type-utils@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.0.tgz#98f3af926a5099153f092d4dad87148df21fbaae"
integrity sha512-GF8JZbZqSS+azehzlv/lmQQ3EU3VfWYzCczdZjJRxSEeXDQkqFhCBgFhallLDbPwQOEQ4MHpiPfkjKk7zlmeNg==
"@typescript-eslint/type-utils@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz#a64aa9acbe609ab77f09f53434a6af2b9685f3af"
integrity sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==
dependencies:
"@typescript-eslint/utils" "5.30.0"
"@typescript-eslint/utils" "5.30.6"
debug "^4.3.4"
tsutils "^3.21.0"
"@typescript-eslint/types@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.0.tgz#db7d81d585a3da3801432a9c1d2fafbff125e110"
integrity sha512-vfqcBrsRNWw/LBXyncMF/KrUTYYzzygCSsVqlZ1qGu1QtGs6vMkt3US0VNSQ05grXi5Yadp3qv5XZdYLjpp8ag==
"@typescript-eslint/types@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.6.tgz#86369d0a7af8c67024115ac1da3e8fb2d38907e1"
integrity sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==
"@typescript-eslint/typescript-estree@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.0.tgz#4565ee8a6d2ac368996e20b2344ea0eab1a8f0bb"
integrity sha512-hDEawogreZB4n1zoqcrrtg/wPyyiCxmhPLpZ6kmWfKF5M5G0clRLaEexpuWr31fZ42F96SlD/5xCt1bT5Qm4Nw==
"@typescript-eslint/typescript-estree@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz#a84a0d6a486f9b54042da1de3d671a2c9f14484e"
integrity sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/visitor-keys" "5.30.0"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/visitor-keys" "5.30.6"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.0.tgz#1dac771fead5eab40d31860716de219356f5f754"
integrity sha512-0bIgOgZflLKIcZsWvfklsaQTM3ZUbmtH0rJ1hKyV3raoUYyeZwcjQ8ZUJTzS7KnhNcsVT1Rxs7zeeMHEhGlltw==
"@typescript-eslint/utils@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.6.tgz#1de2da14f678e7d187daa6f2e4cdb558ed0609dc"
integrity sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==
dependencies:
"@types/json-schema" "^7.0.9"
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/typescript-estree" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/typescript-estree" "5.30.6"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/visitor-keys@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.0.tgz#07721d23daca2ec4c2da7f1e660d41cd78bacac3"
integrity sha512-6WcIeRk2DQ3pHKxU1Ni0qMXJkjO/zLjBymlYBy/53qxe7yjEFSvzKLDToJjURUhSl2Fzhkl4SMXQoETauF74cw==
"@typescript-eslint/visitor-keys@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz#94dd10bb481c8083378d24de1742a14b38a2678c"
integrity sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/types" "5.30.6"
eslint-visitor-keys "^3.3.0"
"@ungap/promise-all-settled@1.1.2":
@ -1278,6 +1278,14 @@ anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
app-root-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad"
@ -1878,7 +1886,7 @@ cheerio@0.22.0:
lodash.reject "^4.4.0"
lodash.some "^4.4.0"
chokidar@3.3.1, chokidar@3.5.3, chokidar@^3.3.1, chokidar@^3.5.3:
chokidar@3.5.3, chokidar@^3.3.1, chokidar@^3.5.3:
version "3.3.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450"
integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==
@ -2882,10 +2890,10 @@ eslint-visitor-keys@^3.3.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
eslint@8.18.0:
version "8.18.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.18.0.tgz#78d565d16c993d0b73968c523c0446b13da784fd"
integrity sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==
eslint@8.19.0:
version "8.19.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.19.0.tgz#7342a3cbc4fbc5c106a1eefe0fd0b50b6b1a7d28"
integrity sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==
dependencies:
"@eslint/eslintrc" "^1.3.0"
"@humanwhocodes/config-array" "^0.9.2"
@ -3281,6 +3289,11 @@ fsevents@~2.1.2:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
fstream@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
@ -3417,7 +3430,7 @@ github-from-package@0.0.0:
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
glob-parent@^5.1.0, glob-parent@^5.1.2, glob-parent@~5.1.0:
glob-parent@^5.1.0, glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@ -4856,12 +4869,12 @@ methods@^1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
mfm-js@0.22.1:
version "0.22.1"
resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.22.1.tgz#ad5f0b95cc903ca5a5e414e2edf64ac4648dc8c2"
integrity sha512-UV5zvDKlWPpBFeABhyCzuOTJ3RwrNrmVpJ+zz/dFX6D/ntEywljgxkfsLamcy0ZSwUAr0O+WQxGHvAwyxUgsAQ==
mfm-js@0.23.0-canary.1:
version "0.23.0-canary.1"
resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.23.0-canary.1.tgz#1b7b7635f18bed9776054406b72e6bd613c8d0eb"
integrity sha512-SkMrW1rQAv+mFGtLKN9DSv6vxSREDu8ChmkBl1Ch5sQfp47BhuvcRg5EKGmt3WAQRAOylXYMg8wVYR7C5BHKeA==
dependencies:
twemoji-parser "14.0.x"
twemoji-parser "14.0.0"
micromatch@^4.0.0, micromatch@^4.0.2:
version "4.0.2"
@ -5283,10 +5296,10 @@ node-fetch@*:
fetch-blob "^3.1.4"
formdata-polyfill "^4.0.10"
node-fetch@3.2.6, node-fetch@^3.2.2:
version "3.2.6"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.6.tgz#6d4627181697a9d9674aae0d61548e0d629b31b9"
integrity sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw==
node-fetch@3.2.8:
version "3.2.8"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.8.tgz#0d9516dcf43a758d78d6dbe538adf0b1f6a4944e"
integrity sha512-KtpD1YhGszhntMpBDyp5lyagk8KIMopC1LEb7cQUAh7zcosaX5uK8HnbNb2i3NTQK3sIawCItS0uFC3QzcLHdg==
dependencies:
data-uri-to-buffer "^4.0.0"
fetch-blob "^3.1.4"
@ -5299,6 +5312,15 @@ node-fetch@^2.6.1, node-fetch@~2.6.1:
dependencies:
whatwg-url "^5.0.0"
node-fetch@^3.2.2:
version "3.2.6"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.6.tgz#6d4627181697a9d9674aae0d61548e0d629b31b9"
integrity sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw==
dependencies:
data-uri-to-buffer "^4.0.0"
fetch-blob "^3.1.4"
formdata-polyfill "^4.0.10"
node-gyp-build@^4.2.3:
version "4.3.0"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
@ -5325,10 +5347,10 @@ node-gyp@^9.0.0:
tar "^6.1.2"
which "^2.0.2"
nodemailer@6.7.6:
version "6.7.6"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.6.tgz#d3de8f644eaa0dad784d1be1375c596de492f3fc"
integrity sha512-/6KF/umU7r7X21Y648/yiRLrgkfz0dmpyuo4BfgYWIpnT/jCbkPTvegMfxCsDAu+O810p2L1BGXieMTPp3nJVA==
nodemailer@6.7.7:
version "6.7.7"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.7.tgz#e522fbd7507b81c51446d3f79c4603bf00083ddd"
integrity sha512-pOLC/s+2I1EXuSqO5Wa34i3kXZG3gugDssH+ZNCevHad65tc8vQlCQpOLaUjopvkRQKm2Cki2aME7fEOPRy3bA==
nofilter@^2.0.3:
version "2.0.3"
@ -6263,6 +6285,13 @@ readdirp@~3.3.0:
dependencies:
picomatch "^2.0.7"
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
reconnecting-websocket@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783"
@ -7006,10 +7035,10 @@ syslog-pro@1.0.0:
dependencies:
moment "^2.22.2"
systeminformation@5.11.22:
version "5.11.22"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.11.22.tgz#52eb78fd6bb48eef372f502b494ff59aacf82c02"
integrity sha512-sBZJ/WBCf2vDLeMZaEyVuo+aXylOSmNHHB2cX0jHULFxSBLXHX+QUHYrCvmz+YiflKY3bsahVWX7vwuz1p1QZA==
systeminformation@5.12.0:
version "5.12.0"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.12.0.tgz#1ff8d0b0fef9c2a6f70e1b1f2e681b8cd2d4b78e"
integrity sha512-2fa/2cnWxiC/g8v3XX4aEC2CQWl/WJ+JrfLq9f76lxYqkW4DWiU3vJhrEgAzBT07ta73c5wHd0xgMeMo0vBiMQ==
tapable@^2.2.0:
version "2.2.0"
@ -7203,10 +7232,10 @@ ts-loader@9.3.1:
micromatch "^4.0.0"
semver "^7.3.4"
ts-node@10.8.1:
version "10.8.1"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.8.1.tgz#ea2bd3459011b52699d7e88daa55a45a1af4f066"
integrity sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==
ts-node@10.8.2:
version "10.8.2"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.8.2.tgz#3185b75228cef116bf82ffe8762594f54b2a23f2"
integrity sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==
dependencies:
"@cspotcode/source-map-support" "^0.8.0"
"@tsconfig/node10" "^1.0.7"
@ -7287,7 +7316,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
twemoji-parser@14.0.0, twemoji-parser@14.0.x:
twemoji-parser@14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-14.0.0.tgz#13dabcb6d3a261d9efbf58a1666b182033bf2b62"
integrity sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==

View File

@ -15,7 +15,7 @@
"@rollup/plugin-alias": "3.1.9",
"@rollup/plugin-json": "4.1.0",
"@syuilo/aiscript": "0.11.1",
"@vitejs/plugin-vue": "3.0.0-beta.1",
"@vitejs/plugin-vue": "3.0.0",
"@vue/compiler-sfc": "3.2.37",
"abort-controller": "3.0.0",
"autobind-decorator": "2.4.0",
@ -40,7 +40,7 @@
"json5": "2.2.1",
"katex": "0.15.6",
"matter-js": "0.18.0",
"mfm-js": "0.22.1",
"mfm-js": "0.23.0-canary.1",
"misskey-js": "0.0.14",
"mocha": "10.0.0",
"ms": "2.1.3",
@ -56,7 +56,7 @@
"random-seed": "0.3.0",
"reflect-metadata": "0.1.13",
"rndstr": "1.0.0",
"rollup": "2.75.7",
"rollup": "2.76.0",
"s-age": "1.1.2",
"sass": "1.53.0",
"seedrandom": "3.0.5",
@ -74,7 +74,7 @@
"uuid": "8.3.2",
"v-debounce": "0.1.2",
"vanilla-tilt": "1.7.2",
"vite": "3.0.0-beta.7",
"vite": "3.0.0",
"vue": "3.2.37",
"vue-prism-editor": "2.0.0-alpha.2",
"vuedraggable": "4.0.1",
@ -100,13 +100,13 @@
"@types/uuid": "8.3.4",
"@types/websocket": "1.0.5",
"@types/ws": "8.5.3",
"@typescript-eslint/eslint-plugin": "5.30.0",
"@typescript-eslint/parser": "5.30.0",
"@typescript-eslint/eslint-plugin": "5.30.6",
"@typescript-eslint/parser": "5.30.6",
"cross-env": "7.0.3",
"cypress": "10.3.0",
"eslint": "8.18.0",
"eslint": "8.19.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-vue": "9.1.1",
"eslint-plugin-vue": "9.2.0",
"start-server-and-test": "1.14.0"
}
}

View File

@ -316,7 +316,7 @@ const render = () => {
plugins: [{
id: 'vLine',
beforeDraw(chart, args, options) {
if (chart.tooltip._active && chart.tooltip._active.length) {
if (chart.tooltip?._active?.length) {
const activePoint = chart.tooltip._active[0];
const ctx = chart.ctx;
const x = activePoint.element.x;

View File

@ -59,7 +59,7 @@ const isThumbnailAvailable = computed(() => {
display: flex;
background: var(--panel);
border-radius: 8px;
overflow: hidden; overflow: clip;
overflow: clip;
> .icon-sub {
position: absolute;

View File

@ -13,7 +13,7 @@
</template>
<script lang="ts" setup>
import { } from 'vue';
import { } from 'vue';
import * as Misskey from 'misskey-js';
import XDrive from './drive.vue';
import XWindow from '@/components/ui/window.vue';

View File

@ -41,7 +41,7 @@ import { useInterval } from '@/scripts/use-interval';
const props = defineProps<{
modelValue: string | number;
type?: 'text' | 'number' | 'password' | 'email' | 'url' | 'date' | 'time';
type?: 'text' | 'number' | 'password' | 'email' | 'url' | 'date' | 'time' | 'search';
required?: boolean;
readonly?: boolean;
disabled?: boolean;

View File

@ -189,7 +189,7 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => {
height: 3px;
background: rgba(0, 0, 0, 0.1);
border-radius: 999px;
overflow: hidden; overflow: clip;
overflow: clip;
> .highlight {
position: absolute;

View File

@ -1,5 +1,6 @@
<template>
<component :is="self ? 'MkA' : 'a'" ref="el" class="ieqqeuvs _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
<component
:is="self ? 'MkA' : 'a'" ref="el" class="ieqqeuvs _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
@contextmenu.stop="() => {}"
>
<template v-if="!self">
@ -23,14 +24,7 @@ import { toUnicode as decodePunycode } from 'punycode/';
import { url as local } from '@/config';
import * as os from '@/os';
import { useTooltip } from '@/scripts/use-tooltip';
function safeURIDecode(str: string) {
try {
return decodeURIComponent(str);
} catch {
return str;
}
}
import { safeURIDecode } from '@/scripts/safe-uri-decode';
export default defineComponent({
props: {
@ -42,7 +36,7 @@ export default defineComponent({
type: String,
required: false,
default: null,
}
},
},
setup(props) {
const self = props.url.startsWith(local);

View File

@ -76,7 +76,7 @@ export default {
<style lang="scss" module>
.wrap {
overflow: hidden; overflow: clip;
overflow: clip;
animation-play-state: running;
&:hover {

View File

@ -1,15 +1,15 @@
<template>
<MkA v-if="url.startsWith('/')" v-user-preview="canonical" :class="[$style.root, { isMe }]" :to="url" :style="{ background: bgCss }">
<img :class="$style.icon" :src="`/avatar/@${username}@${host}`" alt="">
<MkA v-if="url.startsWith('/')" v-user-preview="canonical" class="akbvjaqn" :class="{ isMe }" :to="url" :style="{ background: bgCss }">
<img class="icon" :src="`/avatar/@${username}@${host}`" alt="">
<span class="main">
<span class="username">@{{ username }}</span>
<span v-if="(host != localHost) || $store.state.showFullAcct" :class="$style.mainHost">@{{ toUnicode(host) }}</span>
<span v-if="(host != localHost) || $store.state.showFullAcct" class="host">@{{ toUnicode(host) }}</span>
</span>
</MkA>
<a v-else :class="$style.root" :href="url" target="_blank" rel="noopener" :style="{ background: bgCss }">
<a v-else class="akbvjaqn" :href="url" target="_blank" rel="noopener" :style="{ background: bgCss }">
<span class="main">
<span class="username">@{{ username }}</span>
<span :class="$style.mainHost">@{{ toUnicode(host) }}</span>
<span class="host">@{{ toUnicode(host) }}</span>
</span>
</a>
</template>
@ -41,8 +41,8 @@ const bgCss = bg.toRgbString();
useCssModule();
</script>
<style lang="scss" module>
.root {
<style lang="scss" scoped>
.akbvjaqn {
display: inline-block;
padding: 4px 8px 4px 4px;
border-radius: 999px;
@ -51,18 +51,18 @@ useCssModule();
&.isMe {
color: var(--mentionMe);
}
}
.icon {
width: 1.5em;
height: 1.5em;
object-fit: cover;
margin: 0 0.2em 0 0;
vertical-align: bottom;
border-radius: 100%;
}
> .icon {
width: 1.5em;
height: 1.5em;
object-fit: cover;
margin: 0 0.2em 0 0;
vertical-align: bottom;
border-radius: 100%;
}
.mainHost {
opacity: 0.5;
> .main > .host {
opacity: 0.5;
}
}
</style>

View File

@ -47,7 +47,7 @@ export default defineComponent({
render() {
if (this.text == null || this.text === '') return;
const ast = (this.plain ? mfm.parsePlain : mfm.parse)(this.text, { fnNameList: MFM_TAGS });
const ast = (this.plain ? mfm.parseSimple : mfm.parse)(this.text, { fnNameList: MFM_TAGS });
const validTime = (t: string | null | undefined) => {
if (t == null) return null;
@ -312,6 +312,10 @@ export default defineComponent({
})];
}
case 'plain': {
return [h('span', genEl(token.children))];
}
default: {
console.error('unrecognized ast type:', token.type);

View File

@ -27,7 +27,7 @@ const props = defineProps<{
display: flex;
margin: 0;
padding: 0;
overflow: hidden; overflow: clip;
overflow: clip;
font-size: 0.95em;
&.min-width_350px {

View File

@ -36,7 +36,7 @@ const showContent = $ref(false);
display: flex;
margin: 0;
padding: 0;
overflow: hidden; overflow: clip;
overflow: clip;
font-size: 0.95em;
&.min-width_350px {

View File

@ -293,7 +293,7 @@ function readPromo() {
position: relative;
transition: box-shadow 0.1s ease;
font-size: 1.05em;
overflow: hidden; overflow: clip;
overflow: clip;
contain: content;
//

View File

@ -71,7 +71,7 @@ defineExpose({
<style lang="scss" scoped>
.meijqfqm {
position: relative;
overflow: hidden; overflow: clip;
overflow: clip;
display: grid;
place-items: center;

View File

@ -54,7 +54,7 @@ onMounted(() => {
width: min-content;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
border-radius: 8px;
overflow: hidden; overflow: clip;
overflow: clip;
text-align: center;
pointer-events: none;

View File

@ -148,7 +148,7 @@ export default defineComponent({
text-decoration: none;
background: var(--buttonBg);
border-radius: 5px;
overflow: hidden; overflow: clip;
overflow: clip;
box-sizing: border-box;
transition: background 0.1s ease;

View File

@ -143,7 +143,7 @@ export default defineComponent({
.ukygtjoj {
position: relative;
overflow: hidden; overflow: clip;
overflow: clip;
contain: content;
&.naked {

View File

@ -10,7 +10,7 @@
</template>
<script lang="ts" setup>
import { nextTick, onMounted, computed, ref, watch, provide } from 'vue';
import { nextTick, onMounted, watch, provide } from 'vue';
import * as os from '@/os';
import { isTouchUsing } from '@/scripts/touch';
import { defaultStore } from '@/store';
@ -57,13 +57,13 @@ const emit = defineEmits<{
provide('modal', true);
const maxHeight = ref<number>();
const fixed = ref(false);
const transformOrigin = ref('center');
const showing = ref(true);
const content = ref<HTMLElement>();
let maxHeight = $ref<number>();
let fixed = $ref(false);
let transformOrigin = $ref('center');
let showing = $ref(true);
let content = $ref<HTMLElement>();
const zIndex = os.claimZIndex(props.zPriority);
const type = computed(() => {
const type = $computed(() => {
if (props.preferType === 'auto') {
if (!defaultStore.state.disableDrawer && isTouchUsing && deviceKind === 'smartphone') {
return 'drawer';
@ -80,7 +80,7 @@ let contentClicking = false;
const close = () => {
// eslint-disable-next-line vue/no-mutating-props
if (props.src) props.src.style.pointerEvents = 'auto';
showing.value = false;
showing = false;
emit('close');
};
@ -89,8 +89,8 @@ const onBgClick = () => {
emit('click');
};
if (type.value === 'drawer') {
maxHeight.value = window.innerHeight / 1.5;
if (type === 'drawer') {
maxHeight = window.innerHeight / 1.5;
}
const keymap = {
@ -101,22 +101,21 @@ const MARGIN = 16;
const align = () => {
if (props.src == null) return;
if (type.value === 'drawer') return;
if (type.value === 'dialog') return;
if (type === 'drawer') return;
if (type === 'dialog') return;
const popover = content.value!;
if (popover == null) return;
if (content == null) return;
const srcRect = props.src.getBoundingClientRect();
const width = popover.offsetWidth;
const height = popover.offsetHeight;
const width = content!.offsetWidth;
const height = content!.offsetHeight;
let left;
let top;
const x = srcRect.left + (fixed.value ? 0 : window.pageXOffset);
const y = srcRect.top + (fixed.value ? 0 : window.pageYOffset);
const x = srcRect.left + (fixed ? 0 : window.pageXOffset);
const y = srcRect.top + (fixed ? 0 : window.pageYOffset);
if (props.anchor.x === 'center') {
left = x + (props.src.offsetWidth / 2) - (width / 2);
@ -134,7 +133,7 @@ const align = () => {
top = y + props.src.offsetHeight;
}
if (fixed.value) {
if (fixed) {
//
if (left + width > window.innerWidth) {
left = window.innerWidth - width;
@ -147,16 +146,16 @@ const align = () => {
if (top + height > (window.innerHeight - MARGIN)) {
if (props.noOverlap && props.anchor.x === 'center') {
if (underSpace >= (upperSpace / 3)) {
maxHeight.value = underSpace;
maxHeight = underSpace;
} else {
maxHeight.value = upperSpace;
maxHeight = upperSpace;
top = (upperSpace + MARGIN) - height;
}
} else {
top = (window.innerHeight - MARGIN) - height;
}
} else {
maxHeight.value = underSpace;
maxHeight = underSpace;
}
} else {
//
@ -171,16 +170,16 @@ const align = () => {
if (top + height - window.pageYOffset > (window.innerHeight - MARGIN)) {
if (props.noOverlap && props.anchor.x === 'center') {
if (underSpace >= (upperSpace / 3)) {
maxHeight.value = underSpace;
maxHeight = underSpace;
} else {
maxHeight.value = upperSpace;
maxHeight = upperSpace;
top = window.pageYOffset + ((upperSpace + MARGIN) - height);
}
} else {
top = (window.innerHeight - MARGIN) - height + window.pageYOffset - 1;
}
} else {
maxHeight.value = underSpace;
maxHeight = underSpace;
}
}
@ -195,29 +194,29 @@ const align = () => {
let transformOriginX = 'center';
let transformOriginY = 'center';
if (top >= srcRect.top + props.src.offsetHeight + (fixed.value ? 0 : window.pageYOffset)) {
if (top >= srcRect.top + props.src.offsetHeight + (fixed ? 0 : window.pageYOffset)) {
transformOriginY = 'top';
} else if ((top + height) <= srcRect.top + (fixed.value ? 0 : window.pageYOffset)) {
} else if ((top + height) <= srcRect.top + (fixed ? 0 : window.pageYOffset)) {
transformOriginY = 'bottom';
}
if (left >= srcRect.left + props.src.offsetWidth + (fixed.value ? 0 : window.pageXOffset)) {
if (left >= srcRect.left + props.src.offsetWidth + (fixed ? 0 : window.pageXOffset)) {
transformOriginX = 'left';
} else if ((left + width) <= srcRect.left + (fixed.value ? 0 : window.pageXOffset)) {
} else if ((left + width) <= srcRect.left + (fixed ? 0 : window.pageXOffset)) {
transformOriginX = 'right';
}
transformOrigin.value = `${transformOriginX} ${transformOriginY}`;
transformOrigin = `${transformOriginX} ${transformOriginY}`;
popover.style.left = left + 'px';
popover.style.top = top + 'px';
content.style.left = left + 'px';
content.style.top = top + 'px';
};
const onOpened = () => {
emit('opened');
//
const el = content.value!.children[0];
const el = content!.children[0];
el.addEventListener('mousedown', ev => {
contentClicking = true;
window.addEventListener('mouseup', ev => {
@ -235,7 +234,7 @@ onMounted(() => {
// eslint-disable-next-line vue/no-mutating-props
props.src.style.pointerEvents = 'none';
}
fixed.value = (type.value === 'drawer') || (getFixedContainer(props.src) != null);
fixed = (type === 'drawer') || (getFixedContainer(props.src) != null);
await nextTick();
@ -243,10 +242,9 @@ onMounted(() => {
}, { immediate: true });
nextTick(() => {
const popover = content.value;
new ResizeObserver((entries, observer) => {
align();
}).observe(popover!);
}).observe(content!);
});
});
@ -389,7 +387,7 @@ defineExpose({
left: 0;
width: 100%;
height: 100%;
overflow: hidden; overflow: clip;
overflow: clip;
> .content {
position: fixed;

View File

@ -30,7 +30,7 @@ export default defineComponent({
props: {
def: {
type: Array,
required: true
required: true,
},
grid: {
type: Boolean,
@ -64,7 +64,7 @@ export default defineComponent({
box-sizing: border-box;
padding: 10px 16px 10px 8px;
border-radius: 9px;
font-size: 0.95em;
font-size: 0.9em;
&:hover {
text-decoration: none;

View File

@ -105,7 +105,7 @@ function choose(visibility: typeof misskey.noteVisibilities[number]): void {
}
&.active {
color: #fff;
color: var(--fgOnAccent);
background: var(--accent);
}

View File

@ -4,7 +4,7 @@
<header>
<MkSelect v-model="widgetAdderSelected" style="margin-bottom: var(--margin)" class="mk-widget-select">
<template #label>{{ $ts.selectWidget }}</template>
<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ $t(`_widgets.${widget}`) }}</option>
<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ i18n.t(`_widgets.${widget}`) }}</option>
</MkSelect>
<MkButton inline primary class="mk-widget-add" @click="addWidget"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton>
<MkButton inline @click="$emit('exit')">{{ $ts.close }}</MkButton>
@ -26,79 +26,91 @@
</template>
</XDraggable>
</template>
<component :is="`mkw-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" class="widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)"/>
<component :is="`mkw-${widget.name}`" v-for="widget in widgets" v-else :key="widget.id" :ref="el => widgetRefs[widget.id] = el" class="widget" :widget="widget" @updateProps="updateWidget(widget.id, $event)" @contextmenu.stop="onContextmenu(widget, $event)"/>
</div>
</template>
<script lang="ts">
import { defineComponent, defineAsyncComponent, reactive, ref, computed } from 'vue';
<script lang="ts" setup>
import { defineAsyncComponent, reactive, ref, computed } from 'vue';
import { v4 as uuid } from 'uuid';
import MkSelect from '@/components/form/select.vue';
import MkButton from '@/components/ui/button.vue';
import { widgets as widgetDefs } from '@/widgets';
import * as os from '@/os';
import { i18n } from '@/i18n';
export default defineComponent({
components: {
XDraggable: defineAsyncComponent(() => import('vuedraggable')),
MkSelect,
MkButton,
},
const XDraggable = defineAsyncComponent(() => import('vuedraggable'));
props: {
widgets: {
type: Array,
required: true,
},
edit: {
type: Boolean,
required: true,
},
},
type Widget = {
name: string;
id: string;
data: Record<string, any>;
};
emits: ['updateWidgets', 'addWidget', 'removeWidget', 'updateWidget', 'exit'],
const props = defineProps<{
widgets: Widget[];
edit: boolean;
}>();
setup(props, context) {
const widgetRefs = reactive({});
const configWidget = (id: string) => {
widgetRefs[id].configure();
};
const widgetAdderSelected = ref(null);
const addWidget = () => {
if (widgetAdderSelected.value == null) return;
const emit = defineEmits<{
(ev: 'updateWidgets', widgets: Widget[]): void;
(ev: 'addWidget', widget: Widget): void;
(ev: 'removeWidget', widget: Widget): void;
(ev: 'updateWidget', widget: Partial<Widget>): void;
(ev: 'exit'): void;
}>();
context.emit('addWidget', {
name: widgetAdderSelected.value,
id: uuid(),
data: {},
});
const widgetRefs = {};
const configWidget = (id: string) => {
widgetRefs[id].configure();
};
const widgetAdderSelected = ref(null);
const addWidget = () => {
if (widgetAdderSelected.value == null) return;
widgetAdderSelected.value = null;
};
const removeWidget = (widget) => {
context.emit('removeWidget', widget);
};
const updateWidget = (id, data) => {
context.emit('updateWidget', { id, data });
};
const widgets_ = computed({
get: () => props.widgets,
set: (value) => {
context.emit('updateWidgets', value);
},
});
emit('addWidget', {
name: widgetAdderSelected.value,
id: uuid(),
data: {},
});
return {
widgetRefs,
configWidget,
widgetAdderSelected,
widgetDefs,
addWidget,
removeWidget,
updateWidget,
widgets_,
};
widgetAdderSelected.value = null;
};
const removeWidget = (widget) => {
emit('removeWidget', widget);
};
const updateWidget = (id, data) => {
emit('updateWidget', { id, data });
};
const widgets_ = computed({
get: () => props.widgets,
set: (value) => {
emit('updateWidgets', value);
},
});
function onContextmenu(widget: Widget, ev: MouseEvent) {
const isLink = (el: HTMLElement) => {
if (el.tagName === 'A') return true;
if (el.parentElement) {
return isLink(el.parentElement);
}
};
if (isLink(ev.target)) return;
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return;
if (window.getSelection()?.toString() !== '') return;
os.contextMenu([{
type: 'label',
text: i18n.t(`_widgets.${widget.name}`),
}, {
icon: 'fas fa-cog',
text: i18n.ts.settings,
action: () => {
configWidget(widget.id);
},
}], ev);
}
</script>
<style lang="scss" scoped>

View File

@ -27,8 +27,8 @@ function getClassOrder(width: number, queue: Value): ClassOrder {
...(queue.min ? queue.min.filter(v => width >= v).map(getMinClass) : []),
],
remove: [
...(queue.max ? queue.max.filter(v => width > v).map(getMaxClass) : []),
...(queue.min ? queue.min.filter(v => width < v).map(getMinClass) : []),
...(queue.max ? queue.max.filter(v => width > v).map(getMaxClass) : []),
...(queue.min ? queue.min.filter(v => width < v).map(getMinClass) : []),
]
};
}

View File

@ -39,401 +39,403 @@ import { reactionPicker } from '@/scripts/reaction-picker';
import { getUrlWithoutLoginId } from '@/scripts/login-id';
import { getAccountFromId } from '@/scripts/get-account-from-id';
console.info(`Misskey v${version}`);
(async () => {
console.info(`Misskey v${version}`);
if (_DEV_) {
console.warn('Development mode!!!');
if (_DEV_) {
console.warn('Development mode!!!');
console.info(`vue ${vueVersion}`);
console.info(`vue ${vueVersion}`);
(window as any).$i = $i;
(window as any).$store = defaultStore;
(window as any).$i = $i;
(window as any).$store = defaultStore;
window.addEventListener('error', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled error',
text: event.message
window.addEventListener('error', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled error',
text: event.message
});
*/
});
*/
window.addEventListener('unhandledrejection', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled promise rejection',
text: event.reason
});
*/
});
}
// タッチデバイスでCSSの:hoverを機能させる
document.addEventListener('touchend', () => {}, { passive: true });
// 一斉リロード
reloadChannel.addEventListener('message', path => {
if (path !== null) location.href = path;
else location.reload();
});
window.addEventListener('unhandledrejection', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled promise rejection',
text: event.reason
});
*/
});
}
// タッチデバイスでCSSの:hoverを機能させる
document.addEventListener('touchend', () => {}, { passive: true });
// 一斉リロード
reloadChannel.addEventListener('message', path => {
if (path !== null) location.href = path;
else location.reload();
});
//#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
// TODO: いつの日にか消したい
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
window.addEventListener('resize', () => {
//#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
// TODO: いつの日にか消したい
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
//#endregion
window.addEventListener('resize', () => {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
//#endregion
// If mobile, insert the viewport meta tag
if (['smartphone', 'tablet'].includes(deviceKind)) {
const viewport = document.getElementsByName('viewport').item(0);
viewport.setAttribute('content',
`${viewport.getAttribute('content')}, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover`);
}
//#region Set lang attr
const html = document.documentElement;
html.setAttribute('lang', lang);
//#endregion
//#region loginId
const params = new URLSearchParams(location.search);
const loginId = params.get('loginId');
if (loginId) {
const target = getUrlWithoutLoginId(location.href);
if (!$i || $i.id !== loginId) {
const account = await getAccountFromId(loginId);
if (account) {
await login(account.token, target);
}
// If mobile, insert the viewport meta tag
if (['smartphone', 'tablet'].includes(deviceKind)) {
const viewport = document.getElementsByName('viewport').item(0);
viewport.setAttribute('content',
`${viewport.getAttribute('content')}, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover`);
}
history.replaceState({ misskey: 'loginId' }, '', target);
}
//#region Set lang attr
const html = document.documentElement;
html.setAttribute('lang', lang);
//#endregion
//#endregion
//#region loginId
const params = new URLSearchParams(location.search);
const loginId = params.get('loginId');
//#region Fetch user
if ($i && $i.token) {
if (_DEV_) {
console.log('account cache found. refreshing...');
}
if (loginId) {
const target = getUrlWithoutLoginId(location.href);
refreshAccount();
} else {
if (_DEV_) {
console.log('no account cache found.');
}
// 連携ログインの場合用にCookieを参照する
const i = (document.cookie.match(/igi=(\w+)/) || [null, null])[1];
if (i != null && i !== 'null') {
if (_DEV_) {
console.log('signing...');
}
try {
document.body.innerHTML = '<div>Please wait...</div>';
await login(i);
} catch (err) {
// Render the error screen
// TODO: ちゃんとしたコンポーネントをレンダリングする(v10とかのトラブルシューティングゲーム付きのやつみたいな)
document.body.innerHTML = '<div id="err">Oops!</div>';
}
} else {
if (_DEV_) {
console.log('not signed in');
}
}
}
//#endregion
const fetchInstanceMetaPromise = fetchInstance();
fetchInstanceMetaPromise.then(() => {
localStorage.setItem('v', instance.version);
// Init service worker
initializeSw();
});
const app = createApp(
window.location.search === '?zen' ? defineAsyncComponent(() => import('@/ui/zen.vue')) :
!$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) :
ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) :
ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) :
defineAsyncComponent(() => import('@/ui/universal.vue')),
);
if (_DEV_) {
app.config.performance = true;
}
app.config.globalProperties = {
$i,
$store: defaultStore,
$instance: instance,
$t: i18n.t,
$ts: i18n.ts,
};
widgets(app);
directives(app);
components(app);
const splash = document.getElementById('splash');
// 念のためnullチェック(HTMLが古い場合があるため(そのうち消す))
if (splash) splash.addEventListener('transitionend', () => {
splash.remove();
});
// https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210
// なぜかinit.tsの内容が2回実行されることがあるため、mountするdivを1つに制限する
const rootEl = (() => {
const MISSKEY_MOUNT_DIV_ID = 'misskey_app';
const currentEl = document.getElementById(MISSKEY_MOUNT_DIV_ID);
if (currentEl) {
console.warn('multiple import detected');
return currentEl;
}
const rootEl = document.createElement('div');
rootEl.id = MISSKEY_MOUNT_DIV_ID;
document.body.appendChild(rootEl);
return rootEl;
})();
app.mount(rootEl);
// boot.jsのやつを解除
window.onerror = null;
window.onunhandledrejection = null;
reactionPicker.init();
if (splash) {
splash.style.opacity = '0';
splash.style.pointerEvents = 'none';
}
// クライアントが更新されたか?
const lastVersion = localStorage.getItem('lastVersion');
if (lastVersion !== version) {
localStorage.setItem('lastVersion', version);
// テーマリビルドするため
localStorage.removeItem('theme');
try { // 変なバージョン文字列来るとcompareVersionsでエラーになるため
if (lastVersion != null && compareVersions(version, lastVersion) === 1) {
// ログインしてる場合だけ
if ($i) {
popup(defineAsyncComponent(() => import('@/components/updated.vue')), {}, {}, 'closed');
if (!$i || $i.id !== loginId) {
const account = await getAccountFromId(loginId);
if (account) {
await login(account.token, target);
}
}
} catch (err) {
history.replaceState({ misskey: 'loginId' }, '', target);
}
}
// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため)
watch(defaultStore.reactiveState.darkMode, (darkMode) => {
applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
}, { immediate: localStorage.theme == null });
//#endregion
const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme'));
const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme'));
//#region Fetch user
if ($i && $i.token) {
if (_DEV_) {
console.log('account cache found. refreshing...');
}
watch(darkTheme, (theme) => {
if (defaultStore.state.darkMode) {
applyTheme(theme);
}
});
watch(lightTheme, (theme) => {
if (!defaultStore.state.darkMode) {
applyTheme(theme);
}
});
//#region Sync dark mode
if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', isDeviceDarkmode());
}
window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', mql.matches);
}
});
//#endregion
fetchInstanceMetaPromise.then(() => {
if (defaultStore.state.themeInitial) {
if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme));
if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme));
defaultStore.set('themeInitial', false);
}
});
watch(defaultStore.reactiveState.useBlurEffectForModal, v => {
document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none');
}, { immediate: true });
watch(defaultStore.reactiveState.useBlurEffect, v => {
if (v) {
document.documentElement.style.removeProperty('--blur');
refreshAccount();
} else {
document.documentElement.style.setProperty('--blur', 'none');
}
}, { immediate: true });
if (_DEV_) {
console.log('no account cache found.');
}
let reloadDialogShowing = false;
stream.on('_disconnected_', async () => {
if (defaultStore.state.serverDisconnectedBehavior === 'reload') {
location.reload();
} else if (defaultStore.state.serverDisconnectedBehavior === 'dialog') {
if (reloadDialogShowing) return;
reloadDialogShowing = true;
const { canceled } = await confirm({
type: 'warning',
title: i18n.ts.disconnectedFromServer,
text: i18n.ts.reloadConfirm,
});
reloadDialogShowing = false;
if (!canceled) {
// 連携ログインの場合用にCookieを参照する
const i = (document.cookie.match(/igi=(\w+)/) || [null, null])[1];
if (i != null && i !== 'null') {
if (_DEV_) {
console.log('signing...');
}
try {
document.body.innerHTML = '<div>Please wait...</div>';
await login(i);
} catch (err) {
// Render the error screen
// TODO: ちゃんとしたコンポーネントをレンダリングする(v10とかのトラブルシューティングゲーム付きのやつみたいな)
document.body.innerHTML = '<div id="err">Oops!</div>';
}
} else {
if (_DEV_) {
console.log('not signed in');
}
}
}
//#endregion
const fetchInstanceMetaPromise = fetchInstance();
fetchInstanceMetaPromise.then(() => {
localStorage.setItem('v', instance.version);
// Init service worker
initializeSw();
});
const app = createApp(
window.location.search === '?zen' ? defineAsyncComponent(() => import('@/ui/zen.vue')) :
!$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) :
ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) :
ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) :
defineAsyncComponent(() => import('@/ui/universal.vue')),
);
if (_DEV_) {
app.config.performance = true;
}
app.config.globalProperties = {
$i,
$store: defaultStore,
$instance: instance,
$t: i18n.t,
$ts: i18n.ts,
};
widgets(app);
directives(app);
components(app);
const splash = document.getElementById('splash');
// 念のためnullチェック(HTMLが古い場合があるため(そのうち消す))
if (splash) splash.addEventListener('transitionend', () => {
splash.remove();
});
// https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210
// なぜかinit.tsの内容が2回実行されることがあるため、mountするdivを1つに制限する
const rootEl = (() => {
const MISSKEY_MOUNT_DIV_ID = 'misskey_app';
const currentEl = document.getElementById(MISSKEY_MOUNT_DIV_ID);
if (currentEl) {
console.warn('multiple import detected');
return currentEl;
}
const rootEl = document.createElement('div');
rootEl.id = MISSKEY_MOUNT_DIV_ID;
document.body.appendChild(rootEl);
return rootEl;
})();
app.mount(rootEl);
// boot.jsのやつを解除
window.onerror = null;
window.onunhandledrejection = null;
reactionPicker.init();
if (splash) {
splash.style.opacity = '0';
splash.style.pointerEvents = 'none';
}
// クライアントが更新されたか?
const lastVersion = localStorage.getItem('lastVersion');
if (lastVersion !== version) {
localStorage.setItem('lastVersion', version);
// テーマリビルドするため
localStorage.removeItem('theme');
try { // 変なバージョン文字列来るとcompareVersionsでエラーになるため
if (lastVersion != null && compareVersions(version, lastVersion) === 1) {
// ログインしてる場合だけ
if ($i) {
popup(defineAsyncComponent(() => import('@/components/updated.vue')), {}, {}, 'closed');
}
}
} catch (err) {
}
}
// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため)
watch(defaultStore.reactiveState.darkMode, (darkMode) => {
applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme'));
}, { immediate: localStorage.theme == null });
const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme'));
const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme'));
watch(darkTheme, (theme) => {
if (defaultStore.state.darkMode) {
applyTheme(theme);
}
});
watch(lightTheme, (theme) => {
if (!defaultStore.state.darkMode) {
applyTheme(theme);
}
});
//#region Sync dark mode
if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', isDeviceDarkmode());
}
window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
if (ColdDeviceStorage.get('syncDeviceDarkMode')) {
defaultStore.set('darkMode', mql.matches);
}
});
//#endregion
fetchInstanceMetaPromise.then(() => {
if (defaultStore.state.themeInitial) {
if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme));
if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme));
defaultStore.set('themeInitial', false);
}
});
watch(defaultStore.reactiveState.useBlurEffectForModal, v => {
document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none');
}, { immediate: true });
watch(defaultStore.reactiveState.useBlurEffect, v => {
if (v) {
document.documentElement.style.removeProperty('--blur');
} else {
document.documentElement.style.setProperty('--blur', 'none');
}
}, { immediate: true });
let reloadDialogShowing = false;
stream.on('_disconnected_', async () => {
if (defaultStore.state.serverDisconnectedBehavior === 'reload') {
location.reload();
} else if (defaultStore.state.serverDisconnectedBehavior === 'dialog') {
if (reloadDialogShowing) return;
reloadDialogShowing = true;
const { canceled } = await confirm({
type: 'warning',
title: i18n.ts.disconnectedFromServer,
text: i18n.ts.reloadConfirm,
});
reloadDialogShowing = false;
if (!canceled) {
location.reload();
}
}
}
});
stream.on('emojiAdded', emojiData => {
// TODO
//store.commit('instance/set', );
});
for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) {
import('./plugin').then(({ install }) => {
install(plugin);
});
}
const hotkeys = {
'd': (): void => {
defaultStore.set('darkMode', !defaultStore.state.darkMode);
},
's': search,
};
stream.on('emojiAdded', emojiData => {
// TODO
//store.commit('instance/set', );
});
if ($i) {
// only add post shortcuts if logged in
hotkeys['p|n'] = post;
if ($i.isDeleted) {
alert({
type: 'warning',
text: i18n.ts.accountDeletionInProgress,
for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) {
import('./plugin').then(({ install }) => {
install(plugin);
});
}
const lastUsed = localStorage.getItem('lastUsed');
if (lastUsed) {
const lastUsedDate = parseInt(lastUsed, 10);
// 二時間以上前なら
if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) {
toast(i18n.t('welcomeBackWithName', {
name: $i.name || $i.username,
}));
}
}
localStorage.setItem('lastUsed', Date.now().toString());
const hotkeys = {
'd': (): void => {
defaultStore.set('darkMode', !defaultStore.state.darkMode);
},
's': search,
};
if ('Notification' in window) {
// 許可を得ていなかったらリクエスト
if (Notification.permission === 'default') {
Notification.requestPermission();
if ($i) {
// only add post shortcuts if logged in
hotkeys['p|n'] = post;
if ($i.isDeleted) {
alert({
type: 'warning',
text: i18n.ts.accountDeletionInProgress,
});
}
const lastUsed = localStorage.getItem('lastUsed');
if (lastUsed) {
const lastUsedDate = parseInt(lastUsed, 10);
// 二時間以上前なら
if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) {
toast(i18n.t('welcomeBackWithName', {
name: $i.name || $i.username,
}));
}
}
localStorage.setItem('lastUsed', Date.now().toString());
if ('Notification' in window) {
// 許可を得ていなかったらリクエスト
if (Notification.permission === 'default') {
Notification.requestPermission();
}
}
const main = markRaw(stream.useChannel('main', null, 'System'));
// 自分の情報が更新されたとき
main.on('meUpdated', i => {
updateAccount(i);
});
main.on('readAllNotifications', () => {
updateAccount({ hasUnreadNotification: false });
});
main.on('unreadNotification', () => {
updateAccount({ hasUnreadNotification: true });
});
main.on('unreadMention', () => {
updateAccount({ hasUnreadMentions: true });
});
main.on('readAllUnreadMentions', () => {
updateAccount({ hasUnreadMentions: false });
});
main.on('unreadSpecifiedNote', () => {
updateAccount({ hasUnreadSpecifiedNotes: true });
});
main.on('readAllUnreadSpecifiedNotes', () => {
updateAccount({ hasUnreadSpecifiedNotes: false });
});
main.on('readAllMessagingMessages', () => {
updateAccount({ hasUnreadMessagingMessage: false });
});
main.on('unreadMessagingMessage', () => {
updateAccount({ hasUnreadMessagingMessage: true });
sound.play('chatBg');
});
main.on('readAllAntennas', () => {
updateAccount({ hasUnreadAntenna: false });
});
main.on('unreadAntenna', () => {
updateAccount({ hasUnreadAntenna: true });
sound.play('antenna');
});
main.on('readAllAnnouncements', () => {
updateAccount({ hasUnreadAnnouncement: false });
});
main.on('readAllChannels', () => {
updateAccount({ hasUnreadChannel: false });
});
main.on('unreadChannel', () => {
updateAccount({ hasUnreadChannel: true });
sound.play('channel');
});
// トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => {
signout();
});
}
const main = markRaw(stream.useChannel('main', null, 'System'));
// 自分の情報が更新されたとき
main.on('meUpdated', i => {
updateAccount(i);
});
main.on('readAllNotifications', () => {
updateAccount({ hasUnreadNotification: false });
});
main.on('unreadNotification', () => {
updateAccount({ hasUnreadNotification: true });
});
main.on('unreadMention', () => {
updateAccount({ hasUnreadMentions: true });
});
main.on('readAllUnreadMentions', () => {
updateAccount({ hasUnreadMentions: false });
});
main.on('unreadSpecifiedNote', () => {
updateAccount({ hasUnreadSpecifiedNotes: true });
});
main.on('readAllUnreadSpecifiedNotes', () => {
updateAccount({ hasUnreadSpecifiedNotes: false });
});
main.on('readAllMessagingMessages', () => {
updateAccount({ hasUnreadMessagingMessage: false });
});
main.on('unreadMessagingMessage', () => {
updateAccount({ hasUnreadMessagingMessage: true });
sound.play('chatBg');
});
main.on('readAllAntennas', () => {
updateAccount({ hasUnreadAntenna: false });
});
main.on('unreadAntenna', () => {
updateAccount({ hasUnreadAntenna: true });
sound.play('antenna');
});
main.on('readAllAnnouncements', () => {
updateAccount({ hasUnreadAnnouncement: false });
});
main.on('readAllChannels', () => {
updateAccount({ hasUnreadChannel: false });
});
main.on('unreadChannel', () => {
updateAccount({ hasUnreadChannel: true });
sound.play('channel');
});
// トークンが再生成されたとき
// このままではMisskeyが利用できないので強制的にサインアウトさせる
main.on('myTokenRegenerated', () => {
signout();
});
}
// shortcut
document.addEventListener('keydown', makeHotkey(hotkeys));
// shortcut
document.addEventListener('keydown', makeHotkey(hotkeys));
})();

View File

@ -3,6 +3,7 @@
import { EventEmitter } from 'eventemitter3';
import { Ref, Component, ref, shallowRef, ShallowRef } from 'vue';
import { pleaseLogin } from '@/scripts/please-login';
import { safeURIDecode } from '@/scripts/safe-uri-decode';
type RouteDef = {
path: string;
@ -116,7 +117,7 @@ export class Router extends EventEmitter<{
}
if (p.wildcard) {
if (parts.length !== 0) {
props.set(p.name, parts.join('/'));
props.set(p.name, safeURIDecode(parts.join('/')));
parts = [];
}
break pathMatchLoop;
@ -124,10 +125,12 @@ export class Router extends EventEmitter<{
if (p.startsWith) {
if (parts[0] == null || !parts[0].startsWith(p.startsWith)) continue forEachRouteLoop;
props.set(p.name, parts[0].substring(p.startsWith.length));
props.set(p.name, safeURIDecode(parts[0].substring(p.startsWith.length)));
parts.shift();
} else {
props.set(p.name, parts[0]);
if (parts[0]) {
props.set(p.name, safeURIDecode(parts[0]));
}
parts.shift();
}
}
@ -137,7 +140,7 @@ export class Router extends EventEmitter<{
if (parts.length !== 0) continue forEachRouteLoop;
if (route.hash != null && hash != null) {
props.set(route.hash, hash);
props.set(route.hash, safeURIDecode(hash));
}
if (route.query != null && queryString != null) {
@ -147,7 +150,7 @@ export class Router extends EventEmitter<{
for (const q in route.query) {
const as = route.query[q];
if (queryObject[q]) {
props.set(as, queryObject[q]);
props.set(as, safeURIDecode(queryObject[q]));
}
}
}

View File

@ -1,7 +1,7 @@
<template>
<MkStickyContainer>
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<div style="overflow: hidden; overflow: clip;">
<div style="overflow: clip;">
<MkSpacer :content-max="600" :margin-min="20">
<div class="_formRoot znqjceqz">
<div id="debug"></div>

View File

@ -138,7 +138,7 @@ definePageMetadata(computed(() => ({
.fwhjspax {
text-align: center;
border-radius: 10px;
overflow: hidden; overflow: clip;
overflow: clip;
background-size: cover;
background-position: center center;

View File

@ -58,7 +58,7 @@ let view = $ref(null);
let el = $ref(null);
let pageProps = $ref({});
let noMaintainerInformation = isEmpty(instance.maintainerName) || isEmpty(instance.maintainerEmail);
let noBotProtection = !instance.enableHcaptcha && !instance.enableRecaptcha;
let noBotProtection = !instance.disableRegistration && !instance.enableHcaptcha && !instance.enableRecaptcha;
let noEmailServer = !instance.enableEmail;
let thereIsUnresolvedAbuseReport = $ref(false);

View File

@ -355,7 +355,7 @@ async function renderChart() {
plugins: [{
id: 'vLine',
beforeDraw(chart, args, options) {
if (chart.tooltip._active && chart.tooltip._active.length) {
if (chart.tooltip?._active?.length) {
const activePoint = chart.tooltip._active[0];
const ctx = chart.ctx;
const x = activePoint.element.x;
@ -561,7 +561,7 @@ definePageMetadata({
> .body {
background: var(--panel);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
}
@ -620,7 +620,7 @@ definePageMetadata({
> .body {
background: var(--panel);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
}
}

View File

@ -110,7 +110,7 @@ definePageMetadata(computed(() => antenna ? {
> .tl {
background: var(--bg);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
&.min-width_800px {

View File

@ -1,5 +1,9 @@
<template>
<MkSpacer :content-max="1200">
<MkTab v-model="origin" style="margin-bottom: var(--margin);">
<option value="local">{{ $ts.local }}</option>
<option value="remote">{{ $ts.remote }}</option>
</MkTab>
<div v-if="origin === 'local'">
<template v-if="tag == null">
<MkFolder class="_gap" persist-key="explore-pinned-users">
@ -57,16 +61,17 @@
import { computed, watch } from 'vue';
import XUserList from '@/components/user-list.vue';
import MkFolder from '@/components/ui/folder.vue';
import MkTab from '@/components/tab.vue';
import number from '@/filters/number';
import * as os from '@/os';
import { i18n } from '@/i18n';
import { instance } from '@/instance';
const props = defineProps<{
origin: 'local' | 'remote';
tag?: string;
}>();
let origin = $ref('local');
let tagsEl = $ref<InstanceType<typeof MkFolder>>();
let tagsLocal = $ref([]);
let tagsRemote = $ref([]);

View File

@ -5,11 +5,8 @@
<div v-if="tab === 'featured'">
<XFeatured/>
</div>
<div v-else-if="tab === 'localUsers'">
<XUsers origin="local"/>
</div>
<div v-else-if="tab === 'remoteUsers'">
<XUsers origin="remote"/>
<div v-else-if="tab === 'users'">
<XUsers/>
</div>
<div v-else-if="tab === 'search'">
<MkSpacer :content-max="1200">
@ -75,13 +72,9 @@ const headerTabs = $computed(() => [{
icon: 'fas fa-bolt',
title: i18n.ts.featured,
}, {
key: 'localUsers',
key: 'users',
icon: 'fas fa-users',
title: i18n.ts.users,
}, {
key: 'remoteUsers',
icon: 'fas fa-users',
title: i18n.ts.remote,
}, {
key: 'search',
title: i18n.ts.search,

View File

@ -188,7 +188,7 @@ definePageMetadata({
background-size: cover;
background-position: center;
border-radius: 10px;
overflow: hidden; overflow: clip;
overflow: clip;
> .avatar {
display: inline-block;

View File

@ -181,7 +181,7 @@ definePageMetadata({
> .toggleWrapper {
display: inline-block;
text-align: left;
overflow: hidden; overflow: clip;
overflow: clip;
padding: 0 100px;
input {

View File

@ -177,7 +177,7 @@ definePageMetadata(computed(() => ({
> .tl {
background: var(--bg);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
}
</style>

View File

@ -103,7 +103,7 @@ definePageMetadata(computed(() => list ? {
> .tl {
background: var(--bg);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
&.min-width_800px {

View File

@ -90,7 +90,7 @@ export default defineComponent({
> .img {
height: 128px;
border-radius: 6px;
overflow: hidden; overflow: clip;
overflow: clip;
}
}

View File

@ -276,7 +276,7 @@ function showMenu(ev) {
-webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px));
border-radius: 999px;
overflow: hidden; overflow: clip;
overflow: clip;
width: 800px;
padding: 8px 0;

View File

@ -8,4 +8,6 @@ export type UnicodeEmojiDef = {
}
// initial converted from https://github.com/muan/emojilib/commit/242fe68be86ed6536843b83f7e32f376468b38fb
export const emojilist = (await import('../emojilist.json')).default as UnicodeEmojiDef[];
import _emojilist from '../emojilist.json';
export const emojilist = _emojilist as UnicodeEmojiDef[];

View File

@ -16,7 +16,7 @@ export type TextValue = ExprBase & {
value: string;
};
export type MultiLineTextValue = ExprBase & {
export type MultiLineTextValue = ExprBase & {
type: 'multiLineText';
value: string;
};

View File

@ -11,16 +11,15 @@ const fallbackName = (key: string) => `idbfallback::${key}`;
let idbAvailable = typeof window !== 'undefined' ? !!window.indexedDB : true;
if (idbAvailable) {
try {
await iset('idb-test', 'test');
} catch (err) {
iset('idb-test', 'test').catch(err => {
console.error('idb error', err);
console.error('indexedDB is unavailable. It will use localStorage.');
idbAvailable = false;
}
});
} else {
console.error('indexedDB is unavailable. It will use localStorage.');
}
if (!idbAvailable) console.error('indexedDB is unavailable. It will use localStorage.');
export async function get(key: string) {
if (idbAvailable) return iget(key);
return JSON.parse(localStorage.getItem(fallbackName(key)));

View File

@ -0,0 +1,7 @@
export function safeURIDecode(str: string): string {
try {
return decodeURIComponent(str);
} catch {
return str;
}
}

View File

@ -1,6 +1,6 @@
import { ref } from 'vue';
import { globalEvents } from '@/events';
import tinycolor from 'tinycolor2';
import { globalEvents } from '@/events';
export type Theme = {
id: string;
@ -31,11 +31,11 @@ export const getBuiltinThemes = () => Promise.all(
'd-astro',
'd-future',
'd-botanical',
'd-green-lime',
'd-green-orange',
'd-cherry',
'd-ice',
'd-pumpkin',
'd-black',
].map(name => import(`../themes/${name}.json5`).then(({ default: _default }): Theme => _default))
].map(name => import(`../themes/${name}.json5`).then(({ default: _default }): Theme => _default)),
);
export const getBuiltinThemesRef = () => {

View File

@ -252,7 +252,7 @@ hr {
._panel {
background: var(--panel);
border-radius: var(--radius);
overflow: hidden; overflow: clip;
overflow: clip;
}
._block {

View File

@ -1,17 +0,0 @@
{
id: '8c539dc1-0fab-4d47-9194-39c508e9bfe1',
name: 'Mi Black',
author: 'syuilo',
base: 'dark',
props: {
divider: '#2d2d2d',
panel: '#131313',
panelHeaderBg: '@panel',
panelHeaderDivider: '@divider',
shadow: 'rgba(255, 255, 255, 0.05)',
modalBg: 'rgba(255, 255, 255, 0.1)',
},
}

View File

@ -0,0 +1,24 @@
{
id: '02816013-8107-440f-877e-865083ffe194',
name: 'Mi Green+Lime Dark',
author: 'syuilo',
base: 'dark',
props: {
accent: '#b4e900',
bg: '#0C1210',
fg: '#dee7e4',
fgHighlighted: '#fff',
fgOnAccent: '#192320',
divider: '#e7fffb24',
panel: '#192320',
panelHeaderBg: '@panel',
panelHeaderDivider: '@divider',
popup: '#293330',
renote: '@accent',
mentionMe: '#ffaa00',
link: '#24d7ce',
},
}

View File

@ -0,0 +1,24 @@
{
id: 'dc489603-27b5-424a-9b25-1ff6aec9824a',
name: 'Mi Green+Orange Dark',
author: 'syuilo',
base: 'dark',
props: {
accent: '#e97f00',
bg: '#0C1210',
fg: '#dee7e4',
fgHighlighted: '#fff',
fgOnAccent: '#192320',
divider: '#e7fffb24',
panel: '#192320',
panelHeaderBg: '@panel',
panelHeaderDivider: '@divider',
popup: '#293330',
renote: '@accent',
mentionMe: '#b4e900',
link: '#24d7ce',
},
}

View File

@ -1,88 +0,0 @@
{
id: '0b64fef3-02c7-20b5-dd87-b3f77e2b4301',
name: 'Mi Pumpkin Dark',
author: 'syuilo',
base: 'dark',
props: {
X2: ':darken<2<@panel',
X3: 'rgba(255, 255, 255, 0.05)',
X4: 'rgba(255, 255, 255, 0.1)',
X5: 'rgba(255, 255, 255, 0.05)',
X6: 'rgba(255, 255, 255, 0.15)',
X7: 'rgba(255, 255, 255, 0.05)',
X8: ':lighten<5<@accent',
X9: ':darken<5<@accent',
bg: 'rgb(37, 32, 47)',
fg: '#e0d5c0',
X10: ':alpha<0.4<@accent',
X11: 'rgba(0, 0, 0, 0.3)',
X12: 'rgba(255, 255, 255, 0.1)',
X13: 'rgba(255, 255, 255, 0.15)',
X14: ':alpha<0.5<@navBg',
X15: ':alpha<0<@panel',
X16: ':alpha<0.7<@panel',
X17: ':alpha<0.8<@bg',
cwBg: '#687390',
cwFg: '#393f4f',
link: 'rgb(172, 193, 68)',
warn: '#ecb637',
badge: '#31b1ce',
error: '#ec4137',
focus: ':alpha<0.3<@accent',
navBg: '@panel',
navFg: '@fg',
panel: ':lighten<3<@bg',
popup: ':lighten<3<@panel',
accent: 'rgb(242, 133, 36)',
header: ':alpha<0.7<@panel',
infoBg: '#253142',
infoFg: '#fff',
renote: 'rgb(110, 179, 72)',
shadow: 'rgba(0, 0, 0, 0.3)',
divider: 'rgba(255, 255, 255, 0.1)',
hashtag: 'rgb(188, 90, 255)',
mention: 'rgb(72, 179, 139)',
modalBg: 'rgba(0, 0, 0, 0.5)',
success: '#86b300',
buttonBg: 'rgba(255, 255, 255, 0.05)',
switchBg: 'rgba(255, 255, 255, 0.15)',
acrylicBg: ':alpha<0.5<@bg',
cwHoverBg: '#707b97',
indicator: '@accent',
mentionMe: '@accent',
messageBg: '@bg',
navActive: '@accent',
accentedBg: ':alpha<0.15<@accent',
fgOnAccent: '#000',
infoWarnBg: '#42321c',
infoWarnFg: '#ffbd3e',
navHoverFg: ':lighten<17<@fg',
dateLabelFg: '@fg',
inputBorder: 'rgba(255, 255, 255, 0.1)',
panelBorder: '" solid 1px var(--divider)',
accentDarken: ':darken<10<@accent',
acrylicPanel: ':alpha<0.5<@panel',
navIndicator: '@indicator',
accentLighten: ':lighten<10<@accent',
buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
driveFolderBg: ':alpha<0.3<@accent',
fgHighlighted: ':lighten<3<@fg',
fgTransparent: ':alpha<0.5<@fg',
panelHeaderBg: ':lighten<3<@panel',
panelHeaderFg: '@fg',
buttonGradateA: '@accent',
buttonGradateB: ':hue<20<@accent',
htmlThemeColor: '@bg',
panelHighlight: ':lighten<3<@panel',
listItemHoverBg: 'rgba(255, 255, 255, 0.03)',
scrollbarHandle: 'rgba(255, 255, 255, 0.2)',
inputBorderHover: 'rgba(255, 255, 255, 0.2)',
wallpaperOverlay: 'rgba(0, 0, 0, 0.5)',
fgTransparentWeak: ':alpha<0.75<@fg',
panelHeaderDivider: 'rgba(0, 0, 0, 0)',
scrollbarHandleHover: 'rgba(255, 255, 255, 0.4)',
},
}

View File

@ -64,7 +64,7 @@ const XUserList = defineAsyncComponent(() => import('./statusbar-user-list.vue')
width: 100%;
line-height: var(--height);
height: var(--height);
overflow: hidden; overflow: clip;
overflow: clip;
contain: strict;
> .name {

View File

@ -241,7 +241,7 @@ onMounted(() => {
border-left: solid 1px var(--divider);
border-right: solid 1px var(--divider);
border-radius: 0;
overflow: hidden; overflow: clip;
overflow: clip;
--margin: 12px;
}

View File

@ -9,7 +9,7 @@
</template>
<script lang="ts" setup>
import { } from 'vue';
import { } from 'vue';
import XColumn from './column.vue';
import XTimeline from '@/components/timeline.vue';
import * as os from '@/os';

View File

@ -39,15 +39,15 @@ let pointsRenote: any = $ref(null);
let pointsTotal: any = $ref(null);
function dragListen(fn) {
window.addEventListener('mousemove', fn);
window.addEventListener('mousemove', fn);
window.addEventListener('mouseleave', dragClear.bind(null, fn));
window.addEventListener('mouseup', dragClear.bind(null, fn));
window.addEventListener('mouseup', dragClear.bind(null, fn));
}
function dragClear(fn) {
window.removeEventListener('mousemove', fn);
window.removeEventListener('mousemove', fn);
window.removeEventListener('mouseleave', dragClear);
window.removeEventListener('mouseup', dragClear);
window.removeEventListener('mouseup', dragClear);
}
function onMousedown(ev) {

View File

@ -49,6 +49,7 @@ export default defineConfig(({ command, mode }) => {
'chrome100',
'firefox100',
'safari15',
'es2017', // TODO: そのうち消す
],
manifest: 'manifest.json',
rollupOptions: {

View File

@ -515,14 +515,14 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.0.tgz#524a11e15c09701733033c96943ecf33f55d9ca1"
integrity sha512-lvhRJ2pGe2V9MEU46ELTdiHgiAFZPKtLhiU5wlnaYpMc2+c1R8fh8i80ZAa665drvjHKUJyRRGg3gEm1If54ow==
"@typescript-eslint/eslint-plugin@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz#9c6017b6c1d04894141b4a87816388967f64c359"
integrity sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==
dependencies:
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/type-utils" "5.30.0"
"@typescript-eslint/utils" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/type-utils" "5.30.6"
"@typescript-eslint/utils" "5.30.6"
debug "^4.3.4"
functional-red-black-tree "^1.0.1"
ignore "^5.2.0"
@ -530,69 +530,69 @@
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/parser@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.0.tgz#a2184fb5f8ef2bf1db0ae61a43907e2e32aa1b8f"
integrity sha512-2oYYUws5o2liX6SrFQ5RB88+PuRymaM2EU02/9Ppoyu70vllPnHVO7ioxDdq/ypXHA277R04SVjxvwI8HmZpzA==
"@typescript-eslint/parser@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.6.tgz#add440db038fa9d777e4ebdaf66da9e7fb7abe92"
integrity sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==
dependencies:
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/typescript-estree" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/typescript-estree" "5.30.6"
debug "^4.3.4"
"@typescript-eslint/scope-manager@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.0.tgz#bf585ee801ab4ad84db2f840174e171a6bb002c7"
integrity sha512-3TZxvlQcK5fhTBw5solQucWSJvonXf5yua5nx8OqK94hxdrT7/6W3/CS42MLd/f1BmlmmbGEgQcTHHCktUX5bQ==
"@typescript-eslint/scope-manager@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz#ce1b49ff5ce47f55518d63dbe8fc9181ddbd1a33"
integrity sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/visitor-keys" "5.30.0"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/visitor-keys" "5.30.6"
"@typescript-eslint/type-utils@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.0.tgz#98f3af926a5099153f092d4dad87148df21fbaae"
integrity sha512-GF8JZbZqSS+azehzlv/lmQQ3EU3VfWYzCczdZjJRxSEeXDQkqFhCBgFhallLDbPwQOEQ4MHpiPfkjKk7zlmeNg==
"@typescript-eslint/type-utils@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz#a64aa9acbe609ab77f09f53434a6af2b9685f3af"
integrity sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==
dependencies:
"@typescript-eslint/utils" "5.30.0"
"@typescript-eslint/utils" "5.30.6"
debug "^4.3.4"
tsutils "^3.21.0"
"@typescript-eslint/types@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.0.tgz#db7d81d585a3da3801432a9c1d2fafbff125e110"
integrity sha512-vfqcBrsRNWw/LBXyncMF/KrUTYYzzygCSsVqlZ1qGu1QtGs6vMkt3US0VNSQ05grXi5Yadp3qv5XZdYLjpp8ag==
"@typescript-eslint/types@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.6.tgz#86369d0a7af8c67024115ac1da3e8fb2d38907e1"
integrity sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==
"@typescript-eslint/typescript-estree@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.0.tgz#4565ee8a6d2ac368996e20b2344ea0eab1a8f0bb"
integrity sha512-hDEawogreZB4n1zoqcrrtg/wPyyiCxmhPLpZ6kmWfKF5M5G0clRLaEexpuWr31fZ42F96SlD/5xCt1bT5Qm4Nw==
"@typescript-eslint/typescript-estree@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz#a84a0d6a486f9b54042da1de3d671a2c9f14484e"
integrity sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/visitor-keys" "5.30.0"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/visitor-keys" "5.30.6"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.0.tgz#1dac771fead5eab40d31860716de219356f5f754"
integrity sha512-0bIgOgZflLKIcZsWvfklsaQTM3ZUbmtH0rJ1hKyV3raoUYyeZwcjQ8ZUJTzS7KnhNcsVT1Rxs7zeeMHEhGlltw==
"@typescript-eslint/utils@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.6.tgz#1de2da14f678e7d187daa6f2e4cdb558ed0609dc"
integrity sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==
dependencies:
"@types/json-schema" "^7.0.9"
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/typescript-estree" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/typescript-estree" "5.30.6"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/visitor-keys@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.0.tgz#07721d23daca2ec4c2da7f1e660d41cd78bacac3"
integrity sha512-6WcIeRk2DQ3pHKxU1Ni0qMXJkjO/zLjBymlYBy/53qxe7yjEFSvzKLDToJjURUhSl2Fzhkl4SMXQoETauF74cw==
"@typescript-eslint/visitor-keys@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz#94dd10bb481c8083378d24de1742a14b38a2678c"
integrity sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/types" "5.30.6"
eslint-visitor-keys "^3.3.0"
"@ungap/promise-all-settled@1.1.2":
@ -600,10 +600,10 @@
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
"@vitejs/plugin-vue@3.0.0-beta.1":
version "3.0.0-beta.1"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.0.0-beta.1.tgz#65a6be6ed619955a5edea6115dedcfc5da4ed3f6"
integrity sha512-cPVQHIKZkVEQ8qW7+BlbTrGJXNpP2aMKzVhQdTnWK9u6cSDmVdZOXHmKPO2KVvrNpFXXS8R7hHBXMsSApA+XOA==
"@vitejs/plugin-vue@3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.0.0.tgz#7081e2b3fbe04e291bb85107b9fb57a1fa5e6aeb"
integrity sha512-yWP34ArFh/jAeNUDkkLz/kVRLjf5ppJiq4L36f64Cp6dIrMQeYZGDP9xxdemlXfZR9ylN9JgHUl3GzfqOtgYDg==
"@vue/compiler-core@3.2.37":
version "3.2.37"
@ -1715,10 +1715,10 @@ eslint-plugin-import@2.26.0:
resolve "^1.22.0"
tsconfig-paths "^3.14.1"
eslint-plugin-vue@9.1.1:
version "9.1.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.1.1.tgz#341f7533cb041958455138834341d5be01f9f327"
integrity sha512-W9n5PB1X2jzC7CK6riG0oAcxjmKrjTF6+keL1rni8n57DZeilx/Fulz+IRJK3lYseLNAygN0I62L7DvioW40Tw==
eslint-plugin-vue@9.2.0:
version "9.2.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.2.0.tgz#b7ca02b2ce8218b7586346440fc61c2655db353a"
integrity sha512-W2hc+NUXoce8sZtWgZ45miQTy6jNyuSdub5aZ1IBune4JDeAyzucYX0TzkrQ1jMO52sNUDYlCIHDoaNePe0p5g==
dependencies:
eslint-utils "^3.0.0"
natural-compare "^1.4.0"
@ -1761,10 +1761,10 @@ eslint-visitor-keys@^3.3.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
eslint@8.18.0:
version "8.18.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.18.0.tgz#78d565d16c993d0b73968c523c0446b13da784fd"
integrity sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==
eslint@8.19.0:
version "8.19.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.19.0.tgz#7342a3cbc4fbc5c106a1eefe0fd0b50b6b1a7d28"
integrity sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==
dependencies:
"@eslint/eslintrc" "^1.3.0"
"@humanwhocodes/config-array" "^0.9.2"
@ -2866,12 +2866,12 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
mfm-js@0.22.1:
version "0.22.1"
resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.22.1.tgz#ad5f0b95cc903ca5a5e414e2edf64ac4648dc8c2"
integrity sha512-UV5zvDKlWPpBFeABhyCzuOTJ3RwrNrmVpJ+zz/dFX6D/ntEywljgxkfsLamcy0ZSwUAr0O+WQxGHvAwyxUgsAQ==
mfm-js@0.23.0-canary.1:
version "0.23.0-canary.1"
resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.23.0-canary.1.tgz#1b7b7635f18bed9776054406b72e6bd613c8d0eb"
integrity sha512-SkMrW1rQAv+mFGtLKN9DSv6vxSREDu8ChmkBl1Ch5sQfp47BhuvcRg5EKGmt3WAQRAOylXYMg8wVYR7C5BHKeA==
dependencies:
twemoji-parser "14.0.x"
twemoji-parser "14.0.0"
micromatch@^4.0.2:
version "4.0.2"
@ -3649,7 +3649,14 @@ rndstr@1.0.0:
rangestr "0.0.1"
seedrandom "2.4.2"
rollup@2.75.7, rollup@^2.75.6:
rollup@2.76.0:
version "2.76.0"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.76.0.tgz#c69fe03db530ac53fcb9523b3caa0d3c0b9491a1"
integrity sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==
optionalDependencies:
fsevents "~2.3.2"
rollup@^2.75.6:
version "2.75.7"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.75.7.tgz#221ff11887ae271e37dcc649ba32ce1590aaa0b9"
integrity sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==
@ -4085,7 +4092,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
twemoji-parser@14.0.0, twemoji-parser@14.0.x:
twemoji-parser@14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/twemoji-parser/-/twemoji-parser-14.0.0.tgz#13dabcb6d3a261d9efbf58a1666b182033bf2b62"
integrity sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==
@ -4215,10 +4222,10 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
vite@3.0.0-beta.7:
version "3.0.0-beta.7"
resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.0-beta.7.tgz#ded6483ef3b9b16dbe3a912a35accb9cc3498530"
integrity sha512-yjw154hB229qq5Bl6+/CJSTxC/yIDmDJbaAjE/pdracz3jytNEd2ovk5BvxgZT6+qPiUc2rRH3FgGqiZnweIFw==
vite@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.0.tgz#b4675cb9ab83ec0803b9c952ffa6519bcce033a7"
integrity sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==
dependencies:
esbuild "^0.14.47"
postcss "^8.4.14"

View File

@ -53,7 +53,6 @@ module.exports = {
'no-empty-pattern': ['warn'],
'no-async-promise-executor': ['off'],
'no-useless-escape': ['off'],
'no-multi-spaces': ['warn'],
'no-multiple-empty-lines': ['error', { 'max': 1 }],
'no-control-regex': ['warn'],
'no-empty': ['warn'],

View File

@ -42,8 +42,12 @@ self.addEventListener('push', ev => {
// case 'driveFileCreated':
case 'notification':
case 'unreadMessagingMessage':
// 1日以上経過している場合は無視
if ((new Date()).getTime() - data.dateTime > 1000 * 60 * 60 * 24) break;
// クライアントがあったらストリームに接続しているということなので通知しない
if (clients.length != 0) return;
if (clients.length !== 0) break;
return createNotification(data);
case 'readAllNotifications':
for (const n of await self.registration.getNotifications()) {

View File

@ -24,6 +24,7 @@ export type pushNotificationData<K extends keyof pushNotificationDataSourceMap>
type: K;
body: pushNotificationDataSourceMap[K];
userId: string;
dateTime: number;
};
export type pushNotificationDataMap = {

View File

@ -194,48 +194,48 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/parser@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.0.tgz#a2184fb5f8ef2bf1db0ae61a43907e2e32aa1b8f"
integrity sha512-2oYYUws5o2liX6SrFQ5RB88+PuRymaM2EU02/9Ppoyu70vllPnHVO7ioxDdq/ypXHA277R04SVjxvwI8HmZpzA==
"@typescript-eslint/parser@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.6.tgz#add440db038fa9d777e4ebdaf66da9e7fb7abe92"
integrity sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==
dependencies:
"@typescript-eslint/scope-manager" "5.30.0"
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/typescript-estree" "5.30.0"
"@typescript-eslint/scope-manager" "5.30.6"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/typescript-estree" "5.30.6"
debug "^4.3.4"
"@typescript-eslint/scope-manager@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.0.tgz#bf585ee801ab4ad84db2f840174e171a6bb002c7"
integrity sha512-3TZxvlQcK5fhTBw5solQucWSJvonXf5yua5nx8OqK94hxdrT7/6W3/CS42MLd/f1BmlmmbGEgQcTHHCktUX5bQ==
"@typescript-eslint/scope-manager@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz#ce1b49ff5ce47f55518d63dbe8fc9181ddbd1a33"
integrity sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/visitor-keys" "5.30.0"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/visitor-keys" "5.30.6"
"@typescript-eslint/types@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.0.tgz#db7d81d585a3da3801432a9c1d2fafbff125e110"
integrity sha512-vfqcBrsRNWw/LBXyncMF/KrUTYYzzygCSsVqlZ1qGu1QtGs6vMkt3US0VNSQ05grXi5Yadp3qv5XZdYLjpp8ag==
"@typescript-eslint/types@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.6.tgz#86369d0a7af8c67024115ac1da3e8fb2d38907e1"
integrity sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==
"@typescript-eslint/typescript-estree@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.0.tgz#4565ee8a6d2ac368996e20b2344ea0eab1a8f0bb"
integrity sha512-hDEawogreZB4n1zoqcrrtg/wPyyiCxmhPLpZ6kmWfKF5M5G0clRLaEexpuWr31fZ42F96SlD/5xCt1bT5Qm4Nw==
"@typescript-eslint/typescript-estree@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz#a84a0d6a486f9b54042da1de3d671a2c9f14484e"
integrity sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/visitor-keys" "5.30.0"
"@typescript-eslint/types" "5.30.6"
"@typescript-eslint/visitor-keys" "5.30.6"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/visitor-keys@5.30.0":
version "5.30.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.0.tgz#07721d23daca2ec4c2da7f1e660d41cd78bacac3"
integrity sha512-6WcIeRk2DQ3pHKxU1Ni0qMXJkjO/zLjBymlYBy/53qxe7yjEFSvzKLDToJjURUhSl2Fzhkl4SMXQoETauF74cw==
"@typescript-eslint/visitor-keys@5.30.6":
version "5.30.6"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz#94dd10bb481c8083378d24de1742a14b38a2678c"
integrity sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==
dependencies:
"@typescript-eslint/types" "5.30.0"
"@typescript-eslint/types" "5.30.6"
eslint-visitor-keys "^3.3.0"
aggregate-error@^3.0.0: