feat: add contact form, links and project page
0
.phpactor.yml
Normal file
11
README.md
|
@ -1,4 +1,15 @@
|
|||
|
||||
## Structure
|
||||
|
||||
- Tech wall
|
||||
- Pro projects
|
||||
- Side projects
|
||||
- Find me on
|
||||
- Volunteering
|
||||
- Contact form
|
||||
- Reading list
|
||||
|
||||
|
||||
## Technology walls
|
||||
|
||||
Mosaic of squared technologies logos
|
||||
|
|
43
assets/locales/en.yaml
Normal file
|
@ -0,0 +1,43 @@
|
|||
external-website: External website
|
||||
|
||||
last-update: "Last update :"
|
||||
about-website: "About this website"
|
||||
|
||||
page:
|
||||
title: Matthieu Bessat - Web developer
|
||||
|
||||
profile:
|
||||
intro:
|
||||
main: Hi! I'm Matthieu
|
||||
secondary: I like to program stuff
|
||||
|
||||
technologies:
|
||||
title: Some of the technologies that I'm currently working with
|
||||
|
||||
projects:
|
||||
pro:
|
||||
title: Highlighted professional projects
|
||||
side:
|
||||
title: Highlighted side projects
|
||||
|
||||
links:
|
||||
title: Find me on...
|
||||
|
||||
contact:
|
||||
no-script: If you want to use the contact form, you will need to enable javascript to run free-ish software
|
||||
title: Contact me
|
||||
use-email: "You can contact me via e-mail:"
|
||||
use-form: "Or you can use the form bellow if you prefer not opening your email client."
|
||||
form:
|
||||
name: Your name
|
||||
email: Your email
|
||||
subject: The subject
|
||||
message: Your message
|
||||
submit: Submit
|
||||
sucess: Thanks, I will try to read pursly your message
|
||||
fail: Failure
|
||||
|
||||
locales:
|
||||
choose: "Choose your language:"
|
||||
|
||||
|
47
assets/locales/fr.yaml
Normal file
|
@ -0,0 +1,47 @@
|
|||
go-back-to-main: Revenir à la page principale
|
||||
external-website: Site web externe
|
||||
|
||||
last-update: Dernière mise à jour le
|
||||
about-website: A propos de ce site
|
||||
|
||||
page:
|
||||
title: Matthieu Bessat - Développeur web
|
||||
|
||||
profile:
|
||||
intro:
|
||||
main: Salut, je m'appelle Matthieu
|
||||
secondary: J'aime bien programmer des trucs
|
||||
|
||||
technologies:
|
||||
title: Quelques des technologies avec lesquelles je travaille en ce moment
|
||||
|
||||
projects:
|
||||
title: Projets
|
||||
project: Projet
|
||||
pro:
|
||||
title: Projets professionels
|
||||
side:
|
||||
title: Autres projets
|
||||
background: Contexte
|
||||
solution: Solutions
|
||||
technologies: Technologies utilisées
|
||||
|
||||
|
||||
links:
|
||||
title: Retrouvez moi sur...
|
||||
|
||||
contact:
|
||||
no-script: Si vous voulez utiliser le formulaire de contact, vous devez activer le javascript (le site propose un code libre)
|
||||
title: Me contacter
|
||||
use-email: "Vous pouvez me contacter par e-mail :"
|
||||
use-form: "Ou vous pouvez utiliser le formulaire ci-dessous"
|
||||
form:
|
||||
name: Votre nom
|
||||
email: Votre email
|
||||
subject: Sujet du message
|
||||
message: Votre message
|
||||
submit: Soumettre
|
||||
|
||||
locales:
|
||||
choose: "Choisissez votre langue : "
|
||||
|
52
assets/scripts/contact.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
import axios from 'axios'
|
||||
|
||||
function contactFormSetup() {
|
||||
/**
|
||||
* Contact form javascript implementation
|
||||
*/
|
||||
const namespace = "lefuturiste"
|
||||
const postURL = "https://contact-form.thingmill.fr"
|
||||
|
||||
const form = document.getElementById('contact-form')
|
||||
const formName = document.getElementById('contact-form-name')
|
||||
const formEmail = document.getElementById('contact-form-email')
|
||||
const formSubject = document.getElementById('contact-form-subject')
|
||||
const formMessage = document.getElementById('contact-form-message')
|
||||
|
||||
const formSubmit = document.getElementById('contact-form-submit')
|
||||
const formButtonLoading = document.getElementById('contact-form-loading')
|
||||
const successAlert = document.getElementById('contact-alert-success')
|
||||
const errorAlert = document.getElementById('contact-alert-error')
|
||||
|
||||
form.onsubmit = (e) => {
|
||||
e.preventDefault()
|
||||
console.log('> Attempting to send a message', formName.value, formEmail.value, formMessage.value)
|
||||
let savedButtonText = formSubmit.textContent;
|
||||
formButtonLoading.style.display = 'block'
|
||||
formSubmit.style.display = 'none'
|
||||
axios.post(postURL + '/' + namespace, {
|
||||
name: formName.value,
|
||||
email: formEmail.value,
|
||||
subject: formSubject.value,
|
||||
message: formMessage.value
|
||||
}).then(() => {
|
||||
console.log('> Message sent')
|
||||
successAlert.style.display = "block";
|
||||
formButtonLoading.style.display = 'none'
|
||||
formSubmit.style.display = 'block'
|
||||
formSubmit.textContent = savedButtonText;
|
||||
|
||||
// reset the form?
|
||||
// formName.value = ''
|
||||
// formEmail.value = ''
|
||||
// formSubject.value = ''
|
||||
// formMessage.value = ''
|
||||
}).catch((err) => {
|
||||
errorAlert.style.display = "block";
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { contactFormSetup }
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import axios from 'axios'
|
||||
|
||||
import { contactFormSetup } from './contact'
|
||||
|
||||
contactFormSetup()
|
||||
|
8
assets/styles/components/button.scss
Normal file
|
@ -0,0 +1,8 @@
|
|||
.btn {
|
||||
border-radius: 2px;
|
||||
box-shadow: 1px 2px 4px 0 rgba(0,0,0,.08);
|
||||
padding: 1em 1.5em;
|
||||
margin-top: 1em;
|
||||
border: 1px solid #ccc;
|
||||
font-size: 16px;
|
||||
}
|
13
assets/styles/components/chips.scss
Normal file
|
@ -0,0 +1,13 @@
|
|||
.chips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.chip {
|
||||
margin-right: .5em;
|
||||
padding: 0.5em 0.9em;
|
||||
background: $primary;
|
||||
color: white;
|
||||
font-size: .9em;
|
||||
border-radius: 10rem;
|
||||
}
|
||||
}
|
125
assets/styles/components/contact.scss
Normal file
|
@ -0,0 +1,125 @@
|
|||
.means-of-contact {
|
||||
|
||||
p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-form-container {
|
||||
|
||||
form {
|
||||
border-radius: 3px;
|
||||
border: 1px dashed #80808054;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.contact-form-first-group {
|
||||
display: flex;
|
||||
|
||||
.contact-form-input:first-of-type {
|
||||
margin-right: .4em;
|
||||
}
|
||||
.contact-form-input:nth-of-type(2) {
|
||||
margin-left: .4em;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-form-input {
|
||||
width: 100%;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
width: 100%;
|
||||
margin-top: .6em;
|
||||
border-radius: 3px;
|
||||
padding: .6em;
|
||||
border: 1px solid #dbdbdb;
|
||||
box-shadow: 1px 2px 4px 0 rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.contact-form-message textarea {
|
||||
min-height: 8em;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
@keyframes rotating {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.loading-button {
|
||||
display: none;
|
||||
svg {
|
||||
animation: rotating 2s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-form-submit {
|
||||
|
||||
}
|
||||
|
||||
.contact-form-container {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.alert {
|
||||
padding: 1em;
|
||||
margin-bottom: 1em;
|
||||
border-radius: 3px;
|
||||
|
||||
.alert-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.alert.alert-success {
|
||||
background: green;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.alert.alert-error {
|
||||
background: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.alert .alert-icon {
|
||||
padding-right: 0.6em;
|
||||
}
|
||||
|
||||
@media (min-width: $sm-breakpoint) {
|
||||
.contact-form-first-group {
|
||||
.contact-form-input {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $sm-breakpoint) {
|
||||
.contact-form {
|
||||
.contact-form-first-group {
|
||||
display: block;
|
||||
.contact-form-input {
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.contact-form-input:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
46
assets/styles/components/footer.scss
Normal file
|
@ -0,0 +1,46 @@
|
|||
.footer-buffer {
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: auto;
|
||||
border-top: 1px solid gray;
|
||||
border-color: rgb(84, 91, 94) !important;
|
||||
}
|
||||
|
||||
.footer-container {
|
||||
padding: 2em 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.footer-left div {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
.locale-switch-large {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.l {
|
||||
margin-right: 1em;
|
||||
}
|
||||
.r {
|
||||
a {
|
||||
margin-right: .2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.locale-switch-short {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: $sm-breakpoint) {
|
||||
.locale-switch-large {
|
||||
display: none;
|
||||
}
|
||||
.locale-switch-short {
|
||||
display: block;
|
||||
}
|
||||
}
|
57
assets/styles/components/links.scss
Normal file
|
@ -0,0 +1,57 @@
|
|||
.links-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.links {
|
||||
width: 80%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
.link-card {
|
||||
margin: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 10em;
|
||||
}
|
||||
|
||||
.link-card-title {
|
||||
margin-top: .9em;
|
||||
}
|
||||
|
||||
.link-card-logo {
|
||||
padding: .5em;
|
||||
width: 4em;
|
||||
height: 4em;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
|
||||
img {
|
||||
max-width: 4em;
|
||||
max-height: 4em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $sm-breakpoint) {
|
||||
.links {
|
||||
width: 100%;
|
||||
.link-card {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $xs-breakpoint) {
|
||||
.links {
|
||||
width: 100%;
|
||||
.link-card {
|
||||
min-width: 6em;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -95,16 +95,66 @@ img.main-profile {
|
|||
|
||||
.profile-content .title-1 {
|
||||
text-align: center;
|
||||
font-size: 3.5em;
|
||||
font-size: 3em;
|
||||
margin-bottom: 0.4em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.profile-content .title-2 {
|
||||
text-align: center;
|
||||
font-size: 2em;
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.profile-content .subtitle {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: $sm-breakpoint) {
|
||||
.profile-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
.profile-imgs-container {
|
||||
margin-right: 0;
|
||||
}
|
||||
.profile-content {
|
||||
margin-left: 0;
|
||||
margin-top: -1em;
|
||||
|
||||
.title-1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
.title-2 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-imgs-container {
|
||||
transform: scale(0.7);
|
||||
margin-top: -4em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $xs-breakpoint) {
|
||||
.landing-section {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.profile-content {
|
||||
margin-top: -4em;
|
||||
padding: 0 1em;
|
||||
|
||||
.title-1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
.title-2 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
.profile-imgs-container {
|
||||
transform: scale(0.6);
|
||||
margin-top: -4em;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,25 @@
|
|||
.projects {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: 1em;
|
||||
|
||||
.project-card {
|
||||
width: 20em;
|
||||
margin-right: .5em;
|
||||
margin-bottom: .5em;
|
||||
border: 1px solid gray;
|
||||
padding: 1.5em;
|
||||
border-radius: 5px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.project-top {
|
||||
display: flex;
|
||||
|
||||
}
|
||||
|
||||
.project-left {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.project-title {
|
||||
|
@ -19,4 +30,40 @@
|
|||
font-size: .9em;
|
||||
color: gray;
|
||||
}
|
||||
.project-img {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
.project-right {
|
||||
padding-left: .5em;
|
||||
|
||||
}
|
||||
|
||||
.project-bottom {
|
||||
padding-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media(min-width: $lg-breakpoint) {
|
||||
.projects {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: $md-breakpoint) {
|
||||
.projects {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $sm-breakpoint) {
|
||||
.projects {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.project-right {
|
||||
padding-left: 1em !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
img {
|
||||
width: 100%;
|
||||
}
|
||||
padding: 2em;
|
||||
}
|
||||
.item-bg img.img-stretch {
|
||||
width: auto;
|
||||
|
@ -70,7 +71,13 @@
|
|||
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
@media (min-width: 400px) {
|
||||
.item-bg {
|
||||
padding: 1em !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1000px) {
|
||||
.tech-mosaic {
|
||||
.item {
|
||||
flex-basis: percentage(math.div(1, 5));
|
||||
|
@ -78,14 +85,14 @@
|
|||
|
||||
}
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
@media (max-width: 800px) {
|
||||
.tech-mosaic {
|
||||
.item {
|
||||
flex-basis: percentage(math.div(1, 3));
|
||||
flex-basis: percentage(math.div(1, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
@media (max-width: 400px) {
|
||||
.tech-mosaic {
|
||||
.item {
|
||||
flex-basis: percentage(math.div(1, 2));
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
p {
|
||||
line-height: 1.45em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: xx-large;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: x-large;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
|
||||
.section-title {
|
||||
display: grid;
|
||||
font-size: 1.2em;
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=Libre+Baskerville&display=swap');
|
||||
|
||||
$lg-breakpoint: 1500px;
|
||||
$md-breakpoint: 1000px;
|
||||
$sm-breakpoint: 900px;
|
||||
$xs-breakpoint: 400px;
|
||||
|
||||
$primary: #4ba05f;
|
||||
$secondary: #a04b8c;
|
||||
|
||||
|
@ -7,10 +12,21 @@ $secondary: #a04b8c;
|
|||
@import './components/profile.scss';
|
||||
@import './components/projects.scss';
|
||||
@import './components/technologies.scss';
|
||||
@import './components/links.scss';
|
||||
@import './components/typography.scss';
|
||||
@import './components/footer.scss';
|
||||
@import './components/contact.scss';
|
||||
@import './components/button.scss';
|
||||
@import './components/chips.scss';
|
||||
|
||||
p {
|
||||
line-height: 1.2em;
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
@ -25,7 +41,45 @@ p {
|
|||
font-family: 'Libre Baskerville', serif;
|
||||
}
|
||||
|
||||
|
||||
section {
|
||||
border-bottom: 1px solid gray;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
section:last-of-type {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.about-header {
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: $lg-breakpoint) {
|
||||
.container {
|
||||
width: 58%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $md-breakpoint) {
|
||||
.container {
|
||||
width: 65%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $md-breakpoint) {
|
||||
.container {
|
||||
width: 75%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $sm-breakpoint) {
|
||||
.container {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $xs-breakpoint) {
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
"slim/twig-view": "^3.3",
|
||||
"symfony/yaml": "^6.0",
|
||||
"php-di/slim-bridge": "^3.2",
|
||||
"symfony/var-dumper": "^6.0"
|
||||
"symfony/var-dumper": "^6.0",
|
||||
"adbario/php-dot-notation": "^3.1",
|
||||
"boronczyk/localization-middleware": "^2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
376
composer.lock
generated
|
@ -4,8 +4,114 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "5b64e03d031244562c5d143e11e9aa3e",
|
||||
"content-hash": "cec518bea90ee444e31994b065bc4f79",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adbario/php-dot-notation",
|
||||
"version": "3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/adbario/php-dot-notation.git",
|
||||
"reference": "aca06bf775809808232b8c21ce1ca3a4fca70ace"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/adbario/php-dot-notation/zipball/aca06bf775809808232b8c21ce1ca3a4fca70ace",
|
||||
"reference": "aca06bf775809808232b8c21ce1ca3a4fca70ace",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.5",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"squizlabs/php_codesniffer": "^3.6"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Adbar\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Riku Särkinen",
|
||||
"email": "riku@adbar.io"
|
||||
}
|
||||
],
|
||||
"description": "PHP dot notation access to arrays",
|
||||
"homepage": "https://github.com/adbario/php-dot-notation",
|
||||
"keywords": [
|
||||
"ArrayAccess",
|
||||
"dotnotation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/adbario/php-dot-notation/issues",
|
||||
"source": "https://github.com/adbario/php-dot-notation/tree/3.1.1"
|
||||
},
|
||||
"time": "2022-03-28T01:09:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "boronczyk/localization-middleware",
|
||||
"version": "2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tboronczyk/localization-middleware.git",
|
||||
"reference": "c2370e2631351ee35e21095db258a939fdb61368"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/tboronczyk/localization-middleware/zipball/c2370e2631351ee35e21095db258a939fdb61368",
|
||||
"reference": "c2370e2631351ee35e21095db258a939fdb61368",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/http-server-middleware": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.4",
|
||||
"slim/psr7": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Boronczyk\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Timothy Boronczyk",
|
||||
"email": "tboronczyk@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "PSR-15 middleware to assist primarily with language-based content negotiation and various other localization tasks.",
|
||||
"homepage": "https://github.com/tboronczyk/localization-middleware",
|
||||
"keywords": [
|
||||
"localization",
|
||||
"psr-15",
|
||||
"slim"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/tboronczyk/localization-middleware/issues",
|
||||
"source": "https://github.com/tboronczyk/localization-middleware/tree/2.0.1"
|
||||
},
|
||||
"time": "2021-04-15T02:46:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fig/http-message-util",
|
||||
"version": "1.1.5",
|
||||
|
@ -62,6 +168,65 @@
|
|||
},
|
||||
"time": "2020-11-24T22:02:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"version": "v1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/serializable-closure.git",
|
||||
"reference": "09f0e9fb61829f628205b7c94906c28740ff9540"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/09f0e9fb61829f628205b7c94906c28740ff9540",
|
||||
"reference": "09f0e9fb61829f628205b7c94906c28740ff9540",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"pestphp/pest": "^1.18",
|
||||
"phpstan/phpstan": "^0.12.98",
|
||||
"symfony/var-dumper": "^5.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\SerializableClosure\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
},
|
||||
{
|
||||
"name": "Nuno Maduro",
|
||||
"email": "nuno@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.",
|
||||
"keywords": [
|
||||
"closure",
|
||||
"laravel",
|
||||
"serializable"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/serializable-closure/issues",
|
||||
"source": "https://github.com/laravel/serializable-closure"
|
||||
},
|
||||
"time": "2022-05-16T17:09:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"version": "v1.3.0",
|
||||
|
@ -112,71 +277,6 @@
|
|||
},
|
||||
"time": "2018-02-13T20:26:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "opis/closure",
|
||||
"version": "3.6.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opis/closure.git",
|
||||
"reference": "3d81e4309d2a927abbe66df935f4bb60082805ad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad",
|
||||
"reference": "3d81e4309d2a927abbe66df935f4bb60082805ad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.4 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"jeremeamia/superclosure": "^2.0",
|
||||
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.6.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Opis\\Closure\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Marius Sarca",
|
||||
"email": "marius.sarca@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Sorin Sarca",
|
||||
"email": "sarca_sorin@hotmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.",
|
||||
"homepage": "https://opis.io/closure",
|
||||
"keywords": [
|
||||
"anonymous functions",
|
||||
"closure",
|
||||
"function",
|
||||
"serializable",
|
||||
"serialization",
|
||||
"serialize"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/opis/closure/issues",
|
||||
"source": "https://github.com/opis/closure/tree/3.6.3"
|
||||
},
|
||||
"time": "2022-01-27T09:35:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-di/invoker",
|
||||
"version": "2.3.3",
|
||||
|
@ -234,21 +334,21 @@
|
|||
},
|
||||
{
|
||||
"name": "php-di/php-di",
|
||||
"version": "6.3.5",
|
||||
"version": "6.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-DI/PHP-DI.git",
|
||||
"reference": "b8126d066ce144765300ee0ab040c1ed6c9ef588"
|
||||
"reference": "ae0f1b3b03d8b29dff81747063cbfd6276246cc4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/b8126d066ce144765300ee0ab040c1ed6c9ef588",
|
||||
"reference": "b8126d066ce144765300ee0ab040c1ed6c9ef588",
|
||||
"url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/ae0f1b3b03d8b29dff81747063cbfd6276246cc4",
|
||||
"reference": "ae0f1b3b03d8b29dff81747063cbfd6276246cc4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"opis/closure": "^3.5.5",
|
||||
"php": ">=7.2.0",
|
||||
"laravel/serializable-closure": "^1.0",
|
||||
"php": ">=7.4.0",
|
||||
"php-di/invoker": "^2.0",
|
||||
"php-di/phpdoc-reader": "^2.0.1",
|
||||
"psr/container": "^1.0"
|
||||
|
@ -257,12 +357,12 @@
|
|||
"psr/container-implementation": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "~1.2",
|
||||
"doctrine/annotations": "~1.10",
|
||||
"friendsofphp/php-cs-fixer": "^2.4",
|
||||
"mnapoli/phpunit-easymock": "^1.2",
|
||||
"ocramius/proxy-manager": "^2.0.2",
|
||||
"ocramius/proxy-manager": "^2.11.2",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpunit/phpunit": "^8.5|^9.0"
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"suggest": {
|
||||
"doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
|
||||
|
@ -294,7 +394,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-DI/PHP-DI/issues",
|
||||
"source": "https://github.com/PHP-DI/PHP-DI/tree/6.3.5"
|
||||
"source": "https://github.com/PHP-DI/PHP-DI/tree/6.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -306,7 +406,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-09-02T09:49:58+00:00"
|
||||
"time": "2022-04-09T16:46:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-di/phpdoc-reader",
|
||||
|
@ -839,22 +939,22 @@
|
|||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "4.9.0",
|
||||
"version": "4.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim.git",
|
||||
"reference": "44d3c9c0bfcc47e52e42b097b6062689d21b904b"
|
||||
"reference": "0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/44d3c9c0bfcc47e52e42b097b6062689d21b904b",
|
||||
"reference": "44d3c9c0bfcc47e52e42b097b6062689d21b904b",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0",
|
||||
"reference": "0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"nikic/fast-route": "^1.3",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/container": "^1.0 || ^2.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
|
@ -865,13 +965,15 @@
|
|||
"require-dev": {
|
||||
"adriansuter/php-autoload-override": "^1.2",
|
||||
"ext-simplexml": "*",
|
||||
"guzzlehttp/psr7": "^2.0",
|
||||
"guzzlehttp/psr7": "^2.1",
|
||||
"httpsoft/http-message": "^1.0",
|
||||
"httpsoft/http-server-request": "^1.0",
|
||||
"laminas/laminas-diactoros": "^2.8",
|
||||
"nyholm/psr7": "^1.4",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"nyholm/psr7-server": "^1.0",
|
||||
"phpspec/prophecy": "^1.14",
|
||||
"phpspec/prophecy": "^1.15",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpstan/phpstan": "^0.12.99",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"slim/http": "^1.2",
|
||||
"slim/psr7": "^1.5",
|
||||
|
@ -948,7 +1050,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-05T03:00:00+00:00"
|
||||
"time": "2022-03-14T14:18:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/twig-view",
|
||||
|
@ -1017,16 +1119,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1041,7 +1143,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1079,7 +1181,7 @@
|
|||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1095,20 +1197,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-20T20:35:02+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1123,7 +1225,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1162,7 +1264,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1178,20 +1280,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-11-30T18:21:41+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1200,7 +1302,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1245,7 +1347,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1261,20 +1363,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-04T08:16:47+00:00"
|
||||
"time": "2022-05-10T07:21:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.25.0",
|
||||
"version": "v1.26.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||
"reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f"
|
||||
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f",
|
||||
"reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1283,7 +1385,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
"dev-main": "1.26-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
|
@ -1324,7 +1426,7 @@
|
|||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.25.0"
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1340,24 +1442,24 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-09-13T13:58:11+00:00"
|
||||
"time": "2022-05-24T11:49:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v6.0.6",
|
||||
"version": "v6.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-dumper.git",
|
||||
"reference": "38358405ae948963c50a3aae3dfea598223ba15e"
|
||||
"reference": "98587d939cb783aa04e828e8fa857edaca24c212"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/38358405ae948963c50a3aae3dfea598223ba15e",
|
||||
"reference": "38358405ae948963c50a3aae3dfea598223ba15e",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/98587d939cb783aa04e828e8fa857edaca24c212",
|
||||
"reference": "98587d939cb783aa04e828e8fa857edaca24c212",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.2",
|
||||
"php": ">=8.1",
|
||||
"symfony/polyfill-mbstring": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
|
@ -1412,7 +1514,7 @@
|
|||
"dump"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/var-dumper/tree/v6.0.6"
|
||||
"source": "https://github.com/symfony/var-dumper/tree/v6.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1428,24 +1530,24 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-02T12:58:14+00:00"
|
||||
"time": "2022-05-21T13:34:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v6.0.3",
|
||||
"version": "v6.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "e77f3ea0b21141d771d4a5655faa54f692b34af5"
|
||||
"reference": "b01c4e7dc6a51cbf114567af04a19789fd1011fe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/e77f3ea0b21141d771d4a5655faa54f692b34af5",
|
||||
"reference": "e77f3ea0b21141d771d4a5655faa54f692b34af5",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/b01c4e7dc6a51cbf114567af04a19789fd1011fe",
|
||||
"reference": "b01c4e7dc6a51cbf114567af04a19789fd1011fe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.2",
|
||||
"php": ">=8.1",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"conflict": {
|
||||
|
@ -1486,7 +1588,7 @@
|
|||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v6.0.3"
|
||||
"source": "https://github.com/symfony/yaml/tree/v6.1.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1502,20 +1604,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-01-26T17:23:29+00:00"
|
||||
"time": "2022-06-20T12:01:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.3.8",
|
||||
"version": "v3.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "972d8604a92b7054828b539f2febb0211dd5945c"
|
||||
"reference": "e939eae92386b69b49cfa4599dd9bead6bf4a342"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/972d8604a92b7054828b539f2febb0211dd5945c",
|
||||
"reference": "972d8604a92b7054828b539f2febb0211dd5945c",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/e939eae92386b69b49cfa4599dd9bead6bf4a342",
|
||||
"reference": "e939eae92386b69b49cfa4599dd9bead6bf4a342",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1530,7 +1632,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1566,7 +1668,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.3.8"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.4.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1578,7 +1680,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-02-04T06:59:48+00:00"
|
||||
"time": "2022-05-17T05:48:52+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
@ -1589,5 +1691,5 @@
|
|||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.2.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
links:
|
||||
youtube: https://www.youtube.com/channel/UC0x-gNbsyyrC69HjT5Z44MQ
|
||||
twitter: https://twitter.com/_le_futuriste
|
||||
github: https://github.com/lefuturiste
|
||||
gitlab: https://gitlab.com/lefuturiste
|
||||
malt: https://www.malt.fr/profile/matthieubessat
|
||||
discord_guild: https://discord.com/invite/3W94m7ts3H
|
||||
soundcloud: https://soundcloud.com/lefuturiste
|
||||
stackoverflow: https://stackoverflow.com/users/7100565/lefuturiste
|
||||
osm: https://openstreetmap.org/user/lefuturiste
|
||||
osm_wiki: https://wiki.openstreetmap.org/wiki/User:Lefuturiste
|
||||
wikipedia_fr: https://fr.wikipedia.org/wiki/Utilisateur:Matthieu2743
|
||||
wikidata: https://www.wikidata.org/wiki/User:Matthieu2743
|
||||
mastodon: https://mstdn.io/users/lefuturiste
|
||||
|
||||
|
58
config/links.yaml
Normal file
|
@ -0,0 +1,58 @@
|
|||
links:
|
||||
- id: mastodon
|
||||
name: Mastodon
|
||||
url: https://mstdn.io/users/lefuturiste
|
||||
# - id: youtube
|
||||
# name: YouTube
|
||||
# url: https://www.youtube.com/channel/UC0x-gNbsyyrC69HjT5Z44MQ
|
||||
|
||||
# - id: twitter
|
||||
# name: Twitter
|
||||
# url: https://twitter.com/_le_futuriste
|
||||
- id: github
|
||||
name: GitHub
|
||||
url: https://github.com/lefuturiste
|
||||
- id: gitlab
|
||||
name: GitLab
|
||||
url: https://gitlab.com/lefuturiste
|
||||
thumbnail:
|
||||
src: gitlab.svg
|
||||
alt: Gitlab logo
|
||||
style: "transform: scale(1.5)"
|
||||
- id: malt
|
||||
name: Malt
|
||||
url: https://www.malt.fr/profile/matthieubessat
|
||||
thumbnail:
|
||||
src: malt.svg
|
||||
- id: discord
|
||||
name:
|
||||
fr: Mon serveur discord
|
||||
en: My discord server
|
||||
url: https://discord.com/invite/3W94m7ts3H
|
||||
thumbnail:
|
||||
src: discord.svg
|
||||
style: "transform: scale(0.75)"
|
||||
# - id: soundcloud
|
||||
# name: Sound Cloud
|
||||
# url: https://soundcloud.com/lefuturiste
|
||||
- id: stackoverflow
|
||||
name: StackOverflow
|
||||
url: https://stackoverflow.com/users/7100565/lefuturiste
|
||||
- id: osm
|
||||
name: OpenStreetMap
|
||||
url: https://openstreetmap.org/user/lefuturiste
|
||||
# - id: osm_wiki
|
||||
# name:
|
||||
# en: OpenStreetMap wiki
|
||||
# fr: Le wiki d'OpenStreetMap
|
||||
# url: https://wiki.openstreetmap.org/wiki/User:Lefuturiste
|
||||
- id: wikipedia_fr
|
||||
name: Wikipedia
|
||||
url: https://fr.wikipedia.org/wiki/Utilisateur:Matthieu2743
|
||||
thumbnail:
|
||||
src: wikipedia.svg
|
||||
alt: Wikipedia logo
|
||||
- id: wikidata
|
||||
name: Wikidata
|
||||
url: https://www.wikidata.org/wiki/User:Matthieu2743
|
||||
|
4
config/misc.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
email: bonjour@matthieubessat.fr
|
||||
updated_at: '2022-07-04'
|
||||
|
||||
|
|
@ -1,99 +1,214 @@
|
|||
pro_projects:
|
||||
- id: associations.espacecondorcet
|
||||
- id: forum_asso
|
||||
detailled_page: true
|
||||
date: 2020-07
|
||||
link: https://associations.espacecondorcet.org
|
||||
images:
|
||||
- id: public_list
|
||||
name:
|
||||
fr: Liste des associations
|
||||
en: f
|
||||
description:
|
||||
fr: Page regroupant toute les associations de la localité triées par catégories
|
||||
en: Public page
|
||||
- id: public_page
|
||||
name:
|
||||
fr: Page d'une association
|
||||
en: e
|
||||
description:
|
||||
fr: Page publique d'une association contenenant toute les informations de sa fiche
|
||||
en: e
|
||||
- id: manage_organizations
|
||||
name:
|
||||
fr: Gestion des associations
|
||||
en: e
|
||||
description:
|
||||
fr: L'administrateur peut ajouter, modifier, valider toute les associations depuis une unique interface
|
||||
en: e
|
||||
- id: changes_approval
|
||||
name:
|
||||
fr: Vérification par l'administrateur
|
||||
en: e
|
||||
description:
|
||||
fr: L'administrateur peut valider ou refuser les changements apportés par l'association
|
||||
en: e
|
||||
- id: edit_main
|
||||
name:
|
||||
fr: Panel associatif
|
||||
en: e
|
||||
description:
|
||||
fr: Les associations disposent d'un espace réservé pour remplir leur fiche
|
||||
en: e
|
||||
- id: edit_images
|
||||
name:
|
||||
fr: Images et vidéos
|
||||
en: e
|
||||
description:
|
||||
fr: Les associations peuvent ajouter des images ou des vidéos
|
||||
en: e
|
||||
technologies:
|
||||
- Node.js
|
||||
- TypeScript
|
||||
- Express.js
|
||||
- Vue.js
|
||||
- Vuetify
|
||||
- MongoDB
|
||||
locales:
|
||||
fr:
|
||||
name: Annuaire assocatif administré
|
||||
description: Création d'une application web de gestion de contenu
|
||||
background: |
|
||||
En Juin 2020, l'Espace condorcet voulais un moyen de partager les associations locales
|
||||
en:
|
||||
name: Administered association directory
|
||||
description: Created a web app of content management
|
||||
background: |
|
||||
In June of 2020, the Espace Condorcet wanted a way to have the public discover associations around them in around the town.
|
||||
- node
|
||||
- typescript
|
||||
- express
|
||||
- vue
|
||||
- vuetify
|
||||
- mongodb
|
||||
name:
|
||||
fr: Annuaire assocatif administré
|
||||
en: Administered association directory
|
||||
description:
|
||||
fr: |
|
||||
Application web de gestion de fiche associative avec interface administrative.
|
||||
en: |
|
||||
Web application of association management with administration interface.
|
||||
background:
|
||||
fr: |
|
||||
En Juin 2020, l'Espace condorcet cherchait un moyen numérique afin de substituer le forum associatif physique qui était compromis pour cause sanitaire, ils voulait un moyen simple pour que les associations puissent se décrire et en même temps que le personnel de l'espace condorcet puissent valider le contenu facilement sans d'étapes manuelle pour la publication.
|
||||
en: |
|
||||
In June of 2020, the Espace Condorcet wanted a way to have the public discover associations around them in around the town.
|
||||
solution:
|
||||
fr: |
|
||||
Afin de répondre aux besoins du client, j'ai développé pendant l'été le logiciel qui se compose en plusieurs parties : une partie accessible par tous qui permet de naviguer dans les associations basé sur un serveur Node.js et une interface d'administration et d'édition par les associations qui communique avec une API web en Node.js qui va ensuite mettre à jour la base de données MongoDB.
|
||||
en: |
|
||||
Foo bar
|
||||
action:
|
||||
fr: Site web externe
|
||||
en: External website
|
||||
thumbnail:
|
||||
src: condorcet.jpg
|
||||
alt:
|
||||
fr: Un dessin enfantin représentant le soleil éclairant un chemin
|
||||
en: A childish drawing representing the sun lighting up a footway.
|
||||
- id: tracklift
|
||||
detailled_page: false
|
||||
date: 2022-01
|
||||
link: https://tracklift.fr
|
||||
name: Tracklift
|
||||
# En 2021 Socobat Environnement avait le besoin d'une application web afin de modéliser la gestion des déchets sur des chantiers d'ascenseurs (collecte, retraitement, revalorisation) et de partager le résultat à des clients. J'ai démarré le développement à partir d'une base et j'ai mit en production le site web.
|
||||
description:
|
||||
fr: |
|
||||
Gestion de la récupération, le traitement et la revalorisation des déchets issues des chantiers d'ascenseurs.
|
||||
# De façon plus général, logiciel de gestion de l'activité d'une entreprise.
|
||||
en: |
|
||||
Management of the recovering, the processing and the revaluation of wastes from elevator's worksite
|
||||
thumbnail:
|
||||
src: logo_square.svg
|
||||
alt: A 'T' letter encapsulated into brackets
|
||||
technologies:
|
||||
- Vue
|
||||
- Vuetify
|
||||
- Symfony 5
|
||||
- Api Platform
|
||||
- PHP
|
||||
- MySQL
|
||||
locales:
|
||||
fr:
|
||||
name: Tracklift
|
||||
description: Site pour gérer l'activité de démontage d'ascenseur de l'entreprise Socobat
|
||||
background: |
|
||||
Sometimes none run start somebody learn card.
|
||||
Once remain foreign player task decision social. Student police lawyer pattern local.
|
||||
en:
|
||||
name: Tracklift
|
||||
description: Web site to manage business of the tracklift society
|
||||
background: |
|
||||
Sometimes none run start somebody learn card.
|
||||
Once remain foreign player task decision social. Student police lawyer pattern local.
|
||||
- vue
|
||||
- vuetify
|
||||
- symfony
|
||||
- api-platform
|
||||
- php
|
||||
- mysql
|
||||
side_projects:
|
||||
- id: werobot
|
||||
detailled_page: false
|
||||
date: 2018-11
|
||||
link: https://werobot.fr
|
||||
technologies:
|
||||
- Nuxt.js
|
||||
- Vue.js
|
||||
- PHP
|
||||
- Slim Framework
|
||||
locales:
|
||||
fr:
|
||||
name: WeRobot.fr
|
||||
description: Création d'un site vitrine accompagné d'un blog pour l'association robotique locale We Robot
|
||||
en:
|
||||
name: WeRobot.fr
|
||||
description: Creation of a presentation website along with a blog for the robotic club We Robot
|
||||
- nuxt
|
||||
- vue
|
||||
- php
|
||||
- slim
|
||||
- mariadb
|
||||
thumbnail:
|
||||
src: logo-300.png
|
||||
alt:
|
||||
fr: Une flèche rouge poussant vers le haut la lettre W bleu surmonté par la lettre R en blanc
|
||||
en: A red arrow pushing up a blue W letter which is supporting a white R letter
|
||||
name: WeRobot.fr
|
||||
description:
|
||||
en: A presentation website along with a blog for the robotic club We Robot.
|
||||
fr: Un site vitrine accompagné d'un blog pour l'association de robotique locale We Robot.
|
||||
- id: retrobox
|
||||
detailled_page: false
|
||||
name: RetroBox
|
||||
description:
|
||||
en: E-commerce website from scratch to sell the retrobox console and allow the customer to manage it remotely.
|
||||
fr: E-commerce de A à Z pour vendre des consoles RetroBox et permettre la gestion à distance de celle ci par le client.
|
||||
date: 2018-08
|
||||
link: https://retrobox.tech
|
||||
thumbnail:
|
||||
src: logo_alone_square.png
|
||||
alt:
|
||||
fr: Une console démontrant qu'il peut afficher plusieurs couleurs de façon verticale
|
||||
en: A console demonstrating that it can show many coulor in an vertical mannel
|
||||
technologies:
|
||||
- Nuxt.js
|
||||
- nuxt
|
||||
- vue
|
||||
- php
|
||||
- slim
|
||||
- mariadb
|
||||
- socket-io
|
||||
- stripe
|
||||
- paypal
|
||||
- electron
|
||||
- id: jobatator
|
||||
name: Jobatator
|
||||
date: 2020-06
|
||||
link: https://github.com/jobatator
|
||||
logo: logo.png
|
||||
description:
|
||||
fr: |
|
||||
Un serveur TCP développé comme alternative simplifié à RabbitMQ afin de dispatcher des tâches à des processus.
|
||||
en: |
|
||||
A simplified alternative to RabbitMQ to dispatch jobs to workers (in order to for example send an email).
|
||||
technologies:
|
||||
- Go
|
||||
- go
|
||||
action:
|
||||
fr: GitHub du projet
|
||||
en: GitHub page
|
||||
- id: keyvaluer
|
||||
detailled_page: false
|
||||
name: KeyValuer
|
||||
date: 2020-04
|
||||
link: https://github.com/lefuturiste/keyvaluer
|
||||
description:
|
||||
fr: |
|
||||
Une implementation d'un serveur supportant les commandes basiques de Redis formant une base clé-valeur.
|
||||
en: |
|
||||
An implementation of a redis compatible serveur to have a key-value database.
|
||||
technologies:
|
||||
- Go
|
||||
- go
|
||||
action:
|
||||
fr: GitHub du projet
|
||||
en: GitHub page
|
||||
- id: discord-monolog-handler
|
||||
detailled_page: false
|
||||
name: Discord Monolog handler
|
||||
date: 2017-08
|
||||
link: https://github.com/lefuturiste/monolog-discord-handler
|
||||
technologies:
|
||||
- PHP
|
||||
- php
|
||||
description:
|
||||
fr: |
|
||||
Un projet open-source pour permettre à la librairie monolog d'envoyer des logs via un webhook discord.
|
||||
en: |
|
||||
An open-source project to extend the monolog library in order to send logs via discord webhooks.
|
||||
action:
|
||||
fr: GitHub du projet
|
||||
en: GitHub page
|
||||
- id: langatator
|
||||
detailled_page: false
|
||||
name: Langatator
|
||||
date: 2022-05
|
||||
link: https://gitlab.com/lefuturiste/langatator
|
||||
description:
|
||||
fr: |
|
||||
Développement d'un langage de programmation impératif interprété afin de découvrir le fonctionnement d'un interpréteur.
|
||||
en: |
|
||||
Creation of an impérative interpreted langage, trying to enforce a grammar with a lexer, a parser and an evaluator.
|
||||
technologies:
|
||||
- C
|
||||
- id: quasator
|
||||
name: Quasator
|
||||
date: 2022-03
|
||||
link: https://gitlab.com/lefuturiste/quasator
|
||||
technologies:
|
||||
- Python
|
||||
- Latex
|
||||
- c
|
||||
action:
|
||||
fr: GitLab du projet
|
||||
en: GitLab page
|
||||
# - id: quasator
|
||||
# name: Quasator
|
||||
# date: 2022-03
|
||||
# link: https://gitlab.com/lefuturiste/quasator
|
||||
# technologies:
|
||||
# - python
|
||||
# - latex
|
||||
|
||||
|
|
|
@ -1,90 +1,212 @@
|
|||
# TODO: add git; vim; mariadb; latex; socket-io; docker; c (programming language); express.js; stripe and paypal integrations
|
||||
|
||||
technologies:
|
||||
|
||||
# Front End
|
||||
- image: css3.svg
|
||||
- id: css
|
||||
image: css3.svg
|
||||
name: CSS 3
|
||||
height: stretch
|
||||
- image: html5.svg
|
||||
website: https://www.w3.org/TR/css/
|
||||
wikidata: Q11707176
|
||||
|
||||
- id: html
|
||||
image: html5.svg
|
||||
name: HTML 5
|
||||
website: https://html.spec.whatwg.org/multipage/
|
||||
wikidata: Q2053
|
||||
|
||||
# JavaScript
|
||||
- image: jquery.svg
|
||||
- id: jquery
|
||||
image: jquery.svg
|
||||
name: JQuery
|
||||
- image: node.svg
|
||||
name: Node.js
|
||||
- image: yarn.svg
|
||||
name: Yarn
|
||||
- image: webpack.svg
|
||||
name: Webpack
|
||||
- image: sass.svg
|
||||
name: SASS
|
||||
- image: typescript.svg
|
||||
name: Type Script
|
||||
website: https://jquery.com/
|
||||
wikidata: Q230036
|
||||
|
||||
- image: electron.png
|
||||
- id: node
|
||||
image: node.svg
|
||||
name: Node.js
|
||||
website: https://nodejs.org/
|
||||
wikidata: Q756100
|
||||
|
||||
- id: yarn
|
||||
image: yarn.svg
|
||||
name: Yarn
|
||||
website: https://yarnpkg.com
|
||||
wikidata: Q28975591
|
||||
|
||||
- id: webpack
|
||||
image: webpack.svg
|
||||
name: Webpack
|
||||
website: https://webpack.js.org/
|
||||
wikidata:
|
||||
|
||||
- id: sass
|
||||
image: sass.svg
|
||||
name: SASS
|
||||
website: https://sass-lang.com/
|
||||
wikidata: Q1572865
|
||||
|
||||
- id: typescript
|
||||
image: typescript.svg
|
||||
name: Type Script
|
||||
website: https://www.typescriptlang.org/
|
||||
wikidata: Q978185
|
||||
|
||||
- id: electron
|
||||
image: electron.svg
|
||||
name: Electron
|
||||
website: https://www.electronjs.org/
|
||||
wikidata: Q21614124
|
||||
|
||||
# Python
|
||||
- image: python.svg
|
||||
- id: python
|
||||
image: python.svg
|
||||
name: Python
|
||||
- image: gunicorn.svg
|
||||
name: Gunicorn
|
||||
website: https://python.org
|
||||
wikidata: Q28865
|
||||
|
||||
- id: gunicorn
|
||||
image: gunicorn.svg
|
||||
name: Gunicorn
|
||||
website: https://gunicorn.org/
|
||||
wikidata: Q5618801
|
||||
|
||||
# Dev Ops
|
||||
- image: docker.svg
|
||||
- id: docker
|
||||
image: docker.svg
|
||||
name: Docker
|
||||
- image: caddy.png
|
||||
website: https://docker.com
|
||||
wikidata: Q15206305
|
||||
|
||||
- id: caddy
|
||||
image: caddy.png
|
||||
name: Caddy
|
||||
- image: nginx.svg
|
||||
website: https://caddyserver.com/
|
||||
wikidata: Q24008327
|
||||
|
||||
- id: nginx
|
||||
image: nginx.svg
|
||||
name: Nginx
|
||||
height: stretch
|
||||
- image: varnish.svg
|
||||
name: Varnish
|
||||
- image: cloudflare.svg
|
||||
name: Cloudflare
|
||||
website: https://nginx.org/en/
|
||||
wikidata: Q306144
|
||||
|
||||
- id: varnish
|
||||
image: varnish.svg
|
||||
name: Varnish
|
||||
website: https://varnish-cache.org
|
||||
wikidata: Q1602447
|
||||
|
||||
- id: cloudflare
|
||||
image: cloudflare.svg
|
||||
name: Cloudflare
|
||||
website: https://cloudflare.com
|
||||
wikidata: Q4778915
|
||||
|
||||
# Databases
|
||||
- image: mysql.svg
|
||||
name: MySQL
|
||||
description: Database management system
|
||||
- image: mongodb.svg
|
||||
- id: mariadb
|
||||
alias: mysql
|
||||
image: mariadb.svg
|
||||
name: MariaDB
|
||||
description: Database management system similar to MySQL
|
||||
website: https://mariadb.org/
|
||||
wikidata: Q787177
|
||||
|
||||
- id: mongodb
|
||||
image: mongodb.svg
|
||||
height: stretch
|
||||
name: MongoDB
|
||||
- image: elasticsearch.png
|
||||
description: NoSQL database
|
||||
website: https://mongodb.com
|
||||
wikidata: Q1165204
|
||||
|
||||
- id: elasticsearch
|
||||
image: elasticsearch.png
|
||||
name: Elastic Search
|
||||
- image: redis.svg
|
||||
website: https://www.elastic.co/elasticsearch/
|
||||
wikidata: Q3050461
|
||||
|
||||
- id: redis
|
||||
image: redis.svg
|
||||
name: Redis
|
||||
website: https://redis.io
|
||||
wikidata: Q2136322
|
||||
|
||||
# PHP ecosystem
|
||||
|
||||
- image: php.svg
|
||||
- id: php
|
||||
image: php.svg
|
||||
name: PHP
|
||||
description: Language to make cool website
|
||||
website: https://php.net
|
||||
color: blue
|
||||
- image: api-platform.svg
|
||||
wikidata: Q59
|
||||
|
||||
- id: api-platform
|
||||
image: api-platform.svg
|
||||
name: API Platform
|
||||
- image: composer.svg
|
||||
website: https://api-platform.com/
|
||||
wikidata: Q108740058
|
||||
|
||||
- id: composer
|
||||
image: composer.svg
|
||||
name: Composer
|
||||
height: stretch
|
||||
- image: slim.svg
|
||||
website: https://getcomposer.org/
|
||||
wikidata: Q15252222
|
||||
|
||||
- id: slim
|
||||
image: slim.svg
|
||||
name: Slim Framework
|
||||
- image: laravel.svg
|
||||
website: https://www.slimframework.com/
|
||||
wikidata: null
|
||||
|
||||
- id: laravel
|
||||
image: laravel.svg
|
||||
name: Laravel
|
||||
- image: symfony.svg
|
||||
website: https://laravel.com/
|
||||
wikidata: Q13634357
|
||||
|
||||
- id: symfony
|
||||
image: symfony.svg
|
||||
name: Symfony
|
||||
- image: phpunit.svg
|
||||
website: https://symfony.com
|
||||
wikidata: Q1322933
|
||||
|
||||
- id: phpunit
|
||||
image: phpunit.svg
|
||||
name: PHP Unit
|
||||
website: https://phpunit.de/
|
||||
wikidata: Q1663673
|
||||
|
||||
- image: vue.svg
|
||||
- id: vue
|
||||
image: vue.svg
|
||||
name: Vue.js
|
||||
- image: nuxt.svg
|
||||
website: https://vuejs.org/
|
||||
wikidata: Q24589705
|
||||
|
||||
- id: nuxt
|
||||
image: nuxt.svg
|
||||
name: Nuxt.js
|
||||
- image: vuetify.svg
|
||||
website: https://nuxtjs.org/
|
||||
wikidata: Q55641291
|
||||
|
||||
- id: vuetify
|
||||
image: vuetify.svg
|
||||
name: Vuetify
|
||||
website: https://vuetifyjs.com/
|
||||
wikidata: Q112943923
|
||||
|
||||
- image: golang.svg
|
||||
- id: go
|
||||
image: go.svg
|
||||
name: Go
|
||||
website: https://go.dev
|
||||
wikidata: Q37227
|
||||
|
||||
- id: express
|
||||
image: express.svg
|
||||
name: Express.js
|
||||
wikidata: Q16878131
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"build": "cross-env NODE_ENV=production webpack"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.27.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"node-sass-glob-importer": "^5.3.2",
|
||||
"sass": "^1.42.1",
|
||||
|
@ -14,5 +15,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^7.0.3"
|
||||
}
|
||||
},
|
||||
"_comment": "YES"
|
||||
}
|
||||
|
|
2
public/dist/app.min.css
vendored
2
public/dist/app.min.js
vendored
230
public/dist/app.min.js.LICENSE.txt
vendored
|
@ -1,3 +1,233 @@
|
|||
/*! ../adapters/xhr */
|
||||
|
||||
/*! ../cancel/CanceledError */
|
||||
|
||||
/*! ../cancel/isCancel */
|
||||
|
||||
/*! ../core/AxiosError */
|
||||
|
||||
/*! ../core/buildFullPath */
|
||||
|
||||
/*! ../defaults */
|
||||
|
||||
/*! ../defaults/transitional */
|
||||
|
||||
/*! ../env/data */
|
||||
|
||||
/*! ../helpers/buildURL */
|
||||
|
||||
/*! ../helpers/combineURLs */
|
||||
|
||||
/*! ../helpers/isAbsoluteURL */
|
||||
|
||||
/*! ../helpers/normalizeHeaderName */
|
||||
|
||||
/*! ../helpers/parseProtocol */
|
||||
|
||||
/*! ../helpers/toFormData */
|
||||
|
||||
/*! ../helpers/validator */
|
||||
|
||||
/*! ../lib/core/AxiosError */
|
||||
|
||||
/*! ../utils */
|
||||
|
||||
/*! ./../core/settle */
|
||||
|
||||
/*! ./../helpers/buildURL */
|
||||
|
||||
/*! ./../helpers/cookies */
|
||||
|
||||
/*! ./../helpers/isURLSameOrigin */
|
||||
|
||||
/*! ./../helpers/parseHeaders */
|
||||
|
||||
/*! ./../utils */
|
||||
|
||||
/*! ./AxiosError */
|
||||
|
||||
/*! ./CanceledError */
|
||||
|
||||
/*! ./InterceptorManager */
|
||||
|
||||
/*! ./buildFullPath */
|
||||
|
||||
/*! ./cancel/CancelToken */
|
||||
|
||||
/*! ./cancel/CanceledError */
|
||||
|
||||
/*! ./cancel/isCancel */
|
||||
|
||||
/*! ./contact */
|
||||
|
||||
/*! ./core/Axios */
|
||||
|
||||
/*! ./core/mergeConfig */
|
||||
|
||||
/*! ./defaults */
|
||||
|
||||
/*! ./dispatchRequest */
|
||||
|
||||
/*! ./env/FormData */
|
||||
|
||||
/*! ./env/data */
|
||||
|
||||
/*! ./helpers/bind */
|
||||
|
||||
/*! ./helpers/isAxiosError */
|
||||
|
||||
/*! ./helpers/spread */
|
||||
|
||||
/*! ./helpers/toFormData */
|
||||
|
||||
/*! ./lib/axios */
|
||||
|
||||
/*! ./mergeConfig */
|
||||
|
||||
/*! ./transformData */
|
||||
|
||||
/*! ./transitional */
|
||||
|
||||
/*! ./utils */
|
||||
|
||||
/*! axios */
|
||||
|
||||
/*!********************************!*\
|
||||
!*** ./assets/scripts/main.js ***!
|
||||
\********************************/
|
||||
|
||||
/*!*********************************!*\
|
||||
!*** ./assets/styles/main.scss ***!
|
||||
\*********************************/
|
||||
|
||||
/*!***********************************!*\
|
||||
!*** ./assets/scripts/contact.js ***!
|
||||
\***********************************/
|
||||
|
||||
/*!*************************************!*\
|
||||
!*** ./node_modules/axios/index.js ***!
|
||||
\*************************************/
|
||||
|
||||
/*!*****************************************!*\
|
||||
!*** ./node_modules/axios/lib/axios.js ***!
|
||||
\*****************************************/
|
||||
|
||||
/*!*****************************************!*\
|
||||
!*** ./node_modules/axios/lib/utils.js ***!
|
||||
\*****************************************/
|
||||
|
||||
/*!********************************************!*\
|
||||
!*** ./node_modules/axios/lib/env/data.js ***!
|
||||
\********************************************/
|
||||
|
||||
/*!**********************************************!*\
|
||||
!*** ./node_modules/axios/lib/core/Axios.js ***!
|
||||
\**********************************************/
|
||||
|
||||
/*!***********************************************!*\
|
||||
!*** ./node_modules/axios/lib/core/settle.js ***!
|
||||
\***********************************************/
|
||||
|
||||
/*!************************************************!*\
|
||||
!*** ./node_modules/axios/lib/adapters/xhr.js ***!
|
||||
\************************************************/
|
||||
|
||||
/*!************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/bind.js ***!
|
||||
\************************************************/
|
||||
|
||||
/*!************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/null.js ***!
|
||||
\************************************************/
|
||||
|
||||
/*!**************************************************!*\
|
||||
!*** ./node_modules/axios/lib/defaults/index.js ***!
|
||||
\**************************************************/
|
||||
|
||||
/*!**************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/spread.js ***!
|
||||
\**************************************************/
|
||||
|
||||
/*!***************************************************!*\
|
||||
!*** ./node_modules/axios/lib/cancel/isCancel.js ***!
|
||||
\***************************************************/
|
||||
|
||||
/*!***************************************************!*\
|
||||
!*** ./node_modules/axios/lib/core/AxiosError.js ***!
|
||||
\***************************************************/
|
||||
|
||||
/*!***************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/cookies.js ***!
|
||||
\***************************************************/
|
||||
|
||||
/*!****************************************************!*\
|
||||
!*** ./node_modules/axios/lib/core/mergeConfig.js ***!
|
||||
\****************************************************/
|
||||
|
||||
/*!****************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/buildURL.js ***!
|
||||
\****************************************************/
|
||||
|
||||
/*!*****************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/validator.js ***!
|
||||
\*****************************************************/
|
||||
|
||||
/*!******************************************************!*\
|
||||
!*** ./node_modules/axios/lib/cancel/CancelToken.js ***!
|
||||
\******************************************************/
|
||||
|
||||
/*!******************************************************!*\
|
||||
!*** ./node_modules/axios/lib/core/buildFullPath.js ***!
|
||||
\******************************************************/
|
||||
|
||||
/*!******************************************************!*\
|
||||
!*** ./node_modules/axios/lib/core/transformData.js ***!
|
||||
\******************************************************/
|
||||
|
||||
/*!******************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/toFormData.js ***!
|
||||
\******************************************************/
|
||||
|
||||
/*!*******************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/combineURLs.js ***!
|
||||
\*******************************************************/
|
||||
|
||||
/*!********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/cancel/CanceledError.js ***!
|
||||
\********************************************************/
|
||||
|
||||
/*!********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/core/dispatchRequest.js ***!
|
||||
\********************************************************/
|
||||
|
||||
/*!********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/isAxiosError.js ***!
|
||||
\********************************************************/
|
||||
|
||||
/*!********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/parseHeaders.js ***!
|
||||
\********************************************************/
|
||||
|
||||
/*!*********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/defaults/transitional.js ***!
|
||||
\*********************************************************/
|
||||
|
||||
/*!*********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/isAbsoluteURL.js ***!
|
||||
\*********************************************************/
|
||||
|
||||
/*!*********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/parseProtocol.js ***!
|
||||
\*********************************************************/
|
||||
|
||||
/*!***********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/core/InterceptorManager.js ***!
|
||||
\***********************************************************/
|
||||
|
||||
/*!***********************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/isURLSameOrigin.js ***!
|
||||
\***********************************************************/
|
||||
|
||||
/*!***************************************************************!*\
|
||||
!*** ./node_modules/axios/lib/helpers/normalizeHeaderName.js ***!
|
||||
\***************************************************************/
|
||||
|
|
1
public/imgs/icons/checkmark-circle-outline.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Checkmark Circle</title><path d="M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M352 176L217.6 336 160 272"/></svg>
|
After Width: | Height: | Size: 413 B |
1
public/imgs/icons/close-circle-outline.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Close Circle</title><path d="M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M320 320L192 192M192 320l128-128"/></svg>
|
After Width: | Height: | Size: 415 B |
10
public/imgs/logos/discord.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg width="71" height="55" viewBox="0 0 71 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z" fill="#5865F2"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="71" height="55" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
5
public/imgs/logos/github.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
||||
<!--
|
||||
Font Awesome Free 5.4.1 by @fontawesome - https://fontawesome.com
|
||||
License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
-->
|
After Width: | Height: | Size: 1.5 KiB |
1
public/imgs/logos/gitlab.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 380 380"><defs><style>.cls-1{fill:#e24329;}.cls-2{fill:#fc6d26;}.cls-3{fill:#fca326;}</style></defs><g id="LOGO"><path class="cls-1" d="M282.83,170.73l-.27-.69-26.14-68.22a6.81,6.81,0,0,0-2.69-3.24,7,7,0,0,0-8,.43,7,7,0,0,0-2.32,3.52l-17.65,54H154.29l-17.65-54A6.86,6.86,0,0,0,134.32,99a7,7,0,0,0-8-.43,6.87,6.87,0,0,0-2.69,3.24L97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82,19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91,40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/><path class="cls-2" d="M282.83,170.73l-.27-.69a88.3,88.3,0,0,0-35.15,15.8L190,229.25c19.55,14.79,36.57,27.64,36.57,27.64l40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/><path class="cls-3" d="M153.43,256.89l19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91S209.55,244,190,229.25C170.45,244,153.43,256.89,153.43,256.89Z"/><path class="cls-2" d="M132.58,185.84A88.19,88.19,0,0,0,97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82s17-12.85,36.57-27.64Z"/></g></svg>
|
After Width: | Height: | Size: 1 KiB |
63
public/imgs/logos/malt.svg
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 23.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Calque_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 300 300"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="malt.svg"
|
||||
width="300"
|
||||
height="300"
|
||||
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs93" /><sodipodi:namedview
|
||||
id="namedview91"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#cccccc"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.1676101"
|
||||
inkscape:cx="9.8491785"
|
||||
inkscape:cy="181.13924"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1038"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g88" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style60">
|
||||
.st0{fill:#FC5656;}
|
||||
</style>
|
||||
<g
|
||||
id="g88">
|
||||
<path
|
||||
id="path62"
|
||||
class="st0"
|
||||
d="m 149.6871,31.865607 c -19.42382,0 -26.71707,11.742455 -29.2386,24.70815 1.81227,1.585943 3.62361,3.176246 5.45481,5.028855 l 23.7961,24.055249 24.22008,-24.486367 c 1.64443,-1.666322 3.31412,-3.211652 4.99388,-4.670004 -2.53668,-12.937626 -9.83906,-24.635883 -29.22627,-24.635883 z m 63.48832,25.109363 c -10.95884,0.07618 -21.1727,7.44531 -28.60759,14.961948 L 128.383,128.74201 72.190779,185.55206 c -11.895837,12.02536 -24.345929,30.29761 -5.617495,49.2294 18.728432,18.93819 36.800696,6.34738 48.694016,-5.67926 l 56.18976,-56.80756 56.18976,-56.80508 C 239.5439,103.46165 251.05877,84.242808 233.26677,66.255169 226.59382,59.508841 219.7507,56.929261 213.17542,56.97497 Z M 87.061493,56.99241 c -6.547339,-0.07353 -13.477371,2.593482 -20.500535,9.693864 -13.733343,13.884342 -10.68349,27.396611 -3.399088,38.366796 2.218636,-0.16715 67.6811,-0.35637 67.68111,-0.35635 l 8.19578,-8.285905 -23.78133,-24.04527 C 107.82175,64.849698 97.97372,57.114957 87.061493,56.992412 Z m -17.123629,62.92794 c -16.821513,0 -38.407995,5.35719 -38.407995,30.79608 0,18.98158 12.017709,26.77466 25.107421,29.51271 1.549767,-1.80792 59.17475,-60.30879 59.17475,-60.30879 z m 172.900096,1.23602 c -1.45259,1.70713 -59.19938,60.35615 -59.19938,60.35615 h 45.22341 c 16.82155,0 38.40801,-4.01878 38.40801,-30.79609 0,-19.63482 -11.60989,-27.01083 -24.43204,-29.56006 z m -6.69466,75.23838 c -2.3625,0.17226 -67.59481,0.34139 -67.59481,0.34139 l -8.21551,8.30831 24.22253,24.48637 c 11.89583,12.02792 30.90446,23.6694 48.69646,5.68176 13.2765,-13.42375 10.23126,-27.52357 2.89133,-38.81783 z m -86.44142,19.4276 -23.78377,24.04278 c -1.80596,1.82712 -3.60364,3.49566 -5.39319,5.06374 2.72723,13.189 10.44751,25.26886 29.16711,25.26886 18.76884,0 26.47726,-12.14493 29.18683,-25.37601 -1.66462,-1.44815 -3.33233,-2.86807 -4.97171,-4.52546 z"
|
||||
style="stroke-width:1.26894" />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
4
public/imgs/logos/mastodon.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="61.076954mm" height="65.47831mm" viewBox="0 0 216.4144 232.00976">
|
||||
<path fill="#2b90d9" d="M211.80734 139.0875c-3.18125 16.36625-28.4925 34.2775-57.5625 37.74875-15.15875 1.80875-30.08375 3.47125-45.99875 2.74125-26.0275-1.1925-46.565-6.2125-46.565-6.2125 0 2.53375.15625 4.94625.46875 7.2025 3.38375 25.68625 25.47 27.225 46.39125 27.9425 21.11625.7225 39.91875-5.20625 39.91875-5.20625l.8675 19.09s-14.77 7.93125-41.08125 9.39c-14.50875.7975-32.52375-.365-53.50625-5.91875C9.23234 213.82 1.40609 165.31125.20859 116.09125c-.365-14.61375-.14-28.39375-.14-39.91875 0-50.33 32.97625-65.0825 32.97625-65.0825C49.67234 3.45375 78.20359.2425 107.86484 0h.72875c29.66125.2425 58.21125 3.45375 74.8375 11.09 0 0 32.975 14.7525 32.975 65.0825 0 0 .41375 37.13375-4.59875 62.915"/>
|
||||
<path fill="#fff" d="M177.50984 80.077v60.94125h-24.14375v-59.15c0-12.46875-5.24625-18.7975-15.74-18.7975-11.6025 0-17.4175 7.5075-17.4175 22.3525v32.37625H96.20734V85.42325c0-14.845-5.81625-22.3525-17.41875-22.3525-10.49375 0-15.74 6.32875-15.74 18.7975v59.15H38.90484V80.077c0-12.455 3.17125-22.3525 9.54125-29.675 6.56875-7.3225 15.17125-11.07625 25.85-11.07625 12.355 0 21.71125 4.74875 27.8975 14.2475l6.01375 10.08125 6.015-10.08125c6.185-9.49875 15.54125-14.2475 27.8975-14.2475 10.6775 0 19.28 3.75375 25.85 11.07625 6.36875 7.3225 9.54 17.22 9.54 29.675"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
758
public/imgs/logos/openstreetmap.svg
Normal file
After Width: | Height: | Size: 150 KiB |
758
public/imgs/logos/osm.svg
Normal file
After Width: | Height: | Size: 150 KiB |
49
public/imgs/logos/stackoverflow.svg
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="svg-icon iconLogoGlyphMd native"
|
||||
width="32"
|
||||
height="37"
|
||||
viewBox="0 0 32 37"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="stackoverflow_i.svg"
|
||||
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
id="namedview8"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#cccccc"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8.2702703"
|
||||
inkscape:cx="15.900327"
|
||||
inkscape:cy="22.308824"
|
||||
inkscape:window-width="958"
|
||||
inkscape:window-height="1038"
|
||||
inkscape:window-x="960"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6" />
|
||||
<path
|
||||
d="M26 33v-9h4v13H0V24h4v9h22Z"
|
||||
fill="#BCBBBB"
|
||||
style="--darkreader-inline-fill: #bdb8af;"
|
||||
data-darkreader-inline-fill=""
|
||||
id="path2" />
|
||||
<path
|
||||
d="m21.5 0-2.7 2 9.9 13.3 2.7-2L21.5 0ZM26 18.4 13.3 7.8l2.1-2.5 12.7 10.6-2.1 2.5ZM9.1 15.2l15 7 1.4-3-15-7-1.4 3Zm14 10.79.68-2.95-16.1-3.35L7 23l16.1 2.99ZM23 30H7v-3h16v3Z"
|
||||
fill="#F48024"
|
||||
style="--darkreader-inline-fill: #f58a35;"
|
||||
data-darkreader-inline-fill=""
|
||||
id="path4" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
50
public/imgs/logos/wikidata.svg
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.2"
|
||||
width="1000"
|
||||
height="1000"
|
||||
id="svg1012"
|
||||
sodipodi:docname="wikidata.svg"
|
||||
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1016" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1014"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#cccccc"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.57452725"
|
||||
inkscape:cx="813.71249"
|
||||
inkscape:cy="585.69893"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1038"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1012" />
|
||||
<path
|
||||
d="m 95.59227,669.96435 h 29.16277 V 170.00006 H 95.59227 Z m 60.27256,0 h 89.42926 V 170.00006 h -89.42926 z m 118.5981,-499.96429 v 499.94645 h 89.42926 V 170.00006 Z"
|
||||
style="fill:#990000"
|
||||
id="path1004" />
|
||||
<path
|
||||
d="m 815.1509,669.99996 h 29.16883 V 170 H 815.1509 Z M 875.42952,170 v 499.99996 h 29.16277 V 170 Z M 394.02544,670.00003 h 29.16277 V 170.00006 H 394.02544 Z M 454.30406,170.00006 V 669.98219 H 483.4729 V 170.00006 Z"
|
||||
style="fill:#339966"
|
||||
id="path1006" />
|
||||
<path
|
||||
d="m 513.59401,670.00003 h 89.4414 V 170.00006 h -89.4414 z m 118.5981,0 h 31.10372 V 170.00006 h -31.10372 z m 60.27256,-499.99997 v 499.98213 h 89.42926 V 170.00006 Z"
|
||||
style="fill:#006699"
|
||||
id="path1008" />
|
||||
<path
|
||||
d="m 860.16016,725.03567 46.01562,103.68359 h -27.75781 l -8.53516,-20.48438 h -46.38672 l -7.71875,20.48438 h -27.38672 l 41.78516,-103.68359 h 29.98438 m 2.07812,65.08984 -16.69922,-40.30078 -15.21484,40.30078 h 31.91406 m -60.26562,-65.08984 v 19 h -37.55469 v 84.68359 h -25.82813 v -84.68359 h -37.55468 v -19 h 100.9375 m -133.59375,0 46.01562,103.68359 h -27.75781 l -8.53516,-20.48438 h -46.38672 l -7.71875,20.48438 h -27.38672 l 41.78516,-103.68359 h 29.98438 m 2.07812,65.08984 -16.69922,-40.30078 -15.21484,40.30078 h 31.91406 M 493.89062,725.03567 h 45.71875 c 17.66399,10e-5 31.6171,4.84905 41.85938,14.54687 10.29156,9.64852 15.43739,22.142 15.4375,37.48047 -1.1e-4,16.08076 -5.22016,28.72268 -15.66016,37.92578 -10.39071,9.15365 -25.23444,13.73047 -44.53125,13.73047 H 493.89062 V 725.03567 m 25.82813,19 v 65.68359 h 16.84766 c 10.93483,2e-5 19.2968,-2.99347 25.08593,-8.98047 5.78898,-6.03642 8.68351,-13.97782 8.6836,-23.82422 -9e-5,-10.19264 -2.9441,-18.20826 -8.83203,-24.04687 -5.83862,-5.88794 -14.25007,-8.83195 -25.23438,-8.83203 h -16.55078 m -49.72656,-19 V 828.71926 H 444.16406 V 725.03567 h 25.82813 m -48.91016,0 -33.76953,48.6875 45.79297,54.99609 h -32.35938 l -41.04297,-48.61328 v 48.61328 H 333.875 V 725.03567 h 25.82812 v 46.68359 l 32.95313,-46.68359 h 28.42578 m -111.10547,0 V 828.71926 H 284.14844 V 725.03567 h 25.82812 m -127.21094,37.40625 -32.0625,67.61328 H 139.57031 L 94,725.03567 h 27.38672 l 24.41797,57.29687 26.64453,-57.29687 h 20.78125 l 26.64453,57.29687 24.26953,-57.29687 h 27.38672 L 226.10937,830.0552 h -11.13281 l -32.21094,-67.61328"
|
||||
style="font-family:'Gill Sans MT';fill:#484848;fill-opacity:1;stroke:none"
|
||||
id="path1010" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
3
public/imgs/logos/wikipedia.svg
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
public/imgs/projects/forum_asso/ask_approval.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
public/imgs/projects/forum_asso/changes_approval.png
Normal file
After Width: | Height: | Size: 505 KiB |
BIN
public/imgs/projects/forum_asso/condorcet.jpg
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
public/imgs/projects/forum_asso/edit_contact.png
Normal file
After Width: | Height: | Size: 107 KiB |
BIN
public/imgs/projects/forum_asso/edit_description.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
public/imgs/projects/forum_asso/edit_images.png
Normal file
After Width: | Height: | Size: 789 KiB |
BIN
public/imgs/projects/forum_asso/edit_main.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
public/imgs/projects/forum_asso/edit_prices.png
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
public/imgs/projects/forum_asso/edit_schedule.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
public/imgs/projects/forum_asso/manage_organizations.png
Normal file
After Width: | Height: | Size: 95 KiB |
BIN
public/imgs/projects/forum_asso/manage_tags.png
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
public/imgs/projects/forum_asso/public_list.png
Normal file
After Width: | Height: | Size: 333 KiB |
BIN
public/imgs/projects/forum_asso/public_page.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
public/imgs/projects/jobatator/logo.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
public/imgs/projects/retrobox/logo_alone_square.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
47
public/imgs/projects/tracklift/logo_square.svg
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg140"
|
||||
sodipodi:docname="tracklift_logo_square.svg"
|
||||
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
|
||||
width="100"
|
||||
height="100"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs144" />
|
||||
<sodipodi:namedview
|
||||
id="namedview142"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#cccccc"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4.9820652"
|
||||
inkscape:cx="31.412676"
|
||||
inkscape:cy="62.724992"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1080"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg140" />
|
||||
<path
|
||||
d="M 90.52215,9.8348385 H 10.182101 V 47.545474 h 9.699831 V 19.528112 H 80.828878 V 80.475058 H 36.153252 v 9.693273 H 90.52215 Z M 35.399039,31.287271 h 9.706389 v 9.70639 h -9.706389 z"
|
||||
fill="#3aaa35"
|
||||
id="path134"
|
||||
sodipodi:nodetypes="cccccccccccccccc"
|
||||
style="stroke-width:0.655837" />
|
||||
<path
|
||||
d="m 46.502362,68.689665 h 9.693272 V 40.993661 h 11.083649 v -9.70639 H 46.502362 Z M 19.881932,52.772496 h -9.699831 v 37.395835 h 20.77692 v -9.70639 H 19.875374 V 52.772496 Z"
|
||||
fill="#c8d400"
|
||||
id="path136"
|
||||
sodipodi:nodetypes="ccccccccccccccc"
|
||||
style="stroke-width:0.655837" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/imgs/projects/werobot/logo-300.png
Normal file
After Width: | Height: | Size: 31 KiB |
1
public/imgs/technos/electron.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><circle fill="#2B2E3A" cx="128" cy="128" r="128"/><g fill="#9FEAF9" fill-rule="nonzero"><path d="M100.502 71.69c-26.005-4.736-46.567.221-54.762 14.415-6.115 10.592-4.367 24.635 4.24 39.646a2.667 2.667 0 1 0 4.626-2.653c-7.752-13.522-9.261-25.641-4.247-34.326 6.808-11.791 25.148-16.213 49.187-11.835a2.667 2.667 0 0 0 .956-5.247zm-36.999 72.307c10.515 11.555 24.176 22.394 39.756 31.388 37.723 21.78 77.883 27.601 97.675 14.106a2.667 2.667 0 1 0-3.005-4.406c-17.714 12.078-55.862 6.548-92.003-14.318-15.114-8.726-28.343-19.222-38.478-30.36a2.667 2.667 0 1 0-3.945 3.59z"/><path d="M194.62 140.753c17.028-20.116 22.973-40.348 14.795-54.512-6.017-10.423-18.738-15.926-35.645-16.146a2.667 2.667 0 0 0-.069 5.333c15.205.198 26.165 4.939 31.096 13.48 6.792 11.765 1.49 29.807-14.248 48.399a2.667 2.667 0 1 0 4.071 3.446zm-43.761-68.175c-15.396 3.299-31.784 9.749-47.522 18.835-38.942 22.483-64.345 55.636-60.817 79.675a2.667 2.667 0 1 0 5.277-.775c-3.133-21.344 20.947-52.769 58.207-74.281 15.267-8.815 31.135-15.06 45.972-18.239a2.667 2.667 0 1 0-1.117-5.215z"/><path d="M87.77 187.753c8.904 24.86 23.469 40.167 39.847 40.167 11.945 0 22.996-8.143 31.614-22.478a2.667 2.667 0 1 0-4.571-2.748c-7.745 12.883-17.258 19.892-27.043 19.892-13.605 0-26.596-13.652-34.825-36.63a2.667 2.667 0 1 0-5.021 1.797zm81.322-4.863c4.61-14.728 7.085-31.718 7.085-49.423 0-44.179-15.463-82.263-37.487-92.042a2.667 2.667 0 0 0-2.164 4.874c19.643 8.723 34.317 44.866 34.317 87.168 0 17.177-2.397 33.63-6.84 47.83a2.667 2.667 0 1 0 5.09 1.593zm50.224-2.612c0-7.049-5.714-12.763-12.763-12.763-7.049 0-12.763 5.714-12.763 12.763 0 7.049 5.714 12.763 12.763 12.763 7.049 0 12.763-5.714 12.763-12.763zm-5.333 0a7.43 7.43 0 1 1-14.86 0 7.43 7.43 0 0 1 14.86 0zM48.497 193.041c7.05 0 12.764-5.714 12.764-12.763 0-7.049-5.715-12.763-12.764-12.763-7.048 0-12.763 5.714-12.763 12.763 0 7.049 5.715 12.763 12.763 12.763zm0-5.333a7.43 7.43 0 1 1 0-14.86 7.43 7.43 0 0 1 0 14.86z"/><path d="M127.617 54.444c7.049 0 12.763-5.714 12.763-12.763 0-7.049-5.714-12.763-12.763-12.763-7.049 0-12.763 5.714-12.763 12.763 0 7.049 5.714 12.763 12.763 12.763zm0-5.333a7.43 7.43 0 1 1 0-14.86 7.43 7.43 0 0 1 0 14.86zm1.949 93.382c-4.985 1.077-9.896-2.091-10.975-7.076a9.236 9.236 0 0 1 7.076-10.976c4.985-1.077 9.896 2.091 10.976 7.076 1.077 4.985-2.091 9.897-7.077 10.976z"/></g></g></svg>
|
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use App\App;
|
||||
use App\Middlewares\TwigLocalizationMiddleware;
|
||||
use App\Util\ContainerBuilder;
|
||||
use App\Utils\DotEnv;
|
||||
use Slim\Factory\AppFactory;
|
||||
|
@ -8,6 +9,11 @@ use Slim\Views\Twig;
|
|||
use Slim\Views\TwigMiddleware;
|
||||
use DI\Container;
|
||||
|
||||
use App\Middlewares\LocalizationMiddleware;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
use function App\addRoutes;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
@ -25,8 +31,12 @@ $app = AppFactory::createFromContainer($container);
|
|||
$app->addRoutingMiddleware();
|
||||
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
|
||||
|
||||
$twig = Twig::create('../templates', ['cache' => false]);
|
||||
$app->add(TwigMiddleware::create($app, $twig));
|
||||
// we place the definition BEFORE the localization middleware to get the locale attribute
|
||||
$app->add(new TwigLocalizationMiddleware($container));
|
||||
$app->add($container->get(LocalizationMiddleware::class));
|
||||
|
||||
$app->add(TwigMiddleware::create($app, $container->get(Twig::class)));
|
||||
|
||||
|
||||
require '../src/routes.php';
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Middlewares\LocalizationMiddleware;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\Views\Twig;
|
||||
|
@ -10,14 +11,69 @@ class HomeController extends AbstractController
|
|||
{
|
||||
public function getHome(ServerRequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
return Twig::fromRequest($request)->render(
|
||||
// $locale = $request->getAttributes()['locale'];
|
||||
// dd($locale);
|
||||
return $this->container->get(Twig::class)->render(
|
||||
$response, 'home/home.html.twig',
|
||||
[
|
||||
'links' => array_map(function ($link) {
|
||||
if (!isset($link['thumbnail'])) {
|
||||
$link['thumbnail'] = ['src' => $link['id'] . '.svg', 'alt' => $link['id'] . " logo"];
|
||||
}
|
||||
|
||||
return $link;
|
||||
}, $this->container->get('links')),
|
||||
'technologies' => $this->container->get('technologies'),
|
||||
'pro_projects' => $this->container->get('pro_projects'),
|
||||
'side_projects' => $this->container->get('side_projects'),
|
||||
'locale' => 'fr'
|
||||
'email' => $this->container->get('misc')['email']
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getAbout(ServerRequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
return $this->container->get(Twig::class)->render(
|
||||
$response, 'about.html.twig',
|
||||
[
|
||||
'email' => $this->container->get('misc')['email']
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getProject(ServerRequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
$id = $request->getAttribute('id');
|
||||
$projects = [...$this->container->get('pro_projects'), ...$this->container->get('side_projects')];
|
||||
$projectsCandidates = array_values(array_filter($projects, fn ($p) => $p['id'] == $id));
|
||||
if (count($projectsCandidates) === 0) {
|
||||
// TODO: add proper response body
|
||||
return $response
|
||||
->withStatus(404);
|
||||
}
|
||||
$project = $projectsCandidates[0];
|
||||
|
||||
$technologies = $this->container->get('technologies');
|
||||
|
||||
$projectTechnologies = array_map(fn ($tId) => array_values(array_filter($technologies, fn ($t) => $t['id'] == $tId))[0], $project['technologies']);
|
||||
|
||||
return $this->container->get(Twig::class)->render(
|
||||
$response, 'project.html.twig',
|
||||
[
|
||||
'project' => [...$project, 'technologies' => $projectTechnologies]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function switchToLocale(ServerRequestInterface $request, ResponseInterface $response)
|
||||
{
|
||||
$newLocale = substr($request->getUri()->getPath(), 1);
|
||||
$redir = $request->hasHeader('Referer') ? $request->getHeader('Referer') : '/';
|
||||
return $this->container->get(LocalizationMiddleware::class)->withSetCookieLocale(
|
||||
$response
|
||||
->withStatus(302)
|
||||
->withAddedHeader('Location', $redir),
|
||||
$newLocale
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
332
src/Middlewares/LocalizationMiddleware.php
Normal file
|
@ -0,0 +1,332 @@
|
|||
<?php
|
||||
namespace App\Middlewares;
|
||||
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
/**
|
||||
* Middleware to assist primarily with language-based content negotiation
|
||||
* and various other localization tasks
|
||||
* Credits: https://raw.githubusercontent.com/tboronczyk/localization-middleware/master/src/LocalizationMiddleware.php
|
||||
*/
|
||||
class LocalizationMiddleware implements MiddlewareInterface
|
||||
{
|
||||
const FROM_URI_PATH = 1;
|
||||
const FROM_URI_PARAM = 2;
|
||||
const FROM_COOKIE = 3;
|
||||
const FROM_HEADER = 4;
|
||||
const FROM_CALLBACK = 5;
|
||||
|
||||
protected $availableLocales;
|
||||
protected $defaultLocale;
|
||||
|
||||
protected $searchOrder;
|
||||
|
||||
protected $reqAttrName;
|
||||
protected $uriParamName;
|
||||
protected $cookieName;
|
||||
protected $cookiePath;
|
||||
protected $cookieExpire;
|
||||
|
||||
protected $localeCallback;
|
||||
protected $searchCallback;
|
||||
|
||||
/**
|
||||
* @param array $locales a list of available locales
|
||||
* @param string $default the default locale
|
||||
*/
|
||||
public function __construct(array $locales, string $default)
|
||||
{
|
||||
$this->setAvailableLocales($locales);
|
||||
$this->setDefaultLocale($default);
|
||||
$this->setSearchOrder([
|
||||
self::FROM_URI_PATH,
|
||||
self::FROM_URI_PARAM,
|
||||
self::FROM_COOKIE,
|
||||
self::FROM_HEADER
|
||||
]);
|
||||
$this->setReqAttrName('locale');
|
||||
$this->setUriParamName('locale');
|
||||
$this->setCookieName('locale');
|
||||
$this->setCookiePath('/');
|
||||
$this->setCookieExpire(3600 * 24 * 30); // 30 days
|
||||
$this->setLocaleCallback(function () { /* empty function */ });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $locales a list of available locales
|
||||
*/
|
||||
public function setAvailableLocales(array $locales)
|
||||
{
|
||||
$this->availableLocales = [];
|
||||
foreach ($locales as $locale) {
|
||||
$this->availableLocales[] = $this->parseLocale($locale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $default the default locale
|
||||
*/
|
||||
public function setDefaultLocale(string $default)
|
||||
{
|
||||
$this->defaultLocale = $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $order the order in which the search will be performed to
|
||||
* resolve the locale
|
||||
*/
|
||||
public function setSearchOrder(array $order)
|
||||
{
|
||||
$this->searchOrder = $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $func callable to invoke when searching the locale
|
||||
*/
|
||||
public function setSearchCallback(callable $func)
|
||||
{
|
||||
$this->searchCallback = $func;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name the name for the attribute attached to the request
|
||||
*/
|
||||
public function setReqAttrName(string $name)
|
||||
{
|
||||
$this->reqAttrName = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name the name for the locale URI parameter
|
||||
*/
|
||||
public function setUriParamName(string $name)
|
||||
{
|
||||
$this->uriParamName = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name the name for the locale cookie
|
||||
*/
|
||||
public function setCookieName(string $name)
|
||||
{
|
||||
$this->cookieName = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path the locale cookie's path
|
||||
*/
|
||||
public function setCookiePath(string $path)
|
||||
{
|
||||
$this->cookiePath = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $secs cookie expiration in seconds from now
|
||||
*/
|
||||
public function setCookieExpire(int $secs)
|
||||
{
|
||||
$this->cookieExpire = gmdate('D, d M Y H:i:s T', time() + $secs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $func callable to invoke when locale is determined
|
||||
*/
|
||||
public function setLocaleCallback(callable $func)
|
||||
{
|
||||
$this->localeCallback = $func;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the locale to the request and response objects
|
||||
*/
|
||||
public function process(Request $req, RequestHandler $handler): Response
|
||||
{
|
||||
$locale = $this->getLocale($req);
|
||||
|
||||
$this->localeCallback->__invoke($locale);
|
||||
|
||||
$req = $req->withAttribute($this->reqAttrName, $locale);
|
||||
|
||||
$resp = $handler->handle($req);
|
||||
|
||||
if (in_array(self::FROM_COOKIE, $this->searchOrder) && $req->getAttribute('doSetLocaleCookie') === true) {
|
||||
$resp = $this->withSetCookieLocale($resp, $locale);
|
||||
}
|
||||
return $resp;
|
||||
}
|
||||
|
||||
public function withSetCookieLocale(Response $res, string $locale): Response
|
||||
{
|
||||
return $res->withAddedHeader('Set-Cookie', "{$this->cookieName}=$locale; Path={$this->cookiePath}; Expires={$this->cookieExpire}");
|
||||
}
|
||||
|
||||
protected function getLocale(Request $req)
|
||||
{
|
||||
foreach ($this->searchOrder as $order) {
|
||||
switch ($order) {
|
||||
case self::FROM_URI_PATH:
|
||||
$locale = $this->localeFromPath($req);
|
||||
break;
|
||||
|
||||
case self::FROM_URI_PARAM:
|
||||
$locale = $this->localeFromParam($req);
|
||||
break;
|
||||
|
||||
case self::FROM_COOKIE:
|
||||
$locale = $this->localeFromCookie($req);
|
||||
break;
|
||||
|
||||
case self::FROM_HEADER:
|
||||
$locale = $this->localeFromHeader($req);
|
||||
break;
|
||||
|
||||
case self::FROM_CALLBACK:
|
||||
$locale = $this->localeFromCallback($req);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \DomainException('Unknown search option provided');
|
||||
}
|
||||
if (!empty($locale)) {
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
return $this->defaultLocale;
|
||||
}
|
||||
|
||||
protected function localeFromPath(Request $req): string
|
||||
{
|
||||
list(, $value) = explode('/', $req->getUri()->getPath());
|
||||
return $this->filterLocale($value);
|
||||
}
|
||||
|
||||
protected function localeFromParam(Request $req): string
|
||||
{
|
||||
$params = $req->getQueryParams();
|
||||
$value = $params[$this->uriParamName] ?? '';
|
||||
return $this->filterLocale($value);
|
||||
}
|
||||
|
||||
protected function localeFromCookie(Request $req): string
|
||||
{
|
||||
$cookies = $req->getCookieParams();
|
||||
$value = $cookies[$this->cookieName] ?? '';
|
||||
return $this->filterLocale($value);
|
||||
}
|
||||
|
||||
protected function localeFromCallback(Request $req): string
|
||||
{
|
||||
if (!is_callable($this->searchCallback)) {
|
||||
throw new \LogicException('Search callback not set');
|
||||
}
|
||||
$locale = $this->searchCallback->__invoke($req);
|
||||
return $this->filterLocale($locale);
|
||||
}
|
||||
|
||||
protected function localeFromHeader(Request $req): string
|
||||
{
|
||||
$header = $req->getHeaderLine('Accept-Language');
|
||||
if (empty($header)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$values = $this->parse($header);
|
||||
usort($values, [$this, 'sort']);
|
||||
foreach ($values as $value) {
|
||||
$value = $this->filterLocale($value['locale']);
|
||||
if (!empty($value)) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
// search language if a full locale is not found
|
||||
foreach ($values as $value) {
|
||||
$value = $this->filterLocale($value['language']);
|
||||
if (!empty($value)) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function filterLocale(string $locale): string
|
||||
{
|
||||
// return the locale if it is available
|
||||
foreach ($this->availableLocales as $avail) {
|
||||
if ($locale == $avail['locale']) {
|
||||
return $avail['locale'];
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function parse(string $header): array
|
||||
{
|
||||
// the value may contain multiple languages separated by commas,
|
||||
// possibly as locales (ex: en_US) with quality (ex: en_US;q=0.5)
|
||||
$values = [];
|
||||
foreach (explode(',', $header) as $lang) {
|
||||
@list($locale, $quality) = explode(';', $lang, 2);
|
||||
$val = $this->parseLocale(str_replace('*', $this->defaultLocale, $locale));
|
||||
$val['quality'] = $this->parseQuality($quality ?? '');
|
||||
$values[] = $val;
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
protected function parseLocale(string $locale): array
|
||||
{
|
||||
// Locale format: language[_territory[.encoding[@modifier]]]
|
||||
//
|
||||
// Language and territory should be separated by an underscore
|
||||
// although sometimes a hyphen is used. The language code should
|
||||
// be lowercase. Territory should be uppercase. Take this into
|
||||
// account but normalize the returned string as lowercase,
|
||||
// underscore, uppercase.
|
||||
//
|
||||
// The possible codeset and modifier is discarded since the header
|
||||
// *should* really list languages (not locales) in the first place
|
||||
// and the chances of needing to present content at that level of
|
||||
// granularity are pretty slim.
|
||||
$lang = '([[:alpha:]]{2})';
|
||||
$terr = '([[:alpha:]]{2})';
|
||||
$code = '([-\\w]+)';
|
||||
$mod = '([-\\w]+)';
|
||||
$regex = "/$lang(?:[-_]$terr(?:\\.$code(?:@$mod)?)?)?/";
|
||||
preg_match_all($regex, $locale, $m);
|
||||
|
||||
$locale = $language = strtolower($m[1][0]);
|
||||
if (!empty($m[2][0])) {
|
||||
$locale .= '_' . strtoupper($m[2][0]);
|
||||
}
|
||||
|
||||
return [
|
||||
'locale' => $locale,
|
||||
'language' => $language
|
||||
];
|
||||
}
|
||||
|
||||
protected function parseQuality(string $quality): float
|
||||
{
|
||||
// If no quality is given then return 1 as this is the default quality
|
||||
// defined in RFC 2616 HTTP/1.1 section 14.4 Accept-Language
|
||||
// See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
||||
@list(, $value) = explode('=', $quality, 2);
|
||||
return (float)($value ?: 1.0);
|
||||
}
|
||||
|
||||
protected function sort(array $a, array $b): int
|
||||
{
|
||||
// Sort order is determined first by quality (higher values are
|
||||
// placed first) then by order of their apperance in the header.
|
||||
if ($a['quality'] < $b['quality']) {
|
||||
return 1;
|
||||
}
|
||||
if ($a['quality'] == $b['quality']) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
32
src/Middlewares/TwigLocalizationMiddleware.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Middlewares;
|
||||
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Slim\Http\Factory\DecoratedResponseFactory;
|
||||
use Slim\Http\Response;
|
||||
use Slim\Psr7\Factory\ResponseFactory;
|
||||
use Slim\Psr7\Factory\StreamFactory;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Slim\Views\Twig;
|
||||
|
||||
class TwigLocalizationMiddleware {
|
||||
|
||||
public function __construct(
|
||||
private ContainerInterface $container
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
$this->container->get(Twig::class)->getEnvironment()->addGlobal('locale', $request->getAttribute('locale'));
|
||||
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ class ContainerBuilder
|
|||
{
|
||||
private static array $definitions = [
|
||||
'app',
|
||||
'container'
|
||||
];
|
||||
|
||||
public static function getContainerBuilder(\DI\ContainerBuilder $containerBuilder = null): \DI\ContainerBuilder
|
||||
|
|
|
@ -4,14 +4,22 @@ use App\App;
|
|||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
function getYAML($name) {
|
||||
$path = App::getBasePath() . '/config/' . $name;
|
||||
$path = App::getBasePath() . '/' . $name;
|
||||
return Yaml::parseFile($path);
|
||||
}
|
||||
|
||||
$misc = getYAML('config/misc.yaml');
|
||||
|
||||
return [
|
||||
'basePath' => App::getBasePath(),
|
||||
'foo' => 'barz',
|
||||
'technologies' => getYAML('technologies.yaml')['technologies'],
|
||||
'pro_projects' => getYAML('projects.yaml')['pro_projects'],
|
||||
'side_projects' => getYAML('projects.yaml')['side_projects']
|
||||
'misc' => $misc,
|
||||
'last_update' => new DateTime($misc['updated_at']),
|
||||
'links' => getYAML('config/links.yaml')['links'],
|
||||
'technologies' => getYAML('config/technologies.yaml')['technologies'],
|
||||
'pro_projects' => getYAML('config/projects.yaml')['pro_projects'],
|
||||
'side_projects' => getYAML('config/projects.yaml')['side_projects'],
|
||||
'locales' => [
|
||||
'fr' => new \Adbar\Dot(getYAML('assets/locales/fr.yaml')),
|
||||
'en' => new \Adbar\Dot(getYAML('assets/locales/en.yaml'))
|
||||
],
|
||||
];
|
||||
|
|
47
src/config/container.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Slim\Views\Twig;
|
||||
use App\Middlewares\LocalizationMiddleware;
|
||||
|
||||
return [
|
||||
Twig::class => function(ContainerInterface $container) {
|
||||
$twig = Twig::create('../templates', ['cache' => false]);
|
||||
|
||||
$twig->getEnvironment()->addFunction(new \Twig\TwigFunction('getDynLocalizedStr', function (\Twig\Environment $env, $inp) {
|
||||
$locale = $env->getGlobals()['locale'];
|
||||
if (is_array($inp)) {
|
||||
return $inp[$locale];
|
||||
}
|
||||
if (is_string($inp)) {
|
||||
return $inp;
|
||||
}
|
||||
|
||||
return 'invalid';
|
||||
}, ['needs_environment' => true]));
|
||||
|
||||
$twig->getEnvironment()->addFunction(new \Twig\TwigFunction('getLocalizedStr', function (\Twig\Environment $env, $inp) use ($container) {
|
||||
$locale = $env->getGlobals()['locale'];
|
||||
|
||||
if (!$container->get('locales')[$locale]->has($inp)) {
|
||||
return $inp;
|
||||
}
|
||||
return $container->get('locales')[$locale]->get($inp);
|
||||
}, ['needs_environment' => true]));
|
||||
|
||||
$twig->getEnvironment()->addFunction(new \Twig\TwigFunction('getLocale', function (\Twig\Environment $env) {
|
||||
return $env->getGlobals()['locale'];
|
||||
}, ['needs_environment' => true]));
|
||||
|
||||
$twig->getEnvironment()->addGlobal('lastUpdate', $container->get('last_update'));
|
||||
|
||||
|
||||
return $twig;
|
||||
},
|
||||
|
||||
LocalizationMiddleware::class => function () {
|
||||
$availableLocales = ['en', 'fr'];
|
||||
$defaultLocale = 'en';
|
||||
return new LocalizationMiddleware($availableLocales, $defaultLocale);
|
||||
}
|
||||
];
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Slim\Routing\RouteCollectorProxy;
|
||||
|
||||
function addRoutes(\Slim\App $app): void
|
||||
|
@ -9,5 +11,14 @@ function addRoutes(\Slim\App $app): void
|
|||
$container = $app->getContainer();
|
||||
|
||||
$app->get('/', [Controller\HomeController::class, 'getHome']);
|
||||
$app->get('/project/{id}', [Controller\HomeController::class, 'getProject']);
|
||||
$app->get('/about', [Controller\HomeController::class, 'getAbout']);
|
||||
$app->get('/ping', [Controller\PingController::class, 'getPing']);
|
||||
|
||||
$addDoNotSetLocaleCookieMiddleware = function (ServerRequestInterface $req, RequestHandlerInterface $handler) {
|
||||
return $handler->handle($req->withAttribute('doSetLocaleCookie', false));
|
||||
};
|
||||
|
||||
$app->get('/en', [Controller\HomeController::class, 'switchToLocale'])->add($addDoNotSetLocaleCookieMiddleware);
|
||||
$app->get('/fr', [Controller\HomeController::class, 'switchToLocale'])->add($addDoNotSetLocaleCookieMiddleware);
|
||||
}
|
||||
|
|
21
templates/about.html.twig
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% extends 'layout.html.twig' %}
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="about-header">
|
||||
<a href="/">{{ getLocalizedStr('go-back-to-main') }}</a>
|
||||
</div>
|
||||
{% if getLocale() == 'fr' %}
|
||||
<h1>A propos de ce site</h1>
|
||||
|
||||
<h2></h2>
|
||||
<p>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if getLocale() == 'en' %}
|
||||
<h1>About this website</h1>
|
||||
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<section id="contact">
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2 class="title-text">{{ getLocalizedStr('contact.title') }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="means-of-contact">
|
||||
<p>
|
||||
{{ getLocalizedStr('contact.use-email') }} <a href="mailto:{{ email }}">{{ email }}</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{{ getLocalizedStr('contact.use-form') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="contact-form-container">
|
||||
<form id="contact-form">
|
||||
<noscript>{{ getLocalizedStr('contact.no-script') }}</noscript>
|
||||
<div class="alert alert-success hidden" id="contact-alert-success">
|
||||
<div class="alert-content">
|
||||
<div class="alert-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-circle-check" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<circle cx="12" cy="12" r="9"></circle>
|
||||
<path d="M9 12l2 2l4 -4"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="alert-text">
|
||||
Thanks, your message has been sent!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-error hidden" id="contact-alert-error">
|
||||
<div class="alert-content">
|
||||
<div class="alert-icon">
|
||||
<!-- <img src="/imgs/error.svg" alt="Error icon" /> -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-alert-circle" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<circle cx="12" cy="12" r="9"></circle>
|
||||
<line x1="12" y1="8" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="alert-text">
|
||||
Sorry, there was an error while processing your message.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-form-first-group">
|
||||
<div class="contact-form-input">
|
||||
<label for="contact-form-name">{{ getLocalizedStr('contact.form.name') }}</label>
|
||||
<input id="contact-form-name" type="text" name="name" minlength="2" maxlength="100" />
|
||||
</div>
|
||||
<div class="contact-form-input">
|
||||
<label for="contact-form-email">{{ getLocalizedStr('contact.form.email') }}</label>
|
||||
<input id="contact-form-email" type="email" name="email" required="required" maxlength="100" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-form-subject contact-form-input">
|
||||
<label for="contact-form-subject">{{ getLocalizedStr('contact.form.subject') }}</label>
|
||||
<input id="contact-form-subject" type="text" name="subject" required="required" maxlength="100" />
|
||||
</div>
|
||||
<div class="contact-form-message contact-form-input">
|
||||
<label for="contact-form-message">{{ getLocalizedStr('contact.form.message') }}</label>
|
||||
<textarea id="contact-form-message" type="text" name="message" minlength="10" maxlength="8000"></textarea>
|
||||
</div>
|
||||
<div class="contact-form-container">
|
||||
<button type="submit" class="btn contact-form-submit" id="contact-form-submit">
|
||||
{{ getLocalizedStr('contact.form.submit') }}
|
||||
</button>
|
||||
<button class="btn contact-form-submit loading-button" id="contact-form-loading">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-refresh" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4"></path>
|
||||
<path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
|
@ -3,6 +3,7 @@
|
|||
{% include('home/profile.html.twig') %}
|
||||
{% include('home/technologies.html.twig') %}
|
||||
{% include('home/projects.html.twig') %}
|
||||
{# {% include('home/side_projects.html.twig') %} #}
|
||||
{% include('home/links.html.twig') %}
|
||||
{% include('home/contact.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
|
|
26
templates/home/links.html.twig
Normal file
|
@ -0,0 +1,26 @@
|
|||
<section id="links">
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2 class="title-text">{{ getLocalizedStr('links.title') }}</h2>
|
||||
</div>
|
||||
<div class="links-container">
|
||||
<div class="links">
|
||||
{% for link in links %}
|
||||
<a class="link-card" href="{{ link.url }}" data-id="{{ link.id }}">
|
||||
<div class="link-card-logo">
|
||||
<img
|
||||
src="imgs/logos/{{ link.thumbnail.src }}"
|
||||
alt="{{ getDynLocalizedStr(link.thumbnail.alt) }}"
|
||||
style="{{ link.thumbnail.style }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="link-card-title">
|
||||
{{ getDynLocalizedStr(link.name) }}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2 class="title-text">Professional projects</h2>
|
||||
</div>
|
||||
<div class="projects">
|
||||
<!-- Box thing -->
|
||||
<div class="project-card">
|
||||
<h3 class="project-title">
|
||||
Annuaire associatif administré
|
||||
</h3>
|
||||
<p class="project-description">
|
||||
Light add loss traditional on. Against capital political black network option.
|
||||
Need education ready. Too knowledge once practice customer.
|
||||
Environmental loss level southern protect guy.
|
||||
</p>
|
||||
</div>
|
||||
<div class="project-card">
|
||||
<h3 class="project-title">
|
||||
Tracklift
|
||||
</h3>
|
||||
<p class="">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
|
@ -50,8 +50,8 @@
|
|||
<div class="profile-shadow"></div>
|
||||
</div>
|
||||
<div class="profile-content">
|
||||
<span class="title-1">Hi! I'm Matthieu</span>
|
||||
<span class="title-2">I like to program stuff</span>
|
||||
<span class="title-1">{{ getLocalizedStr('profile.intro.main') }}</span>
|
||||
<span class="title-2">{{ getLocalizedStr('profile.intro.secondary') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
|
||||
<section>
|
||||
<section id="pro-projects">
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2 class="title-text">Highlighted professional projects</h2>
|
||||
<h2 class="title-text">
|
||||
{{ getLocalizedStr('projects.pro.title') }}
|
||||
</h2>
|
||||
</div>
|
||||
{% include 'home/projects_list.html.twig' with {'projects': pro_projects} %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section id="side-projects">
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2 class="title-text">Highlighted side projects</h2>
|
||||
<h2 class="title-text">
|
||||
{{ getLocalizedStr('projects.side.title') }}
|
||||
</h2>
|
||||
</div>
|
||||
{% include 'home/projects_list.html.twig' with {'projects': side_projects} %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
@ -1,21 +1,43 @@
|
|||
<div class="projects">
|
||||
{% for project in projects %}
|
||||
<div class="project-card" data-id="{{ project.id }}">
|
||||
<h3 class="project-title">
|
||||
<a href="{{ project.link }}">
|
||||
{% if project.locales[locale].name is not defined %}
|
||||
{{ project.name }}
|
||||
{% else %}
|
||||
{{ project.locales[locale].name }}
|
||||
{% endif %}
|
||||
<div class="project-top">
|
||||
<div class="project-left">
|
||||
<h3 class="project-title">
|
||||
{% if project.detailled_page %}
|
||||
<a href="/project/{{ project.id }}">
|
||||
{{ getDynLocalizedStr(project.name) }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ getDynLocalizedStr(project.name) }}
|
||||
{% endif %}
|
||||
</h3>
|
||||
{% if project.description is defined %}
|
||||
<p class="project-description">
|
||||
{{ getDynLocalizedStr(project.description) }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="project-right">
|
||||
{% if project.thumbnail is defined %}
|
||||
<img
|
||||
class="project-img"
|
||||
src="imgs/projects/{{ project.id }}/{{ project.thumbnail.src }}"
|
||||
alt="{{ getDynLocalizedStr(project.thumbnail.alt) }}"
|
||||
/>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-bottom">
|
||||
<a href="{{ project.link}}">
|
||||
{% if project.action is defined %}
|
||||
{{ getDynLocalizedStr(project.action) }}
|
||||
{% else %}
|
||||
{{ getLocalizedStr('external-website') }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</h3>
|
||||
{% if project.locales is defined %}
|
||||
<p class="project-description">
|
||||
{{ project.locales[locale].description }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2 class="title-text">Highlighted projects</h2>
|
||||
</div>
|
||||
<div class="projects">
|
||||
<!-- Box thing -->
|
||||
<div class="project-card">
|
||||
<h3 class="project-title">
|
||||
Annuaire associatif administré
|
||||
</h3>
|
||||
<p class="project-description">
|
||||
Light add loss traditional on. Against capital political black network option.
|
||||
Need education ready. Too knowledge once practice customer.
|
||||
Environmental loss level southern protect guy.
|
||||
</p>
|
||||
</div>
|
||||
<div class="project-card">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
|
@ -1,7 +1,9 @@
|
|||
<section>
|
||||
<section id="technologies">
|
||||
<div class="container">
|
||||
<div class="section-title">
|
||||
<h2 class="title-text">Some of the technologies that I'm currently working with</h2>
|
||||
<h2 class="title-text">
|
||||
{{ getLocalizedStr('technologies.title') }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="tech-mosaic">
|
||||
{% for tech in technologies %}
|
||||
|
|
|
@ -1,14 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="{{ getLocale() }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Matthieu Bessat - Web Developer</title>
|
||||
<link href="dist/app.min.css" rel="stylesheet">
|
||||
<title>{% block title %}{% endblock %}{{ getLocalizedStr('page.title') }}</title>
|
||||
<link href="/dist/app.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
{% block content %}{% endblock %}
|
||||
<script src="dist/app.min.js"></script>
|
||||
|
||||
<div class="footer-buffer"></div>
|
||||
<footer class="footer">
|
||||
<div class="footer-container container">
|
||||
<div class="footer-left">
|
||||
<div>
|
||||
<a href="/about">{{ getLocalizedStr('about-website') }}</a>
|
||||
</div>
|
||||
<div>
|
||||
{{ getLocalizedStr('last-update') }} <span>{{ lastUpdate | date("Y-m-d") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-right">
|
||||
<div class="locale-switch-short">
|
||||
<a href="/fr">FR</a>
|
||||
<a href="/en">EN</a>
|
||||
</div>
|
||||
<div class="locale-switch-large">
|
||||
<div class="l">{{ getLocalizedStr('locales.choose') }}</div>
|
||||
<div class="r">
|
||||
<a href="/fr">Français</a>
|
||||
<a href="/en">English</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/dist/app.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
40
templates/project.html.twig
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
{% extends 'layout.html.twig' %}
|
||||
{% block title %}
|
||||
{{ getDynLocalizedStr(project.name) }}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="about-header">
|
||||
<a href="/">{{ getLocalizedStr('go-back-to-main') }}</a>
|
||||
</div>
|
||||
<div>
|
||||
<h1>{{ getLocalizedStr('projects.project') }} {{ getDynLocalizedStr(project.name) }}</h1>
|
||||
|
||||
{% if project.background is defined %}
|
||||
<h2>{{ getLocalizedStr('projects.background') }}</h2>
|
||||
<p>
|
||||
{{ getDynLocalizedStr(project.background) }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if project.solution is defined %}
|
||||
<h2>{{ getLocalizedStr('projects.solution') }}</h2>
|
||||
<p>
|
||||
{{ getDynLocalizedStr(project.solution) }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<h2>{{ getLocalizedStr('projects.technologies') }}</h2>
|
||||
<p>
|
||||
<div class="chips">
|
||||
{% for tech in project.technologies %}
|
||||
<div class="project-technology chip">
|
||||
{{ tech.name }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
33
wikidata.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
Q11707176 Cascading Style Sheets Level 3 style sheet language
|
||||
Q2053 HTML5 fifth and current version of the hypertext markup language for structuring and presenting content for the World Wide Web
|
||||
Q230036 jQuery JavaScript library
|
||||
Q756100 Node.js JavaScript runtime environment
|
||||
Q49007 yarn long continuous length of interlocked fibers
|
||||
Q22909730 webpack open-source JavaScript module bundler
|
||||
Q1572865 Sass Syntactically Awesome StyleSheets stylesheet language
|
||||
no result
|
||||
Q2225 electron subatomic particle with negative electric charge
|
||||
Q28865 Python general-purpose programming language
|
||||
Q5618801 Gunicorn web server
|
||||
Q1537445 stevedore occupation of loading and unloading ships
|
||||
Q411840 cadmium chloride chemical compound
|
||||
Q306144 nginx open source web server and a reverse proxy server
|
||||
Q81683 varnish transparent, hard, protective finish or film used in painting
|
||||
Q4778915 Cloudflare Web infrastructure and website security company
|
||||
Q787177 MariaDB Database management system, relational, open source, community developed fork of MySQL
|
||||
Q1165204 MongoDB cross-platform document-oriented database
|
||||
Q105097049 Curator tool to tend Elasticsearch indices
|
||||
Q2136322 Redis NoSQL database management software
|
||||
Q17193 Philippine peso official currency of the Philippines
|
||||
Q108740058 API Platform
|
||||
Q36834 composer musician who is an author of music in any form; person who creates music, either by musical notation or oral tradition
|
||||
no result
|
||||
Q13634357 Laravel open source web application framework, written in PHP
|
||||
Q1322933 Symfony PHP web application framework for MVC applications
|
||||
no result
|
||||
Q24589705 Vue.js JavaScript framework
|
||||
Q55641291 Nuxt.js JavaScript framework
|
||||
no result
|
||||
Q11413 go board game for two players that originated in China more than 2,500 years ago
|
||||
Q16878131 Express.js JavaScript framework
|
||||
|
51
yarn.lock
|
@ -251,11 +251,24 @@ assign-symbols@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
|
||||
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||
|
||||
atob@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
||||
axios@^0.27.2:
|
||||
version "0.27.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
|
||||
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.9"
|
||||
form-data "^4.0.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
|
@ -456,6 +469,13 @@ colorette@^1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
|
||||
integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==
|
||||
|
||||
combined-stream@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.20.0:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
|
@ -554,6 +574,11 @@ define-property@^2.0.2:
|
|||
is-descriptor "^1.0.2"
|
||||
isobject "^3.0.1"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||
|
||||
detect-file@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
|
||||
|
@ -756,11 +781,25 @@ findup-sync@^3.0.0:
|
|||
micromatch "^3.0.4"
|
||||
resolve-dir "^1.0.1"
|
||||
|
||||
follow-redirects@^1.14.9:
|
||||
version "1.15.1"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
|
||||
integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
|
||||
|
||||
for-in@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
||||
integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fragment-cache@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
|
||||
|
@ -1224,6 +1263,18 @@ mime-db@1.49.0:
|
|||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed"
|
||||
integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==
|
||||
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@^2.1.12:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mime-types@^2.1.27:
|
||||
version "2.1.32"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5"
|
||||
|
|