Merge branch 'chore/portfolio'
Some checks failed
ci/woodpecker/push/publish Pipeline failed

This commit is contained in:
Mylloon 2023-04-11 02:13:54 +02:00
commit 7f01fe98db
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
13 changed files with 258 additions and 314 deletions

View file

@ -0,0 +1,6 @@
---
title: Botanique
link: https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique
---
✨ Bot Discord libre et écrit en Typescript.

View file

@ -0,0 +1,6 @@
---
title: feurBot
link: https://git.mylloon.fr/Anri/feurBot
---
Réponds à certains tweets (exemple : si un tweet fini par _quoi_, le bot répondra _feur_).

View file

@ -0,0 +1,6 @@
---
title: cal8tor
link: https://git.mylloon.fr/Anri/cal8tor
---
Lecteur de l'emploi du temps pour la licence d'informatique de Paris 8, avec possibilité d'exporter le calendrier en ICS.

View file

@ -0,0 +1,6 @@
---
title: confOS
link: https://git.mylloon.fr/Anri/confOS
---
Scripts et fichiers de configuration pour me simplifier la vie quand je réinstalle mes systèmes d'exploitation.

View file

@ -0,0 +1,6 @@
---
title: Constnium
link: https://git.mylloon.fr/Anri/Constnium
---
Calculez votre propre constante sur la base de votre prénom en multipliant de vraies constantes mathématiques entre elles. Une [démo est disponible ici](https://constnium.mylloon.fr/).

View file

@ -0,0 +1,6 @@
---
title: csh
link: https://git.mylloon.fr/Anri/csh
---
Application python pour tricher dans le jeu compétitif Counter-Strike : Global Offensive. Repose sur le principe de cheat externe. C'était marrant à faire.

View file

@ -0,0 +1,6 @@
---
title: prose_dl
link: https://git.mylloon.fr/Anri/prose_dl
---
Permets de télécharger tous les posts d'un utilisateur depuis [prose.sh](https://prose.sh/). J'ai [écrit ici](https://anri.prose.sh/prose_dl) sur son développement.

5
data/projects/univ.md Normal file
View file

@ -0,0 +1,5 @@
---
title: Projet de l'université
---
✨ Parce que j'ai fait plusieurs projets dont je suis fier mais qui ne mérite pas une place entière sur cette page comme mon [premier pendu](https://git.mylloon.fr/Paris8/penduEnC) ou une jolie [interface manager/caisser](https://git.mylloon.fr/Paris8/GesMag), vous pouvez simplement aller voir la liste des projets en vrac qui sont disponibles sur mon [git](https://git.mylloon.fr/Paris8/).

View file

@ -1,7 +1,11 @@
use actix_web::{get, web, HttpResponse, Responder};
use glob::glob;
use ramhorns::Content;
use crate::config::Config;
use crate::{
config::Config,
template::{read_md, File},
};
#[get("/portfolio")]
pub async fn page(config: web::Data<Config>) -> impl Responder {
@ -9,8 +13,36 @@ pub async fn page(config: web::Data<Config>) -> impl Responder {
}
#[derive(Content)]
struct PortfolioTemplate {}
struct PortfolioTemplate {
page_title: String,
bots_app: Vec<File>,
persos_app: Vec<File>,
univ_content: String,
}
pub fn get_page(config: Config) -> std::string::String {
config.tmpl.render("portfolio.html", PortfolioTemplate {})
let projects_dir = "data/projects";
let ext = ".md";
// Get bots apps
let mut bots_apps = Vec::new();
for entry in glob(&format!("{projects_dir}/bots/*{ext}")).unwrap() {
bots_apps.push(read_md(&entry.unwrap().to_string_lossy()));
}
// Get perso apps
let mut perso_apps = Vec::new();
for entry in glob(&format!("{projects_dir}/perso/*{ext}")).unwrap() {
perso_apps.push(read_md(&entry.unwrap().to_string_lossy()));
}
config.tmpl.render(
"portfolio.html",
PortfolioTemplate {
page_title: "Portfolio".to_string(),
bots_app: bots_apps,
persos_app: perso_apps,
univ_content: read_md(&format!("{projects_dir}/univ{ext}")).content,
},
)
}

View file

@ -54,7 +54,13 @@ pub struct Metadata {
pub syntax_highlight: bool,
}
pub fn read_md(filename: &str) -> (Metadata, String) {
#[derive(Content)]
pub struct File {
pub metadata: Metadata,
pub content: String,
}
pub fn read_md(filename: &str) -> File {
// Read markdown file
let mut text = std::fs::read_to_string(filename).unwrap();
@ -106,12 +112,12 @@ pub fn read_md(filename: &str) -> (Metadata, String) {
_ => false,
});
(
Metadata {
File {
metadata: Metadata {
info: metadata,
mermaid: presence_mermaid,
syntax_highlight: presence_code,
},
html,
)
content: html,
}
}

View file

@ -1,60 +1,60 @@
/* Title font */
@import url("https://fonts.googleapis.com/css2?family=Overpass:wght@200&display=swap");
@import url("https://api.fonts.coollabs.io/css2?family=Overpass:wght@200&display=swap");
/* Normal font */
@font-face {
font-family: "Luciole";
font-style: normal;
font-weight: normal;
src: url(/css/fonts/Luciole-Regular.ttf);
font-family: "Luciole";
font-style: normal;
font-weight: normal;
src: url(/css/fonts/Luciole-Regular.ttf);
}
/* Italic font */
@font-face {
font-family: "Luciole";
font-style: italic;
font-weight: normal;
src: url(/css/fonts/Luciole-Regular-Italic.ttf);
font-family: "Luciole";
font-style: italic;
font-weight: normal;
src: url(/css/fonts/Luciole-Regular-Italic.ttf);
}
/* Bold fond */
@font-face {
font-family: "Luciole";
font-style: normal;
font-weight: bold;
src: url(/css/fonts/Luciole-Bold.ttf);
font-family: "Luciole";
font-style: normal;
font-weight: bold;
src: url(/css/fonts/Luciole-Bold.ttf);
}
/* Bold italic font */
@font-face {
font-family: "Luciole";
font-style: italic;
font-weight: bold;
src: url(/css/fonts/Luciole-Bold-Italic.ttf);
font-family: "Luciole";
font-style: italic;
font-weight: bold;
src: url(/css/fonts/Luciole-Bold-Italic.ttf);
}
/* Page bottom */
footer {
position: absolute;
bottom: 0;
margin: -8px;
width: 100%;
height: 2.5rem;
position: absolute;
bottom: 0;
margin: -8px;
width: 100%;
height: 2.5rem;
}
/* Regular tags */
html {
position: relative;
min-height: 100vh;
height: 100%;
scroll-behavior: smooth;
position: relative;
min-height: 100vh;
height: 100%;
scroll-behavior: smooth;
}
body {
position: relative;
padding-bottom: 3em;
min-height: 90%;
background-color: rgb(24, 24, 24);
position: relative;
padding-bottom: 3em;
min-height: 90%;
background-color: rgb(24, 24, 24);
}
p,
@ -63,186 +63,186 @@ h2,
h3,
li,
a {
font-family: "Luciole", sans-serif;
font-family: "Luciole", sans-serif;
}
::selection {
color: rgb(255, 255, 255);
background: rgba(124, 75, 173, 0.486);
color: rgb(255, 255, 255);
background: rgba(124, 75, 173, 0.486);
}
/* Frames */
h1.subtitle {
text-decoration: none;
color: rgb(28, 118, 236);
text-decoration: none;
color: rgb(28, 118, 236);
}
h1#title {
text-align: center;
color: rgb(28, 236, 174);
text-align: center;
color: rgb(28, 236, 174);
}
h2.subtitle,
h2.subtitle a {
color: rgb(28, 118, 236) !important;
color: rgb(28, 118, 236) !important;
}
h3.subsubtitle,
#content h3.subsubtitle a {
text-align: left;
color: rgb(149, 87, 201);
text-align: left;
color: rgb(149, 87, 201);
}
#content h3.subsubtitle a:hover {
color: rgb(0, 181, 236);
transition: color 0.1s;
color: rgb(0, 181, 236);
transition: color 0.1s;
}
div#content {
margin-left: auto;
margin-right: auto;
margin-top: 2%;
padding: 0.9% 0.9% 0.9% 0.9%;
width: 42%;
border-radius: 6px;
border: 1px solid rgb(170, 170, 170);
text-align: center;
margin-left: auto;
margin-right: auto;
margin-top: 2%;
padding: 0.9% 0.9% 0.9% 0.9%;
width: 42%;
border-radius: 6px;
border: 1px solid rgb(170, 170, 170);
text-align: center;
}
@media only screen and (max-width: 850px) {
/* Mobile display */
div#content {
width: 90%;
}
/* Mobile display */
div#content {
width: 90%;
}
}
#content a,
#content a:visited,
#content ul {
text-decoration: none;
color: rgb(201, 201, 201);
text-align: center;
text-decoration: none;
color: rgb(201, 201, 201);
text-align: center;
}
#content p {
text-decoration: none;
color: rgb(201, 201, 201);
text-align: center;
padding: 0.7em;
text-decoration: none;
color: rgb(201, 201, 201);
text-align: center;
padding: 0.7em;
}
#content a:hover {
color: rgb(0, 181, 236);
transition: color 0.1s;
color: rgb(0, 181, 236);
transition: color 0.1s;
}
/* https://stackoverflow.com/a/40244401/15436737 */
#content a {
position: relative;
text-decoration: none;
display: inline-block;
position: relative;
text-decoration: none;
display: inline-block;
}
#content a:after {
display: block;
content: "";
border-bottom: solid 3px;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
transform-origin: 100% 50%;
display: block;
content: "";
border-bottom: solid 3px;
transform: scaleX(0);
transition: transform 250ms ease-in-out;
transform-origin: 100% 50%;
}
#content a:hover:after {
transform: scaleX(1);
transform-origin: 0 50%;
transform: scaleX(1);
transform-origin: 0 50%;
}
/* ------------------------------------------- */
div.subcontent {
margin-left: auto;
margin-right: auto;
margin-top: 5%;
padding: 1.2% 1.2% 1.2% 1.2%;
width: 78%;
border-radius: 6px;
border: 1px solid rgb(170, 170, 170);
text-align: center;
margin-left: auto;
margin-right: auto;
margin-top: 5%;
padding: 1.2% 1.2% 1.2% 1.2%;
width: 78%;
border-radius: 6px;
border: 1px solid rgb(170, 170, 170);
text-align: center;
}
#listecontent li {
margin-bottom: 0.5em;
margin-bottom: 0.5em;
}
/* Index */
.index {
height: 100%;
padding: 0;
margin: 0;
height: 100%;
padding: 0;
margin: 0;
}
.divIndex {
width: 50%;
height: 50%;
float: left;
width: 50%;
height: 50%;
float: left;
}
button.buttonIndex {
width: 100%;
height: 100%;
border: none;
opacity: 0.6;
transition: all 0.1s;
cursor: pointer;
width: 100%;
height: 100%;
border: none;
opacity: 0.6;
transition: all 0.1s;
cursor: pointer;
}
span.buttonIndex {
font-family: "Overpass", sans-serif;
font-size: 500%;
cursor: pointer;
display: inline-block;
position: relative;
transition: 0.5s;
font-family: "Overpass", sans-serif;
font-size: 500%;
cursor: pointer;
display: inline-block;
position: relative;
transition: 0.5s;
}
.buttonIndex:hover,
span.buttonIndex:after {
opacity: 1;
padding-right: 2%;
opacity: 1;
padding-right: 2%;
}
#buttonIndexTL {
background-color: rgb(0, 255, 255);
background-color: rgb(0, 255, 255);
}
#buttonIndexTR {
background-color: rgb(21, 255, 0);
background-color: rgb(21, 255, 0);
}
#buttonIndexBL {
background-color: rgb(187, 255, 0);
background-color: rgb(187, 255, 0);
}
#buttonIndexBR {
background-color: rgb(208, 88, 255);
background-color: rgb(208, 88, 255);
}
/* Back links going to the index */
footer.backToIndexPage {
text-align: center;
text-align: center;
}
footer.backToIndexPage a {
color: rgb(114, 180, 76);
text-decoration: none;
color: rgb(114, 180, 76);
text-decoration: none;
}
footer.backToIndexPage a:hover {
color: rgb(152, 187, 132);
color: rgb(152, 187, 132);
}
/* Hide content */
.hide {
display: none;
display: none;
}

37
templates/header.html Normal file
View file

@ -0,0 +1,37 @@
<head dir="rtl">
<title>{{#data}}{{page_title}}{{/data}} - {{app_name}}</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="css/style.css" />
<meta name="author" content="Mylloon" />
<meta name="description" content="{{ desc }}" />
<base target="_blank" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="icons/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="icons/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="icons/favicon-16x16.png"
/>
<link rel="manifest" href="icons/site.webmanifest" />
<link rel="mask-icon" href="icons/safari-pinned-tab.svg" color="#5bbad5" />
<link rel="shortcut icon" href="icons/favicon.ico" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta name="msapplication-config" content="icons/browserconfig.xml" />
<meta name="theme-color" content="#2a2424" />
<meta content="{{ title }}" property="og:title" />
<meta content="{{ desc }}" property="og:description" />
<meta content="icons/apple-touch-icon.png" property="og:image" />
<meta content="#43B581" data-react-helmet="true" name="theme-color" />
</head>

View file

@ -1,218 +1,40 @@
<!DOCTYPE html>
<html class="index" lang="fr">
<head dir="rtl">
<title>Mon portfolio - Anri</title>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="css/style.css" />
<meta name="author" content="Mylloon" />
<meta name="description" content="Portfolio d'Anri Kennel" />
<base target="_blank" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="icons/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="icons/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="icons/favicon-16x16.png"
/>
<link rel="manifest" href="icons/site.webmanifest" />
<link rel="mask-icon" href="icons/safari-pinned-tab.svg" color="#5bbad5" />
<link rel="shortcut icon" href="icons/favicon.ico" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta name="msapplication-config" content="icons/browserconfig.xml" />
<meta name="theme-color" content="#2a2424" />
<meta content="Portfolio" property="og:title" />
<meta content="Portfolio d'Anri Kennel" property="og:description" />
<meta content="icons/apple-touch-icon.png" property="og:image" />
<meta content="#43B581" data-react-helmet="true" name="theme-color" />
</head>
{{> header.html }}
<body>
{{#data}}
<h1 id="title">Projets qui me tiennent à coeur</h1>
<div id="content">
<h2 class="subtitle">Bots</h2>
<div class="subcontent">
{{#bots_app}} {{#metadata}} {{#info}}
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/ConfrerieDuKassoulait/KassouBot"
>KassouBot</a
>
<a href="{{link}}">{{title}}</a>
</h3>
<div class="subcontent">
<p>
✨ Basé sur une
<a href="https://git.mylloon.fr/Anri/ravaBot">ancienne version</a>,
permet de faire plusieurs choses comme maintenir des reminders, des
todos, écouter de la musique, etc.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/feurBot">feurBot</a>
</h3>
<div class="subcontent">
<p>
Réponds à certains tweets (exemple : si un tweet fini par
<em>quoi</em>, le bot répondra <em>feur</em>).
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/ConfrerieDuKassoulait/Bot-Tom"
>Bot-Tom</a
>
</h3>
<div class="subcontent">
<p>
Utilise SQLite pour avoir des commandes personnalisables sur Twitch.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique"
>Botanique</a
>
</h3>
<div class="subcontent">
<p>
<a href="https://git.mylloon.fr/ConfrerieDuKassoulait/KassouBot"
>Pas ma première expérience</a
>&nbsp;en matière de bot Discord. Actuellement en actif
développement. Complètement libre et écrit en Typescript.
</p>
</div>
{{/info}} {{/metadata}}
<div class="subcontent">{{&content }}</div>
{{/bots_app}}
<br />
</div>
<h2 class="subtitle">
<a href="https://git.mylloon.fr/Paris8/">Projet de l'université</a>
<a href="https://git.mylloon.fr/Paris8">Projet de l'université</a>
</h2>
<div class="subcontent">
<p>
✨ Parce que j'ai fait plusieurs projets dont je suis fier mais qui ne
mérite pas une place entière sur cette page comme mon
<a href="https://git.mylloon.fr/Paris8/penduEnC">premier pendu</a
>&nbsp;ou une jolie
<a href="https://git.mylloon.fr/Paris8/GesMag"
>interface manager/caisser</a
>, vous pouvez simplement aller voir la liste des projets en vrac qui
sont disponibles sur mon
<a href="https://git.mylloon.fr/Paris8/">git</a>.
</p>
</div>
<div class="subcontent">{{&univ_content}}</div>
<h2 class="subtitle">Projets perso</h2>
<div class="subcontent">
{{#persos_app}} {{#metadata}} {{#info}}
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/Constnium">Constnium</a>
<a href="{{link}}">{{title}}</a>
</h3>
<div class="subcontent">
<p>
Calculez votre propre constante sur la base de votre prénom en
multipliant de vraies constantes mathématiques entre elles. Une
<a href="https://constnium.mylloon.fr/">démo est disponible ici</a>.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/cal8tor">cal8tor</a>
</h3>
<div class="subcontent">
<p>
Lecteur de l'emploi du temps pour la licence d'informatique de Paris
8, avec possibilité d'exporter le calendrier en ICS.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/prose_dl">prose_dl</a>
</h3>
<div class="subcontent">
<p>
Permets de télécharger tous les posts d'un utilisateur depuis
<a href="https://prose.sh/">prose.sh</a>. J'ai
<a href="https://anri.prose.sh/prose_dl">écrit ici</a>&nbsp;sur son
développement.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/downloadcodium"
>downloadCodium</a
>
</h3>
<div class="subcontent">
<p>
Petit script qui permet de télécharger et garder à-jour facilement
la version .AppImage VSCodium.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/confOS">confOS</a>
</h3>
<div class="subcontent">
<p>
Scripts et fichiers de configuration pour me simplifier la vie quand
je réinstalle mes systèmes d'exploitation.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/mobilismScrap">mobilismScrap</a>
</h3>
<div class="subcontent">
<p>Deux versions, une en python et une en Kotlin :</p>
<ul id="listecontent">
<li>
Celle en Python permet juste de lancer, en ligne de commande, une
recherche qui va récupérer sur le forum Mobilism des versions
crackées d'applications mobiles.
</li>
<li>
✨ Celle en Kotlin est une application android qui fait
basiquement la même chose mais avec une interface plus sympa.
</li>
</ul>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/CleanTemporaryFiles"
>cleanTemporaryFiles</a
>
</h3>
<div class="subcontent">
<p>
Petit script Windows qui lance quelques commandes pour supprimer les
fichiers temporaires.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/microphonePopcat"
>microphonePopcat</a
>
</h3>
<div class="subcontent">
<p>
Petit programme en python qui permet d'ouvrir la bouche d'un chat
quand on parle.
</p>
</div>
<h3 class="subsubtitle">
<a href="https://git.mylloon.fr/Anri/RenameFilesForPlex"
>renameFilesForPlex</a
>
</h3>
<div class="subcontent">
<p>
Petit programme pour renommer des fichiers vidéo (séries) pour
qu'ils soient lisibles directement par Plex.
</p>
</div>
{{/info}} {{/metadata}}
<div class="subcontent">{{&content }}</div>
{{/persos_app}}
<br />
</div>
</div>
<footer class="backToIndexPage">
<a href="/" target="_self">Retour à la page principale</a>
</footer>
{{/data}}
</body>
</html>