diff --git a/src/assets/icons/chevron-right.svg b/src/assets/icons/chevron-right.svg new file mode 100644 index 0000000..d6c4b2b --- /dev/null +++ b/src/assets/icons/chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/TOC.astro b/src/components/TOC.astro new file mode 100644 index 0000000..c50ae14 --- /dev/null +++ b/src/components/TOC.astro @@ -0,0 +1,62 @@ +--- +import type { MarkdownHeading } from 'astro'; +import TOCItem from './TOCItem.astro'; + +interface Props { + headings: MarkdownHeading[]; +} + +const { headings } = Astro.props; + +export type NestedMarkdownHeading = { + slug: string; + text: string; + items?: NestedMarkdownHeading[]; +}; + +function toNestedHeadings(headings: MarkdownHeading[]): NestedMarkdownHeading[] { + const root: NestedMarkdownHeading[] = []; + const stack: { item: NestedMarkdownHeading; depth: number }[] = []; + + for (const heading of headings) { + const nestedHeading: NestedMarkdownHeading = { text: heading.text, slug: heading.slug }; + + // find the parent in the stack + while (stack.length > 0 && stack[stack.length - 1].depth >= heading.depth) { + stack.pop(); + } + + if (stack.length > 0) { + // add the current item to the parent's items + const parent = stack[stack.length - 1].item; + if (!parent.items) { + parent.items = []; + } + parent.items.push(nestedHeading); + } else { + // add to root + root.push(nestedHeading); + } + + // push the current item to the stack + stack.push({ item: nestedHeading, depth: heading.depth }); + } + + return root; +} + +const nestedHeadings = toNestedHeadings(headings.filter((h) => h.depth <= 3)); +--- + + + + diff --git a/src/components/TOCItem.astro b/src/components/TOCItem.astro new file mode 100644 index 0000000..74d3599 --- /dev/null +++ b/src/components/TOCItem.astro @@ -0,0 +1,159 @@ +--- +import type { NestedMarkdownHeading } from './TOC.astro'; +import ChevronRight from '@assets/icons/chevron-right.svg'; + +interface Props { + item: NestedMarkdownHeading; +} + +const { item } = Astro.props; +const hasSubItems = !!item.items?.length; +--- + +
  • + { + hasSubItems && ( +
    + + + {item.text} + + + {hasSubItems && ( + + )} +
    + ) + } + + {!hasSubItems && {item.text}} +
  • + + diff --git a/src/content/blog/uniten-internship/fr.mdx b/src/content/blog/uniten-internship/fr.mdx index 617e66c..0285ec7 100644 --- a/src/content/blog/uniten-internship/fr.mdx +++ b/src/content/blog/uniten-internship/fr.mdx @@ -31,32 +31,6 @@ Enfin, je remercie M. Brice Arnault de nous avoir enseigné les principes du dé Plus généralement, je remercie tout le corps enseignant du département informatique de l'IUT pour les cours dispensés, les connaissances qu'ils m'ont apporté et qui m'ont facilité l'insertion professionnelle. -## Table des matières - -- [Note de confidentialité](#note-de-confidentialite) -- [Remerciements](#remerciements) -- [Introduction](#introduction) -- [I. Présentation d'UNITEN](#i-présentation-duniten) - - [1. L'entreprise](#1-lentreprise) - - [2. Lieu et horaires de travail](#2-lieu-et-horaires-de-travail) - - [3. Environnement de travail](#3-environnement-de-travail) -- [II. Analyse des missions](#ii-analyse-des-missions) - - [1. Prise en main de FlutterFlow, outil low-code tout-en-un](#1-prise-en-main-de-flutterflow-outil-low-code-tout-en-un) - - [2. Récupération des communes via une API](#2-récupération-des-communes-via-une-api) - - [3. Recréation du système de design](#3-recréation-du-système-de-design) - - [4. Extraction des données clefs](#4-extraction-des-données-clefs) - - [5. Algorithme de classement et optimisation](#5-algorithme-de-classement-et-optimisation) -- [III. Méthodologie](#iii-méthodologie) - - [1. Démarche et choix](#1-démarche-et-choix) - - [2. Organisation](#2-organisation) - - [3. Outils utilisés](#3-outils-utilisés) -- [IV. Résultats et bilan](#iv-résultats-et-bilan) - - [1. Bilan professionnel](#1-bilan-professionnel) - - [2. Bilan personnel](#2-bilan-personnel) - - [3. Bilan de mon maître de stage sur FlutterFlow](#3-bilan-de-mon-maître-de-stage-sur-flutterflow) -- [Conclusion](#conclusion) -- [Glossaire et sitographie](#glossaire-et-sitographie) - ## Introduction Entrepreneur et joueur de tennis, M. Martin PASQUIER a eu l'idée de réaliser une application mobile pour faciliter la recherche et le partage de sessions de tennis aux joueurs de la France entière. Souhaitant déployer son idée plus rapidement et n'ayant pas toutes les connaissances techniques nécessaires, il cherchait des stagiaires pour réaliser intégralement cette application en moins de 8 semaines. @@ -377,86 +351,86 @@ Mon maître de stage, M. PASQUIER, m'a toujours écouté avec bienveillance, et ## Glossaire et sitographie -### FlutterFlow +#### FlutterFlow Logiciel fondé par deux ex-ingénieurs chez Google permettant de concevoir des applications mobile grâce à un éditeur visuel, intégrant des passerelles pour utiliser du code Dart (language de programmation). - https://www.flutterflow.io (site en anglais) -### Flutter +#### Flutter Une infrastructure logicielle permettant le codage d'applications multiplateformes (iOS, Android, Web, Linux, macOS et Windows) à partir d'une base de code [Dart](#dart). - https://flutter.dev (site en anglais) - https://aws.amazon.com/fr/what-is/flutter -### Dart +#### Dart Un langage de programmation développé par Google et optimisé pour créer des applications multiplateformes. Du code Dart peut être compilé (transformé) en du code JavaScript pour l'exécution sur le web, mais s'utilise surtout dans le cadre du développement d'applications avec Flutter. - https://dart.dev (site en anglais) -### Supabase +#### Supabase Service open-source fondé sur la base de données PostgreSQL, offrant depuis une interface web la gestion d'une base de données relationnelle, de l'authentification d'utilisateurs, d'un système de stockage et d'[edge functions](#edge-function). Une version hébergée freemium est proposée pour les entreprises. - https://supabase.com (site en anglais) -### Firebase +#### Firebase Service similaire à [Supabase](#supabase) créé avant lui par Google, en source fermée et fondé sur une base de données orientée documents. - https://firebase.google.com (site en anglais) - https://fr.wikipedia.org/wiki/Base_de_donn%C3%A9es_orient%C3%A9e_documents -### Edge function +#### Edge function Une "serverless function" est généralement défini comme un script synchrone exécuté sur un serveur. Il a une limite de temps d'exécution, ne persiste aucun état (stateless) et est invoqué à la demande (cold start). L'implémentation la plus connue est AWS Lambda. Le terme "edge function" désigne une serverless function qui s'exécute sur le serveur le plus proche de l'utilisateur disponible. - https://aws.amazon.com/fr/lambda -### Figma +#### Figma Outil de conception graphique et de prototypage collaboratif, permettant de créer des interfaces au niveau de maquette basique comme de prototype interactif avancé. - https://www.figma.com/fr-fr/design -### La Tchatche +#### La Tchatche Projet universitaire en R4.A.10 (complément web) de messagerie instantanée réalisée par mes soins en PHP. Une [API](#api-rest) pour accéder à la messagerie a ensuite été conçue et a permis l'existence de La Tchatche Mobile, un client mobile élaboré par Adam et moi en Flutter pour le projet de R4.A.11 (développement mobile). - https://latchatche.clembs.com -### VSCodium +#### VSCodium Éditeur de code open-source basé sur le très populaire Visual Studio Code de Microsoft sans les dépendances Microsoft et en réimplémentant certaines fonctionnalités propriétaires. - https://vscodium.com (site en anglais) -### Bun +#### Bun Système d'outillage complet pour exécuter du code JavaScript et [TypeScript](#typescript) sur un serveur. Il comprend notamment un environnement d'exécution, de tests unitaires, un débogueur, un serveur HTTP. https://bun.sh (site en anglais) -### TypeScript +#### TypeScript Langage de programmation développé par Microsoft qui complète le langage JavaScript avec un système de typage et de détection de types. - https://www.typescriptlang.org (site en anglais). -### API REST +#### API REST Ensemble de règles permettant à un service de rendre certaines données accessibles et modifiables à des ordinateurs tiers via Internet, organisée par ressources et entités. Par exemple, l'[API Sirene](https://api.gouv.fr/guides/api-definition) de l'État permet à n'importe quel ordinateur de faire une recherche sur les entreprises françaises. - https://api.gouv.fr/guides/api-definition - https://fr.wikipedia.org/wiki/Interface_de_programmation -### Puppeteer +#### Puppeteer Outil de scraping en JavaScript qui permet de lancer un navigateur invisible (headless) et de le contrôler de manière programmée. - https://pptr.dev (site en anglais) -### Refactorisation +#### Refactorisation Refactoring en anglais, c'est une pratique qui consiste à remanier un morceau de code afin de le rendre plus lisible et optimisé. diff --git a/src/i18n/langs/en.ts b/src/i18n/langs/en.ts index 8040e59..5833c11 100644 --- a/src/i18n/langs/en.ts +++ b/src/i18n/langs/en.ts @@ -77,6 +77,7 @@ export default { 'blog.edited_on': 'Edited on', 'blog.warning_unlocalized': 'You are reading the original version of this article, as it was not adapted to English. Sorry for the inconvenience.', + 'blog.toc': 'Table of contents', /* PROJECTS */ 'projects.uniten.title': 'UNITEN', diff --git a/src/i18n/langs/fr.ts b/src/i18n/langs/fr.ts index d97ff2c..96fd091 100644 --- a/src/i18n/langs/fr.ts +++ b/src/i18n/langs/fr.ts @@ -79,6 +79,7 @@ export const fr: typeof en = { 'blog.edited_on': 'Édité le', 'blog.warning_unlocalized': "Vous lisez cet article dans sa version originale, car il n'a pas été traduit en français. Désolé pour la gêne occasionnée.", + 'blog.toc': 'Table des matières', /* PROJECTS */ 'projects.uniten.title': 'UNITEN', diff --git a/src/layouts/Blog.astro b/src/layouts/Blog.astro index e9bc8d4..779231b 100644 --- a/src/layouts/Blog.astro +++ b/src/layouts/Blog.astro @@ -6,8 +6,9 @@ import '../styles/blog.scss'; import Layout from './Layout.astro'; import { Image } from 'astro:assets'; import { getLocaleFromUrl, getPostSlug, useTranslations } from '@i18n'; -import type { CollectionEntry } from 'astro:content'; +import { render, type CollectionEntry } from 'astro:content'; import ShareDialog from '@components/ShareDialog.astro'; +import TOC from '@components/TOC.astro'; type Props = { post: CollectionEntry<'blog'>; @@ -22,6 +23,8 @@ const slug = getPostSlug(post.id); const lang = getLocaleFromUrl(Astro.url); const t = useTranslations(lang); + +const { headings } = await render(post); ---