Merge pull request #2 from LucasVbr/dev

Dev
This commit is contained in:
Lucàs
2024-01-09 15:22:58 +01:00
committed by GitHub
31 changed files with 628 additions and 405 deletions
+4 -1
View File
@@ -1 +1,4 @@
.idea/
.idea/
.vscode/
.DS_Store
+45 -38
View File
@@ -1,49 +1,56 @@
![Hi I'm Lucàs👋](https://svg-banners.vercel.app/api?type=glitch&text1=Hi+I%27m+Luc%C3%A0s%F0%9F%91%8B&width=1000&height=400)
<header>
<div align="center">
![Hi I'm Lucàs👋](assets/banner.svg)
</div>
</header>
## 🚀 About Me
I&#39;m a passionate developer from 🇫🇷 **Albi, France**.
## 🔗 Links
[![My Portfolio](https://img.shields.io/static/v1?style=for-the-badge&amp;label=+&amp;logoColor=white&amp;message=My+Portfolio&amp;logo=ko-fi&amp;color=000)](https://lucasvbr.github.io/links/?portfolio)
[![Linkedin](https://img.shields.io/static/v1?style=for-the-badge&amp;label=+&amp;logoColor=white&amp;message=Linkedin&amp;color=0e76a8&amp;logo=linkedin)](https://www.linkedin.com/in/lucasvbr)
[![FreeCodeCamp](https://img.shields.io/static/v1?style=for-the-badge&amp;label=+&amp;logoColor=white&amp;message=FreeCodeCamp&amp;color=0a0a23&amp;logo=freecodecamp)](https://www.freecodecamp.org/LucasVbr)
[![OpenClassRooms](https://img.shields.io/static/v1?style=for-the-badge&amp;label=+&amp;logoColor=white&amp;message=OpenClassRooms&amp;color=7451eb&amp;logo=openclassrooms)](https://openclassrooms.com/fr/members/97j9zltv6225)
[![Exercism](https://img.shields.io/static/v1?style=for-the-badge&amp;label=+&amp;logoColor=white&amp;message=Exercism&amp;color=2e57e8&amp;logo=exercism)](https://exercism.org/profiles/LucasVbr)
I'm a passionate developer from 🇫🇷 **Pau, France**.
## 🔗 Social Links
[![Linkedin](https://img.shields.io/static/v1?message=LinkedIn&style=for-the-badge&logo=linkedin&logoColor=white&label=+&color=0A66C2&link=https%3A%2F%2Fwww.linkedin.com%2Fin%2Flucasvbr)](https://www.linkedin.com/in/lucasvbr)
[![FreeCodeCamp](https://img.shields.io/static/v1?message=freeCodeCamp&style=for-the-badge&logo=freecodecamp&logoColor=white&label=+&color=0A0A23&link=https%3A%2F%2Fwww.freecodecamp.org%2FLucasVbr)](https://www.freecodecamp.org/LucasVbr)
[![OpenClassRooms](https://img.shields.io/static/v1?message=OpenClassRooms&style=for-the-badge&logoColor=white&label=+&color=black&link=https%3A%2F%2Fopenclassrooms.com%2Ffr%2Fmembers%2F97j9zltv6225)](https://openclassrooms.com/fr/members/97j9zltv6225)
[![Exercism](https://img.shields.io/static/v1?message=Exercism&style=for-the-badge&logo=exercism&logoColor=white&label=+&color=009CAB&link=https%3A%2F%2Fexercism.org%2Fprofiles%2FLucasVbr)](https://exercism.org/profiles/LucasVbr)
## 🛠 Skills
![Android](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Android&amp;color=3DDC84&amp;logo=android)
![Angular](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Angular&amp;color=DD0031&amp;logo=angular)
![Bootstrap](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Bootstrap&amp;color=7952B3&amp;logo=bootstrap)
![Bulma](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Bulma&amp;color=00D1B2&amp;logo=bulma)
![C](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=C&amp;color=A8B9CC&amp;logo=c)
![CSS3](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=CSS3&amp;color=1572B6&amp;logo=css3)
![Deno](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Deno&amp;color=000&amp;logo=deno)
![Docker](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Docker&amp;color=2496ED&amp;logo=docker)
![Express](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Express&amp;color=000&amp;logo=express)
![Figma](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Figma&amp;color=F24E1E&amp;logo=figma)
![Git](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Git&amp;color=F05032&amp;logo=git)
![GNU Bash](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=GNU+Bash&amp;color=4EAA25&amp;logo=gnubash)
![HTML5](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=HTML5&amp;color=E34F26&amp;logo=html5)
![JavaScript](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=JavaScript&amp;color=F7DF1E&amp;logo=javascript)
![MariaDB](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=MariaDB&amp;color=003545&amp;logo=mariadb)
![MongoDB](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=MongoDB&amp;color=47A248&amp;logo=mongodb)
![MySQL](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=MySQL&amp;color=4479A1&amp;logo=mysql)
![Node.js](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Node.js&amp;color=339933&amp;logo=nodedotjs)
![Nunjucks](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Nunjucks&amp;color=1C4913&amp;logo=nunjucks)
![OCaml](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=OCaml&amp;color=EC6813&amp;logo=ocaml)
![PHP](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=PHP&amp;color=777BB4&amp;logo=php)
![PostgreSQL](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=PostgreSQL&amp;color=4169E1&amp;logo=postgresql)
![Pug](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Pug&amp;color=A86454&amp;logo=pug)
![Python](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Python&amp;color=3776AB&amp;logo=python)
![React](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=React&amp;color=61DAFB&amp;logo=react)
![SQLite](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=SQLite&amp;color=003B57&amp;logo=sqlite)
![Symfony](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=Symfony&amp;color=000&amp;logo=symfony)
![TypeScript](https://img.shields.io/static/v1?style=flat&amp;label=+&amp;logoColor=white&amp;message=TypeScript&amp;color=3178C6&amp;logo=typescript)
![Android](https://img.shields.io/static/v1?message=Android&logo=android&logoColor=white&label=+&color=3DDC84)
![Angular](https://img.shields.io/static/v1?message=Angular&logo=angular&logoColor=white&label=+&color=DD0031)
![Bootstrap](https://img.shields.io/static/v1?message=Bootstrap&logo=bootstrap&logoColor=white&label=+&color=7952B3)
![Bulma](https://img.shields.io/static/v1?message=Bulma&logo=bulma&logoColor=white&label=+&color=00D1B2)
![C](https://img.shields.io/static/v1?message=C&logo=c&logoColor=white&label=+&color=A8B9CC)
![CSS3](https://img.shields.io/static/v1?message=CSS3&logo=css3&logoColor=white&label=+&color=1572B6)
![Deno](https://img.shields.io/static/v1?message=Deno&logo=deno&logoColor=white&label=+&color=000000)
![Docker](https://img.shields.io/static/v1?message=Docker&logo=docker&logoColor=white&label=+&color=2496ED)
![Express](https://img.shields.io/static/v1?message=Express&logo=express&logoColor=white&label=+&color=000000)
![Figma](https://img.shields.io/static/v1?message=Figma&logo=figma&logoColor=white&label=+&color=F24E1E)
![GNU Bash](https://img.shields.io/static/v1?message=GNU_Bash&logo=gnubash&logoColor=white&label=+&color=4EAA25)
![Git](https://img.shields.io/static/v1?message=Git&logo=git&logoColor=white&label=+&color=F05032)
![HTML5](https://img.shields.io/static/v1?message=HTML5&logo=html5&logoColor=white&label=+&color=E34F26)
![JavaScript](https://img.shields.io/static/v1?message=JavaScript&logo=javascript&logoColor=white&label=+&color=F7DF1E)
![MariaDB](https://img.shields.io/static/v1?message=MariaDB&logo=mariadb&logoColor=white&label=+&color=003545)
![MongoDB](https://img.shields.io/static/v1?message=MongoDB&logo=mongodb&logoColor=white&label=+&color=47A248)
![MySQL](https://img.shields.io/static/v1?message=MySQL&logo=mysql&logoColor=white&label=+&color=4479A1)
![Node.js](https://img.shields.io/static/v1?message=Node.js&logo=nodedotjs&logoColor=white&label=+&color=339933)
![Nunjucks](https://img.shields.io/static/v1?message=Nunjucks&logo=nunjucks&logoColor=white&label=+&color=1C4913)
![OCaml](https://img.shields.io/static/v1?message=OCaml&logo=ocaml&logoColor=white&label=+&color=EC6813)
![PHP](https://img.shields.io/static/v1?message=PHP&logo=php&logoColor=white&label=+&color=777BB4)
![PostgreSQL](https://img.shields.io/static/v1?message=PostgreSQL&logo=postgresql&logoColor=white&label=+&color=4169E1)
![Pug](https://img.shields.io/static/v1?message=Pug&logo=pug&logoColor=white&label=+&color=A86454)
![Python](https://img.shields.io/static/v1?message=Python&logo=python&logoColor=white&label=+&color=3776AB)
![React](https://img.shields.io/static/v1?message=React&logo=react&logoColor=white&label=+&color=61DAFB)
![SQLite](https://img.shields.io/static/v1?message=SQLite&logo=sqlite&logoColor=white&label=+&color=003B57)
![Symfony](https://img.shields.io/static/v1?message=Symfony&logo=symfony&logoColor=white&label=+&color=000000)
![TypeScript](https://img.shields.io/static/v1?message=TypeScript&logo=typescript&logoColor=white&label=+&color=3178C6)
---
<footer>
<div align="center">
![SVG Stats](https://github-stats-alpha.vercel.app/api?username=LucasVbr&cc=000&tc=fff&ic=fff&bc=000)
@@ -52,5 +59,5 @@ I&#39;m a passionate developer from 🇫🇷 **Albi, France**.
![FreeCodeCamp Points](https://img.shields.io/freecodecamp/points/lucasvbr?label=FreeCodeCamp%20points)
![Made with love](https://img.shields.io/badge/-made%20with%20%E2%9D%A4%EF%B8%8F-red)
</div>
</div>
</footer>
+222
View File
@@ -0,0 +1,222 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 1000 400" width="1000" height="400">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml">
<style>
.container {
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 0;
width: 100%;
height: 400px;
/* background: linear-gradient(-45deg, #fc5c7d, #6a82fb, #05dfd7); */
background: #333;
background-size: 600% 400%;
border-radius: 10px;
/* color: white; */
text-align: center;
}
h1 {
text-align: center;
color: #fff;
font-size: 5em;
letter-spacing: 8px;
font-family: "Lucida Console", Monaco, monospace;
font-weight: 400;
/*Create overlap*/
margin: 0;
line-height: 0;
/*Animation*/
animation: glitch1 2.5s infinite;
}
h1:nth-child(2) {
color: #67f3da;
animation: glitch2 2.5s infinite;
}
h1:nth-child(3) {
color: #f16f6f;
animation: glitch3 2.5s infinite;
}
/*Keyframes*/
@keyframes glitch1 {
0% {
transform: none;
opacity: 1;
}
7% {
transform: skew(-0.5deg, -0.9deg);
opacity: 0.75;
}
10% {
transform: none;
opacity: 1;
}
27% {
transform: none;
opacity: 1;
}
30% {
transform: skew(0.8deg, -0.1deg);
opacity: 0.75;
}
35% {
transform: none;
opacity: 1;
}
52% {
transform: none;
opacity: 1;
}
55% {
transform: skew(-1deg, 0.2deg);
opacity: 0.75;
}
50% {
transform: none;
opacity: 1;
}
72% {
transform: none;
opacity: 1;
}
75% {
transform: skew(0.4deg, 1deg);
opacity: 0.75;
}
80% {
transform: none;
opacity: 1;
}
100% {
transform: none;
opacity: 1;
}
}
@keyframes glitch2 {
0% {
transform: none;
opacity: 0.25;
}
7% {
transform: translate(-2px, -3px);
opacity: 0.5;
}
10% {
transform: none;
opacity: 0.25;
}
27% {
transform: none;
opacity: 0.25;
}
30% {
transform: translate(-5px, -2px);
opacity: 0.5;
}
35% {
transform: none;
opacity: 0.25;
}
52% {
transform: none;
opacity: 0.25;
}
55% {
transform: translate(-5px, -1px);
opacity: 0.5;
}
50% {
transform: none;
opacity: 0.25;
}
72% {
transform: none;
opacity: 0.25;
}
75% {
transform: translate(-2px, -6px);
opacity: 0.5;
}
80% {
transform: none;
opacity: 0.25;
}
100% {
transform: none;
opacity: 0.25;
}
}
@keyframes glitch3 {
0% {
transform: none;
opacity: 0.25;
}
7% {
transform: translate(2px, 3px);
opacity: 0.5;
}
10% {
transform: none;
opacity: 0.25;
}
27% {
transform: none;
opacity: 0.25;
}
30% {
transform: translate(5px, 2px);
opacity: 0.5;
}
35% {
transform: none;
opacity: 0.25;
}
52% {
transform: none;
opacity: 0.25;
}
55% {
transform: translate(5px, 1px);
opacity: 0.5;
}
50% {
transform: none;
opacity: 0.25;
}
72% {
transform: none;
opacity: 0.25;
}
75% {
transform: translate(2px, 6px);
opacity: 0.5;
}
80% {
transform: none;
opacity: 0.25;
}
100% {
transform: none;
opacity: 0.25;
}
}
</style>
<div class="container">
<h1>Hi I'm Lucàs👋</h1>
<h1>Hi I'm Lucàs👋</h1>
<h1>Hi I'm Lucàs👋</h1>
</div>
</div>
</foreignObject>
<script xmlns=""/></svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

-3
View File
@@ -1,3 +0,0 @@
const ImageComponent = (label: string, url: URL) => `![${label}](${url})`;
export default ImageComponent
-3
View File
@@ -1,3 +0,0 @@
const LinkComponent = (label: string, url: string) => `[${label}](${url})`;
export default LinkComponent;
+39 -123
View File
@@ -1,128 +1,44 @@
file:
template: "template.njk"
output: "README.md"
user: "LucasVbr"
view:
userName: "LucasVbr"
socials:
- name: "Linkedin"
url: "https://www.linkedin.com/in/lucasvbr"
banner:
type: "glitch"
text1: "Hi I'm Lucàs👋"
width: 1000
height: 400
- name: "FreeCodeCamp"
url: "https://www.freecodecamp.org/LucasVbr"
about: "I'm a passionate developer from 🇫🇷 **Albi, France**."
- name: "OpenClassRooms"
url: "https://openclassrooms.com/fr/members/97j9zltv6225"
links:
- label:
message: "My Portfolio"
logo: "ko-fi"
url: "https://lucasvbr.github.io/links/?portfolio"
- name: "Exercism"
url: "https://exercism.org/profiles/LucasVbr"
- label:
message: "Linkedin"
color: "0e76a8"
url: "https://www.linkedin.com/in/lucasvbr"
- label:
message: "FreeCodeCamp"
color: "0a0a23"
url: "https://www.freecodecamp.org/LucasVbr"
- label:
message: "OpenClassRooms"
color: "7451eb"
url: "https://openclassrooms.com/fr/members/97j9zltv6225"
- label:
message: "Exercism"
color: "2e57e8"
url: "https://exercism.org/profiles/LucasVbr"
skills:
- message: "Android"
color: "3DDC84"
- message: "Angular"
color: "DD0031"
- message: "Bootstrap"
color: "7952B3"
- message: "Bulma"
color: "00D1B2"
- message: "C"
color: "A8B9CC"
- message: "CSS3"
color: "1572B6"
- message: "Deno"
- message: "Docker"
color: "2496ED"
- message: "Express"
- message: "Figma"
color: "F24E1E"
- message: "Git"
color: "F05032"
- message: "GNU Bash"
color: "4EAA25"
- message: "HTML5"
color: "E34F26"
- message: "JavaScript"
color: "F7DF1E"
- message: "MariaDB"
color: "003545"
- message: "MongoDB"
color: "47A248"
- message: "MySQL"
color: "4479A1"
- message: "Node.js"
color: "339933"
logo: "nodedotjs"
- message: "Nunjucks"
color: "1C4913"
- message: "OCaml"
color: "EC6813"
- message: "PHP"
color: "777BB4"
- message: "PostgreSQL"
color: "4169E1"
- message: "Pug"
color: "A86454"
- message: "Python"
color: "3776AB"
- message: "React"
color: "61DAFB"
- message: "SQLite"
color: "003B57"
- message: "Symfony"
- message: "TypeScript"
color: "3178C6"
footer:
- "![Profile Views](https://komarev.com/ghpvc/?username=lucasvbr&amp;amp;label=Profile%20views&amp;amp;color=0e75b6&amp;amp;style=flat)"
- "![FreeCodeCamp Points](https://img.shields.io/freecodecamp/points/lucasvbr?label=FreeCodeCamp%20points)"
- "![Made with love](https://img.shields.io/badge/-made%20with%20%E2%9D%A4%EF%B8%8F-red)"
skills:
- "Android"
- "Angular"
- "Bootstrap"
- "Bulma"
- "C"
- "CSS3"
- "Deno"
- "Docker"
- "Express"
- "Figma"
- "Git"
- "GNU Bash"
- "HTML5"
- "JavaScript"
- "MariaDB"
- "MongoDB"
- "MySQL"
- "Node.js"
- "Nunjucks"
- "OCaml"
- "PHP"
- "PostgreSQL"
- "Pug"
- "Python"
- "React"
- "SQLite"
- "Symfony"
- "TypeScript"
+17
View File
@@ -0,0 +1,17 @@
from src.config import Config
from src.template import Template
CONFIG_FILE = 'config.yaml'
TEMPLATE_FILE = 'template.md'
OUTPUT_FILE = 'README.md'
if __name__ == '__main__':
template = Template(TEMPLATE_FILE)
data = Config(CONFIG_FILE).get_data()
# Generate README file
render = template.render(**data)
with open(OUTPUT_FILE, 'w') as f:
f.write(render)
print(f"{OUTPUT_FILE} generated successfully! 🎉")
-18
View File
@@ -1,18 +0,0 @@
import {parse} from 'https://deno.land/std@0.82.0/encoding/yaml.ts';
import nunjucks from 'https://deno.land/x/nunjucks@3.2.3-2/mod.js';
import makeContext from './src/Context.ts';
import type ConfigModel from './models/ConfigModel.ts';
// Load Config file
const config: ConfigModel = parse(await Deno.readTextFile('config.yaml')) as ConfigModel;
const context = makeContext(config.view)
// Render
nunjucks.configure('views/', {autoescape: true});
nunjucks.render(config.file.template, context, (err, res) => {
if (err) return console.error(err);
Deno.writeTextFile(config.file.output, res ?? '')
.then(() => console.info(`[INFO] ${config.file.output} successfully generated`))
.catch(err => console.error(err));
});
-13
View File
@@ -1,13 +0,0 @@
type BadgeModel = {
label?: string,
message?: string,
color?: string,
logo?: string,
style: "plastic" | "flat" | "flat-square" | "for-the-badge" | "social",
logoColor?: string,
logoWidth?: number,
link?: string,
labelColor?: string,
cacheSeconds?: number,
}
export default BadgeModel;
-9
View File
@@ -1,9 +0,0 @@
type BannerModel = {
text1: string,
text2?: string,
type: "origin" | "textBox" | "glitch" | "luminance" | "typeWriter" | "rainbow",
width: number,
height: number,
}
export default BannerModel;
-20
View File
@@ -1,20 +0,0 @@
import type BannerModel from './BannerModel.ts';
import type LinkModel from './LinkModel.ts';
import type BadgeModel from './BadgeModel.ts';
type ConfigModel = {
file: {
template: string,
output: string
},
view: {
userName: string,
banner: BannerModel,
about: string,
links: LinkModel[],
skills: BadgeModel[],
footer: string[]
}
}
export default ConfigModel;
-8
View File
@@ -1,8 +0,0 @@
import BadgeModel from './BadgeModel.ts';
type LinkModel = {
label: BadgeModel,
url: string
}
export default LinkModel
+4
View File
@@ -0,0 +1,4 @@
pyyaml
json
requests
simpleicons
-18
View File
@@ -1,18 +0,0 @@
import ImageComponent from '../components/ImageComponent.ts';
import type BannerModel from '../models/BannerModel.ts';
import BannerUrlBuilder from './url_builder/BannerUrlBuilder.ts';
export default class Banner {
constructor(private model: BannerModel) {
};
toString(): string {
const url = new BannerUrlBuilder()
.setParameters({...this.model})
.build()
;
return ImageComponent(this.model.text1, url);
}
}
-12
View File
@@ -1,12 +0,0 @@
import Skill from './Skill.ts';
import Banner from './Banner.ts';
import Link from './Link.ts';
export default function makeContext(viewConfig) {
return {
...viewConfig,
banner: new Banner(viewConfig.banner).toString(),
links: viewConfig.links.map(link => (new Link(link)).toString()),
skills: viewConfig.skills.map(skill => (new Skill(skill)).toString()),
}
}
-32
View File
@@ -1,32 +0,0 @@
import BadgeUrlBuilder from './url_builder/BadgeUrlBuilder.ts';
import ImageComponent from '../components/ImageComponent.ts';
import LinkModel from '../models/LinkModel.ts';
import LinkComponent from '../components/LinkComponent.ts';
export default class Link {
constructor(private model: LinkModel) {}
handleLabel() {
const {label: badge} = this.model;
const defaultLogo = badge.message.toLowerCase().replace(/\s+/g, '')
const url = new BadgeUrlBuilder()
.setParameters({
...badge,
style: "for-the-badge",
logo: badge.logo ?? defaultLogo,
color: badge.color ?? '000',
},
)
.build()
;
return ImageComponent(badge.message, url);
}
toString(): string {
const label = this.handleLabel().toString()
return LinkComponent(label, this.model.url).toString()
}
}
-24
View File
@@ -1,24 +0,0 @@
import BadgeUrlBuilder from './url_builder/BadgeUrlBuilder.ts';
import ImageComponent from '../components/ImageComponent.ts';
import type SkillModel from '../models/SkillModel.ts';
export default class Skill {
constructor(private model: SkillModel) {};
toString(): string {
const defaultLogo = this.model.message.toLowerCase().replace(/\s+/g, '');
const url = new BadgeUrlBuilder()
.setParameters({
...this.model,
color: this.model.color ?? '000',
logo: this.model.logo ?? defaultLogo
},
)
.build()
;
return ImageComponent(this.model.message, url);
}
}
+37
View File
@@ -0,0 +1,37 @@
import yaml
from src.model.skill_list import SkillList
import requests
from src.model.social_list import SocialList
class Config:
config_file_path: str
config_data: dict[str, any] = None
def __init__(self, config_file_path: str):
self.config_file_path = config_file_path
def load_config_file(self):
with open(self.config_file_path, 'r') as config_file:
self.config_data = yaml.safe_load(config_file)
def handle_user_info(self):
user = self.config_data["user"]
response = requests.get(f"https://api.github.com/users/{user}")
if response.status_code != 200:
raise Exception("User not found")
self.config_data["user"] = response.json()
def handle_skill_section(self):
self.config_data["skills"] = str(SkillList(self.config_data["skills"]))
def handle_social_section(self):
self.config_data["socials"] = str(SocialList(self.config_data["socials"]))
def get_data(self):
self.load_config_file()
self.handle_user_info()
self.handle_skill_section()
self.handle_social_section()
return self.config_data
+13
View File
@@ -0,0 +1,13 @@
from src.shield.skill_shield import SkillShield
class Skill:
alt: str
src: str
def __init__(self, name: str):
self.alt = name
self.src = SkillShield(name).__str__()
def __str__(self) -> str:
return f"![{self.alt}]({self.src})"
+15
View File
@@ -0,0 +1,15 @@
from src.model.skill import Skill
class SkillList:
skills: list[Skill]
def __init__(self, skills: list[str]):
# Sort and remove duplicates
skills = list(set(skills))
skills.sort()
self.skills = [Skill(skill) for skill in skills]
def __str__(self) -> str:
return "\n".join([str(skill) for skill in self.skills])
+14
View File
@@ -0,0 +1,14 @@
from src.shield.social_shield import SocialShield
class Social:
name: str
img: str
def __init__(self, name: str, url: str):
self.name = name
self.img = SocialShield(name, url).__str__()
self.url = url
def __str__(self) -> str:
return f"[![{self.name}]({self.img})]({self.url})"
+11
View File
@@ -0,0 +1,11 @@
from src.model.social import Social
class SocialList:
socials: list[Social]
def __init__(self, socials: list):
self.socials = [Social(social.get("name"), social.get("url")) for social in socials]
def __str__(self) -> str:
return "\n".join([str(social) for social in self.socials])
+94
View File
@@ -0,0 +1,94 @@
from urllib.parse import urlunsplit, urlencode
from simpleicons.all import icons
class ShieldBuilder:
BASE_URL = "https://img.shields.io/static/v1"
message: str = None
style: str = None
logo: str = None
logo_color: str = None
label: str = None
label_color: str = None
color: str = None
cache_seconds: int = None
link: str = None
def __init__(self):
self.logo_color = "white"
self.label = " "
self.color = "black"
def set_message(self, message: str):
self.message = (
message
.replace("_", "__")
.replace("-", "--")
.replace(" ", "_")
)
return self
def set_style(self, style: str):
if not style in ["flat", "flat-square", "plastic", "for-the-badge", "social"]:
raise Exception("Invalid style")
self.style = style
return self
def set_logo(self, logo: str):
self.logo = icons.get(logo).slug if logo in icons else None
return self
def set_logo_color(self, logo_color: str):
self.logo_color = logo_color
return self
def set_label(self, label: str):
self.label = label
return self
def set_label_color(self, label_color: str):
self.label_color = label_color
return self
def set_color(self, color: str):
self.color = color
return self
def set_cache_seconds(self, cache_seconds: int):
self.cache_seconds = cache_seconds
return self
def set_link(self, link: str):
self.link = link
return self
def get_query(self):
query = {
"message": self.message,
"style": self.style,
"logo": self.logo,
"logoColor": self.logo_color,
"label": self.label,
"labelColor": self.label_color,
"color": self.color,
"cacheSeconds": self.cache_seconds,
"link": self.link
}
# Remove None values
return {k: v for k, v in query.items() if v is not None}
def build(self):
query = urlencode(self.get_query())
return urlunsplit(("", "", self.BASE_URL, query, ""))
if "__main__" == __name__:
shield_builder = (
ShieldBuilder()
.set_logo("HTML5")
.set_message("HTML5")
.build()
)
print(shield_builder)
+33
View File
@@ -0,0 +1,33 @@
from simpleicons.all import icons
from src.shield.shield_builder import ShieldBuilder
class SkillShield:
def __init__(self, name: str = None):
self.builder = ShieldBuilder()
self.skill = self.set_skill(name) if name is not None else None
def get_skill(self):
return self.skill
def set_skill(self, name: str):
self.skill = icons.get(name)
if self.skill is not None:
(self.builder.set_message(self.skill.title)
.set_logo(self.skill.slug)
.set_color(self.skill.hex)
)
else:
self.builder.set_message(name)
def get_builder(self):
return self.builder
def __repr__(self):
self.__str__()
def __str__(self):
return self.builder.build()
+37
View File
@@ -0,0 +1,37 @@
from simpleicons.all import icons
from src.shield.shield_builder import ShieldBuilder
class SocialShield:
def __init__(self, name: str = None, url: str = None):
self.builder = ShieldBuilder().set_style("for-the-badge")
self.name = name
self.url = url
self.social = self.set_social(name, url) if name is not None and url is not None else None
def get_social(self):
return self.social
def set_social(self, name: str, url: str):
self.social = icons.get(name)
if self.social is not None:
(self.builder.set_message(self.social.title)
.set_logo(self.social.slug)
.set_color(self.social.hex)
)
else:
self.builder.set_message(name)
self.builder.set_link(url)
def get_builder(self):
return self.builder
def __repr__(self):
self.__str__()
def __str__(self):
return self.builder.build()
+10
View File
@@ -0,0 +1,10 @@
class Template:
def __init__(self, template_path: str):
self.template_path = template_path
def render(self, **kwargs) -> str:
with open(self.template_path, 'r') as f:
template = f.read()
return template.format(**kwargs)
-18
View File
@@ -1,18 +0,0 @@
import type BadgeModel from '../../models/BadgeModel.ts';
import UrlBuilder from './UrlBuilder.ts';
export default class BadgeUrlBuilder extends UrlBuilder {
static BASE_URL = 'https://img.shields.io/static/v1';
static DEFAULT_PARAMETERS: BadgeModel = {style: 'flat', label: " ", logoColor: "white"};
constructor(parameters?: BadgeModel) {
super(BadgeUrlBuilder.BASE_URL,
parameters,
BadgeUrlBuilder.DEFAULT_PARAMETERS,
);
};
public setParameters(parameters: BadgeModel): this {
return super.setParameters(parameters);
}
}
-14
View File
@@ -1,14 +0,0 @@
import UrlBuilder from './UrlBuilder.ts';
import type BannerModel from '../../models/BannerModel.ts';
export default class BannerUrlBuilder extends UrlBuilder {
static BASE_URL = 'https://svg-banners.vercel.app/api';
constructor(parameters: BannerModel) {
super(BannerUrlBuilder.BASE_URL, parameters, {});
}
public setParameters(parameters: BannerModel): this {
return super.setParameters(parameters);
}
}
-25
View File
@@ -1,25 +0,0 @@
export default abstract class UrlBuilder {
private parameters;
protected constructor(
private baseUrl: string,
parameters,
private defaultParameters,
) {
this.parameters = {...defaultParameters, ...parameters};
};
setParameters(parameters) {
this.parameters = {...this.parameters, ...parameters};
return this;
}
build(): URL {
const url = new URL(this.baseUrl);
for (const [key, value] of Object.entries(this.parameters)) {
if (value) url.searchParams.set(key, value);
}
return url;
};
}
+33
View File
@@ -0,0 +1,33 @@
<header>
<div align="center">
![Hi I'm Lucàs👋](assets/banner.svg)
</div>
</header>
## 🚀 About Me
I'm a passionate developer from 🇫🇷 **{user[location]}**.
## 🔗 Social Links
{socials}
## 🛠 Skills
{skills}
---
<footer>
<div align="center">
![SVG Stats](https://github-stats-alpha.vercel.app/api?username=LucasVbr&cc=000&tc=fff&ic=fff&bc=000)
![Profile Views](https://komarev.com/ghpvc/?username=lucasvbr&amp;amp;amp;label=Profile%20views&amp;amp;amp;color=0e75b6&amp;amp;amp;style=flat)
![FreeCodeCamp Points](https://img.shields.io/freecodecamp/points/lucasvbr?label=FreeCodeCamp%20points)
![Made with love](https://img.shields.io/badge/-made%20with%20%E2%9D%A4%EF%B8%8F-red)
</div>
</footer>
-26
View File
@@ -1,26 +0,0 @@
{{banner}}
## 🚀 About Me
{{about}}
## 🔗 Links
{% for link in links -%}
{{link}}
{% endfor %}
## 🛠 Skills
{% for skill in skills -%}
{{skill}}
{% endfor %}
---
<div align="center">
![SVG Stats](https://github-stats-alpha.vercel.app/api?username={{userName}}&cc=000&tc=fff&ic=fff&bc=000)
{% for badge in footer -%}
{{badge}}
{% endfor %}
</div>