Change linter config to antfu config and lint code

This commit is contained in:
2024-07-24 02:01:30 +02:00
parent 45293e4982
commit 2331b01a8d
53 changed files with 1999 additions and 1556 deletions

View File

@@ -71,4 +71,4 @@ NUXT_PUBLIC_I18N_BASE_URL=...
## 📄 License ## 📄 License
[MIT](./LICENSE) © Arthur Danjou [MIT](./LICENSE) © Arthur Danjou

View File

@@ -3,10 +3,10 @@ export default defineAppConfig({
gray: 'neutral', gray: 'neutral',
primary: 'gray', primary: 'gray',
container: { container: {
constrained: 'max-w-3xl' constrained: 'max-w-3xl',
}, },
icons: { icons: {
dynamic: true dynamic: true,
} },
} },
}) })

View File

@@ -1,3 +1,15 @@
<script lang="ts" setup>
useHead({
link: [{ rel: 'icon', type: 'image/png', href: '/favicon.png' }],
})
const head = useLocaleHead({
addDirAttribute: true,
identifierAttribute: 'id',
addSeoAttributes: true,
})
</script>
<template> <template>
<Html <Html
:dir="head.htmlAttrs.dir" :dir="head.htmlAttrs.dir"
@@ -40,18 +52,6 @@
</Html> </Html>
</template> </template>
<script lang="ts" setup>
useHead({
link: [{ rel: 'icon', type: 'image/png', href: '/favicon.png' }]
})
const head = useLocaleHead({
addDirAttribute: true,
identifierAttribute: 'id',
addSeoAttributes: true
})
</script>
<style> <style>
body { body {
font-family: 'DM Sans', sans-serif; font-family: 'DM Sans', sans-serif;

View File

@@ -3,26 +3,27 @@ const socials = [
{ {
icon: 'i-ph-x-logo-duotone', icon: 'i-ph-x-logo-duotone',
label: 'Twitter', label: 'Twitter',
link: 'https://twitter.com/ArthurDanj' link: 'https://twitter.com/ArthurDanj',
}, },
{ {
icon: 'i-ph-github-logo-duotone', icon: 'i-ph-github-logo-duotone',
label: 'GitHub', label: 'GitHub',
link: 'https://github.com/ArthurDanjou' link: 'https://github.com/ArthurDanjou',
}, },
{ {
icon: 'i-ph-linkedin-logo-duotone', icon: 'i-ph-linkedin-logo-duotone',
label: 'LinkedIn', label: 'LinkedIn',
link: 'https://www.linkedin.com/in/arthurdanjou/' link: 'https://www.linkedin.com/in/arthurdanjou/',
}, { },
{
icon: 'i-ph-discord-logo-duotone', icon: 'i-ph-discord-logo-duotone',
label: 'Discord', label: 'Discord',
link: 'https://discordapp.com/users/179635349100691456' link: 'https://discordapp.com/users/179635349100691456',
} },
] ]
const { t } = useI18n({ const { t } = useI18n({
useScope: 'local' useScope: 'local',
}) })
</script> </script>
@@ -63,7 +64,7 @@ const { t } = useI18n({
<div class="mt-8 w-full flex justify-center text-xs"> <div class="mt-8 w-full flex justify-center text-xs">
{{ {{
t('copyright', { t('copyright', {
date: new Date().getFullYear() date: new Date().getFullYear(),
}) })
}} }}
</div> </div>

View File

@@ -10,52 +10,52 @@ const navs = [
{ {
label: { label: {
en: 'home', en: 'home',
fr: 'accueil' fr: 'accueil',
}, },
to: '/', to: '/',
icon: 'i-ph-house-line-duotone', icon: 'i-ph-house-line-duotone',
shortcut: { shortcut: {
en: 'h', en: 'h',
fr: 'a' fr: 'a',
} },
}, },
{ {
label: { label: {
en: 'uses', en: 'uses',
fr: 'usages' fr: 'usages',
}, },
to: '/uses', to: '/uses',
icon: 'i-ph-backpack-duotone', icon: 'i-ph-backpack-duotone',
shortcut: { shortcut: {
en: 'u', en: 'u',
fr: 'u' fr: 'u',
} },
}, },
{ {
label: { label: {
en: 'writings', en: 'writings',
fr: 'écrits' fr: 'écrits',
}, },
to: '/writings', to: '/writings',
icon: 'i-ph-books-duotone', icon: 'i-ph-books-duotone',
shortcut: { shortcut: {
en: 'w', en: 'w',
fr: 'e' fr: 'e',
} },
}, },
{ {
label: { label: {
en: 'resume', en: 'resume',
fr: 'cv' fr: 'cv',
}, },
to: config.public.cloud.resume, to: config.public.cloud.resume,
target: '_blank', target: '_blank',
icon: 'i-ph-address-book-duotone', icon: 'i-ph-address-book-duotone',
shortcut: { shortcut: {
en: 'r', en: 'r',
fr: 'c' fr: 'c',
} },
} },
] ]
async function toggleTheme() { async function toggleTheme() {
@@ -69,6 +69,9 @@ async function toggleTheme() {
document.body.style.animation = '' document.body.style.animation = ''
} }
const { locale, setLocale, locales, t } = useI18n()
const currentLocale = computed(() => locales.value.filter(l => l.code === locale.value)[0])
async function changeLocale() { async function changeLocale() {
document.body.style.animation = 'switch-on .2s' document.body.style.animation = 'switch-on .2s'
await new Promise(resolve => setTimeout(resolve, 200)) await new Promise(resolve => setTimeout(resolve, 200))
@@ -81,8 +84,6 @@ async function changeLocale() {
} }
const router = useRouter() const router = useRouter()
const { locale, setLocale, locales, t } = useI18n()
const currentLocale = computed(() => locales.value.filter(l => l.code === locale.value)[0])
defineShortcuts({ defineShortcuts({
h: () => router.push('/'), h: () => router.push('/'),
a: () => router.push('/'), a: () => router.push('/'),
@@ -93,7 +94,7 @@ defineShortcuts({
c: () => window.open(config.public.cloud.resume, '_blank'), c: () => window.open(config.public.cloud.resume, '_blank'),
t: () => toggleTheme(), t: () => toggleTheme(),
l: () => changeLocale(), l: () => changeLocale(),
backspace: () => router.back() backspace: () => router.back(),
}) })
</script> </script>

View File

@@ -2,12 +2,12 @@
defineProps({ defineProps({
title: { title: {
type: String, type: String,
required: true required: true,
}, },
description: { description: {
type: String, type: String,
required: true required: true,
} },
}) })
</script> </script>

View File

@@ -9,7 +9,8 @@ const { locale, locales } = useI18n()
const currentLocale = computed(() => locales.value.find(l => l.code === locale.value)) const currentLocale = computed(() => locales.value.find(l => l.code === locale.value))
const getActivity = computed(() => { const getActivity = computed(() => {
if (!codingActivity.value) return if (!codingActivity.value)
return
const { name, details, state, timestamps } = codingActivity.value const { name, details, state, timestamps } = codingActivity.value
const isActive = name === 'Visual Studio Code' const isActive = name === 'Visual Studio Code'
@@ -44,14 +45,14 @@ const getActivity = computed(() => {
.trim(), .trim(),
formated: { formated: {
date: formatDate(timestamps.start, 'DD MMM YYYY'), date: formatDate(timestamps.start, 'DD MMM YYYY'),
time: formatDate(timestamps.start, 'HH:mm:ss') time: formatDate(timestamps.start, 'HH:mm:ss'),
} },
} },
} }
}) })
const { t } = useI18n({ const { t } = useI18n({
useScope: 'local' useScope: 'local',
}) })
</script> </script>

View File

@@ -1,3 +1,10 @@
<script lang="ts" setup>
const { width } = useWindowSize()
const { t } = useI18n({
useScope: 'local',
})
</script>
<template> <template>
<ClientOnly> <ClientOnly>
<div <div
@@ -13,13 +20,6 @@
</ClientOnly> </ClientOnly>
</template> </template>
<script lang="ts" setup>
const { width } = useWindowSize()
const { t } = useI18n({
useScope: 'local'
})
</script>
<i18n lang="json"> <i18n lang="json">
{ {
"en": { "en": {

View File

@@ -4,15 +4,15 @@ import type { PropType } from 'vue'
defineProps({ defineProps({
text: { text: {
type: [String, Number], type: [String, Number],
required: true required: true,
}, },
hover: { hover: {
type: String, type: String,
required: true required: true,
}, },
position: { position: {
type: String as PropType<'top' | 'right' | 'bottom' | 'left'> type: String as PropType<'top' | 'right' | 'bottom' | 'left'>,
} },
}) })
</script> </script>

View File

@@ -4,13 +4,13 @@ import type { PropType } from 'vue'
defineProps({ defineProps({
href: { href: {
type: String, type: String,
default: '' default: '',
}, },
target: { target: {
type: String as PropType<'_blank' | '_parent' | '_self' | '_top' | (string & object) | null | undefined>, type: String as PropType<'_blank' | '_parent' | '_self' | '_top' | (string & object) | null | undefined>,
default: undefined, default: undefined,
required: false required: false,
} },
}) })
</script> </script>

View File

@@ -1,3 +1,12 @@
<script lang="ts" setup>
import { computed, useRuntimeConfig } from '#imports'
const props = defineProps<{ id?: string }>()
const { headings } = useRuntimeConfig().public.mdc
const generate = computed(() => props.id && ((typeof headings?.anchorLinks === 'boolean' && headings?.anchorLinks) || (typeof headings?.anchorLinks === 'object' && headings?.anchorLinks?.h2)))
</script>
<template> <template>
<h2 <h2
:id="id" :id="id"
@@ -12,12 +21,3 @@
<slot v-else /> <slot v-else />
</h2> </h2>
</template> </template>
<script lang="ts" setup>
import { computed, useRuntimeConfig } from '#imports'
const props = defineProps<{ id?: string }>()
const { headings } = useRuntimeConfig().public.mdc
const generate = computed(() => props.id && ((typeof headings?.anchorLinks === 'boolean' && headings?.anchorLinks) || (typeof headings?.anchorLinks === 'object' && headings?.anchorLinks?.h2)))
</script>

View File

@@ -1,3 +1,12 @@
<script lang="ts" setup>
import { computed, useRuntimeConfig } from '#imports'
const props = defineProps<{ id?: string }>()
const { headings } = useRuntimeConfig().public.mdc
const generate = computed(() => props.id && ((typeof headings?.anchorLinks === 'boolean' && headings?.anchorLinks) || (typeof headings?.anchorLinks === 'object' && headings?.anchorLinks?.h2)))
</script>
<template> <template>
<h2 <h2
:id="id" :id="id"
@@ -12,12 +21,3 @@
<slot v-else /> <slot v-else />
</h2> </h2>
</template> </template>
<script lang="ts" setup>
import { computed, useRuntimeConfig } from '#imports'
const props = defineProps<{ id?: string }>()
const { headings } = useRuntimeConfig().public.mdc
const generate = computed(() => props.id && ((typeof headings?.anchorLinks === 'boolean' && headings?.anchorLinks) || (typeof headings?.anchorLinks === 'object' && headings?.anchorLinks?.h2)))
</script>

View File

@@ -2,8 +2,8 @@
defineProps({ defineProps({
icon: { icon: {
type: String, type: String,
required: true required: true,
} },
}) })
</script> </script>

View File

@@ -1,3 +1,9 @@
<script lang="ts" setup>
const { t } = useI18n({
useScope: 'local',
})
</script>
<template> <template>
<div class="flex items-center gap-2 mt-4"> <div class="flex items-center gap-2 mt-4">
<div class="flex items-center"> <div class="flex items-center">
@@ -17,12 +23,6 @@
</div> </div>
</template> </template>
<script lang="ts" setup>
const { t } = useI18n({
useScope: 'local'
})
</script>
<i18n lang="json"> <i18n lang="json">
{ {
"en": { "en": {

View File

@@ -3,7 +3,7 @@ import type { Stats } from '~~/types'
const { data: stats } = await useFetch<Stats>('/api/stats') const { data: stats } = await useFetch<Stats>('/api/stats')
const { t } = useI18n({ const { t } = useI18n({
useScope: 'local' useScope: 'local',
}) })
</script> </script>

View File

@@ -2,19 +2,19 @@
defineProps({ defineProps({
label: { label: {
type: String, type: String,
required: true required: true,
}, },
href: { href: {
type: String, type: String,
required: true required: true,
}, },
icon: { icon: {
type: String type: String,
}, },
blanked: { blanked: {
type: Boolean, type: Boolean,
default: false default: false,
} },
}) })
</script> </script>

View File

@@ -5,8 +5,8 @@ import type { UsesItem } from '#components'
defineProps({ defineProps({
item: { item: {
type: Object as PropType<typeof UsesItem>, type: Object as PropType<typeof UsesItem>,
required: true required: true,
} },
}) })
const { locale } = useI18n() const { locale } = useI18n()

View File

@@ -1,3 +1,12 @@
<script lang="ts" setup>
defineProps({
title: {
type: String,
required: true,
},
})
</script>
<template> <template>
<div class="space-y-8"> <div class="space-y-8">
<UDivider <UDivider
@@ -9,12 +18,3 @@
</ul> </ul>
</div> </div>
</template> </template>
<script lang="ts" setup>
defineProps({
title: {
type: String,
required: true
}
})
</script>

View File

@@ -1,9 +1,9 @@
<script lang="ts" setup>
const { locale } = useI18n()
</script>
<template> <template>
<main class="!max-w-none prose dark:prose-invert"> <main class="!max-w-none prose dark:prose-invert">
<ContentDoc :path="`/home/${locale}`" /> <ContentDoc :path="`/home/${locale}`" />
</main> </main>
</template> </template>
<script lang="ts" setup>
const { locale } = useI18n()
</script>

View File

@@ -1,14 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
const { t } = useI18n({ const { t } = useI18n({
useScope: 'local' useScope: 'local',
}) })
useSeoMeta({ useSeoMeta({
title: 'Things I use', title: 'Things I use',
description: t('description') description: t('description'),
}) })
const { data: items } = await useAsyncData('uses', () => queryContent('/uses').find() const { data: items } = await useAsyncData('uses', () => queryContent('/uses').find(),
) )
const hardware = items.value!.filter(item => item.category === 'hardware') const hardware = items.value!.filter(item => item.category === 'hardware')

View File

@@ -3,33 +3,33 @@ const route = useRoute()
const { data: post } = await useAsyncData(`writing:${route.params.slug}`, () => queryContent(`/writings/${route.params.slug}`).findOne()) const { data: post } = await useAsyncData(`writing:${route.params.slug}`, () => queryContent(`/writings/${route.params.slug}`).findOne())
const { const {
data: postDB, data: postDB,
refresh refresh,
} = await useAsyncData(`writing:${route.params.slug}:db`, () => $fetch(`/api/posts/${route.params.slug}`, { method: 'POST' })) } = await useAsyncData(`writing:${route.params.slug}:db`, () => $fetch(`/api/posts/${route.params.slug}`, { method: 'POST' }))
const { locale, locales } = useI18n() const { locale, locales } = useI18n()
const currentLocale = computed(() => locales.value.filter(l => l.code === locale.value)[0]) const currentLocale = computed(() => locales.value.filter(l => l.code === locale.value)[0])
const { t } = useI18n({ const { t } = useI18n({
useScope: 'local' useScope: 'local',
}) })
function top() { function top() {
window.scrollTo({ window.scrollTo({
top: 0, top: 0,
left: 0, left: 0,
behavior: 'smooth' behavior: 'smooth',
}) })
} }
const { copy, copied } = useClipboard({ const { copy, copied } = useClipboard({
source: `https://arthurdanjou.fr/writings/${route.params.slug}`, source: `https://arthurdanjou.fr/writings/${route.params.slug}`,
copiedDuring: 4000 copiedDuring: 4000,
}) })
useSeoMeta({ useSeoMeta({
title: post.value?.title, title: post.value?.title,
description: post.value?.description, description: post.value?.description,
author: 'Arthur Danjou' author: 'Arthur Danjou',
}) })
function getDetails() { function getDetails() {
@@ -43,11 +43,12 @@ function getDetails() {
} }
const likeCookie = useCookie<boolean>(`post:like:${route.params.slug}`, { const likeCookie = useCookie<boolean>(`post:like:${route.params.slug}`, {
maxAge: 7200 maxAge: 7200,
}) })
async function handleLike() { async function handleLike() {
if (likeCookie.value) return if (likeCookie.value)
return
await $fetch(`/api/posts/like/${route.params.slug}`, { method: 'PUT' }) await $fetch(`/api/posts/like/${route.params.slug}`, { method: 'PUT' })
await refresh() await refresh()
likeCookie.value = true likeCookie.value = true
@@ -133,7 +134,7 @@ async function handleLike() {
<div class="flex gap-4 items-center flex-wrap"> <div class="flex gap-4 items-center flex-wrap">
<UButton <UButton
:label="postDB?.likes > 1 ? `${postDB?.likes} likes` : `${postDB?.likes} like`" :label="postDB?.likes > 1 ? `${postDB?.likes} likes` : `${postDB?.likes} like`"
:color="likeCookie ? 'red': 'white'" :color="likeCookie ? 'red' : 'white'"
icon="i-ph-heart-duotone" icon="i-ph-heart-duotone"
size="lg" size="lg"
variant="solid" variant="solid"

View File

@@ -1,23 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
const { t, locale } = useI18n({ const { t, locale } = useI18n({
useScope: 'local' useScope: 'local',
}) })
useSeoMeta({ useSeoMeta({
title: 'My Shelf', title: 'My Shelf',
description: t('description') description: t('description'),
}) })
const { data: writings } = await useAsyncData('all-writings', () => const { data: writings } = await useAsyncData('all-writings', () =>
queryContent('/writings').sort({ published: -1 }).without('body').find() queryContent('/writings').sort({ published: -1 }).without('body').find())
)
const { data: writingsDB } = await useAsyncData('all-writings-db', () => const { data: writingsDB } = await useAsyncData('all-writings-db', () =>
$fetch(`/api/posts`) $fetch(`/api/posts`))
)
function getDetails(slug: string) { function getDetails(slug: string) {
const writing = writingsDB.value!.find(writing => writing.slug === slug) const writing = writingsDB.value!.find(writing => writing.slug === slug)
if (!writing) return '' if (!writing)
return ''
const like = writing.likes! > 1 ? t('likes.many') : t('likes.one') const like = writing.likes! > 1 ? t('likes.many') : t('likes.one')
const view = writing.views! > 1 ? t('views.many') : t('views.one') const view = writing.views! > 1 ? t('views.many') : t('views.one')

View File

@@ -5,4 +5,4 @@
"fr": "Probablement l'objet que j'utilise le plus après mon téléphone et mon ordinateur portable. Je les utilise pour tout, de l'écoute de musique à la prise d'appels. Ils sont super pratiques et la qualité sonore est excellente." "fr": "Probablement l'objet que j'utilise le plus après mon téléphone et mon ordinateur portable. Je les utilise pour tout, de l'écoute de musique à la prise d'appels. Ils sont super pratiques et la qualité sonore est excellente."
}, },
"category": "hardware" "category": "hardware"
} }

View File

@@ -5,4 +5,4 @@
"fr": "J'utilise mon iPad pour lire des livres, regarder des films et naviguer sur le web, mais aussi pour prendre des notes et écrire des équations pendant mes cours de mathématiques." "fr": "J'utilise mon iPad pour lire des livres, regarder des films et naviguer sur le web, mais aussi pour prendre des notes et écrire des équations pendant mes cours de mathématiques."
}, },
"category": "hardware" "category": "hardware"
} }

View File

@@ -5,4 +5,4 @@
"fr": "Je n'améliore pas mon téléphone chaque année, mais quand je le fais, je vais pour le meilleur. L'iPhone 14 Pro est le meilleur téléphone sur le marché, et je suis excité de mettre la main dessus." "fr": "Je n'améliore pas mon téléphone chaque année, mais quand je le fais, je vais pour le meilleur. L'iPhone 14 Pro est le meilleur téléphone sur le marché, et je suis excité de mettre la main dessus."
}, },
"category": "hardware" "category": "hardware"
} }

View File

@@ -5,4 +5,4 @@
"fr": "Mon ordinateur principal pour programmer est un MacBook Pro 13' 2020 avec la puce Apple M1 et 16Go de RAM. J'utilise MacOS Sorona." "fr": "Mon ordinateur principal pour programmer est un MacBook Pro 13' 2020 avec la puce Apple M1 et 16Go de RAM. J'utilise MacOS Sorona."
}, },
"category": "hardware" "category": "hardware"
} }

View File

@@ -5,4 +5,4 @@
"fr": "J'utilise la suite Apple comprenant Mail, Calendar, Notes, Music et Reminders pour mon organisation quotidienne." "fr": "J'utilise la suite Apple comprenant Mail, Calendar, Notes, Music et Reminders pour mon organisation quotidienne."
}, },
"category": "software" "category": "software"
} }

View File

@@ -5,4 +5,4 @@
"fr": "J'utilise Discord pour discuter et parler avec mes amis et mes clients et discuter avec certains membres de la communauté." "fr": "J'utilise Discord pour discuter et parler avec mes amis et mes clients et discuter avec certains membres de la communauté."
}, },
"category": "software" "category": "software"
} }

View File

@@ -5,4 +5,4 @@
"fr": "J'ai acheté un ordinateur personnalisé pour le jeu. J'ai choisi un Intel Core i5-10400F, avec 16Go DDR4 et ma carte graphique est une RTX 2060. J'utilise Windows 11." "fr": "J'ai acheté un ordinateur personnalisé pour le jeu. J'ai choisi un Intel Core i5-10400F, avec 16Go DDR4 et ma carte graphique est une RTX 2060. J'utilise Windows 11."
}, },
"category": "hardware" "category": "hardware"
} }

View File

@@ -5,4 +5,4 @@
"fr": "J'utilise Google Chrome pour naviguer, l'outil de développement et le marché des extensions." "fr": "J'utilise Google Chrome pour naviguer, l'outil de développement et le marché des extensions."
}, },
"category": "software" "category": "software"
} }

View File

@@ -5,4 +5,4 @@
"fr": "J'utilise la suite JetBrains pour le développement depuis 7 ans. C'est le meilleur IDE pour Java, Python, JavaScript, SQL et plus encore. J'ai utilisé cette suite pour développer et créer ce site web." "fr": "J'utilise la suite JetBrains pour le développement depuis 7 ans. C'est le meilleur IDE pour Java, Python, JavaScript, SQL et plus encore. J'ai utilisé cette suite pour développer et créer ce site web."
}, },
"category": "ide" "category": "ide"
} }

View File

@@ -5,4 +5,4 @@
"fr": "Cette souris de jeu est conçue pour être le compagnon de jeu parfait. Avec un design classique et une disposition simple, cette souris est parfaite pour tout joueur." "fr": "Cette souris de jeu est conçue pour être le compagnon de jeu parfait. Avec un design classique et une disposition simple, cette souris est parfaite pour tout joueur."
}, },
"category": "hardware" "category": "hardware"
} }

View File

@@ -5,4 +5,4 @@
"fr": "Notion est mon outil de prise de notes, de kanban, de wikis et de brouillon tout-en-un." "fr": "Notion est mon outil de prise de notes, de kanban, de wikis et de brouillon tout-en-un."
}, },
"category": "software" "category": "software"
} }

View File

@@ -5,4 +5,4 @@
"fr": "Raycast est mon lanceur extensible remplaçant Apple Spotlight. Il me permet d'accomplir des tâches, de calculer, de partager des liens communs et bien plus encore grâce aux extensions." "fr": "Raycast est mon lanceur extensible remplaçant Apple Spotlight. Il me permet d'accomplir des tâches, de calculer, de partager des liens communs et bien plus encore grâce aux extensions."
}, },
"category": "software" "category": "software"
} }

View File

@@ -5,4 +5,4 @@
"fr": "J'utilise TypeScript, Vue 3 avec Nuxt 3, Nuxt Stack (UI, Hub, Content, Studio) & TailwindCss pour le FrontEnd. Nuxt (alimenté par Nitro) et AdonisJs sont utilisés pour le BackEnd en fonction de la complexité du projet. PostgreSQL est utilisé pour la base de données, Redis pour le caching. Docker est utilisé pour la conteneurisation. Les applications sont déployées sur NuxtHub (alimenté par CloudFlare) ou Vercel." "fr": "J'utilise TypeScript, Vue 3 avec Nuxt 3, Nuxt Stack (UI, Hub, Content, Studio) & TailwindCss pour le FrontEnd. Nuxt (alimenté par Nitro) et AdonisJs sont utilisés pour le BackEnd en fonction de la complexité du projet. PostgreSQL est utilisé pour la base de données, Redis pour le caching. Docker est utilisé pour la conteneurisation. Les applications sont déployées sur NuxtHub (alimenté par CloudFlare) ou Vercel."
}, },
"category": "stack" "category": "stack"
} }

View File

@@ -5,4 +5,4 @@
"fr": "Ce clavier TKL est un excellent choix pour les joueurs qui veulent un clavier compact avec de nombreuses fonctionnalités." "fr": "Ce clavier TKL est un excellent choix pour les joueurs qui veulent un clavier compact avec de nombreuses fonctionnalités."
}, },
"category": "hardware" "category": "hardware"
} }

View File

@@ -5,4 +5,4 @@
"fr": "Mon thème est Catppuccin Macchiato, un thème pastel piloté par la communauté qui vise à être le juste milieu entre les thèmes à faible et à fort contraste. Mes polices principales sont Vercel Geist et JetBrains Mono" "fr": "Mon thème est Catppuccin Macchiato, un thème pastel piloté par la communauté qui vise à être le juste milieu entre les thèmes à faible et à fort contraste. Mes polices principales sont Vercel Geist et JetBrains Mono"
}, },
"category": "ide" "category": "ide"
} }

View File

@@ -5,4 +5,4 @@
"fr": "Warp est un terminal moderne basé sur Rust réimaginé avec l'IA et des outils collaboratifs pour une meilleure productivité. Je l'adore jusqu'à présent !" "fr": "Warp est un terminal moderne basé sur Rust réimaginé avec l'IA et des outils collaboratifs pour une meilleure productivité. Je l'adore jusqu'à présent !"
}, },
"category": "software" "category": "software"
} }

View File

@@ -3,5 +3,5 @@ import type { Config } from 'drizzle-kit'
export default { export default {
dialect: 'sqlite', dialect: 'sqlite',
schema: './server/database/schema.ts', schema: './server/database/schema.ts',
out: './server/database/migrations' out: './server/database/migrations',
} satisfies Config } satisfies Config

View File

@@ -1,6 +1,5 @@
// @ts-check import antfu from '@antfu/eslint-config'
import withNuxt from './.nuxt/eslint.config.mjs'
export default withNuxt( export default antfu(
// Your custom configs here // Your custom configs here
) )

View File

@@ -6,22 +6,21 @@ export default defineNuxtConfig({
pageTransition: { name: 'page', mode: 'out-in' }, pageTransition: { name: 'page', mode: 'out-in' },
head: { head: {
templateParams: { templateParams: {
separator: '•' separator: '•',
} },
} },
}, },
// Nuxt Modules // Nuxt Modules
modules: [ modules: [
'@nuxthub/core', '@nuxthub/core',
'@nuxt/eslint',
'@nuxt/ui', '@nuxt/ui',
'@nuxt/content', '@nuxt/content',
'@vueuse/nuxt', '@vueuse/nuxt',
'@nuxtjs/google-fonts', '@nuxtjs/google-fonts',
'@nuxthq/studio', '@nuxthq/studio',
'@nuxt/image', '@nuxt/image',
'@nuxtjs/i18n' '@nuxtjs/i18n',
], ],
// Nuxt Hub // Nuxt Hub
@@ -29,26 +28,27 @@ export default defineNuxtConfig({
cache: true, cache: true,
kv: true, kv: true,
database: true, database: true,
analytics: true analytics: true,
}, },
// Nuxt Content // Nuxt Content
content: { content: {
highlight: { highlight: {
theme: 'github-dark' theme: 'github-dark',
} },
locales: ['en', 'fr'],
}, },
// Nuxt Color Mode // Nuxt Color Mode
colorMode: { colorMode: {
preference: 'system', preference: 'system',
fallback: 'light' fallback: 'light',
}, },
// Nuxt Devtools // Nuxt Devtools
devtools: { devtools: {
enabled: true, enabled: true,
timeline: { enabled: true } timeline: { enabled: true },
}, },
// Nuxt I18N // Nuxt I18N
@@ -58,24 +58,15 @@ export default defineNuxtConfig({
{ {
code: 'en', code: 'en',
iso: 'en-EN', iso: 'en-EN',
icon: 'i-twemoji-flag-united-kingdom' icon: 'i-twemoji-flag-united-kingdom',
}, { },
{
code: 'fr', code: 'fr',
iso: 'fr-FR', iso: 'fr-FR',
icon: 'i-twemoji-flag-france' icon: 'i-twemoji-flag-france',
} },
], ],
defaultLocale: 'en' defaultLocale: 'en',
},
// Nuxt Eslint
eslint: {
config: {
stylistic: {
quotes: 'single',
commaDangle: 'never'
}
}
}, },
// Nuxt Google Fonts // Nuxt Google Fonts
@@ -85,15 +76,15 @@ export default defineNuxtConfig({
'Inter': [400, 500, 600, 700, 800, 900], 'Inter': [400, 500, 600, 700, 800, 900],
'Sofia Sans': [400], 'Sofia Sans': [400],
'DM Sans': [400, 500, 600, 700, 800, 900], 'DM Sans': [400, 500, 600, 700, 800, 900],
'Dancing Script': [400, 700] 'Dancing Script': [400, 700],
} },
}, },
// Nitro // Nitro
nitro: { nitro: {
experimental: { experimental: {
openAPI: true openAPI: true,
} },
}, },
// Nuxt Env // Nuxt Env
@@ -101,21 +92,21 @@ export default defineNuxtConfig({
discord: { discord: {
userId: '', userId: '',
id: '', id: '',
token: '' token: '',
}, },
wakatime: { wakatime: {
userId: '', userId: '',
coding: '', coding: '',
editors: '', editors: '',
languages: '', languages: '',
os: '' os: '',
}, },
public: { public: {
cloud: { cloud: {
resume: '' resume: '',
} },
} },
}, },
compatibilityDate: '2024-07-08' compatibilityDate: '2024-07-08',
}) })

View File

@@ -1,7 +1,7 @@
{ {
"name": "artsite", "name": "artsite",
"private": true, "private": true,
"packageManager": "pnpm@9.4.0", "packageManager": "pnpm@9.5.0",
"scripts": { "scripts": {
"build": "nuxt build", "build": "nuxt build",
"dev": "nuxt dev --host", "dev": "nuxt dev --host",
@@ -9,34 +9,34 @@
"preview": "nuxt preview", "preview": "nuxt preview",
"postinstall": "nuxt prepare", "postinstall": "nuxt prepare",
"lint": "eslint .", "lint": "eslint .",
"lint:fix": "eslint --fix .",
"db:generate": "drizzle-kit generate" "db:generate": "drizzle-kit generate"
}, },
"dependencies": { "dependencies": {
"@iconify/json": "^2.2.225", "@iconify/json": "^2.2.230",
"@nuxt/content": "^2.13.1", "@nuxt/content": "^2.13.2",
"@nuxt/eslint": "^0.3.13",
"@nuxt/image": "^1.7.0", "@nuxt/image": "^1.7.0",
"@nuxt/ui": "^2.17.0", "@nuxt/ui": "^2.17.0",
"@nuxthq/studio": "^2.0.3", "@nuxthq/studio": "^2.0.3",
"@nuxthub/core": "^0.7.0", "@nuxthub/core": "^0.7.1",
"@nuxtjs/google-fonts": "^3.2.0", "@nuxtjs/google-fonts": "^3.2.0",
"@nuxtjs/i18n": "^8.3.1", "@nuxtjs/i18n": "^8.3.1",
"drizzle-orm": "^0.31.2", "drizzle-orm": "^0.31.4",
"h3-zod": "^0.5.3", "h3-zod": "^0.5.3",
"nuxt": "^3.12.3", "nuxt": "^3.12.4",
"zod": "^3.23.8" "zod": "^3.23.8"
}, },
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^2.23.2",
"@nuxt/devtools": "^1.3.9", "@nuxt/devtools": "^1.3.9",
"@nuxt/eslint-config": "^0.3.13",
"@nuxt/ui": "^2.17.0", "@nuxt/ui": "^2.17.0",
"@types/node": "^20.14.10", "@types/node": "^20.14.12",
"@vueuse/core": "^10.11.0", "@vueuse/core": "^10.11.0",
"@vueuse/nuxt": "^10.11.0", "@vueuse/nuxt": "^10.11.0",
"drizzle-kit": "^0.22.8", "drizzle-kit": "^0.22.8",
"eslint": "^9.6.0", "eslint": "^9.7.0",
"typescript": "^5.5.3", "typescript": "^5.5.4",
"vue-tsc": "^2.0.26", "vue-tsc": "^2.0.28",
"wrangler": "^3.63.1" "wrangler": "^3.66.0"
} }
} }

3123
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,16 +2,16 @@ import { useValidatedParams, z } from 'h3-zod'
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const { slug } = await useValidatedParams(event, { const { slug } = await useValidatedParams(event, {
slug: z.string() slug: z.string(),
}) })
return useDB().insert(tables.posts).values({ return useDB().insert(tables.posts).values({
slug slug,
}).onConflictDoUpdate({ }).onConflictDoUpdate({
target: tables.posts.slug, target: tables.posts.slug,
set: { set: {
slug, slug,
views: sql`${tables.posts.views} views: sql`${tables.posts.views}
+ 1` + 1`,
} },
}).returning().get() }).returning().get()
}) })

View File

@@ -2,12 +2,12 @@ import { useValidatedParams, z } from 'h3-zod'
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const { slug } = await useValidatedParams(event, { const { slug } = await useValidatedParams(event, {
slug: z.string() slug: z.string(),
}) })
return useDB().update(tables.posts) return useDB().update(tables.posts)
.set({ .set({
likes: sql`${tables.posts.likes} likes: sql`${tables.posts.likes}
+ 1` + 1`,
}) })
.where(eq(tables.posts.slug, slug)) .where(eq(tables.posts.slug, slug))
}) })

View File

@@ -10,9 +10,9 @@ export default defineCachedEventHandler(async (event) => {
coding, coding,
editors, editors,
os, os,
languages languages,
} }
}, { }, {
maxAge: 24 * 60 * 60, maxAge: 24 * 60 * 60,
name: 'wakatime' name: 'wakatime',
}) })

View File

@@ -110,4 +110,4 @@
"internal": { "internal": {
"indexes": {} "indexes": {}
} }
} }

View File

@@ -54,4 +54,4 @@
"internal": { "internal": {
"indexes": {} "indexes": {}
} }
} }

View File

@@ -17,4 +17,4 @@
"breakpoints": true "breakpoints": true
} }
] ]
} }

View File

@@ -5,5 +5,5 @@ export const posts = sqliteTable('posts', {
slug: text('slug').primaryKey(), slug: text('slug').primaryKey(),
likes: integer('likes').default(0), likes: integer('likes').default(0),
views: integer('views').default(0), views: integer('views').default(0),
createdAt: text('created_at').default(sql`(CURRENT_DATE)`) createdAt: text('created_at').default(sql`(CURRENT_DATE)`),
}) })

View File

@@ -2,7 +2,8 @@ import { consola } from 'consola'
import { migrate } from 'drizzle-orm/d1/migrator' import { migrate } from 'drizzle-orm/d1/migrator'
export default defineNitroPlugin(async () => { export default defineNitroPlugin(async () => {
if (!import.meta.dev) return if (!import.meta.dev)
return
onHubReady(async () => { onHubReady(async () => {
await migrate(useDB(), { migrationsFolder: 'server/database/migrations' }) await migrate(useDB(), { migrationsFolder: 'server/database/migrations' })

View File

@@ -14,24 +14,24 @@ export default <Partial<Config>>{
'./Error.{js,ts,vue}', './Error.{js,ts,vue}',
'./error.{js,ts,vue}', './error.{js,ts,vue}',
'./app.config.{js,ts}', './app.config.{js,ts}',
'content/**/*.md' 'content/**/*.md',
], ],
theme: { theme: {
extend: { extend: {
animation: { animation: {
wave: 'wave 3s infinite' wave: 'wave 3s infinite',
}, },
keyframes: { keyframes: {
wave: { wave: {
'0%, 50%, 100%': { '0%, 50%, 100%': {
transform: 'rotate(-12deg)' transform: 'rotate(-12deg)',
}, },
'25%, 75%': { '25%, 75%': {
transform: 'rotate(12deg) scale(1.5)' transform: 'rotate(12deg) scale(1.5)',
} },
} },
} },
} },
}, },
plugins: [typography] plugins: [typography],
} }

View File

@@ -43,5 +43,5 @@ export interface Activity {
export const IDEs = [ export const IDEs = [
{ name: 'Visual Studio Code', icon: 'i-logos-visual-studio-code' }, { name: 'Visual Studio Code', icon: 'i-logos-visual-studio-code' },
{ name: 'IntelliJ IDEA Ultimate', icon: 'i-logos-intellij-idea' }, { name: 'IntelliJ IDEA Ultimate', icon: 'i-logos-intellij-idea' },
{ name: 'WebStorm', icon: 'i-logos-webstorm' } { name: 'WebStorm', icon: 'i-logos-webstorm' },
] ]