diff --git a/.gitignore b/.gitignore index b24d52f..58a674e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -dst/ +.idea/ .vscode/ -node_modules/ -package-lock.json +public diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 2bda374..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,48 +0,0 @@ -image: docker:latest -services: - - docker:dind - -stages: - - release - - deploy - -# Disable the Gradle daemon for Continuous Integration servers as correctness -# is usually a priority over speed in CI environments. Using a fresh -# runtime for each build is more reliable since the runtime is completely -# isolated from any previous builds. -variables: - # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled - DOCKER_HOST: tcp://docker:2376 - DOCKER_TLS_CERTDIR: "/certs" - CONTAINER_BRANCH_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG - CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest - -release: - stage: release - script: - - sed -i "s/__VERSION__/${CI_COMMIT_SHORT_SHA}/" src/_footer.html - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker build . -t $CONTAINER_BRANCH_IMAGE - - docker push $CONTAINER_BRANCH_IMAGE - except: - - master - -release-master: - stage: release - script: - - sed -i "s/__VERSION__/${CI_COMMIT_SHORT_SHA}/" src/_footer.html - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - docker build . -t $CONTAINER_RELEASE_IMAGE - - docker push $CONTAINER_RELEASE_IMAGE - only: - - master - -deploy: - stage: deploy - before_script: - - eval $(ssh-agent -s) - - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - - - mkdir -p ~/.ssh - - chmod 700 ~/.ssh - script: - - ssh -o StrictHostKeyChecking=no -p $SSH_PORT $SSH_DESTINATION "cd $PATH_TO_APPLICATION; $UPGRADE_COMMAND;" diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3a07023 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "themes/terminimal"] + path = themes/terminimal + url = https://github.com/pawroman/zola-theme-terminimal.git diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index e5ea9b8..0000000 --- a/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM alpine AS builder - -WORKDIR /root - -COPY . . - -RUN apk --no-cache add gcc git make musl-dev npm && \ - git clone -b VERSION_0_10_0 https://github.com/kristapsdz/lowdown.git && \ - cd lowdown && ./configure && make && make regress && make install && cd .. && \ - npm install && \ - chmod u+x ./ssg5 && mkdir -p dst && \ - ./ssg5 ./src/ ./dst/ "Le blog de Louis Vallat" "https://blog.louis-vallat.xyz" && rm dst/.files - -FROM nginx - -COPY --from=builder /root/dst /usr/share/nginx/html diff --git a/README.md b/README.md index 7d01cf3..658599e 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,9 @@ # Blog -> This is the source code from [this live website](https://blog.louis-vallat.xyz). +> This is the source code from [this live website](https://blog.louis-vallat.fr). -## Todo +Build it using [Zola](https://www.getzola.org): -- [ ] Add dark and light theme switch and colors - -## Sources - -- [SSG](https://www.romanzolotarev.com/ssg.html) -- [Wolfgang's video](https://youtu.be/N_ttw2Dihn8): `Fast & Minimal Blog Using POSIX Shell and Markdown` - -## Licenses - -The fonts provided in this repository are licensed under the [Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL). -The code, if not stated otherwise, is licensed under the [GPLv3 License](LICENSE). +```bash +zola build +``` diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..44cf0c2 --- /dev/null +++ b/config.toml @@ -0,0 +1,37 @@ +base_url = "https://blog.louis-vallat.fr" +title = "Le blog de Louis" +description = "Le blog très simple d'un développeur très compliqué." + +theme = "terminimal" +compile_sass = true +default_language = "fr" + +generate_feed = true +feed_filename = "atom.xml" + +taxonomies = [ + {name = "tags"}, + {name = "categories"} +] + +[markdown] +highlight_code = true + +[extra] +logo_text = "Le blog de Louis" +author = "Louis Vallat" +page_titles = "combined" + +enable_post_view_navigation = true +post_view_navigation_prompt = "En savoir plus" + +menu_items = [ + {name = "blog", url = "$BASE_URL"}, + {name = "tags", url = "$BASE_URL/tags"}, + {name = "archive", url = "$BASE_URL/archive"}, + {name = "portfolio", url = "https://louis-vallat.fr"}, + {name = "gitlab", url = "https://gitlab.com/lovallat", newtab = true}, +] + +favicon = "/favicon.png" +favicon_mimetype = "image/png" diff --git a/src/assets/images/git_flow/git_rebase.svg b/content/2021-05-10-git-flow/images/git_rebase.svg similarity index 100% rename from src/assets/images/git_flow/git_rebase.svg rename to content/2021-05-10-git-flow/images/git_rebase.svg diff --git a/src/git_flow.md b/content/2021-05-10-git-flow/index.md similarity index 96% rename from src/git_flow.md rename to content/2021-05-10-git-flow/index.md index 18c4e0e..0e99006 100644 --- a/src/git_flow.md +++ b/content/2021-05-10-git-flow/index.md @@ -1,12 +1,21 @@ -# Git Workflow ++++ +title = "Git Workflow" +description = "Git est un outil de versionnage très utile, voici comment je m'en sers." +date = 2021-05-10 + +[taxonomies] +tags = ["git", "workflow"] ++++ Git est un outil de versionnage très utile, voici comment je m'en sers. + + > À noter que ce guide est destiné aux personnes qui ont déjà utilisé git auparavant, > il ne s'agit pas ici d'un tutoriel pour débutants (bien que je sois ici assez > exhaustif dans mes explications). -[TL;DR](#TL;DR) +[TL;DR](#tldr) ## Les fondations @@ -21,7 +30,7 @@ par exemple, aka. vous avez committé et quelqu'un d'autre aussi en même temps) Nous allons donc demander à git de ne pull que lorsque l'historique est linéaire (fast-forward), et sinon de faire automatiquement un rebase : -```git +```bash git config pull.rebase true ``` @@ -33,7 +42,7 @@ git. Voici un alias, à placer dans votre `~/.gitconfig`, qui vous permet d'affi un graphique de vos branches et vos commits de manière plus visuelle que le `git log` de base de git (honteusement volés [ici](https://stackoverflow.com/a/9074343)) : -```git +```conf [alias] lg1 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all lg2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all @@ -43,13 +52,13 @@ de base de git (honteusement volés [ici](https://stackoverflow.com/a/9074343)) Si vous n'avez pas besoin d'autant de décorations, ou que vous ne pouvez pas définir d'alias, cette commande fait quelque chose d'assez similaire : -```git +```bash git log --all --decorate --oneline --graph ``` Pour avoir des messages de commits unifiés et cohérents avec de jolis alias : -```git +```conf fix = "!f() { git commit -sm \"fix: $1\"; }; f" feat = "!f() { git commit -sm \"feat: $1\"; }; f" misc = "!f() { git commit -sm \"misc: $1\"; }; f" @@ -85,19 +94,19 @@ stabilité par exemple, ou qui n'est pas prête pour la mise en production. Pour créer une branche fille à partir de la branche sur laquelle vous êtes : -```git +```bash git checkout -b nom_de_la_nouvelle_branche ``` Et pour basculer de branche en branche : -```git +```bash git checkout nom_de_la_branche ``` Si vous ne savez pas sur quelle branche vous vous trouvez, vous pouvez faire : -```git +```bash git branch ``` @@ -120,7 +129,7 @@ notre branche de travail, par exemple la résolution d'un bogue handicapant. Un `rebase` va faire changer votre commit de départ et l'échanger avec un autre. Prenons le schéma suivant : -![Schéma d'un rebase](assets/images/git_flow/git_rebase.svg) +![Schéma d'un rebase](images/git_rebase.svg) Nous avons ici la branche `new_feature` qui part d'un commit de master. Disons que vous êtes en train de développer une fonctionnalité importante, et qu'un bug @@ -129,7 +138,7 @@ de votre branche, et qu'il est disponible sur `master`. Pour le récupérer sur branche, vous n'avez qu'à `rebase` votre branche sur la dernière version de `master`. La commande pour faire ceci serait alors : -```git +```bash git rebase nom_de_branche_parente ``` @@ -173,7 +182,7 @@ forcément toutes en tête. Pour fusionner une branche dans celle sur laquelle vous vous trouvez : -```git +```bash git merge nom_de_la_branche_à_fusionner_dans_celle_sur_laquelle_vous_êtes ``` @@ -188,7 +197,7 @@ temps de lui dire au revoir ! Commençons d'abord par la supprimer sur le repo distant : -```git +```bash git push -d origin nom_de_branche ``` @@ -200,7 +209,7 @@ références locales à des branches fantômes distantes avec la commande `git f Enfin, il est temps de supprimer votre copie locale de cette branche : -```git +```bash git branch -d nom_de_branche ``` @@ -210,12 +219,12 @@ possible de forcer la suppression d'une branche locale non fusionnée avec l'opt "Don't cry because it's over, smile because it happened." - *Dr. Seuss* -## TL;DR +## TL;DR {#tldr} On commence par demander à git de ne pull que s'il n'y a pas de divergence avec la version distante de notre branche, et sinon, de rebase notre branche automatiquement : -```git +```bash git config pull.rebase true ``` diff --git a/src/assets/images/robot-timide/pcb_fritzing.png b/content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/pcb_fritzing.png similarity index 100% rename from src/assets/images/robot-timide/pcb_fritzing.png rename to content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/pcb_fritzing.png diff --git a/src/assets/images/robot-timide/pcb_irl.jpg b/content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/pcb_irl.jpg similarity index 100% rename from src/assets/images/robot-timide/pcb_irl.jpg rename to content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/pcb_irl.jpg diff --git a/src/assets/images/robot-timide/pile9v.jpg b/content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/pile9v.jpg similarity index 100% rename from src/assets/images/robot-timide/pile9v.jpg rename to content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/pile9v.jpg diff --git a/src/assets/images/robot-timide/robot_timide_enseirb.jpg b/content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/robot_timide_enseirb.jpg similarity index 100% rename from src/assets/images/robot-timide/robot_timide_enseirb.jpg rename to content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/robot_timide_enseirb.jpg diff --git a/src/assets/images/robot-timide/robot_timide_header.jpg b/content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/robot_timide_header.jpg similarity index 100% rename from src/assets/images/robot-timide/robot_timide_header.jpg rename to content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/robot_timide_header.jpg diff --git a/src/assets/images/robot-timide/u_shape.jpg b/content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/u_shape.jpg similarity index 100% rename from src/assets/images/robot-timide/u_shape.jpg rename to content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/images/u_shape.jpg diff --git a/src/robot-timide-robot-qui-fuit-la-lumiere.md b/content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/index.md similarity index 94% rename from src/robot-timide-robot-qui-fuit-la-lumiere.md rename to content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/index.md index 346161f..0398801 100644 --- a/src/robot-timide-robot-qui-fuit-la-lumiere.md +++ b/content/2022-05-19-robot-timide-robot-qui-fuit-la-lumiere/index.md @@ -1,4 +1,11 @@ -# Robot timide – le robot qui fuit la lumière ++++ +title = "Robot timide – le robot qui fuit la lumière" +description = "Création d'un robot timide pour un projet scolaire." +date = 2022-05-19 + +[taxonomies] +tags = ["maker", "fablab", "robotique"] ++++ Création d'un robot timide pour un projet scolaire. @@ -9,7 +16,9 @@ en filière Informatique, un robot timide a vu le jour au sein d’Eirlab. Cet article est un guide pour expliquer comment reproduire notre travail, dans le plus pur esprit Maker. -![Une vue de 3/4 face du robot finalisé](./assets/images/robot-timide/robot_timide_header.jpg) + + +![Une vue de 3/4 face du robot finalisé](images/robot_timide_header.jpg) ## Concept de base @@ -20,7 +29,7 @@ mode est aussi disponible, permettant non pas d’aller vers l’endroit le plus sombre, mais à l’inverse de fuir l’endroit le plus lumineux, pour avoir deux manières de voir le problème. -![Une vue de face du robot timide dans sa forme finale.](./assets/images/robot-timide/robot_timide_enseirb.jpg) +![Une vue de face du robot timide dans sa forme finale.](images/robot_timide_enseirb.jpg) ## Du matériel @@ -55,7 +64,7 @@ percée pour accueillir les différents modules du robot. Les éléments les plu légers ou risquant moins de se détacher sont fixés par un simple système de mâchoire, prenant en étau la plaque de bois dans une forme de U. -![La forme de U pour prendre la plaque de base en mâchoire et tenir un capteur par pression.](./assets/images/robot-timide/u_shape.jpg) +![La forme de U pour prendre la plaque de base en mâchoire et tenir un capteur par pression.](images/u_shape.jpg) ### Alimentation @@ -69,7 +78,7 @@ et prend donc des tensions entre 5 et 9 Volts. Dans ce projet, nous utilisons une pile 9 Volts rechargeable dans un boîtier vissé au châssis. -![Une vue de la pile 9 Volts que nous utilisons, rechargeable en micro USB.](./assets/images/robot-timide/pile9v.jpg) +![Une vue de la pile 9 Volts que nous utilisons, rechargeable en micro USB.](images/pile9v.jpg) ### Moteurs @@ -92,11 +101,11 @@ aussi appelé breadboard. Dans un second temps et pour éviter toute déconnexio de câbles liée à une potentielle accélération violente, nous avons fait un PCB, soudé manuellement sur une carte de prototypage prévu à cet effet. -![Une vue du dessus de notre PCB fait main.](./assets/images/robot-timide/pcb_irl.jpg) +![Une vue du dessus de notre PCB fait main.](images/pcb_irl.jpg) Au niveau électronique, le PCB est routé de la manière suivante : -![Le routage du PCB sur une carte de protypage de type Breadboard.](./assets/images/robot-timide/pcb_fritzing.png) +![Le routage du PCB sur une carte de protypage de type Breadboard.](images/pcb_fritzing.png) Les différents composants viennent se connecter sur le PCB au moyen de différentes broches femelles, pour que ce dernier puisse être détaché et modifié diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..a91000b --- /dev/null +++ b/content/_index.md @@ -0,0 +1,4 @@ ++++ +paginate_by=5 +sort_by = "date" ++++ diff --git a/content/pages/archive.md b/content/pages/archive.md new file mode 100644 index 0000000..0da1e0b --- /dev/null +++ b/content/pages/archive.md @@ -0,0 +1,6 @@ ++++ +title = "Articles archivés" +path = "archive" ++++ + +N/A \ No newline at end of file diff --git a/enrich_codeblocks.js b/enrich_codeblocks.js deleted file mode 100644 index 11fda5a..0000000 --- a/enrich_codeblocks.js +++ /dev/null @@ -1,20 +0,0 @@ -const Prism = require('prismjs'); -const fs = require('fs'); -const cheerio = require('cheerio'); -const loadLanguages = require('prismjs/components/'); -const fsc = require('fs-cheerio'); - -loadLanguages([ - 'rust', 'py', 'cpp', 'c', 'git' -]); - -const file = process.argv[2]; -fsc.readFile(file).then(function ($, err) { - $('*[class^="language-"]').replaceWith(function () { - return $(this).html(Prism.highlight( - $(this).text(), - Prism.languages[$(this).attr('class').split('-')[1]]) - ); - }); - fsc.writeFile(file, $); -}); diff --git a/package.json b/package.json deleted file mode 100644 index 96ef342..0000000 --- a/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "dependencies": { - "cheerio": "^1.0.0-rc.10", - "fs-cheerio": "^3.0.0", - "prismjs": "^1.26.0" - } -} diff --git a/src/_footer.html b/src/_footer.html deleted file mode 100644 index 56446d9..0000000 --- a/src/_footer.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/src/_header.html b/src/_header.html deleted file mode 100644 index 98fe627..0000000 --- a/src/_header.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/aoc-2021-jour-0-commencement.md b/src/aoc-2021-jour-0-commencement.md deleted file mode 100644 index af03c83..0000000 --- a/src/aoc-2021-jour-0-commencement.md +++ /dev/null @@ -1,73 +0,0 @@ -# AoC 2021 Jour 0: Commencement - -Le début d'une grande aventure ! - -Cette année, j'ai découvert l'[Advent Of Code](https://adventofcode.com/). -Ce site géré de manière bénévole par [Eric Wastl](http://was.tl/) sur son temps -libre met à disposition des puzzles sur un thème différent d'une année sur -l'autre. Ces petits puzzles sont à résoudre à l'aide d'un programme informatique -ou d'un algorithme que l'on est sensé imaginer et mettre en oeuvre, pour, à partir -d'un fichier d'entrée qui nous est propre, donner un résultat à troquer sur le site -du challenge en échange d'une étoile. Le langage et la manière d'obtenir le -résultat sont libres, mais faire les défis "à la main" est rarement possible -(en tous cas en temps humain). Pendant tout le mois de décembre, un défi est publié -chaque jour du 1er au 25. Ils sont systématiquement découpés en 2 parties, la -seconde n'étant accessible qu'une fois la première résolue. -En échange d'une réponse valide au problème, une étoile nous est donnée, pour avoir -un total de 50 étoiles par an. - -Il n'y a pas de pénalité si le puzzle n'est pas résolu dans la journée, mais un -*leaderboard* est disponible, et les 100 premiers à résoudre les puzzles obtiennent -des points sur leur profil. C'est comme cela que j'ai découvert qu'il existait -une discipline de [Programmation Compétitive](https://en.wikipedia.org/wiki/Competitive_programming). - -Cette année, le thème c'était la quête de la clé du traîneau du Père Noël au fond -d'une crevasse sous-marine, armé d'un petit sous-marin, et rencontrant au passage -une faune et flore locale diverse. - -![Vue de l'intérieur d'un sous-marin d'exploration. Photo par Michael Mrozek pour Unsplash.](./assets/images/aoc-2021-day-0/michal-mrozek-BEUd36I1-f8-unsplash.jpg) - -J'ai déjà résolu les 25 jours et obtenu mes 50 étoiles, je souhaite maintenant -raconter ici mon aventure, jour après jour, et les algorithmes que j'ai mis en -place. - -## Pourquoi - -J'ai choisi de participer à cet évènement pour différentes raisons : - -- j'aime les défis, je trouve amusant et plaisant d'avoir un but à atteindre en code -- je voulais m'exercer, j'aime travailler sur des projets sur mon temps libre - -## Comment - -Mes algorithmes sont implémentés en [Rust](https://www.rust-lang.org/), un langage -que j'aime beaucoup, pour différentes raisons qui sont hors sujet par rapport à -cette série d'articles. Un article spécifique sur ce qui me plaît dans ce -langage de programmation arrivera peut-être plus tard. - -Mon but était de résoudre les puzzles en temps limité, si possible en moins d'une -journée, et que le programme final donne sa réponse le plus rapidement possible. -Si après 3 jours à travailler sur un puzzle, il donne une réponse en 300ms, cela -me convient. **Le but n'étant pas ici de faire des algorithmes optimaux.** - -Chaque jour a été mis à disposition sur [gitlab](https://gitlab.com/lovallat/advent-of-code-2021). - -## Beurk - -Vous trouvez le code illisible ? C'est **normal**. - -J'ai tendance dans mes programmes à avoir de mauvaises habitudes, *hostiles* à -la relecture de code. J'ai tendance à utiliser par exemple des variables dont le -nom se résume à une unique lettre. J'ai aussi tendance à vouloir produire un -fichier source le plus court possible (tout en respectant les standards du langage -utilisé). Le code fourni est alors un bloc compact **difficile à lire**. - -J'ai donc décidé de me faire subir le même sort que celui réservé à mes collègues -lorsqu'il doivent relire mon code, afin de me faire **perdre** ces mauvaises -habitudes. (*spoiler: c'était efficace*) - -## À suivre - -Seront publiés sur ce blog différents articles retraçant et expliquant jour après -jour ce que mes algorithmes et programmes font pour résoudre les différents défis. - diff --git a/src/aoc-2021-jour-1-sonar-sweep.md b/src/aoc-2021-jour-1-sonar-sweep.md deleted file mode 100644 index a1d0177..0000000 --- a/src/aoc-2021-jour-1-sonar-sweep.md +++ /dev/null @@ -1,112 +0,0 @@ -# AoC 2021 Jour 1: Sonar Sweep - -À la recherche de la clef du traîneau à l'aide d'un sonar. - -Le défi peut être trouvé [ici](https://adventofcode.com/2021/day/1), et le code -lié est sur [gitlab](https://gitlab.com/lovallat/advent-of-code-2021/-/tree/master/day1). - -## Consigne du défi - -Le premier puzzle est assez simple, et peut se résumer en "compter les variations -dans un fichier d'entrée". - -## Lecture du fichier d'entrée - -Pour lire le fichier, rien de plus simple. L'entrée étant une simple liste d'entiers -séparés par des retours à la ligne, il est assez facile de le transformer en -tableau d'entiers. - -En code, cela se traduit par : - -```rust -fn parse_input(s: &str) -> Vec { - return s.split("\n").into_iter().filter_map(|f| f.parse::().ok()).collect::>(); -} -``` - -Maintenant que j'ai acquis un peu plus d'expérience en Rust, je le ferais d'une -manière assez différente : - -- tout d'abord, `s.split("\n").into_iter()` peut être remplacé par `s.lines()`, -plus robuste et [System Agnostic](https://en.wikipedia.org/wiki/Agnostic_(data)), -les systèmes Windows utilisant une fin de ligne [différente](https://en.wikipedia.org/wiki/Newline#In_programming_languages). -- ensuite, utiliser des `u16`, soit des entiers non signés et encodés sur 16 bits. -Ici utiliser 32 bits signés pour stocker des valeurs relativement faibles (dans ce -jeu de données) et strictement positives n'est pas optimal. - -## Première partie - -La première partie nécessite de compter les augmentations de nombres un-à-un. - -Nous avons donc un tableau (vecteur) d'entiers, alors il suffira simplement de le -parcourir, et si l'entier actuel est plus grand que le précédent, alors on retient -qu'on a vu une augmentation supplémentaire. - -Le code de cette partie est le suivant : - -```rust -fn get_increase_nb(e: &Vec) -> i32 { - let mut n = 0; - for i in 1..e.len() { - n += if e[i] > e[i - 1] { 1 } else { 0 }; - } - return n; -} -``` - -On a donc un entier `n` qui va retenir le nombre d'augmentations observées, -et pour tous les entiers du tableau, de la case 1 (les tableaux en informatique -débutent à la case 0), à la case `taille` (non incluse, toujours parce que les -tableaux commencent à 0). Si le nombre actuel est plus grand que le précédent, -alors `n` augmente de 1. - -## Deuxième partie - -Pour cette deuxième partie, le concept est le même mais cette fois on prend les -entiers d'entrée par groupe de 3 et on compte les augmentations entre chaque -sommes d'entiers. - -On transforme donc le tableau d'entiers en un second tableau correspondant aux -sommes de 3 entiers selon une fenêtre flottante. - -```rust -fn get_sums(v: &Vec) -> BTreeMap { - let mut sums = BTreeMap::new(); - for i in 0..(v.len() - 2) { - sums.insert(i, v[i] + v[i + 1] + v[i + 2]); - } - return sums; -} -``` - -Ici, une [BTreeMap](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html) -est **totalement** inutile. Je ne sais pas trop pourquoi j'ai choisi ce type de -structure de données. Surtout qu'après, cette Map est convertie en simple tableau -en ignorant totalement la clef : - -```rust -let map = get_sums(&vec_in).iter().map(|e| e.1.to_owned()).collect::>(); -``` - -Ici il serait *beaucoup plus intéressant* d'utiliser un simple tableau, et à chaque -nouvelle somme on peut l'envoyer sur le dessus du tableau (de sommes) d'entiers. - -Ce tableau enfin obtenu sera alors envoyé à la même méthode que pour la partie une -pour en obtenir le nombre d'augmentations. - -Évidemment il serait aussi possible de simplement compter les augmentations en même -temps que l'on parcourt les tableaux, pour éviter de multiples passages. - -## Conclusion - -Ce puzzle était loin d'être compliqué. J'ai passé un peu de temps sur la -compréhension du système de sommes de la partie 2, ne sachant que faire dans le -cas où il n'y avait plus assez d'entiers pour faire une somme. - -Après un peu de temps et d'essais, j'ai pu m'en sortir sans difficulté. - -Concernant la qualité du code, je me demande bien ce que j'ai pu penser sur le -moment pour choisir de stocker les sommes dans une map à arbre binaire... - -> À suivre - diff --git a/src/aoc-2021-jour-2-dive.md b/src/aoc-2021-jour-2-dive.md deleted file mode 100644 index 2b5c6c6..0000000 --- a/src/aoc-2021-jour-2-dive.md +++ /dev/null @@ -1,127 +0,0 @@ -# AoC 2021 Jour 2: Dive - -Comment piloter le sous-marin des elfes ? - -Le défi peut être trouvé [ici](https://adventofcode.com/2021/day/2), et le code -lié est sur [gitlab](https://gitlab.com/lovallat/advent-of-code-2021/-/tree/master/day2). - -## Consigne du défi - -Le sous-marin peut prendre 3 types de commandes : - -- `forward X` -- `down X` -- `up X` - -Le fichier d'entrée est une suite de ces ordres, que l'on doit interpréter pour -trouver la position du sous-marin dans l'espace (horizontalement et verticalement). - -## Lecture du fichier d'entrée - -La lecture du fichier d'entrée se fait à nouveau dans une seule fonction : - -```rust -fn parse_input(s: &str) -> Vec<(String, i32)> { - let mut r:Vec<(String, i32)> = vec![]; - let v = s.split("\n").into_iter(); - for e in v { - let p = e.split_whitespace().collect::>(); - if p.len() == 2 && p[1].parse::().is_ok() { - r.push((p[0].to_owned(), p[1].parse::().unwrap())); - } - } - return r; -} -``` - -Ici, on va tout simplement transformer une ligne en tuple `(String, i32)`, et -de transformer le fichier d'entrée en un tableau `Vec` de ces ordres. On découpe -donc une ligne `ordre X` en fonction d'un espace, et si on a bien 2 éléments et -que le deuxième peut être converti en entier signé stocké sur 32 bits, alors on -l'ajoute à notre tableau d'instructions. - -On pourrait ici utiliser une énumeration telle que `Direction::Forward`, -`Direction::Up` et `Direction::Down` pour éviter de stocker les chaînes de -caractère en entier dans le tableau. On pourrait aussi utiliser des entiers stockés -sur moins de bits, étant relativement petits. - -## Première partie - -Pour la première partie, l'interprétation des instructions est la suivante : - -- `forward X` qui permet de faire avancer le sous-marin de `X` unités horizontalement -- `down X` fait plonger le sous-marin et donc augmente sa profondeur de `X` unités -- `up X` fait remonter à l'inverse le sous-marin vers la surface - -La réponse à la première partie se trouve en multipliant la position horizontale -et verticale. Pour cela, on va faire un `fold` sur le tableau pour calculer toutes -les instructions à la suite et donnant le résultat en une seule ligne : - -```rust -fn get_horizontal_depth(v: Vec<(String, i32)>) -> (i32, i32) { - return v.into_iter().fold((0, 0), |acc, e| compute_horizontal_depth(e, acc)); -} -``` - -Chaque ligne est traitée individuellement pour interprétation, en donnat en valeur -de retour les nouvelles positions du sous-marin après application de l'instruction -sur la position donnée en entrée : - -```rust -fn compute_horizontal_depth(t: (String, i32), a: (i32, i32)) -> (i32, i32) { - return match t.0.as_str() { - "up" => (a.0, a.1 - t.1), - "down" => (a.0, a.1 + t.1), - "forward" => (a.0 + t.1, a.1), - _ => a - }; -} -``` - -Ce traitement est donc très simple. Pour chaque instruction et en partant d'une -position `(0, 0)`, on va appliquer les règles les unes après les autres en mettant -à jour la position à chaque fois. Cela se fait en temps linéaire sans calcul autre -que des additions. - -## Deuxième partie - -Pour la deuxième partie, le traitement est assez similaire, mais on va calculer -une composante supplémentaire : la *visée*. - -Les instructions sont désormais à interpréter de cette manière : - -- `forward X` permet deux choses : - - augmente la position horizontale de `X` unités - - augmente la profondeur par la *visée* multipliée par `X` -- `down X` augmente la *visée* de `X` unités -- `up X` à l'inverse diminue la *visée* de `X` unités - -Le concept pour calculer est le même, on applique les instructions l'une après -l'autre en partant de `(0, 0, 0)`. - -```rust -fn compute_horizontal_depth_aim(t: (String, i32), a: (i32, i32, i32)) -> (i32, i32, i32) { - return match t.0.as_str() { - "up" => (a.0, a.1, a.2 - t.1), - "down" => (a.0, a.1, a.2 + t.1), - "forward" => (a.0 + t.1, a.1 + a.2 * t.1, a.2), - _ => a - }; -} -``` - -Enfin, la réponse à donner est la multiplication de la position horizontale et -verticale, comme pour la précédente partie. - -## Conclusion - -Ce défi n'était pas compliqué et ma réponse me semble adaptée. Bien sûr il y a -toujours des pistes d'améliorations, telle que le type de données stockées : -les chaînes de caractères étant moins performantes à traiter, mais aussi la taille -des entiers stockés, ou encore le fait que je ne passe pas de référence aux -fonctions, nécéssitant une copie systématique, consommant des cycles supplémentaires. - -Mais globalement je suis satisfait de ma réponse à ce défi. - -> À suivre - diff --git a/src/aoc-2021-jour-3-binary-diagnostic.md b/src/aoc-2021-jour-3-binary-diagnostic.md deleted file mode 100644 index 68ec07f..0000000 --- a/src/aoc-2021-jour-3-binary-diagnostic.md +++ /dev/null @@ -1,167 +0,0 @@ -# AoC 2021 Jour 3: Binary Diagnostic - -Grincements étranges et inquiétants dans le sous-marin. - -Le défi peut être trouvé [ici](https://adventofcode.com/2021/day/3), et le code -lié est sur [gitlab](https://gitlab.com/lovallat/advent-of-code-2021/-/tree/master/day3). - -## Consigne du défi - -Dans ce défi, on nous apprend que le sous-marin fait des bruits *pour le moins -étranges*. Le fichier d'entrée se compose d'une longue liste de nombres binaires, -que nous devons analyser. - -## Lecture du fichier d'entrée - -La lecture du fichier d'entrée se fait de la manière suivante, assez simplement : - -```rust -fn parse_input(s: &str) -> Vec> { - let mut r: Vec> = vec![]; - for e in s.split("\n") { - if !e.is_empty() { - r.push(e.chars().filter_map(|e| e.to_digit(2)).collect()); - } - } - return r; -} -``` - -On va donc transformer chaque ligne (par exemple `101000001100`) en un tableau -de chiffres, ayant pour valeur `0` ou `1` (dans l'exemple -`[ 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0 ]`). On fait cela pour chaque ligne, pour -assembler une matrice de chiffres binaires, faciles à parcourir dans toutes les -directions. - -## Première partie - -Pour la première partie, il va falloir créer un nombre binaire à partir des chiffres -les **plus** fréquents dans les colonnes, et un nombre binaire à partir des chiffres -les **moins** fréquents, toujours dans les colonnes. On obtiendra alors deux -nombres binaires, qui une fois convertis en base 10 et ensuite multipliés entre eux, -donne la réponse à cette première partie. - -Une fonction utilitaire permet de convertir les tableaux de nombres binaires en -nombre entier non signé : - -```rust -fn bit_vec_to_u32(v: &Vec, invert: bool) -> u32 { - let mut acc = 0; - for i in 0..v.len() { - acc += if invert { (v[i] + 1) % 2 } else { v[i] } << (v.len() - 1 - i); - } - return acc; -} -``` - -On a donc ici un accumulateur qui fait la somme des éléments tout en faisant un -décalage binaire, produisant un nombre entier en temps linéaire. - -On va donc utiliser une fonction permettant d'obtenir, pour tout le fichier d'entrée, -le bit le plus présent dans la colonne `c` : - -```rust -fn get_most_in_col(v: &Vec>, c: usize) -> u32 { - let mut a = (0, 0); - for r in 0..v.len() { - if v[r][c] == 0 { - a.0 += 1; - } else { - a.1 += 1; - } - } - if a.1 == a.0 { return 1; } - else { return if a.1 > a.0 { 1 } else { 0 }; } -} -``` - -À la fin de la fonction, on peut voir que lors d'une égalité, c'est le `1` qui est -considéré comme valeur la plus présente dans la colonne étudiée. - -**Amélioration possible :** il serait potentiellement plus intéressant de faire la somme des entiers stockés -dans la colonne, et regarder si cette somme est supérieure au nombre de lignes -divisée par deux, car cela nous évite de faire des comparaisons et rend inutiles -les conditions `if` qui sont au milieu de la boucle, ralentissent fortement -le calcul et sont donc à **proscrire**. - -On va donc ici calculer en un seul coup la suite de chiffres binaires les plus -représentés par colonne dans le fichier d'entrée. La valeur `gamma` sera donc la -conversion directe de ce tableau en nombre entier non signé, et la valeur `epsilon` -sera aussi une conversion, mais inversée. - -```rust -fn get_gamma_epsilon(v: &Vec>) -> (u32, u32) { - let mut acc: Vec = vec![]; - - for c in 0..v[0].len() { - acc.push(get_most_in_col(&v, c)); - } - return (bit_vec_to_u32(&acc, false), bit_vec_to_u32(&acc, true)); -} -``` - -La multiplication de ces deux valeurs nous donne la réponse à cette première partie. - -## Deuxième partie - -Toujours à partir de ce fichier d'entrée, on doit alors calculer deux nouvelles -valeurs : le niveau de génération d'oxygène et le niveau de filtrage de CO2. - -Pour obtenir ces deux valeurs, on joue encore sur les bits les plus et les moins -communs dans une colonne donnée mais en rajoutant cette fois un concept -d'élimination. On va donc faire ceci : - -- On récupère le bit le plus (ou le moins) présent dans la colonne observée -- On ne conserve que les nombres binaires qui ont cette valeur de bit pour cette colonne -- On répète cette opération jusqu'à ce qu'il ne reste qu'une seule valeur - -Ici, j'ai utilisé une approche récursive : - -```rust -fn get_o2(v: &Vec>, c: usize) -> u32 { - if v.len() == 1 { return bit_vec_to_u32(&v[0], false); } - - let a = get_most_in_col(&v, c); - let f = v.into_iter().filter(|e| e[c] == (a + 1) % 2) - .fold(vec![], |mut acc, e| { acc.push(e.to_owned()); return acc;}); - return get_o2(&f, c + 1); -} - -fn get_co2(v: &Vec>, c: usize) -> u32 { - if v.len() == 1 { return bit_vec_to_u32(&v[0], false); } - - let a = get_most_in_col(&v, c); - let f = v.into_iter().filter(|e| e[c] == a) - .fold(vec![], |mut acc, e| { acc.push(e.to_owned()); return acc;}); - return get_co2(&f, c + 1); -} -``` - -On va donc récupérer le bit le plus présent dans la colonne `c`, et conserver les -valeurs qui nous intéressent, puis rappeler la méthode sur les valeurs restantes -en avançant d'une colonne. Une fois qu'il ne reste qu'une valeur, on sait qu'on -a notre résultat, et c'est ce qui est renvoyé. - -En relisant ce code, j'ai plusieurs critiques à en faire : - -- J'ai visiblement inversé le calcul de CO2 et de O2. Dans le calcul pour l'oxygène, -je ne conserve que les bits les moins présents, alors que c'est les plus présents -que je devrais conserver. Cela ne pose pas de problème car je dois multiplier les -deux valeurs entre elles, et l'ordre des termes d'un produit importe peu. -- J'utilise `(a + 1) % 2` pour obtenir l'inverse d'un bit, alors qu'un simple "différent" -suffirait. Cela demande de faire des opérations coûteuses (la division est coûteuse -en cycles CPU) pour rien. -- Je fais une copie du tableau avec les éléments restants après le tri au lieu de -faire un simple `filter`. Une copie est de toutes façons nécessaire, mais filtrer -le tableau serait plus élégant. - -## Conclusion - -Ce défi fait monter très légèrement la difficulté et le temps de réflexion -nécessaire, mais cela reste très accessible. Encore une fois, relire son code -et se poser les bonnes questions est très important, surtout se demander si telle -ou telle copie ou opération est bien nécessaire. C'est une réflexion que je -m'appliquerai à faire plus souvent. - -> À suivre - diff --git a/src/assets/css/reset.css b/src/assets/css/reset.css deleted file mode 100644 index af94440..0000000 --- a/src/assets/css/reset.css +++ /dev/null @@ -1,48 +0,0 @@ -/* http://meyerweb.com/eric/tools/css/reset/ - v2.0 | 20110126 - License: none (public domain) -*/ - -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -b, u, i, center, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, -menu, nav, output, ruby, section, summary, -time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -/* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; -} -body { - line-height: 1; -} -ol, ul { - list-style: none; -} -blockquote, q { - quotes: none; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} \ No newline at end of file diff --git a/src/assets/css/style.css b/src/assets/css/style.css deleted file mode 100644 index 32d50f8..0000000 --- a/src/assets/css/style.css +++ /dev/null @@ -1,218 +0,0 @@ -@charset "utf-8"; -/* Coded by Louis Vallat */ - -@font-face { - font-family: 'JetBrains Mono'; - src: url("/assets/fonts/JetBrainsMono.ttf"); - font-display: swap; -} - -@font-face { - font-family: 'IBM Plex Mono'; - src: url("/assets/fonts/IBMPlexMono.ttf"); - font-display: swap; -} - -@font-face { - font-family: 'Open Sans'; - src: url("/assets/fonts/OpenSans-Regular.ttf"); - font-display: swap; -} - -:root { - --bg: #2A2D34; - --light_bg: #414652; - --fg: #fefefe; - --link: #009DDC; - --link_h: #009B72; - --link_v: #ACACDE; -} - -blockquote { - border-left: 5px solid var(--light_bg); - border-radius: 5px; - margin-left: 10px; - padding-left: 7px; -} - -body { - font-family: 'Open Sans', sans-serif; - background-color: var(--bg); - color: var(--fg); - margin-right: 27vw; - margin-left: 27vw; - text-align: justify; - font-size: 16px; -} - -p, ul { - margin-top: 10px; - line-height: 1.55em; -} - -li>ul { - margin-top: 0; - margin-left: 15px; - list-style-type: circle; -} - -img { - margin-top: 15px; - margin-bottom: 5px; - width: 100%; -} - -a { - color: var(--link); -} - -a:visited { - color: var(--link_v); -} - -a:hover { - color: var(--link_h); -} - -nav { - display: flex; - flex-direction: row; - justify-content: space-between; - margin-top: 10px; - margin-bottom: 10px; - flex-wrap: wrap; -} - -.filler { - flex-grow: 2; -} - -nav>a { - font-family: 'Open Sans', sans-serif; - padding: 10px; -} - -nav>a:visited, nav>a:hover, nav>a { - color: var(--fg); - text-decoration: none; -} - -nav>a:not(#home_link) { - margin-left: 25px; -} - -h1, h2, h3, h4, h5, h6 { - font-family: 'JetBrains Mono', sans-serif; - font-weight: bold; - margin-top: 20px; - margin-bottom: 10px; -} - -ul { - list-style: disc; - list-style-position: inside; -} - -h1 { - font-size: 2.5em; -} - -h2 { - font-size: 1.85em; -} - -h3 { - font-size: 1.65em; -} - -h4 { - font-size: 1.45em; -} - -h5 { - font-size: 1.35em; -} - -h6 { - font-size: 1.25em; -} - -b, strong { - font-weight: bold; -} - -em, i { - font-style: italic; -} - -footer { - font-size: 14px; - margin-bottom: 100px; -} - -pre { - margin-bottom: 5px; - margin-top: 5px; -} - -pre>code { - padding: 10px; - display: block; - overflow: auto; - line-height: 1.35em; -} - -code { - padding: 2px 5px 2px 5px; - border-radius: 5px; - background-color: var(--light_bg); - font-family: 'IBM Plex Mono', monospace; -} - -/* Code blocks colors */ -.token.keyword, .token.macro { - color: #D55FDE; -} - -.token.function { - color: #52ADF2; -} - -.token.class-name { - color: #E5C07B; -} - -.token.punctuation, .token.operator { - color: #AAB1C0; -} - -.token.string { - color: #89CA78; -} - -.token.number { - color: #D8985F; -} - -@media screen and (max-width: 992px) { - body { - margin-right: 10vw; - margin-left: 10vw; - } - nav>a:not(#home_link) { - margin-left: 5px; - } -} - -@media screen and (max-width: 768px) { - body { - margin-right: 5vw; - margin-left: 5vw; - } - nav>a:not(#home_link) { - margin-left: 0px; - } - blockquote { - margin-left: 0px; - } -} diff --git a/src/assets/fonts/IBMPlexMono.ttf b/src/assets/fonts/IBMPlexMono.ttf deleted file mode 100644 index 021eaec..0000000 Binary files a/src/assets/fonts/IBMPlexMono.ttf and /dev/null differ diff --git a/src/assets/fonts/JetBrainsMono.ttf b/src/assets/fonts/JetBrainsMono.ttf deleted file mode 100644 index 9a5202e..0000000 Binary files a/src/assets/fonts/JetBrainsMono.ttf and /dev/null differ diff --git a/src/assets/fonts/OpenSans-Regular.ttf b/src/assets/fonts/OpenSans-Regular.ttf deleted file mode 100644 index 29bfd35..0000000 Binary files a/src/assets/fonts/OpenSans-Regular.ttf and /dev/null differ diff --git a/src/assets/images/aoc-2021-day-0/michal-mrozek-BEUd36I1-f8-unsplash.jpg b/src/assets/images/aoc-2021-day-0/michal-mrozek-BEUd36I1-f8-unsplash.jpg deleted file mode 100644 index 39fd285..0000000 Binary files a/src/assets/images/aoc-2021-day-0/michal-mrozek-BEUd36I1-f8-unsplash.jpg and /dev/null differ diff --git a/src/assets/images/icon.png b/src/assets/images/icon.png deleted file mode 100644 index cb8cee2..0000000 Binary files a/src/assets/images/icon.png and /dev/null differ diff --git a/src/index.md b/src/index.md deleted file mode 100644 index c66f5a7..0000000 --- a/src/index.md +++ /dev/null @@ -1,12 +0,0 @@ -#### Articles - -Un blog on ne peut plus simple. - -- [Archive/Projet Makers ENSEIRB - Robot timide](./robot-timide-robot-qui-fuit-la-lumiere.html) -- Advent of Code 2021 : - - [Advent of Code 2021 Jour 3 : Binary Diagnostic](./aoc-2021-jour-3-binary-diagnostic.html) - *07/02/2021* - - [Advent of Code 2021 Jour 2 : Dive](./aoc-2021-jour-2-dive.html) - *24/01/2021* - - [Advent of Code 2021 Jour 1 : Sonar Sweep](./aoc-2021-jour-1-sonar-sweep.html) - *19/01/2021* - - [Advent of Code 2021 Jour 0 : le commencement](./aoc-2021-jour-0-commencement.html) - *17/01/2022* -- [Git workflow](./git_flow.html) - *10/05/2021* - diff --git a/ssg5 b/ssg5 deleted file mode 100755 index ddadbda..0000000 --- a/ssg5 +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -e -# -# https://rgz.ee/bin/ssg5 -# Copyright 2018-2019 Roman Zolotarev -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -main() { - test -n "$1" || usage - test -n "$2" || usage - test -n "$3" || usage - test -n "$4" || usage - test -d "$1" || no_dir "$1" - test -d "$2" || no_dir "$2" - - - src=$(readlink_f "$1") - dst=$(readlink_f "$2") - - IGNORE=$( - if ! test -f "$src/.ssgignore" - then - printf ' ! -path "*/.*"' - return - fi - while read -r x - do - test -n "$x" || continue - printf ' ! -path "*/%s*"' "$x" - done < "$src/.ssgignore" - ) - - # files - - title="$3" - - h_file="$src/_header.html" - f_file="$src/_footer.html" - test -f "$f_file" && FOOTER=$(cat "$f_file") && export FOOTER - test -f "$h_file" && HEADER=$(cat "$h_file") && export HEADER - - list_dirs "$src" | - (cd "$src" && cpio -pdu "$dst") - - fs=$( - if test -f "$dst/.files" - then list_affected_files "$src" "$dst/.files" - else list_files "$1" - fi - ) - - if test -n "$fs" - then - echo "$fs" | tee "$dst/.files" - - if echo "$fs" | grep -q '\.md$' - then - if test -x "$(which lowdown 2> /dev/null)" - then - echo "$fs" | grep '\.md$' | - render_md_files_lowdown "$src" "$dst" "$title" - else - if test -x "$(which Markdown.pl 2> /dev/null)" - then - echo "$fs" | grep '\.md$' | - render_md_files_Markdown_pl "$src" "$dst" "$title" - else - echo "couldn't find lowdown nor Markdown.pl" - exit 3 - fi - fi - fi - - echo "$fs" | grep '\.html$' | - render_html_files "$src" "$dst" "$title" - - - echo "$fs" | grep -Ev '\.md$|\.html$' | - (cd "$src" && cpio -pu "$dst") - fi - - printf '[ssg] ' >&2 - print_status 'file, ' 'files, ' "$fs" >&2 - - - # sitemap - - base_url="$4" - date=$(date +%Y-%m-%d) - urls=$(list_pages "$src") - - test -n "$urls" && - render_sitemap "$urls" "$base_url" "$date" > "$dst/sitemap.xml" - - print_status 'url' 'urls' "$urls" >&2 - echo >&2 -} - - -readlink_f() { - file="$1" - cd "$(dirname "$file")" - file=$(basename "$file") - while test -L "$file" - do - file=$(readlink "$file") - cd "$(dirname "$file")" - file=$(basename "$file") - done - dir=$(pwd -P) - echo "$dir/$file" -} - - -print_status() { - test -z "$3" && printf 'no %s' "$2" && return - - echo "$3" | awk -v singular="$1" -v plural="$2" ' - END { - if (NR==1) printf NR " " singular - if (NR>1) printf NR " " plural - }' -} - - -usage() { - echo "usage: ${0##*/} src dst title base_url" >&2 - exit 1 -} - - -no_dir() { - echo "${0##*/}: $1: No such directory" >&2 - exit 2 -} - -list_dirs() { - cd "$1" && eval "find . -type d ! -name '.' ! -path '*/_*' $IGNORE" -} - - -list_files() { - cd "$1" && eval "find . -type f ! -name '.' ! -path '*/_*' $IGNORE" -} - - -list_dependant_files () { - e="\\( -name '*.html' -o -name '*.md' -o -name '*.css' -o -name '*.js' \\)" - cd "$1" && eval "find . -type f ! -name '.' ! -path '*/_*' $IGNORE $e" -} - -list_newer_files() { - cd "$1" && eval "find . -type f ! -name '.' $IGNORE -newer $2" -} - - -has_partials() { - grep -qE '^./_.*\.html$|^./_.*\.js$|^./_.*\.css$' -} - - -list_affected_files() { - fs=$(list_newer_files "$1" "$2") - - if echo "$fs" | has_partials - then list_dependant_files "$1" - else echo "$fs" - fi -} - - -render_html_files() { - while read -r f - do render_html_file "$3" < "$1/$f" > "$2/$f" - done -} - - -render_md_files_lowdown() { - while read -r f - do - lowdown \ - --html-no-skiphtml \ - --html-no-escapehtml < "$1/$f" | - render_html_file "$3" "$(head -n 3 ${1}/${f} | tail -n 1)" > "$2/${f%\.md}.html" - node ./enrich_codeblocks.js "$2/${f%\.md}.html" - done -} - - -render_md_files_Markdown_pl() { - while read -r f - do - Markdown.pl < "$1/$f" | - render_html_file "$3" \ - > "$2/${f%\.md}.html" - done -} - - -render_html_file() { - # h/t Devin Teske - # TODO IMPROVE THIS IF POSSIBLE - awk -v title="${1}" -v brief="${2}" ' - { body = body "\n" $0 } - END { - body = substr(body, 2) - if (body ~ /<[Hh][Tt][Mm][Ll]/) { - print body - exit - } - if (match(body, /<[[:space:]]*[Hh]1(>|[[:space:]][^>]*>)/)) { - t = substr(body, RSTART + RLENGTH) - sub("<[[:space:]]*/[[:space:]]*[Hh]1.*", "", t) - gsub(/^[[:space:]]*|[[:space:]]$/, "", t) - if (t) title = t " — " title - } - n = split(ENVIRON["HEADER"], header, /\n/) - for (i = 1; i <= n; i++) { - if (match(tolower(header[i]), "")) { - head = substr(header[i], 1, RSTART - 1) - tail = substr(header[i], RSTART + RLENGTH) - print head "" tail - } else if (match(tolower(header[i]), "")) { - head = substr(header[i], 1, RSTART - 1) - tail = substr(header[i], RSTART + RLENGTH) - print head "" tail - } else if (match(tolower(header[i]), "")) { - head = substr(header[i], 1, RSTART - 1) - tail = substr(header[i], RSTART + RLENGTH) - print head "" title "" tail - } else if (match(tolower(header[i]), "")) { - head = substr(header[i], 1, RSTART - 1) - tail = substr(header[i], RSTART + RLENGTH) - print head "" tail - } else if (match(tolower(header[i]), "")) { - head = substr(header[i], 1, RSTART - 1) - tail = substr(header[i], RSTART + RLENGTH) - print head "" tail - } else if (match(tolower(header[i]), "")) { - head = substr(header[i], 1, RSTART - 1) - tail = substr(header[i], RSTART + RLENGTH) - print head "" tail - } else print header[i] - } - print body - print ENVIRON["FOOTER"] - }' -} - - -list_pages() { - e="\\( -name '*.html' -o -name '*.md' \\)" - cd "$1" && eval "find . -type f ! -path '*/.*' ! -path '*/_*' $IGNORE $e" | - sed 's#^./##;s#.md$#.html#;s#/index.html$#/#' -} - -render_sitemap() { - urls="$1" - base_url="$2" - date="$3" - - echo '' - echo '' - echo "$urls" | - sed -E 's#^(.*)$#'"$base_url"'/\1'\ -"$date"'1.0#' - echo '' -} - -main "$@" diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..54c6866 Binary files /dev/null and b/static/favicon.png differ diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 0000000..50a5bc5 --- /dev/null +++ b/templates/404.html @@ -0,0 +1,8 @@ +{% extends "terminimal/templates/404.html" %} + +{% block content %} +
+

{% block heading %}Perdu ?{% endblock heading %}

+

{% block message %}Cette page n'existe pas.{% endblock message %}

+
+{% endblock content %} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..dfc8aa1 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,56 @@ +{% extends "terminimal/templates/index.html" %} + +{% block content %} +
+ {%- if paginator %} + {%- set show_pages = paginator.pages -%} + {% else %} + {%- set show_pages = section.pages -%} + {% endif -%} + + {%- for page in show_pages %} +
+ {{ post_macros::header(page=page) }} + {{ post_macros::content(page=page, summary=true, show_only_description=page.extra.show_only_description | default(value=false)) }} +
+ {% endfor -%} + +
+{% endblock content %} + +{% block footer %} +
+ +
+{% endblock footer %} \ No newline at end of file diff --git a/templates/tags/list.html b/templates/tags/list.html new file mode 100644 index 0000000..4590e71 --- /dev/null +++ b/templates/tags/list.html @@ -0,0 +1,17 @@ +{% extends "terminimal/templates/tags/list.html" %} + +{% block content %} +
+

Liste des tags

+ + +
+{% endblock content %} diff --git a/templates/tags/single.html b/templates/tags/single.html new file mode 100644 index 0000000..d903c36 --- /dev/null +++ b/templates/tags/single.html @@ -0,0 +1,17 @@ +{% extends "terminimal/templates/tags/single.html" %} + + +{% block content %} +
+

+ tag: #{{ term.name }} + ({{ term.pages | length }} post{{ term.pages | length | pluralize }}) +

+ + + Voir tous les tags + + + {{ post_macros::list_posts(pages=term.pages) }} +
+{% endblock content %} diff --git a/themes/terminimal b/themes/terminimal new file mode 160000 index 0000000..0ced778 --- /dev/null +++ b/themes/terminimal @@ -0,0 +1 @@ +Subproject commit 0ced77898f37eb388181c4bdfa564febe437841e