refactor: migrate to common eslint+prettier configs (#4168)

* refactor: migrate to common eslint+prettier configs

* fix: prettier frontend

* feat: config changes

* fix: lint issues

* fix: lint

* fix: type imports

* fix: cyclical import issue

* fix: lockfile

* fix: missing dep

* fix: switch to tabs

* fix: continue switch to tabs

* fix: rustfmt parity

* fix: moderation lint issue

* fix: lint issues

* fix: ui intl

* fix: lint issues

* Revert "fix: rustfmt parity"

This reverts commit cb99d2376c321d813d4b7fc7e2a213bb30a54711.

* feat: revert last rs
This commit is contained in:
Cal H.
2025-08-14 21:48:38 +01:00
committed by GitHub
parent 82697278dc
commit 2aabcf36ee
702 changed files with 101360 additions and 102020 deletions

View File

@@ -1,39 +1,39 @@
<script setup lang="ts">
import { useVIntl, defineMessages } from '@vintl/vintl'
import type { VersionChannel } from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
const { formatMessage } = useVIntl()
withDefaults(
defineProps<{
channel: VersionChannel
large?: boolean
}>(),
{
large: false,
},
defineProps<{
channel: VersionChannel
large?: boolean
}>(),
{
large: false,
},
)
const messages = defineMessages({
releaseSymbol: {
id: 'project.versions.channel.release.symbol',
defaultMessage: 'R',
},
betaSymbol: {
id: 'project.versions.channel.beta.symbol',
defaultMessage: 'B',
},
alphaSymbol: {
id: 'project.versions.channel.alpha.symbol',
defaultMessage: 'A',
},
releaseSymbol: {
id: 'project.versions.channel.release.symbol',
defaultMessage: 'R',
},
betaSymbol: {
id: 'project.versions.channel.beta.symbol',
defaultMessage: 'B',
},
alphaSymbol: {
id: 'project.versions.channel.alpha.symbol',
defaultMessage: 'A',
},
})
</script>
<template>
<div
:class="`flex ${large ? 'text-lg w-[2.625rem] h-[2.625rem]' : 'text-sm w-9 h-9'} font-bold justify-center items-center rounded-full ${channel === 'release' ? 'bg-bg-green text-brand-green' : channel === 'beta' ? 'bg-bg-orange text-brand-orange' : 'bg-bg-red text-brand-red'}`"
>
{{ channel ? formatMessage(messages[`${channel}Symbol`]) : '?' }}
</div>
<div
:class="`flex ${large ? 'text-lg w-[2.625rem] h-[2.625rem]' : 'text-sm w-9 h-9'} font-bold justify-center items-center rounded-full ${channel === 'release' ? 'bg-bg-green text-brand-green' : channel === 'beta' ? 'bg-bg-orange text-brand-orange' : 'bg-bg-red text-brand-red'}`"
>
{{ channel ? formatMessage(messages[`${channel}Symbol`]) : '?' }}
</div>
</template>

View File

@@ -1,95 +1,96 @@
<template>
<div class="experimental-styles-within flex flex-col gap-3">
<div class="flex flex-wrap items-center gap-2">
<ManySelect
v-model="selectedPlatforms"
:options="filterOptions.platform"
:dropdown-id="`${baseId}-platform`"
@change="updateFilters"
>
<FilterIcon class="h-5 w-5 text-secondary" />
Platform
<template #option="{ option }">
{{ formatCategory(option) }}
</template>
</ManySelect>
<ManySelect
v-model="selectedGameVersions"
:options="filterOptions.gameVersion"
:dropdown-id="`${baseId}-game-version`"
search
@change="updateFilters"
>
<FilterIcon class="h-5 w-5 text-secondary" />
Game versions
<template #footer>
<Checkbox v-model="showSnapshots" class="mx-1" :label="`Show all versions`" />
</template>
</ManySelect>
<ManySelect
v-model="selectedChannels"
:options="filterOptions.channel"
:dropdown-id="`${baseId}-channel`"
@change="updateFilters"
>
<FilterIcon class="h-5 w-5 text-secondary" />
Channels
<template #option="{ option }">
{{ option === 'release' ? 'Release' : option === 'beta' ? 'Beta' : 'Alpha' }}
</template>
</ManySelect>
</div>
<div class="flex flex-wrap items-center gap-1 empty:hidden">
<TagItem
v-if="selectedChannels.length + selectedGameVersions.length + selectedPlatforms.length > 1"
class="transition-transform active:scale-[0.95]"
:action="clearFilters"
>
<XCircleIcon />
Clear all filters
</TagItem>
<TagItem
v-for="channel in selectedChannels"
:key="`remove-filter-${channel}`"
:style="`--_color: var(--color-${channel === 'alpha' ? 'red' : channel === 'beta' ? 'orange' : 'green'});--_bg-color: var(--color-${channel === 'alpha' ? 'red' : channel === 'beta' ? 'orange' : 'green'}-highlight)`"
:action="() => toggleFilter('channel', channel)"
>
<XIcon />
{{ channel.slice(0, 1).toUpperCase() + channel.slice(1) }}
</TagItem>
<TagItem
v-for="version in selectedGameVersions"
:key="`remove-filter-${version}`"
:action="() => toggleFilter('gameVersion', version)"
>
<XIcon />
{{ version }}
</TagItem>
<TagItem
v-for="platform in selectedPlatforms"
:key="`remove-filter-${platform}`"
:style="`--_color: var(--color-platform-${platform})`"
:action="() => toggleFilter('platform', platform)"
>
<XIcon />
{{ formatCategory(platform) }}
</TagItem>
</div>
</div>
<div class="experimental-styles-within flex flex-col gap-3">
<div class="flex flex-wrap items-center gap-2">
<ManySelect
v-model="selectedPlatforms"
:options="filterOptions.platform"
:dropdown-id="`${baseId}-platform`"
@change="updateFilters"
>
<FilterIcon class="h-5 w-5 text-secondary" />
Platform
<template #option="{ option }">
{{ formatCategory(option) }}
</template>
</ManySelect>
<ManySelect
v-model="selectedGameVersions"
:options="filterOptions.gameVersion"
:dropdown-id="`${baseId}-game-version`"
search
@change="updateFilters"
>
<FilterIcon class="h-5 w-5 text-secondary" />
Game versions
<template #footer>
<Checkbox v-model="showSnapshots" class="mx-1" :label="`Show all versions`" />
</template>
</ManySelect>
<ManySelect
v-model="selectedChannels"
:options="filterOptions.channel"
:dropdown-id="`${baseId}-channel`"
@change="updateFilters"
>
<FilterIcon class="h-5 w-5 text-secondary" />
Channels
<template #option="{ option }">
{{ option === 'release' ? 'Release' : option === 'beta' ? 'Beta' : 'Alpha' }}
</template>
</ManySelect>
</div>
<div class="flex flex-wrap items-center gap-1 empty:hidden">
<TagItem
v-if="selectedChannels.length + selectedGameVersions.length + selectedPlatforms.length > 1"
class="transition-transform active:scale-[0.95]"
:action="clearFilters"
>
<XCircleIcon />
Clear all filters
</TagItem>
<TagItem
v-for="channel in selectedChannels"
:key="`remove-filter-${channel}`"
:style="`--_color: var(--color-${channel === 'alpha' ? 'red' : channel === 'beta' ? 'orange' : 'green'});--_bg-color: var(--color-${channel === 'alpha' ? 'red' : channel === 'beta' ? 'orange' : 'green'}-highlight)`"
:action="() => toggleFilter('channel', channel)"
>
<XIcon />
{{ channel.slice(0, 1).toUpperCase() + channel.slice(1) }}
</TagItem>
<TagItem
v-for="version in selectedGameVersions"
:key="`remove-filter-${version}`"
:action="() => toggleFilter('gameVersion', version)"
>
<XIcon />
{{ version }}
</TagItem>
<TagItem
v-for="platform in selectedPlatforms"
:key="`remove-filter-${platform}`"
:style="`--_color: var(--color-platform-${platform})`"
:action="() => toggleFilter('platform', platform)"
>
<XIcon />
{{ formatCategory(platform) }}
</TagItem>
</div>
</div>
</template>
<script setup lang="ts">
import { FilterIcon, XCircleIcon, XIcon } from '@modrinth/assets'
import { ManySelect, Checkbox } from '../index'
import { type Version, formatCategory, type GameVersionTag } from '@modrinth/utils'
import { ref, computed } from 'vue'
import { formatCategory, type GameVersionTag, type Version } from '@modrinth/utils'
import { computed, ref } from 'vue'
import { useRoute } from 'vue-router'
import TagItem from '../base/TagItem.vue'
import { Checkbox, ManySelect } from '../index'
const props = defineProps<{
versions: Version[]
gameVersions: GameVersionTag[]
baseId?: string
versions: Version[]
gameVersions: GameVersionTag[]
baseId?: string
}>()
const emit = defineEmits(['update:query'])
@@ -104,42 +105,42 @@ type FilterType = 'channel' | 'gameVersion' | 'platform'
type Filter = string
const filterOptions = computed(() => {
const filters: Record<FilterType, Filter[]> = {
channel: [],
gameVersion: [],
platform: [],
}
const filters: Record<FilterType, Filter[]> = {
channel: [],
gameVersion: [],
platform: [],
}
const platformSet = new Set()
const gameVersionSet = new Set()
const channelSet = new Set()
const platformSet = new Set()
const gameVersionSet = new Set()
const channelSet = new Set()
for (const version of props.versions) {
for (const loader of version.loaders) {
platformSet.add(loader)
}
for (const gameVersion of version.game_versions) {
gameVersionSet.add(gameVersion)
}
channelSet.add(version.version_type)
}
for (const version of props.versions) {
for (const loader of version.loaders) {
platformSet.add(loader)
}
for (const gameVersion of version.game_versions) {
gameVersionSet.add(gameVersion)
}
channelSet.add(version.version_type)
}
if (channelSet.size > 0) {
filters.channel = Array.from(channelSet) as Filter[]
filters.channel.sort((a, b) => allChannels.value.indexOf(a) - allChannels.value.indexOf(b))
}
if (gameVersionSet.size > 0) {
const gameVersions = props.gameVersions.filter((x) => gameVersionSet.has(x.version))
if (channelSet.size > 0) {
filters.channel = Array.from(channelSet) as Filter[]
filters.channel.sort((a, b) => allChannels.value.indexOf(a) - allChannels.value.indexOf(b))
}
if (gameVersionSet.size > 0) {
const gameVersions = props.gameVersions.filter((x) => gameVersionSet.has(x.version))
filters.gameVersion = gameVersions
.filter((x) => (showSnapshots.value ? true : x.version_type === 'release'))
.map((x) => x.version)
}
if (platformSet.size > 0) {
filters.platform = Array.from(platformSet) as Filter[]
}
filters.gameVersion = gameVersions
.filter((x) => (showSnapshots.value ? true : x.version_type === 'release'))
.map((x) => x.version)
}
if (platformSet.size > 0) {
filters.platform = Array.from(platformSet) as Filter[]
}
return filters
return filters
})
const selectedChannels = ref<string[]>([])
@@ -151,62 +152,62 @@ selectedGameVersions.value = route.query.g ? getArrayOrString(route.query.g) : [
selectedPlatforms.value = route.query.l ? getArrayOrString(route.query.l) : []
async function toggleFilters(type: FilterType, filters: Filter[]) {
for (const filter of filters) {
await toggleFilter(type, filter, true)
}
for (const filter of filters) {
await toggleFilter(type, filter, true)
}
updateFilters()
updateFilters()
}
async function toggleFilter(type: FilterType, filter: Filter, bulk = false) {
if (type === 'channel') {
selectedChannels.value = selectedChannels.value.includes(filter)
? selectedChannels.value.filter((x) => x !== filter)
: [...selectedChannels.value, filter]
} else if (type === 'gameVersion') {
selectedGameVersions.value = selectedGameVersions.value.includes(filter)
? selectedGameVersions.value.filter((x) => x !== filter)
: [...selectedGameVersions.value, filter]
} else if (type === 'platform') {
selectedPlatforms.value = selectedPlatforms.value.includes(filter)
? selectedPlatforms.value.filter((x) => x !== filter)
: [...selectedPlatforms.value, filter]
}
if (!bulk) {
updateFilters()
}
if (type === 'channel') {
selectedChannels.value = selectedChannels.value.includes(filter)
? selectedChannels.value.filter((x) => x !== filter)
: [...selectedChannels.value, filter]
} else if (type === 'gameVersion') {
selectedGameVersions.value = selectedGameVersions.value.includes(filter)
? selectedGameVersions.value.filter((x) => x !== filter)
: [...selectedGameVersions.value, filter]
} else if (type === 'platform') {
selectedPlatforms.value = selectedPlatforms.value.includes(filter)
? selectedPlatforms.value.filter((x) => x !== filter)
: [...selectedPlatforms.value, filter]
}
if (!bulk) {
updateFilters()
}
}
async function clearFilters() {
selectedChannels.value = []
selectedGameVersions.value = []
selectedPlatforms.value = []
selectedChannels.value = []
selectedGameVersions.value = []
selectedPlatforms.value = []
updateFilters()
updateFilters()
}
function updateFilters() {
emit('update:query', {
c: selectedChannels.value,
g: selectedGameVersions.value,
l: selectedPlatforms.value,
page: undefined,
})
emit('update:query', {
c: selectedChannels.value,
g: selectedGameVersions.value,
l: selectedPlatforms.value,
page: undefined,
})
}
defineExpose({
toggleFilter,
toggleFilters,
selectedChannels,
selectedGameVersions,
selectedPlatforms,
toggleFilter,
toggleFilters,
selectedChannels,
selectedGameVersions,
selectedPlatforms,
})
function getArrayOrString(x: string | string[]): string[] {
if (typeof x === 'string') {
return [x]
} else {
return x
}
if (typeof x === 'string') {
return [x]
} else {
return x
}
}
</script>

View File

@@ -1,46 +1,47 @@
<template>
<div
class="grid grid-cols-[min-content_auto_min-content_min-content] items-center gap-2 rounded-2xl border-[1px] border-divider bg-bg p-2"
>
<VersionChannelIndicator :channel="version.version_type" />
<div class="flex min-w-0 flex-col gap-1">
<h1 class="my-0 truncate text-nowrap text-base font-extrabold leading-none text-contrast">
{{ version.version_number }}
</h1>
<p class="m-0 truncate text-nowrap text-xs font-semibold text-secondary">
{{ version.name }}
</p>
</div>
<ButtonStyled color="brand">
<a :href="downloadUrl" class="min-w-0" @click="emit('onDownload')">
<DownloadIcon aria-hidden="true" /> Download
</a>
</ButtonStyled>
<ButtonStyled circular>
<nuxt-link
:to="`/project/${props.version.project_id}/version/${props.version.id}`"
class="min-w-0"
aria-label="Open project page"
@click="emit('onNavigate')"
>
<ExternalIcon aria-hidden="true" />
</nuxt-link>
</ButtonStyled>
</div>
<div
class="grid grid-cols-[min-content_auto_min-content_min-content] items-center gap-2 rounded-2xl border-[1px] border-divider bg-bg p-2"
>
<VersionChannelIndicator :channel="version.version_type" />
<div class="flex min-w-0 flex-col gap-1">
<h1 class="my-0 truncate text-nowrap text-base font-extrabold leading-none text-contrast">
{{ version.version_number }}
</h1>
<p class="m-0 truncate text-nowrap text-xs font-semibold text-secondary">
{{ version.name }}
</p>
</div>
<ButtonStyled color="brand">
<a :href="downloadUrl" class="min-w-0" @click="emit('onDownload')">
<DownloadIcon aria-hidden="true" /> Download
</a>
</ButtonStyled>
<ButtonStyled circular>
<nuxt-link
:to="`/project/${props.version.project_id}/version/${props.version.id}`"
class="min-w-0"
aria-label="Open project page"
@click="emit('onNavigate')"
>
<ExternalIcon aria-hidden="true" />
</nuxt-link>
</ButtonStyled>
</div>
</template>
<script setup lang="ts">
import { ButtonStyled, VersionChannelIndicator } from '../index'
import { DownloadIcon, ExternalIcon } from '@modrinth/assets'
import { computed } from 'vue'
import { ButtonStyled, VersionChannelIndicator } from '../index'
const props = defineProps<{
version: Version
version: Version
}>()
const downloadUrl = computed(() => {
const primary: VersionFile = props.version.files.find((x) => x.primary) || props.version.files[0]
return primary.url
const primary: VersionFile = props.version.files.find((x) => x.primary) || props.version.files[0]
return primary.url
})
const emit = defineEmits(['onDownload', 'onNavigate'])