Initial commit 🚀

This commit is contained in:
2022-02-28 20:07:01 +01:00
commit 08f616fe70
53 changed files with 4735 additions and 0 deletions

3
.eslintignore Normal file
View File

@@ -0,0 +1,3 @@
dist
node_modules
public

3
.eslintrc Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "@antfu"
}

9
.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
.DS_Store
.vite-ssg-dist
.vite-ssg-temp
*.local
dist
dist-ssr
node_modules
.idea/
*.log

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
shamefully-hoist=true

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020-2021 Anthony Fu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

82
README.md Normal file
View File

@@ -0,0 +1,82 @@
<p align='center'>
<img src='https://user-images.githubusercontent.com/11247099/111864893-a457fd00-899e-11eb-9f05-f4b88987541d.png' alt='Vitesse - Opinionated Vite Starter Template' width='600'/>
</p>
<h6 align='center'>
<a href="https://vitesse-lite.netlify.app/">Live Demo</a>
</h6>
<h5 align='center'>
<b>Lightweight version of <a href="https://github.com/antfu/vitesse">Vitesse</a></b>
</h5>
<br>
## Features
- ⚡️ [Vue 3](https://github.com/vuejs/vue-next), [Vite 2](https://github.com/vitejs/vite), [pnpm](https://pnpm.js.org/), [ESBuild](https://github.com/evanw/esbuild) - born with fastness
- 🗂 [File based routing](./src/pages)
- 📦 [Components auto importing](./src/components)
- 🎨 [UnoCSS](https://github.com/antfu/unocss) - The instant on-demand atomic CSS engine.
- 😃 Use icons from any icon sets in [Pure CSS](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
- 🔥 Use the [new `<script setup>` style](https://github.com/vuejs/rfcs/pull/227)
- ✅ Use [Vitest](http://vitest.dev/) for unit and components testing
- 🦾 TypeScript, of course
- ☁️ Deploy on Netlify, zero-config
<br>
See [Vitesse](https://github.com/antfu/vitesse) for full featureset.
## Dropped Features from [Vitesse](https://github.com/antfu/vitesse)
- ~~i18n~~
- ~~Layouts~~
- ~~SSG~~
- ~~PWA~~
- ~~Markdown~~
## Pre-packed
### UI Frameworks
- [UnoCSS](https://github.com/antfu/unocss) - The instant on-demand atomic CSS engine.
### Icons
- [Iconify](https://iconify.design) - use icons from any icon sets [🔍Icônes](https://icones.netlify.app/)
- [Pure CSS Icons via UnoCSS](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
### Plugins
- [Vue Router](https://github.com/vuejs/vue-router)
- [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) - file system based routing
- [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) - Directly use Vue Composition API and others without importing
- [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components) - components auto import
- [VueUse](https://github.com/antfu/vueuse) - collection of useful composition APIs
## Try it now!
### GitHub Template
[Create a repo from this template on GitHub](https://github.com/antfu/vitesse-lite/generate).
### Clone to local
If you prefer to do it manually with the cleaner git history
```bash
npx degit antfu/vitesse-lite my-vitesse-app
cd my-vitesse-app
pnpm i # If you don't have pnpm installed, run: npm install -g pnpm
```

228
auto-imports.d.ts vendored Normal file
View File

@@ -0,0 +1,228 @@
// Generated by 'unplugin-auto-import'
// We suggest you to commit this file into source control
declare global {
const afterAll: typeof import('vitest')['afterAll']
const afterEach: typeof import('vitest')['afterEach']
const assert: typeof import('vitest')['assert']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const beforeAll: typeof import('vitest')['beforeAll']
const beforeEach: typeof import('vitest')['beforeEach']
const biSyncRef: typeof import('@vueuse/core')['biSyncRef']
const chai: typeof import('vitest')['chai']
const computed: typeof import('vue')['computed']
const computedInject: typeof import('@vueuse/core')['computedInject']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
const createEventHook: typeof import('@vueuse/core')['createEventHook']
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const describe: typeof import('vitest')['describe']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const EffectScope: typeof import('vue')['EffectScope']
const expect: typeof import('vitest')['expect']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const it: typeof import('vitest')['it']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refDefault: typeof import('@vueuse/core')['refDefault']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const suite: typeof import('vitest')['suite']
const syncRef: typeof import('@vueuse/core')['syncRef']
const templateRef: typeof import('@vueuse/core')['templateRef']
const test: typeof import('vitest')['test']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClamp: typeof import('@vueuse/core')['useClamp']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useHead: typeof import('@vueuse/head')['useHead']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const vi: typeof import('vitest')['vi']
const vitest: typeof import('vitest')['vitest']
const watch: typeof import('vue')['watch']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchEffect: typeof import('vue')['watchEffect']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
export {}

37
components.d.ts vendored Normal file
View File

@@ -0,0 +1,37 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399
declare module 'vue' {
export interface GlobalComponents {
AboutSection: typeof import('./src/components/AboutSection.vue')['default']
BackToSite: typeof import('./src/components/BackToSite.vue')['default']
DownArrowIcon: typeof import('./src/components/icons/DownArrowIcon.vue')['default']
Education: typeof import('./src/components/Education.vue')['default']
EducationSection: typeof import('./src/components/EducationSection.vue')['default']
Footer: typeof import('./src/components/Footer.vue')['default']
GithubIcon: typeof import('./src/components/icons/GithubIcon.vue')['default']
Header: typeof import('./src/components/Header.vue')['default']
InstagramIcon: typeof import('./src/components/icons/InstagramIcon.vue')['default']
InterestSection: typeof import('./src/components/InterestSection.vue')['default']
LanguageSection: typeof import('./src/components/LanguageSection.vue')['default']
LeftArrowIcon: typeof import('./src/components/icons/LeftArrowIcon.vue')['default']
LinkedInIcon: typeof import('./src/components/icons/LinkedInIcon.vue')['default']
MailIcon: typeof import('./src/components/icons/MailIcon.vue')['default']
Menu: typeof import('./src/components/Menu.vue')['default']
MoonIcon: typeof import('./src/components/icons/MoonIcon.vue')['default']
Project: typeof import('./src/components/Project.vue')['default']
ProjectSection: typeof import('./src/components/ProjectSection.vue')['default']
SectionPart: typeof import('./src/components/SectionPart.vue')['default']
SectionTitle: typeof import('./src/components/SectionTitle.vue')['default']
SocialList: typeof import('./src/components/SocialList.vue')['default']
Stack: typeof import('./src/components/Stack.vue')['default']
StackSection: typeof import('./src/components/StackSection.vue')['default']
SunIcon: typeof import('./src/components/icons/SunIcon.vue')['default']
TwitterIcon: typeof import('./src/components/icons/TwitterIcon.vue')['default']
WorkExperience: typeof import('./src/components/WorkExperience.vue')['default']
WorkSection: typeof import('./src/components/WorkSection.vue')['default']
}
}
export { }

22
index.html Normal file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<title>Arthur Danjou - My Résumé</title>
<meta name="description" content="Opinionated Vite Starter Template">
</head>
<body>
<div id="app"></div>
<script>
(function() {
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
const setting = localStorage.getItem('color-schema') || 'auto'
if (setting === 'dark' || (prefersDark && setting !== 'light'))
document.documentElement.classList.toggle('dark', true)
})()
</script>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

85
locales/en.yml Normal file
View File

@@ -0,0 +1,85 @@
back: Back to main website
date:
from: From
to: to
in: In
today: Today'hui
months:
'01': January
'02': Debruary
'03': March
'04': April
'05': May
'06': June
'07': July
'08': August
'09': September
10: October
11: November
12: December
about:
title: About
first: Je suis Arthur Danjou, un étudiant en mathématiques à la faculté des sciences de Paris-Saclay mais également un ingénieur logiciel freelance.
Je m'intéresse beaucoup aux nouvelles technologies, au développement et à l'informatique.
Je suis capable d'apprendre rapidement des nouvelles technologies pour répondre aux besoins des différents projets.
Je suis toujours motivé par un défi et j'aime être bien organisé pour produire des résultats cohérents.
Pouvoir créer un logiciel à partir de rien est une réelle source de motivation.
second: J'adore partager mes connaissances et aider les autres. Je me renseigne beaucoup et lis beaucoup d'articles techniques pour découvrir de nouvelles fonctionnalités.
Tant que je partage mes passions, je continuerai à faire ça.
footer:
pdf: PDF version
updated: Last updated on {date}
copyright: © {year} Arthur Danjou - All rights reserved
header.job: Software Ingineer
interests:
title: Interests
content: Nouvelles technologies, développement, administration système, cloud computing, voyage, automobile, aéronautique, aérospatial, mathématiques, musculation
projects:
title: Projects
more: See more projects
stacks:
title: Stack
languages: Languages
devops: DevOps
frontend: FrontEnd
backend: BackEnd
languages:
title: Languages
content: <strong>French</strong> (Native Speaker), <strong>English</strong> (Fluent)
works:
title: Work experiences
autoentrepreneur:
title: FullStack Web et Software Development
content: Développement, conception et illustration de projets informatiques personnels. Apprentissage de nouvelles technologies et langages de programmation
erisium:
title: Junior Developer
content: Développement et réalisation de projets informatiques conçus par léquipe de Design. Maintien et mise à jour de projets en production. Correction de bugs présents
idemia:
title: Stage d'observation
content: Découverte du secteur IT, technologie de linformation et du Datacenter. Découverte de différents métiers de la société
lsam:
title: Stage de découverte
content: Nettoyage et préparation de la salle, accueil des clients, prise de commandes et services en salle
educations:
title: Educations
tb: Mention Très Bien
b: Mention Bien
license: Licence de Mathématiques
baccalaureate: Baccalauréat Général spécialités Mathématiques et Physique-Chimie
dnb: Diplôme National du Brevet
selftaught:
title: Apprentissage en autodidacte
content: Apprentissage de langages de programmation (TypeScript, Rust, Java, Python...) et de technologies

90
locales/fr.yml Normal file
View File

@@ -0,0 +1,90 @@
back: Retour au site principal
date:
from: De
to: à
in: En
today: Aujourd'hui
months:
'01': Janvier
'02': Février
'03': Mars
'04': Avril
'05': Mai
'06': Juin
'07': Juillet
'08': Août
'09': Septembre
10: Octobre
11: Novembre
12: Décembre
about:
title: A propos
first: Je suis Arthur Danjou, un étudiant en mathématiques à la faculté des sciences de Paris-Saclay mais également un ingénieur logiciel freelance.
Je m'intéresse beaucoup aux nouvelles technologies, au développement et à l'informatique.
Je suis capable d'apprendre rapidement des nouvelles technologies pour répondre aux besoins des différents projets.
Je suis toujours motivé par un défi et j'aime être bien organisé pour produire des résultats cohérents.
Pouvoir créer un logiciel à partir de rien est une réelle source de motivation.
second: J'adore partager mes connaissances et aider les autres. Je me renseigne beaucoup et lis beaucoup d'articles techniques pour découvrir de nouvelles fonctionnalités.
Tant que je partage mes passions, je continuerai à faire ça.
footer:
pdf: version PDF
updated: Dernière mise à jour le {date}
copyright: © {year} Arthur Danjou - Tous droits réservés
header.job: Ingénieur Logiciel
interests:
title: Intérêts
content: Nouvelles technologies, développement, administration système, cloud computing, voyage, automobile, aéronautique, aérospatial, mathématiques, musculation
projects:
title: Projets
more: Voir plus de projets
ares: Site web personnel créant un unique point de contact
athena: API connectée à des services comme Spotify fournissant diverses informations
linkyjs: Raccourcisseur d'URL Open-Source pour les développeurs
slidev: Traduction de la documentation en Français
stacks:
title: Stack technique
languages: Langages
devops: DevOps
frontend: FrontEnd
backend: BackEnd
languages:
title: Langues
content: <strong>Francais</strong> (Langue natale), <strong>Anglais</strong> (Langue courante)
works:
title: Expériences professionnelles
autoentrepreneur:
title: Développement FullStack Web et Logiciel
content: Développement, conception et illustration de projets informatiques personnels. Apprentissage de nouvelles technologies et langages de programmation
erisium:
title: Développeur Junior
content: Développement et réalisation de projets informatiques conçus par léquipe de Design. Maintien et mise à jour de projets en production. Correction de bugs présents
idemia:
title: Stage d'observation
content: Découverte du secteur IT, technologie de linformation et du Datacenter. Découverte de différents métiers de la société
lsam:
title: Stage de découverte
content: Nettoyage et préparation de la salle, accueil des clients, prise de commandes et services en salle
educations:
title: Formations
tb: Mention Très Bien
b: Mention Bien
license: Licence de Mathématiques
baccalaureate: Baccalauréat Général spécialités Mathématiques et Physique-Chimie
dnb: Diplôme National du Brevet
selftaught:
title: Apprentissage en autodidacte
content: Apprentissage de langages de programmation (TypeScript, Rust, Java, Python...) et de technologies

35
package.json Normal file
View File

@@ -0,0 +1,35 @@
{
"private": true,
"scripts": {
"dev": "vite --port 3333 --open --host",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --ext=.ts,.vue",
"test": "vitest"
},
"dependencies": {
"@vueuse/core": "^7.7.0",
"@vueuse/head": "^0.7.5",
"sass": "^1.49.9",
"vue": "^3.2.31",
"vue-i18n": "^9.1.9",
"vue-router": "^4.0.12",
"windicss": "^3.5.0"
},
"devDependencies": {
"@antfu/eslint-config": "^0.16.1",
"@intlify/vite-plugin-vue-i18n": "^3.3.1",
"@types/node": "^17.0.21",
"@vitejs/plugin-vue": "^2.2.2",
"@vue/test-utils": "^2.0.0-rc.18",
"eslint": "^8.10.0",
"jsdom": "^19.0.0",
"typescript": "^4.5.5",
"unplugin-auto-import": "^0.6.1",
"unplugin-vue-components": "^0.17.11",
"vite": "^2.8.4",
"vite-plugin-pages": "^0.21.0",
"vite-plugin-windicss": "^1.8.1",
"vitest": "^0.5.8"
}
}

9
public/favicon.svg Normal file
View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style>
path { fill: #222; }
@media (prefers-color-scheme: dark) {
path { fill: #ffffff; }
}
</style>
<path d="M27.562 26L17.17 8.928l2.366-3.888L17.828 4L16 7.005L14.17 4l-1.708 1.04l2.366 3.888L4.438 26H2v2h28v-2zM16 10.85L25.22 26H17v-8h-2v8H6.78z" />
</svg>

After

Width:  |  Height:  |  Size: 347 B

2
public/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
User-agent: *
Allow: /

31
src/App.vue Normal file
View File

@@ -0,0 +1,31 @@
<script setup>
import { useHead } from '@vueuse/head'
useHead({
title: 'Arthur Danjou - My Résumé',
meta: [
{ name: 'description', content: 'See my technology resume' },
],
})
</script>
<template>
<div class="px-4 lg:px-32 dark:text-white lg:flex py-8 lg:py-16">
<Menu />
<section class="lg:w-1/4 flex flex-col">
<BackToSite />
<Header />
<SocialList />
</section>
<section class="lg:w-3/4 mt-4 lg:mt-0">
<AboutSection />
<WorkSection />
<EducationSection />
<StackSection />
<ProjectSection />
<InterestSection />
<LanguageSection />
<Footer />
</section>
</div>
</template>

View File

@@ -0,0 +1,16 @@
<template>
<SectionTitle title="about.title" />
<SectionPart>
<p class="text-justify leading-6">
{{ t('about.first') }}
<br><br>
{{ t('about.second') }}
</p>
</SectionPart>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,13 @@
<template>
<a href="https://arthurdanjou.fr" target="_blank" class="flex items-center mb-4 text-gray-700 dark:text-gray-300 text-sm">
<div class="group cursor-pointer flex items-center">
<LeftArrowIcon class="mr-2 group-hover:-translate-x-2 duration-300 transform" /> {{ t('back') }}
</div>
</a>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,50 @@
<template>
<div>
<div>
<h1 class="text-lg leading-5">
<strong>{{ t(title) }}</strong>, {{ location }}
</h1>
<h3 class="my-1 text-sm text-gray-500 dark:text-gray-400">
{{ t('date.from') }} {{ getBeginDate }} {{ t('date.to') }} {{ getEndDate }}
</h3>
</div>
<p class="text-justify text-md leading-5 dark:text-gray-300">
<slot />
</p>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const props = defineProps({
title: {
type: String,
default: 'Title',
},
location: {
type: String,
default: 'Location',
},
beginDate: {
type: String,
required: true,
},
endDate: {
type: String,
required: true,
},
})
const getEndDate = computed(() => {
return props.endDate === 'Today'
? t('date.today')
: `${t(`months.${props.endDate.split('/')[0]}`)} ${props.endDate.split('/')[1]}`
})
const getBeginDate = computed(() => {
return `${t(`months.${props.beginDate.split('/')[0]}`)} ${props.beginDate.split('/')[1]}`
})
</script>

View File

@@ -0,0 +1,41 @@
<template>
<SectionTitle title="educations.title" />
<SectionPart class="space-y-4">
<Education
title="educations.license"
location="Faculté des Sciences de l'Université Paris-Saclay, Orsay (France)"
begin-date="08/2021"
end-date="Today"
/>
<Education
title="educations.selftaught.title"
location="Remote"
begin-date="08/2021"
end-date="Today"
>
{{ t('educations.selftaught.content') }}
</Education>
<Education
title="educations.baccalaureate"
location="Lycée La Salle Passy-Buzenval, Rueil-Malmaison (France)"
begin-date="09/2020"
end-date="09/2021"
>
{{ t('educations.b') }}
</Education>
<Education
title="educations.dnb"
location="Collège La Salle Passy-Buzenval, Rueil-Malmaison (France)"
begin-date="09/2017"
end-date="09/2018"
>
{{ t('educations.tb') }}
</Education>
</SectionPart>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

28
src/components/Footer.vue Normal file
View File

@@ -0,0 +1,28 @@
<template>
<div class="mt-8 text-center">
<a class="leading-5 font-bold border-b-2 hover:(border-gray-700 dark:border-white) border-gray-300 dark:border-gray-700 dark:border-gray-800 duration-300 cursor-pointer">
{{ t('footer.pdf') }}
</a>
<p class="text-xs text-gray-700 dark:text-gray-300 mt-4">
{{ t('footer.updated', {date: updated}) }}
</p>
<p class="text-xs text-gray-700 dark:text-gray-300 mt-1">
{{ t('footer.copyright', {year}) }}
</p>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
const year = computed(() => {
return new Date().getFullYear()
})
const updated = computed(() => {
return locale.value === 'fr'
? '28 Février 2022 à 16h22'
: 'February 28th 2022 at 16:22'
})
</script>

19
src/components/Header.vue Normal file
View File

@@ -0,0 +1,19 @@
<template>
<div class="my-4 text-center sm:text-left">
<h1 class="font-black text-2xl">
Arthur DANJOU
</h1>
<h2 class="text-lg text-gray-600 dark:text-gray-400">
{{ t('header.job') }}
</h2>
<h3 class="text-sm text-gray-500 dark:text-gray-300 mt-2">
Paris, France
</h3>
</div>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,14 @@
<template>
<SectionTitle title="interests.title" />
<SectionPart>
<p class="text-justify">
{{ t('interests.content') }}
</p>
</SectionPart>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,12 @@
<template>
<SectionTitle title="languages.title" />
<SectionPart>
<p v-html="t('languages.content')" />
</SectionPart>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

57
src/components/Menu.vue Normal file
View File

@@ -0,0 +1,57 @@
<template>
<div class="fixed top-2 right-1 sm:(top-4 right-4) grid grid-rows-2 gap-y-2 text-center">
<div
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-800 duration-300 cursor-pointer rounded-full"
@click.prevent="toggleDark"
>
<SunIcon v-if="isDark" />
<MoonIcon v-else />
</div>
<div
class="p-1 hover:bg-gray-300 dark:hover:bg-gray-800 duration-300 cursor-pointer rounded-full transform"
:class="{'rotate-180': scrollPosition > 100}"
@click.prevent="teleport"
>
<DownArrowIcon />
</div>
<div @click.prevent="switchLanguage">
<div v-if="locale === 'fr'" class="text-right text-xl px-1 hover:bg-gray-300 dark:hover:bg-gray-800 duration-300 cursor-pointer rounded-full">
🇬🇧
</div>
<div v-else class="text-right text-xl px-1 hover:bg-gray-300 dark:hover:bg-gray-800 duration-300 cursor-pointer rounded-full">
🇫🇷
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { isDark, toggleDark } from '~/composables'
const { locale } = useI18n()
const switchLanguage = () => {
locale.value = locale.value === 'fr' ? 'en' : 'fr'
}
const scrollPosition = ref(0)
const teleport = () => {
window.scroll({
behavior: 'smooth',
top: scrollPosition.value > 100 ? 0 : document.body.scrollHeight,
})
}
const updateScroll = () => {
scrollPosition.value = window.scrollY
}
onMounted(() => {
window.addEventListener('scroll', updateScroll)
})
onUnmounted(() => {
window.removeEventListener('scroll', updateScroll)
})
</script>

View File

@@ -0,0 +1,35 @@
<template>
<a
class="w-full h-full"
:href="url"
target="_blank"
>
<div class="w-full h-full p-2 border-2 rounded-lg border-white hover:border-gray-300 duration-500 cursor-pointer">
<h1 class="font-bold">
{{ title }}
</h1>
<h2 class="text-gray-700 text-justify dark:text-gray-200">
{{ t(description) }}
</h2>
</div>
</a>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
defineProps({
title: {
type: String,
},
url: {
type: String,
},
description: {
type: String,
},
})
</script>

View File

@@ -0,0 +1,40 @@
<template>
<SectionTitle title="projects.title" />
<SectionPart>
<div class="grid gris-cols-1 sm:grid-cols-2 gap-x-8 gap-y-4 mb-4">
<Project
title="Ares"
description="projects.ares"
url="https://arthurdanjou.fr"
/>
<Project
title="Athena"
description="projects.athena"
url="https://api.arthurdanjou.fr"
/>
<Project
title="LinkyJs"
description="projects.linkyjs"
/>
<Project
title="Slidev"
description="projects.slidev"
/>
</div>
<div class="flex justify-center sm:justify-start">
<a
href="https://arthurdanjou.fr/projects"
target="_blank"
class="leading-5 font-bold border-b-2 hover:(border-gray-700 dark:border-white) border-gray-300 dark:border-gray-700 dark:border-gray-800 duration-300 cursor-pointer"
>
{{ t('projects.more') }}
</a>
</div>
</SectionPart>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,5 @@
<template>
<div class="p-6">
<slot />
</div>
</template>

View File

@@ -0,0 +1,19 @@
<template>
<h3>
<span class="pl-1 pr-4 title py-1 font-bold text-xl relative bg-black text-white dark:(bg-white text-black)">{{ t(title) }}</span>
</h3>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
defineProps({
title: {
default: 'Title',
required: true,
type: String,
},
})
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,41 @@
<template>
<div class="flex justify-center sm:justify-start">
<div class="flex space-x-3 items-center">
<a
class="hover:bg-gray-300 dark:hover:bg-gray-800 p-1 rounded-full duration-300"
href="mailto:contact@arthurdanjou.fr"
target="_blank"
>
<MailIcon />
</a>
<a
class="hover:bg-gray-300 dark:hover:bg-gray-800 p-1 rounded-full duration-300"
href="https://github.com/arthurdanjou"
target="_blank"
>
<GithubIcon />
</a>
<a
class="hover:bg-gray-300 dark:hover:bg-gray-800 p-1 rounded-full duration-300"
href="https://twitter.com/arthurdanj"
target="_blank"
>
<TwitterIcon />
</a>
<a
class="hover:bg-gray-300 dark:hover:bg-gray-800 p-1 rounded-full duration-300"
href="https://www.linkedin.com/in/arthurdanjou"
target="_blank"
>
<LinkedInIcon />
</a>
<a
class="hover:bg-gray-300 dark:hover:bg-gray-800 p-1.5 rounded-full duration-300"
href="https://www.instagram.com/arthur.dnj"
target="_blank"
>
<InstagramIcon />
</a>
</div>
</div>
</template>

22
src/components/Stack.vue Normal file
View File

@@ -0,0 +1,22 @@
<template>
<div class="mb-2">
<strong class="mr-2">{{ t(title) }}</strong><span class="dark:text-gray-200">{{ content }}</span>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
defineProps({
title: {
default: 'Title',
required: true,
},
content: {
default: 'Content',
required: true,
},
})
</script>

View File

@@ -0,0 +1,9 @@
<template>
<SectionTitle title="stacks.title" />
<SectionPart>
<Stack title="stacks.languages" content="TypeScript, JavaScript, Python, Java, Rust" />
<Stack title="stacks.frontend" content="VueJs, NuxtJs, WindiCss, Sass, TauriApp, ViteJs" />
<Stack title="stacks.backend" content="AdonisJs, MariaDB, Redis, RabbitMQ" />
<Stack title="stacks.devops" content="Git, Docker, CI/CD, Traefik" />
</SectionPart>
</template>

View File

@@ -0,0 +1,66 @@
<template>
<div>
<div>
<h1 v-if="url" class="text-lg">
<a
:href="url"
target="_blank"
class="font-bold border-b-2 hover:(border-gray-700 dark:border-white) border-gray-300 dark:border-gray-600 dark:border-gray-800 duration-300 cursor-pointer"
>
{{ company }}
</a> - <span class="text-gray-700 dark:text-gray-300">{{ t(title) }}</span>
</h1>
<h1 v-else class="text-lg">
<strong>{{ company }}</strong> - <span class="text-gray-700 dark:text-gray-300">{{ t(title) }}</span>
</h1>
<h3 v-if="getBeginDate === getEndDate" class="text-sm text-gray-500 dark:text-gray-400 my-1">
{{ t('date.in') }} {{ getEndDate }} <span class="mx-2">|</span> {{ location }}
</h3>
<h3 v-else class="text-sm text-gray-500 dark:text-gray-400 my-1">
{{ t('date.from') }} {{ getBeginDate }} {{ t('date.to') }} {{ getEndDate }} <span class="mx-2">|</span> {{ location }}
</h3>
</div>
<p class="text-justify text-md leading-5 dark:text-gray-300">
<slot />
</p>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const props = defineProps({
title: {
type: String,
},
company: {
type: String,
},
location: {
type: String,
},
beginDate: {
type: String,
required: true,
},
endDate: {
type: String,
required: true,
},
url: {
type: String,
},
})
const getEndDate = computed(() => {
return props.endDate === 'Today'
? t('date.today')
: `${t(`months.${props.endDate.split('/')[0]}`)} ${props.endDate.split('/')[1]}`
})
const getBeginDate = computed(() => {
return `${t(`months.${props.beginDate.split('/')[0]}`)} ${props.beginDate.split('/')[1]}`
})
</script>

View File

@@ -0,0 +1,50 @@
<template>
<SectionTitle title="works.title" />
<SectionPart class="space-y-4">
<WorkExperience
title="works.autoentrepreneur.title"
company="ArtDanjProduction"
begin-date="09/2015"
end-date="Today"
location="Rueil-Malmaison, France"
url="https://arthurdanjou.fr"
>
{{ t('works.autoentrepreneur.content') }}
</WorkExperience>
<WorkExperience
title="works.erisium.title"
company="Erisium"
begin-date="02/2019"
end-date="11/2020"
location="Remote"
url="https://erisium.com"
>
{{ t('works.erisium.content') }}
</WorkExperience>
<WorkExperience
title="works.idemia.title"
company="Idemia"
begin-date="06/2019"
end-date="06/2019"
location="Courbevoie, France"
url="https://idemia.com"
>
{{ t('works.idemia.content') }}
</WorkExperience>
<WorkExperience
title="works.lsam.title"
company="La Salle à Manger"
begin-date="04/2018"
end-date="04/2018"
location="Boulogne-Billancourt, France"
>
{{ t('works.lsam.content') }}
</WorkExperience>
</SectionPart>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg width="1.3em" height="1.3em" viewBox="0 0 256 256" focusable="false">
<path
d="M208.485 152.485l-72 72a12 12 0 0 1-16.97 0l-72-72a12 12 0 0 1 16.97-16.97L116 187.029V40a12 12 0 0 1 24 0v147.03l51.515-51.515a12 12 0 0 1 16.97 16.97z"
fill="currentColor"
/>
</svg>
</template>
<script>
export default {
name: 'DownArrowIcon',
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg width="1.3em" height="1.3em" viewBox="0 0 24 24" focusable="false">
<path
fill="currentColor"
d="M10.07 20.503a1 1 0 0 0-1.18-.983c-1.31.24-2.963.276-3.402-.958a5.708 5.708 0 0 0-1.837-2.415a1.2 1.2 0 0 1-.167-.11a1 1 0 0 0-.93-.645h-.005a1 1 0 0 0-1 .995c-.004.815.81 1.338 1.141 1.514a4.44 4.44 0 0 1 .924 1.36c.365 1.023 1.423 2.576 4.466 2.376l.003.098l.004.268a1 1 0 0 0 2 0l-.005-.318c-.005-.19-.012-.464-.012-1.182ZM20.737 5.377a5.39 5.39 0 0 0 .09-.42a6.278 6.278 0 0 0-.408-3.293a1.002 1.002 0 0 0-.615-.58c-.356-.12-1.67-.357-4.184 1.25a13.87 13.87 0 0 0-6.354 0C6.762.75 5.455.966 5.102 1.079a.997.997 0 0 0-.631.584a6.3 6.3 0 0 0-.404 3.357c.025.127.051.246.079.354a6.27 6.27 0 0 0-1.256 3.83a8.422 8.422 0 0 0 .043.921c.334 4.603 3.334 5.984 5.424 6.459a4.591 4.591 0 0 0-.118.4a1 1 0 0 0 1.942.479a1.678 1.678 0 0 1 .468-.878a1 1 0 0 0-.546-1.745c-3.454-.395-4.954-1.802-5.18-4.899a6.61 6.61 0 0 1-.033-.738a4.258 4.258 0 0 1 .92-2.713a3.022 3.022 0 0 1 .195-.231a1 1 0 0 0 .188-1.025a3.388 3.388 0 0 1-.155-.555a4.094 4.094 0 0 1 .079-1.616a7.543 7.543 0 0 1 2.415 1.18a1.009 1.009 0 0 0 .827.133a11.777 11.777 0 0 1 6.173.001a1.005 1.005 0 0 0 .83-.138a7.572 7.572 0 0 1 2.406-1.19a4.04 4.04 0 0 1 .087 1.578a3.205 3.205 0 0 1-.169.607a1 1 0 0 0 .188 1.025c.078.087.155.18.224.268A4.122 4.122 0 0 1 20 9.203a7.039 7.039 0 0 1-.038.777c-.22 3.056-1.725 4.464-5.195 4.86a1 1 0 0 0-.546 1.746a1.63 1.63 0 0 1 .466.908a3.06 3.06 0 0 1 .093.82v2.333c-.01.648-.01 1.133-.01 1.356a1 1 0 1 0 2 0c0-.217 0-.692.01-1.34v-2.35a4.881 4.881 0 0 0-.155-1.311a4.256 4.256 0 0 0-.116-.416a6.513 6.513 0 0 0 5.445-6.424A8.697 8.697 0 0 0 22 9.203a6.13 6.13 0 0 0-1.263-3.826Z"
/>
</svg>
</template>
<script>
export default {
name: 'GithubIcon',
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg width="1.2em" height="1.2em" viewBox="0 0 16 16" focusable="false">
<path
fill="currentColor"
d="M8 0C5.829 0 5.556.01 4.703.048C3.85.088 3.269.222 2.76.42a3.917 3.917 0 0 0-1.417.923A3.927 3.927 0 0 0 .42 2.76C.222 3.268.087 3.85.048 4.7C.01 5.555 0 5.827 0 8.001c0 2.172.01 2.444.048 3.297c.04.852.174 1.433.372 1.942c.205.526.478.972.923 1.417c.444.445.89.719 1.416.923c.51.198 1.09.333 1.942.372C5.555 15.99 5.827 16 8 16s2.444-.01 3.298-.048c.851-.04 1.434-.174 1.943-.372a3.916 3.916 0 0 0 1.416-.923c.445-.445.718-.891.923-1.417c.197-.509.332-1.09.372-1.942C15.99 10.445 16 10.173 16 8s-.01-2.445-.048-3.299c-.04-.851-.175-1.433-.372-1.941a3.926 3.926 0 0 0-.923-1.417A3.911 3.911 0 0 0 13.24.42c-.51-.198-1.092-.333-1.943-.372C10.443.01 10.172 0 7.998 0h.003zm-.717 1.442h.718c2.136 0 2.389.007 3.232.046c.78.035 1.204.166 1.486.275c.373.145.64.319.92.599c.28.28.453.546.598.92c.11.281.24.705.275 1.485c.039.843.047 1.096.047 3.231s-.008 2.389-.047 3.232c-.035.78-.166 1.203-.275 1.485a2.47 2.47 0 0 1-.599.919c-.28.28-.546.453-.92.598c-.28.11-.704.24-1.485.276c-.843.038-1.096.047-3.232.047s-2.39-.009-3.233-.047c-.78-.036-1.203-.166-1.485-.276a2.478 2.478 0 0 1-.92-.598a2.48 2.48 0 0 1-.6-.92c-.109-.281-.24-.705-.275-1.485c-.038-.843-.046-1.096-.046-3.233c0-2.136.008-2.388.046-3.231c.036-.78.166-1.204.276-1.486c.145-.373.319-.64.599-.92c.28-.28.546-.453.92-.598c.282-.11.705-.24 1.485-.276c.738-.034 1.024-.044 2.515-.045v.002zm4.988 1.328a.96.96 0 1 0 0 1.92a.96.96 0 0 0 0-1.92zm-4.27 1.122a4.109 4.109 0 1 0 0 8.217a4.109 4.109 0 0 0 0-8.217zm0 1.441a2.667 2.667 0 1 1 0 5.334a2.667 2.667 0 0 1 0-5.334z"
/>
</svg>
</template>
<script>
export default {
name: 'InstagramIcon',
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg width="1em" height="1em" viewBox="0 0 256 256" focusable="false">
<path
d="M228 128a12 12 0 0 1-12 12H68.97l51.515 51.515a12 12 0 0 1-16.97 16.97l-72-72a12 12 0 0 1 0-16.97l72-72a12 12 0 0 1 16.97 16.97L68.971 116H216a12 12 0 0 1 12 12z"
fill="currentColor"
/>
</svg>
</template>
<script>
export default {
name: 'LeftArrowIcon',
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg width="1.5em" height="1.5em" viewBox="0 0 24 24" focusable="false">
<path
fill="currentColor"
d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14m-.5 15.5v-5.3a3.26 3.26 0 0 0-3.26-3.26c-.85 0-1.84.52-2.32 1.3v-1.11h-2.79v8.37h2.79v-4.93c0-.77.62-1.4 1.39-1.4a1.4 1.4 0 0 1 1.4 1.4v4.93h2.79M6.88 8.56a1.68 1.68 0 0 0 1.68-1.68c0-.93-.75-1.69-1.68-1.69a1.69 1.69 0 0 0-1.69 1.69c0 .93.76 1.68 1.69 1.68m1.39 9.94v-8.37H5.5v8.37h2.77Z"
/>
</svg>
</template>
<script>
export default {
name: 'LinkedInIcon',
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg width="1.3em" height="1.3em" viewBox="0 0 24 24" focusable="false">
<path
fill="currentColor"
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10h5v-2h-5c-4.34 0-8-3.66-8-8s3.66-8 8-8s8 3.66 8 8v1.43c0 .79-.71 1.57-1.5 1.57s-1.5-.78-1.5-1.57V12c0-2.76-2.24-5-5-5s-5 2.24-5 5s2.24 5 5 5c1.38 0 2.64-.56 3.54-1.47c.65.89 1.77 1.47 2.96 1.47c1.97 0 3.5-1.6 3.5-3.57V12c0-5.52-4.48-10-10-10zm0 13c-1.66 0-3-1.34-3-3s1.34-3 3-3s3 1.34 3 3s-1.34 3-3 3z"
/>
</svg>
</template>
<script>
export default {
name: 'MailIcon',
}
</script>

View File

@@ -0,0 +1,13 @@
<template>
<svg width="1.3em" height="1.3em" viewBox="0 0 256 256" focusable="false">
<path
d="M228.13 149.117a12.004 12.004 0 0 0-14.962-7.952a80.032 80.032 0 0 1-98.31-98.415a12.002 12.002 0 0 0-14.919-14.917a104.014 104.014 0 1 0 128.247 128.162a12.002 12.002 0 0 0-.055-6.878zM128 208A80.01 80.01 0 0 1 88.146 58.617a103.982 103.982 0 0 0 109.237 109.237A80.31 80.31 0 0 1 128 208z" fill="currentColor"
/>
</svg>
</template>
<script>
export default {
name: 'MoonIcon',
}
</script>

View File

@@ -0,0 +1,13 @@
<template>
<svg width="1.3em" height="1.3em" viewBox="0 0 256 256" focusable="false">
<path
d="M128 56a72 72 0 1 0 72 72a72.081 72.081 0 0 0-72-72zm0 120a48 48 0 1 1 48-48a48.054 48.054 0 0 1-48 48zM116 28v-8a12 12 0 0 1 24 0v8a12 12 0 0 1-24 0zm74.225 37.774a12 12 0 0 1 0-16.97l5.658-5.657a12 12 0 1 1 16.97 16.971l-5.658 5.657a12 12 0 0 1-16.97 0zM248 128a12 12 0 0 1-12 12h-8a12 12 0 0 1 0-24h8a12 12 0 0 1 12 12zm-35.147 67.882a12 12 0 0 1-16.97 16.971l-5.658-5.657a12 12 0 1 1 16.97-16.97zM140 228v8a12 12 0 0 1-24 0v-8a12 12 0 0 1 24 0zm-74.225-37.775a12 12 0 0 1 0 16.97l-5.657 5.658a12 12 0 0 1-16.971-16.97l5.657-5.658a12 12 0 0 1 16.97 0zM40 128a12 12 0 0 1-12 12h-8a12 12 0 0 1 0-24h8a12 12 0 0 1 12 12zm3.147-67.882a12 12 0 1 1 16.97-16.971l5.657 5.657a12 12 0 1 1-16.97 16.97z" fill="currentColor"
/>
</svg>
</template>
<script>
export default {
name: 'SunIcon',
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg width="1.5em" height="1.5em" viewBox="0 0 24 24">
<path
fill="currentColor"
d="M15.3 5.55a2.9 2.9 0 0 0-2.9 2.847l-.028 1.575a.6.6 0 0 1-.68.583l-1.561-.212c-2.054-.28-4.022-1.226-5.91-2.799c-.598 3.31.57 5.603 3.383 7.372l1.747 1.098a.6.6 0 0 1 .034.993L7.793 18.17c.947.059 1.846.017 2.592-.131c4.718-.942 7.855-4.492 7.855-10.348c0-.478-1.012-2.141-2.94-2.141zm-4.9 2.81a4.9 4.9 0 0 1 8.385-3.355c.711-.005 1.316.175 2.669-.645c-.335 1.64-.5 2.352-1.214 3.331c0 7.642-4.697 11.358-9.463 12.309c-3.268.652-8.02-.419-9.382-1.841c.694-.054 3.514-.357 5.144-1.55C5.16 15.7-.329 12.47 3.278 3.786c1.693 1.977 3.41 3.323 5.15 4.037c1.158.475 1.442.465 1.973.538z"
/>
</svg>
</template>
<script>
export default {
name: 'RiTwitterLine',
}
</script>

2
src/composables/dark.ts Normal file
View File

@@ -0,0 +1,2 @@
export const isDark = useDark()
export const toggleDark = useToggle(isDark)

1
src/composables/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from './dark'

43
src/main.ts Normal file
View File

@@ -0,0 +1,43 @@
// register vue composition api globally
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { createHead } from '@vueuse/head'
import { createI18n } from 'vue-i18n'
import routes from 'virtual:generated-pages'
import App from './App.vue'
import 'virtual:windi-base.css'
import 'virtual:windi-components.css'
// your custom styles here
import './styles/main.css'
// windicss utilities should be the last style import
import 'virtual:windi-utilities.css'
// windicss devtools support (dev only)
import 'virtual:windi-devtools'
const app = createApp(App)
const router = createRouter({
history: createWebHistory(),
routes,
})
const head = createHead()
const messages = Object.fromEntries(
Object.entries(
import.meta.globEager('../locales/*.y(a)?ml'))
.map(([key, value]) => {
const yaml = key.endsWith('.yaml')
return [key.slice(11, yaml ? -5 : -4), value.default]
}),
)
const i18n = createI18n({
legacy: false,
locale: 'en',
messages,
})
app.use(i18n)
app.use(router)
app.use(head)
app.mount('#app')

11
src/styles/main.css Executable file
View File

@@ -0,0 +1,11 @@
html,
body,
#app {
height: 100%;
margin: 0;
padding: 0;
}
html.dark {
background: #121212;
}

View File

@@ -0,0 +1,3 @@
// Vitest Snapshot v1
exports[`Counter.vue > should render 1`] = `"<div>10 <button class=\\"inc\\"> + </button><button class=\\"dec\\"> - </button></div>"`;

5
test/basic.test.ts Normal file
View File

@@ -0,0 +1,5 @@
describe('Hi', () => {
it('should works', () => {
expect(1 + 1).toEqual(2)
})
})

20
test/component.test.ts Normal file
View File

@@ -0,0 +1,20 @@
import { mount } from '@vue/test-utils'
describe('Counter.vue', () => {
it('should render', () => {
const wrapper = mount(Counter, { props: { initial: 10 } })
expect(wrapper.text()).toContain('10')
expect(wrapper.html()).toMatchSnapshot()
})
it('should be interactive', async() => {
const wrapper = mount(Counter, { props: { initial: 0 } })
expect(wrapper.text()).toContain('0')
expect(wrapper.find('.inc').exists()).toBe(true)
await wrapper.get('button').trigger('click')
expect(wrapper.text()).toContain('1')
})
})

25
tsconfig.json Normal file
View File

@@ -0,0 +1,25 @@
{
"compilerOptions": {
"baseUrl": ".",
"module": "ESNext",
"target": "es2016",
"lib": ["DOM", "ESNext"],
"strict": true,
"esModuleInterop": true,
"incremental": false,
"skipLibCheck": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"noUnusedLocals": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"types": [
"vite/client",
"vite-plugin-pages/client"
],
"paths": {
"~/*": ["src/*"]
}
},
"exclude": ["dist", "node_modules"]
}

66
vite.config.ts Normal file
View File

@@ -0,0 +1,66 @@
/// <reference types="vitest" />
import path from 'path'
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import Pages from 'vite-plugin-pages'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import WindiCSS from 'vite-plugin-windicss'
import VueI18n from '@intlify/vite-plugin-vue-i18n'
export default defineConfig({
resolve: {
alias: {
'~/': `${path.resolve(__dirname, 'src')}/`,
},
},
plugins: [
Vue(),
// https://github.com/hannoeru/vite-plugin-pages
Pages(),
WindiCSS(),
// https://github.com/antfu/unplugin-auto-import
AutoImport({
imports: [
'vue',
'vue-router',
'@vueuse/core',
'@vueuse/head',
'vitest',
],
dts: true,
}),
// https://github.com/antfu/vite-plugin-components
Components({
dts: true,
}),
VueI18n({
runtimeOnly: true,
compositionOnly: true,
include: [path.resolve(__dirname, 'locales/**')],
}),
],
// https://github.com/vitest-dev/vitest
test: {
environment: 'jsdom',
},
optimizeDeps: {
include: [
'vue',
'vue-router',
'@vueuse/core',
'@vueuse/head',
],
exclude: [
'vue-demi',
],
},
})

5
windi.config.ts Normal file
View File

@@ -0,0 +1,5 @@
import { defineConfig } from 'windicss/helpers'
export default defineConfig({
darkMode: 'class',
})

3235
yarn.lock Normal file

File diff suppressed because it is too large Load Diff