Migrate to forgejo

This commit is contained in:
Morg 2025-05-25 10:34:01 +02:00
commit af654ff353
50 changed files with 8357 additions and 0 deletions

6
.editorconfig Normal file
View file

@ -0,0 +1,6 @@
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}]
charset = utf-8
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true

28
.gitignore vendored Normal file
View file

@ -0,0 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

10
.prettierrc.json Normal file
View file

@ -0,0 +1,10 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": true,
"useTabs": true,
"tabWidth": 4,
"singleQuote": false,
"experimentalTernaries": true,
"singleAttributePerLine": true,
"endOfLine": "lf"
}

8
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,8 @@
{
"recommendations": [
"Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

6
README.md Normal file
View file

@ -0,0 +1,6 @@
## My Resume
Homepage: https://morgane.de-carpentier.fr
This repo contains the source files of my online resume.
If you're a recruiter: Hi, I hope this will convince you.
Else, I don't know why you are here but have a nice day !

2
env.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
/// <reference types="vite/client" />
declare module "vue-i18n"

27
eslint.config.js Normal file
View file

@ -0,0 +1,27 @@
import pluginVue from "eslint-plugin-vue";
import {
defineConfigWithVueTs,
vueTsConfigs,
} from "@vue/eslint-config-typescript";
import oxlint from "eslint-plugin-oxlint";
import skipFormatting from "@vue/eslint-config-prettier/skip-formatting";
export default [
{
name: "app/files-to-lint",
files: ["**/*.{ts,mts,tsx,vue}"],
},
{
name: "app/files-to-ignore",
ignores: ["**/dist/**", "**/dist-ssr/**", "**/coverage/**"],
},
...defineConfigWithVueTs(
pluginVue.configs["flat/essential"],
vueTsConfigs.recommended,
),
...oxlint.configs["flat/recommended"],
skipFormatting,
];

17
index.html Normal file
View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link
rel="preload"
as="image"
href='/avatar.webp'>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Morgane de Carpentier - Conceptrice Dévelopeuse FullStack sur Strasbourg.">
<title>Morgane de Carpentier</title>
</head>
<body class="text-sm min-h-screen bg-[#caca] print:min-h-0" id="app">
<script type="module" src="/src/main.ts"></script>
</body>
</html>

6335
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

43
package.json Normal file
View file

@ -0,0 +1,43 @@
{
"name": "my-resume",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "run-p type-check build-only",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"lint:oxlint": "oxlint . --fix -D correctness --ignore-path .gitignore",
"lint:eslint": "eslint . --fix",
"lint": "run-s lint:*",
"format": "prettier --write src/"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.2",
"vue": "^3.3.4",
"vue-i18n": "^11.1.4"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.7",
"@tsconfig/node22": "^22.0.0",
"@types/node": "^22.15.21",
"@vitejs/plugin-vue": "^5.2.4",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.5.0",
"@vue/tsconfig": "^0.7.0",
"eslint": "^9.27.0",
"eslint-plugin-oxlint": "^0.16.12",
"eslint-plugin-vue": "^10.1.0",
"npm-run-all": "^4.1.5",
"oxlint": "^0.16.12",
"postcss": "^8.4.29",
"prettier": "^3.0.0",
"tailwindcss": "^4.1.7",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vite-bundle-analyzer": "^0.21.0",
"vue-tsc": "^2.2.10"
}
}

5
postcss.config.cjs Normal file
View file

@ -0,0 +1,5 @@
module.exports = {
plugins: {
'@tailwindcss/postcss': {},
},
}

BIN
public/avatar.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

178
public/en.svg Normal file
View file

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
<!-- /Creative Commons Public Domain -->
<!--
-->
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:ns1="http://sozi.baierouge.fr"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="svg1"
inkscape:version="0.46"
viewBox="0 0 1000 500"
sodipodi:version="0.32"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
sodipodi:docname="united_kingdom.svg"
>
<sodipodi:namedview
id="base"
inkscape:window-x="353"
inkscape:window-y="389"
inkscape:window-height="704"
inkscape:zoom="0.544"
showgrid="false"
inkscape:current-layer="svg1"
inkscape:cx="500"
inkscape:cy="250"
inkscape:window-width="952"
/>
<g
id="g578"
transform="scale(16.667)"
>
<rect
id="rect124"
style="stroke-width:1pt;fill:#000066"
height="30"
width="60"
y="0"
x="0"
/>
<g
id="g584"
>
<path
id="path146"
style="stroke-width:1pt;fill:#ffffff"
d="m0 0v3.3541l53.292 26.646h6.708v-3.354l-53.292-26.646h-6.708zm60 0v3.354l-53.292 26.646h-6.708v-3.354l53.292-26.646h6.708z"
/>
<path
id="path136"
style="stroke-width:1pt;fill:#ffffff"
d="m25 0v30h10v-30h-10zm-25 10v10h60v-10h-60z"
/>
<path
id="path141"
style="stroke-width:1pt;fill:#cc0000"
d="m0 12v6h60v-6h-60zm27-12v30h6v-30h-6z"
/>
<path
id="path150"
style="stroke-width:1pt;fill:#cc0000"
d="m0 30l20-10h4.472l-20 10h-4.472zm0-30l20 10h-4.472l-15.528-7.7639v-2.2361zm35.528 10l20-10h4.472l-20 10h-4.472zm24.472 20l-20-10h4.472l15.528 7.764v2.236z"
/>
</g
>
</g
>
<metadata
>
<rdf:RDF
>
<cc:Work
>
<dc:format
>image/svg+xml</dc:format
>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
/>
<dc:publisher
>
<cc:Agent
rdf:about="http://openclipart.org/"
>
<dc:title
>Openclipart</dc:title
>
</cc:Agent
>
</dc:publisher
>
<dc:title
>Flag of the United Kingdom</dc:title
>
<dc:date
>2008-07-12T12:27:21</dc:date
>
<dc:description
/>
<dc:source
>https://openclipart.org/detail/17754/flag-of-the-united-kingdom-by-tobias</dc:source
>
<dc:creator
>
<cc:Agent
>
<dc:title
>tobias</dc:title
>
</cc:Agent
>
</dc:creator
>
<dc:subject
>
<rdf:Bag
>
<rdf:li
>country</rdf:li
>
<rdf:li
>europe</rdf:li
>
<rdf:li
>european union</rdf:li
>
<rdf:li
>flag</rdf:li
>
<rdf:li
>nation</rdf:li
>
<rdf:li
>sign</rdf:li
>
<rdf:li
>united nations member</rdf:li
>
<rdf:li
>unitedkingdom</rdf:li
>
</rdf:Bag
>
</dc:subject
>
</cc:Work
>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:License
>
</rdf:RDF
>
</metadata
>
</svg
>

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

163
public/fr.svg Normal file
View file

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:ns1="http://sozi.baierouge.fr"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="svg378"
inkscape:version="0.46"
viewBox="0 0 1063 708.66"
sodipodi:version="0.32"
version="1"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
y="0"
x="0"
sodipodi:docname="france.svg"
sodipodi:docbase="/home/tobias/Desktop/Flags"
>
<sodipodi:namedview
id="base"
inkscape:window-x="69"
inkscape:window-y="25"
inkscape:window-height="704"
inkscape:zoom="0.51176399"
showgrid="false"
inkscape:current-layer="svg378"
inkscape:cx="531.495"
inkscape:cy="354.33051"
inkscape:window-width="952"
/>
<rect
id="rect171"
style="fill-rule:evenodd;stroke-width:1pt;fill:#ffffff"
height="708.66"
width="1063"
y="0"
x="0"
/>
<rect
id="rect403"
style="fill-rule:evenodd;stroke-width:1pt;fill:#00267f"
height="708.66"
width="354.33"
y="0"
x="0"
/>
<rect
id="rect135"
style="fill-rule:evenodd;stroke-width:1pt;fill:#f31830"
width="354.33"
y="0"
x="708.66"
height="708.66"
sodipodi:fill-cmyk="(0 0.9 0.8 0.05)"
/>
<metadata
>
<rdf:RDF
>
<cc:Work
>
<dc:format
>image/svg+xml</dc:format
>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
/>
<dc:publisher
>
<cc:Agent
rdf:about="http://openclipart.org/"
>
<dc:title
>Openclipart</dc:title
>
</cc:Agent
>
</dc:publisher
>
<dc:title
>Flag of France</dc:title
>
<dc:date
>2008-07-12T11:19:23</dc:date
>
<dc:description
/>
<dc:source
>https://openclipart.org/detail/17736/flag-of-france-by-tobias</dc:source
>
<dc:creator
>
<cc:Agent
>
<dc:title
>tobias</dc:title
>
</cc:Agent
>
</dc:creator
>
<dc:subject
>
<rdf:Bag
>
<rdf:li
>country</rdf:li
>
<rdf:li
>europe</rdf:li
>
<rdf:li
>european union</rdf:li
>
<rdf:li
>flag</rdf:li
>
<rdf:li
>france</rdf:li
>
<rdf:li
>nation</rdf:li
>
<rdf:li
>sign</rdf:li
>
<rdf:li
>united nations member</rdf:li
>
</rdf:Bag
>
</dc:subject
>
</cc:Work
>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:License
>
</rdf:RDF
>
</metadata
>
</svg
>

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
public/peppy.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,016 B

108
src/App.vue Normal file
View file

@ -0,0 +1,108 @@
<template>
<header
class="print:hidden sticky top-0 z-10 text-center border-b bg-[#caca]"
:aria-label="t('Menu')"
>
<button
@click="locale = 'fr'"
class="px-1 border rounded-sm hover:bg-slate-100 m-1 bg-white"
:aria-pressed="locale === 'fr'"
lang="fr"
>
<img
src="/fr.svg"
class="w-[4mm] inline"
height="15"
width="10"
:alt="t('IMG_ALT.FRENCH_FLAG')"
aria-hidden="true"
/>
<span class="sr-only"> Traduire en </span>
<span> Français </span>
</button>
<button
@click="locale = 'en'"
class="px-1 border rounded-sm hover:bg-slate-100 m-1 bg-white"
:aria-pressed="locale === 'en'"
lang="en"
>
<img
src="/en.svg"
class="w-[4mm] inline"
height="15"
width="10"
:alt="t('IMG_ALT.ENGLISH_FLAG')"
aria-hidden="true"
/>
<span class="sr-only"> Translate in </span>
<span> English </span>
</button>
<button
@click="print"
class="px-1 border rounded-sm hover:bg-slate-100 m-1 bg-white hidden md:inline"
>
<i
class="fa-solid fa-print"
aria-hidden="true"
></i>
{{ t("Imprimer") }}
</button>
</header>
<div class="md:m-4 print:m-0!">
<ResumePage />
</div>
<button
@click="doABarrelRoll"
title="Do a barrell roll!"
class="fixed right-4 bottom-4 border rounded-full hover:bg-slate-100 m-1 bg-white disabled:opacity-50 disabled:hover:bg-white print:hidden"
:disabled="rolling"
aria-hidden="true"
tabindex="-1"
>
<img
src="/peppy.webp"
class="w-[10mm] rounded-full"
width="118"
height="118"
:alt="t('IMG_ALT.DO_A_BARRELL_ROLL')"
/>
</button>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import ResumePage from "./components/ResumePage.vue";
import { useI18n } from "vue-i18n";
const { locale, t } = useI18n();
const rolling = ref(false);
watch(
() => locale.value,
() => {
document.documentElement.lang = locale.value;
},
{ immediate: true },
);
function print() {
window.print();
}
function doABarrelRoll() {
if (rolling.value) {
return;
}
rolling.value = true;
const avatar = document.getElementById("avatar")!.classList;
avatar.add("do-a-barrel-roll");
setTimeout(() => {
avatar.remove("do-a-barrel-roll");
rolling.value = false;
}, 4000);
}
</script>

View file

@ -0,0 +1,563 @@
Installing
==========
Windows
-------
In the ttf folder, double-click each font file, click “Install font”; to install all at once, select all files, right-click, and choose “Install”
OR
Use https://chocolatey.org:
choco install firacode
macOS
-----
In the downloaded TTF folder:
1. Select all font files
2. Right click and select `Open` (alternatively `Open With Font Book`)
3. Select "Install Font"
OR
Use http://brew.sh:
`brew tap homebrew/cask-fonts`
`brew install font-fira-code`
Ubuntu Zesty (17.04), Debian Stretch (9) or newer
-------------------------------------------------
1. Make sure that the `universe` (for Ubuntu) or `contrib` (for Debian) repository is enabled (see https://askubuntu.com/questions/148638/how-do-i-enable-the-universe-repository or https://wiki.debian.org/SourcesList#Component)
2. Install `fonts-firacode` package either by executing `sudo apt install fonts-firacode` in the terminal or via GUI tool (like “Software Center”)
Arch Linux
----------
Fira Code package is available in the official repository: https://www.archlinux.org/packages/community/any/ttf-fira-code/.
Variant of Fira Code package is available in the AUR: https://aur.archlinux.org/packages/otf-fira-code-git/.
Gentoo
------
emerge -av media-fonts/fira-code
Fedora
------
To install, perform the following commands:
dnf install fira-code-fonts
Solus
-----
Fira Code package is available in the official repository: `font-firacode-ttf` and `font-firacode-otf`.
They can be installed by running:
sudo eopkg install font-firacode-ttf font-firacode-otf
Void linux
----------
xbps-install font-firacode
Linux Manual Installation
-------------------------
With most desktop-oriented distributions, double-clicking each font file in the ttf folder and selecting “Install font” should be enough. If it isnt, create and run `download_and_install.sh` script:
#!/usr/bin/env bash
fonts_dir="${HOME}/.local/share/fonts"
if [ ! -d "${fonts_dir}" ]; then
echo "mkdir -p $fonts_dir"
mkdir -p "${fonts_dir}"
else
echo "Found fonts dir $fonts_dir"
fi
for type in Bold Light Medium Regular Retina; do
file_path="${HOME}/.local/share/fonts/FiraCode-${type}.ttf"
file_url="https://github.com/tonsky/FiraCode/blob/master/distr/ttf/FiraCode-${type}.ttf?raw=true"
if [ ! -e "${file_path}" ]; then
echo "wget -O $file_path $file_url"
wget -O "${file_path}" "${file_url}"
else
echo "Found existing file $file_path"
fi;
done
echo "fc-cache -f"
fc-cache -f
More details: https://github.com/tonsky/FiraCode/issues/4
FreeBSD
-------
Using pkg(8):
pkg install firacode
OR
Using ports:
cd /usr/ports/x11-fonts/firacode && make install clean
Enabling ligatures
==================
Atom
----
To change your font to Fira Code, open Atom's preferences (`cmd + ,` on a Mac, `ctrl + ,` on PC), make sure the "Settings" tab is selected, or the "Editor" in Atom 1.10+, and scroll down to "Editor Settings". In the "Font Family" field, enter `Fira Code`.
If you wish to specify a font weight, for example, Light, use `Fira Code Light` as a font name (Windows) or `FiraCode-Light` (macOS).
Ligatures are enabled by default in Atom 1.9 and above.
VS Code
-------
To open the settings editor, first from the File menu choose Preferences, Settings or use keyboard shortcut `Ctrl + ,` (Windows) or `Cmd + ,` (macOS).
To enable FiraCode in the settings editor, under "Commonly Used", expand the "Text Editor" settings and then click on "Font". In the "Font Family" input box type `Fira Code`, replacing any content. Tick the check box "Enables/Disables font ligatures" under "Font Ligatures" to enable the special ligatures.
If you wish to specify a font weight, for example, Light, use `Fira Code Light` as a font name (Windows) or `FiraCode-Light` (macOS).
IntelliJ products
-----------------
1. Enable in Settings → Editor → Font → Enable Font Ligatures
2. Select `Fira Code` as "Primary font" under Settings → Editor → Font
Additionally, if a Color Scheme is selected:
3. Enable in Settings → Editor → Color Scheme → Color Scheme Font → Enable Font Ligatures
4. Select Fira Code as "Primary font" under Settings → Editor → Color Scheme → Color Scheme Font
BBEdit, TextWrangler
--------------------
Run in your terminal:
defaults write com.barebones.bbedit "EnableFontLigatures_Fira Code" -bool YES
Source: https://www.barebones.com/support/bbedit/ExpertPreferences.html
Brackets
--------
1. From the `View` menu choose `Themes....`
2. Paste `'Fira Code'`, at the beginning of `Font Family`
Emacs
-----
There are a few options when it comes down to using ligatures in
Emacs. They are listed in order of preferred to less-preferred. Pick one!
1. Using composition mode in Emacs Mac port
If you're using the latest Mac port of Emacs (https://bitbucket.org/mituharu/emacs-mac by Mitsuharu Yamamoto) for macOS, you can use:
(mac-auto-operator-composition-mode)
This is generally the easiest solution, but can only be used on macOS.
2. Using prettify-symbols
These instructions are pieced together by https://github.com/Triavanicus, taking some pieces from https://github.com/minad/hasklig-mode.
This method requires you to install the Fira Code Symbol font, made by https://github.com/siegebell:
https://github.com/tonsky/FiraCode/issues/211#issuecomment-239058632
(defun fira-code-mode--make-alist (list)
"Generate prettify-symbols alist from LIST."
(let ((idx -1))
(mapcar
(lambda (s)
(setq idx (1+ idx))
(let* ((code (+ #Xe100 idx))
(width (string-width s))
(prefix ())
(suffix '(?\s (Br . Br)))
(n 1))
(while (< n width)
(setq prefix (append prefix '(?\s (Br . Bl))))
(setq n (1+ n)))
(cons s (append prefix suffix (list (decode-char 'ucs code))))))
list)))
(defconst fira-code-mode--ligatures
'("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\"
"{-" "[]" "::" ":::" ":=" "!!" "!=" "!==" "-}"
"--" "---" "-->" "->" "->>" "-<" "-<<" "-~"
"#{" "#[" "##" "###" "####" "#(" "#?" "#_" "#_("
".-" ".=" ".." "..<" "..." "?=" "??" ";;" "/*"
"/**" "/=" "/==" "/>" "//" "///" "&&" "||" "||="
"|=" "|>" "^=" "$>" "++" "+++" "+>" "=:=" "=="
"===" "==>" "=>" "=>>" "<=" "=<<" "=/=" ">-" ">="
">=>" ">>" ">>-" ">>=" ">>>" "<*" "<*>" "<|" "<|>"
"<$" "<$>" "<!--" "<-" "<--" "<->" "<+" "<+>" "<="
"<==" "<=>" "<=<" "<>" "<<" "<<-" "<<=" "<<<" "<~"
"<~~" "</" "</>" "~@" "~-" "~=" "~>" "~~" "~~>" "%%"
"x" ":" "+" "+" "*"))
(defvar fira-code-mode--old-prettify-alist)
(defun fira-code-mode--enable ()
"Enable Fira Code ligatures in current buffer."
(setq-local fira-code-mode--old-prettify-alist prettify-symbols-alist)
(setq-local prettify-symbols-alist (append (fira-code-mode--make-alist fira-code-mode--ligatures) fira-code-mode--old-prettify-alist))
(prettify-symbols-mode t))
(defun fira-code-mode--disable ()
"Disable Fira Code ligatures in current buffer."
(setq-local prettify-symbols-alist fira-code-mode--old-prettify-alist)
(prettify-symbols-mode -1))
(define-minor-mode fira-code-mode
"Fira Code ligatures minor mode"
:lighter " Fira Code"
(setq-local prettify-symbols-unprettify-at-point 'right-edge)
(if fira-code-mode
(fira-code-mode--enable)
(fira-code-mode--disable)))
(defun fira-code-mode--setup ()
"Setup Fira Code Symbols"
(set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol"))
(provide 'fira-code-mode)
Alternative instructions: https://github.com/Profpatsch/blog/blob/master/posts/ligature-emulation-in-emacs/post.md#appendix-b-update-1-firacode-integration
3. Using composition char table
Thanks to https://github.com/seanfarley for putting this together; extended by https://github.com/jrblevin.
Put this lisp in your .emacs:
(when (window-system)
(set-frame-font "Fira Code"))
(let ((alist '((33 . ".\\(?:\\(?:==\\|!!\\)\\|[!=]\\)")
(35 . ".\\(?:###\\|##\\|_(\\|[#(?[_{]\\)")
(36 . ".\\(?:>\\)")
(37 . ".\\(?:\\(?:%%\\)\\|%\\)")
(38 . ".\\(?:\\(?:&&\\)\\|&\\)")
(42 . ".\\(?:\\(?:\\*\\*/\\)\\|\\(?:\\*[*/]\\)\\|[*/>]\\)")
(43 . ".\\(?:\\(?:\\+\\+\\)\\|[+>]\\)")
(45 . ".\\(?:\\(?:-[>-]\\|<<\\|>>\\)\\|[<>}~-]\\)")
(46 . ".\\(?:\\(?:\\.[.<]\\)\\|[.=-]\\)")
(47 . ".\\(?:\\(?:\\*\\*\\|//\\|==\\)\\|[*/=>]\\)")
(48 . ".\\(?:x[a-zA-Z]\\)")
(58 . ".\\(?:::\\|[:=]\\)")
(59 . ".\\(?:;;\\|;\\)")
(60 . ".\\(?:\\(?:!--\\)\\|\\(?:~~\\|->\\|\\$>\\|\\*>\\|\\+>\\|--\\|<[<=-]\\|=[<=>]\\||>\\)\\|[*$+~/<=>|-]\\)")
(61 . ".\\(?:\\(?:/=\\|:=\\|<<\\|=[=>]\\|>>\\)\\|[<=>~]\\)")
(62 . ".\\(?:\\(?:=>\\|>[=>-]\\)\\|[=>-]\\)")
(63 . ".\\(?:\\(\\?\\?\\)\\|[:=?]\\)")
(91 . ".\\(?:]\\)")
(92 . ".\\(?:\\(?:\\\\\\\\\\)\\|\\\\\\)")
(94 . ".\\(?:=\\)")
(119 . ".\\(?:ww\\)")
(123 . ".\\(?:-\\)")
(124 . ".\\(?:\\(?:|[=|]\\)\\|[=>|]\\)")
(126 . ".\\(?:~>\\|~~\\|[>=@~-]\\)")
)
))
(dolist (char-regexp alist)
(set-char-table-range composition-function-table (car char-regexp)
`([,(cdr char-regexp) 0 font-shape-gstring]))))
**Note!** If you get `error in process filter: Attempt to shape unibyte text`, check out https://github.com/tonsky/FiraCode/issues/42. Emacs Cider users may avoid this issue by commenting the following line from the above config:
;; (46 . ".\\(?:\\(?:\\.[.<]\\)\\|[.=-]\\)")
Char `45` is also known to have issues in macOS Mojave.
If you are having problems with helm you can disable ligatures in helm:
(add-hook 'helm-major-mode-hook
(lambda ()
(setq auto-composition-mode nil)))
4. Using font-lock keywords
If none of the above worked, you can try this method.
This method requires you to install the Fira Code Symbol font, made by https://github.com/siegebell:
https://github.com/tonsky/FiraCode/issues/211#issuecomment-239058632
;;; Fira code
;; This works when using emacs --daemon + emacsclient
(add-hook 'after-make-frame-functions (lambda (frame) (set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol")))
;; This works when using emacs without server/client
(set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol")
;; I haven't found one statement that makes both of the above situations work, so I use both for now
(defconst fira-code-font-lock-keywords-alist
(mapcar (lambda (regex-char-pair)
`(,(car regex-char-pair)
(0 (prog1 ()
(compose-region (match-beginning 1)
(match-end 1)
;; The first argument to concat is a string containing a literal tab
,(concat " " (list (decode-char 'ucs (cadr regex-char-pair)))))))))
'(("\\(www\\)" #Xe100)
("[^/]\\(\\*\\*\\)[^/]" #Xe101)
("\\(\\*\\*\\*\\)" #Xe102)
("\\(\\*\\*/\\)" #Xe103)
("\\(\\*>\\)" #Xe104)
("[^*]\\(\\*/\\)" #Xe105)
("\\(\\\\\\\\\\)" #Xe106)
("\\(\\\\\\\\\\\\\\)" #Xe107)
("\\({-\\)" #Xe108)
("\\(\\[\\]\\)" #Xe109)
("\\(::\\)" #Xe10a)
("\\(:::\\)" #Xe10b)
("[^=]\\(:=\\)" #Xe10c)
("\\(!!\\)" #Xe10d)
("\\(!=\\)" #Xe10e)
("\\(!==\\)" #Xe10f)
("\\(-}\\)" #Xe110)
("\\(--\\)" #Xe111)
("\\(---\\)" #Xe112)
("\\(-->\\)" #Xe113)
("[^-]\\(->\\)" #Xe114)
("\\(->>\\)" #Xe115)
("\\(-<\\)" #Xe116)
("\\(-<<\\)" #Xe117)
("\\(-~\\)" #Xe118)
("\\(#{\\)" #Xe119)
("\\(#\\[\\)" #Xe11a)
("\\(##\\)" #Xe11b)
("\\(###\\)" #Xe11c)
("\\(####\\)" #Xe11d)
("\\(#(\\)" #Xe11e)
("\\(#\\?\\)" #Xe11f)
("\\(#_\\)" #Xe120)
("\\(#_(\\)" #Xe121)
("\\(\\.-\\)" #Xe122)
("\\(\\.=\\)" #Xe123)
("\\(\\.\\.\\)" #Xe124)
("\\(\\.\\.<\\)" #Xe125)
("\\(\\.\\.\\.\\)" #Xe126)
("\\(\\?=\\)" #Xe127)
("\\(\\?\\?\\)" #Xe128)
("\\(;;\\)" #Xe129)
("\\(/\\*\\)" #Xe12a)
("\\(/\\*\\*\\)" #Xe12b)
("\\(/=\\)" #Xe12c)
("\\(/==\\)" #Xe12d)
("\\(/>\\)" #Xe12e)
("\\(//\\)" #Xe12f)
("\\(///\\)" #Xe130)
("\\(&&\\)" #Xe131)
("\\(||\\)" #Xe132)
("\\(||=\\)" #Xe133)
("[^|]\\(|=\\)" #Xe134)
("\\(|>\\)" #Xe135)
("\\(\\^=\\)" #Xe136)
("\\(\\$>\\)" #Xe137)
("\\(\\+\\+\\)" #Xe138)
("\\(\\+\\+\\+\\)" #Xe139)
("\\(\\+>\\)" #Xe13a)
("\\(=:=\\)" #Xe13b)
("[^!/]\\(==\\)[^>]" #Xe13c)
("\\(===\\)" #Xe13d)
("\\(==>\\)" #Xe13e)
("[^=]\\(=>\\)" #Xe13f)
("\\(=>>\\)" #Xe140)
("\\(<=\\)" #Xe141)
("\\(=<<\\)" #Xe142)
("\\(=/=\\)" #Xe143)
("\\(>-\\)" #Xe144)
("\\(>=\\)" #Xe145)
("\\(>=>\\)" #Xe146)
("[^-=]\\(>>\\)" #Xe147)
("\\(>>-\\)" #Xe148)
("\\(>>=\\)" #Xe149)
("\\(>>>\\)" #Xe14a)
("\\(<\\*\\)" #Xe14b)
("\\(<\\*>\\)" #Xe14c)
("\\(<|\\)" #Xe14d)
("\\(<|>\\)" #Xe14e)
("\\(<\\$\\)" #Xe14f)
("\\(<\\$>\\)" #Xe150)
("\\(<!--\\)" #Xe151)
("\\(<-\\)" #Xe152)
("\\(<--\\)" #Xe153)
("\\(<->\\)" #Xe154)
("\\(<\\+\\)" #Xe155)
("\\(<\\+>\\)" #Xe156)
("\\(<=\\)" #Xe157)
("\\(<==\\)" #Xe158)
("\\(<=>\\)" #Xe159)
("\\(<=<\\)" #Xe15a)
("\\(<>\\)" #Xe15b)
("[^-=]\\(<<\\)" #Xe15c)
("\\(<<-\\)" #Xe15d)
("\\(<<=\\)" #Xe15e)
("\\(<<<\\)" #Xe15f)
("\\(<~\\)" #Xe160)
("\\(<~~\\)" #Xe161)
("\\(</\\)" #Xe162)
("\\(</>\\)" #Xe163)
("\\(~@\\)" #Xe164)
("\\(~-\\)" #Xe165)
("\\(~=\\)" #Xe166)
("\\(~>\\)" #Xe167)
("[^<]\\(~~\\)" #Xe168)
("\\(~~>\\)" #Xe169)
("\\(%%\\)" #Xe16a)
("[0\[]\\(x\\)" #Xe16b)
("[^:=]\\(:\\)[^:=]" #Xe16c)
("[^\\+<>]\\(\\+\\)[^\\+<>]" #Xe16d)
("[^\\*/<>]\\(\\*\\)[^\\*/<>]" #Xe16f))))
(defun add-fira-code-symbol-keywords ()
(font-lock-add-keywords nil fira-code-font-lock-keywords-alist))
(add-hook 'prog-mode-hook
#'add-fira-code-symbol-keywords)
On some systems, `==` will appear incorrectly as a blank space in certain modes unless you add the following lines to your init file:
(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8)
GoormIDE
--------
In a workspace:
1. Click goormIDE, then Preferences.
2. Go to Theme, then focus Custom Theme CSS.
3. Copy & paste the following:
@font-face{
font-family: 'Fira Code';
src: url('https://raw.githubusercontent.com/tonsky/FiraCode/master/distr/eot/FiraCode-Regular.eot') format('embedded-opentype'),
url('https://raw.githubusercontent.com/tonsky/FiraCode/master/distr/woff2/FiraCode-Regular.woff2') format('woff2'),
url('https://raw.githubusercontent.com/tonsky/FiraCode/master/distr/woff/FiraCode-Regular.woff') format('woff'),
url('https://raw.githubusercontent.com/tonsky/FiraCode/master/distr/ttf/FiraCode-Regular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
.editor_container pre {
-webkit-font-feature-settings: "liga" on, "calt" on;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: 'Fira Code';
}
4. Click Aplly or OK
5. Happy coding!
Cloud9
------
In a workspace:
1. Click Cloud9, then Preferences (or use keyboard shortcut CTRL + ,)
2. Go to Themes, then click on You can also style Cloud9 by editing your stylesheet (this will open a blank styles.css file in the C9 editor)
3. Copy & paste the following:
@font-face{
font-family: 'Fira Code';
src: url('https://raw.githubusercontent.com/tonsky/FiraCode/master/distr/eot/FiraCode-Regular.eot') format('embedded-opentype'),
url('https://raw.githubusercontent.com/tonsky/FiraCode/master/distr/woff2/FiraCode-Regular.woff2') format('woff2'),
url('https://raw.githubusercontent.com/tonsky/FiraCode/master/distr/woff/FiraCode-Regular.woff') format('woff'),
url('https://raw.githubusercontent.com/tonsky/FiraCode/master/distr/ttf/FiraCode-Regular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
.ace_editor{
-webkit-font-feature-settings: "liga" on, "calt" on;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: 'Fira Code';
}
4. Back in Preferences tab, click on User Settings, then click on Code Editor (Ace)
5. In Font Family field, enter Fira Code
6. Optionally, repeat step 5 for Preferences > User Settings > Terminal, if you want Fira Code font in C9 terminal.
MacVim
------
Add this to ~/.gvimrc:
set macligatures
set guifont=Fira\ Code:h12
MacVim supports ligatures starting from version 7.4.
RStudio
-------
In RStudio:
1. Go to Tools > Global Options > Appearance
2. Select "Fira Code" as Editor Font. In older versions of RStudio, check "Use Ligatures".
3. Hit "OK" and enjoy
Sublime Text
------------
Preferences --> Settings
Add before "ignored_packages":
"font_face": "Fira Code",
"font_options": ["subpixel_antialias"],
If you want enable antialias, add in font_options: "gray_antialias"
Visual Studio
-------------
1. Launch Visual Studio (2015 or later).
2. Launch the Options dialog by opening the "Tools" menu and selecting "Options".
3. In the Options dialog, under the "Environment" category, you'll find "Fonts and Colors". Click on that. You'll see a combo-box on the right hand side of the dialog labelled "Font". Select "Fira Code" from that combo-box.
4. Click "OK" to dismiss.
5. Restart Visual Studio.
Now, most FiraCode ligatures will work. A notable exception is the hyphen-based ligatures (e.g. the C++ dereference '->'). See https://github.com/tonsky/FiraCode/issues/422 for details.
Troubleshooting
===============
See https://github.com/tonsky/FiraCode/wiki/Troubleshooting

View file

@ -0,0 +1,54 @@
@font-face {
font-family: "Fira Code";
src:
url("woff2/FiraCode-Light.woff2") format("woff2"),
url("woff/FiraCode-Light.woff") format("woff");
font-weight: 300;
font-style: normal;
}
@font-face {
font-family: "Fira Code";
src:
url("woff2/FiraCode-Regular.woff2") format("woff2"),
url("woff/FiraCode-Regular.woff") format("woff");
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: "Fira Code";
src:
url("woff2/FiraCode-Medium.woff2") format("woff2"),
url("woff/FiraCode-Medium.woff") format("woff");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: "Fira Code";
src:
url("woff2/FiraCode-SemiBold.woff2") format("woff2"),
url("woff/FiraCode-SemiBold.woff") format("woff");
font-weight: 600;
font-style: normal;
}
@font-face {
font-family: "Fira Code";
src:
url("woff2/FiraCode-Bold.woff2") format("woff2"),
url("woff/FiraCode-Bold.woff") format("woff");
font-weight: 700;
font-style: normal;
}
@font-face {
font-family: "Fira Code VF";
src:
url("woff2/FiraCode-VF.woff2") format("woff2-variations"),
url("woff/FiraCode-VF.woff") format("woff-variations");
/* font-weight requires a range: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide#Using_a_variable_font_font-face_changes */
font-weight: 300 700;
font-style: normal;
}

View file

@ -0,0 +1,134 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0"
/>
<title>Fira Code Specimen</title>
<link
rel="stylesheet"
href="fira_code.css"
/>
<style>
body {
font: 14px/1.5em "Fira Code";
}
.code {
font-feature-settings: "calt" 1; /* Enable ligatures for IE 10+, Edge */
text-rendering: optimizeLegibility; /* Force ligatures for Webkit, Blink, Gecko */
width: 30em;
margin: 5em auto;
white-space: pre-wrap;
word-break: break-all;
}
.light {
font-weight: 300;
}
.regular {
font-weight: 400;
}
.medium {
font-weight: 500;
}
.semibold {
font-weight: 600;
}
.bold {
font-weight: 700;
}
.variable {
font-family: "Fira Code VF";
font-variation-settings: "wght" 400;
}
i {
font-style: normal;
color: #c33;
}
b {
font-weight: inherit;
color: #c33;
}
</style>
<script type="text/javascript">
function onWeightChange(weight) {
// code_variable.style['font-weight'] = weight;
code_variable.style["font-variation-settings"] =
"'wght' " + weight;
span_wght.innerText = weight;
}
</script>
<body>
<div class="code light">
<b># Fira Code Light</b>
take = (n, [x, <i>...</i>xs]:list) <i>--&gt;</i> | n
<i>&lt;=</i> 0 <i>=&gt;</i> [] | empty list <i>=&gt;</i> [] |
otherwise <i>=&gt;</i> [x] <i>++</i> take n-1, xs last3 =
reverse <i>&gt;&gt;</i> take 3 <i>&gt;&gt;</i> reverse
</div>
<div class="code regular">
<b># Fira Code Regular</b>
take = (n, [x, <i>...</i>xs]:list) <i>--></i> | n <i>&lt;=</i> 0
<i>=&gt;</i> [] | empty list <i>=&gt;</i> [] | otherwise
<i>=&gt;</i> [x] <i>++</i> take n-1, xs last3 = reverse
<i>&gt;&gt;</i> take 3 <i>&gt;&gt;</i> reverse
</div>
<div class="code medium">
<b># Fira Code Medium</b>
take = (n, [x, <i>...</i>xs]:list) <i>--&gt;</i> | n
<i>&lt;=</i> 0 <i>=&gt;</i> [] | empty list <i>=&gt;</i> [] |
otherwise <i>=&gt;</i> [x] <i>++</i> take n-1, xs last3 =
reverse <i>&gt;&gt;</i> take 3 <i>&gt;&gt;</i> reverse
</div>
<div class="code semibold">
<b># Fira Code SemiBold</b>
take = (n, [x, <i>...</i>xs]:list) <i>--&gt;</i> | n
<i>&lt;=</i> 0 <i>=&gt;</i> [] | empty list <i>=&gt;</i> [] |
otherwise <i>=&gt;</i> [x] <i>++</i> take n-1, xs last3 =
reverse <i>&gt;&gt;</i> take 3 <i>&gt;&gt;</i> reverse
</div>
<div class="code bold">
<b># Fira Code Bold</b>
take = (n, [x, <i>...</i>xs]:list) <i>--&gt;</i> | n
<i>&lt;=</i> 0 <i>=&gt;</i> [] | empty list <i>=&gt;</i> [] |
otherwise <i>=&gt;</i> [x] <i>++</i> take n-1, xs last3 =
reverse <i>&gt;&gt;</i> take 3 <i>&gt;&gt;</i> reverse
</div>
<div
id="code_variable"
class="code variable"
>
<b># Fira Code Variable</b>
<input
type="range"
min="300"
max="700"
value="400"
step="10"
style="width: 300px"
oninput="onWeightChange(this.value)"
onchange="onWeightChange(this.value)"
/>
<span id="span_wght">400</span>
take = (n, [x, <i>...</i>xs]:list) <i>--&gt;</i> | n
<i>&lt;=</i> 0 <i>=&gt;</i> [] | empty list <i>=&gt;</i> [] |
otherwise <i>=&gt;</i> [x] <i>++</i> take n-1, xs last3 =
reverse <i>&gt;&gt;</i> take 3 <i>&gt;&gt;</i> reverse
</div>
</body>
</head>
</html>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

40
src/assets/style.css Normal file
View file

@ -0,0 +1,40 @@
@import "tailwindcss";
@theme {
--font-fira-code: "Fira Code";
}
/*
The default border color has changed to `currentcolor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
}
}
@layer base {
h1,
h2,
h3 {
@apply font-fira-code;
}
a {
@apply text-blue-600;
}
}
.do-a-barrel-roll {
transform: rotate(360deg);
transition-property: all;
transition-duration: 4s;
}

View file

@ -0,0 +1,56 @@
<template>
<li class="grid md:grid-cols-6 md:gap-1 mt-2 md:mt-0">
<div class="md:col-span-1 text-center md:text-left text-slate-600">
{{ date }}
</div>
<div class="md:col-span-5 text-center md:text-left">
<span
class="font-bold"
v-if="title"
>
{{ title }}
</span>
<ul
v-if="missions"
:aria-description="t('Missions réalisées')"
>
<li
v-for="mission in missions"
:key="mission"
>
{{ mission }}
</li>
</ul>
<div
v-if="technos"
class="text-left text-slate-700 font-mono"
>
<i
class="fab fa-envira text-slate-500 mr-1"
aria-hidden="true"
></i>
<p
class="inline"
:aria-description="t('Technologies utilisées')"
>
{{ technos.join(", ") }}
</p>
</div>
</div>
</li>
</template>
<script setup lang="ts">
import { useI18n } from "vue-i18n";
defineProps<Props>();
const { t } = useI18n();
</script>
<script lang="ts">
export interface Props {
date: string;
title?: string;
missions?: string[];
technos?: string[];
}
</script>

View file

@ -0,0 +1,23 @@
<template>
<li class="flex">
<div
class="text-center w-[6mm] shrink-0"
aria-hidden="true"
>
<i
class="fas text-slate-500"
:class="icon"
/>
</div>
<div>
<slot />
</div>
</li>
</template>
<script setup lang="ts">
interface Props {
icon: string;
}
defineProps<Props>();
</script>

View file

@ -0,0 +1,358 @@
<template>
<main
:aria-label="t('Mon CV')"
class="relative md:h-[297mm] md:w-[210mm] overflow-hidden bg-white shadow-lg print:m-0 print:h-screen! print:w-screen! print:shadow-none grid md:grid-cols-3 print:grid-cols-3 md:grid-rows-[min-content_1fr] print:grid-rows-[min-content_1fr] m-auto"
>
<div
class="order-1 md:col-span-1 print:col-span-1 md:p-[10mm] print:p-[10mm] md:pb-0 print:pb-0 md:bg-slate-100 print:bg-slate-100"
>
<div class="m-[4mm]">
<img
id="avatar"
src="/avatar.webp"
height="150"
width="150"
class="rounded-full border-[#caca] border-[1mm] m-auto"
:alt="t('IMG_ALT.AVATAR')"
/>
</div>
</div>
<div
class="order-2 md:col-span-2 print:col-span-2 md:p-[10mm] print:p-[10mm] md:pb-0 print:pb-0"
>
<h1
class="text-xl md:text-2xl print:text-2xl text-center md:mt-[14mm] print:mt-[14mm]"
>
Morgane de Carpentier
<br /><strong>
{{ t("Conceptrice Développeuse FullStack") }}
</strong>
</h1>
</div>
<div
class="order-3 md:order-4 print:order-4 md:col-span-2 print:col-span-2 p-[10mm]"
>
<section aria-labelledby="my-experience">
<h2
id="my-experience"
class="text-xl text-center md:text-left print:text-left"
>
{{ t("Expérience") }}
</h2>
<ul>
<ExperienceInfo
v-for="experience in experiences"
:key="experience.date"
v-bind="experience"
/>
</ul>
</section>
<section
class="mt-15 md:mt-[20mm] print:mt-[20mm]"
aria-labelledby="my-education"
>
<h2
id="my-education"
class="text-xl text-center md:text-left print:text-left"
>
{{ t("Formation") }}
</h2>
<ul>
<li
class="grid md:grid-cols-6 print:grid-cols-6 md:gap-1 print:gap-1"
>
<div
class="md:col-span-1 print:col-span-1 text-center md:text-left print:text-left text-slate-600"
>
2014-2015
</div>
<div class="md:col-span-5 print:col-span-5">
<strong> {{ t("Licence CDED") }} </strong>
{{
t(
"(Concepteur-développeur en environnement distribué)",
)
}}
<address>
{{ t("ADDRESS.IUT_ROBERT_SCHUMAN") }}
</address>
</div>
</li>
<li
class="grid md:grid-cols-6 print:grid-cols-6 md:gap-1 print:gap-1"
>
<div
class="md:col-span-1 print:col-span-1 text-center md:text-left print:text-left text-slate-600"
>
2013-2014
</div>
<div class="md:col-span-5 print:col-span-5">
<strong> {{ t("Licence 3 Math-Info") }} </strong>
<address>{{ t("ADDRESS.UFR_MATH_INFO") }}</address>
</div>
</li>
<li
class="grid md:grid-cols-6 print:grid-cols-6 md:gap-1 print:gap-1"
>
<div
class="md:col-span-1 print:col-span-1 text-center md:text-left print:text-left text-slate-600"
>
2011-2013
</div>
<div class="md:col-span-5 print:col-span-5">
<strong> {{ t("DUT Informatique") }} </strong>
<address>
{{ t("ADDRESS.IUT_ROBERT_SCHUMAN") }}
</address>
</div>
</li>
</ul>
</section>
</div>
<div
class="order-4 md:order-3 print:order-3 md:col-span-1 print:col-span-1 p-[10mm] pr-[8px] bg-slate-100 grid grid-cols-2 md:grid-cols-1 print:grid-cols-1"
>
<section
class="order-4 md:order-1 print:order-1 md:mt-[6px] print:mt-[6px]"
>
<h3>{{ t("Contact") }}</h3>
<ul class="mb-[10mm] ms-1">
<QuickInfo icon="fa-calendar">
{{
t("@count years", {
count: new Date().getFullYear() - 1992,
})
}}
</QuickInfo>
<QuickInfo icon="fa-map-marker">
<address class="not-italic">
2a rue Poincaré
<br />67800 Bischheim
<span class="sr-only"
>({{ t("Prononcé") }}
<span lang="fr">bichailleme</span>)</span
>
</address>
</QuickInfo>
<QuickInfo icon="fa-phone">
<a href="tel:+33602325541">06 02 32 55 41</a>
</QuickInfo>
<QuickInfo icon="fa-envelope">
<a href="mailto:morgane@de-carpentier.fr"
>morgane@de-carpentier.fr</a
>
</QuickInfo>
</ul>
</section>
<section class="order-3 md:order-2 print:order-2">
<h3>{{ t("Langues") }}</h3>
<ul class="mb-[10mm] ms-1">
<li>
<button
class="flex cursor-pointer"
@click="locale = 'fr'"
>
<div
class="w-[6mm] flex justify-center items-center"
aria-hidden="true"
>
<img
src="/fr.svg"
class="w-[4mm] align-middle"
height="15"
width="10"
:alt="t('IMG_ALT.FRENCH_FLAG')"
/>
</div>
<div>{{ t("Français") }}</div>
</button>
</li>
<li>
<button
class="flex cursor-pointer"
@click="locale = 'en'"
>
<div
class="w-[6mm] flex justify-center items-center"
aria-hidden="true"
>
<img
src="/en.svg"
class="w-[4mm] align-middle"
height="15"
width="10"
:alt="t('IMG_ALT.ENGLISH_FLAG')"
/>
</div>
<div>{{ t("Anglais") }}</div>
</button>
</li>
</ul>
</section>
<section class="order-2 md:order-3 print:order-3">
<h3>{{ t("Intérêts") }}</h3>
<ul class="mb-[10mm] ms-1">
<QuickInfo icon="fa-dragon">
{{ t("Jeux de rôle / société") }}
</QuickInfo>
<QuickInfo icon="fa-running">
{{ t("Escalade, vélo") }}
</QuickInfo>
<QuickInfo icon="fa-cube">
{{ t("Impression 3D") }}
</QuickInfo>
</ul>
</section>
<section class="order-1 md:order-4 print:order-4 mb-[31px]">
<h3>{{ t("TODO") }}</h3>
<ul class="mb-[10mm] ms-1">
<QuickInfo icon="fa-regular fa-square-check">
<a
:href="t('LINKS.KISS')"
target="_blank"
>
{{ t("KISS") }}
<sup class="hidden print:inline">1</sup>
</a>
</QuickInfo>
<QuickInfo icon="fa-regular fa-square-check">
<a
:href="t('LINKS.SOLID')"
target="_blank"
>
{{ t("Stay SOLID") }}
<sup class="hidden print:inline">2</sup>
</a>
</QuickInfo>
<QuickInfo icon="fa-regular fa-square-check">
<a
:href="t('LINKS.DRY')"
target="_blank"
>
{{ t("Stop being WET and DRY up") }}
<sup class="hidden print:inline">3</sup>
</a>
</QuickInfo>
<QuickInfo icon="fa-regular fa-square-check">
<a
:href="t('LINKS.DIVIDE_AND_CONQUER')"
target="_blank"
>
{{ t("Diviser pour mieux régner") }}
<sup class="hidden print:inline">4</sup>
</a>
</QuickInfo>
</ul>
</section>
</div>
<div
class="absolute bottom-0 w-full text-xs hidden print:flex justify-start"
aria-hidden="true"
>
<!-- Display the url links at the bottom of the resume when printed -->
<ul class="bg-white m-[10mm] mb-[8mm] p-[2mm] border rounded-sm">
<li lang="en">
<sup aria-hidden="true">1</sup>
{{ t("LINKS.KISS") }}
</li>
<li lang="en">
<sup aria-hidden="true">2</sup>
{{ t("LINKS.SOLID") }}
</li>
<li lang="en">
<sup aria-hidden="true">3</sup>
{{ t("LINKS.DRY") }}
</li>
<li>
<sup aria-hidden="true">4</sup>
{{ t("LINKS.DIVIDE_AND_CONQUER") }}
</li>
</ul>
</div>
</main>
</template>
<script setup lang="ts">
import { computed } from "vue";
import QuickInfo from "./QuickInfo.vue";
import ExperienceInfo from "./ExperienceInfo.vue";
import type { Props as ExperienceInfoProps } from "./ExperienceInfo.vue";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const experiences = computed<ExperienceInfoProps[]>(() => [
{
date: t("2023-Aujourd'hui"),
title: t("Développeuse senior chez Jaune de Mars"),
missions: [
t("Logiciel de gestion de parc/pannes d'appareils"),
t("Migration progressive des outils et technologies internes"),
t("Mise en place d'outils d'analyse de code"),
t("Implémentation d'un système d'intégration continue"),
],
technos: [
"TypeScript",
"VueJs",
"PHP",
"Symfony",
"Redis",
"PostgreSQL",
"Docker",
"Kubernetes",
"GitLab CI/CD",
],
},
{
date: "2019-2023",
title: t("Développeuse logiciel chez Caldera"),
missions: [
t("Logiciels d'automatisation du prépresse"),
t("Référente technique des solutions web internes"),
t("Veille et mises à jours technologiques"),
t("Amélioration du système d'intégration continue"),
],
technos: ["TypeScript", "VueJs", "Electron", "GitLab CI/CD"],
},
{
date: "2019",
title: t("Développeuse web chez Thuria"),
missions: [
t("Amélioration des outils de développement internes"),
t("Réalisation de sites vitrines"),
],
technos: ["PHP", "Wordpress", "Symfony", "ElasticSearch"],
},
{
date: "2014-2019",
title: t("Conceptrice développeuse chez AZ Conception"),
missions: [
t("Solution de géolocalisation et réservation de taxi"),
t("Référente technique des solutions web internes"),
t("Veille et mises à jours technologiques"),
t("ERP, sites e-commerce et sites vitrines"),
],
technos: [
"PHP",
"Laravel",
"VueJs",
"Docker",
"Nginx",
"MySql",
"Redis",
"Magento",
"Drupal",
],
},
]);
</script>

62
src/locales/en.json Normal file
View file

@ -0,0 +1,62 @@
{
"@count years": "{count} years",
"IMG_ALT": {
"AVATAR": "Selfie of the candidate: in their thirties, with shoulder-length dyed red hair, wearing tinted glasses. A black and white cat is perched on their shoulders.",
"FRENCH_FLAG": "French flag",
"ENGLISH_FLAG": "English flag",
"DO_A_BARRELL_ROLL": "Avatar of Peppy Hare, a member of the legendary Star Fox team in Star Fox 64"
},
"Contact": "Contact",
"Langues": "Languages",
"Français": "French",
"Anglais": "English",
"Intérêts": "Interests",
"Jeux de rôle / société": "Role-playing/board games",
"Escalade, vélo": "Climbing, cycling",
"Impression 3D": "3D printing",
"TODO": "TODO",
"LINKS": {
"KISS": "https://en.wikipedia.org/wiki/KISS_principle",
"SOLID": "https://en.wikipedia.org/wiki/SOLID",
"DRY": "https://en.wikipedia.org/wiki/Don%27t_repeat_yourself",
"DIVIDE_AND_CONQUER": "https://en.wikipedia.org/wiki/Divide-and-conquer_algorithm"
},
"KISS": "KISS",
"Stay SOLID": "Stay SOLID",
"Stop being WET and DRY up": "Stop being WET and DRY up",
"Diviser pour mieux régner": "Divide and conquer",
"Conceptrice Développeuse FullStack": "Full-Stack Developer",
"Expérience": "Experience",
"Formation": "Education",
"Licence CDED": "CDED Bachelor's Degree",
"(Concepteur-développeur en environnement distribué)": "(Bachelor's degree in distributed environment software development)",
"Licence 3 Math-Info": "Bachelor's degree in Mathematics and Computer Science",
"DUT Informatique": "DUT in Computer Science",
"ADDRESS": {
"IUT_ROBERT_SCHUMAN": "IUT Robert Schuman, 67411 Illkirch-Graffenstaden",
"UFR_MATH_INFO": "Faculty of Mathematics and Computer Science, 67084 Strasbourg"
},
"Développeuse senior chez Jaune de Mars": "Senior Developer at Jaune de Mars",
"Logiciel de gestion de parc/pannes d'appareils": "Device management and incident tracking software",
"Migration progressive des outils et technologies internes": "Gradual migration of internal tools and technologies",
"Mise en place d'outils d'analyse de code": "Setup of code analysis tools",
"Implémentation d'un système d'intégration continue": "Implementation of CI/CD systems",
"Développeuse logiciel chez Caldera": "Software Developer at Caldera",
"Logiciels d'automatisation du prépresse": "Prepress automation software",
"Référente technique des solutions web internes": "Technical lead for internal web solutions",
"Veille et mises à jours technologiques": "Technology watch and updates",
"Amélioration du système d'intégration continue": "Improvements to the CI/CD system",
"Développeuse web chez Thuria": "Web Developer at Thuria",
"Amélioration des outils de développement internes": "Enhancement of internal development tools",
"Réalisation de sites vitrines": "Development of showcase websites",
"Conceptrice développeuse chez AZ Conception": "Designer-Developer at AZ Conception",
"Solution de géolocalisation et réservation de taxi": "Geolocation and cab booking solution",
"ERP, sites e-commerce et sites vitrines": "ERP, e-commerce, and showcase websites",
"2023-Aujourd'hui": "2023-Present",
"Imprimer": "Print",
"Mon CV": "My Resume",
"Menu": "Menu",
"Technologies utilisées": "Technologies used",
"Missions réalisées": "Notable tasks",
"Prononcé": "Pronounced"
}

62
src/locales/fr.json Normal file
View file

@ -0,0 +1,62 @@
{
"@count years": "{count} ans",
"IMG_ALT": {
"AVATAR": "Selfie de la candidate : trentenaire, cheveux mi-longs teints en rouge, portant une paire de lunettes teintées. Un chat noir et blanc est perché sur ses épaules.",
"FRENCH_FLAG": "Drapeau français",
"ENGLISH_FLAG": "Drapeau anglais",
"DO_A_BARRELL_ROLL": "Avatar de Peppy Hare, membre légendaire de l'équipe Star Fox dans le jeu Star Fox 64"
},
"Contact": "Contact",
"Langues": "Langues",
"Français": "Français",
"Anglais": "Anglais",
"Intérêts": "Intérêts",
"Jeux de rôle / société": "Jeux de rôle / société",
"Escalade, vélo": "Escalade, vélo",
"Impression 3D": "Impression 3D",
"TODO": "TODO",
"LINKS": {
"KISS": "https://fr.wikipedia.org/wiki/Principe_KISS",
"SOLID": "https://fr.wikipedia.org/wiki/SOLID_(informatique)",
"DRY": "https://fr.wikipedia.org/wiki/Ne_vous_répétez_pas",
"DIVIDE_AND_CONQUER": "https://fr.wikipedia.org/wiki/Diviser_pour_régner_(informatique)"
},
"KISS": "KISS",
"Stay SOLID": "Stay SOLID",
"Stop being WET and DRY up": "Stop being WET and DRY up",
"Diviser pour mieux régner": "Diviser pour mieux régner",
"Conceptrice Développeuse FullStack": "Conceptrice-Développeuse FullStack",
"Expérience": "Expérience",
"Formation": "Formation",
"Licence CDED": "Licence CDED",
"(Concepteur-développeur en environnement distribué)": "(Concepteur·ice-développeur·se en environnement distribué)",
"Licence 3 Math-Info": "Licence 3 Math-Info",
"DUT Informatique": "DUT Informatique",
"ADDRESS": {
"IUT_ROBERT_SCHUMAN": "IUT Robert Schuman, 67411 Illkirch-Graffenstaden",
"UFR_MATH_INFO": "UFR de Mathématiques et d'Informatique, 67084 Strasbourg"
},
"Développeuse senior chez Jaune de Mars": "Développeuse senior chez Jaune de Mars",
"Logiciel de gestion de parc/pannes d'appareils": "Logiciel de gestion de parc et de suivi des pannes",
"Migration progressive des outils et technologies internes": "Migration progressive des outils et technologies internes",
"Mise en place d'outils d'analyse de code": "Mise en place d'outils d'analyse de code",
"Implémentation d'un système d'intégration continue": "Implémentation d'un système d'intégration continue",
"Développeuse logiciel chez Caldera": "Développeuse logiciel chez Caldera",
"Logiciels d'automatisation du prépresse": "Logiciels d'automatisation du prépresse",
"Référente technique des solutions web internes": "Référente technique des solutions web internes",
"Veille et mises à jours technologiques": "Veille et mises à jour technologiques",
"Amélioration du système d'intégration continue": "Amélioration du système d'intégration continue",
"Développeuse web chez Thuria": "Développeuse web chez Thuria",
"Amélioration des outils de développement internes": "Amélioration des outils de développement internes",
"Réalisation de sites vitrines": "Réalisation de sites vitrines",
"Conceptrice développeuse chez AZ Conception": "Conceptrice-développeuse chez AZ Conception",
"Solution de géolocalisation et réservation de taxi": "Solution de géolocalisation et de réservation de taxi",
"ERP, sites e-commerce et sites vitrines": "ERP, sites e-commerce et sites vitrines",
"2023-Aujourd'hui": "2023-Aujourd'hui",
"Imprimer": "Imprimer",
"Mon CV": "Mon CV",
"Menu": "Menu",
"Technologies utilisées": "Technologies utilisées",
"Missions réalisées": "Missions réalisées",
"Prononcé": "Prononcé"
}

7
src/locales/index.ts Normal file
View file

@ -0,0 +1,7 @@
import en from "./en.json";
import fr from "./fr.json";
export default {
en,
fr,
};

26
src/main.ts Normal file
View file

@ -0,0 +1,26 @@
import "./assets/style.css";
import "@fortawesome/fontawesome-free/css/fontawesome.min.css";
import "@fortawesome/fontawesome-free/css/brands.min.css";
import "@fortawesome/fontawesome-free/css/solid.min.css";
import "@fortawesome/fontawesome-free/css/regular.min.css";
import "./assets/Fira_Code_v6.2/fira_code.css";
import { createApp } from "vue";
import { createI18n } from "vue-i18n";
import translations from "./locales";
import App from "./App.vue";
const navigatorLanguage = navigator.language
.substring(0, 2)
.toLocaleLowerCase();
const locale =
["en", "fr"].includes(navigatorLanguage) ? navigatorLanguage : "fr";
const i18n = createI18n({
legacy: false, // you must set `false`, to use Composition API
locale: locale, // set locale
fallbackLocale: "fr", // set fallback locale,
messages: translations,
});
createApp(App).use(i18n).mount("#app");

12
tsconfig.app.json Normal file
View file

@ -0,0 +1,12 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

8
tsconfig.json Normal file
View file

@ -0,0 +1,8 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
}
]
}

16
vite.config.ts Normal file
View file

@ -0,0 +1,16 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { analyzer } from 'vite-bundle-analyzer'
export default defineConfig({
plugins: [
vue(),
analyzer(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})