commit 95b226f6599df1ba343079ea608c8d208e110fe5 Author: Alexis Lahouze Date: Sat Feb 7 10:51:00 2026 +0100 Initialisation du dépôt. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..46b1ec7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +tags + +*.odt +!reference.odt + +docs/* +!docs/Makefile + +filters/* +!filters/Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6b70ee0 --- /dev/null +++ b/Makefile @@ -0,0 +1,51 @@ +# Nécessaire pour avoir les dépendances dans le répertoire lié à l'article. +.SECONDEXPANSION: + +# Un article par fichier .md. +ARTICLES=$(wildcard *.md) + +# Tâche par défaut. +all: $(patsubst %.md,%.odt,$(ARTICLES)) docs/all +.DEFAULT_GOAL:=all + +# Tâches virtuelles. +.PHONY: all docs/all src/all clean docs/clean filters/clean src/clean filters/diamond + +# Tâches liées à la doc. +docs/clean: + $(MAKE) -C docs clean + +docs/all: + $(MAKE) -C docs all + +# Tâche de nettoyage des sources. +src/clean: + $(MAKE) -C src clean + +# Tâche de génération du filtre. +filters/diamond: + $(MAKE) -C filters diamond + +# Tâche générique pour un article. +ARTICLE_DEPS=$(wildcard $*/*) + +%.odt: %.md filters/diamond reference.odt templates/diamond.opendocument $$(ARTICLE_DEPS) + echo $^ + pandoc \ + $< \ + --data-dir=. \ + --filter=diamond \ + --template=diamond.opendocument \ + --output=$@ + +%.unfiltered.json: %.md $$(ARTICLE_DEPS) + pandoc \ + $< \ + -t json \ + --outpur=$@ + +# Nettoyage. +clean: docs/clean filters/clean src/clean + rm -f $(patsubst %.md,%.odt,$(ARTICLES)) + +# vim: set tw=80 ts=4 sw=4 sts=4 spelllang=fr: diff --git a/README.md b/README.md new file mode 100644 index 0000000..79cf1ba --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Génération article GLMF avec pandoc + +## Dépendances + +La construction nécessite Haskell et la bibliothèque Pandoc. + +Sous Debian, voici la liste des paquets à installer : + + - haskell + - libghc-pandoc-dev + +## Métadonnées + +Le template utilise les métadonnées suivantes : + + - titre: Titre de l'article + - auteur_nom: Nom de l'auteur + - auteur_description: Description de l'auteur + - editeur_nom: Nom de l'éditeur + - editeur_description: Description de l'éditeur + - chapeau: Chapeau + - mots_cles: Liste de mots clés + +## Construction du document + +Pour construire le document, il faut utiliser la commande : + +``` +pandoc monarticle.md \ + --filter=diamond.hs \ + --template=diamond.opendocument \ + --reference-doc=../guide-auteurs/diamond.ott \ + --output=monarticle.odt +``` + + + + diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..669393f --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,27 @@ + +# Tâche par défaut. +.DEFAULT_GOAL:=all +all: index.html + +.PHONY: all clean + +# Fichiers sources. +HS_FILES=$(wildcard ../src/*.hs) + +# Interfaces. +HI_BASE=$(wildcard /usr/lib/ghc-doc/haddock/ghc/base-*/base.haddock) +HI_PANDOC_TYPES=$(wildcard /usr/lib/ghc-doc/haddock/pandoc-types-*/pandoc-types.haddock) + +# Construction de la documentation. +index.html: ../src/diamond.hs $(HS_FILES) + haddock \ + --read-interface=https://hackage.haskell.org/package/base/docs,$(HI_BASE) \ + --read-interface=https://hackage.haskell.org/package/pandoc-types/docs/,$(HI_PANDOC_TYPES) \ + --source-base=../src \ + --odir . --html $^ + +# Nettoyage. +clean: + rm -f *.html *.css *.js *.json *.png + +# vim: set tw=80 ts=4 sw=4 sts=4 spelllang=fr: diff --git a/filters/Makefile b/filters/Makefile new file mode 100644 index 0000000..458fd14 --- /dev/null +++ b/filters/Makefile @@ -0,0 +1,16 @@ +# Tâche par défaut. +all: diamond +.DEFAULT_GOAL:=all + +# Tâches virtuelles. +.PHONY: all diamond clean + +# Construction du filtre diamond. +diamond: + $(MAKE) -C ../src ../filters/diamond + +# Nettoyage. +clean: + rm -f diamond + +# vim: set tw=80 ts=4 sw=4 sts=4 spelllang=fr: diff --git a/modele-article.md b/modele-article.md new file mode 100644 index 0000000..781879d --- /dev/null +++ b/modele-article.md @@ -0,0 +1,207 @@ +--- +titre: Titre de l'article +auteurs: + - nom: Prénom et Nom + description: Fonction ou métier et/ou contribution à des projets. Adresse e-mail si vous le souhaitez. + - nom: Denis Bodor + description: Chef des rédactions – dbodor@ed-diamond.com +mots_cles_entete: |- + Vous devez lister ici les mots-clés définissant votre article de la manière + suivante, exemple : +mots_cles: + - MALWARE + - PENTEST + - ANALYSE FORENSIQUE + - EXPLOIT + - RÉSEAU + - CYBERCRIMINALITÉ +chapeau: > + Ceci est le chapeau de l'article. Il s'agit d'une courte introduction au + sujet ou à la problématique. Essayez d'être explicite et de donner envie au + lecteur de poursuivre la lecture de l'article. +... +Votre article peut commencer par une introduction (attention, celle-ci ne doit +en principe pas être numérotée). + +Plutôt que de parler des outils les plus fréquemment utilisés, nous nous sommes +en partie concentrés ici sur des outils moins courants, et rarement abordés +dans les colonnes de *MISC* / *GNU/Linux Magazine* / *SysOps Pratique* / +*Hackable* (Attention ! Cet italique est généré par le style de caractère +« italic » et non par l'icône italique de LibreOffice, idem pour le gras) ou des +autres magazines spécialisés. + +# 1. Titre de niveau 1 + +Paragraphe en style « Normal » (et non « Standard » ou « Corps de texte »). +``` +# Ceci est du code +# Une entrée typique de menu.lst +# Le style employé est « code » +title= DEBIAN GNU/Linux 2.6.24 (hdc3 - ext3) +kernel= (hd1,2)/boot/vmlinuz-2.6.24-1-686 root=/dev/hdc3 vga=extended +initusrd (hd1,2)/boot/initrd.img-2.6.24-1-686 +``` + +Paragraphe en « Normal ». On fait ici mention d'un élément de la configuration : +l'étiquette `title` (style de caractère « code_par » pour du code dans du +texte) permet d'ajouter un titre dans les menus de GRUB. La commande +`grub-install` permet l'installation du *bootloader*. Nous pouvons spécifier +le mode graphique à utiliser avec l'option `vga` : + +``` +01: # Une entrée typique de menu.lst +02: title= DEBIAN GNU/Linux 2.6.24 (hdc3 - ext3) +03: kernel= (hd1,2)/boot/vmlinuz-2.6.24-1-686 root=/dev/hdc3 **vga=extended** +04: initrd (hd1,2)/boot/initrd.img-2.6.24-1-686 +``` +Si vous souhaitez faire référence à des lignes de code pour les expliquer, vous +pouvez les numéroter comme dans le code ci-dessus. Pour mettre en avant un +passage du code, utilisez le style « code_em » comme on l’a fait ci-dessus pour +« vga-extended ». + +:::pao +Vous pouvez mentionner de cette manière les éventuelles informations à indiquer +à la rédaction ou au service de mise en page. Cette mention n'apparaîtra pas +dans l'article final. +::: + +Le second thème de ce dossier explore l’audit des applications à la découverte +de failles de sécurité. Il s’ouvre avec un article sur **American Fuzzy Lop** +(Attention, le « gras » est généré par le style de caractère « gras » et non par +l'icône gras de LibreOffice), un outil de fuzzing cherchant à couvrir le maximum +de code du programme audité en analysant son graphe d’exécution. + +:::note +Le texte présent ici, rédigé en style « Note », apparaîtra dans l'article final +dans une boîte spéciale « note ». Vous pourrez ainsi présenter des informations +complémentaires. +::: + +Les indications en style « pragma », comme ci-dessus, doivent toujours être +encadrées de 3 slashs /// … ///. + +Si vous souhaitez une note ayant un titre spécifique, par exemple : +« Attention », il faut utiliser : + +:::attention +Le texte présent ici, rédigé en style « Note », apparaîtra dans l'article final +dans une boîte spéciale « Attention ». Vous pouvez par ce biais donner un titre +à vos encarts de notes. +::: + +Les sessions de commandes interactives sont à utiliser avec le style de +paragraphe « console ». On peut également ici mettre en évidence certaines +parties, grâce au style de caractère « code_em » : + +| $ cat dma +| 2: floppy +| 3: **parport0** # mise en évidence avec **code_em** +| 4: cascade + +Plus d'informations sur nos magazines sur : +(notez l'utilisation du style de caractère « url » et la désactivation de +l'hyperlien). + +Vous pouvez également insérer des listes à puces ou numérotées +dans votre article, comme ceci : + + - item 1 ; + - item 2 ; + - item 3 ; + - etc. + +Notez que nous n'utilisons pas les puces/numérotations automatiques de +LibreOffice. + +De même, les tableaux doivent être présentés le plus simplement possible, le +contenu doit être en style « Normal », par exemple : + +blabla | blabla | blabla +-------+--------+------- +blabla | blabla | blabla + +Les références, à placer entre crochets et à mettre en style « ref_par», doivent +être intégrées dans le discours du texte et leur étiquette sera un nombre OU un +mot-clé. Exemple : + +Vous trouverez tous les sommaires des derniers numéros publiés sur la base +documentaire des Éditions Diamond [^BASEDOC]. + +OU + +Enfin, des infrastructures dédiées sont parfois mises en place pour chacune des +cibles comme l'a décrit cet article [^1]. Vous trouverez également des +informations supplémentaires sur le sujet dans cet ouvrage [^2]. + +C'est seulement lorsqu'une citation apparaît dans le texte qu'elle peut être +développée dans la section « Références » en fin d'article. Dans cette section, +on lui applique alors le style « ref_cible » (voir en bas de l’article). + +N'intégrez pas vos images dans le fichier LibreOffice, mais faites-en mention +avec le style « pragma ». Vous pouvez faire référence à une figure dans le +texte : comme on peut le voir en figure 1... ou encore (voir figure 1). + +![figure_01](nom_article_figure_01.png "Exemple d'écran de démarrage GRUB. Une légende peut être une simple phrase ou même la mention du numéro de figure. Le style utilisé pour une légende.... est « legende ».") + +Lorsqu'on décrit une interface graphique ou texte, il est possible de faire +référence aux menus et options avec le style de caractères « menu ». Exemple : +Cochez l'option [Auto-connexion]{.menu} dans la fenêtre des options qui apparaît via le +menu [Fichier > Préférences]{.menu}. + +Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla +blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla +bla bla blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla +blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla blabla. Bla +blabla bla blabla, bla bla bla blabla. + +## 1.1 Titre de niveau 2 + +Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla +blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla +bla bla blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla +blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla blabla. Bla +blabla bla blabla, bla bla bla blabla. + +Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla +blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla +bla bla blabla. + +### 1.1.1 Titre de niveau 3 + +Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla +blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla +bla bla blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla +blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla blabla. Bla +blabla bla blabla, bla bla bla blabla. + +Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla +blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla +bla bla blabla. + +#### 1.1.1.1 Titre de niveau 4 + +Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla +blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla +bla bla blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla +blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla blabla. Bla +blabla bla blabla, bla bla bla blabla. + +Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla bla bla +blabla. Bla blabla bla blabla, bla bla bla blabla. Bla blabla bla blabla, bla +bla bla blabla. + +# Conclusion + +La conclusion de l'article ne comporte pas de numérotation. + +# Remerciements + +Si vous souhaitez ajouter des remerciements à votre article, cette partie pourra +être ajoutée à cet endroit et présentée de cette manière. + +[^BASEDOC]: Base documentaire des Éditions Diamond : +[https://connect.ed-diamond.com/](https://connect.ed-diamond.com/) +[^1]: P. Nom, « Titre de l'article », *MISC n°118*, novembre-décembre 2021 +[^2]: P. Nom et P. Autre-nom, « Titre livre », éditeur, année + + diff --git a/reference.odt b/reference.odt new file mode 100644 index 0000000..0f29ad7 Binary files /dev/null and b/reference.odt differ diff --git a/src/Blocks.hi b/src/Blocks.hi new file mode 100644 index 0000000..4d6e44a Binary files /dev/null and b/src/Blocks.hi differ diff --git a/src/Blocks.hs b/src/Blocks.hs new file mode 100644 index 0000000..bc3a253 --- /dev/null +++ b/src/Blocks.hs @@ -0,0 +1,126 @@ +{- | + Module : Blocks + Description : Ce module contient les fonctions nécessaires au traitement des blocks. +-} +module Blocks (topLvlBlock) where + +import Inlines + +import Data.List +import Data.Maybe +import Data.Text +-- +import Text.Pandoc.Definition +import Text.Pandoc.Builder +import Text.Pandoc.Walk + +-- Construit une structure d'attributs de Div à partir du nom du style. +styleDivAttr :: Maybe String -> Attr +styleDivAttr Nothing = styleDivAttr . Just $ "Normal" +styleDivAttr (Just "") = (pack "", [], []) +styleDivAttr (Just style) = (pack "", [], [(pack "custom-style", pack style)]) + +topLvlBlock :: Block -> Blocks + +-- Traite un block Para (paragraphe). +topLvlBlock (Para inlines) = + divWith + (styleDivAttr Nothing) + (para . mconcat $ inline <$> inlines) + +-- Traite un block Header (titre). +topLvlBlock (Header level attributes inlines) = + headerWith attributes level $ fromList inlines + +-- Transforme un CodeBlock en bloc avec le style "code". +topLvlBlock (CodeBlock _ txt) = + mconcat $ codeBlockLine <$> Data.Text.lines txt + where + codeBlockLine :: Text -> Blocks + codeBlockLine txt = + divWith + (styleDivAttr $ Just "code") + (para . mconcat $ codeEmInline <$> (toList . text $ txt)) + +-- Traite un block Div. +topLvlBlock (Div (identifier, classes, pairs) blocks) + -- Note "PAO" + | pack "pao" `Prelude.elem` classes = + noteBlock + (Just "Début note PAO") + (fromList blocks) + (Just "Fin note PAO") + (Just "Normal") + | pack "note" `Prelude.elem` classes = + noteBlock + (Just $ "Début note") + (fromList blocks) + (Just "Fin note") + (Just "note") + -- Note "Attention" + | Data.List.length classes > 0 = + noteBlock + (Just $ "Début note : " ++ (unpack . toTitle . Data.Text.unwords $ classes)) + (fromList blocks) + (Just "Fin note") + (Just "note") + where + --- Note générique. + noteBlock :: Maybe String -> Blocks -> Maybe String -> Maybe String -> Blocks + noteBlock header blocks footer style = + (pragma . pack $ "/// " ++ fromJust header ++ " ///") + <> (divWith (styleDivAttr style) blocks) + <> (pragma . pack $ "/// " ++ fromJust footer ++ " ///") + -- Block "pragma". + pragma :: Text -> Blocks + pragma txt = + divWith + (styleDivAttr $ Just "pragma") + (para . Text.Pandoc.Builder.singleton $ Str txt) + +-- Transforme un LineBlock avec un seul Div en block avec le style "console". +topLvlBlock (LineBlock inlines) = + divWith + (styleDivAttr $ Just "console") + (mconcat $ lineBlockLine <$> inlines) + where + lineBlockLine :: [Inline] -> Blocks + lineBlockLine inlines = para . mconcat $ codeEmInline <$> inlines + +-- Traite un block BulletList (list à puces). +topLvlBlock (BulletList blocks) = + mconcat $ bulletListItem <$> blocks + where + -- Traite un élément de liste. + -- Note : on traite ici le cas simple. Ça plantera probablement si on met du + -- code ou autre dans un élémente de liste. + bulletListItem :: [Block] -> Blocks + bulletListItem (first:others) = + divWith + (styleDivAttr $ Just "Normal") + (firstBlock first <> fromList others) + where + firstBlock :: Block -> Blocks + firstBlock (Plain inlines) = + para + $ (Text.Pandoc.Builder.singleton . Str $ pack "- ") + <> mconcat (inline <$> inlines) + +-- TODO Alexis Lahouze 2025-09-30 Tables +topLvlBlock (Table attributes caption columns header body footer) = + tableWith attributes caption columns header body footer + +topLvlBlock (Figure attributes caption blocks) = + fromList [Figure attributes caption blocks] + +-- Ignore les blocs HTML bruts. +topLvlBlock (RawBlock (Format format) text) = fromList [] + + +-- Transforme un BlockQuote en bloc avec le style "console" +--diamond (BlockQuote block) = styleBlock block "console" +--topLvlBlock (BlockQuote blocks) = blockQuote . fromList $ blocks + +-- TODO Alexis Lahouze 2025-09-30 Références + +--topLvlBlock block = Text.Pandoc.Builder.singleton block diff --git a/src/Blocks.o b/src/Blocks.o new file mode 100644 index 0000000..9c13754 Binary files /dev/null and b/src/Blocks.o differ diff --git a/src/Inlines.hi b/src/Inlines.hi new file mode 100644 index 0000000..31f9635 Binary files /dev/null and b/src/Inlines.hi differ diff --git a/src/Inlines.hs b/src/Inlines.hs new file mode 100644 index 0000000..d964156 --- /dev/null +++ b/src/Inlines.hs @@ -0,0 +1,60 @@ +module Inlines + ( styleInlines + , codeEmInline + , inline + ) where + +import Data.List +import Data.Maybe +import Data.Text + +import Text.Pandoc.Definition +import Text.Pandoc.Builder + +-- Génère une structure d'attributs de Spam à partir du nom du style. +styleSpanAttr :: Maybe String -> Attr +styleSpanAttr Nothing = styleSpanAttr $ Just "" +styleSpanAttr (Just "") = (pack "", [], []) +styleSpanAttr (Just style) = (pack "", [], [(pack "custom-style", pack style)]) + +-- Applique le style ODT à une liste d'Inline. +styleInlines :: Inlines -> Maybe String -> Inlines +-- Intègre la liste d'Inline dans un paragraphe. +styleInlines inlines style = spanWith (styleSpanAttr style) inlines + + +codeEmInline :: Inline -> Inlines +codeEmInline (Emph inlines) = + spanWith (styleSpanAttr $ Just "code_em") $ fromList inlines +codeEmInline (Strong inlines) = + spanWith (styleSpanAttr $ Just "code_em") $ fromList inlines +codeEmInline (Str txt) = + codeEmStr txt + where + codeEmStr :: Text -> Inlines + codeEmStr txt + | isJust strippedSuffix && isJust stripped = + codeEmInline $ Emph [Str . fromJust $ stripped] + | otherwise = text txt + where + strippedSuffix = Data.Text.stripSuffix (pack "**") txt + stripped = Data.Text.stripPrefix (pack "**") $ fromJust strippedSuffix +codeEmInline txt = Text.Pandoc.Builder.singleton txt + +inline :: Inline -> Inlines +inline (Emph inlines) = + spanWith (styleSpanAttr $ Just "italic") $ fromList inlines +inline (Strong inlines) = + spanWith (styleSpanAttr $ Just "gras") $ fromList inlines +inline (Code _ txt) = + spanWith (styleSpanAttr $ Just "code_par") $ text txt +inline (Link _ _ (url, _)) = + spanWith + (styleSpanAttr $ Just "url") + (Text.Pandoc.Builder.singleton $ Str url) + +inline (Span (_, classes, _) inlines) + | Data.List.elem (pack "menu") classes = + spanWith (styleSpanAttr $ Just "menu") $ fromList inlines + +inline inline = Text.Pandoc.Builder.singleton inline diff --git a/src/Inlines.o b/src/Inlines.o new file mode 100644 index 0000000..65a5703 Binary files /dev/null and b/src/Inlines.o differ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..9e91ec8 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,19 @@ + +# Tâche par défaut. +all: $(FILTERS_DIR)/diamond +.DEFAULT_GOAL:=all + +# Tâches virtuelles. +.PHONY: lean all + +# Construction du filtre diamond. +SRC_FILES=$(wildcard *.hs) + +../filters/diamond: diamond.hs $(SRC_FILES) + ghc -o $@ $< + +# Nettoyage. +clean: + rm -f *.hi *.o + +# vim: set tw=80 ts=4 sw=4 sts=4 spelllang=fr: diff --git a/src/diamond.hi b/src/diamond.hi new file mode 100644 index 0000000..694e3d9 Binary files /dev/null and b/src/diamond.hi differ diff --git a/src/diamond.hs b/src/diamond.hs new file mode 100755 index 0000000..a094ab3 --- /dev/null +++ b/src/diamond.hs @@ -0,0 +1,45 @@ +{-| Main filter module. +-} + +{- | + Module : Main + Copyright : (c) Alexis Lahouze, 2025 +-} + +module Main (main, diamond) where + +import Inlines +import Blocks + +import Data.Map +import Data.Maybe +import Data.Text + +import Text.Pandoc.Builder +import Text.Pandoc.Definition +import Text.Pandoc.JSON +import Text.Pandoc.Walk + +-- | Extract notes from inline. +note :: Inline -> [Block] +note (Note blocks) = Text.Pandoc.Builder.toList . mconcat $ topLvlBlock <$> blocks +note _ = [] + +-- | Extract notes in a Metavalue. +notes :: [Block] -> MetaValue +notes blocks = MetaBlocks $ query Main.note blocks + + +-- | Fonction de base du filtre. +diamond :: Pandoc -> Pandoc + +-- | Par défaut on retourne le block sans transformation. +diamond (Pandoc meta blocks) = + Pandoc + (Meta $ insert (pack "notes") (notes blocks) (unMeta meta)) + (Text.Pandoc.Builder.toList . mconcat $ topLvlBlock <$> blocks) + -- TODO Alexis Lahouze 2025-11-20 Append notes. + +-- | Fonction principale du filtre. +main :: IO () +main = toJSONFilter diamond diff --git a/src/diamond.o b/src/diamond.o new file mode 100644 index 0000000..6cf3861 Binary files /dev/null and b/src/diamond.o differ diff --git a/templates/diamond.opendocument b/templates/diamond.opendocument new file mode 100644 index 0000000..f669990 --- /dev/null +++ b/templates/diamond.opendocument @@ -0,0 +1,47 @@ + + + + + + + $automatic-styles$ + +$for(header-includes)$ + $header-includes$ +$endfor$ + + +$if(titre)$ +$titre$ +$endif$ +$for(auteurs)$ +$it.nom$ +$if(it.description)$ +$it.description$ +$endif$ +$sep$ +$endfor$ +$if(chapeau)$ + +$chapeau$ + +$endif$ +$if(mots_cles)$ +/// Mots-clés /// +$if(mots_cles_entete)$ +$mots_cles_entete$ +$endif$ +$for(mots_cles)$$mots_cles$$sep$ / $endfor$ +/// Fin Mots-clés /// +$endif$ +$for(include-before)$ +$include-before$ +$endfor$ +$body$ +Références +$for(include-after)$ +$include-after$ +$endfor$ + + +