mirror of
https://github.com/ArthurDanjou/artsite.git
synced 2026-02-01 12:29:32 +01:00
Change linter config to antfu config and lint code
This commit is contained in:
@@ -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,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
24
app/app.vue
24
app/app.vue
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
|
||||||
|
|||||||
@@ -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>
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
defineProps({
|
defineProps({
|
||||||
icon: {
|
icon: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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>
|
|
||||||
|
|||||||
@@ -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>
|
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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',
|
||||||
})
|
})
|
||||||
|
|||||||
26
package.json
26
package.json
@@ -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
3123
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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)`),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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' })
|
||||||
|
|||||||
@@ -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],
|
||||||
}
|
}
|
||||||
|
|||||||
2
types.ts
2
types.ts
@@ -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' },
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user