From a89003b57a27379f056e4f1be907e41e91b7b598 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Sun, 1 May 2022 22:51:07 +0900
Subject: refactor: use Vite to build instead of webpack (#8575)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* update stream.ts

* https://github.com/misskey-dev/misskey/pull/7769#issuecomment-917542339

* fix lint

* clean up?

* add app

* fix

* nanka iroiro

* wip

* wip

* fix lint

* fix loginId

* fix

* refactor

* refactor

* remove follow action

* clean up

* Revert "remove follow action"

This reverts commit defbb416480905af2150d1c92f10d8e1d1288c0a.

* Revert "clean up"

This reverts commit f94919cb9cff41e274044fc69c56ad36a33974f2.

* remove fetch specification

* renoteの条件追加

* apiFetch => cli

* bypass fetch?

* fix

* refactor: use path alias

* temp: add submodule

* remove submodule

* enhane: unison-reloadに指定したパスに移動できるように

* null

* null

* feat: ログインするアカウントのIDをクエリ文字列で指定する機能

* null

* await?

* rename

* rename

* Update read.ts

* merge

* get-note-summary

* fix

* swパッケージに

* add missing packages

* fix getNoteSummary

* add webpack-cli

* :v:

* remove plugins

* sw-inject分離したがテストしてない

* fix notification.vue

* remove a blank line

* disconnect intersection observer

* disconnect2

* fix notification.vue

* remove a blank line

* disconnect intersection observer

* disconnect2

* fix

* :v:

* clean up config

* typesを戻した

* Update packages/client/src/components/notification.vue

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>

* disconnect

* oops

* Failed to load the script unexpectedly回避
sw.jsとlib.tsを分離してみた

* truncate notification

* Update packages/client/src/ui/_common_/common.vue

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>

* clean up

* clean up

* キャッシュ対策

* Truncate push notification message

* クライアントがあったらストリームに接続しているということなので通知しない判定の位置を修正

* components/drive-file-thumbnail.vue

* components/drive-select-dialog.vue

* components/drive-window.vue

* merge

* fix

* Service Workerのビルドにesbuildを使うようにする

* return createEmptyNotification()

* fix

* i18n.ts

* update

* :v:

* remove ts-loader

* fix

* fix

* enhance: Service Workerを常に登録するように

* pollEnded

* URLをsw.jsに戻す

* clean up

* wip

* wip

* wip

* wip

* wip

* wip

* :v:

* use import

* fix

* install rollup

* use defineAsyncComponent.

* fix emojilist

* wip use defineAsyncComponent

* popup(import -> popup(defineAsyncComponent(() => import

* draggable?

* fix init import

* clean up

* fix router

* add comment

* :v:

* :v:

* :v:

* remove webpack

* update vite

* fix boot sequence

* Revert "fix boot sequence"

This reverts commit e893dbf37aed83bf9f12e427d98c78a7065b4a39.

* revert boot import

* never make two app div

* ;

* remove console.log

* change clientEntry sequence

* fix

* Revert "fix"

This reverts commit 12741b3d89950a31dbb1bb81477ddb27b0e9951a.

* fix

* add comment https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210

* add log

* add comment

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
---
 packages/client/src/components/widgets.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'packages/client/src/components/widgets.vue')

diff --git a/packages/client/src/components/widgets.vue b/packages/client/src/components/widgets.vue
index da9d935281..6e4122427b 100644
--- a/packages/client/src/components/widgets.vue
+++ b/packages/client/src/components/widgets.vue
@@ -37,7 +37,7 @@ import { widgets as widgetDefs } from '@/widgets';
 
 export default defineComponent({
 	components: {
-		XDraggable: defineAsyncComponent(() => import('vuedraggable').then(x => x.default)),
+		XDraggable: defineAsyncComponent(() => import('vuedraggable')),
 		MkSelect,
 		MkButton,
 	},
-- 
cgit v1.2.3-freya


From 3dae18b93cc2a219087c4e1a8acc763ff064b71d Mon Sep 17 00:00:00 2001
From: Johann150 <johann.galle@protonmail.com>
Date: Thu, 26 May 2022 15:53:09 +0200
Subject: fix lints (#8737)

* fix: emits use ev instead of e

* fix: errors use err instead of e

* fix: replace use of data where possible

* fix: events use evt instead of e

* fix: use strict equals

* fix: use emoji instead of e

* fix: vue lints
---
 packages/client/src/account.ts                     | 10 ++--
 .../client/src/components/abuse-report-window.vue  |  2 +-
 packages/client/src/components/abuse-report.vue    |  2 +-
 .../src/components/channel-follow-button.vue       |  4 +-
 packages/client/src/components/cw-button.vue       |  2 +-
 packages/client/src/components/dialog.vue          | 16 +++---
 packages/client/src/components/follow-button.vue   |  6 +--
 packages/client/src/components/forgot-password.vue |  4 +-
 packages/client/src/components/form-dialog.vue     |  2 +-
 packages/client/src/components/form/switch.vue     |  2 +-
 packages/client/src/components/global/avatar.vue   |  2 +-
 packages/client/src/components/global/emoji.vue    |  2 +-
 packages/client/src/components/global/time.vue     |  2 +-
 packages/client/src/components/image-viewer.vue    |  2 +-
 packages/client/src/components/media-caption.vue   | 16 +++---
 packages/client/src/components/note-detailed.vue   |  4 +-
 packages/client/src/components/note.vue            |  2 +-
 packages/client/src/components/page/page.post.vue  | 10 ++--
 packages/client/src/components/page/page.vue       | 10 ++--
 packages/client/src/components/poll-editor.vue     |  2 +-
 .../client/src/components/post-form-attaches.vue   |  2 +-
 packages/client/src/components/post-form.vue       |  2 +-
 packages/client/src/components/signup-dialog.vue   |  4 +-
 packages/client/src/components/signup.vue          | 20 +++----
 packages/client/src/components/timeline.vue        |  6 +--
 packages/client/src/components/toast.vue           |  2 +-
 packages/client/src/components/ui/button.vue       | 14 ++---
 packages/client/src/components/ui/context-menu.vue |  6 +--
 packages/client/src/components/ui/menu.vue         |  2 +-
 packages/client/src/components/ui/modal-window.vue |  8 +--
 packages/client/src/components/ui/pagination.vue   |  8 +--
 packages/client/src/components/ui/popup-menu.vue   |  2 +-
 packages/client/src/components/ui/window.vue       | 54 +++++++++----------
 packages/client/src/components/user-preview.vue    |  2 +-
 .../client/src/components/user-select-dialog.vue   |  6 +--
 .../client/src/components/visibility-picker.vue    |  6 +--
 packages/client/src/components/waiting-dialog.vue  |  4 +-
 packages/client/src/components/widgets.vue         |  2 +-
 packages/client/src/filters/bytes.ts               |  2 +-
 packages/client/src/init.ts                        |  6 +--
 packages/client/src/instance.ts                    |  4 +-
 packages/client/src/os.ts                          | 12 ++---
 packages/client/src/pages/admin/emojis.vue         |  8 +--
 packages/client/src/pages/admin/index.vue          |  4 +-
 packages/client/src/pages/channel-editor.vue       |  4 +-
 packages/client/src/pages/emojis.category.vue      |  4 +-
 packages/client/src/pages/emojis.vue               |  4 +-
 packages/client/src/pages/follow.vue               |  2 +-
 packages/client/src/pages/gallery/edit.vue         |  4 +-
 packages/client/src/pages/gallery/post.vue         |  4 +-
 packages/client/src/pages/messaging/index.vue      |  8 +--
 .../src/pages/messaging/messaging-room.form.vue    | 61 +++++++++++-----------
 .../client/src/pages/messaging/messaging-room.vue  | 32 ++++++------
 packages/client/src/pages/note.vue                 |  4 +-
 packages/client/src/pages/page.vue                 |  4 +-
 packages/client/src/pages/settings/2fa.vue         |  4 +-
 .../client/src/pages/settings/plugin.install.vue   |  8 +--
 .../client/src/pages/settings/theme.install.vue    |  2 +-
 .../client/src/pages/settings/webhook.edit.vue     | 16 +++---
 packages/client/src/pages/settings/word-mute.vue   |  2 +-
 packages/client/src/pages/share.vue                |  6 +--
 packages/client/src/pages/theme-editor.vue         |  2 +-
 packages/client/src/pages/user-info.vue            |  4 +-
 packages/client/src/pages/user/index.vue           |  4 +-
 packages/client/src/theme-store.ts                 |  8 +--
 packages/client/src/ui/_common_/sw-inject.ts       | 23 ++++----
 packages/client/src/ui/classic.widgets.vue         |  4 +-
 packages/client/src/ui/deck/deck-store.ts          |  4 +-
 packages/client/src/ui/universal.widgets.vue       |  6 +--
 69 files changed, 255 insertions(+), 257 deletions(-)

(limited to 'packages/client/src/components/widgets.vue')

diff --git a/packages/client/src/account.ts b/packages/client/src/account.ts
index 6f806ccc58..ce4af61f18 100644
--- a/packages/client/src/account.ts
+++ b/packages/client/src/account.ts
@@ -11,10 +11,10 @@ import { i18n } from './i18n';
 
 type Account = misskey.entities.MeDetailed;
 
-const data = localStorage.getItem('account');
+const accountData = localStorage.getItem('account');
 
 // TODO: 外部からはreadonlyに
-export const $i = data ? reactive(JSON.parse(data) as Account) : null;
+export const $i = accountData ? reactive(JSON.parse(accountData) as Account) : null;
 
 export const iAmModerator = $i != null && ($i.isAdmin || $i.isModerator);
 
@@ -52,7 +52,7 @@ export async function signout() {
 					return Promise.all(registrations.map(registration => registration.unregister()));
 				});
 		}
-	} catch (e) {}
+	} catch (err) {}
 	//#endregion
 
 	document.cookie = `igi=; path=/`;
@@ -104,8 +104,8 @@ function fetchAccount(token: string): Promise<Account> {
 	});
 }
 
-export function updateAccount(data) {
-	for (const [key, value] of Object.entries(data)) {
+export function updateAccount(accountData) {
+	for (const [key, value] of Object.entries(accountData)) {
 		$i[key] = value;
 	}
 	localStorage.setItem('account', JSON.stringify($i));
diff --git a/packages/client/src/components/abuse-report-window.vue b/packages/client/src/components/abuse-report-window.vue
index f2cb369802..5114349620 100644
--- a/packages/client/src/components/abuse-report-window.vue
+++ b/packages/client/src/components/abuse-report-window.vue
@@ -37,7 +37,7 @@ const props = defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'closed'): void;
+	(ev: 'closed'): void;
 }>();
 
 const window = ref<InstanceType<typeof XWindow>>();
diff --git a/packages/client/src/components/abuse-report.vue b/packages/client/src/components/abuse-report.vue
index 46d45b690f..a947406f88 100644
--- a/packages/client/src/components/abuse-report.vue
+++ b/packages/client/src/components/abuse-report.vue
@@ -2,7 +2,7 @@
 <div class="bcekxzvu _card _gap">
 	<div class="_content target">
 		<MkAvatar class="avatar" :user="report.targetUser" :show-indicator="true"/>
-		<MkA class="info" :to="userPage(report.targetUser)" v-user-preview="report.targetUserId">
+		<MkA v-user-preview="report.targetUserId" class="info" :to="userPage(report.targetUser)">
 			<MkUserName class="name" :user="report.targetUser"/>
 			<MkAcct class="acct" :user="report.targetUser" style="display: block;"/>
 		</MkA>
diff --git a/packages/client/src/components/channel-follow-button.vue b/packages/client/src/components/channel-follow-button.vue
index 7bbf5ae663..dff02beec0 100644
--- a/packages/client/src/components/channel-follow-button.vue
+++ b/packages/client/src/components/channel-follow-button.vue
@@ -48,8 +48,8 @@ async function onClick() {
 			});
 			isFollowing.value = true;
 		}
-	} catch (e) {
-		console.error(e);
+	} catch (err) {
+		console.error(err);
 	} finally {
 		wait.value = false;
 	}
diff --git a/packages/client/src/components/cw-button.vue b/packages/client/src/components/cw-button.vue
index e7c9aabe4e..dd906f9bf3 100644
--- a/packages/client/src/components/cw-button.vue
+++ b/packages/client/src/components/cw-button.vue
@@ -18,7 +18,7 @@ const props = defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'update:modelValue', v: boolean): void;
+	(ev: 'update:modelValue', v: boolean): void;
 }>();
 
 const label = computed(() => {
diff --git a/packages/client/src/components/dialog.vue b/packages/client/src/components/dialog.vue
index 3e106a4f0c..b090f3cb4e 100644
--- a/packages/client/src/components/dialog.vue
+++ b/packages/client/src/components/dialog.vue
@@ -90,8 +90,8 @@ const props = withDefaults(defineProps<{
 });
 
 const emit = defineEmits<{
-	(e: 'done', v: { canceled: boolean; result: any }): void;
-	(e: 'closed'): void;
+	(ev: 'done', v: { canceled: boolean; result: any }): void;
+	(ev: 'closed'): void;
 }>();
 
 const modal = ref<InstanceType<typeof MkModal>>();
@@ -122,14 +122,14 @@ function onBgClick() {
 	if (props.cancelableByBgClick) cancel();
 }
 */
-function onKeydown(e: KeyboardEvent) {
-	if (e.key === 'Escape') cancel();
+function onKeydown(evt: KeyboardEvent) {
+	if (evt.key === 'Escape') cancel();
 }
 
-function onInputKeydown(e: KeyboardEvent) {
-	if (e.key === 'Enter') {
-		e.preventDefault();
-		e.stopPropagation();
+function onInputKeydown(evt: KeyboardEvent) {
+	if (evt.key === 'Enter') {
+		evt.preventDefault();
+		evt.stopPropagation();
 		ok();
 	}
 }
diff --git a/packages/client/src/components/follow-button.vue b/packages/client/src/components/follow-button.vue
index 93c9e891c1..b3540bc316 100644
--- a/packages/client/src/components/follow-button.vue
+++ b/packages/client/src/components/follow-button.vue
@@ -58,7 +58,7 @@ if (props.user.isFollowing == null) {
 }
 
 function onFollowChange(user: Misskey.entities.UserDetailed) {
-	if (user.id == props.user.id) {
+	if (user.id === props.user.id) {
 		isFollowing.value = user.isFollowing;
 		hasPendingFollowRequestFromYou.value = user.hasPendingFollowRequestFromYou;
 	}
@@ -96,8 +96,8 @@ async function onClick() {
 				hasPendingFollowRequestFromYou.value = true;
 			}
 		}
-	} catch (e) {
-		console.error(e);
+	} catch (err) {
+		console.error(err);
 	} finally {
 		wait.value = false;
 	}
diff --git a/packages/client/src/components/forgot-password.vue b/packages/client/src/components/forgot-password.vue
index 46cbf6bd70..19c1f23c85 100644
--- a/packages/client/src/components/forgot-password.vue
+++ b/packages/client/src/components/forgot-password.vue
@@ -41,8 +41,8 @@ import { instance } from '@/instance';
 import { i18n } from '@/i18n';
 
 const emit = defineEmits<{
-	(e: 'done'): void;
-	(e: 'closed'): void;
+	(ev: 'done'): void;
+	(ev: 'closed'): void;
 }>();
 
 let dialog: InstanceType<typeof XModalWindow> = $ref();
diff --git a/packages/client/src/components/form-dialog.vue b/packages/client/src/components/form-dialog.vue
index efd0da443d..11459f5937 100644
--- a/packages/client/src/components/form-dialog.vue
+++ b/packages/client/src/components/form-dialog.vue
@@ -44,7 +44,7 @@
 					<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
 					<template v-if="form[item].description" #caption>{{ form[item].description }}</template>
 				</FormRange>
-				<MkButton v-else-if="form[item].type === 'button'" @click="form[item].action($event, values)" class="_formBlock">
+				<MkButton v-else-if="form[item].type === 'button'" class="_formBlock" @click="form[item].action($event, values)">
 					<span v-text="form[item].content || item"></span>
 				</MkButton>
 			</template>
diff --git a/packages/client/src/components/form/switch.vue b/packages/client/src/components/form/switch.vue
index b5a30d635c..fadb770aee 100644
--- a/packages/client/src/components/form/switch.vue
+++ b/packages/client/src/components/form/switch.vue
@@ -31,7 +31,7 @@ const props = defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'update:modelValue', v: boolean): void;
+	(ev: 'update:modelValue', v: boolean): void;
 }>();
 
 let button = $ref<HTMLElement>();
diff --git a/packages/client/src/components/global/avatar.vue b/packages/client/src/components/global/avatar.vue
index 27cfb6e4d4..4868896c99 100644
--- a/packages/client/src/components/global/avatar.vue
+++ b/packages/client/src/components/global/avatar.vue
@@ -32,7 +32,7 @@ const props = withDefaults(defineProps<{
 });
 
 const emit = defineEmits<{
-	(e: 'click', ev: MouseEvent): void;
+	(ev: 'click', v: MouseEvent): void;
 }>();
 
 const url = $computed(() => defaultStore.state.disableShowingAnimatedImages
diff --git a/packages/client/src/components/global/emoji.vue b/packages/client/src/components/global/emoji.vue
index 92edb1caf9..0075e0867d 100644
--- a/packages/client/src/components/global/emoji.vue
+++ b/packages/client/src/components/global/emoji.vue
@@ -46,7 +46,7 @@ export default defineComponent({
 		const url = computed(() => {
 			if (char.value) {
 				let codes = Array.from(char.value).map(x => x.codePointAt(0).toString(16));
-				if (!codes.includes('200d')) codes = codes.filter(x => x != 'fe0f');
+				if (!codes.includes('200d')) codes = codes.filter(x => x !== 'fe0f');
 				codes = codes.filter(x => x && x.length);
 				return `${twemojiSvgBase}/${codes.join('-')}.svg`;
 			} else {
diff --git a/packages/client/src/components/global/time.vue b/packages/client/src/components/global/time.vue
index 5748d9de61..02351deb5f 100644
--- a/packages/client/src/components/global/time.vue
+++ b/packages/client/src/components/global/time.vue
@@ -17,7 +17,7 @@ const props = withDefaults(defineProps<{
 	mode: 'relative',
 });
 
-const _time = typeof props.time == 'string' ? new Date(props.time) : props.time;
+const _time = typeof props.time === 'string' ? new Date(props.time) : props.time;
 const absolute = _time.toLocaleString();
 
 let now = $ref(new Date());
diff --git a/packages/client/src/components/image-viewer.vue b/packages/client/src/components/image-viewer.vue
index c39076df16..7bc88399ef 100644
--- a/packages/client/src/components/image-viewer.vue
+++ b/packages/client/src/components/image-viewer.vue
@@ -25,7 +25,7 @@ const props = withDefaults(defineProps<{
 });
 
 const emit = defineEmits<{
-	(e: 'closed'): void;
+	(ev: 'closed'): void;
 }>();
 
 const modal = $ref<InstanceType<typeof MkModal>>();
diff --git a/packages/client/src/components/media-caption.vue b/packages/client/src/components/media-caption.vue
index ef546f3f70..feed3854f9 100644
--- a/packages/client/src/components/media-caption.vue
+++ b/packages/client/src/components/media-caption.vue
@@ -77,7 +77,7 @@ export default defineComponent({
 
 	computed: {
 		remainingLength(): number {
-			if (typeof this.inputValue != "string") return 512;
+			if (typeof this.inputValue !== "string") return 512;
 			return 512 - length(this.inputValue);
 		}
 	},
@@ -116,17 +116,17 @@ export default defineComponent({
 			}
 		},
 
-		onKeydown(e) {
-			if (e.which === 27) { // ESC
+		onKeydown(evt) {
+			if (evt.which === 27) { // ESC
 				this.cancel();
 			}
 		},
 
-		onInputKeydown(e) {
-			if (e.which === 13) { // Enter
-				if (e.ctrlKey) {
-					e.preventDefault();
-					e.stopPropagation();
+		onInputKeydown(evt) {
+			if (evt.which === 13) { // Enter
+				if (evt.ctrlKey) {
+					evt.preventDefault();
+					evt.stopPropagation();
 					this.ok();
 				}
 			}
diff --git a/packages/client/src/components/note-detailed.vue b/packages/client/src/components/note-detailed.vue
index d30284ca5f..14bbbd4f3c 100644
--- a/packages/client/src/components/note-detailed.vue
+++ b/packages/client/src/components/note-detailed.vue
@@ -2,9 +2,9 @@
 <div
 	v-if="!muted"
 	v-show="!isDeleted"
+	ref="el"
 	v-hotkey="keymap"
 	v-size="{ max: [500, 450, 350, 300] }"
-	ref="el"
 	class="lxwezrsl _block"
 	:tabindex="!isDeleted ? '-1' : null"
 	:class="{ renote: isRenote }"
@@ -197,7 +197,7 @@ const keymap = {
 	'q': () => renoteButton.value.renote(true),
 	'esc': blur,
 	'm|o': () => menu(true),
-	's': () => showContent.value != showContent.value,
+	's': () => showContent.value !== showContent.value,
 };
 
 useNoteCapture({
diff --git a/packages/client/src/components/note.vue b/packages/client/src/components/note.vue
index 3cd7a819d4..bc8a0dd19d 100644
--- a/packages/client/src/components/note.vue
+++ b/packages/client/src/components/note.vue
@@ -185,7 +185,7 @@ const keymap = {
 	'down|j|tab': focusAfter,
 	'esc': blur,
 	'm|o': () => menu(true),
-	's': () => showContent.value != showContent.value,
+	's': () => showContent.value !== showContent.value,
 };
 
 useNoteCapture({
diff --git a/packages/client/src/components/page/page.post.vue b/packages/client/src/components/page/page.post.vue
index 847da37c51..8ac8c46692 100644
--- a/packages/client/src/components/page/page.post.vue
+++ b/packages/client/src/components/page/page.post.vue
@@ -52,16 +52,16 @@ export default defineComponent({
 			const promise = new Promise((ok) => {
 				const canvas = this.hpml.canvases[this.block.canvasId];
 				canvas.toBlob(blob => {
-					const data = new FormData();
-					data.append('file', blob);
-					data.append('i', this.$i.token);
+					const formData = new FormData();
+					formData.append('file', blob);
+					formData.append('i', this.$i.token);
 					if (this.$store.state.uploadFolder) {
-						data.append('folderId', this.$store.state.uploadFolder);
+						formData.append('folderId', this.$store.state.uploadFolder);
 					}
 
 					fetch(apiUrl + '/drive/files/create', {
 						method: 'POST',
-						body: data
+						body: formData,
 					})
 					.then(response => response.json())
 					.then(f => {
diff --git a/packages/client/src/components/page/page.vue b/packages/client/src/components/page/page.vue
index e54147bbd0..a067762372 100644
--- a/packages/client/src/components/page/page.vue
+++ b/packages/client/src/components/page/page.vue
@@ -38,8 +38,8 @@ export default defineComponent({
 					let ast;
 					try {
 						ast = parse(props.page.script);
-					} catch (e) {
-						console.error(e);
+					} catch (err) {
+						console.error(err);
 						/*os.alert({
 							type: 'error',
 							text: 'Syntax error :('
@@ -48,11 +48,11 @@ export default defineComponent({
 					}
 					hpml.aiscript.exec(ast).then(() => {
 						hpml.eval();
-					}).catch(e => {
-						console.error(e);
+					}).catch(err => {
+						console.error(err);
 						/*os.alert({
 							type: 'error',
-							text: e
+							text: err
 						});*/
 					});
 				} else {
diff --git a/packages/client/src/components/poll-editor.vue b/packages/client/src/components/poll-editor.vue
index 6f3f23a2d3..9aa5510c7f 100644
--- a/packages/client/src/components/poll-editor.vue
+++ b/packages/client/src/components/poll-editor.vue
@@ -104,7 +104,7 @@ function add() {
 }
 
 function remove(i) {
-	choices.value = choices.value.filter((_, _i) => _i != i);
+	choices.value = choices.value.filter((_, _i) => _i !== i);
 }
 
 function get() {
diff --git a/packages/client/src/components/post-form-attaches.vue b/packages/client/src/components/post-form-attaches.vue
index 47e2e6ce0f..3807769118 100644
--- a/packages/client/src/components/post-form-attaches.vue
+++ b/packages/client/src/components/post-form-attaches.vue
@@ -98,7 +98,7 @@ export default defineComponent({
 			}, {
 				done: result => {
 					if (!result || result.canceled) return;
-					let comment = result.result.length == 0 ? null : result.result;
+					let comment = result.result.length === 0 ? null : result.result;
 					os.api('drive/files/update', {
 						fileId: file.id,
 						comment: comment,
diff --git a/packages/client/src/components/post-form.vue b/packages/client/src/components/post-form.vue
index 488c55231f..64ee873fd7 100644
--- a/packages/client/src/components/post-form.vue
+++ b/packages/client/src/components/post-form.vue
@@ -107,7 +107,7 @@ const props = withDefaults(defineProps<{
 	fixed?: boolean;
 	autofocus?: boolean;
 }>(), {
-	initialVisibleUsers: [],
+	initialVisibleUsers: () => [],
 	autofocus: true,
 });
 
diff --git a/packages/client/src/components/signup-dialog.vue b/packages/client/src/components/signup-dialog.vue
index bda2495ba7..6dad9257a4 100644
--- a/packages/client/src/components/signup-dialog.vue
+++ b/packages/client/src/components/signup-dialog.vue
@@ -27,8 +27,8 @@ const props = withDefaults(defineProps<{
 });
 
 const emit = defineEmits<{
-	(e: 'done'): void;
-	(e: 'closed'): void;
+	(ev: 'done'): void;
+	(ev: 'closed'): void;
 }>();
 
 const dialog = $ref<InstanceType<typeof XModalWindow>>();
diff --git a/packages/client/src/components/signup.vue b/packages/client/src/components/signup.vue
index aeed0e53fa..58c15d81b1 100644
--- a/packages/client/src/components/signup.vue
+++ b/packages/client/src/components/signup.vue
@@ -124,20 +124,20 @@ export default defineComponent({
 				this.meta.tosUrl && !this.ToSAgreement ||
 				this.meta.enableHcaptcha && !this.hCaptchaResponse ||
 				this.meta.enableRecaptcha && !this.reCaptchaResponse ||
-				this.passwordRetypeState == 'not-match';
+				this.passwordRetypeState === 'not-match';
 		},
 
 		shouldShowProfileUrl(): boolean {
-			return (this.username != '' &&
-				this.usernameState != 'invalid-format' &&
-				this.usernameState != 'min-range' &&
-				this.usernameState != 'max-range');
+			return (this.username !== '' &&
+				this.usernameState !== 'invalid-format' &&
+				this.usernameState !== 'min-range' &&
+				this.usernameState !== 'max-range');
 		}
 	},
 
 	methods: {
 		onChangeUsername() {
-			if (this.username == '') {
+			if (this.username === '') {
 				this.usernameState = null;
 				return;
 			}
@@ -165,7 +165,7 @@ export default defineComponent({
 		},
 
 		onChangeEmail() {
-			if (this.email == '') {
+			if (this.email === '') {
 				this.emailState = null;
 				return;
 			}
@@ -188,7 +188,7 @@ export default defineComponent({
 		},
 
 		onChangePassword() {
-			if (this.password == '') {
+			if (this.password === '') {
 				this.passwordStrength = '';
 				return;
 			}
@@ -198,12 +198,12 @@ export default defineComponent({
 		},
 
 		onChangePasswordRetype() {
-			if (this.retypedPassword == '') {
+			if (this.retypedPassword === '') {
 				this.passwordRetypeState = null;
 				return;
 			}
 
-			this.passwordRetypeState = this.password == this.retypedPassword ? 'match' : 'not-match';
+			this.passwordRetypeState = this.password === this.retypedPassword ? 'match' : 'not-match';
 		},
 
 		onSubmit() {
diff --git a/packages/client/src/components/timeline.vue b/packages/client/src/components/timeline.vue
index 59956b9526..a3fa27ab78 100644
--- a/packages/client/src/components/timeline.vue
+++ b/packages/client/src/components/timeline.vue
@@ -19,8 +19,8 @@ const props = defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'note'): void;
-	(e: 'queue', count: number): void;
+	(ev: 'note'): void;
+	(ev: 'queue', count: number): void;
 }>();
 
 provide('inChannel', computed(() => props.src === 'channel'));
@@ -95,7 +95,7 @@ if (props.src === 'antenna') {
 		visibility: 'specified'
 	};
 	const onNote = note => {
-		if (note.visibility == 'specified') {
+		if (note.visibility === 'specified') {
 			prepend(note);
 		}
 	};
diff --git a/packages/client/src/components/toast.vue b/packages/client/src/components/toast.vue
index 99933f3846..c9fad64eb6 100644
--- a/packages/client/src/components/toast.vue
+++ b/packages/client/src/components/toast.vue
@@ -19,7 +19,7 @@ defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'closed'): void;
+	(ev: 'closed'): void;
 }>();
 
 const zIndex = os.claimZIndex('high');
diff --git a/packages/client/src/components/ui/button.vue b/packages/client/src/components/ui/button.vue
index c7b6c8ba96..fe8f1c7cca 100644
--- a/packages/client/src/components/ui/button.vue
+++ b/packages/client/src/components/ui/button.vue
@@ -90,7 +90,7 @@ export default defineComponent({
 		}
 	},
 	methods: {
-		onMousedown(e: MouseEvent) {
+		onMousedown(evt: MouseEvent) {
 			function distance(p, q) {
 				return Math.hypot(p.x - q.x, p.y - q.y);
 			}
@@ -104,18 +104,18 @@ export default defineComponent({
 				return Math.max(dist1, dist2, dist3, dist4) * 2;
 			}
 
-			const rect = e.target.getBoundingClientRect();
+			const rect = evt.target.getBoundingClientRect();
 
 			const ripple = document.createElement('div');
-			ripple.style.top = (e.clientY - rect.top - 1).toString() + 'px';
-			ripple.style.left = (e.clientX - rect.left - 1).toString() + 'px';
+			ripple.style.top = (evt.clientY - rect.top - 1).toString() + 'px';
+			ripple.style.left = (evt.clientX - rect.left - 1).toString() + 'px';
 
 			this.$refs.ripples.appendChild(ripple);
 
-			const circleCenterX = e.clientX - rect.left;
-			const circleCenterY = e.clientY - rect.top;
+			const circleCenterX = evt.clientX - rect.left;
+			const circleCenterY = evt.clientY - rect.top;
 
-			const scale = calcCircleScale(e.target.clientWidth, e.target.clientHeight, circleCenterX, circleCenterY);
+			const scale = calcCircleScale(evt.target.clientWidth, evt.target.clientHeight, circleCenterX, circleCenterY);
 
 			window.setTimeout(() => {
 				ripple.style.transform = 'scale(' + (scale / 2) + ')';
diff --git a/packages/client/src/components/ui/context-menu.vue b/packages/client/src/components/ui/context-menu.vue
index f491b43b46..e637d361cf 100644
--- a/packages/client/src/components/ui/context-menu.vue
+++ b/packages/client/src/components/ui/context-menu.vue
@@ -19,7 +19,7 @@ const props = defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'closed'): void;
+	(ev: 'closed'): void;
 }>();
 
 let rootEl = $ref<HTMLDivElement>();
@@ -63,8 +63,8 @@ onBeforeUnmount(() => {
 	}
 });
 
-function onMousedown(e: Event) {
-	if (!contains(rootEl, e.target) && (rootEl != e.target)) emit('closed');
+function onMousedown(evt: Event) {
+	if (!contains(rootEl, evt.target) && (rootEl !== evt.target)) emit('closed');
 }
 </script>
 
diff --git a/packages/client/src/components/ui/menu.vue b/packages/client/src/components/ui/menu.vue
index a93cc8cda8..ca56048262 100644
--- a/packages/client/src/components/ui/menu.vue
+++ b/packages/client/src/components/ui/menu.vue
@@ -60,7 +60,7 @@ const props = defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'close'): void;
+	(ev: 'close'): void;
 }>();
 
 let itemsEl = $ref<HTMLDivElement>();
diff --git a/packages/client/src/components/ui/modal-window.vue b/packages/client/src/components/ui/modal-window.vue
index b4b8c2b965..6de29c83fa 100644
--- a/packages/client/src/components/ui/modal-window.vue
+++ b/packages/client/src/components/ui/modal-window.vue
@@ -79,10 +79,10 @@ export default defineComponent({
 			this.$refs.modal.close();
 		},
 
-		onKeydown(e) {
-			if (e.which === 27) { // Esc
-				e.preventDefault();
-				e.stopPropagation();
+		onKeydown(evt) {
+			if (evt.which === 27) { // Esc
+				evt.preventDefault();
+				evt.stopPropagation();
 				this.close();
 			}
 		},
diff --git a/packages/client/src/components/ui/pagination.vue b/packages/client/src/components/ui/pagination.vue
index 428a9d0225..c081e06acd 100644
--- a/packages/client/src/components/ui/pagination.vue
+++ b/packages/client/src/components/ui/pagination.vue
@@ -68,7 +68,7 @@ const props = withDefaults(defineProps<{
 });
 
 const emit = defineEmits<{
-	(e: 'queue', count: number): void;
+	(ev: 'queue', count: number): void;
 }>();
 
 type Item = { id: string; [another: string]: unknown; };
@@ -112,7 +112,7 @@ const init = async (): Promise<void> => {
 		offset.value = res.length;
 		error.value = false;
 		fetching.value = false;
-	}, e => {
+	}, err => {
 		error.value = true;
 		fetching.value = false;
 	});
@@ -155,7 +155,7 @@ const fetchMore = async (): Promise<void> => {
 		}
 		offset.value += res.length;
 		moreFetching.value = false;
-	}, e => {
+	}, err => {
 		moreFetching.value = false;
 	});
 };
@@ -183,7 +183,7 @@ const fetchMoreAhead = async (): Promise<void> => {
 		}
 		offset.value += res.length;
 		moreFetching.value = false;
-	}, e => {
+	}, err => {
 		moreFetching.value = false;
 	});
 };
diff --git a/packages/client/src/components/ui/popup-menu.vue b/packages/client/src/components/ui/popup-menu.vue
index 8d6c1b5695..2bc7030d77 100644
--- a/packages/client/src/components/ui/popup-menu.vue
+++ b/packages/client/src/components/ui/popup-menu.vue
@@ -19,7 +19,7 @@ defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'closed'): void;
+	(ev: 'closed'): void;
 }>();
 
 let modal = $ref<InstanceType<typeof MkModal>>();
diff --git a/packages/client/src/components/ui/window.vue b/packages/client/src/components/ui/window.vue
index fa32ecfdef..2066cf579d 100644
--- a/packages/client/src/components/ui/window.vue
+++ b/packages/client/src/components/ui/window.vue
@@ -139,10 +139,10 @@ export default defineComponent({
 			this.showing = false;
 		},
 
-		onKeydown(e) {
-			if (e.which === 27) { // Esc
-				e.preventDefault();
-				e.stopPropagation();
+		onKeydown(evt) {
+			if (evt.which === 27) { // Esc
+				evt.preventDefault();
+				evt.stopPropagation();
 				this.close();
 			}
 		},
@@ -162,15 +162,15 @@ export default defineComponent({
 			this.top();
 		},
 
-		onHeaderMousedown(e) {
+		onHeaderMousedown(evt) {
 			const main = this.$el as any;
 
 			if (!contains(main, document.activeElement)) main.focus();
 
 			const position = main.getBoundingClientRect();
 
-			const clickX = e.touches && e.touches.length > 0 ? e.touches[0].clientX : e.clientX;
-			const clickY = e.touches && e.touches.length > 0 ? e.touches[0].clientY : e.clientY;
+			const clickX = evt.touches && evt.touches.length > 0 ? evt.touches[0].clientX : evt.clientX;
+			const clickY = evt.touches && evt.touches.length > 0 ? evt.touches[0].clientY : evt.clientY;
 			const moveBaseX = clickX - position.left;
 			const moveBaseY = clickY - position.top;
 			const browserWidth = window.innerWidth;
@@ -204,10 +204,10 @@ export default defineComponent({
 		},
 
 		// 上ハンドル掴み時
-		onTopHandleMousedown(e) {
+		onTopHandleMousedown(evt) {
 			const main = this.$el as any;
 
-			const base = e.clientY;
+			const base = evt.clientY;
 			const height = parseInt(getComputedStyle(main, '').height, 10);
 			const top = parseInt(getComputedStyle(main, '').top, 10);
 
@@ -230,10 +230,10 @@ export default defineComponent({
 		},
 
 		// 右ハンドル掴み時
-		onRightHandleMousedown(e) {
+		onRightHandleMousedown(evt) {
 			const main = this.$el as any;
 
-			const base = e.clientX;
+			const base = evt.clientX;
 			const width = parseInt(getComputedStyle(main, '').width, 10);
 			const left = parseInt(getComputedStyle(main, '').left, 10);
 			const browserWidth = window.innerWidth;
@@ -254,10 +254,10 @@ export default defineComponent({
 		},
 
 		// 下ハンドル掴み時
-		onBottomHandleMousedown(e) {
+		onBottomHandleMousedown(evt) {
 			const main = this.$el as any;
 
-			const base = e.clientY;
+			const base = evt.clientY;
 			const height = parseInt(getComputedStyle(main, '').height, 10);
 			const top = parseInt(getComputedStyle(main, '').top, 10);
 			const browserHeight = window.innerHeight;
@@ -278,10 +278,10 @@ export default defineComponent({
 		},
 
 		// 左ハンドル掴み時
-		onLeftHandleMousedown(e) {
+		onLeftHandleMousedown(evt) {
 			const main = this.$el as any;
 
-			const base = e.clientX;
+			const base = evt.clientX;
 			const width = parseInt(getComputedStyle(main, '').width, 10);
 			const left = parseInt(getComputedStyle(main, '').left, 10);
 
@@ -304,27 +304,27 @@ export default defineComponent({
 		},
 
 		// 左上ハンドル掴み時
-		onTopLeftHandleMousedown(e) {
-			this.onTopHandleMousedown(e);
-			this.onLeftHandleMousedown(e);
+		onTopLeftHandleMousedown(evt) {
+			this.onTopHandleMousedown(evt);
+			this.onLeftHandleMousedown(evt);
 		},
 
 		// 右上ハンドル掴み時
-		onTopRightHandleMousedown(e) {
-			this.onTopHandleMousedown(e);
-			this.onRightHandleMousedown(e);
+		onTopRightHandleMousedown(evt) {
+			this.onTopHandleMousedown(evt);
+			this.onRightHandleMousedown(evt);
 		},
 
 		// 右下ハンドル掴み時
-		onBottomRightHandleMousedown(e) {
-			this.onBottomHandleMousedown(e);
-			this.onRightHandleMousedown(e);
+		onBottomRightHandleMousedown(evt) {
+			this.onBottomHandleMousedown(evt);
+			this.onRightHandleMousedown(evt);
 		},
 
 		// 左下ハンドル掴み時
-		onBottomLeftHandleMousedown(e) {
-			this.onBottomHandleMousedown(e);
-			this.onLeftHandleMousedown(e);
+		onBottomLeftHandleMousedown(evt) {
+			this.onBottomHandleMousedown(evt);
+			this.onLeftHandleMousedown(evt);
 		},
 
 		// 高さを適用
diff --git a/packages/client/src/components/user-preview.vue b/packages/client/src/components/user-preview.vue
index 51c5330564..f80947f75a 100644
--- a/packages/client/src/components/user-preview.vue
+++ b/packages/client/src/components/user-preview.vue
@@ -70,7 +70,7 @@ export default defineComponent({
 	},
 
 	mounted() {
-		if (typeof this.q == 'object') {
+		if (typeof this.q === 'object') {
 			this.user = this.q;
 			this.fetched = true;
 		} else {
diff --git a/packages/client/src/components/user-select-dialog.vue b/packages/client/src/components/user-select-dialog.vue
index dbef34d547..b34d21af07 100644
--- a/packages/client/src/components/user-select-dialog.vue
+++ b/packages/client/src/components/user-select-dialog.vue
@@ -60,9 +60,9 @@ import * as os from '@/os';
 import { defaultStore } from '@/store';
 
 const emit = defineEmits<{
-  (e: 'ok', selected: misskey.entities.UserDetailed): void;
-  (e: 'cancel'): void;
-	(e: 'closed'): void;
+	(ev: 'ok', selected: misskey.entities.UserDetailed): void;
+	(ev: 'cancel'): void;
+	(ev: 'closed'): void;
 }>();
 
 let username = $ref('');
diff --git a/packages/client/src/components/visibility-picker.vue b/packages/client/src/components/visibility-picker.vue
index 4b20063a51..c717c3a461 100644
--- a/packages/client/src/components/visibility-picker.vue
+++ b/packages/client/src/components/visibility-picker.vue
@@ -57,9 +57,9 @@ const props = withDefaults(defineProps<{
 });
 
 const emit = defineEmits<{
-	(e: 'changeVisibility', v: typeof misskey.noteVisibilities[number]): void;
-	(e: 'changeLocalOnly', v: boolean): void;
-	(e: 'closed'): void;
+	(ev: 'changeVisibility', v: typeof misskey.noteVisibilities[number]): void;
+	(ev: 'changeLocalOnly', v: boolean): void;
+	(ev: 'closed'): void;
 }>();
 
 let v = $ref(props.currentVisibility);
diff --git a/packages/client/src/components/waiting-dialog.vue b/packages/client/src/components/waiting-dialog.vue
index 7dfcc55695..9e631b55b1 100644
--- a/packages/client/src/components/waiting-dialog.vue
+++ b/packages/client/src/components/waiting-dialog.vue
@@ -21,8 +21,8 @@ const props = defineProps<{
 }>();
 
 const emit = defineEmits<{
-	(e: 'done');
-	(e: 'closed');
+	(ev: 'done');
+	(ev: 'closed');
 }>();
 
 function done() {
diff --git a/packages/client/src/components/widgets.vue b/packages/client/src/components/widgets.vue
index 6e4122427b..b6835795cb 100644
--- a/packages/client/src/components/widgets.vue
+++ b/packages/client/src/components/widgets.vue
@@ -19,7 +19,7 @@
 				<div class="customize-container">
 					<button class="config _button" @click.prevent.stop="configWidget(element.id)"><i class="fas fa-cog"></i></button>
 					<button class="remove _button" @click.prevent.stop="removeWidget(element)"><i class="fas fa-times"></i></button>
-					<component class="handle" :ref="el => widgetRefs[element.id] = el" :is="`mkw-${element.name}`" :widget="element" @updateProps="updateWidget(element.id, $event)"/>
+					<component :is="`mkw-${element.name}`" :ref="el => widgetRefs[element.id] = el" class="handle" :widget="element" @updateProps="updateWidget(element.id, $event)"/>
 				</div>
 			</template>
 		</XDraggable>
diff --git a/packages/client/src/filters/bytes.ts b/packages/client/src/filters/bytes.ts
index 50e63534b6..c80f2f0ed2 100644
--- a/packages/client/src/filters/bytes.ts
+++ b/packages/client/src/filters/bytes.ts
@@ -1,7 +1,7 @@
 export default (v, digits = 0) => {
 	if (v == null) return '?';
 	const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
-	if (v == 0) return '0';
+	if (v === 0) return '0';
 	const isMinus = v < 0;
 	if (isMinus) v = -v;
 	const i = Math.floor(Math.log(v) / Math.log(1024));
diff --git a/packages/client/src/init.ts b/packages/client/src/init.ts
index 5dbbcb2a2b..bb6176e409 100644
--- a/packages/client/src/init.ts
+++ b/packages/client/src/init.ts
@@ -146,7 +146,7 @@ if ($i && $i.token) {
 		try {
 			document.body.innerHTML = '<div>Please wait...</div>';
 			await login(i);
-		} catch (e) {
+		} catch (err) {
 			// Render the error screen
 			// TODO: ちゃんとしたコンポーネントをレンダリングする(v10とかのトラブルシューティングゲーム付きのやつみたいな)
 			document.body.innerHTML = '<div id="err">Oops!</div>';
@@ -249,7 +249,7 @@ if (lastVersion !== version) {
 				popup(defineAsyncComponent(() => import('@/components/updated.vue')), {}, {}, 'closed');
 			}
 		}
-	} catch (e) {
+	} catch (err) {
 	}
 }
 
@@ -334,7 +334,7 @@ stream.on('_disconnected_', async () => {
 	}
 });
 
-stream.on('emojiAdded', data => {
+stream.on('emojiAdded', emojiData => {
 	// TODO
 	//store.commit('instance/set', );
 });
diff --git a/packages/client/src/instance.ts b/packages/client/src/instance.ts
index 6e912aa2e5..d24eb2419a 100644
--- a/packages/client/src/instance.ts
+++ b/packages/client/src/instance.ts
@@ -4,11 +4,11 @@ import { api } from './os';
 
 // TODO: 他のタブと永続化されたstateを同期
 
-const data = localStorage.getItem('instance');
+const instanceData = localStorage.getItem('instance');
 
 // TODO: instanceをリアクティブにするかは再考の余地あり
 
-export const instance: Misskey.entities.InstanceMetadata = reactive(data ? JSON.parse(data) : {
+export const instance: Misskey.entities.InstanceMetadata = reactive(instanceData ? JSON.parse(instanceData) : {
 	// TODO: set default values
 });
 
diff --git a/packages/client/src/os.ts b/packages/client/src/os.ts
index 06a8ff99dc..6baf538917 100644
--- a/packages/client/src/os.ts
+++ b/packages/client/src/os.ts
@@ -59,10 +59,10 @@ export const apiWithDialog = ((
 	token?: string | null | undefined,
 ) => {
 	const promise = api(endpoint, data, token);
-	promiseDialog(promise, null, (e) => {
+	promiseDialog(promise, null, (err) => {
 		alert({
 			type: 'error',
-			text: e.message + '\n' + (e as any).id,
+			text: err.message + '\n' + (err as any).id,
 		});
 	});
 
@@ -72,7 +72,7 @@ export const apiWithDialog = ((
 export function promiseDialog<T extends Promise<any>>(
 	promise: T,
 	onSuccess?: ((res: any) => void) | null,
-	onFailure?: ((e: Error) => void) | null,
+	onFailure?: ((err: Error) => void) | null,
 	text?: string,
 ): T {
 	const showing = ref(true);
@@ -88,14 +88,14 @@ export function promiseDialog<T extends Promise<any>>(
 				showing.value = false;
 			}, 1000);
 		}
-	}).catch(e => {
+	}).catch(err => {
 		showing.value = false;
 		if (onFailure) {
-			onFailure(e);
+			onFailure(err);
 		} else {
 			alert({
 				type: 'error',
-				text: e
+				text: err,
 			});
 		}
 	});
diff --git a/packages/client/src/pages/admin/emojis.vue b/packages/client/src/pages/admin/emojis.vue
index ffb7fb34aa..38bcc41ea0 100644
--- a/packages/client/src/pages/admin/emojis.vue
+++ b/packages/client/src/pages/admin/emojis.vue
@@ -175,10 +175,10 @@ const menu = (ev: MouseEvent) => {
 					type: 'info',
 					text: i18n.ts.exportRequested,
 				});
-			}).catch((e) => {
+			}).catch((err) => {
 				os.alert({
 					type: 'error',
-					text: e.message,
+					text: err.message,
 				});
 			});
 		}
@@ -195,10 +195,10 @@ const menu = (ev: MouseEvent) => {
 					type: 'info',
 					text: i18n.ts.importRequested,
 				});
-			}).catch((e) => {
+			}).catch((err) => {
 				os.alert({
 					type: 'error',
-					text: e.message,
+					text: err.message,
 				});
 			});
 		}
diff --git a/packages/client/src/pages/admin/index.vue b/packages/client/src/pages/admin/index.vue
index 210226f283..9b7fa5678e 100644
--- a/packages/client/src/pages/admin/index.vue
+++ b/packages/client/src/pages/admin/index.vue
@@ -265,10 +265,10 @@ const invite = () => {
 			type: 'info',
 			text: x.code
 		});
-	}).catch(e => {
+	}).catch(err => {
 		os.alert({
 			type: 'error',
-			text: e
+			text: err,
 		});
 	});
 };
diff --git a/packages/client/src/pages/channel-editor.vue b/packages/client/src/pages/channel-editor.vue
index 3818c7481a..ea3a5dab76 100644
--- a/packages/client/src/pages/channel-editor.vue
+++ b/packages/client/src/pages/channel-editor.vue
@@ -111,8 +111,8 @@ export default defineComponent({
 			}
 		},
 
-		setBannerImage(e) {
-			selectFile(e.currentTarget ?? e.target, null).then(file => {
+		setBannerImage(evt) {
+			selectFile(evt.currentTarget ?? evt.target, null).then(file => {
 				this.bannerId = file.id;
 			});
 		},
diff --git a/packages/client/src/pages/emojis.category.vue b/packages/client/src/pages/emojis.category.vue
index 9a317418be..1be004cf51 100644
--- a/packages/client/src/pages/emojis.category.vue
+++ b/packages/client/src/pages/emojis.category.vue
@@ -79,9 +79,9 @@ export default defineComponent({
 			}
 
 			if (this.selectedTags.size === 0) {
-				this.searchEmojis = this.customEmojis.filter(e => e.name.includes(this.q) || e.aliases.includes(this.q));
+				this.searchEmojis = this.customEmojis.filter(emoji => emoji.name.includes(this.q) || emoji.aliases.includes(this.q));
 			} else {
-				this.searchEmojis = this.customEmojis.filter(e => (e.name.includes(this.q) || e.aliases.includes(this.q)) && [...this.selectedTags].every(t => e.aliases.includes(t)));
+				this.searchEmojis = this.customEmojis.filter(emoji => (emoji.name.includes(this.q) || emoji.aliases.includes(this.q)) && [...this.selectedTags].every(t => emoji.aliases.includes(t)));
 			}
 		},
 
diff --git a/packages/client/src/pages/emojis.vue b/packages/client/src/pages/emojis.vue
index 886b5f7119..f44b29df04 100644
--- a/packages/client/src/pages/emojis.vue
+++ b/packages/client/src/pages/emojis.vue
@@ -25,10 +25,10 @@ function menu(ev) {
 					type: 'info',
 					text: i18n.ts.exportRequested,
 				});
-			}).catch((e) => {
+			}).catch((err) => {
 				os.alert({
 					type: 'error',
-					text: e.message,
+					text: err.message,
 				});
 			});
 		}
diff --git a/packages/client/src/pages/follow.vue b/packages/client/src/pages/follow.vue
index d8a6824dca..e69e0481e0 100644
--- a/packages/client/src/pages/follow.vue
+++ b/packages/client/src/pages/follow.vue
@@ -20,7 +20,7 @@ export default defineComponent({
 				uri: acct
 			});
 			promise.then(res => {
-				if (res.type == 'User') {
+				if (res.type === 'User') {
 					this.follow(res.object);
 				} else if (res.type === 'Note') {
 					this.$router.push(`/notes/${res.object.id}`);
diff --git a/packages/client/src/pages/gallery/edit.vue b/packages/client/src/pages/gallery/edit.vue
index 25ee513186..a0c2d1a596 100644
--- a/packages/client/src/pages/gallery/edit.vue
+++ b/packages/client/src/pages/gallery/edit.vue
@@ -91,8 +91,8 @@ export default defineComponent({
 	},
 
 	methods: {
-		selectFile(e) {
-			selectFiles(e.currentTarget ?? e.target, null).then(files => {
+		selectFile(evt) {
+			selectFiles(evt.currentTarget ?? evt.target, null).then(files => {
 				this.files = this.files.concat(files);
 			});
 		},
diff --git a/packages/client/src/pages/gallery/post.vue b/packages/client/src/pages/gallery/post.vue
index 1755c23286..1ca3443e56 100644
--- a/packages/client/src/pages/gallery/post.vue
+++ b/packages/client/src/pages/gallery/post.vue
@@ -119,8 +119,8 @@ export default defineComponent({
 				postId: this.postId
 			}).then(post => {
 				this.post = post;
-			}).catch(e => {
-				this.error = e;
+			}).catch(err => {
+				this.error = err;
 			});
 		},
 
diff --git a/packages/client/src/pages/messaging/index.vue b/packages/client/src/pages/messaging/index.vue
index 88a1e07afc..61c8bb0ce3 100644
--- a/packages/client/src/pages/messaging/index.vue
+++ b/packages/client/src/pages/messaging/index.vue
@@ -90,14 +90,14 @@ export default defineComponent({
 		getAcct: Acct.toString,
 
 		isMe(message) {
-			return message.userId == this.$i.id;
+			return message.userId === this.$i.id;
 		},
 
 		onMessage(message) {
 			if (message.recipientId) {
 				this.messages = this.messages.filter(m => !(
-					(m.recipientId == message.recipientId && m.userId == message.userId) ||
-					(m.recipientId == message.userId && m.userId == message.recipientId)));
+					(m.recipientId === message.recipientId && m.userId === message.userId) ||
+					(m.recipientId === message.userId && m.userId === message.recipientId)));
 
 				this.messages.unshift(message);
 			} else if (message.groupId) {
@@ -108,7 +108,7 @@ export default defineComponent({
 
 		onRead(ids) {
 			for (const id of ids) {
-				const found = this.messages.find(m => m.id == id);
+				const found = this.messages.find(m => m.id === id);
 				if (found) {
 					if (found.recipientId) {
 						found.isRead = true;
diff --git a/packages/client/src/pages/messaging/messaging-room.form.vue b/packages/client/src/pages/messaging/messaging-room.form.vue
index 35cb75743f..ad8aaae6b7 100644
--- a/packages/client/src/pages/messaging/messaging-room.form.vue
+++ b/packages/client/src/pages/messaging/messaging-room.form.vue
@@ -59,7 +59,7 @@ export default defineComponent({
 			return this.user ? 'user:' + this.user.id : 'group:' + this.group.id;
 		},
 		canSend(): boolean {
-			return (this.text != null && this.text != '') || this.file != null;
+			return (this.text != null && this.text !== '') || this.file != null;
 		},
 		room(): any {
 			return this.$parent;
@@ -88,12 +88,11 @@ export default defineComponent({
 		}
 	},
 	methods: {
-		async onPaste(e: ClipboardEvent) {
-			const data = e.clipboardData;
-			const items = data.items;
+		async onPaste(evt: ClipboardEvent) {
+			const items = evt.clipboardData.items;
 
-			if (items.length == 1) {
-				if (items[0].kind == 'file') {
+			if (items.length === 1) {
+				if (items[0].kind === 'file') {
 					const file = items[0].getAsFile();
 					const lio = file.name.lastIndexOf('.');
 					const ext = lio >= 0 ? file.name.slice(lio) : '';
@@ -101,7 +100,7 @@ export default defineComponent({
 					if (formatted) this.upload(file, formatted);
 				}
 			} else {
-				if (items[0].kind == 'file') {
+				if (items[0].kind === 'file') {
 					os.alert({
 						type: 'error',
 						text: this.$ts.onlyOneFileCanBeAttached
@@ -110,23 +109,23 @@ export default defineComponent({
 			}
 		},
 
-		onDragover(e) {
-			const isFile = e.dataTransfer.items[0].kind == 'file';
-			const isDriveFile = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_;
+		onDragover(evt) {
+			const isFile = evt.dataTransfer.items[0].kind === 'file';
+			const isDriveFile = evt.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_;
 			if (isFile || isDriveFile) {
-				e.preventDefault();
-				e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
+				evt.preventDefault();
+				evt.dataTransfer.dropEffect = evt.dataTransfer.effectAllowed === 'all' ? 'copy' : 'move';
 			}
 		},
 
-		onDrop(e): void {
+		onDrop(evt): void {
 			// ファイルだったら
-			if (e.dataTransfer.files.length == 1) {
-				e.preventDefault();
-				this.upload(e.dataTransfer.files[0]);
+			if (evt.dataTransfer.files.length === 1) {
+				evt.preventDefault();
+				this.upload(evt.dataTransfer.files[0]);
 				return;
-			} else if (e.dataTransfer.files.length > 1) {
-				e.preventDefault();
+			} else if (evt.dataTransfer.files.length > 1) {
+				evt.preventDefault();
 				os.alert({
 					type: 'error',
 					text: this.$ts.onlyOneFileCanBeAttached
@@ -135,17 +134,17 @@ export default defineComponent({
 			}
 
 			//#region ドライブのファイル
-			const driveFile = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
-			if (driveFile != null && driveFile != '') {
+			const driveFile = evt.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
+			if (driveFile != null && driveFile !== '') {
 				this.file = JSON.parse(driveFile);
-				e.preventDefault();
+				evt.preventDefault();
 			}
 			//#endregion
 		},
 
-		onKeydown(e) {
+		onKeydown(evt) {
 			this.typing();
-			if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && this.canSend) {
+			if ((evt.which === 10 || evt.which === 13) && (evt.ctrlKey || evt.metaKey) && this.canSend) {
 				this.send();
 			}
 		},
@@ -154,8 +153,8 @@ export default defineComponent({
 			this.typing();
 		},
 
-		chooseFile(e) {
-			selectFile(e.currentTarget ?? e.target, this.$ts.selectFile).then(file => {
+		chooseFile(evt) {
+			selectFile(evt.currentTarget ?? evt.target, this.$ts.selectFile).then(file => {
 				this.file = file;
 			});
 		},
@@ -193,9 +192,9 @@ export default defineComponent({
 		},
 
 		saveDraft() {
-			const data = JSON.parse(localStorage.getItem('message_drafts') || '{}');
+			const drafts = JSON.parse(localStorage.getItem('message_drafts') || '{}');
 
-			data[this.draftKey] = {
+			drafts[this.draftKey] = {
 				updatedAt: new Date(),
 				data: {
 					text: this.text,
@@ -203,15 +202,15 @@ export default defineComponent({
 				}
 			}
 
-			localStorage.setItem('message_drafts', JSON.stringify(data));
+			localStorage.setItem('message_drafts', JSON.stringify(drafts));
 		},
 
 		deleteDraft() {
-			const data = JSON.parse(localStorage.getItem('message_drafts') || '{}');
+			const drafts = JSON.parse(localStorage.getItem('message_drafts') || '{}');
 
-			delete data[this.draftKey];
+			delete drafts[this.draftKey];
 
-			localStorage.setItem('message_drafts', JSON.stringify(data));
+			localStorage.setItem('message_drafts', JSON.stringify(drafts));
 		},
 
 		async insertEmoji(ev) {
diff --git a/packages/client/src/pages/messaging/messaging-room.vue b/packages/client/src/pages/messaging/messaging-room.vue
index 2ecc68eb54..fd1962218a 100644
--- a/packages/client/src/pages/messaging/messaging-room.vue
+++ b/packages/client/src/pages/messaging/messaging-room.vue
@@ -166,23 +166,23 @@ const Component = defineComponent({
 			});
 		},
 
-		onDragover(e) {
-			const isFile = e.dataTransfer.items[0].kind == 'file';
-			const isDriveFile = e.dataTransfer.types[0] == _DATA_TRANSFER_DRIVE_FILE_;
+		onDragover(evt) {
+			const isFile = evt.dataTransfer.items[0].kind === 'file';
+			const isDriveFile = evt.dataTransfer.types[0] === _DATA_TRANSFER_DRIVE_FILE_;
 
 			if (isFile || isDriveFile) {
-				e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
+				evt.dataTransfer.dropEffect = evt.dataTransfer.effectAllowed === 'all' ? 'copy' : 'move';
 			} else {
-				e.dataTransfer.dropEffect = 'none';
+				evt.dataTransfer.dropEffect = 'none';
 			}
 		},
 
-		onDrop(e): void {
+		onDrop(evt): void {
 			// ファイルだったら
-			if (e.dataTransfer.files.length == 1) {
-				this.form.upload(e.dataTransfer.files[0]);
+			if (evt.dataTransfer.files.length === 1) {
+				this.form.upload(evt.dataTransfer.files[0]);
 				return;
-			} else if (e.dataTransfer.files.length > 1) {
+			} else if (evt.dataTransfer.files.length > 1) {
 				os.alert({
 					type: 'error',
 					text: this.$ts.onlyOneFileCanBeAttached
@@ -191,8 +191,8 @@ const Component = defineComponent({
 			}
 
 			//#region ドライブのファイル
-			const driveFile = e.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
-			if (driveFile != null && driveFile != '') {
+			const driveFile = evt.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
+			if (driveFile != null && driveFile !== '') {
 				const file = JSON.parse(driveFile);
 				this.form.file = file;
 			}
@@ -209,7 +209,7 @@ const Component = defineComponent({
 					limit: max + 1,
 					untilId: this.existMoreMessages ? this.messages[0].id : undefined
 				}).then(messages => {
-					if (messages.length == max + 1) {
+					if (messages.length === max + 1) {
 						this.existMoreMessages = true;
 						messages.pop();
 					} else {
@@ -235,7 +235,7 @@ const Component = defineComponent({
 			const _isBottom = isBottom(this.$el, 64);
 
 			this.messages.push(message);
-			if (message.userId != this.$i.id && !document.hidden) {
+			if (message.userId !== this.$i.id && !document.hidden) {
 				this.connection.send('read', {
 					id: message.id
 				});
@@ -246,7 +246,7 @@ const Component = defineComponent({
 				this.$nextTick(() => {
 					this.scrollToBottom();
 				});
-			} else if (message.userId != this.$i.id) {
+			} else if (message.userId !== this.$i.id) {
 				// Notify
 				this.notifyNewMessage();
 			}
@@ -256,7 +256,7 @@ const Component = defineComponent({
 			if (this.user) {
 				if (!Array.isArray(x)) x = [x];
 				for (const id of x) {
-					if (this.messages.some(x => x.id == id)) {
+					if (this.messages.some(x => x.id === id)) {
 						const exist = this.messages.map(x => x.id).indexOf(id);
 						this.messages[exist] = {
 							...this.messages[exist],
@@ -266,7 +266,7 @@ const Component = defineComponent({
 				}
 			} else if (this.group) {
 				for (const id of x.ids) {
-					if (this.messages.some(x => x.id == id)) {
+					if (this.messages.some(x => x.id === id)) {
 						const exist = this.messages.map(x => x.id).indexOf(id);
 						this.messages[exist] = {
 							...this.messages[exist],
diff --git a/packages/client/src/pages/note.vue b/packages/client/src/pages/note.vue
index 9e174ef495..f0a18ecc36 100644
--- a/packages/client/src/pages/note.vue
+++ b/packages/client/src/pages/note.vue
@@ -136,8 +136,8 @@ export default defineComponent({
 					this.hasPrev = prev.length !== 0;
 					this.hasNext = next.length !== 0;
 				});
-			}).catch(e => {
-				this.error = e;
+			}).catch(err => {
+				this.error = err;
 			});
 		}
 	}
diff --git a/packages/client/src/pages/page.vue b/packages/client/src/pages/page.vue
index b2c039a269..5bca971438 100644
--- a/packages/client/src/pages/page.vue
+++ b/packages/client/src/pages/page.vue
@@ -139,8 +139,8 @@ export default defineComponent({
 				username: this.username,
 			}).then(page => {
 				this.page = page;
-			}).catch(e => {
-				this.error = e;
+			}).catch(err => {
+				this.error = err;
 			});
 		},
 
diff --git a/packages/client/src/pages/settings/2fa.vue b/packages/client/src/pages/settings/2fa.vue
index a19d6378d7..be464f040d 100644
--- a/packages/client/src/pages/settings/2fa.vue
+++ b/packages/client/src/pages/settings/2fa.vue
@@ -121,10 +121,10 @@ function submit() {
 	}).then(() => {
 		os.success();
 		$i!.twoFactorEnabled = true;
-	}).catch(e => {
+	}).catch(err => {
 		os.alert({
 			type: 'error',
-			text: e
+			text: err,
 		});
 	});
 }
diff --git a/packages/client/src/pages/settings/plugin.install.vue b/packages/client/src/pages/settings/plugin.install.vue
index 6ece531462..96c0abfd99 100644
--- a/packages/client/src/pages/settings/plugin.install.vue
+++ b/packages/client/src/pages/settings/plugin.install.vue
@@ -43,7 +43,7 @@ async function install() {
 	let ast;
 	try {
 		ast = parse(code.value);
-	} catch (e) {
+	} catch (err) {
 		os.alert({
 			type: 'error',
 			text: 'Syntax error :('
@@ -60,8 +60,8 @@ async function install() {
 		return;
 	}
 
-	const data = meta.get(null);
-	if (data == null) {
+	const metadata = meta.get(null);
+	if (metadata == null) {
 		os.alert({
 			type: 'error',
 			text: 'No metadata found :('
@@ -69,7 +69,7 @@ async function install() {
 		return;
 	}
 
-	const { name, version, author, description, permissions, config } = data;
+	const { name, version, author, description, permissions, config } = metadata;
 	if (name == null || version == null || author == null) {
 		os.alert({
 			type: 'error',
diff --git a/packages/client/src/pages/settings/theme.install.vue b/packages/client/src/pages/settings/theme.install.vue
index 0ef098f318..25fa6c012b 100644
--- a/packages/client/src/pages/settings/theme.install.vue
+++ b/packages/client/src/pages/settings/theme.install.vue
@@ -29,7 +29,7 @@ function parseThemeCode(code: string) {
 
 	try {
 		theme = JSON5.parse(code);
-	} catch (e) {
+	} catch (err) {
 		os.alert({
 			type: 'error',
 			text: i18n.ts._theme.invalid
diff --git a/packages/client/src/pages/settings/webhook.edit.vue b/packages/client/src/pages/settings/webhook.edit.vue
index bb3a25407e..3690526b41 100644
--- a/packages/client/src/pages/settings/webhook.edit.vue
+++ b/packages/client/src/pages/settings/webhook.edit.vue
@@ -43,6 +43,14 @@ import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { i18n } from '@/i18n';
 
+defineExpose({
+	[symbols.PAGE_INFO]: {
+		title: 'Edit webhook',
+		icon: 'fas fa-bolt',
+		bg: 'var(--bg)',
+	},
+});
+
 const webhook = await os.api('i/webhooks/show', {
 	webhookId: new URLSearchParams(window.location.search).get('id')
 });
@@ -78,12 +86,4 @@ async function save(): Promise<void> {
 		active,
 	});
 }
-
-defineExpose({
-	[symbols.PAGE_INFO]: {
-		title: 'Edit webhook',
-		icon: 'fas fa-bolt',
-		bg: 'var(--bg)',
-	},
-});
 </script>
diff --git a/packages/client/src/pages/settings/word-mute.vue b/packages/client/src/pages/settings/word-mute.vue
index 97a15da5b5..48fcb362b9 100644
--- a/packages/client/src/pages/settings/word-mute.vue
+++ b/packages/client/src/pages/settings/word-mute.vue
@@ -71,7 +71,7 @@ watch(hardMutedWords, () => {
 async function save() {
 	const parseMutes = (mutes, tab) => {
 		// split into lines, remove empty lines and unnecessary whitespace
-		let lines = mutes.trim().split('\n').map(line => line.trim()).filter(line => line != '');
+		let lines = mutes.trim().split('\n').map(line => line.trim()).filter(line => line !== '');
 
 		// check each line if it is a RegExp or not
 		for (let i = 0; i < lines.length; i++) {
diff --git a/packages/client/src/pages/share.vue b/packages/client/src/pages/share.vue
index 4d77de5819..b08ac2b237 100644
--- a/packages/client/src/pages/share.vue
+++ b/packages/client/src/pages/share.vue
@@ -153,11 +153,11 @@ export default defineComponent({
 				);
 			}
 			//#endregion
-		} catch (e) {
+		} catch (err) {
 			os.alert({
 				type: 'error',
-				title: e.message,
-				text: e.name
+				title: err.message,
+				text: err.name
 			});
 		}
 
diff --git a/packages/client/src/pages/theme-editor.vue b/packages/client/src/pages/theme-editor.vue
index 5f9f1b9783..4250673d91 100644
--- a/packages/client/src/pages/theme-editor.vue
+++ b/packages/client/src/pages/theme-editor.vue
@@ -128,7 +128,7 @@ function showPreview() {
 }
 
 function setBgColor(color: typeof bgColors[number]) {
-	if (theme.base != color.kind) {
+	if (theme.base !== color.kind) {
 		const base = color.kind === 'dark' ? darkTheme : lightTheme;
 		for (const prop of Object.keys(base.props)) {
 			if (prop === 'accent') continue;
diff --git a/packages/client/src/pages/user-info.vue b/packages/client/src/pages/user-info.vue
index 516ab4d440..1b2682ed29 100644
--- a/packages/client/src/pages/user-info.vue
+++ b/packages/client/src/pages/user-info.vue
@@ -232,10 +232,10 @@ export default defineComponent({
 				await os.api('admin/delete-all-files-of-a-user', { userId: this.user.id });
 				os.success();
 			};
-			await process().catch(e => {
+			await process().catch(err => {
 				os.alert({
 					type: 'error',
-					text: e.toString()
+					text: err.toString(),
 				});
 			});
 			await this.refreshUser();
diff --git a/packages/client/src/pages/user/index.vue b/packages/client/src/pages/user/index.vue
index 17e815892b..a024dd28bc 100644
--- a/packages/client/src/pages/user/index.vue
+++ b/packages/client/src/pages/user/index.vue
@@ -260,8 +260,8 @@ export default defineComponent({
 			this.user = null;
 			os.api('users/show', Acct.parse(this.acct)).then(user => {
 				this.user = user;
-			}).catch(e => {
-				this.error = e;
+			}).catch(err => {
+				this.error = err;
 			});
 		},
 
diff --git a/packages/client/src/theme-store.ts b/packages/client/src/theme-store.ts
index e7962e7e8e..fdc92ed793 100644
--- a/packages/client/src/theme-store.ts
+++ b/packages/client/src/theme-store.ts
@@ -14,9 +14,9 @@ export async function fetchThemes(): Promise<void> {
 	try {
 		const themes = await api('i/registry/get', { scope: ['client'], key: 'themes' });
 		localStorage.setItem(lsCacheKey, JSON.stringify(themes));
-	} catch (e) {
-		if (e.code === 'NO_SUCH_KEY') return;
-		throw e;
+	} catch (err) {
+		if (err.code === 'NO_SUCH_KEY') return;
+		throw err;
 	}
 }
 
@@ -28,7 +28,7 @@ export async function addTheme(theme: Theme): Promise<void> {
 }
 
 export async function removeTheme(theme: Theme): Promise<void> {
-	const themes = getThemes().filter(t => t.id != theme.id);
+	const themes = getThemes().filter(t => t.id !== theme.id);
 	await api('i/registry/set', { scope: ['client'], key: 'themes', value: themes });
 	localStorage.setItem(lsCacheKey, JSON.stringify(themes));
 }
diff --git a/packages/client/src/ui/_common_/sw-inject.ts b/packages/client/src/ui/_common_/sw-inject.ts
index e3e2ddd7e6..371f80ca15 100644
--- a/packages/client/src/ui/_common_/sw-inject.ts
+++ b/packages/client/src/ui/_common_/sw-inject.ts
@@ -14,30 +14,29 @@ export function swInject() {
 			console.log('sw msg', ev.data);
 		}
 
-		const data = ev.data; // as SwMessage
-		if (data.type !== 'order') return;
+		if (ev.data.type !== 'order') return;
 
-		if (data.loginId !== $i?.id) {
-			return getAccountFromId(data.loginId).then(account => {
+		if (ev.data.loginId !== $i?.id) {
+			return getAccountFromId(ev.data.loginId).then(account => {
 				if (!account) return;
-				return login(account.token, data.url);
+				return login(account.token, ev.data.url);
 			});
 		}
 
-		switch (data.order) {
+		switch (ev.data.order) {
 			case 'post':
-				return post(data.options);
+				return post(ev.data.options);
 			case 'push':
-				if (router.currentRoute.value.path === data.url) {
+				if (router.currentRoute.value.path === ev.data.url) {
 					return window.scroll({ top: 0, behavior: 'smooth' });
 				}
 				if (navHook) {
-					return navHook(data.url);
+					return navHook(ev.data.url);
 				}
-				if (sideViewHook && defaultStore.state.defaultSideView && data.url !== '/') {
-					return sideViewHook(data.url);
+				if (sideViewHook && defaultStore.state.defaultSideView && ev.data.url !== '/') {
+					return sideViewHook(ev.data.url);
 				}
-				return router.push(data.url);
+				return router.push(ev.data.url);
 			default:
 				return;
 		}
diff --git a/packages/client/src/ui/classic.widgets.vue b/packages/client/src/ui/classic.widgets.vue
index f42f27e926..6f9d18bde5 100644
--- a/packages/client/src/ui/classic.widgets.vue
+++ b/packages/client/src/ui/classic.widgets.vue
@@ -44,13 +44,13 @@ export default defineComponent({
 		},
 
 		removeWidget(widget) {
-			this.$store.set('widgets', this.$store.state.widgets.filter(w => w.id != widget.id));
+			this.$store.set('widgets', this.$store.state.widgets.filter(w => w.id !== widget.id));
 		},
 
 		updateWidget({ id, data }) {
 			this.$store.set('widgets', this.$store.state.widgets.map(w => w.id === id ? {
 				...w,
-				data: data
+				data,
 			} : w));
 		},
 
diff --git a/packages/client/src/ui/deck/deck-store.ts b/packages/client/src/ui/deck/deck-store.ts
index c2c9ae540b..c847bf2b43 100644
--- a/packages/client/src/ui/deck/deck-store.ts
+++ b/packages/client/src/ui/deck/deck-store.ts
@@ -276,14 +276,14 @@ export function setColumnWidgets(id: Column['id'], widgets: ColumnWidget[]) {
 	saveDeck();
 }
 
-export function updateColumnWidget(id: Column['id'], widgetId: string, data: any) {
+export function updateColumnWidget(id: Column['id'], widgetId: string, WidgetData: any) {
 	const columns = copy(deckStore.state.columns);
 	const columnIndex = deckStore.state.columns.findIndex(c => c.id === id);
 	const column = copy(deckStore.state.columns[columnIndex]);
 	if (column == null) return;
 	column.widgets = column.widgets.map(w => w.id === widgetId ? {
 		...w,
-		data: data
+		data: widgetData,
 	} : w);
 	columns[columnIndex] = column;
 	deckStore.set('columns', columns);
diff --git a/packages/client/src/ui/universal.widgets.vue b/packages/client/src/ui/universal.widgets.vue
index 2660e80368..a42c085690 100644
--- a/packages/client/src/ui/universal.widgets.vue
+++ b/packages/client/src/ui/universal.widgets.vue
@@ -14,7 +14,7 @@ import { i18n } from '@/i18n';
 import { defaultStore } from '@/store';
 
 const emit = defineEmits<{
-	(e: 'mounted', el: Element): void;
+	(ev: 'mounted', el: Element): void;
 }>();
 
 let editMode = $ref(false);
@@ -32,13 +32,13 @@ function addWidget(widget) {
 }
 
 function removeWidget(widget) {
-	defaultStore.set('widgets', defaultStore.state.widgets.filter(w => w.id != widget.id));
+	defaultStore.set('widgets', defaultStore.state.widgets.filter(w => w.id !== widget.id));
 }
 
 function updateWidget({ id, data }) {
 	defaultStore.set('widgets', defaultStore.state.widgets.map(w => w.id === id ? {
 		...w,
-		data: data
+		data,
 	} : w));
 }
 
-- 
cgit v1.2.3-freya


From 708fba989adab95b3a4c381f6b351979c5973591 Mon Sep 17 00:00:00 2001
From: Andreas Nedbal <github-bf215181b5140522137b3d4f6b73544a@desu.email>
Date: Sat, 28 May 2022 07:28:12 +0200
Subject: feat(tests): add e2e tests for widgets (#8735)

* test(e2e): add baseline for widget tests

* chore(repo): enable test running in branch

* fix(e2e): set viewport for widget tests

* fix(client): add widget identifier classes to widgets

* test(e2e): add memo widget test

* fix(tests): force select value

* fix(tests): force button press for widget addition

* fix(tests): invoke select value differently

* fix(tests): adjust widget submit

* fix(tests): don't explicitly navigate for widget test

* fix(tests): click label to hide select popup

* fix(tests): just click modal background

* fix(tests): adjust modal background selector

* fix(tests): click all modal backgrounds

* feat(e2e): add test for adding timeline widget

* fix(client): add more widget identifier classes

* feat(tests): add method abstraction for test cases

* fix(tests): force-click overlays

* fix(tests): force widget button press

* fix(tests): remove timeout from final widget check

* feat(tests): add widget removal test case

* fix(client): use mk instead of msky as class prefix

* fix(tests): check widgets for existence rather than visibility

* chore(meta): don't run tests for specific feature branch
---
 cypress/integration/widgets.js                | 84 +++++++++++++++++++++++++++
 packages/client/src/components/widgets.vue    |  4 +-
 packages/client/src/ui/universal.widgets.vue  |  2 +-
 packages/client/src/widgets/activity.vue      |  2 +-
 packages/client/src/widgets/aichan.vue        |  2 +-
 packages/client/src/widgets/aiscript.vue      |  2 +-
 packages/client/src/widgets/clock.vue         |  2 +-
 packages/client/src/widgets/federation.vue    |  2 +-
 packages/client/src/widgets/memo.vue          |  2 +-
 packages/client/src/widgets/notifications.vue |  2 +-
 packages/client/src/widgets/photos.vue        |  2 +-
 packages/client/src/widgets/post-form.vue     |  2 +-
 packages/client/src/widgets/rss.vue           |  2 +-
 packages/client/src/widgets/slideshow.vue     |  2 +-
 packages/client/src/widgets/timeline.vue      |  2 +-
 packages/client/src/widgets/trends.vue        |  2 +-
 16 files changed, 100 insertions(+), 16 deletions(-)
 create mode 100644 cypress/integration/widgets.js

(limited to 'packages/client/src/components/widgets.vue')

diff --git a/cypress/integration/widgets.js b/cypress/integration/widgets.js
new file mode 100644
index 0000000000..d63ff274bd
--- /dev/null
+++ b/cypress/integration/widgets.js
@@ -0,0 +1,84 @@
+describe('After user signed in', () => {
+	beforeEach(() => {
+		cy.window(win => {
+			win.indexedDB.deleteDatabase('keyval-store');
+		});
+		cy.viewport('macbook-16');
+		cy.request('POST', '/api/reset-db').as('reset');
+		cy.get('@reset').its('status').should('equal', 204);
+		cy.reload(true);
+
+		// インスタンス初期セットアップ
+		cy.request('POST', '/api/admin/accounts/create', {
+			username: 'admin',
+			password: 'pass',
+		}).its('body').as('admin');
+
+		// ユーザー作成
+		cy.request('POST', '/api/signup', {
+			username: 'alice',
+			password: 'alice1234',
+		}).its('body').as('alice');
+
+		cy.visit('/');
+
+		cy.intercept('POST', '/api/signin').as('signin');
+
+		cy.get('[data-cy-signin]').click();
+		cy.get('[data-cy-signin-username] input').type('alice');
+		cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
+
+		cy.wait('@signin').as('signedIn');
+	});
+
+	afterEach(() => {
+		// テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。
+		// waitを入れることでそれを防止できる
+		cy.wait(1000);
+	});
+
+  it('widget edit toggle is visible', () => {
+		cy.get('.mk-widget-edit').should('be.visible');
+  });
+
+	it('widget select should be visible in edit mode', () => {
+		cy.get('.mk-widget-edit').click();
+		cy.get('.mk-widget-select').should('be.visible');
+  });
+
+	it('first widget should be removed', () => {
+		cy.get('.mk-widget-edit').click();
+		cy.get('.customize-container:first-child .remove._button').click();
+		cy.get('.customize-container').should('have.length', 2);
+	});
+
+	function buildWidgetTest(widgetName) {
+		it(`${widgetName} widget should get added`, () => {
+			cy.get('.mk-widget-edit').click();
+			cy.get('.mk-widget-select select').select(widgetName, { force: true });
+			cy.get('.bg._modalBg.transparent').click({ multiple: true, force: true });
+			cy.get('.mk-widget-add').click({ force: true });
+			cy.get(`.mkw-${widgetName}`).should('exist');
+		});
+	}
+
+	buildWidgetTest('memo');
+	buildWidgetTest('notifications');
+	buildWidgetTest('timeline');
+	buildWidgetTest('calendar');
+	buildWidgetTest('rss');
+	buildWidgetTest('trends');
+	buildWidgetTest('clock');
+	buildWidgetTest('activity');
+	buildWidgetTest('photos');
+	buildWidgetTest('digitalClock');
+	buildWidgetTest('federation');
+	buildWidgetTest('postForm');
+	buildWidgetTest('slideshow');
+	buildWidgetTest('serverMetric');
+	buildWidgetTest('onlineUsers');
+	buildWidgetTest('jobQueue');
+	buildWidgetTest('button');
+	buildWidgetTest('aiscript');
+	buildWidgetTest('aichan');
+});
diff --git a/packages/client/src/components/widgets.vue b/packages/client/src/components/widgets.vue
index b6835795cb..74dd79f733 100644
--- a/packages/client/src/components/widgets.vue
+++ b/packages/client/src/components/widgets.vue
@@ -2,11 +2,11 @@
 <div class="vjoppmmu">
 	<template v-if="edit">
 		<header>
-			<MkSelect v-model="widgetAdderSelected" style="margin-bottom: var(--margin)">
+			<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>
 			</MkSelect>
-			<MkButton inline primary @click="addWidget"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton>
+			<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>
 		</header>
 		<XDraggable
diff --git a/packages/client/src/ui/universal.widgets.vue b/packages/client/src/ui/universal.widgets.vue
index a42c085690..7aed083886 100644
--- a/packages/client/src/ui/universal.widgets.vue
+++ b/packages/client/src/ui/universal.widgets.vue
@@ -3,7 +3,7 @@
 	<XWidgets :edit="editMode" :widgets="defaultStore.reactiveState.widgets.value" @add-widget="addWidget" @remove-widget="removeWidget" @update-widget="updateWidget" @update-widgets="updateWidgets" @exit="editMode = false"/>
 
 	<button v-if="editMode" class="_textButton" style="font-size: 0.9em;" @click="editMode = false"><i class="fas fa-check"></i> {{ i18n.ts.editWidgetsExit }}</button>
-	<button v-else class="_textButton" style="font-size: 0.9em;" @click="editMode = true"><i class="fas fa-pencil-alt"></i> {{ i18n.ts.editWidgets }}</button>
+	<button v-else class="_textButton mk-widget-edit" style="font-size: 0.9em;" @click="editMode = true"><i class="fas fa-pencil-alt"></i> {{ i18n.ts.editWidgets }}</button>
 </div>
 </template>
 
diff --git a/packages/client/src/widgets/activity.vue b/packages/client/src/widgets/activity.vue
index 631beceb72..7fb9f5894c 100644
--- a/packages/client/src/widgets/activity.vue
+++ b/packages/client/src/widgets/activity.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent">
+<MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent" class="mkw-activity">
 	<template #header><i class="fas fa-chart-bar"></i>{{ $ts._widgets.activity }}</template>
 	<template #func><button class="_button" @click="toggleView()"><i class="fas fa-sort"></i></button></template>
 
diff --git a/packages/client/src/widgets/aichan.vue b/packages/client/src/widgets/aichan.vue
index 70e47f2af1..cdd367cc84 100644
--- a/packages/client/src/widgets/aichan.vue
+++ b/packages/client/src/widgets/aichan.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :naked="widgetProps.transparent" :show-header="false">
+<MkContainer :naked="widgetProps.transparent" :show-header="false" class="mkw-aichan">
 	<iframe ref="live2d" class="dedjhjmo" src="https://misskey-dev.github.io/mascot-web/?scale=1.5&y=1.1&eyeY=100" @click="touched"></iframe>
 </MkContainer>
 </template>
diff --git a/packages/client/src/widgets/aiscript.vue b/packages/client/src/widgets/aiscript.vue
index b74e2258a9..9fed292a69 100644
--- a/packages/client/src/widgets/aiscript.vue
+++ b/packages/client/src/widgets/aiscript.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :show-header="widgetProps.showHeader">
+<MkContainer :show-header="widgetProps.showHeader" class="mkw-aiscript">
 	<template #header><i class="fas fa-terminal"></i>{{ $ts._widgets.aiscript }}</template>
 
 	<div class="uylguesu _monospace">
diff --git a/packages/client/src/widgets/clock.vue b/packages/client/src/widgets/clock.vue
index 0a35c4c5ab..fbd2f9e899 100644
--- a/packages/client/src/widgets/clock.vue
+++ b/packages/client/src/widgets/clock.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :naked="widgetProps.transparent" :show-header="false">
+<MkContainer :naked="widgetProps.transparent" :show-header="false" class="mkw-clock">
 	<div class="vubelbmv">
 		<MkAnalogClock class="clock" :thickness="widgetProps.thickness"/>
 	</div>
diff --git a/packages/client/src/widgets/federation.vue b/packages/client/src/widgets/federation.vue
index 1bfb068a2f..a3862077bb 100644
--- a/packages/client/src/widgets/federation.vue
+++ b/packages/client/src/widgets/federation.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :show-header="widgetProps.showHeader" :foldable="foldable" :scrollable="scrollable">
+<MkContainer :show-header="widgetProps.showHeader" :foldable="foldable" :scrollable="scrollable" class="mkw-federation">
 	<template #header><i class="fas fa-globe"></i>{{ $ts._widgets.federation }}</template>
 
 	<div class="wbrkwalb">
diff --git a/packages/client/src/widgets/memo.vue b/packages/client/src/widgets/memo.vue
index f2d1bbc047..8670cb2bac 100644
--- a/packages/client/src/widgets/memo.vue
+++ b/packages/client/src/widgets/memo.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :show-header="widgetProps.showHeader">
+<MkContainer :show-header="widgetProps.showHeader" class="mkw-memo">
 	<template #header><i class="fas fa-sticky-note"></i>{{ $ts._widgets.memo }}</template>
 
 	<div class="otgbylcu">
diff --git a/packages/client/src/widgets/notifications.vue b/packages/client/src/widgets/notifications.vue
index f51e983a0e..18c546ee74 100644
--- a/packages/client/src/widgets/notifications.vue
+++ b/packages/client/src/widgets/notifications.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :style="`height: ${widgetProps.height}px;`" :show-header="widgetProps.showHeader" :scrollable="true">
+<MkContainer :style="`height: ${widgetProps.height}px;`" :show-header="widgetProps.showHeader" :scrollable="true" class="mkw-notifications">
 	<template #header><i class="fas fa-bell"></i>{{ $ts.notifications }}</template>
 	<template #func><button class="_button" @click="configureNotification()"><i class="fas fa-cog"></i></button></template>
 
diff --git a/packages/client/src/widgets/photos.vue b/packages/client/src/widgets/photos.vue
index 8e30765290..5d9b9e2984 100644
--- a/packages/client/src/widgets/photos.vue
+++ b/packages/client/src/widgets/photos.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent" :class="$style.root" :data-transparent="widgetProps.transparent ? true : null">
+<MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent" :class="$style.root" :data-transparent="widgetProps.transparent ? true : null" class="mkw-photos">
 	<template #header><i class="fas fa-camera"></i>{{ $ts._widgets.photos }}</template>
 
 	<div class="">
diff --git a/packages/client/src/widgets/post-form.vue b/packages/client/src/widgets/post-form.vue
index 5b74602c85..b542913357 100644
--- a/packages/client/src/widgets/post-form.vue
+++ b/packages/client/src/widgets/post-form.vue
@@ -1,5 +1,5 @@
 <template>
-<XPostForm class="_panel" :fixed="true" :autofocus="false"/>
+<XPostForm class="_panel mkw-postForm" :fixed="true" :autofocus="false"/>
 </template>
 
 <script lang="ts" setup>
diff --git a/packages/client/src/widgets/rss.vue b/packages/client/src/widgets/rss.vue
index 6b057cdd06..fc65f11813 100644
--- a/packages/client/src/widgets/rss.vue
+++ b/packages/client/src/widgets/rss.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :show-header="widgetProps.showHeader">
+<MkContainer :show-header="widgetProps.showHeader" class="mkw-rss">
 	<template #header><i class="fas fa-rss-square"></i>RSS</template>
 	<template #func><button class="_button" @click="configure"><i class="fas fa-cog"></i></button></template>
 
diff --git a/packages/client/src/widgets/slideshow.vue b/packages/client/src/widgets/slideshow.vue
index 1b6c2d766d..fd78edbe40 100644
--- a/packages/client/src/widgets/slideshow.vue
+++ b/packages/client/src/widgets/slideshow.vue
@@ -1,5 +1,5 @@
 <template>
-<div class="kvausudm _panel" :style="{ height: widgetProps.height + 'px' }">
+<div class="kvausudm _panel mkw-slideshow" :style="{ height: widgetProps.height + 'px' }">
 	<div @click="choose">
 		<p v-if="widgetProps.folderId == null">
 			{{ $ts.folder }}
diff --git a/packages/client/src/widgets/timeline.vue b/packages/client/src/widgets/timeline.vue
index c9a9e68bb9..408cf2cbea 100644
--- a/packages/client/src/widgets/timeline.vue
+++ b/packages/client/src/widgets/timeline.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :show-header="widgetProps.showHeader" :style="`height: ${widgetProps.height}px;`" :scrollable="true">
+<MkContainer :show-header="widgetProps.showHeader" :style="`height: ${widgetProps.height}px;`" :scrollable="true" class="mkw-timeline">
 	<template #header>
 		<button class="_button" @click="choose">
 			<i v-if="widgetProps.src === 'home'" class="fas fa-home"></i>
diff --git a/packages/client/src/widgets/trends.vue b/packages/client/src/widgets/trends.vue
index 34bbc16a8b..9680f1c892 100644
--- a/packages/client/src/widgets/trends.vue
+++ b/packages/client/src/widgets/trends.vue
@@ -1,5 +1,5 @@
 <template>
-<MkContainer :show-header="widgetProps.showHeader">
+<MkContainer :show-header="widgetProps.showHeader" class="mkw-trends">
 	<template #header><i class="fas fa-hashtag"></i>{{ $ts._widgets.trends }}</template>
 
 	<div class="wbrkwala">
-- 
cgit v1.2.3-freya

