#!/usr/bin/env bash set -euo pipefail # ============================================================ # new-marp-project.sh — crée un nouveau projet Marp prêt à l'emploi. # # Usage : # ./new-marp-project.sh slides # diaporama 16:9 (thème custom) # ./new-marp-project.sh a4 # document A4 (thème custom-a4) # ./new-marp-project.sh # mode interactif # ./new-marp-project.sh --help # ============================================================ usage() { sed -n 's/^# \+//p' "$0" | sed -n '2,8p' exit "${1:-0}" } # --- Arguments ---------------------------------------------------- if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then usage 0 fi if [ $# -eq 2 ]; then TYPE="$1" DIR="$2" elif [ $# -eq 0 ]; then read -rp "Type de projet (slides/a4) : " TYPE read -rp "Nom du dossier : " DIR else usage 1 fi case "$TYPE" in slides|a4) ;; *) echo "Type invalide : attendu 'slides' ou 'a4'."; usage 1 ;; esac # --- Sécurités ---------------------------------------------------- if [ -z "$DIR" ]; then echo "Nom du dossier manquant."; exit 1 fi if [ -e "$DIR" ] && [ -n "$(ls -A "$DIR" 2>/dev/null)" ]; then echo "ERREUR : le dossier '$DIR' existe déjà et n'est pas vide."; exit 1 fi mkdir -p "$DIR/.vscode" echo "Création du projet '$TYPE' dans '$DIR'..." # ============================================================ # 1. Configuration commune (Marp CLI + extension VS Code) # ============================================================ if [ "$TYPE" = "slides" ]; then cat > "$DIR/.marprc.json" <<'EOF' { "themeSet": [".vscode/custom.css"] } EOF cat > "$DIR/.vscode/settings.json" <<'EOF' { "markdown.marp.themes": [".vscode/custom.css"] } EOF else cat > "$DIR/.marprc.json" <<'EOF' { "themeSet": [".vscode/custom.css", ".vscode/custom-a4.css"] } EOF cat > "$DIR/.vscode/settings.json" <<'EOF' { "markdown.marp.themes": [".vscode/custom.css", ".vscode/custom-a4.css"] } EOF fi # ============================================================ # 2. Thème commun custom.css # ============================================================ cat > "$DIR/.vscode/custom.css" <<'EOF' /* @theme custom * * Surcharge du thème "default" de Marp. * Le thème par défaut est importé puis adapté. * * Toutes les couleurs / valeurs sont centralisées dans les variables * :root pour faciliter les modifications. * * Sommaire * --------- * 1. Design tokens (:root) — couleurs, typo, bordures * 2. Base — section, titres, liens, strong, blockquote * 3. Layout de section — variante .nolead * 4. Header / Footer / Pages — en-tête, pied de page, pagination * 5. Tableaux — table, th, td, zebra, cas .two-cols * 6. Colonnes (grid) — .columns / .cols-N * 7. Impression — @media print */ @import "default"; /* ================================================================== * 1. Design tokens — toutes les valeurs modifiables du thème * ================================================================== */ :root { /* --- Couleurs principales --- */ --color-bg: #ffffff; /* fond des diapos */ --color-text: #1f2328; /* texte principal */ --color-primary: #0969da; /* titres, liens, tableaux */ --color-accent: #cf222e; /* strong, code */ --color-muted: #6e7781; /* header, footer, numérotation */ --color-border: #d0d7de; /* bordures */ --color-bg-soft: #f6f8fa; /* fonds secondaires (blockquote, pre, zebra) */ --color-code-bg: #eeeeee; /* fond du code inline */ /* --- Typographie --- */ --font-family: "Segoe UI", Arial, sans-serif; --font-size-small: 0.8em; --font-size-medium: 0.9em; /* --- Bordures & arrondis --- */ --radius: 6px; --border-width-thick: 4px; --border-width-thin: 1px; } /* ================================================================== * 2. Base — styles globaux de la diapo * ================================================================== */ section { background: var(--color-bg); color: var(--color-text); font-family: var(--font-family); } h1 { color: var(--color-primary); padding-bottom: 0.2em; } h2, h3 { color: var(--color-text); } strong { color: var(--color-accent); } a { color: var(--color-primary); } blockquote { border-left: var(--border-width-thick) solid var(--color-primary); background: var(--color-bg-soft); padding: 0.5em 1em; border-radius: var(--radius); } /* ================================================================== * 3. Layout de section — variante .nolead * (contenu aligné en haut à gauche, sans la mise en page centrée * par défaut de Marp) * ================================================================== */ section.nolead { display: flex; flex-direction: column; justify-content: flex-start; text-align: left; } /* ================================================================== * 4. Header / Footer / Pagination * ================================================================== */ /* En-tête / pied de page définis dans le front-matter */ header { color: var(--color-muted); font-size: var(--font-size-small); border-bottom: var(--border-width-thin) solid var(--color-border); } footer { color: var(--color-muted); font-size: var(--font-size-medium); } /* Numérotation de page */ section::after { color: var(--color-muted); } /* ================================================================== * 5. Tableaux * ================================================================== */ table { display: table; /* la base GFM impose display:block, ce qui ignore les largeurs de colonnes */ border-collapse: collapse; width: 100%; } th, td { border: var(--border-width-thin) solid var(--color-border); padding: 0.4em 0.8em; } th { background: var(--color-primary); color: var(--color-bg); } /* Lignes impaires sur fond neutre (effet "zebra") */ tr:nth-child(even) td { background: var(--color-bg-soft); } /* --- Variante .two-cols : tableau 2 colonnes verticales (gauche / droite) --- */ section.two-cols table { display: table; /* la base GFM impose display:block, ce qui ignore les largeurs de colonnes */ width: 100%; table-layout: fixed; /* 2 colonnes égales (50/50) au lieu de l'auto */ border-collapse: collapse; } section.two-cols th, section.two-cols td { vertical-align: top; /* contenu aligné en haut, façon listes */ text-align: left; padding: 0.6em 1em; } /* Séparateur vertical entre les 2 colonnes */ section.two-cols th:first-child, section.two-cols td:first-child { border-right: var(--border-width-thin) solid var(--color-border); } /* ================================================================== * 6. Colonnes verticales — .columns + .cols-N (display: grid) * ================================================================== */ section .columns { display: grid; gap: 0 2em; } section .columns.cols-2 { grid-template-columns: repeat(2, 1fr); } section .columns.cols-3 { grid-template-columns: repeat(3, 1fr); } section .columns.cols-4 { grid-template-columns: repeat(4, 1fr); } section .columns > div { min-width: 0; /* permet au contenu (pre, code, tableaux) de rester dans sa colonne */ padding: 0.6em 1em; } /* Séparateur vertical entre les colonnes */ section .columns > div + div { border-left: var(--border-width-thin) solid var(--color-border); } /* ================================================================== * 7. Impression / export PDF — conserver les couleurs * ================================================================== */ @media print { section { background: var(--color-bg); } } EOF # ============================================================ # 3. Fichiers spécifiques au type A4 # ============================================================ if [ "$TYPE" = "a4" ]; then cat > "$DIR/.vscode/custom-a4.css" <<'EOF' /* @theme custom-a4 * * Variante du thème "custom" adaptée au format A4 (portrait). * Destinée aux exports PDF / DOCX, elle reprend intégralement les * règles du thème "custom" et n'adapte que la taille de page et * les marges. * * Le thème de base est importé via @import, puis surchargé : inutile * de dupliquer les styles, toute modification de "custom" se * répercute automatiquement ici. * * Sommaire * -------- * 1. Page A4 — taille, marges et corps de texte de la diapo * 2. Typographie — tailles des titres pour un document * 3. Impression / export PDF — réglages @page */ @import "custom"; /* ================================================================== * 1. Page A4 — taille de la diapo en unités absolues * * Marpit utilise la taille des
(ou :root) comme taille de * page pour le PDF exporté. Le format A4 standard fait 210 x 297 mm. * La taille de diapo est fixée dans le thème : il n'est pas possible * de la modifier via une classe ou une directive locale. * ================================================================== */ section { width: 210mm; /* ~794 px */ height: 297mm; /* ~1123 px */ /* Marges "papier" plus généreuses que le défaut du thème "default" * (~78px), pour un rendu proche d'un document imprimé. */ padding: 20mm 22mm; /* Corps de texte type document imprimé. * Le thème "default" (conçu pour des diapos 1280x720) impose 29px, * beaucoup trop grand une fois la page passée au format A4. */ font-size: 11pt; /* ~14.7 px — texte courant */ line-height: 1.4; } /* ================================================================== * 2. Typographie — tailles des titres pour un document A4 * (valeurs exprimées en em, relatives au corps de texte ci-dessus) * ================================================================== */ h1 { font-size: 1.45em; /* ~16 pt */ } h2 { font-size: 1.25em; /* ~13.8 pt */ } h3 { font-size: 1.1em; /* ~12 pt */ } h4 { font-size: 1em; /* ~11 pt */ } /* ================================================================== * 3. Impression / export PDF — réglages @page * * Assure une page A4 exacte (sans marges navigateur supplémentaires) * lors de l'export PDF via Marp CLI. La largeur/hauteur des sections * définie ci-dessus reste la source de vérité du format. * ================================================================== */ @page { size: A4 portrait; margin: 0; } EOF cat > "$DIR/pandoc-strip-hr.lua" <<'EOF' -- ================================================================== -- pandoc-strip-hr.lua -- -- Filtre pandoc : supprime les filets horizontaux (---, ***) lors de -- la conversion vers DOCX. -- -- Dans un projet Marp, les "---" servent à séparer les diapos : en -- les convertissant avec pandoc, ils apparaissent comme des traits -- horizontaux inutiles dans le document Word. Ce filtre les retire. -- -- Usage : -- pandoc document.md --lua-filter=pandoc-strip-hr.lua -o document.docx -- ================================================================== function HorizontalRule() return {} end EOF fi # ============================================================ # 4. Fichier de départ (le front-matter choisit déjà le thème) # ============================================================ if [ "$TYPE" = "slides" ]; then cat > "$DIR/slides.md" <<'EOF' --- marp: true theme: custom paginate: true header: "Mon header" footer: "Mon footer" class: nolead --- # Bienvenue ## Nouveau diaporama Ceci est la première diapo de votre nouveau projet. --- # Une nouvelle diapo - Item 1 - Item 2 EOF else cat > "$DIR/document.md" <<'EOF' --- marp: true theme: custom-a4 paginate: true header: "Mon header" footer: "Mon footer" class: nolead --- # Titre du document A4 ## Sous-titre Corps de texte du document. Chaque bloc `---` devient une nouvelle page A4. --- # Deuxième page Contenu de la deuxième page. EOF fi chmod -R u+rw "$DIR" # ============================================================ # 5. Récapitulatif et commandes d'export # ============================================================ echo echo "Projet '$TYPE' créé dans '$DIR' :" find "$DIR" -type f | sort | sed 's/^/ /' echo if [ "$TYPE" = "slides" ]; then echo "Exports :" echo " npx @marp-team/marp-cli $DIR/slides.md --pdf" echo " npx @marp-team/marp-cli $DIR/slides.md --pptx" else echo "Exports :" echo " npx @marp-team/marp-cli $DIR/document.md --pdf" echo " pandoc $DIR/document.md --lua-filter=$DIR/pandoc-strip-hr.lua -o $DIR/document.docx" fi echo echo "Préview VS Code : ouvrir $DIR/slides.md et lancer le preview Marp."