mirror of
https://github.com/LucasVbr/LucasVbr.git
synced 2026-05-13 17:11:52 +00:00
feat: Use Typescript, YAML, Handlebars with generation workflow
Took 5 hours 7 minutes
This commit is contained in:
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
venv/
|
build/
|
||||||
|
dist/
|
||||||
.DS_Store
|
node_modules/
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
## Hi there! <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Hand%20gestures/Waving%20Hand.png" alt="Waving Hand" width="25" height="25" />
|
|
||||||
|
|
||||||
I'm **Lucàs**, a passionate developer based in 🇫🇷 **Pau, France**.<br/>
|
|
||||||
My journey in the world of programming started 7 years ago when I fell in love with   .
|
|
||||||
|
|
||||||
### <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Travel%20and%20places/Rocket.png" alt="Rocket" width="25" height="25" /> What I do
|
|
||||||
|
|
||||||
- 💻 Currently, I'm studying at **UPPA** for my Master's degree in Informatics.
|
|
||||||
- 🌐 I specialize in Web Development, and I'm always eager to explore new technologies and frameworks.
|
|
||||||
- 🌱 I'm constantly learning and expanding my skill set to stay up-to-date with the ever-evolving tech landscape.
|
|
||||||
|
|
||||||
### <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Travel%20and%20places/Globe%20Showing%20Europe-Africa.png" alt="Globe Showing Europe-Africa" width="25" height="25" /> Connect with me
|
|
||||||
|
|
||||||
[](https://www.lucasvbr.dev)
|
|
||||||
[](https://www.linkedin.com/in/lucasvbr)
|
|
||||||
[](https://www.freecodecamp.org/LucasVbr)
|
|
||||||
[](https://openclassrooms.com/fr/members/97j9zltv6225)
|
|
||||||
[](https://exercism.org/profiles/LucasVbr)
|
|
||||||
|
|
||||||
### <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Objects/Hammer%20and%20Wrench.png" alt="Hammer and Wrench" width="25" height="25" /> Tech Stack
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Hand%20gestures/Handshake.png" alt="Handshake" width="25" height="25" /> Let's collaborate
|
|
||||||
|
|
||||||
👀 I'm always open to collaboration and exciting projects. If you have something in mind, feel free to reach out!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<footer>
|
|
||||||
<div align="center">
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "lucasvbr",
|
||||||
|
"dependencies": {
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
|
"yaml": "^2.8.0",
|
||||||
|
"zod": "^4.0.5",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@24.0.13", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ=="],
|
||||||
|
|
||||||
|
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||||
|
|
||||||
|
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||||
|
|
||||||
|
"handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="],
|
||||||
|
|
||||||
|
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||||
|
|
||||||
|
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
|
||||||
|
|
||||||
|
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||||
|
|
||||||
|
"uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="],
|
||||||
|
|
||||||
|
"undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||||
|
|
||||||
|
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
||||||
|
|
||||||
|
"yaml": ["yaml@2.8.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ=="],
|
||||||
|
|
||||||
|
"zod": ["zod@4.0.5", "", {}, "sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parser_type": "YAML",
|
||||||
|
"compiler_type": "HANDLEBARS",
|
||||||
|
"input_file": "src/templates/README.md.hbs",
|
||||||
|
"data_file": "static/README.yaml",
|
||||||
|
"output_file": "README.md"
|
||||||
|
}
|
||||||
-48
@@ -1,48 +0,0 @@
|
|||||||
user: "LucasVbr"
|
|
||||||
|
|
||||||
socials:
|
|
||||||
- name: "Portfolio"
|
|
||||||
url: "https://www.lucasvbr.dev"
|
|
||||||
|
|
||||||
- name: "Linkedin"
|
|
||||||
url: "https://www.linkedin.com/in/lucasvbr"
|
|
||||||
|
|
||||||
- name: "FreeCodeCamp"
|
|
||||||
url: "https://www.freecodecamp.org/LucasVbr"
|
|
||||||
|
|
||||||
- name: "OpenClassRooms"
|
|
||||||
url: "https://openclassrooms.com/fr/members/97j9zltv6225"
|
|
||||||
|
|
||||||
- name: "Exercism"
|
|
||||||
url: "https://exercism.org/profiles/LucasVbr"
|
|
||||||
|
|
||||||
skills:
|
|
||||||
- Android
|
|
||||||
- Angular
|
|
||||||
- Astro
|
|
||||||
- Bun
|
|
||||||
- Bootstrap
|
|
||||||
- Bulma
|
|
||||||
- C
|
|
||||||
- CSS3
|
|
||||||
- Deno
|
|
||||||
- Docker
|
|
||||||
- Express
|
|
||||||
- Figma
|
|
||||||
- Git
|
|
||||||
- GNU Bash
|
|
||||||
- HTML5
|
|
||||||
- JavaScript
|
|
||||||
- MariaDB
|
|
||||||
- MongoDB
|
|
||||||
- MySQL
|
|
||||||
- Node.js
|
|
||||||
- OCaml
|
|
||||||
- PHP
|
|
||||||
- PostgreSQL
|
|
||||||
- Pug
|
|
||||||
- Python
|
|
||||||
- React
|
|
||||||
- SQLite
|
|
||||||
- Symfony
|
|
||||||
- TypeScript
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
name: Build and Commit README
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [dev]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install Bun
|
||||||
|
uses: oven-sh/setup-bun@v1
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bun install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Run build
|
||||||
|
run: bun run build
|
||||||
|
|
||||||
|
- name: Configure Git
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
- name: Commit README.md to main
|
||||||
|
run: |
|
||||||
|
git checkout main
|
||||||
|
git pull origin main
|
||||||
|
git checkout dev -- README.md
|
||||||
|
if git diff --quiet README.md; then
|
||||||
|
echo "No changes to README.md"
|
||||||
|
else
|
||||||
|
git add README.md
|
||||||
|
git commit -m "chore(readme): update after build [CI]"
|
||||||
|
git push origin main
|
||||||
|
fi
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
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! 🎉")
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "lucasvbr",
|
||||||
|
"module": "src/index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "bun run src/index.ts"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
|
"yaml": "^2.8.0",
|
||||||
|
"zod": "^4.0.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
pyyaml
|
|
||||||
json
|
|
||||||
requests
|
|
||||||
simpleicons
|
|
||||||
urllib3
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Compiler interface for compiling templates with data.
|
||||||
|
*/
|
||||||
|
export interface Compiler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the given template with the provided data.
|
||||||
|
* @param template - The template string to compile.
|
||||||
|
* @param data - The data object to use for compilation.
|
||||||
|
*/
|
||||||
|
compile(template: string, data: object): string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import {type Compiler, CompilerType, HandlebarsCompiler} from '.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory class for creating compiler instances.
|
||||||
|
* This class provides a method to get a compiler based on the specified type.
|
||||||
|
*/
|
||||||
|
export class CompilerFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a compiler instance based on the specified type.
|
||||||
|
* @param type - The type of compiler to create.
|
||||||
|
* @returns An instance of the specified compiler.
|
||||||
|
*/
|
||||||
|
public static getCompiler(type: CompilerType): Compiler {
|
||||||
|
switch (type) {
|
||||||
|
case CompilerType.HANDLEBARS:
|
||||||
|
return HandlebarsCompiler.getInstance();
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported compiler type: ${type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Enum representing different types of compilers.
|
||||||
|
*/
|
||||||
|
export enum CompilerType {
|
||||||
|
HANDLEBARS = 'handlebars',
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import {type Compiler, CompilerType} from '.';
|
||||||
|
import {compile} from 'handlebars';
|
||||||
|
|
||||||
|
export class HandlebarsCompiler implements Compiler {
|
||||||
|
|
||||||
|
static readonly TYPE: CompilerType = CompilerType.HANDLEBARS;
|
||||||
|
|
||||||
|
private static instance: HandlebarsCompiler;
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
public static getInstance(): HandlebarsCompiler {
|
||||||
|
if (!HandlebarsCompiler.instance) {
|
||||||
|
HandlebarsCompiler.instance = new HandlebarsCompiler();
|
||||||
|
}
|
||||||
|
return HandlebarsCompiler.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public compile(template: string, data: object = {}): string {
|
||||||
|
const compiledTemplate = compile(template);
|
||||||
|
return compiledTemplate(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './Compiler';
|
||||||
|
export * from './CompilerType';
|
||||||
|
export * from './CompilerFactory';
|
||||||
|
export * from './HandlebarsCompiler';
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import yaml
|
|
||||||
from src.model.skill_list import skill_list
|
|
||||||
import requests
|
|
||||||
from src.model.social_list import social_list
|
|
||||||
|
|
||||||
|
|
||||||
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 get_data(self):
|
|
||||||
self.load_config_file()
|
|
||||||
self.handle_user_info()
|
|
||||||
self.config_data["skills"] = skill_list(self.config_data["skills"])
|
|
||||||
self.config_data["socials"] = social_list(self.config_data["socials"])
|
|
||||||
|
|
||||||
return self.config_data
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import config from '../config.json';
|
||||||
|
import {CompilerFactory, CompilerType} from './compilers';
|
||||||
|
import {ParserFactory, ParserType} from './parsers';
|
||||||
|
import {Validator} from './validators/Validator.ts';
|
||||||
|
import {FileManager} from './io/FileManager.ts';
|
||||||
|
import {ReadmeSchema} from './validators/schemas';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Point d'entrée du script
|
||||||
|
*/
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
const compiler = createCompiler(config.compiler_type);
|
||||||
|
const parser = createParser(config.parser_type);
|
||||||
|
const validator = new Validator(ReadmeSchema);
|
||||||
|
|
||||||
|
const data = await loadData(config.data_file, parser, validator);
|
||||||
|
const template = await loadTemplate(config.input_file);
|
||||||
|
const result = compiler.compile(template, data);
|
||||||
|
|
||||||
|
await saveOutput(config.output_file, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un compilateur en fonction du type spécifié dans la configuration
|
||||||
|
* @param type - Le type de compilateur à créer
|
||||||
|
*/
|
||||||
|
function createCompiler(type: string) {
|
||||||
|
const compilerType = CompilerType[type as keyof typeof CompilerType];
|
||||||
|
return CompilerFactory.getCompiler(compilerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée un parseur en fonction du type spécifié dans la configuration
|
||||||
|
* @param type - Le type de parseur à créer
|
||||||
|
*/
|
||||||
|
function createParser(type: string) {
|
||||||
|
const parserType = ParserType[type as keyof typeof ParserType];
|
||||||
|
return ParserFactory.getParser(parserType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Charge les données depuis le fichier spécifié, les parse et les valide
|
||||||
|
* @param path - Le chemin du fichier de données
|
||||||
|
* @param parser - Le parseur à utiliser pour analyser les données
|
||||||
|
* @param validator - Le validateur à utiliser pour valider les données
|
||||||
|
*/
|
||||||
|
async function loadData(
|
||||||
|
path: string, parser: ReturnType<typeof createParser>,
|
||||||
|
validator: Validator) {
|
||||||
|
const raw = await FileManager.read(path);
|
||||||
|
const parsed = parser.parse(raw);
|
||||||
|
return validator.validate(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Charge le modèle de template depuis le fichier spécifié
|
||||||
|
* @param path - Le chemin du fichier de template
|
||||||
|
*/
|
||||||
|
async function loadTemplate(path: string): Promise<string> {
|
||||||
|
return FileManager.read(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enregistre le résultat compilé dans le fichier de sortie spécifié
|
||||||
|
* @param path - Le chemin du fichier de sortie
|
||||||
|
* @param content - Le contenu à écrire dans le fichier
|
||||||
|
*/
|
||||||
|
async function saveOutput(path: string, content: string): Promise<void> {
|
||||||
|
await FileManager.write(path, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exécute le script principal
|
||||||
|
main()
|
||||||
|
.then(() => console.log('🎉 Exécution terminée avec succès.'))
|
||||||
|
.catch(err => console.error('❌ Erreur pendant l’exécution:', err));
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import {readFileSync, writeFileSync} from 'node:fs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FileManager is a singleton class that provides methods to read and write files.
|
||||||
|
* It ensures that only one instance of the FileManager exists throughout the application.
|
||||||
|
*/
|
||||||
|
export class FileManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the content of a file at the specified path.
|
||||||
|
* @param {string} filePath - The path to the file to read.
|
||||||
|
* @returns {Promise<string>} A promise that resolves with the file content.
|
||||||
|
*/
|
||||||
|
public static async read(filePath: string): Promise<string> {
|
||||||
|
return readFileSync(filePath, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes content to a file at the specified path.
|
||||||
|
* If the file does not exist, it will be created.
|
||||||
|
* @param {string} filePath - The path to the file to write.
|
||||||
|
* @param {string} content - The content to write to the file.
|
||||||
|
* @returns {Promise<void>} A promise that resolves when the write operation is complete.
|
||||||
|
*/
|
||||||
|
public static async write(filePath: string, content: string): Promise<void> {
|
||||||
|
return writeFileSync(filePath, content, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
flag: 'w',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
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""
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
from src.model.skill import Skill
|
|
||||||
|
|
||||||
|
|
||||||
def skill_list(skills: list[str]) -> dict[str, str]:
|
|
||||||
# Sort and remove duplicates
|
|
||||||
skills = list(set(skills))
|
|
||||||
skills.sort()
|
|
||||||
|
|
||||||
skills = {skill: Skill(skill).__str__() for skill in skills}
|
|
||||||
skills["all"] = "\n".join([str(skill) for skill in skills.values()])
|
|
||||||
return skills
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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.url})"
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
from src.model.social import Social
|
|
||||||
|
|
||||||
|
|
||||||
def social_list(socials: list) -> dict[str, str]:
|
|
||||||
socials: dict[str, str] = {social.get("name"): str(Social(social.get("name"), social.get("url"))) for social in
|
|
||||||
socials}
|
|
||||||
socials["all"] = "\n".join([str(social) for social in socials.values()])
|
|
||||||
return socials
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* Parser interface for parsing data strings into object representations.
|
||||||
|
*/
|
||||||
|
export interface Parser {
|
||||||
|
/**
|
||||||
|
* Parses the given data string and returns an object representation.
|
||||||
|
* @param data - The data string to parse.
|
||||||
|
* @returns An object representation of the parsed data.
|
||||||
|
*/
|
||||||
|
parse(data: string): object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance of the parser.
|
||||||
|
* @returns An instance of the parser.
|
||||||
|
*/
|
||||||
|
getInstance(): Parser;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import {ParserType, type Parser, YamlParser} from "."
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory class for creating parser instances.
|
||||||
|
*/
|
||||||
|
export class ParserFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a parser instance based on the specified type.
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
static getParser(type: ParserType): Parser {
|
||||||
|
switch (type) {
|
||||||
|
case ParserType.YAML:
|
||||||
|
return YamlParser.getInstance();
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported parser type: ${type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Enum representing different parser types.
|
||||||
|
*/
|
||||||
|
export enum ParserType {
|
||||||
|
YAML = 'yaml',
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import {type Parser, ParserType} from '.';
|
||||||
|
import {parse} from 'yaml';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* YamlParser class implements the Parser interface for parsing YAML data.
|
||||||
|
*/
|
||||||
|
export class YamlParser implements Parser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the parser.
|
||||||
|
* This is used to identify the parser type in the system.
|
||||||
|
*/
|
||||||
|
static readonly TYPE: ParserType = ParserType.YAML;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton instance of the parser.
|
||||||
|
* This ensures that only one instance of the parser exists.
|
||||||
|
*/
|
||||||
|
static instance?: YamlParser;
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public static getInstance(): YamlParser {
|
||||||
|
if (!this.instance) {
|
||||||
|
this.instance = new YamlParser();
|
||||||
|
}
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance(): Parser {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public parse(data: string): object {
|
||||||
|
try {
|
||||||
|
return parse(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing YAML data:', error);
|
||||||
|
throw new Error('Failed to parse YAML data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export * from "./Parser";
|
||||||
|
export * from "./ParserType";
|
||||||
|
export * from "./ParserFactory";
|
||||||
|
export * from "./YamlParser";
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
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)
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
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()
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
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()
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
class Template:
|
|
||||||
|
|
||||||
def __init__(self, template_path: str):
|
|
||||||
self.template_path = template_path
|
|
||||||
|
|
||||||
def render(self, **kwargs):
|
|
||||||
with open(self.template_path, 'r') as f:
|
|
||||||
template = f.read()
|
|
||||||
|
|
||||||
return template.format(**kwargs)
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
## Hi there! 👋
|
||||||
|
|
||||||
|
I'm **{{author.first_name}}**, a passionate developer based in **{{author.location}}**.
|
||||||
|
|
||||||
|
### 🚀 What I do
|
||||||
|
|
||||||
|
- 💻 Currently, I'm studying at **{{author.company}}** for my Master's degree in Informatics.
|
||||||
|
- 🌐 I specialize in Web Development, and I'm always eager to explore new technologies and frameworks.
|
||||||
|
- 🌱 I'm constantly learning and expanding my skill set to stay up-to-date with the ever-evolving tech landscape.
|
||||||
|
|
||||||
|
### 🌍 Connect with me
|
||||||
|
|
||||||
|
{{#each socials as | social |}}
|
||||||
|
[]({{social.url}})
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
### 🛠️ Tech Stack
|
||||||
|
|
||||||
|
{{#each skills as | skill |}}
|
||||||
|

|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
### 🤝 Let's collaborate
|
||||||
|
|
||||||
|
👀 I'm always open to collaboration and exciting projects. If you have something in mind, feel free to reach out!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<footer><div align="center">
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
</div></footer>
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import type {ZodObject} from 'zod';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validator class for validating and parsing objects against a Zod schema.
|
||||||
|
*/
|
||||||
|
export class Validator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of the Validator.
|
||||||
|
* @param schema - The Zod schema to validate against.
|
||||||
|
*/
|
||||||
|
constructor(private schema: ZodObject<any, any>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the given value against the schema.
|
||||||
|
* @param value - The object to validate.
|
||||||
|
* @returns true if the value is valid, false otherwise.
|
||||||
|
*/
|
||||||
|
public isValid(value: object): boolean {
|
||||||
|
try {
|
||||||
|
this.schema.parse(value);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Validation error:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given value against the schema.
|
||||||
|
* @param value - The object to parse.
|
||||||
|
* @returns The parsed object if valid, throws an error otherwise.
|
||||||
|
*/
|
||||||
|
public validate(value: object): object {
|
||||||
|
try {
|
||||||
|
return this.schema.parse(value);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Parsing error:', error);
|
||||||
|
throw new Error('Failed to parse value');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import {z} from 'zod';
|
||||||
|
|
||||||
|
export const AuthorSchema = z.object({
|
||||||
|
first_name: z.string(),
|
||||||
|
location: z.string(),
|
||||||
|
company: z.string(),
|
||||||
|
});
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import {z} from 'zod';
|
||||||
|
import {AuthorSchema, SkillSchema, SocialSchema} from '.';
|
||||||
|
|
||||||
|
export const ReadmeSchema = z.object({
|
||||||
|
author: AuthorSchema,
|
||||||
|
socials: z.array(SocialSchema),
|
||||||
|
skills: z.array(SkillSchema),
|
||||||
|
});
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import {z} from 'zod';
|
||||||
|
|
||||||
|
export const SkillSchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
icon: z.string(),
|
||||||
|
});
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import {z} from 'zod';
|
||||||
|
|
||||||
|
export const SocialSchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
icon: z.string(),
|
||||||
|
url: z.string(),
|
||||||
|
});
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './AuthorSchema';
|
||||||
|
export * from './SocialSchema';
|
||||||
|
export * from './SkillSchema';
|
||||||
|
export * from './ReadmeSchema';
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
author:
|
||||||
|
first_name: Lucàs
|
||||||
|
location: 🇫🇷 Toulouse, France
|
||||||
|
company: UPPA
|
||||||
|
socials:
|
||||||
|
- name: Portfolio
|
||||||
|
icon: ""
|
||||||
|
url: https://www.lucasvbr.dev
|
||||||
|
- name: LinkedIn
|
||||||
|
icon: ""
|
||||||
|
url: https://www.linkedin.com/in/lucasvbr
|
||||||
|
skills:
|
||||||
|
- name: Android
|
||||||
|
icon: ""
|
||||||
|
- name: Angular
|
||||||
|
icon: ""
|
||||||
|
- name: Astro
|
||||||
|
icon: ""
|
||||||
|
- name: Bun
|
||||||
|
icon: ""
|
||||||
|
- name: Bootstrap
|
||||||
|
icon: ""
|
||||||
|
- name: Bulma
|
||||||
|
icon: ""
|
||||||
|
- name: C
|
||||||
|
icon: ""
|
||||||
|
- name: CSS3
|
||||||
|
icon: ""
|
||||||
|
- name: Deno
|
||||||
|
icon: ""
|
||||||
|
- name: Docker
|
||||||
|
icon: ""
|
||||||
|
- name: Express
|
||||||
|
icon: ""
|
||||||
|
- name: Figma
|
||||||
|
icon: ""
|
||||||
|
- name: Git
|
||||||
|
icon: ""
|
||||||
|
- name: GNU Bash
|
||||||
|
icon: ""
|
||||||
|
- name: HTML5
|
||||||
|
icon: ""
|
||||||
|
- name: JavaScript
|
||||||
|
icon: ""
|
||||||
|
- name: MariaDB
|
||||||
|
icon: ""
|
||||||
|
- name: MongoDB
|
||||||
|
icon: ""
|
||||||
|
- name: MySQL
|
||||||
|
icon: ""
|
||||||
|
- name: Node.js
|
||||||
|
icon: ""
|
||||||
|
- name: OCaml
|
||||||
|
icon: ""
|
||||||
|
- name: PHP
|
||||||
|
icon: ""
|
||||||
|
- name: PostgreSQL
|
||||||
|
icon: ""
|
||||||
|
- name: Pug
|
||||||
|
icon: ""
|
||||||
|
- name: Python
|
||||||
|
icon: ""
|
||||||
|
- name: React
|
||||||
|
icon: ""
|
||||||
|
- name: SQLite
|
||||||
|
icon: ""
|
||||||
|
- name: Symfony
|
||||||
|
icon: ""
|
||||||
|
- name: TypeScript
|
||||||
|
icon: ""
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
## Hi there! <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Hand%20gestures/Waving%20Hand.png" alt="Waving Hand" width="25" height="25" />
|
|
||||||
|
|
||||||
I'm **{user[name]}**, a passionate developer based in 🇫🇷 **{user[location]}**.<br/>
|
|
||||||
My journey in the world of programming started 7 years ago when I fell in love with {skills[HTML5]} {skills[CSS3]} {skills[JavaScript]}.
|
|
||||||
|
|
||||||
### <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Travel%20and%20places/Rocket.png" alt="Rocket" width="25" height="25" /> What I do
|
|
||||||
|
|
||||||
- 💻 Currently, I'm studying at **{user[company]}** for my Master's degree in Informatics.
|
|
||||||
- 🌐 I specialize in Web Development, and I'm always eager to explore new technologies and frameworks.
|
|
||||||
- 🌱 I'm constantly learning and expanding my skill set to stay up-to-date with the ever-evolving tech landscape.
|
|
||||||
|
|
||||||
### <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Travel%20and%20places/Globe%20Showing%20Europe-Africa.png" alt="Globe Showing Europe-Africa" width="25" height="25" /> Connect with me
|
|
||||||
|
|
||||||
{socials[all]}
|
|
||||||
|
|
||||||
### <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Objects/Hammer%20and%20Wrench.png" alt="Hammer and Wrench" width="25" height="25" /> Tech Stack
|
|
||||||
|
|
||||||
{skills[all]}
|
|
||||||
|
|
||||||
### <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Hand%20gestures/Handshake.png" alt="Handshake" width="25" height="25" /> Let's collaborate
|
|
||||||
|
|
||||||
👀 I'm always open to collaboration and exciting projects. If you have something in mind, feel free to reach out!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<footer>
|
|
||||||
<div align="center">
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Enable latest features
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user