mirror of
https://github.com/ArthurDanjou/artsite.git
synced 2026-01-14 18:59:59 +01:00
Merge branch 'content_v3'
This commit is contained in:
@@ -44,6 +44,7 @@ const head = useLocaleHead({
|
||||
<AppBackground />
|
||||
<UContainer class="z-50 relative">
|
||||
<AppHeader />
|
||||
<AppVisitors />
|
||||
<NuxtPage class="mt-12" />
|
||||
<AppFooter />
|
||||
</UContainer>
|
||||
|
||||
14
app/components/AppVisitors.vue
Normal file
14
app/components/AppVisitors.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
const { isLoading, visitors } = useVisitors()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="fixed bottom-4 right-8">
|
||||
<UTooltip text="Visitors currently on my portfolio" placement="left">
|
||||
<nav v-if="!isLoading" class="text-xs flex space-x-1 items-center border border-green-400 dark:border-green-600 px-2 rounded-xl">
|
||||
<div>{{ visitors }}</div>
|
||||
<div class="h-3 w-3 bg-green-200 dark:bg-green-600 rounded-full border-2 border-green-400 dark:border-green-800" />
|
||||
</nav>
|
||||
</UTooltip>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,10 +1,20 @@
|
||||
<script lang="ts" setup>
|
||||
const { locale } = useI18n()
|
||||
|
||||
const { data: page } = await useAsyncData(`/home/${locale.value}`, () => {
|
||||
return queryCollection('main').path(`/home/${locale.value}`).first()
|
||||
}, {
|
||||
watch: [locale],
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="!max-w-none prose dark:prose-invert">
|
||||
<ContentDoc :path="`/home/${locale}`" />
|
||||
<ContentRenderer v-if="page" :value="page" />
|
||||
<HomeStats />
|
||||
<HomeActivity />
|
||||
<HomeQuote />
|
||||
<HomeCatchPhrase />
|
||||
<HomeMap />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<script lang="ts" setup>
|
||||
const route = useRoute()
|
||||
const { data: post } = await useAsyncData(`portfolio:${route.params.slug}`, () => queryContent(`/portfolio/${route.params.slug}`).findOne())
|
||||
const { data: post } = await useAsyncData(`portfolio/${route.params.slug}`, () =>
|
||||
queryCollection('portfolio').path(`/portfolio/${route.params.slug}`).first())
|
||||
|
||||
const {
|
||||
data: postDB,
|
||||
refresh,
|
||||
} = await useAsyncData(`portfolio:${route.params.slug}:db`, () => $fetch(`/api/posts/${route.params.slug}`, { method: 'POST' }))
|
||||
|
||||
const { locale, locales } = useI18n()
|
||||
const currentLocale = computed(() => locales.value.filter(l => l.code === locale.value)[0])
|
||||
} = await useAsyncData(`portfolio/${route.params.slug}/db`, () => $fetch(`/api/posts/${route.params.slug}`, { method: 'POST' }))
|
||||
|
||||
const { locale } = useI18n()
|
||||
const { t } = useI18n({
|
||||
useScope: 'local',
|
||||
})
|
||||
@@ -122,12 +122,10 @@ async function handleLike() {
|
||||
icon="i-ph-pencil-line-duotone"
|
||||
/>
|
||||
<article class="mt-8">
|
||||
<ContentRenderer :value="post">
|
||||
<ContentRendererMarkdown
|
||||
:value="post"
|
||||
class="!max-w-none prose dark:prose-invert"
|
||||
/>
|
||||
</ContentRenderer>
|
||||
<ContentRenderer
|
||||
:value="post"
|
||||
class="!max-w-none prose dark:prose-invert"
|
||||
/>
|
||||
<UDivider
|
||||
class="my-16"
|
||||
icon="i-ph-hands-clapping-duotone"
|
||||
@@ -188,6 +186,10 @@ async function handleLike() {
|
||||
.prose h4 a {
|
||||
@apply no-underline;
|
||||
}
|
||||
|
||||
.katex-html {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n lang="json">
|
||||
|
||||
@@ -11,13 +11,10 @@ useSeoMeta({
|
||||
|
||||
const tagFilter = ref<string | undefined>(undefined)
|
||||
|
||||
const { data: writings, refresh } = await useAsyncData('all-portfolio', () => queryContent('/portfolio')
|
||||
.sort({ publishedAt: -1 })
|
||||
.where({
|
||||
tags: { $contains: tagFilter.value },
|
||||
})
|
||||
.without('body')
|
||||
.find())
|
||||
const { data: writings, refresh } = await useAsyncData('all-portfolio', () => queryCollection('portfolio')
|
||||
.order('publishedAt', 'DESC')
|
||||
.where('tags', 'LIKE', tagFilter.value ? `%${tagFilter.value}%` : '%')
|
||||
.all())
|
||||
|
||||
watch(tagFilter, async () => await refresh())
|
||||
|
||||
@@ -60,7 +57,7 @@ function updateTag(index: number) {
|
||||
<NuxtLink
|
||||
v-for="(writing, id) in writings"
|
||||
:key="id"
|
||||
:to="writing._path"
|
||||
:to="writing.path"
|
||||
>
|
||||
<li
|
||||
class=" h-full border p-4 shadow-sm border-neutral-200 rounded-md hover:border-neutral-500 dark:border-neutral-700 dark:hover:border-neutral-500 duration-300"
|
||||
@@ -114,6 +111,17 @@ function updateTag(index: number) {
|
||||
"alert": {
|
||||
"title": "Translations alert!",
|
||||
"description": "Due to time constraints, all article translations will be available only in English. Thank you for your understanding."
|
||||
},
|
||||
"tags": {
|
||||
"article": "Articles",
|
||||
"all": "Library",
|
||||
"project": "Projects",
|
||||
"r": "R",
|
||||
"python": "Python",
|
||||
"data": "Data",
|
||||
"ai": "AI",
|
||||
"maths": "Maths",
|
||||
"web": "Web"
|
||||
}
|
||||
},
|
||||
"fr": {
|
||||
|
||||
@@ -8,7 +8,7 @@ useSeoMeta({
|
||||
description: t('description'),
|
||||
})
|
||||
|
||||
const { data: items } = await useAsyncData('uses', () => queryContent('/uses').find())
|
||||
const { data: items } = await useAsyncData('uses', async () => await queryCollection('uses').all())
|
||||
|
||||
const hardware = items.value!.filter(item => item.category === 'hardware')
|
||||
const software = items.value!.filter(item => item.category === 'software')
|
||||
|
||||
34
content.config.ts
Normal file
34
content.config.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { defineCollection, z } from '@nuxt/content'
|
||||
|
||||
export const collections = {
|
||||
main: defineCollection({
|
||||
type: 'page',
|
||||
source: 'home/*.md',
|
||||
}),
|
||||
portfolio: defineCollection({
|
||||
type: 'page',
|
||||
source: 'portfolio/*.md',
|
||||
schema: z.object({
|
||||
slug: z.string(),
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
publishedAt: z.date(),
|
||||
readingTime: z.number(),
|
||||
cover: z.string(),
|
||||
tags: z.array(z.string()),
|
||||
}),
|
||||
}),
|
||||
uses: defineCollection({
|
||||
type: 'data',
|
||||
source: 'uses/*.json',
|
||||
schema: z.object({
|
||||
name: z.string(),
|
||||
description: z.object({
|
||||
en: z.string(),
|
||||
fr: z.string(),
|
||||
es: z.string(),
|
||||
}),
|
||||
category: z.string(),
|
||||
}),
|
||||
}),
|
||||
}
|
||||
@@ -32,14 +32,3 @@ As well as programming, I enjoy :hover-text{hover="Sport allows me to burn off e
|
||||
eagerness to learn and progress are the qualities that enable me to succeed in my :hover-text{hover="Career already
|
||||
begun and far from over 😎" text="career"} and :hover-text{hover="Only 2 years of study left 💪" text="studies"}.
|
||||
|
||||
::stats
|
||||
::
|
||||
|
||||
::activity
|
||||
::
|
||||
|
||||
::quote
|
||||
::
|
||||
|
||||
::catch-phrase
|
||||
::
|
||||
|
||||
@@ -34,15 +34,3 @@ A parte de la programación, me gusta el :hover-text{hover="el deporte me permit
|
||||
y :hover-text{hover="los viajes me permiten desconectar ✈️" text="viajar"}.
|
||||
Mi pasión, mi compromiso y mis ganas de aprender y mejorar son las cualidades que me permiten triunfar en mi
|
||||
:hover-text{hover="carrera que ya he empezado, y le queda mucho para terminar 😎" text="carrera"} y en mis :hover-text{hover="solo me quedan 2 años de estudios 💪" text="estudios"}.
|
||||
|
||||
::stats
|
||||
::
|
||||
|
||||
::activity
|
||||
::
|
||||
|
||||
::quote
|
||||
::
|
||||
|
||||
::catch-phrase
|
||||
::
|
||||
|
||||
@@ -37,16 +37,4 @@ Outre la programmation, j'aime le :hover-text{hover="Le sport me permet de dépe
|
||||
et :hover-text{hover="Les voyages me libèrent et m'évadent ✈️" text="voyager"}.
|
||||
Ma passion, mon engagement et mon envie d'apprendre et de progresser sont les qualités qui me permettent de réussir dans
|
||||
ma :hover-text{hover="Carrière déjà commencée et loin d'être terminée 😎" text="carrière"} et mes :hover-text{hover="Il
|
||||
ne me reste que 2 ans d'études 💪" text="études"}.
|
||||
|
||||
::stats
|
||||
::
|
||||
|
||||
::activity
|
||||
::
|
||||
|
||||
::quote
|
||||
::
|
||||
|
||||
::catch-phrase
|
||||
::
|
||||
ne me reste que 2 ans d'études 💪" text="études"}.
|
||||
@@ -10,6 +10,15 @@ tags:
|
||||
- maths
|
||||
---
|
||||
|
||||
::UAlert
|
||||
---
|
||||
icon: i-ph-warning-duotone
|
||||
color: amber
|
||||
variant: soft
|
||||
title: The Latex format may be not well rendered in the article, please refresh the page if you encounter any issue.
|
||||
---
|
||||
::
|
||||
|
||||
## Introduction
|
||||
|
||||
Machine Learning (ML) is a key discipline in artificial intelligence (AI), enabling systems to learn from data to make predictions or discover patterns. It is the driving force behind many modern innovations, from personalised recommendations to autonomous vehicles.
|
||||
|
||||
@@ -18,10 +18,10 @@ export default defineNuxtConfig({
|
||||
'@nuxt/content',
|
||||
'@vueuse/nuxt',
|
||||
'@nuxtjs/google-fonts',
|
||||
'@nuxthq/studio',
|
||||
'@nuxt/image',
|
||||
'@nuxtjs/i18n',
|
||||
'nuxt-mapbox',
|
||||
'nuxt-visitors',
|
||||
],
|
||||
|
||||
// Nuxt Hub
|
||||
@@ -34,14 +34,18 @@ export default defineNuxtConfig({
|
||||
|
||||
// Nuxt Content
|
||||
content: {
|
||||
highlight: {
|
||||
theme: 'github-dark',
|
||||
},
|
||||
markdown: {
|
||||
remarkPlugins: ['remark-math'],
|
||||
rehypePlugins: {
|
||||
'rehype-katex': {
|
||||
output: 'mathml',
|
||||
build: {
|
||||
markdown: {
|
||||
highlight: {
|
||||
theme: 'github-dark',
|
||||
},
|
||||
remarkPlugins: {
|
||||
'remark-math': {},
|
||||
},
|
||||
rehypePlugins: {
|
||||
'rehype-katex': {
|
||||
output: 'mathml',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -150,4 +154,4 @@ export default defineNuxtConfig({
|
||||
},
|
||||
|
||||
compatibilityDate: '2024-08-19',
|
||||
})
|
||||
})
|
||||
39
package.json
39
package.json
@@ -13,35 +13,34 @@
|
||||
"db:generate": "drizzle-kit generate"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/content": "^2.13.4",
|
||||
"@nuxt/image": "^1.8.1",
|
||||
"@nuxt/ui": "^2.18.5",
|
||||
"@nuxthq/studio": "^2.1.1",
|
||||
"@nuxthub/core": "^0.8.7",
|
||||
"@nuxt/content": "3.0.1",
|
||||
"@nuxt/image": "^1.9.0",
|
||||
"@nuxt/ui": "^2.21.0",
|
||||
"@nuxthub/core": "^0.8.15",
|
||||
"@nuxtjs/google-fonts": "^3.2.0",
|
||||
"@nuxtjs/i18n": "^8.5.3",
|
||||
"drizzle-orm": "^0.33.0",
|
||||
"h3-zod": "^0.5.3",
|
||||
"nuxt": "^3.13.2",
|
||||
"nuxt": "^3.15.3",
|
||||
"nuxt-visitors": "^1.1.2",
|
||||
"rehype-katex": "^7.0.1",
|
||||
"remark-math": "^6.0.0",
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.1.1",
|
||||
"zod": "^3.23.8"
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^3.10.0",
|
||||
"@nuxt/devtools": "^1.6.1",
|
||||
"@nuxt/ui": "^2.19.2",
|
||||
"@types/node": "^22.10.0",
|
||||
"@vueuse/core": "^11.3.0",
|
||||
"@vueuse/nuxt": "^11.1.0",
|
||||
"drizzle-kit": "^0.28.1",
|
||||
"eslint": "^9.15.0",
|
||||
"mapbox-gl": "^3.8.0",
|
||||
"nuxt-mapbox": "^1.6.1",
|
||||
"typescript": "^5.7.2",
|
||||
"vue-tsc": "^2.1.10",
|
||||
"wrangler": "^3.90.0"
|
||||
"@antfu/eslint-config": "^4.1.0",
|
||||
"@nuxt/devtools": "^2.0.0-beta.3",
|
||||
"@types/node": "^22.12.0",
|
||||
"@vueuse/core": "^12.5.0",
|
||||
"@vueuse/nuxt": "^12.5.0",
|
||||
"drizzle-kit": "^0.30.3",
|
||||
"eslint": "^9.19.0",
|
||||
"mapbox-gl": "^3.9.4",
|
||||
"nuxt-mapbox": "^1.6.2",
|
||||
"typescript": "^5.7.3",
|
||||
"vue-tsc": "^2.2.0",
|
||||
"wrangler": "^3.106.0"
|
||||
}
|
||||
}
|
||||
|
||||
6150
pnpm-lock.yaml
generated
6150
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user