init
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
node_modules/*
|
||||||
25
backend/app.ts
Normal file
25
backend/app.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import express, { type Request, type Response } from "express";
|
||||||
|
|
||||||
|
const hostname = '127.0.0.1';
|
||||||
|
const httpPort = 4080;
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.set('views', 'views');
|
||||||
|
app.set('view engine', 'hbs');
|
||||||
|
|
||||||
|
// import morgan from 'morgan'
|
||||||
|
// app.use(morgan('dev'));
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.urlencoded({ extended: false }));
|
||||||
|
app.use(express.static('public'));
|
||||||
|
|
||||||
|
import userData from './userKnowledge.json';
|
||||||
|
|
||||||
|
app.get('/', function (req: Request, res: Response) {
|
||||||
|
res.render('cv2', { userData });
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(httpPort, () => {
|
||||||
|
console.log(`Server running at http://${hostname}:${httpPort}/`);
|
||||||
|
});
|
||||||
6
backend/public/assets/javascripts/html2pdf.v0.9.3.bundle.min.js
vendored
Normal file
6
backend/public/assets/javascripts/html2pdf.v0.9.3.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
183
backend/public/assets/javascripts/main.js
Normal file
183
backend/public/assets/javascripts/main.js
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/* Set picture in url base 64 */
|
||||||
|
|
||||||
|
const img = document.getElementById('home-img');
|
||||||
|
|
||||||
|
/*fetch('assets/pictures/profile.txt', {
|
||||||
|
mode: 'no-cors',
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin':'*'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((result) => {
|
||||||
|
console.log('Success:', result);
|
||||||
|
//img.src = result;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
});*/
|
||||||
|
|
||||||
|
/* Show Menu */
|
||||||
|
|
||||||
|
const showMenu = (toggleId, navId) => {
|
||||||
|
const toggle = document.getElementById(toggleId);
|
||||||
|
nav = document.getElementById(navId);
|
||||||
|
|
||||||
|
// Validate that variables exist
|
||||||
|
if (toggle && nav) {
|
||||||
|
toggle.addEventListener('click', () => {
|
||||||
|
// We add the show-menu class to the div tag with the nav__menu class
|
||||||
|
nav.classList.toggle('show-menu');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showMenu('nav-toggle', 'nav-menu');
|
||||||
|
|
||||||
|
/* Remove menu mobile */
|
||||||
|
|
||||||
|
const navLink = document.querySelectorAll('.nav_link');
|
||||||
|
|
||||||
|
function linkAction() {
|
||||||
|
const navMenu = document.getElementById('nav-menu');
|
||||||
|
// When we click on each nav__link, we remove the show-menu class
|
||||||
|
navMenu.classList.remove('show-menu');
|
||||||
|
}
|
||||||
|
|
||||||
|
navLink.forEach(n => n.addEventListener('click', linkAction));
|
||||||
|
|
||||||
|
/* Scroll sections active link */
|
||||||
|
|
||||||
|
const sections = document.querySelectorAll('section[id]');
|
||||||
|
|
||||||
|
function scrollActive() {
|
||||||
|
const scrollY = window.pageYOffset;
|
||||||
|
|
||||||
|
sections.forEach(current => {
|
||||||
|
const sectionHeight = current.offsetHeight;
|
||||||
|
const sectionTop = current.offsetTop - 50;
|
||||||
|
sectionId = current.getAttribute('id');
|
||||||
|
|
||||||
|
if (scrollY > sectionTop && scrollY <= sectionTop + sectionHeight) {
|
||||||
|
document.querySelector('.nav_menu a[href*=' + sectionId + ']').classList.add('active-link');
|
||||||
|
} else {
|
||||||
|
document.querySelector('.nav_menu a[href*=' + sectionId + ']').classList.remove('active-link');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('scroll', scrollActive);
|
||||||
|
|
||||||
|
/* Show scroll top */
|
||||||
|
|
||||||
|
function scrollTop() {
|
||||||
|
const scrollTop = document.getElementById('scroll-top');
|
||||||
|
if (this.scrollY >= 200) {
|
||||||
|
scrollTop.classList.add('show-scroll');
|
||||||
|
} else {
|
||||||
|
scrollTop.classList.remove('show-scroll');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('scroll', scrollTop);
|
||||||
|
|
||||||
|
/* Light/Dark mode */
|
||||||
|
|
||||||
|
const themeButton = document.getElementById('theme-button');
|
||||||
|
let darkTheme = 'dark-theme';
|
||||||
|
let darkMode = localStorage.getItem("dark-mode");
|
||||||
|
|
||||||
|
function enableDarkMode() {
|
||||||
|
document.body.classList.add(darkTheme);
|
||||||
|
themeButton.classList.add('fa-sun');
|
||||||
|
themeButton.classList.remove('fa-moon');
|
||||||
|
localStorage.setItem("dark-mode", "enabled");
|
||||||
|
};
|
||||||
|
|
||||||
|
function disableDarkMode() {
|
||||||
|
document.body.classList.remove(darkTheme);
|
||||||
|
themeButton.classList.add('fa-moon');
|
||||||
|
themeButton.classList.remove('fa-sun');
|
||||||
|
localStorage.setItem("dark-mode", "disabled");
|
||||||
|
};
|
||||||
|
|
||||||
|
if (darkMode === "enabled") {
|
||||||
|
enableDarkMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
themeButton.addEventListener("click", () => {
|
||||||
|
darkMode = localStorage.getItem("dark-mode");
|
||||||
|
if (darkMode === "disabled") {
|
||||||
|
enableDarkMode();
|
||||||
|
} else {
|
||||||
|
disableDarkMode();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Link PDF Download on Mobile screen depending of the light/dark mode */
|
||||||
|
|
||||||
|
const downloadButton = document.getElementById('download-button');
|
||||||
|
|
||||||
|
downloadButton.addEventListener('click', () => {
|
||||||
|
if (document.body.classList.contains(darkTheme)) {
|
||||||
|
downloadButton.href = "assets/pdf/myResumeCV-dark.pdf";
|
||||||
|
} else {
|
||||||
|
downloadButton.href = "assets/pdf/myResumeCV-light.pdf";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Reduce the size and print on an A4 sheet */
|
||||||
|
|
||||||
|
function addScaleCV() {
|
||||||
|
document.body.classList.add("scale-cv");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remote the size when the CV is downloaded */
|
||||||
|
|
||||||
|
function removeScaleCV() {
|
||||||
|
document.body.classList.remove("scale-cv");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate PDF */
|
||||||
|
|
||||||
|
// PDF generated area
|
||||||
|
let areaCV = document.getElementById('area-cv');
|
||||||
|
|
||||||
|
// Button
|
||||||
|
let resumeButton = document.getElementById("resume-button");
|
||||||
|
|
||||||
|
// Generate PDF with html2pdf.js
|
||||||
|
function generateResume() {
|
||||||
|
// PDF filename change depending of the light/dark mode
|
||||||
|
if (document.body.classList.contains(darkTheme)) {
|
||||||
|
// html2pdf.js options
|
||||||
|
let opt = {
|
||||||
|
margin: 0,
|
||||||
|
filename: 'myResumeCV-dark.pdf',
|
||||||
|
image: { type: 'jpeg', quality: 0.98 },
|
||||||
|
html2canvas: { scale: 4, useCORS: true },
|
||||||
|
jsPDF: { format: 'a4', orientation: 'portrait' }
|
||||||
|
};
|
||||||
|
html2pdf(areaCV, opt);
|
||||||
|
} else {
|
||||||
|
// html2pdf.js options
|
||||||
|
let opt = {
|
||||||
|
margin: 0,
|
||||||
|
filename: 'myResumeCV-light.pdf',
|
||||||
|
image: { type: 'jpeg', quality: 0.98 },
|
||||||
|
html2canvas: { scale: 4, useCORS: true },
|
||||||
|
jsPDF: { format: 'a4', orientation: 'portrait' }
|
||||||
|
};
|
||||||
|
html2pdf(areaCV, opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action executed by clicking on the button => generation of the final PDF CV CV
|
||||||
|
resumeButton.addEventListener("click", () => {
|
||||||
|
// Adapt the area of the PDF
|
||||||
|
addScaleCV();
|
||||||
|
// Generate the PDF
|
||||||
|
generateResume();
|
||||||
|
// Remove adaptation after 1 second (you can choose to set more than 1 second if your PDF download time is long)
|
||||||
|
setTimeout(removeScaleCV, 1000);
|
||||||
|
});
|
||||||
BIN
backend/public/assets/pictures/favicon/favicon.ico
Normal file
BIN
backend/public/assets/pictures/favicon/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
19
backend/public/assets/pictures/favicon/site.webmanifest
Normal file
19
backend/public/assets/pictures/favicon/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"short_name": "",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#FFFFFF",
|
||||||
|
"background_color": "#FFFFFF",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
||||||
BIN
backend/public/assets/pictures/profile.png
Normal file
BIN
backend/public/assets/pictures/profile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
39
backend/public/assets/stylesheets/layout.css
Normal file
39
backend/public/assets/stylesheets/layout.css
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* Google Font Poppins */
|
||||||
|
@import url('https://fonts.googleapis.com/css?family=Poppins:100,200,300,400,500,600,700,800,900&display=swap');
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
:root {
|
||||||
|
--header-height: 3rem;
|
||||||
|
|
||||||
|
/* Colors */
|
||||||
|
--title-color: #0B0A0A;
|
||||||
|
--text-color: #403A3A;
|
||||||
|
--text-color-light: #707070;
|
||||||
|
--container-color: #FAFAFA;
|
||||||
|
--container-color-alt: #F0EFEF;
|
||||||
|
--body-color: #FCFCFC;
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
--body-font: 'Poppins', sans-serif;
|
||||||
|
|
||||||
|
/* Fonts size */
|
||||||
|
--h1-font-size: 1.5rem;
|
||||||
|
--h2-font-size: 1.25rem;
|
||||||
|
--h3-font-size: 1rem;
|
||||||
|
--normal-font-size: .938rem;
|
||||||
|
--small-font-size: .875rem;
|
||||||
|
--smaller-font-size: .813rem;
|
||||||
|
|
||||||
|
/* Fonts weight */
|
||||||
|
--font-medium: 500;
|
||||||
|
--font-semi-bold: 600;
|
||||||
|
|
||||||
|
/* Margins */
|
||||||
|
--margin-1: .5rem;
|
||||||
|
--margin-2: 1rem;
|
||||||
|
--margin-3: 1.5rem;
|
||||||
|
|
||||||
|
/* Z Index */
|
||||||
|
--z-tooltip: 10;
|
||||||
|
--z-fixed: 100;
|
||||||
|
}
|
||||||
746
backend/public/assets/stylesheets/style.css
Normal file
746
backend/public/assets/stylesheets/style.css
Normal file
@@ -0,0 +1,746 @@
|
|||||||
|
/* Google Font Poppins */
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@500&display=swap');
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
:root {
|
||||||
|
--header-height: 3rem;
|
||||||
|
|
||||||
|
/* Colors */
|
||||||
|
--title-color: #0B0A0A;
|
||||||
|
--text-color: #403A3A;
|
||||||
|
--text-color-light: #707070;
|
||||||
|
--container-color: #FAFAFA;
|
||||||
|
--container-color-alt: #F0EFEF;
|
||||||
|
--body-color: #FCFCFC;
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
--body-font: 'Poppins', sans-serif;
|
||||||
|
|
||||||
|
/* Fonts size */
|
||||||
|
--h1-font-size: 1.5rem;
|
||||||
|
--h2-font-size: 1.25rem;
|
||||||
|
--h3-font-size: 1rem;
|
||||||
|
--normal-font-size: .938rem;
|
||||||
|
--small-font-size: .875rem;
|
||||||
|
--smaller-font-size: .813rem;
|
||||||
|
|
||||||
|
/* Fonts weight */
|
||||||
|
--font-medium: 500;
|
||||||
|
--font-semi-bold: 600;
|
||||||
|
|
||||||
|
/* Margins */
|
||||||
|
--margin-1: .5rem;
|
||||||
|
--margin-2: 1rem;
|
||||||
|
--margin-3: 1.5rem;
|
||||||
|
|
||||||
|
/* Z Index */
|
||||||
|
--z-tooltip: 10;
|
||||||
|
--z-fixed: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base */
|
||||||
|
|
||||||
|
*,
|
||||||
|
::before,
|
||||||
|
::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button Light/Dark */
|
||||||
|
|
||||||
|
.change-theme {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 2.2rem;
|
||||||
|
display: flex;
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-theme:hover {
|
||||||
|
color: var(--title-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode */
|
||||||
|
|
||||||
|
body.dark-theme {
|
||||||
|
--title-color: #F2F2F2;
|
||||||
|
--text-color: #BFBFBF;
|
||||||
|
--container-color: #212121;
|
||||||
|
--container-color-alt: #181616;
|
||||||
|
--body-color: #2B2B2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate PDF Button */
|
||||||
|
|
||||||
|
.generate-pdf {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 2.2rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-pdf:hover {
|
||||||
|
color: var(--title-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scale CV */
|
||||||
|
|
||||||
|
body.scale-cv {
|
||||||
|
--h1-font-size: 0.938rem;
|
||||||
|
--h2-font-size: 0.938rem;
|
||||||
|
--h3-font-size: 0.875rem;
|
||||||
|
--normal-font-size: 0.813rem;
|
||||||
|
--small-font-size: 0.75rem;
|
||||||
|
--smaller-font-size: 0.688rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PDF A4 */
|
||||||
|
|
||||||
|
.scale-cv .change-theme,
|
||||||
|
.scale-cv .generate-pdf {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .bd-container {
|
||||||
|
max-width: 695px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .section {
|
||||||
|
padding: 1.5rem 0 0.80rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .section-title {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .resume {
|
||||||
|
height: 1122px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .resume_left {
|
||||||
|
width: 250px;
|
||||||
|
padding: 0 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .resume_right {
|
||||||
|
padding: 0 1rem 0 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .home_img {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .home_container {
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .home_data {
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .home_address,
|
||||||
|
.scale-cv .social_container {
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .home_icon,
|
||||||
|
.scale-cv .social_icon,
|
||||||
|
.scale-cv .interests_icon {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .education_container,
|
||||||
|
.scale-cv .experience_container,
|
||||||
|
.scale-cv .certificate_container {
|
||||||
|
width: 500px;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .education_time,
|
||||||
|
.scale-cv .experience_time,
|
||||||
|
.scale-cv .certificate_item {
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .education_rounder,
|
||||||
|
.scale-cv .experience_rounder {
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
margin-top: 0.22rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .education_line,
|
||||||
|
.scale-cv .experience_line {
|
||||||
|
width: 2px;
|
||||||
|
transform: translate(4.4px, -2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .education_data,
|
||||||
|
.scale-cv .experience_data,
|
||||||
|
.scale-cv .certificate_data {
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .certificate_rounder {
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .skills_content {
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .skills_box {
|
||||||
|
width: 100px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .skills_progress {
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transform: translate(0.01px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .languages_content {
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-cv .languages_text {
|
||||||
|
width: 115px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Body */
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0 0 var(--header-height) 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: var(--body-font);
|
||||||
|
font-size: var(--normal-font-size);
|
||||||
|
background-color: var(--body-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
ul,
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
|
color: var(--title-color);
|
||||||
|
font-weight: var(--font-medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Class CSS */
|
||||||
|
|
||||||
|
.section {
|
||||||
|
padding: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: var(--h2-font-size);
|
||||||
|
color: var(--title-color);
|
||||||
|
font-weight: var(--font-semi-bold);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: .35rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: var(--margin-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layout */
|
||||||
|
|
||||||
|
.bd-container {
|
||||||
|
max-width: 968px;
|
||||||
|
width: calc(100% - 3rem);
|
||||||
|
margin-left: var(--margin-3);
|
||||||
|
margin-right: var(--margin-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-header {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: var(--z-fixed);
|
||||||
|
background-color: var(--body-color);
|
||||||
|
box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav */
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
height: var(--header-height);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 968px) {
|
||||||
|
.nav_menu {
|
||||||
|
position: fixed;
|
||||||
|
bottom: -100%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: 2rem 1.5rem;
|
||||||
|
background-color: var(--body-color);
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 1rem 1rem 0 0;
|
||||||
|
z-index: var(--z-fixed);
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav_logo,
|
||||||
|
.nav_toggle {
|
||||||
|
color: var(--title-color);
|
||||||
|
font-weight: var(--font-medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav_toggle {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav_list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav_item {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav_link {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: var(--smaller-font-size);
|
||||||
|
color: var(--text-color-light);
|
||||||
|
font-weight: var(--font-medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav_link:hover {
|
||||||
|
color: var(--title-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav_icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: var(--margin-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show menu */
|
||||||
|
|
||||||
|
.show-menu {
|
||||||
|
bottom: var(--header-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Active menu link */
|
||||||
|
|
||||||
|
.active-link {
|
||||||
|
color: var(--title-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Home page */
|
||||||
|
|
||||||
|
.home {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_container {
|
||||||
|
gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_data {
|
||||||
|
gap: .5rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_img {
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
border-radius: 50%;
|
||||||
|
justify-self: center;
|
||||||
|
margin-bottom: var(--margin-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_title {
|
||||||
|
font-size: var(--h1-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_profession {
|
||||||
|
font-size: var(--normal-font-size);
|
||||||
|
margin-bottom: var(--margin-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_address {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_information {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: var(--small-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
display: flex;
|
||||||
|
width: 25px;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: var(--small-font-size);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_link:hover {
|
||||||
|
color: var(--title-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_button-movil {
|
||||||
|
display: inline-block;
|
||||||
|
border: 2px solid var(--text-color);
|
||||||
|
color: var(--title-color);
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
border-radius: .25rem;
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
font-weight: var(--font-medium);
|
||||||
|
margin-top: var(--margin-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_button-movil:hover {
|
||||||
|
background-color: var(--text-color);
|
||||||
|
color: var(--container-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Social page */
|
||||||
|
|
||||||
|
.social_container {
|
||||||
|
grid-template-columns: max-content;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social_link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: var(--small-font-size);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.social_link:hover {
|
||||||
|
color: var(--title-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.social_icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
display: flex;
|
||||||
|
width: 25px;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Profile page */
|
||||||
|
|
||||||
|
.profile_description {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Education page */
|
||||||
|
|
||||||
|
.education_content,
|
||||||
|
.experience_content,
|
||||||
|
.certificate_content {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.education_time,
|
||||||
|
.experience_time,
|
||||||
|
.certificate_item {
|
||||||
|
padding-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.education_rounder,
|
||||||
|
.experience_rounder {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: var(--text-color-light);
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-top: .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.education_line,
|
||||||
|
.experience_line {
|
||||||
|
display: block;
|
||||||
|
width: 2px;
|
||||||
|
height: 115%;
|
||||||
|
background-color: var(--text-color-light);
|
||||||
|
transform: translate(7px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.education_data,
|
||||||
|
.experience_data,
|
||||||
|
.certificate_data {
|
||||||
|
gap: .35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.education_title,
|
||||||
|
.experience_title,
|
||||||
|
.certificate_year {
|
||||||
|
font-size: var(--h3-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.education_studies,
|
||||||
|
.experience_company,
|
||||||
|
.certificate_title {
|
||||||
|
font-size: var(--small-font-size);
|
||||||
|
color: var(--title-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.education_year,
|
||||||
|
.experience_year {
|
||||||
|
font-size: var(--smaller-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.experience_description {
|
||||||
|
color: var(--text-color-light);
|
||||||
|
font-size: var(--smaller-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skills */
|
||||||
|
|
||||||
|
.skills_content {
|
||||||
|
gap: 0.2rem;
|
||||||
|
padding-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills_name {
|
||||||
|
margin-bottom: .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills_text {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills_box {
|
||||||
|
display: inline-block;
|
||||||
|
width: 150px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: var(--text-color-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills_progress {
|
||||||
|
background-color: var(--text-color);
|
||||||
|
display: block;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Certificates */
|
||||||
|
|
||||||
|
.certificate_container {
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate_rounder {
|
||||||
|
display: inline-block;
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
background-color: var(--text-color-light);
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 0.38rem;
|
||||||
|
margin-left: 0.37rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate_honours {
|
||||||
|
font-size: var(--smaller-font-size);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Languages */
|
||||||
|
|
||||||
|
.languages_content {
|
||||||
|
gap: 0.2rem;
|
||||||
|
padding-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.languages_name {
|
||||||
|
margin-bottom: .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.languages_text {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.languages_stars {
|
||||||
|
position: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.languages_stars_checked {
|
||||||
|
color: var(--text-color-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interests */
|
||||||
|
|
||||||
|
.interests_container {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
margin-top: var(--margin-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.interests_content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interests_icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: var(--text-color-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrolltop {
|
||||||
|
position: fixed;
|
||||||
|
right: 1.2rem;
|
||||||
|
bottom: -20%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.4rem;
|
||||||
|
background-color: var(--container-color-alt);
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
z-index: var(--z-tooltip);
|
||||||
|
transition: 0.4s;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrolltop_icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-scroll {
|
||||||
|
visibility: visible;
|
||||||
|
bottom: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Screen for small phones */
|
||||||
|
|
||||||
|
@media screen and (max-width: 320px) {
|
||||||
|
.nav_list {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 1rem 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Computer screen -> PDF */
|
||||||
|
|
||||||
|
@media screen and (min-width: 968px) {
|
||||||
|
body {
|
||||||
|
margin: 3rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-container {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-header,
|
||||||
|
.scrolltop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resume {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: .5fr 1fr;
|
||||||
|
background-color: var(--container-color);
|
||||||
|
box-shadow: 0 0 8px rgba(13, 12, 12, .15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.resume_left {
|
||||||
|
background-color: var(--container-color-alt);
|
||||||
|
}
|
||||||
|
|
||||||
|
.resume_left,
|
||||||
|
.resume_right {
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-pdf {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title,
|
||||||
|
.profile_description {
|
||||||
|
text-align: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_container {
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home_button-movil {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.languages_content {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.languages_text {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills_content {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interests_container {
|
||||||
|
grid-template-columns: repeat(4, max-content);
|
||||||
|
column-gap: 3.5rem;
|
||||||
|
padding-left: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
backend/userKnowledge.json
Normal file
64
backend/userKnowledge.json
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"first_name": "Nikola",
|
||||||
|
"last_name": "Petrov",
|
||||||
|
"phone_number": "+38670749506",
|
||||||
|
"occupation": "Student",
|
||||||
|
"birth": "14, November, 2000",
|
||||||
|
"living_location": "Ljubljana, Slovenia",
|
||||||
|
"web_link": "https://petrovv.com",
|
||||||
|
"git_link": "https://git.petrovv.com/explore",
|
||||||
|
"email": "nikola@petrovv.com",
|
||||||
|
"instagram_handle":"@nikolainsta7",
|
||||||
|
"instagram_link":"https://www.instagram.com/nikolainsta7",
|
||||||
|
"about_me": "I am Nikola, currently pursuing my studies at the Faculty of Electrical Engineering and Computer Science (FERI) in Maribor. My academic journey is largely driven by my interest in application and web development. I find the process of creating functional and user-friendly digital solutions both challenging and rewarding. This field allows me to blend creativity with technical skills, which I find particularly engaging.",
|
||||||
|
"experience": [
|
||||||
|
{
|
||||||
|
"title": "HW Developer",
|
||||||
|
"company": "Spica International",
|
||||||
|
"time": "17/03/2025 - 01/08/2025",
|
||||||
|
"des": "Worked on access menegment systems. Programed integrated devices, based on Buildroot using c++ and python web server."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Backend/Frontend",
|
||||||
|
"company": "RRC d.o.o",
|
||||||
|
"time": "01/09/2024 - 31/12/2024",
|
||||||
|
"des": "Worked on goverment websites for collage enrolment and student dorm requests."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Developer",
|
||||||
|
"company": "RRC d.o.o",
|
||||||
|
"time": "18/03/2024 - 31/05/2024",
|
||||||
|
"des": "Student practicum. Backend in java with frontend in ext JS and jQuery."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Developer/IT",
|
||||||
|
"company": "LightAct",
|
||||||
|
"time": "01/07/2022 - 01/09/2022",
|
||||||
|
"des": "I helped maintaining data base, worked on the application (integrated a capture card and IP camera), assembled new server rack, installed new UTP/power connectors in the office."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Mentor",
|
||||||
|
"company": "Institute 404",
|
||||||
|
"time": "08/06/2020 - 19/06/2020",
|
||||||
|
"des": "I helped primary school children with their projects with soldering, laser cutting, and building."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Maintenance technician",
|
||||||
|
"company": "Hella Saturnos d.o.o.",
|
||||||
|
"time": "04/09/2018 - 18/01/2019",
|
||||||
|
"des": "I maintained and repaired machines from plastic presses to personal stations."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"education": [
|
||||||
|
{
|
||||||
|
"title": "(FERI) Faculty of Electrical Engineering and Computer Science, University of Maribor",
|
||||||
|
"time": "01/10/2021 - CURRENT",
|
||||||
|
"des": "Graduate engineer of computer science and information technology."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "(SSTS Siska) Secondary school of technical professions siska",
|
||||||
|
"time": "01/09/2016 - 07/07/2021",
|
||||||
|
"des": "Electrotechnician."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
228
backend/views/cv2.hbs
Normal file
228
backend/views/cv2.hbs
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
<!--
|
||||||
|
┌──────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ @name CV generator │
|
||||||
|
│ @author Léa Gallier │
|
||||||
|
│ @version 1.0 │
|
||||||
|
│ @created 2022-12-19 │
|
||||||
|
│ @modified 2023-03-17 │
|
||||||
|
│ @description Resume CV with dark/light mode and PDF export │
|
||||||
|
└──────────────────────────────────────────────────────────────────────┘
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta http-equiv="Permissions-Policy" content="interest-cohort=()">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<title>CV</title>
|
||||||
|
<link rel="shortcut icon" href="/assets/pictures/favicon/favicon.ico" type="image/x-icon">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Import Fontawesome -->
|
||||||
|
<script src="https://kit.fontawesome.com/cb81440751.js" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<!-- Import stylesheets in CSS3 -->
|
||||||
|
<link rel="stylesheet" href="assets/stylesheets/style.css" type="text/css">
|
||||||
|
|
||||||
|
<!-- HTML2PDF.js -->
|
||||||
|
<!-- Version 0.8.0 -->
|
||||||
|
<!-- <script src="assets/javascripts/html2pdf.v0.8.0.bundle.min.js"></script> -->
|
||||||
|
<!-- Version 0.9.3 -->
|
||||||
|
<script defer src="assets/javascripts/html2pdf.v0.9.3.bundle.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Main Javascript file -->
|
||||||
|
<script defer src="assets/javascripts/main.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
{{#with userData}}
|
||||||
|
<header class="l-header" id="header">
|
||||||
|
<!-- Nav menu -->
|
||||||
|
<nav class="nav bd-container">
|
||||||
|
<a href="#" class="nav_logo">{{first_name}} {{last_name}}</a>
|
||||||
|
<div class="nav_menu" id="nav-menu">
|
||||||
|
<ul class="nav_list">
|
||||||
|
|
||||||
|
<li class="nav_item">
|
||||||
|
<a href="#home" class="nav_link active-link">
|
||||||
|
<i class="fa-solid fa-house nav_icon"></i>Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav_item">
|
||||||
|
<a href="#profile" class="nav_link">
|
||||||
|
<i class="fa-solid fa-user nav_icon"></i>Profile
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav_item">
|
||||||
|
<a href="#experience" class="nav_link">
|
||||||
|
<i class="fa-solid fa-briefcase nav_icon"></i>Experiences
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav_item">
|
||||||
|
<a href="#education" class="nav_link">
|
||||||
|
<i class="fa-solid fa-book-bookmark nav_icon"></i>Education
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nav_toggle" id="nav-toggle">
|
||||||
|
<i class="fa-solid fa-bars"></i>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="l-main bd-container">
|
||||||
|
<!-- Resume CV -->
|
||||||
|
<div class="resume" id="area-cv">
|
||||||
|
<div class="resume_left">
|
||||||
|
|
||||||
|
<!-- HOME -->
|
||||||
|
<section class="home" id="home">
|
||||||
|
<div class="home_container section bd-grid">
|
||||||
|
|
||||||
|
<div class="home_data bd-grid">
|
||||||
|
<img src="assets/pictures/profile.png" alt="Icon picture" class="home_img" id="home-img">
|
||||||
|
<!--<img alt="Icon picture" class="home_img" id="home-img">-->
|
||||||
|
<h1 class="home_title">{{first_name}} {{last_name}}</b></h1>
|
||||||
|
<h3 class="home_profession">{{occupation}}</h3>
|
||||||
|
<div>
|
||||||
|
<a download="" id="download-button" class="home_button-movil">Download</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="home_address bd-grid">
|
||||||
|
<span class="home_information">
|
||||||
|
<i class="fa-solid fa-location-dot home_icon"></i>{{living_location}}
|
||||||
|
</span>
|
||||||
|
<span class="home_information">
|
||||||
|
<i class="fa-solid fa-calendar-days home_icon"></i>{{birth}}
|
||||||
|
</span>
|
||||||
|
<span class="home_information">
|
||||||
|
<a href="mailto:{{email}}" class="home_link">
|
||||||
|
<i class="fa-solid fa-envelope home_icon"></i>{{email}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
<span class="home_information">
|
||||||
|
<a href="tel:{{phone_number}}" class="home_link">
|
||||||
|
<i class="fa-solid fa-phone home_icon"></i>{{phone_number}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
<span class="home_information">
|
||||||
|
<a href="{{web_link}}" class="home_link">
|
||||||
|
<i class="fa-solid fa-globe home_icon"></i>{{web_link}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Theme change button -->
|
||||||
|
<i class="fa-solid fa-moon change-theme" title="Theme" id="theme-button"></i>
|
||||||
|
|
||||||
|
<!-- Button to generate and download the pdf. Available for desktop. -->
|
||||||
|
<i class="fa-solid fa-download generate-pdf" title="Generate PDF" id="resume-button"></i>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- SOCIAL -->
|
||||||
|
<section class="social section">
|
||||||
|
<h2 class="section-title">Social</h2>
|
||||||
|
|
||||||
|
<div class="social_container bd-grid">
|
||||||
|
<a href="{{git_link}}" target="_blank" class="social_link">
|
||||||
|
<i class="fa-brands fa-git social_icon"></i>{{git_link}}
|
||||||
|
</a>
|
||||||
|
<a href="{{instagram_link}}" target="_blank" class="social_link">
|
||||||
|
<i class="fa-brands fa-instagram social_icon"></i>{{instagram_handle}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- PROFILE -->
|
||||||
|
<section class="profile section" id="profile">
|
||||||
|
<h2 class="section-title">Profile</h2>
|
||||||
|
|
||||||
|
<p class="profile_description">
|
||||||
|
{{about_me}}
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="resume_right">
|
||||||
|
|
||||||
|
<!-- EXPERIENCE -->
|
||||||
|
<section class="experience section" id="experience">
|
||||||
|
<h2 class="section-title">Experience</h2>
|
||||||
|
|
||||||
|
<div class="experience_container bd-grid">
|
||||||
|
|
||||||
|
{{#each experience}}
|
||||||
|
<div class="experience_content">
|
||||||
|
<div class="experience_time">
|
||||||
|
<span class="experience_rounder"></span>
|
||||||
|
{{#unless @last}}
|
||||||
|
<span class="experience_line"></span>
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
<div class="experience_data bd-grid">
|
||||||
|
<h3 class="experience_title">{{title}}</h3>
|
||||||
|
<span class="experience_company">{{company}}</span>
|
||||||
|
<span class="experience_year">{{time}}</span>
|
||||||
|
<p class="experience_description">
|
||||||
|
{{des}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- EDUCATION -->
|
||||||
|
<section class="education section" id="education">
|
||||||
|
<h2 class="section-title">Education</h2>
|
||||||
|
|
||||||
|
<div class="education_container bd-grid">
|
||||||
|
|
||||||
|
{{#each education}}
|
||||||
|
<div class="education_content">
|
||||||
|
<div class="education_time">
|
||||||
|
<span class="education_rounder"></span>
|
||||||
|
{{#unless @last}}
|
||||||
|
<span class="education_line"></span>
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
<div class="education_data bd-grid">
|
||||||
|
<h3 class="education_title">{{des}}</h3>
|
||||||
|
<span class="education_studies">{{title}}</span>
|
||||||
|
<span class="education_year">{{time}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<a href="#" class="scrolltop" id="scroll-top">
|
||||||
|
<i class="fa-solid fa-arrow-up scrolltop_icon"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{{/with}}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
209
bun.lock
Normal file
209
bun.lock
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "web",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "^5.0.3",
|
||||||
|
"@types/morgan": "^1.9.10",
|
||||||
|
"bun-types": "^1.2.22",
|
||||||
|
"express": "^5.1.0",
|
||||||
|
"hbs": "^4.2.0",
|
||||||
|
"morgan": "~1.10.1",
|
||||||
|
"typescript": "^5.9.2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="],
|
||||||
|
|
||||||
|
"@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="],
|
||||||
|
|
||||||
|
"@types/express": ["@types/express@5.0.6", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", "@types/serve-static": "^2" } }, "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA=="],
|
||||||
|
|
||||||
|
"@types/express-serve-static-core": ["@types/express-serve-static-core@5.1.1", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A=="],
|
||||||
|
|
||||||
|
"@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="],
|
||||||
|
|
||||||
|
"@types/morgan": ["@types/morgan@1.9.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
|
||||||
|
|
||||||
|
"@types/qs": ["@types/qs@6.15.0", "", {}, "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow=="],
|
||||||
|
|
||||||
|
"@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="],
|
||||||
|
|
||||||
|
"@types/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="],
|
||||||
|
|
||||||
|
"@types/serve-static": ["@types/serve-static@2.2.0", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*" } }, "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ=="],
|
||||||
|
|
||||||
|
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||||
|
|
||||||
|
"basic-auth": ["basic-auth@2.0.1", "", { "dependencies": { "safe-buffer": "5.1.2" } }, "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg=="],
|
||||||
|
|
||||||
|
"body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
|
||||||
|
|
||||||
|
"bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
|
||||||
|
|
||||||
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||||
|
|
||||||
|
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||||
|
|
||||||
|
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
||||||
|
|
||||||
|
"content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
|
||||||
|
|
||||||
|
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
||||||
|
|
||||||
|
"cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
||||||
|
|
||||||
|
"cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
|
||||||
|
|
||||||
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
|
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
||||||
|
|
||||||
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
|
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||||
|
|
||||||
|
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
||||||
|
|
||||||
|
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||||
|
|
||||||
|
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||||
|
|
||||||
|
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||||
|
|
||||||
|
"escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
|
||||||
|
|
||||||
|
"etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
|
||||||
|
|
||||||
|
"express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
|
||||||
|
|
||||||
|
"finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
|
||||||
|
|
||||||
|
"foreachasync": ["foreachasync@3.0.0", "", {}, "sha512-J+ler7Ta54FwwNcx6wQRDhTIbNeyDcARMkOcguEqnEdtm0jKvN3Li3PDAb2Du3ubJYEWfYL83XMROXdsXAXycw=="],
|
||||||
|
|
||||||
|
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
|
||||||
|
|
||||||
|
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
|
||||||
|
|
||||||
|
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||||
|
|
||||||
|
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||||
|
|
||||||
|
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||||
|
|
||||||
|
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||||
|
|
||||||
|
"handlebars": ["handlebars@4.7.7", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.0", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA=="],
|
||||||
|
|
||||||
|
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||||
|
|
||||||
|
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||||
|
|
||||||
|
"hbs": ["hbs@4.2.0", "", { "dependencies": { "handlebars": "4.7.7", "walk": "2.3.15" } }, "sha512-dQwHnrfWlTk5PvG9+a45GYpg0VpX47ryKF8dULVd6DtwOE6TEcYQXQ5QM6nyOx/h7v3bvEQbdn19EDAcfUAgZg=="],
|
||||||
|
|
||||||
|
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
||||||
|
|
||||||
|
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
||||||
|
|
||||||
|
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||||
|
|
||||||
|
"ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
|
||||||
|
|
||||||
|
"is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
|
||||||
|
|
||||||
|
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||||
|
|
||||||
|
"media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
|
||||||
|
|
||||||
|
"merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
|
||||||
|
|
||||||
|
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||||
|
|
||||||
|
"mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
||||||
|
|
||||||
|
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||||
|
|
||||||
|
"morgan": ["morgan@1.10.1", "", { "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", "depd": "~2.0.0", "on-finished": "~2.3.0", "on-headers": "~1.1.0" } }, "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A=="],
|
||||||
|
|
||||||
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
|
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||||
|
|
||||||
|
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
|
||||||
|
|
||||||
|
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
||||||
|
|
||||||
|
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
|
||||||
|
|
||||||
|
"on-headers": ["on-headers@1.1.0", "", {}, "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A=="],
|
||||||
|
|
||||||
|
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||||
|
|
||||||
|
"parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
|
||||||
|
|
||||||
|
"path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="],
|
||||||
|
|
||||||
|
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
||||||
|
|
||||||
|
"qs": ["qs@6.15.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ=="],
|
||||||
|
|
||||||
|
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
|
||||||
|
|
||||||
|
"raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
|
||||||
|
|
||||||
|
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
|
||||||
|
|
||||||
|
"safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||||
|
|
||||||
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||||
|
|
||||||
|
"send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
|
||||||
|
|
||||||
|
"serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
|
||||||
|
|
||||||
|
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||||
|
|
||||||
|
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
||||||
|
|
||||||
|
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
|
||||||
|
|
||||||
|
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
||||||
|
|
||||||
|
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
||||||
|
|
||||||
|
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||||
|
|
||||||
|
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
||||||
|
|
||||||
|
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||||
|
|
||||||
|
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
|
"uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="],
|
||||||
|
|
||||||
|
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
||||||
|
|
||||||
|
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
||||||
|
|
||||||
|
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
||||||
|
|
||||||
|
"walk": ["walk@2.3.15", "", { "dependencies": { "foreachasync": "^3.0.0" } }, "sha512-4eRTBZljBfIISK1Vnt69Gvr2w/wc3U6Vtrw7qiN5iqYJPH7LElcYh/iU4XWhdCy2dZqv1ToMyYlybDylfG/5Vg=="],
|
||||||
|
|
||||||
|
"wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="],
|
||||||
|
|
||||||
|
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||||
|
|
||||||
|
"morgan/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||||
|
|
||||||
|
"morgan/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="],
|
||||||
|
|
||||||
|
"morgan/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
14
package.json
Normal file
14
package.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "web",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "^5.0.3",
|
||||||
|
"@types/morgan": "^1.9.10",
|
||||||
|
"express": "^5.1.0",
|
||||||
|
"hbs": "^4.2.0",
|
||||||
|
"morgan": "~1.10.1",
|
||||||
|
"bun-types": "^1.2.22",
|
||||||
|
"typescript": "^5.9.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
34
tsconfig.json
Normal file
34
tsconfig.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Enable latest features
|
||||||
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"DOM"
|
||||||
|
],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react",
|
||||||
|
"jsxFactory": "elements.createElement",
|
||||||
|
"allowJs": true,
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
|
"types": [
|
||||||
|
"bun-types"
|
||||||
|
],
|
||||||
|
"baseUrl": "./"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user