linter fixes

This commit is contained in:
2026-07-28 14:50:24 +02:00
parent 1513a451ae
commit b1da8c9a84
24 changed files with 1731 additions and 56 deletions
+30
View File
@@ -0,0 +1,30 @@
import js from '@eslint/js'
import tseslint from 'typescript-eslint'
import pluginVue from 'eslint-plugin-vue'
export default [
js.configs.recommended,
...tseslint.configs.recommended,
...pluginVue.configs['flat/recommended'],
{
files: ['src/**/*.{ts,vue}'],
languageOptions: {
parserOptions: {
parser: tseslint.parser,
},
},
rules: {
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'warn',
'vue/multi-word-component-names': 'off',
'vue/html-self-closing': 'off',
'vue/max-attributes-per-line': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/html-indent': ['warn', 2],
},
},
{
ignores: ['dist/', 'node_modules/'],
},
]
+1579
View File
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -5,7 +5,9 @@
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
"preview": "vite preview",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix"
},
"dependencies": {
"pinia": "^2.2.0",
@@ -21,6 +23,10 @@
"tailwindcss": "^3.4.0",
"typescript": "^5.6.0",
"vite": "^5.4.0",
"vue-tsc": "^2.1.0"
"vue-tsc": "^2.1.0",
"eslint": "^9.0.0",
"@eslint/js": "^9.0.0",
"typescript-eslint": "^8.0.0",
"eslint-plugin-vue": "^9.28.0"
}
}
+7 -3
View File
@@ -9,10 +9,14 @@ import { onMounted } from 'vue'
import AppLayout from './layout/AppLayout.vue'
import { RouterView, useRouter } from 'vue-router'
declare global {
interface Window { _paq?: Array<unknown[]> }
}
const router = useRouter()
onMounted(() => {
const _paq = ((window as any)._paq = (window as any)._paq || [])
const _paq = (window._paq = window._paq || [])
_paq.push(['enableLinkTracking'])
const u = '//matomo.vps.teletype.hu/'
_paq.push(['setTrackerUrl', u + 'matomo.php'])
@@ -29,14 +33,14 @@ onMounted(() => {
})
router.beforeEach((_to, from) => {
const _paq = (window as any)._paq
const _paq = window._paq
if (_paq && from.fullPath) {
_paq.push(['setReferrerUrl', window.location.origin + from.fullPath])
}
})
router.afterEach((to) => {
const _paq = (window as any)._paq
const _paq = window._paq
if (!_paq) return
_paq.push(['setCustomUrl', window.location.origin + to.fullPath])
setTimeout(() => {
+5 -5
View File
@@ -14,14 +14,14 @@
<RouterLink to="/contact" class="p-2 hover:text-purple-300 transition-colors duration-200">{{ t('nav.contact') }}</RouterLink>
<div class="flex items-center gap-1 text-sm font-bold ml-2 border-l border-gray-600 pl-4">
<button @click="switchLocale('en')" :class="locale === 'en' ? 'text-white' : 'text-gray-400 hover:text-white'" class="transition-colors px-1">EN</button>
<button :class="locale === 'en' ? 'text-white' : 'text-gray-400 hover:text-white'" class="transition-colors px-1" @click="switchLocale('en')">EN</button>
<span class="text-gray-600">|</span>
<button @click="switchLocale('hu')" :class="locale === 'hu' ? 'text-white' : 'text-gray-400 hover:text-white'" class="transition-colors px-1">HU</button>
<button :class="locale === 'hu' ? 'text-white' : 'text-gray-400 hover:text-white'" class="transition-colors px-1" @click="switchLocale('hu')">HU</button>
</div>
</nav>
<!-- Hamburger Button (Mobile only) -->
<button @click="toggleMenu" class="md:hidden p-2 focus:outline-none focus:ring-2 focus:ring-purple-500 rounded-md">
<button class="md:hidden p-2 focus:outline-none focus:ring-2 focus:ring-purple-500 rounded-md" @click="toggleMenu">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
@@ -37,9 +37,9 @@
<RouterLink to="/team" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.team') }}</RouterLink>
<RouterLink to="/contact" class="block p-2 w-full text-center hover:bg-gray-700 transition-colors duration-200">{{ t('nav.contact') }}</RouterLink>
<div class="flex items-center gap-2 pt-2 border-t border-gray-700 w-full justify-center text-sm font-bold">
<button @click="switchLocale('en')" :class="locale === 'en' ? 'text-white' : 'text-gray-400'" class="transition-colors px-2 py-1">EN</button>
<button :class="locale === 'en' ? 'text-white' : 'text-gray-400'" class="transition-colors px-2 py-1" @click="switchLocale('en')">EN</button>
<span class="text-gray-600">|</span>
<button @click="switchLocale('hu')" :class="locale === 'hu' ? 'text-white' : 'text-gray-400'" class="transition-colors px-2 py-1">HU</button>
<button :class="locale === 'hu' ? 'text-white' : 'text-gray-400'" class="transition-colors px-2 py-1" @click="switchLocale('hu')">HU</button>
</div>
</nav>
</header>
@@ -70,7 +70,7 @@ import { RouterLink } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { useSoftwareStore } from '../../stores/software.store'
import { getDefaultImageUrl, getLatestStable } from '../../lib/softwareUtils'
import type { Software, SoftwareEntry } from '../../lib/interfaces/software.interface'
import type { SoftwareEntry } from '../../lib/interfaces/software.interface'
const { t } = useI18n()
@@ -23,7 +23,6 @@
<main v-if="software" class="main-container -mt-10">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Sidebar Info -->
<div class="lg:col-span-1 space-y-6">
<div class="bg-white rounded-3xl shadow-xl p-8 border border-gray-100">
@@ -258,8 +257,8 @@ onMounted(async () => {
} else {
error.value = t('catalogShow.notFound')
}
} catch (e: any) {
error.value = `${t('catalogShow.failedToLoad')} ${e.message}`
} catch (e) {
error.value = `${t('catalogShow.failedToLoad')} ${e instanceof Error ? e.message : String(e)}`
}
})
</script>
@@ -2,18 +2,22 @@
<Teleport to="body">
<div
v-if="isOpen"
ref="overlay"
class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm"
tabindex="0"
@click.self="close"
@keydown.escape="close"
@keydown.left="prev"
@keydown.right="next"
tabindex="0"
ref="overlay"
>
<button @click="close" class="absolute top-4 right-4 text-white/70 hover:text-white text-3xl font-bold z-10">&times;</button>
<button class="absolute top-4 right-4 text-white/70 hover:text-white text-3xl font-bold z-10" @click="close">&times;</button>
<button v-if="images.length > 1" @click="prev"
class="absolute left-4 text-white/70 hover:text-white text-5xl font-bold z-10 select-none">&lsaquo;</button>
<button
v-if="images.length > 1" class="absolute left-4 text-white/70 hover:text-white text-5xl font-bold z-10 select-none"
@click="prev"
>
&lsaquo;
</button>
<img
:src="images[currentIndex].url"
@@ -21,8 +25,12 @@
class="max-h-[85vh] max-w-[90vw] object-contain rounded-lg shadow-2xl"
/>
<button v-if="images.length > 1" @click="next"
class="absolute right-4 text-white/70 hover:text-white text-5xl font-bold z-10 select-none">&rsaquo;</button>
<button
v-if="images.length > 1" class="absolute right-4 text-white/70 hover:text-white text-5xl font-bold z-10 select-none"
@click="next"
>
&rsaquo;
</button>
<div v-if="images.length > 1" class="absolute bottom-6 text-white/60 text-sm font-mono">
{{ currentIndex + 1 }} / {{ images.length }}
@@ -5,7 +5,7 @@
<p class="hero-subtitle mb-10 text-blue-100">{{ t('contact.subtitle') }}</p>
<a :href="DISCORD_INVITE_LINK" target="_blank" class="discord-hero-btn">
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037 19.736 19.736 0 0 0-4.885 1.515.069.069 0 0 0-.032.027C.533 9.048-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.862-1.297 1.197-1.99.051-.105.001-.23-.106-.272a13.223 13.223 0 0 1-1.878-.894.077.077 0 0 1-.007-.128c.126-.094.252-.192.372-.29a.074.074 0 0 1 .077-.01c3.927 1.793 8.18 1.793 12.061 0a.074.074 0 0 1 .077.01c.12.098.246.196.373.29a.077.077 0 0 1-.006.128 12.299 12.299 0 0 1-1.878.894.077.077 0 0 0-.106.272c.335.693.735 1.36 1.197 1.99a.078.078 0 0 0 .084.028 19.83 19.83 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.182 0-2.156-1.085-2.156-2.419 0-1.333.956-2.419 2.156-2.419 1.21 0 2.176 1.096 2.156 2.419 0 1.334-.956 2.419-2.156 2.419zm7.974 0c-1.182 0-2.156-1.085-2.156-2.419 0-1.333.955-2.419 2.156-2.419 1.21 0 2.176 1.096 2.156 2.419 0 1.334-.946 2.419-2.156 2.419z"/>
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037 19.736 19.736 0 0 0-4.885 1.515.069.069 0 0 0-.032.027C.533 9.048-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.862-1.297 1.197-1.99.051-.105.001-.23-.106-.272a13.223 13.223 0 0 1-1.878-.894.077.077 0 0 1-.007-.128c.126-.094.252-.192.372-.29a.074.074 0 0 1 .077-.01c3.927 1.793 8.18 1.793 12.061 0a.074.074 0 0 1 .077.01c.12.098.246.196.373.29a.077.077 0 0 1-.006.128 12.299 12.299 0 0 1-1.878.894.077.077 0 0 0-.106.272c.335.693.735 1.36 1.197 1.99a.078.078 0 0 0 .084.028 19.83 19.83 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.182 0-2.156-1.085-2.156-2.419 0-1.333.956-2.419 2.156-2.419 1.21 0 2.176 1.096 2.156 2.419 0 1.334-.956 2.419-2.156 2.419zm7.974 0c-1.182 0-2.156-1.085-2.156-2.419 0-1.333.955-2.419 2.156-2.419 1.21 0 2.176 1.096 2.156 2.419 0 1.334-.946 2.419-2.156 2.419z" />
</svg>
{{ t('contact.joinDiscord') }}
</a>
@@ -19,7 +19,7 @@
<span class="text-3xl">📧</span> {{ t('contact.emailUs') }}
</h2>
<p class="contact-card-desc">{{ t('contact.emailDesc') }}</p>
<div @click="openEmail" class="email-link cursor-pointer">
<div class="email-link cursor-pointer" @click="openEmail">
contact@teletype.hu
</div>
</div>
@@ -103,7 +103,7 @@
<div class="spotify-card-header">
<div class="spotify-icon-wrap">
<svg class="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z"/>
<path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z" />
</svg>
</div>
<div>
+5 -5
View File
@@ -21,8 +21,8 @@ export const useBlogStore = defineStore('blog', () => {
try {
pages.value = await wikiApi.listBlogPages()
_loaded = true
} catch (e: any) {
error.value = `Failed to fetch wiki data: ${e.message}`
} catch (e) {
error.value = `Failed to fetch wiki data: ${e instanceof Error ? e.message : String(e)}`
} finally {
loading.value = false
}
@@ -39,8 +39,8 @@ export const useBlogStore = defineStore('blog', () => {
} else {
currentPageError.value = 'Post not found'
}
} catch (e: any) {
currentPageError.value = e.message
} catch (e) {
currentPageError.value = e instanceof Error ? e.message : String(e)
} finally {
currentPageLoading.value = false
}
@@ -53,7 +53,7 @@ export const useBlogStore = defineStore('blog', () => {
function getCleanPreview(content: string): string {
if (!content) return ''
return content.replace(/[#*`_\[\]()]/g, '').trim().slice(0, 300) + '...'
return content.replace(/[#*`_[\]()]/g, '').trim().slice(0, 300) + '...'
}
return { pages, loading, error, currentPage, currentPageLoading, currentPageError, fetchPages, fetchPage, isNew, getPermalink, getCleanPreview }
+2 -2
View File
@@ -55,8 +55,8 @@ export const useEventStore = defineStore('event', () => {
startCountdown(firstDate.toISOString())
}
_loaded = true
} catch (e: any) {
error.value = e.message
} catch (e) {
error.value = e instanceof Error ? e.message : String(e)
} finally {
loading.value = false
}
+2 -2
View File
@@ -25,8 +25,8 @@ export const useGitStore = defineStore('git', () => {
all.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
commits.value = all.slice(0, 20)
_loaded = true
} catch (e: any) {
error.value = e.message
} catch (e) {
error.value = e instanceof Error ? e.message : String(e)
} finally {
loading.value = false
}
+2 -2
View File
@@ -16,8 +16,8 @@ export const useHowtosStore = defineStore('howtos', () => {
try {
pages.value = await wikiApi.listHowtoPages()
_loaded = true
} catch (e: any) {
error.value = `Failed to fetch wiki data: ${e.message}`
} catch (e) {
error.value = `Failed to fetch wiki data: ${e instanceof Error ? e.message : String(e)}`
} finally {
loading.value = false
}
+2 -2
View File
@@ -16,8 +16,8 @@ export const useMemberStore = defineStore('member', () => {
try {
members.value = await memberApi.index()
_loaded = true
} catch (e: any) {
error.value = e.message
} catch (e) {
error.value = e instanceof Error ? e.message : String(e)
} finally {
loading.value = false
}
+4 -4
View File
@@ -23,8 +23,8 @@ export const useSoftwareStore = defineStore('software', () => {
try {
items.value = await softwareApi.index()
_loaded = true
} catch (e: any) {
error.value = e.message
} catch (e) {
error.value = e instanceof Error ? e.message : String(e)
} finally {
loading.value = false
}
@@ -33,8 +33,8 @@ export const useSoftwareStore = defineStore('software', () => {
async function fetchHighlighted() {
try {
highlighted.value = await softwareApi.highlighted()
} catch (e: any) {
error.value = e.message
} catch (e) {
error.value = e instanceof Error ? e.message : String(e)
}
}
+2 -2
View File
@@ -30,8 +30,8 @@ export const useYoutubeStore = defineStore('youtube', () => {
publishDate.value = formatDateTime(video.publishDate)
viewCount.value = video.viewCount ? formatViews(Number(video.viewCount)) : ''
state.value = 'loaded'
} catch (err: any) {
error.value = 'Error loading video: ' + err.message
} catch (err) {
error.value = 'Error loading video: ' + (err instanceof Error ? err.message : String(err))
state.value = 'error'
}
}