From ba76beaf1045a3c9d59d5fd123a578b0d7ec6bff Mon Sep 17 00:00:00 2001 From: kash / Hytus Date: Sat, 20 Sep 2025 05:28:20 +0900 Subject: [PATCH 1/2] fix: replace lossy-equal to strict-equal chore(eslint): add rule 'eqeqeq' Signed-off-by: kash / Hytus --- frontend/app/components/site/a-user.vue | 2 +- .../app/components/site/category-tree.vue | 4 +-- frontend/app/components/site/list-comment.vue | 8 ++--- .../app/components/site/list-notification.vue | 2 +- frontend/app/components/site/md-content.vue | 2 +- frontend/app/components/site/md-editor.vue | 4 +-- frontend/app/components/site/mod/grid-mod.vue | 2 +- frontend/app/components/site/mod/list-mod.vue | 2 +- frontend/app/components/site/mod/mod-list.vue | 6 ++-- frontend/app/components/site/mod/mod-row.vue | 2 +- .../app/components/site/mod/mod-status.vue | 6 ++-- .../site/notifications/base-notification.vue | 6 ++-- .../site/pages/admin/admin-audit-log.vue | 8 ++--- .../site/pages/admin/admin-edit-game.vue | 2 +- .../site/pages/admin/admin-report.vue | 8 ++--- .../components/site/pages/edit-mod-page.vue | 2 +- .../site/pages/edit-mod/edit-dependencies.vue | 2 +- .../site/pages/edit-mod/edit-mod-extra.vue | 2 +- .../site/pages/edit-mod/edit-mod-files.vue | 6 ++-- .../site/pages/edit-mod/edit-mod-images.vue | 2 ++ .../site/pages/edit-mod/edit-mod-members.vue | 6 ++-- .../app/components/site/pages/mod-page.vue | 4 +-- .../components/site/pages/mod/mod-alerts.vue | 4 +-- .../site/pages/mod/mod-download-buttons.vue | 4 +-- .../site/pages/mod/mod-download.vue | 2 +- .../components/site/pages/mod/mod-tabs.vue | 2 +- .../site/pages/mod/mod-top-buttons.vue | 2 +- .../app/components/site/pages/page-block.vue | 12 ++++---- .../app/components/site/pages/the-header.vue | 4 +-- frontend/app/components/site/the-comments.vue | 10 +++---- frontend/app/components/site/thread-list.vue | 2 +- frontend/app/components/site/user-list.vue | 2 +- .../app/components/ui/controls/m-button.vue | 6 ++-- .../app/components/ui/controls/m-duration.vue | 2 +- .../components/ui/controls/m-img-uploader.vue | 2 +- .../app/components/ui/controls/m-input.vue | 2 +- .../app/components/ui/controls/m-select.vue | 30 +++++++++---------- .../app/components/ui/controls/m-time.vue | 4 +-- .../app/components/ui/controls/m-uploader.vue | 2 +- frontend/app/components/ui/layout/m-alert.vue | 10 +++---- .../ui/layout/m-breadcrumb/link.vue | 20 ++++++++----- frontend/app/components/ui/layout/m-modal.vue | 6 ++-- .../app/components/ui/layout/m-nav/link.vue | 2 +- frontend/app/components/ui/layout/m-tab.vue | 2 +- frontend/app/components/ui/layout/m-tabs.vue | 4 +-- .../ui/layout/m-toggle-group/item.vue | 14 ++++----- frontend/app/composables/useEditResource.ts | 2 +- frontend/app/composables/useResource.ts | 2 +- frontend/app/composables/useRouteQuery.js | 12 ++++---- .../app/composables/useWatchedFetchMany.ts | 6 ++-- frontend/app/pages/admin/bans/index.vue | 2 +- .../app/pages/admin/documents/[document].vue | 2 +- frontend/app/pages/admin/roles/index.vue | 6 ++-- frontend/app/pages/g/[game].vue | 10 +++---- .../g/[game]/admin/categories/[category].vue | 4 +-- frontend/app/pages/g/[game]/user/[user].vue | 16 +++++----- frontend/app/pages/index.vue | 2 +- frontend/app/pages/thread/[thread]/index.vue | 2 +- frontend/app/pages/user/[user]/comments.vue | 2 +- frontend/app/pages/user/[user]/threads.vue | 2 +- frontend/app/plugins/mws-api.ts | 2 +- frontend/app/store/index.ts | 12 ++++---- frontend/app/utils/bbcode-parser.js | 2 +- frontend/app/utils/fetch.ts | 2 +- frontend/app/utils/helpers.ts | 18 +++++------ frontend/app/utils/markdown/media.ts | 18 +++++------ frontend/app/utils/markdown/mention.ts | 4 +-- frontend/app/utils/md-parser.ts | 2 +- frontend/app/utils/mod-helpers.ts | 2 +- frontend/eslint.config.mjs | 2 ++ frontend/nuxt.config.ts | 10 +++---- 71 files changed, 196 insertions(+), 186 deletions(-) diff --git a/frontend/app/components/site/a-user.vue b/frontend/app/components/site/a-user.vue index 471b15e7..d07d1177 100644 --- a/frontend/app/components/site/a-user.vue +++ b/frontend/app/components/site/a-user.vue @@ -105,7 +105,7 @@ const userColor = computed(() => { const neededGap = computed(() => { if (props.avatar) { - return props.avatarSize == 'xs' ? 1 : 2; + return props.avatarSize === 'xs' ? 1 : 2; } }); diff --git a/frontend/app/components/site/category-tree.vue b/frontend/app/components/site/category-tree.vue index 4f349835..e005c5ac 100644 --- a/frontend/app/components/site/category-tree.vue +++ b/frontend/app/components/site/category-tree.vue @@ -57,7 +57,7 @@ const queryDelayed = refDebounced(queryVm, 250); const lowSearch = computed(() => queryDelayed.value.toLocaleLowerCase()); const currentCategoryId = props.setQuery ? useRouteQuery('category') : useVModel(props); -const selected = computed(() => props.category?.id == parseInt(currentCategoryId.value)); +const selected = computed(() => props.category?.id === parseInt(currentCategoryId.value)); const classes = computed(() => ({ 'cursor-pointer': true, 'tree-button': true, 'selected': selected.value })); const open = ref(!props.category); @@ -115,7 +115,7 @@ function hasDescendantSelected(category: Category, current: Category[] | null = } function onClickCategory(category: Category) { - if (parseInt(currentCategoryId.value) == category.id) { + if (parseInt(currentCategoryId.value) === category.id) { currentCategoryId.value = null; open.value = false; } else { diff --git a/frontend/app/components/site/list-comment.vue b/frontend/app/components/site/list-comment.vue index 6d20d64e..5f6c1c48 100644 --- a/frontend/app/components/site/list-comment.vue +++ b/frontend/app/components/site/list-comment.vue @@ -150,7 +150,7 @@ const replies = computed(() => props.fetchReplies ? fetchedReplies.value : new P const isAnswer = computed(() => { return props.commentable && Object.hasOwn(props.commentable, 'answer_comment_id') - && (props.commentable as Thread)?.answer_comment_id == props.comment.id; + && (props.commentable as Thread)?.answer_comment_id === props.comment.id; }); watch(replies, val => { @@ -159,7 +159,7 @@ watch(replies, val => { if (props.comment.mentions) { content.value = content.value.replace(/<@([0-9]+)>/g, (match, id) => { - const user = props.comment.mentions.find(user => user.id == id); + const user = props.comment.mentions.find(user => user.id === id); if (user) { return `@${user.unique_name}`; @@ -191,7 +191,7 @@ const canDelete = computed(() => { const canReply = computed(() => props.canComment && !props.comment.user?.blocked_me); const classes = computed(() => { - const focus = focusComment.value == props.comment.id || (props.currentFocus && props.currentFocus.id == props.comment.id); + const focus = (focusComment.value && parseInt(focusComment.value) === props.comment.id) || (props.currentFocus && props.currentFocus.id === props.comment.id); return { comment: true, reply: props.isReply, @@ -211,7 +211,7 @@ const commentPage = computed(() => { }); onMounted(() => { - if ((focusComment.value == props.comment?.id) || params.comment) { + if ((focusComment.value && focusComment.value === props.comment.id) || params.comment) { const element: HTMLDivElement = contentBlockRef.value.element; if (element) { diff --git a/frontend/app/components/site/list-notification.vue b/frontend/app/components/site/list-notification.vue index b79d9a65..99bddadf 100644 --- a/frontend/app/components/site/list-notification.vue +++ b/frontend/app/components/site/list-notification.vue @@ -70,7 +70,7 @@ const to = computed(() => { } else { let obj, objType; - if (defintion.value.link_object == 'context') { + if (defintion.value.link_object === 'context') { obj = context.value; objType = notif.value.context_type; } else { diff --git a/frontend/app/components/site/md-content.vue b/frontend/app/components/site/md-content.vue index 2a23ba43..bff0a004 100644 --- a/frontend/app/components/site/md-content.vue +++ b/frontend/app/components/site/md-content.vue @@ -27,7 +27,7 @@ const mdText = computed(() => { return ''; } - if (parserVersion == 1) { + if (parserVersion === 1) { return oldParseMarkdown(text, allowAnchors); } else { return parseMarkdown(text, allowAnchors, removeTags); diff --git a/frontend/app/components/site/md-editor.vue b/frontend/app/components/site/md-editor.vue index 9d04572e..3ee032c8 100644 --- a/frontend/app/components/site/md-editor.vue +++ b/frontend/app/components/site/md-editor.vue @@ -79,7 +79,7 @@ function clickTool(tool: Tool) { inserted = ''; for (let i = 0; i < lines.length; i++) { const line = lines[i]; - if (i != 0) { + if (i !== 0) { inserted += '\n'; } @@ -103,7 +103,7 @@ function clickTool(tool: Tool) { } function onKeyDown(e: KeyboardEvent) { - if (e.key == 'Tab') { + if (e.key === 'Tab') { e.preventDefault(); clickTool({ insert: '\t$', diff --git a/frontend/app/components/site/mod/grid-mod.vue b/frontend/app/components/site/mod/grid-mod.vue index ffe716f8..85668bdf 100644 --- a/frontend/app/components/site/mod/grid-mod.vue +++ b/frontend/app/components/site/mod/grid-mod.vue @@ -65,7 +65,7 @@ const { mod, game, static: isStatic, noGame, sort } = defineProps<{ const i18n = useI18n(); const locale = computed(() => i18n.locale.value); const showGame = computed(() => !noGame && mod.game); -const date = computed(() => sort == 'published_at' ? mod.published_at : mod.bumped_at); +const date = computed(() => sort === 'published_at' ? mod.published_at : mod.bumped_at); const likes = computed(() => shortStat(mod.likes)); const downloads = computed(() => shortStat(mod.downloads)); const views = computed(() => shortStat(mod.views)); diff --git a/frontend/app/components/site/mod/list-mod.vue b/frontend/app/components/site/mod/list-mod.vue index 4903b3f3..199ead4c 100644 --- a/frontend/app/components/site/mod/list-mod.vue +++ b/frontend/app/components/site/mod/list-mod.vue @@ -74,7 +74,7 @@ const { mod, noGame, displayMode = 1, sort } = defineProps<{ }>(); const showGame = computed(() => !noGame && mod.game); -const date = computed(() => sort == 'published_at' ? mod.published_at : mod.bumped_at); +const date = computed(() => sort === 'published_at' ? mod.published_at : mod.bumped_at); const gameUrl = computed(() => `/g/${store.currentGame?.short_name || mod.game?.short_name || mod.game?.id}`); const locale = computed(() => useI18n().locale.value); const tags = computed(() => { diff --git a/frontend/app/components/site/mod/mod-list.vue b/frontend/app/components/site/mod/mod-list.vue index f2c5e25f..bcc6b55e 100644 --- a/frontend/app/components/site/mod/mod-list.vue +++ b/frontend/app/components/site/mod/mod-list.vue @@ -174,7 +174,7 @@ const selectedCategory = useRouteQuery('category'); const sortByQuery = useRouteQuery('sort'); const sortBy = computed(() => sortByQuery.value ?? props.defaultSortBy ?? user?.extra?.default_mods_sort ?? 'bumped_at'); -const sortByPopularity = computed(() => sortBy.value == 'daily_score' || sortBy.value == 'weekly_score' || sortBy.value == 'score'); +const sortByPopularity = computed(() => sortBy.value === 'daily_score' || sortBy.value === 'weekly_score' || sortBy.value === 'score'); const sortByOtherOptions = { best_match: true, random: true, likes: true, downloads: true, views: true, name: true }; const sortByOther = computed(() => sortByOtherOptions[sortBy.value] === true); @@ -221,6 +221,8 @@ const currentDisplayCats = computed(() => { const cats: Category[] = []; for (const cat of currCategories.value) { + // TODO: fix this equality check + // null (cat.parent_id) == undefined (selectedCategory.value) is true, so it may break if simply replacing with === if (cat.parent_id == selectedCategory.value) { cats.push(cat); } @@ -257,7 +259,7 @@ watch(loadMorePageOverride, newVal => { savedMods.value = currentMods.value; fetchedMods.value = undefined; - loading.value = savedMods.value.length == 0; + loading.value = savedMods.value.length === 0; planLoad(); } }); diff --git a/frontend/app/components/site/mod/mod-row.vue b/frontend/app/components/site/mod/mod-row.vue index d2c6d8f1..0b89e7df 100644 --- a/frontend/app/components/site/mod/mod-row.vue +++ b/frontend/app/components/site/mod/mod-row.vue @@ -56,7 +56,7 @@ const props = withDefaults(defineProps<{ }>(), { displayMode: 1, lite: false }); const showGame = computed(() => !props.noGame && props.mod.game); -const date = computed(() => props.sort == 'published_at' ? props.mod.published_at : props.mod.bumped_at); +const date = computed(() => props.sort === 'published_at' ? props.mod.published_at : props.mod.bumped_at); const likes = computed(() => props.mod.likes); const downloads = computed(() => props.mod.downloads); const views = computed(() => props.mod.views); diff --git a/frontend/app/components/site/mod/mod-status.vue b/frontend/app/components/site/mod/mod-status.vue index f60a61b3..52b098e0 100644 --- a/frontend/app/components/site/mod/mod-status.vue +++ b/frontend/app/components/site/mod/mod-status.vue @@ -27,11 +27,11 @@ const status = computed<[Component, string, string?] | null>(() => { return [MdiCloseThick, 'mod_rejected', 'text-danger']; } else if (!mod.has_download) { return [MdiDownloadOff, 'no_downloads', 'text-warning']; - } else if (mod.visibility == 'public' && !mod.published_at) { + } else if (mod.visibility === 'public' && !mod.published_at) { return [MdiNewspaperRemove, 'not_published', 'text-warning']; - } else if (mod.visibility == 'unlisted') { + } else if (mod.visibility === 'unlisted') { return [MdiEyeOff, 'unlisted']; - } else if (mod.visibility == 'private') { + } else if (mod.visibility === 'private') { return [MdiLock, 'private']; } diff --git a/frontend/app/components/site/notifications/base-notification.vue b/frontend/app/components/site/notifications/base-notification.vue index b5dd3256..9ebf1730 100644 --- a/frontend/app/components/site/notifications/base-notification.vue +++ b/frontend/app/components/site/notifications/base-notification.vue @@ -25,7 +25,7 @@ const name = computed(() => { return null; } - if (typeof props.object == 'string') { + if (typeof props.object === 'string') { return props.object; } @@ -35,7 +35,7 @@ const name = computed(() => { const typeHint = computed(() => { const n = name.value; - if (typeof props.object == 'string') { + if (typeof props.object === 'string') { return null; } @@ -45,5 +45,5 @@ const typeHint = computed(() => { } }); -const link = computed(() => typeof props.object == 'object' ? getObjectLink(props.type, props.object) : null); +const link = computed(() => typeof props.object === 'object' ? getObjectLink(props.type, props.object) : null); diff --git a/frontend/app/components/site/pages/admin/admin-audit-log.vue b/frontend/app/components/site/pages/admin/admin-audit-log.vue index 9a7313e5..3cc1f0d2 100644 --- a/frontend/app/components/site/pages/admin/admin-audit-log.vue +++ b/frontend/app/components/site/pages/admin/admin-audit-log.vue @@ -111,17 +111,17 @@ useI18n({ }); const custom = computed(() => { - if (log.type == 'ban') { + if (log.type === 'ban') { return log.data.with.expire_date ? `until ${log.data.with.expire_date}` : 'permanently'; - } else if (log.type == 'mod_approve_status') { + } else if (log.type === 'mod_approve_status') { return log.data.status ? 'approved' : 'rejected'; - } else if (log.type == 'mod_suspend_status') { + } else if (log.type === 'mod_suspend_status') { return log.data.status ? 'suspended' : 'unsuspended'; } }); const customDetails = computed(() => { - if (log.type == 'mod_approve_status' || log.type == 'mod_suspend_status') { + if (log.type === 'mod_approve_status' || log.type === 'mod_suspend_status') { return 'Reason: ' + log.data.reason; } }); diff --git a/frontend/app/components/site/pages/admin/admin-edit-game.vue b/frontend/app/components/site/pages/admin/admin-edit-game.vue index d3063e1b..5659e34e 100644 --- a/frontend/app/components/site/pages/admin/admin-edit-game.vue +++ b/frontend/app/components/site/pages/admin/admin-edit-game.vue @@ -52,7 +52,7 @@ const { data: modManagers } = await useFetchMany(mmUrl, { } }); -const globalModManagers = computed(() => modManagers.value?.data.filter(mm => mm.game_id == null)); +const globalModManagers = computed(() => modManagers.value?.data.filter(mm => mm.game_id === undefined)); const mergeParams = reactive({ thumbnail_file: thumbnailBlob, diff --git a/frontend/app/components/site/pages/admin/admin-report.vue b/frontend/app/components/site/pages/admin/admin-report.vue index 8dd2fb3b..a66335e6 100644 --- a/frontend/app/components/site/pages/admin/admin-report.vue +++ b/frontend/app/components/site/pages/admin/admin-report.vue @@ -40,7 +40,7 @@ const store = useStore(); const { t } = useI18n(); const casesUrl = computed(() => getGameResourceUrl('cases', game)); const contentTitle = computed(() => { - if (report.reportable_type == 'mod' || report.reportable_type == 'user') { + if (report.reportable_type === 'mod' || report.reportable_type === 'user') { return t('name'); } else { return t('content'); @@ -51,7 +51,7 @@ const currentContent = computed(() => { if (!report.reportable) { return; } - if (report.reportable_type == 'mod' || report.reportable_type == 'user') { + if (report.reportable_type === 'mod' || report.reportable_type === 'user') { return (report.reportable as Mod | User).name; } else { return (report.reportable as Comment).content; @@ -59,7 +59,7 @@ const currentContent = computed(() => { }); const content = computed(() => { - if (report.reportable_type == 'mod' || report.reportable_type == 'user') { + if (report.reportable_type === 'mod' || report.reportable_type === 'user') { return report.name; } else { return report.data.content; @@ -71,7 +71,7 @@ const reportedUser = computed(() => { return; } - if (report.reportable_type == 'user') { + if (report.reportable_type === 'user') { return report.reportable as User; } else { return (report.reportable as { id: number; user: User }).user; diff --git a/frontend/app/components/site/pages/edit-mod-page.vue b/frontend/app/components/site/pages/edit-mod-page.vue index 7b8ba0ca..979d5c37 100644 --- a/frontend/app/components/site/pages/edit-mod-page.vue +++ b/frontend/app/components/site/pages/edit-mod-page.vue @@ -35,7 +35,7 @@ const store = useStore(); const initialMod = defineModel('mod', { required: true }); -if (initialMod.value.id == 0) { +if (initialMod.value.id === 0) { initialMod.value.user_id = store.user!.id; initialMod.value.user = store.user!; } diff --git a/frontend/app/components/site/pages/edit-mod/edit-dependencies.vue b/frontend/app/components/site/pages/edit-mod/edit-dependencies.vue index 669f596c..12bf5106 100644 --- a/frontend/app/components/site/pages/edit-mod/edit-dependencies.vue +++ b/frontend/app/components/site/pages/edit-mod/edit-dependencies.vue @@ -122,7 +122,7 @@ async function addDependency(onError) { dep.mod = selectedMod.value; } try { - if (dep.id == -1) { + if (dep.id === -1) { if (props.paused) { currentDep.value!.id = 0; dependencies.value.push(currentDep.value!); diff --git a/frontend/app/components/site/pages/edit-mod/edit-mod-extra.vue b/frontend/app/components/site/pages/edit-mod/edit-mod-extra.vue index 17f3387c..558b03a7 100644 --- a/frontend/app/components/site/pages/edit-mod/edit-mod-extra.vue +++ b/frontend/app/components/site/pages/edit-mod/edit-mod-extra.vue @@ -30,7 +30,7 @@ const { t } = useI18n(); const superUpdate = inject('canSuperUpdate'); -const member = computed(() => user ? mod.value.members.find(member => member.id == user.id) : null); +const member = computed(() => user ? mod.value.members.find(member => member.id === user.id) : null); const canDelete = computed(() => superUpdate || member.value?.level === 'maintainer'); watch(() => mod.value.game_id, () => mod.value.category_id = undefined); diff --git a/frontend/app/components/site/pages/edit-mod/edit-mod-files.vue b/frontend/app/components/site/pages/edit-mod/edit-mod-files.vue index 1f338c03..687a5f48 100644 --- a/frontend/app/components/site/pages/edit-mod/edit-mod-files.vue +++ b/frontend/app/components/site/pages/edit-mod/edit-mod-files.vue @@ -354,7 +354,7 @@ function fileDeleted(file: MWSFile) { mod.value.used_storage -= file.size; } - if (files.value.length == 0) { + if (files.value.length === 0) { filesPage.value = 1; refreshFiles(); } @@ -373,7 +373,7 @@ async function deleteLink(link: Link) { remove(links.value, link); updateHasDownload(); - if (links.value.length == 0) { + if (links.value.length === 0) { linksPage.value = 1; refreshLinks(); } @@ -397,7 +397,7 @@ async function saveEditLink(error) { try { if (link) { - if (link.id == -1) { + if (link.id === -1) { if (mod.value.id) { const newLink = await postRequest(`mods/${mod.value.id}/links`, link); links.value.push(newLink); diff --git a/frontend/app/components/site/pages/edit-mod/edit-mod-images.vue b/frontend/app/components/site/pages/edit-mod/edit-mod-images.vue index 3cac264b..e811fd0c 100644 --- a/frontend/app/components/site/pages/edit-mod/edit-mod-images.vue +++ b/frontend/app/components/site/pages/edit-mod/edit-mod-images.vue @@ -131,6 +131,8 @@ async function setImageOrder(img: Image, order: number) { await patchRequest(`images/${img.id}`, { display_order: img.display_order + order }); img.display_order = img.display_order + order; + // TODO: fix this equality check + // I don't know this filter is working correctly... images.value = images.value.filter(v => v != img); images.value.splice(img.display_order, 0, img); diff --git a/frontend/app/components/site/pages/edit-mod/edit-mod-members.vue b/frontend/app/components/site/pages/edit-mod/edit-mod-members.vue index 862a6ea8..22f975ba 100644 --- a/frontend/app/components/site/pages/edit-mod/edit-mod-members.vue +++ b/frontend/app/components/site/pages/edit-mod/edit-mod-members.vue @@ -104,7 +104,7 @@ const levelOptions = computed(() => { levels.push({ name: t('member_level_maintainer'), id: 'maintainer' }); } - if (superUpdate || member.value?.level == 'maintainer') { + if (superUpdate || member.value?.level === 'maintainer') { levels.push({ name: t('member_level_collaborator'), id: 'collaborator' }); } @@ -116,7 +116,7 @@ const addingNew = ref(false); const showTransferOwner = ref(false); const members = ref(clone(mod.value.members)); const transferOwner = ref({ owner_id: null, keep_owner_level: null }); -const member = computed(() => user ? mod.value.members.find(member => member.id == user.id) : null); +const member = computed(() => user ? mod.value.members.find(member => member.id === user.id) : null); const selectedUser = ref(); const selectedLevel = ref<'collaborator' | 'maintainer' | 'contributor' | 'viewer'>('collaborator'); @@ -210,7 +210,7 @@ async function cancelTransferRequest() { } function canEditMember(member: ModMember) { - return (user && member.id == user.id) || (memberPerms.value ? memberPerms.value.includes(member.level) : false); + return (user && member.id === user.id) || (memberPerms.value ? memberPerms.value.includes(member.level) : false); } diff --git a/frontend/app/components/site/pages/mod-page.vue b/frontend/app/components/site/pages/mod-page.vue index c4cf09b5..adbaf3ce 100644 --- a/frontend/app/components/site/pages/mod-page.vue +++ b/frontend/app/components/site/pages/mod-page.vue @@ -56,7 +56,7 @@ if (mod.value.game) { if (mod.value.id && import.meta.client) { postRequest(`mods/${mod.value.id}/register-view`, null, { onResponse(response: any) { - if (response.status == 201) { + if (response.status === 201) { mod.value.views++; } } @@ -72,7 +72,7 @@ const breadcrumb = computed(() => { breadcrumb.push(...mod.value.breadcrumb); } - if (route.name == 'mod-mod-edit') { + if (route.name === 'mod-mod-edit') { breadcrumb.push({ name: t('edit') }); } diff --git a/frontend/app/components/site/pages/mod/mod-alerts.vue b/frontend/app/components/site/pages/mod/mod-alerts.vue index d3824c30..a873f2b0 100644 --- a/frontend/app/components/site/pages/mod/mod-alerts.vue +++ b/frontend/app/components/site/pages/mod/mod-alerts.vue @@ -70,7 +70,7 @@ const memberWaitingRole = computed(() => { return t(`member_level_${member.level}`); } }); -const showPublish = computed(() => canEdit.value && !props.mod.published_at && props.mod.visibility == 'public' && props.mod.has_download); +const showPublish = computed(() => canEdit.value && !props.mod.published_at && props.mod.visibility === 'public' && props.mod.has_download); const hasAlerts = computed(() => { const mod = props.mod; @@ -79,7 +79,7 @@ const hasAlerts = computed(() => { return false; } - const transfer = mod.transfer_request && mod.transfer_request.user_id == user?.id; + const transfer = mod.transfer_request && mod.transfer_request.user_id === user?.id; return !mod.has_download || !mod.approved || mod.suspended || memberWaiting.value || transfer || showPublish.value; }); diff --git a/frontend/app/components/site/pages/mod/mod-download-buttons.vue b/frontend/app/components/site/pages/mod/mod-download-buttons.vue index 2cbf8cb1..3bdc02e6 100644 --- a/frontend/app/components/site/pages/mod/mod-download-buttons.vue +++ b/frontend/app/components/site/pages/mod/mod-download-buttons.vue @@ -65,8 +65,8 @@ const primaryModManager = computed(() => { const chosen = chosenModManager.value; const defaultManager = props.mod.game?.default_mod_manager_id; - return managers.value?.find(manager => manager.id == chosen) - ?? managers.value?.find(manager => manager.id == defaultManager) + return managers.value?.find(manager => manager.id === chosen) + ?? managers.value?.find(manager => manager.id === defaultManager) ?? managers.value[0]; }); diff --git a/frontend/app/components/site/pages/mod/mod-download.vue b/frontend/app/components/site/pages/mod/mod-download.vue index 52010bc5..47924221 100644 --- a/frontend/app/components/site/pages/mod/mod-download.vue +++ b/frontend/app/components/site/pages/mod/mod-download.vue @@ -46,5 +46,5 @@ const props = defineProps<{ const i18n = useI18n(); const locale = computed(() => i18n.locale.value); -const image = computed(() => props.mod.images?.find(image => image.id == props.file.image_id)); +const image = computed(() => props.mod.images?.find(image => image.id === props.file.image_id)); diff --git a/frontend/app/components/site/pages/mod/mod-tabs.vue b/frontend/app/components/site/pages/mod/mod-tabs.vue index 5d5f56bb..fe44b90c 100644 --- a/frontend/app/components/site/pages/mod/mod-tabs.vue +++ b/frontend/app/components/site/pages/mod/mod-tabs.vue @@ -81,7 +81,7 @@ const dependencies = computed(() => { const combinedDeps = [...deps, ...templateDeps]; - return combinedDeps.sort((a, b) => a.order == b.order ? a.id - b.id : a.order - b.order); + return combinedDeps.sort((a, b) => a.order === b.order ? a.id - b.id : a.order - b.order); }); const instructions = computed(() => (props.mod.instructs_template ? props.mod.instructs_template.instructions + '\n\n' : '') + props.mod.instructions); diff --git a/frontend/app/components/site/pages/mod/mod-top-buttons.vue b/frontend/app/components/site/pages/mod/mod-top-buttons.vue index b0ca0476..7fbb56bd 100644 --- a/frontend/app/components/site/pages/mod/mod-top-buttons.vue +++ b/frontend/app/components/site/pages/mod/mod-top-buttons.vue @@ -43,7 +43,7 @@ function deleteAllFiles() { async yes() { await deleteRequest(`mods/${props.mod.id}/files`); props.mod.files = new Paginator(); - if (props.mod.download_type == 'file') { + if (props.mod.download_type === 'file') { props.mod.download = undefined; props.mod.download_type = undefined; } diff --git a/frontend/app/components/site/pages/page-block.vue b/frontend/app/components/site/pages/page-block.vue index 488ad516..68aaee2d 100644 --- a/frontend/app/components/site/pages/page-block.vue +++ b/frontend/app/components/site/pages/page-block.vue @@ -94,12 +94,12 @@ const classes = computed(() => ({ const innerClasses = computed(() => ({ 'mx-auto': true, 'page-content': true, - 'page-block-nm': props.size == 'nm', - 'page-block-full': props.size == 'full', - 'page-block-md': props.size == 'md', - 'page-block-sm': props.size == 'sm', - 'page-block-xs': props.size == 'xs', - 'page-block-2xs': props.size == '2xs' + 'page-block-nm': props.size === 'nm', + 'page-block-full': props.size === 'full', + 'page-block-md': props.size === 'md', + 'page-block-sm': props.size === 'sm', + 'page-block-xs': props.size === 'xs', + 'page-block-2xs': props.size === '2xs' })); diff --git a/frontend/app/components/site/pages/the-header.vue b/frontend/app/components/site/pages/the-header.vue index 8ad5838f..46a897a2 100644 --- a/frontend/app/components/site/pages/the-header.vue +++ b/frontend/app/components/site/pages/the-header.vue @@ -233,12 +233,12 @@ watch(query, val => { onMounted(() => { window.addEventListener('keydown', function (e) { - if (e.ctrlKey && e.key == 'k' /** k */) { + if (e.ctrlKey && e.key === 'k' /** k */) { showSearch.value = true; e.preventDefault(); } - if (e.key == 'Escape') { + if (e.key === 'Escape') { showSearch.value = false; } }); diff --git a/frontend/app/components/site/the-comments.vue b/frontend/app/components/site/the-comments.vue index e6aa0c44..a2cbf232 100644 --- a/frontend/app/components/site/the-comments.vue +++ b/frontend/app/components/site/the-comments.vue @@ -222,7 +222,7 @@ function onTextareaKeyup(event: KeyboardEvent) { mentionPos.value = [coords.left + rect.left, coords.top + rect.top]; - if (event.key == 'Enter' || event.key == 'ArrowUp' || event.key == 'Ctrl' || event.key == 'ArrowDown') { + if (event.key === 'Enter' || event.key === 'ArrowUp' || event.key === 'Ctrl' || event.key === 'ArrowDown') { showMentions.value = false; } } @@ -230,20 +230,20 @@ function onTextareaKeyup(event: KeyboardEvent) { function onTextareaInput(event: InputEvent) { const textArea = event.target as HTMLTextAreaElement; - if (event.inputType == 'insertText' || event.inputType == 'insertFromPaste') { - if (event.inputType == 'insertText' && event.data == '@') { + if (event.inputType === 'insertText' || event.inputType === 'insertFromPaste') { + if (event.inputType === 'insertText' && event.data === '@') { mentionRange.value = [textArea.selectionEnd, textArea.selectionEnd]; showMentions.value = true; } else if (showMentions.value) { mentionRange.value = [mentionRange.value[0], textArea.selectionEnd]; } - } else if (event.inputType == 'deleteContentBackward' && commentContent.value.charAt(mentionRange.value[0] - 1) != '@') { + } else if (event.inputType === 'deleteContentBackward' && commentContent.value.charAt(mentionRange.value[0] - 1) !== '@') { showMentions.value = false; } } function onTextareaMouseDown(event: MouseEvent) { - if (event.button == 0) { + if (event.button === 0) { showMentions.value = false; } } diff --git a/frontend/app/components/site/thread-list.vue b/frontend/app/components/site/thread-list.vue index 82c8baba..6a9726e6 100644 --- a/frontend/app/components/site/thread-list.vue +++ b/frontend/app/components/site/thread-list.vue @@ -147,7 +147,7 @@ const { data: categories, refresh: refreshCats } = await useFetchMany categories.value?.data.find(cat => cat.id == categoryId.value)); +const currentCategory = computed(() => categories.value?.data.find(cat => cat.id === categoryId.value)); watch(categoryId, () => { emit('selectCategory', currentCategory.value); page.value = 1; diff --git a/frontend/app/components/site/user-list.vue b/frontend/app/components/site/user-list.vue index 43741e2a..7365daa1 100644 --- a/frontend/app/components/site/user-list.vue +++ b/frontend/app/components/site/user-list.vue @@ -39,7 +39,7 @@ const { url = 'users', column = false, userLink, altBackground = false } = defin }>(); function getUserLink(user) { - if (typeof userLink == 'function') { + if (typeof userLink === 'function') { return userLink(user); } else { return `/user/${user.id}`; diff --git a/frontend/app/components/ui/controls/m-button.vue b/frontend/app/components/ui/controls/m-button.vue index 80832c6d..0e4ad8a1 100644 --- a/frontend/app/components/ui/controls/m-button.vue +++ b/frontend/app/components/ui/controls/m-button.vue @@ -46,9 +46,9 @@ const clss = computed(() => ({ 'button': !props.unstyled, [`button-${props.color}`]: !props.unstyled, 'button-no-bg': props.noBg, - 'button-sm': props.size == 'sm', - 'button-xs': props.size == 'xs', - 'button-lg': props.size == 'lg', + 'button-sm': props.size === 'sm', + 'button-xs': props.size === 'xs', + 'button-lg': props.size === 'lg', 'cursor-pointer': props.unstyled })); diff --git a/frontend/app/components/ui/controls/m-duration.vue b/frontend/app/components/ui/controls/m-duration.vue index 792a4d4d..917f610f 100644 --- a/frontend/app/components/ui/controls/m-duration.vue +++ b/frontend/app/components/ui/controls/m-duration.vue @@ -56,7 +56,7 @@ const controlVm = computed({ } }, set(val: Date | string) { - if (typeof val == 'string') { + if (typeof val === 'string') { vm.value = val; return; } diff --git a/frontend/app/components/ui/controls/m-img-uploader.vue b/frontend/app/components/ui/controls/m-img-uploader.vue index 0bfd75f8..7f51359a 100644 --- a/frontend/app/components/ui/controls/m-img-uploader.vue +++ b/frontend/app/components/ui/controls/m-img-uploader.vue @@ -36,7 +36,7 @@ const fileRef = ref(); const input = ref(); const blob = ref(); const currentSrc = computed(() => { - if (modelValue.value != '') { + if (modelValue.value !== '') { return blob.value || src; } }); diff --git a/frontend/app/components/ui/controls/m-input.vue b/frontend/app/components/ui/controls/m-input.vue index 3a160990..440fb466 100644 --- a/frontend/app/components/ui/controls/m-input.vue +++ b/frontend/app/components/ui/controls/m-input.vue @@ -92,7 +92,7 @@ const uniqueId = useId(); const err = useWatchValidation(vm, elementRef); const labelId = ref(props.id || uniqueId); -const isCheckbox = computed(() => props.type == 'checkbox'); +const isCheckbox = computed(() => props.type === 'checkbox'); const classes = computed(() => ({ 'mw-input': true, 'input-error': !!err.value diff --git a/frontend/app/components/ui/controls/m-select.vue b/frontend/app/components/ui/controls/m-select.vue index 20b73203..4ea10498 100644 --- a/frontend/app/components/ui/controls/m-select.vue +++ b/frontend/app/components/ui/controls/m-select.vue @@ -113,7 +113,7 @@ const emit = defineEmits<{ }>(); const { data: asyncOptions, refresh } = await useFetchMany(props.url ?? '', { - immediate: props.immediateFetch && props.url != undefined, + immediate: props.immediateFetch && props.url !== undefined, params: reactive({ query: searchDebounced, ...props.fetchParams @@ -128,7 +128,7 @@ const { ctrl } = useMagicKeys(); // Only necessary to retrieve the v-model that may not be contained in asyncOptions // Example: user query parameter to prefill a user const { data: fetchedSelected } = await useFetchMany(props.url ?? '', { - immediate: !!(props.url && first.value) && (typeof (first.value) == 'number' || first.value?.length > 0), + immediate: !!(props.url && first.value) && (typeof (first.value) === 'number' || first.value?.length > 0), params: { ids: selected.value, ...props.fetchParams @@ -141,8 +141,8 @@ const opts = computed(() => { if (props.options) { return props.options ?? []; } else { - const opts = reactive(asyncOptions.value != undefined ? [...asyncOptions.value.data] : []); - if (fetchedSelected.value != undefined && fetchedSelected.value.data) { + const opts = reactive(asyncOptions.value !== null && asyncOptions.value !== undefined ? [...asyncOptions.value.data] : []); + if (fetchedSelected.value !== null && fetchedSelected.value !== undefined && fetchedSelected.value.data) { for (const opt of fetchedSelected.value.data) { const val = opt ? optionValue(opt) : null; if (!opts.find(option => optionValue(option) === val)) { @@ -158,7 +158,7 @@ const selectedMax = computed(() => { if (!props.max) { return false; } - const max = typeof props.max == 'number' ? props.max : parseInt(props.max); + const max = typeof props.max === 'number' ? props.max : parseInt(props.max); return selected.value.length >= max; }); const compFilterable = computed(() => props.filterable ?? (!!props.url || opts.value?.length > 10)); @@ -182,7 +182,7 @@ const filtered = computed(() => { }); if (props.filterSelected) { - if (props.multiple && typeof selectedValue.value == 'object') { + if (props.multiple && typeof selectedValue.value === 'object') { options = options.filter(option => optionEnabled(option) && !selected.value.includes(optionValue(option))); } else { options = options.filter(option => optionEnabled(option) && selectedValue.value === optionValue(option)); @@ -203,7 +203,7 @@ const selectedOptions = computed(() => { }); const shownOptions = computed(() => selectedOptions.value.filter((_, i) => { - return !props.maxShown || i < (typeof props.maxShown == 'number' ? props.maxShown : parseInt(props.maxShown)); + return !props.maxShown || i < (typeof props.maxShown === 'number' ? props.maxShown : parseInt(props.maxShown)); })); const selectedOption = computed(() => { @@ -237,7 +237,7 @@ watch(dropdownOpen, val => { function defaultBy(option, propName) { if (typeof props[propName] === 'string') { - if (typeof option == 'object') { + if (typeof option === 'object') { return option[props[propName]]; } else { return option; @@ -248,7 +248,7 @@ function defaultBy(option, propName) { } function optionEnabled(option) { - if (typeof props.enabledBy == 'function') { + if (typeof props.enabledBy === 'function') { return props.enabledBy(option); } else if (props.enabledBy) { return defaultBy(option, 'enabledBy'); @@ -258,7 +258,7 @@ function optionEnabled(option) { } function optionName(option) { - if (typeof props.textBy == 'function') { + if (typeof props.textBy === 'function') { return props.textBy(option); } else { return defaultBy(option, 'textBy'); @@ -266,7 +266,7 @@ function optionName(option) { } function optionValue(option) { - if (typeof props.valueBy == 'function') { + if (typeof props.valueBy === 'function') { return props.valueBy(option); } else { return defaultBy(option, 'valueBy'); @@ -274,7 +274,7 @@ function optionValue(option) { } function optionColor(option) { - if (typeof props.colorBy == 'function') { + if (typeof props.colorBy === 'function') { return props.colorBy(option); } else if (props.colorBy) { return defaultBy(option, 'colorBy'); @@ -288,7 +288,7 @@ watch(searchDebounced, async () => { }); function clearAll() { - if (props.multiple && typeof selectedValue.value == 'object' && opts.value) { + if (props.multiple && typeof selectedValue.value === 'object' && opts.value) { for (const option of opts.value) { const value = optionValue(option); if (optionEnabled(option)) { @@ -325,7 +325,7 @@ function selectOption(option) { dropdownOpen.value = false; } - if (props.multiple && typeof selectedValue.value == 'object') { + if (props.multiple && typeof selectedValue.value === 'object') { if (selectedMax.value) { showInvalid.value = true; setTimeout(() => { @@ -369,7 +369,7 @@ function deselectOption(item) { dropdownOpen.value = false; } - if (props.multiple && typeof selectedValue == 'object') { + if (props.multiple && typeof selectedValue === 'object') { remove(selectedValue.value, value); emit('update:modelValue', selectedValue.value); } else if (props.clearable) { diff --git a/frontend/app/components/ui/controls/m-time.vue b/frontend/app/components/ui/controls/m-time.vue index 529260ce..8f716821 100644 --- a/frontend/app/components/ui/controls/m-time.vue +++ b/frontend/app/components/ui/controls/m-time.vue @@ -47,7 +47,7 @@ const overrideText = computed(() => { return; } - const date = typeof datetime == 'string' ? parseISO(datetime) : datetime; + const date = typeof datetime === 'string' ? parseISO(datetime) : datetime; const secs = Math.abs(differenceInSeconds(now.value, date)); if (relative && useRelativeTime.value) { @@ -87,7 +87,7 @@ function mouseEntered() { dateStyle: 'long' }); - titleHover.value = formatter.format(typeof datetime == 'string' ? parseISO(datetime) : datetime); + titleHover.value = formatter.format(typeof datetime === 'string' ? parseISO(datetime) : datetime); } } diff --git a/frontend/app/components/ui/controls/m-uploader.vue b/frontend/app/components/ui/controls/m-uploader.vue index b2f91c1b..15957648 100644 --- a/frontend/app/components/ui/controls/m-uploader.vue +++ b/frontend/app/components/ui/controls/m-uploader.vue @@ -144,7 +144,7 @@ const reachedMaxFiles = computed(() => { if (!props.maxFiles) { return false; } - return vm.value.length >= (typeof (props.maxFiles) == 'string' ? parseInt(props.maxFiles) : props.maxFiles); + return vm.value.length >= (typeof (props.maxFiles) === 'string' ? parseInt(props.maxFiles) : props.maxFiles); }); const usedSize = computed(() => vm.value.reduce((prev, curr) => prev + curr.size, 0)); diff --git a/frontend/app/components/ui/layout/m-alert.vue b/frontend/app/components/ui/layout/m-alert.vue index 0a2f31cd..6c77db0e 100644 --- a/frontend/app/components/ui/layout/m-alert.vue +++ b/frontend/app/components/ui/layout/m-alert.vue @@ -43,7 +43,7 @@ const icons = { }; const currIcon = computed(() => { - if (typeof props.icon == 'string') { + if (typeof props.icon === 'string') { return props.icon; } else if (props.icon !== false) { return icons[props.color]; @@ -58,10 +58,10 @@ const classes = computed(() => { 'flex': true, 'gap-2': true, 'text-body': true, - 'alert-success': props.color == 'success', - 'alert-danger': props.color == 'danger', - 'alert-info': props.color == 'info', - 'alert-warning': props.color == 'warning', + 'alert-success': props.color === 'success', + 'alert-danger': props.color === 'danger', + 'alert-info': props.color === 'info', + 'alert-warning': props.color === 'warning', 'items-center': true }; }); diff --git a/frontend/app/components/ui/layout/m-breadcrumb/link.vue b/frontend/app/components/ui/layout/m-breadcrumb/link.vue index 8e9199f2..44bbf811 100644 --- a/frontend/app/components/ui/layout/m-breadcrumb/link.vue +++ b/frontend/app/components/ui/layout/m-breadcrumb/link.vue @@ -22,31 +22,35 @@ function getTo(item: Breadcrumb, i: number) { } } else if (item.to) { return `/${item.to}`; - } else if (item.type == 'game') { + } else if (item.type === 'game') { return `/g/${item.id}`; - } else if (item.type == 'category') { + } else if (item.type === 'category') { const first = props.items[0]; const second = props.items[1]; - if (first && first.type == 'game') { + if (first && first.type === 'game') { return getTo(first, 0) + `/mods?category=${item.id}`; - } else if (second && second.type == 'game') { + } else if (second && second.type === 'game') { return getTo(second, 0) + `/mods?category=${item.id}`; } else { return `/category/${item.id}`; } - } else if (item.type == 'forum_category') { + } else if (item.type === 'forum_category') { const second = props.items[1]; - if (second && second.type == 'game') { + if (second && second.type === 'game') { return getTo(second, 0) + `/forum?category=${item.id}`; } else { return `/forum?category=${item.id}`; } - } else if (item.type == 'mod') { + } else if (item.type === 'mod') { return `/mod/${item.id}`; - } else if (item.type == 'thread') { + } else if (item.type === 'thread') { return `/thread/${item.id}`; } } +// TODO: fix this equality check +// fortunately, props.item is referenced from props.items, so `i == props.item` works +// (see: frontend/app/components/ui/layout/m-breadcrumb.vue:L4) +// it is hard to replace deep-equal because it may break if the same item is used multiple times const tos = computed(() => getTo(props.item, props.items.findIndex(i => i == props.item))); diff --git a/frontend/app/components/ui/layout/m-modal.vue b/frontend/app/components/ui/layout/m-modal.vue index ddbab117..f01eab77 100644 --- a/frontend/app/components/ui/layout/m-modal.vue +++ b/frontend/app/components/ui/layout/m-modal.vue @@ -43,9 +43,9 @@ watch(vm, val => { const classes = computed(() => ({ 'modal-body': true, - 'modal-lg': size == 'lg', - 'modal-md': size == 'md', - 'modal-sm': size == 'sm' + 'modal-lg': size === 'lg', + 'modal-md': size === 'md', + 'modal-sm': size === 'sm' })); function onClickOutside() { diff --git a/frontend/app/components/ui/layout/m-nav/link.vue b/frontend/app/components/ui/layout/m-nav/link.vue index 6d873ed5..fb7a30d7 100644 --- a/frontend/app/components/ui/layout/m-nav/link.vue +++ b/frontend/app/components/ui/layout/m-nav/link.vue @@ -21,7 +21,7 @@ const menuOpen = inject>('menuOpen', ref(false)); const root = inject('root', ''); const compAlias = computed(() => { - if (typeof (props.alias) == 'string') { + if (typeof (props.alias) === 'string') { return props.alias ? `${root}/${props.alias}` : root; } }); diff --git a/frontend/app/components/ui/layout/m-tab.vue b/frontend/app/components/ui/layout/m-tab.vue index c8d3164d..2920c909 100644 --- a/frontend/app/components/ui/layout/m-tab.vue +++ b/frontend/app/components/ui/layout/m-tab.vue @@ -30,7 +30,7 @@ const props = defineProps({ const tabState = inject('tabState'); const lazy = inject('lazy'); -const show = computed(() => props.name == tabState.current); +const show = computed(() => props.name === tabState.current); const renderedOnce = ref(false); diff --git a/frontend/app/components/ui/layout/m-tabs.vue b/frontend/app/components/ui/layout/m-tabs.vue index 3d423eef..1be6d6bf 100644 --- a/frontend/app/components/ui/layout/m-tabs.vue +++ b/frontend/app/components/ui/layout/m-tabs.vue @@ -67,7 +67,7 @@ function getCurrentTabs() { if (tab.props) { return { name: tab.props.name, title: tab.props.title }; } - }).filter(tab => typeof tab == 'object') as { name: string; title: string }[]; + }).filter(tab => typeof tab === 'object') as { name: string; title: string }[]; } const tabs = ref(getCurrentTabs()); @@ -78,7 +78,7 @@ function refreshTabs() { // Check if our current tab exists, otherwise fallback to the first. if (tabs.value.length > 0 && tabs.value[0]) { - if (!tabState.current || tabs.value.reduce((prev, curr) => prev && curr.name != tabState.current, true)) { + if (!tabState.current || tabs.value.reduce((prev, curr) => prev && curr.name !== tabState.current, true)) { tabState.current = tabs.value[0].name; } } diff --git a/frontend/app/components/ui/layout/m-toggle-group/item.vue b/frontend/app/components/ui/layout/m-toggle-group/item.vue index ebb09899..8e45d14b 100644 --- a/frontend/app/components/ui/layout/m-toggle-group/item.vue +++ b/frontend/app/components/ui/layout/m-toggle-group/item.vue @@ -13,28 +13,28 @@ diff --git a/frontend/app/pages/index.vue b/frontend/app/pages/index.vue index 26fc34ea..e46f96bf 100644 --- a/frontend/app/pages/index.vue +++ b/frontend/app/pages/index.vue @@ -61,7 +61,7 @@ const links = { }; const currentFollowUrl = computed(() => links[selectedView.value]); -const sortBy = computed(() => selectedView.value == 'all' ? (user.value?.extra?.home_default_mods_sort ?? 'bumped_at') : undefined); +const sortBy = computed(() => selectedView.value === 'all' ? (user.value?.extra?.home_default_mods_sort ?? 'bumped_at') : undefined); watch(selectedView, async () => { await patchRequest('user', { diff --git a/frontend/app/pages/thread/[thread]/index.vue b/frontend/app/pages/thread/[thread]/index.vue index be4d8488..58317c2f 100644 --- a/frontend/app/pages/thread/[thread]/index.vue +++ b/frontend/app/pages/thread/[thread]/index.vue @@ -111,7 +111,7 @@ const cannotCommentReason = computed(() => { async function markCommentAsAnswer(comment: Comment) { try { - if (thread.answer_comment_id == comment.id) { + if (thread.answer_comment_id === comment.id) { await patchRequest(`threads/${thread.id}`, { answer_comment_id: null }); diff --git a/frontend/app/pages/user/[user]/comments.vue b/frontend/app/pages/user/[user]/comments.vue index 646874bb..05c7321f 100644 --- a/frontend/app/pages/user/[user]/comments.vue +++ b/frontend/app/pages/user/[user]/comments.vue @@ -21,7 +21,7 @@ const { user } = defineProps<{ const { hasPermission, user: me } = useStore(); const canEditComments = computed(() => hasPermission('manage-discussions')); -if (user.id != me?.id) { +if (user.id !== me?.id) { useNeedsPermission('manage-discussions'); } diff --git a/frontend/app/pages/user/[user]/threads.vue b/frontend/app/pages/user/[user]/threads.vue index 081caab7..c75c60ff 100644 --- a/frontend/app/pages/user/[user]/threads.vue +++ b/frontend/app/pages/user/[user]/threads.vue @@ -15,7 +15,7 @@ const { user } = defineProps<{ user: User; }>(); -if (user.id != me?.id) { +if (user.id !== me?.id) { useNeedsPermission('manage-discussions'); } diff --git a/frontend/app/plugins/mws-api.ts b/frontend/app/plugins/mws-api.ts index 55298632..017c23a0 100644 --- a/frontend/app/plugins/mws-api.ts +++ b/frontend/app/plugins/mws-api.ts @@ -10,7 +10,7 @@ export default defineNuxtPlugin(() => { credentials: 'include', onRequest({ options }) { // Handle custom query parameter formatting for GET requests - if (options && options.params && (!options.method || options.method == 'GET')) { + if (options && options.params && (!options.method || options.method === 'GET')) { // This retarded code is brought you by stupid web standards https://blog.shalvah.me/posts/fun-stuff-representing-arrays-and-objects-in-query-strings // tl;dr - PHP and JS cannot agree on the format for arrays in queries, we shall use PHP's one. diff --git a/frontend/app/store/index.ts b/frontend/app/store/index.ts index 77216e19..e8a720ae 100644 --- a/frontend/app/store/index.ts +++ b/frontend/app/store/index.ts @@ -44,9 +44,9 @@ export const useStore = defineStore('main', { }), getters: { theme(state) { - if (state.savedTheme == 'light') { + if (state.savedTheme === 'light') { return 'light'; - } else if (state.savedTheme == 'system') { + } else if (state.savedTheme === 'system') { return 'system'; } else { return 'dark'; @@ -64,7 +64,7 @@ export const useStore = defineStore('main', { }, actions: { setTheme(theme: 'light' | 'dark' | 'system') { - if (theme == 'dark') { + if (theme === 'dark') { this.savedTheme = null; } else { this.savedTheme = theme === 'system' ? 'system' : 'light'; @@ -85,7 +85,7 @@ export const useStore = defineStore('main', { async attemptLoginUser(redirect: string | boolean = '/') { await this.loadSiteData(); - if (typeof (redirect) == 'string') { + if (typeof (redirect) === 'string') { useRouter().push(redirect); } }, @@ -143,7 +143,7 @@ export const useStore = defineStore('main', { async logout(redirect: string | boolean = '/') { const router = useRouter(); - if (typeof (redirect) == 'string') { + if (typeof (redirect) === 'string') { router.push(redirect); } @@ -181,7 +181,7 @@ export const useStore = defineStore('main', { if (this.notifications) { promises.push(this.getNotifications()); } - if (this.notificationCount != null) { + if (this.notificationCount !== null) { promises.push(this.getNotificationCount()); } if (this.currentGame) { diff --git a/frontend/app/utils/bbcode-parser.js b/frontend/app/utils/bbcode-parser.js index fc339e74..3c9212fd 100644 --- a/frontend/app/utils/bbcode-parser.js +++ b/frontend/app/utils/bbcode-parser.js @@ -278,7 +278,7 @@ function tagLoop(tagsMap, cleanUp, parent) { } function processTag(tag, module, content) { - const isString = typeof module == 'string'; + const isString = typeof module === 'string'; if (!isString && module.special) return content.replace('[TAG-' + tag.index + ']', module.open); diff --git a/frontend/app/utils/fetch.ts b/frontend/app/utils/fetch.ts index 4fc511dd..7c569af8 100644 --- a/frontend/app/utils/fetch.ts +++ b/frontend/app/utils/fetch.ts @@ -11,7 +11,7 @@ export function buildQueryParams(params, addQueryPrefix = true) { arrayFormat: 'indices', addQueryPrefix, encoder: function (str, defaultEncoder, charset, type) { - if (type == 'value' && typeof str == 'boolean') { + if (type === 'value' && typeof str === 'boolean') { return str ? 1 : 0; } return str; diff --git a/frontend/app/utils/helpers.ts b/frontend/app/utils/helpers.ts index 56a10023..b90ccf4f 100644 --- a/frontend/app/utils/helpers.ts +++ b/frontend/app/utils/helpers.ts @@ -101,7 +101,7 @@ export function setQuery(key: string, value: LocationQueryValueRaw | LocationQue export function serializeObject(data: Record) { const copy = { ...data }; for (const [key, value] of Object.entries(copy)) { - if (value instanceof Array && value.length == 0) { + if (value instanceof Array && value.length === 0) { copy[key] = null; // Thanks web standards for not supporting something as simple as a FUCKING EMPTY ARRAY } } @@ -120,7 +120,7 @@ export function strReplacRange(str: string, start: number, end: number, replacem * Returns whether or not the src URL is external. If it begins with a URL http/https or data: it's "external" */ export function isSrcExternal(src?: string | object | Blob) { - if (typeof src == 'string') { + if (typeof src === 'string') { return src && (src.startsWith('http://') || src.startsWith('https://') || src.startsWith('data:') || src.startsWith('blob:')); } else { return true; @@ -194,13 +194,13 @@ function hexToInt(hex: string) { } function hexToColor(color: string) { - if (color[0] == '#') { + if (color[0] === '#') { color = color.substring(1); } - if (color.length == 3) { + if (color.length === 3) { return [hexToInt(color[0] + color[0]), hexToInt(color[1] + color[1]), hexToInt(color[2] + color[2])]; - } else if (color.length == 6) { + } else if (color.length === 6) { return [hexToInt(color.substring(0, 2)), hexToInt(color.substring(2, 4)), hexToInt(color.substring(4, 6))]; } else { return [255, 255, 255]; @@ -218,8 +218,8 @@ function luminance(color: number[]) { } export function getContrast(color1: string | number[], color2: string | number[]) { - const lum1 = luminance(typeof color1 == 'string' ? hexToColor(color1) : color1); - const lum2 = luminance(typeof color2 == 'string' ? hexToColor(color2) : color2); + const lum1 = luminance(typeof color1 === 'string' ? hexToColor(color1) : color1); + const lum2 = luminance(typeof color2 === 'string' ? hexToColor(color2) : color2); return (Math.max(lum1, lum2) + 0.05) / (Math.min(lum1, lum2) + 0.05); } @@ -228,7 +228,7 @@ export function getContrast(color1: string | number[], color2: string | number[] export function convertRGBDecimalToHex(rgb) { const regex = /rgb *\( *([0-9]{1,3}) *, *([0-9]{1,3}) *, *([0-9]{1,3}) *\)/; const values = regex.exec(rgb); - if (!values || values.length != 4) { + if (!values || values.length !== 4) { return '#fff'; // fall back to white } return '#' @@ -254,7 +254,7 @@ export async function markAllNotificationsAsRead(notifications?: Notification[], */ export function firstNonEmpty(...strs) { for (const s of strs) { - if (typeof s == 'string' && s.length > 0) { + if (typeof s === 'string' && s.length > 0) { return s; } } diff --git a/frontend/app/utils/markdown/media.ts b/frontend/app/utils/markdown/media.ts index 9787b0f9..140ef9fd 100644 --- a/frontend/app/utils/markdown/media.ts +++ b/frontend/app/utils/markdown/media.ts @@ -203,11 +203,11 @@ function tokenizeImagesAndMedia(state: any, silent: boolean, md: MarkdownIt): bo ); const mediaType = guessMediaType(href); - const tag = mediaType == 'image' ? 'img' : mediaType; + const tag = mediaType === 'image' ? 'img' : mediaType; const token = state.push(mediaType, tag, 0); token.attrs = attrs = [['src', href]]; - if (mediaType == 'image') + if (mediaType === 'image') attrs.push(['alt', '']); token.children = tokens; @@ -248,9 +248,9 @@ function guessMediaType(url: string): string { const extension = extensionMatch[1]; if (extension) { - if (validAudioExtensions.indexOf(extension.toLowerCase()) != -1) + if (validAudioExtensions.indexOf(extension.toLowerCase()) !== -1) return 'audio'; - else if (validVideoExtensions.indexOf(extension.toLowerCase()) != -1) + else if (validVideoExtensions.indexOf(extension.toLowerCase()) !== -1) return 'video'; } @@ -258,7 +258,7 @@ function guessMediaType(url: string): string { } function makeIFrame(src: string, w = 560, h = 315) { - return `