<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://cecil.app/fr/xsl/atom.xsl" media="all"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
  <id>https://cecil.app/fr/documentation/developpeurs/</id>
  <title>Cecil - Développeurs</title>
  <subtitle><![CDATA[Cecil est une application PHP en ligne de commande qui fusionne des pages Markdown, des médias et des templates Twig afin de générer un site Web statique.]]></subtitle>
  <link href="https://cecil.app/fr/documentation/developpeurs/atom.xml" rel="self" type="application/atom+xml" />
  <link href="https://cecil.app/fr/documentation/developpeurs/" rel="alternate" type="text/html" />
  <updated>2026-10-06T00:34:18+00:00</updated>
  <author>
    <name>Cecil</name>
    <uri>https://cecil.app</uri>
  </author>
  <entry xml:lang="fr">
    <id>https://cecil.app/fr/documentation/developpeurs/architecture/</id>
    <title>Architecture</title>
    <published>2026-05-27T00:00:00+00:00</published>
    <updated>2026-10-02T00:00:00+00:00</updated>
    <link href="https://cecil.app/fr/documentation/developpeurs/architecture/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Architecture</h1>
<h2 id="diagramme">Diagramme</h2>
<pre><code class="language-mermaid" translate="no">graph TD
    %% Entrée
    CLI["bin/cecil\n(Point d'entrée CLI)"]
    APP["Application\n(Symfony Console)"]
    CMD["Commandes\nbuild / serve / new:site\nnew:page / clear / show:content"]

    CLI --&gt; APP --&gt; CMD

    %% Orchestrateur
    BUILDER["Builder\n(Orchestrateur)"]
    CONFIG["Configuration\n(config.yml + default.php\n+ thèmes)"]
    CMD --&gt; BUILDER
    CONFIG --&gt; BUILDER

    %% Pipeline
    subgraph PIPELINE["Pipeline de génération (étapes)"]
        S1["1. Pages/Load\n(Finder → fichiers Markdown)"]
        S2["2. Data/Load\n(fichiers YAML)"]
        S3["3. StaticFiles/Load\n(chargement des fichiers statiques)"]
        S4["4. Pages/Create\n(création des objets Page)"]
        S5["5. Pages/Convert\n(Markdown → HTML\nfront matter)"]
        S6["6. Taxonomies/Create\n(création des taxonomies)"]
        S7["7. Pages/Generate\n(générateurs)"]
        S8["8. Menus/Create\n(création des menus)"]
        S9["9. StaticFiles/Copy\n(copie des fichiers statiques)"]
        S10["10. Pages/Render\n(rendu Twig)"]
        S11["11. Pages/Save\n(sauvegarde des pages)"]
        S12["12. Assets/Save\n(sauvegarde des assets)"]
        S13["13. Optimize/*\n(optimisation HTML/CSS/JS/Images)"]

        S1 --&gt; S2 --&gt; S3 --&gt; S4 --&gt; S5 --&gt; S6 --&gt; S7 --&gt; S8 --&gt; S9 --&gt; S10 --&gt; S11 --&gt; S12 --&gt; S13
    end

    BUILDER --&gt; PIPELINE

    %% Sous-systèmes
    subgraph COLLECTIONS["Collections"]
        PC["PagesCollection\n(objets Page)"]
        TC["TaxonomiesCollection\n(vocabulaires/termes)"]
        MC["MenusCollection"]
    end

    subgraph GENERATORS["Générateurs (virtuels)"]
        GP["Pagination"]
        GT["Taxonomie"]
        GS["Section"]
        GR["Redirection"]
        GD["DefaultPages (accueil, 404)"]
    end

    subgraph RENDERER["Rendu Twig"]
        TW["Moteur Twig"]
        EXT["Extensions\n(Core, Content, Collection)"]
        PP["PostProcessors\n(métadonnées, extraits, liens)"]
        TH["Thèmes / Layouts"]
        TW --&gt; EXT
        TW --&gt; PP
        TH --&gt; TW
    end

    subgraph ASSETS["Assets"]
        AL["Localisateur d'assets"]
        AC["Compilateur\n(SCSS → CSS)"]
        AI["Processeur d'images\n(responsive, WebP, AVIF)"]
        AO["Optimiseur\n(minification CSS/JS)"]
    end

    subgraph OUTPUT["Sortie (_site/)"]
        HTML["pages .html"]
        CSS2["assets CSS/JS"]
        IMG["images"]
        SF["fichiers statiques"]
    end

    S4 --&gt; PC
    S6 --&gt; TC
    S8 --&gt; MC
    S7 --&gt; GENERATORS
    GENERATORS --&gt; PC
    S10 --&gt; RENDERER
    S12 --&gt; ASSETS

    PC --&gt; RENDERER
    TC --&gt; RENDERER
    MC --&gt; RENDERER

    RENDERER --&gt; S11
    S11 --&gt; HTML
    S12 --&gt; CSS2
    S12 --&gt; IMG
    S9 --&gt; SF

    %% Entrées
    subgraph INPUT["Sources"]
        MD["content/\n(Markdown + front matter)"]
        DATA["data/\n(YAML)"]
        STATIC["static/"]
        LAYOUTS["layouts/\n(modèles Twig)"]
    end

    MD --&gt; S1
    DATA --&gt; S2
    STATIC --&gt; S3
    LAYOUTS --&gt; TH</code></pre>
<h2 id="legende-des-composants-cles">Légende des composants clés</h2>
<table>
<thead>
<tr>
<th>Composant</th>
<th>Rôle</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Builder</strong></td>
<td>Orchestrateur central, exécute les étapes en séquence</td>
</tr>
<tr>
<td><strong>Config</strong></td>
<td>Fusion de la configuration par défaut + thème + projet + CLI</td>
</tr>
<tr>
<td><strong>Steps</strong></td>
<td>Pipeline modulaire (13 étapes), chacune avec <code translate="no">init()</code> / <code translate="no">canProcess()</code> / <code translate="no">process()</code></td>
</tr>
<tr>
<td><strong>Collections</strong></td>
<td>Pages, Taxonomies, Menus — structures de données centrales</td>
</tr>
<tr>
<td><strong>Generators</strong></td>
<td>Créent des pages virtuelles (pagination, tags, redirections…)</td>
</tr>
<tr>
<td><strong>Renderer (Twig)</strong></td>
<td>Applique les modèles + extensions + post-traitements</td>
</tr>
<tr>
<td><strong>Assets</strong></td>
<td>Compile SCSS, optimise images, fingerprinte les fichiers</td>
</tr>
</tbody>
</table>]]>
    </content>
  </entry>
  <entry xml:lang="fr">
    <id>https://cecil.app/fr/documentation/developpeurs/etendre/</id>
    <title>Étendre</title>
    <published>2026-03-27T00:00:00+00:00</published>
    <updated>2026-10-02T00:00:00+00:00</updated>
    <link href="https://cecil.app/fr/documentation/developpeurs/etendre/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Étendre</h1>
<p>Comme Cecil repose sur PHP, il est facile d'en étendre les capacités.</p>
<h2 id="generateur-de-pages">Générateur de pages</h2>
<p>Un générateur permet de créer des pages sans fichiers Markdown (avec des données provenant d'une API ou d'une base de données, par exemple), ou de modifier des pages existantes.</p>
<p>Créez simplement une nouvelle classe PHP dans l'espace de noms <code translate="no">Cecil\Generator</code>, puis ajoutez le nom de la classe à la liste <a href="/fr/documentation/configuration/pages/#pages-generators"><code translate="no">pages.generators</code></a>.</p>
<p><strong>Exemple:</strong></p>
<p><em>/extensions/Cecil/Generator/DummyPage.php</em></p>
<pre><code class="language-php hljs php" translate="no"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Generator</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Collection</span>\<span class="hljs-title">Page</span>\<span class="hljs-title">Page</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Collection</span>\<span class="hljs-title">Page</span>\<span class="hljs-title">Type</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DummyPage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractGenerator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">GeneratorInterface</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generate</span><span class="hljs-params">()</span>: <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-comment">// create a new page $page, then add it to the site collection</span>
        $page = (<span class="hljs-keyword">new</span> Page(<span class="hljs-string">'my-page'</span>))
            -&gt;setType(Type::PAGE-&gt;value)
            -&gt;setPath(<span class="hljs-string">'mypage'</span>)
            -&gt;setBodyHtml(<span class="hljs-string">'&lt;p&gt;My page body&lt;/p&gt;'</span>)
            -&gt;setVariable(<span class="hljs-string">'language'</span>, <span class="hljs-string">'en'</span>)
            -&gt;setVariable(<span class="hljs-string">'title'</span>, <span class="hljs-string">'My page'</span>)
            -&gt;setVariable(<span class="hljs-string">'date'</span>, now())
            -&gt;setVariable(<span class="hljs-string">'menu'</span>, [<span class="hljs-string">'main'</span> =&gt; [<span class="hljs-string">'weight'</span> =&gt; <span class="hljs-number">99</span>]]);
        <span class="hljs-keyword">$this</span>-&gt;generatedPages-&gt;add($page);
    }
}</code></pre>
<p><em>/extensions/Cecil/Generator/Database.php</em></p>
<pre><code class="language-php hljs php" translate="no"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Generator</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Collection</span>\<span class="hljs-title">Page</span>\<span class="hljs-title">Page</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Collection</span>\<span class="hljs-title">Page</span>\<span class="hljs-title">Type</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Database</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractGenerator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">GeneratorInterface</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generate</span><span class="hljs-params">()</span>: <span class="hljs-title">void</span>
    </span>{
        <span class="hljs-comment">// create pages from a SQLite database</span>
        $db = <span class="hljs-keyword">new</span> SQLite3(<span class="hljs-string">'database.sqlite'</span>);
        $statement = $db-&gt;prepare(<span class="hljs-string">'SELECT * FROM blog'</span>);
        $result = $statement-&gt;execute();
        <span class="hljs-keyword">while</span> ($row = $result-&gt;fetchArray(SQLITE3_ASSOC)) {
            $page = (<span class="hljs-keyword">new</span> Page($row[<span class="hljs-string">'page-id'</span>]))
                -&gt;setType(Type::PAGE-&gt;value)
                -&gt;setPath($row[<span class="hljs-string">'path'</span>])
                -&gt;setBodyHtml($row[<span class="hljs-string">'html'</span>])
                -&gt;setVariable(<span class="hljs-string">'title'</span>, $row[<span class="hljs-string">'title'</span>])
                -&gt;setVariable(<span class="hljs-string">'date'</span>, $row[<span class="hljs-string">'date'</span>]);
            <span class="hljs-keyword">$this</span>-&gt;generatedPages-&gt;add($page);
        }
        $result-&gt;finalize();
        $db-&gt;close();
    }
}</code></pre>
<p><em>configuration</em></p>
<pre><code class="language-yaml hljs yaml" translate="no"><span class="hljs-attr">pages:</span>
  <span class="hljs-attr">generators:</span>
    <span class="hljs-comment"># priority: class name</span>
    <span class="hljs-attr">99:</span> <span class="hljs-string">Cecil\Generator\DummyPage</span>
    <span class="hljs-attr">35:</span> <span class="hljs-string">Cecil\Generator\Database</span></code></pre>
<h2 id="extension-twig">Extension Twig</h2>
<p>Vous pouvez ajouter des <a href="/fr/documentation/templates/reference/fonctions/">fonctions</a> et des <a href="/fr/documentation/templates/reference/filtres/">filtres</a> personnalisés :</p>
<ol>
<li><a href="https://twig.symfony.com/doc/advanced.html#creating-an-extension" target="_blank" rel="noopener noreferrer">créez une extension Twig</a> dans l'espace de noms <code translate="no">Cecil\Renderer\Extension</code></li>
<li>ajoutez le fichier PHP dans le répertoire <code translate="no">extensions</code></li>
<li>ajoutez le nom de la classe à la configuration</li>
</ol>
<p><strong>Exemple:</strong></p>
<p><em>/extensions/Cecil/Renderer/Extension/MyTwigExtension.php</em></p>
<pre><code class="language-php hljs php" translate="no"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Renderer</span>\<span class="hljs-title">Extension</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyTwigExtension</span> <span class="hljs-keyword">extends</span> \<span class="hljs-title">Twig</span>\<span class="hljs-title">Extension</span>\<span class="hljs-title">AbstractExtension</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getFilters</span><span class="hljs-params">()</span>
    </span>{
        <span class="hljs-comment">// add a new filter named 'md5'</span>
        <span class="hljs-keyword">return</span> [
            <span class="hljs-keyword">new</span> \Twig\TwigFilter(<span class="hljs-string">'md5'</span>, <span class="hljs-string">'md5'</span>),
        ];
    }
}</code></pre>
<p><em>configuration</em></p>
<pre><code class="language-yaml hljs yaml" translate="no"><span class="hljs-attr">layouts:</span>
  <span class="hljs-attr">extensions:</span>
    <span class="hljs-attr">MyExtension:</span> <span class="hljs-string">Cecil\Renderer\Extension\MyTwigExtension</span></code></pre>
<h2 id="post-processeur-de-rendu">Post-processeur de rendu</h2>
<p>Vous pouvez post-traiter le rendu des pages.</p>
<p>Créez simplement une nouvelle classe PHP dans l'espace de noms <code translate="no">Cecil\Renderer\PostProcessor</code> et ajoutez le nom de la classe à la liste <code translate="no">output.postprocessors</code>.</p>
<p><strong>Exemple:</strong></p>
<p><em>/extensions/Cecil/Renderer/PostProcessor/MyProcessor.php</em></p>
<pre><code class="language-php hljs php" translate="no"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Renderer</span>\<span class="hljs-title">PostProcessor</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Collection</span>\<span class="hljs-title">Page</span>\<span class="hljs-title">Page</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyProcessor</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractPostProcessor</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">process</span><span class="hljs-params">(Page $page, string $output, string $format)</span>: <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-comment">// add a meta tag to the head of the HTML output</span>
        <span class="hljs-keyword">if</span> ($format == <span class="hljs-string">'html'</span>) {
            <span class="hljs-keyword">if</span> (!preg_match(<span class="hljs-string">'/&lt;meta name="test".*/i'</span>, $output)) {
                $meta = \sprintf(<span class="hljs-string">'&lt;meta name="test" content="Test"&gt;'</span>);
                $output = preg_replace_callback(<span class="hljs-string">'/([[:blank:]]*)(&lt;\/head&gt;)/i'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($matches)</span> <span class="hljs-title">use</span> <span class="hljs-params">($meta)</span> </span>{
                    <span class="hljs-keyword">return</span> str_repeat($matches[<span class="hljs-number">1</span>] ?: <span class="hljs-string">' '</span>, <span class="hljs-number">2</span>) . $meta . <span class="hljs-string">"\n"</span> . $matches[<span class="hljs-number">1</span>] . $matches[<span class="hljs-number">2</span>];
                }, $output);
            }
        }

        <span class="hljs-keyword">return</span> $output;
    }
}</code></pre>
<p><em>configuration</em></p>
<pre><code class="language-yaml hljs yaml" translate="no"><span class="hljs-attr">output:</span>
  <span class="hljs-attr">postprocessors:</span>
    <span class="hljs-attr">MyProcessor:</span> <span class="hljs-string">Cecil\Renderer\PostProcessor\MyProcessor</span></code></pre>]]>
    </content>
  </entry>
  <entry xml:lang="fr">
    <id>https://cecil.app/fr/documentation/developpeurs/bibliotheque/</id>
    <title>Bibliothèque</title>
    <published>2026-03-27T00:00:00+00:00</published>
    <updated>2026-10-03T00:00:00+00:00</updated>
    <link href="https://cecil.app/fr/documentation/developpeurs/bibliotheque/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<h1>Bibliothèque</h1>
<p>Cecil propose une API PHP simple pour générer votre site web.</p>
<p>Vous pouvez consulter la <a href="https://cecil.app/documentation/library/api/namespaces/cecil.html">documentation de l'API</a> pour plus de détails.</p>
<h2 id="installation">Installation</h2>
<pre><code class="language-bash hljs bash" translate="no">composer require cecil/cecil</code></pre>
<h3 id="support-de-libvips">Support de libvips</h3>
<p>Pour traiter les images avec <a href="https://www.libvips.org/" target="_blank" rel="noopener noreferrer">libvips</a> (optionnel), installez le driver libvips dans votre projet :</p>
<pre><code class="language-bash hljs bash" translate="no">composer require intervention/image-driver-vips</code></pre>
<aside class="note note-important"><p>Ce driver nécessite <a href="https://www.libvips.org/install.html" target="_blank" rel="noopener noreferrer">libvips</a> installé sur le système et l’extension PHP <a href="https://www.php.net/manual/book.ffi.php" target="_blank" rel="noopener noreferrer">FFI</a> activée.<br>
Sans lui, Cecil utilise <a href="https://www.php.net/manual/book.imagick.php" target="_blank" rel="noopener noreferrer">Imagick</a> ou <a href="https://www.php.net/manual/book.image.php" target="_blank" rel="noopener noreferrer">GD</a> à la place.</p></aside>
<h2 id="utilisation">Utilisation</h2>
<h3 id="construction">Construction</h3>
<p>Construisez un nouveau site web avec une configuration personnalisée :</p>
<pre><code class="language-php hljs php" translate="no"><span class="hljs-keyword">require_once</span> <span class="hljs-string">'vendor/autoload.php'</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Builder</span>;

$config = [
    <span class="hljs-string">'title'</span>   =&gt; <span class="hljs-string">"My website"</span>,
    <span class="hljs-string">'baseurl'</span> =&gt; <span class="hljs-string">'https://domain.tld/'</span>,
];

Builder::create($config)-&gt;build();

exec(<span class="hljs-string">'php -S localhost:8000 -t _site'</span>); <span class="hljs-comment">// prévisualisation locale</span></code></pre>
<aside class="note note-info"><p>Le paramètre principal de la méthode <code translate="no">create</code> doit être un <code translate="no">array</code> PHP ou une instance de <a href="https://github.com/Cecilapp/Cecil/blob/main/src/Config.php" target="_blank" rel="noopener noreferrer"><code translate="no">Cecil\Config</code></a>.</p></aside>
<h3 id="diagnostic">Diagnostic</h3>
<p>Vous pouvez aussi exécuter les vérifications doctor via des services de domaine dédiés, sans utiliser les commandes CLI.</p>
<pre><code class="language-php hljs php" translate="no"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">require_once</span> <span class="hljs-string">'vendor/autoload.php'</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Builder</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Doctor</span>\<span class="hljs-title">SeoDoctor</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Cecil</span>\<span class="hljs-title">Doctor</span>\<span class="hljs-title">SiteDoctor</span>;

$builder = Builder::create(<span class="hljs-keyword">require</span> <span class="hljs-string">'config.php'</span>)
    -&gt;setSourceDir(<span class="hljs-keyword">__DIR__</span>)
    -&gt;setDestinationDir(<span class="hljs-keyword">__DIR__</span>);

$siteDoctor = <span class="hljs-keyword">new</span> SiteDoctor();
$diagnosis = $siteDoctor-&gt;diagnose($builder, <span class="hljs-keyword">__DIR__</span>, [<span class="hljs-string">'cecil.yml'</span>]);

$seoDoctor = <span class="hljs-keyword">new</span> SeoDoctor();
$seoAudit = $seoDoctor-&gt;audit($builder, [
    <span class="hljs-string">'page'</span> =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'include_virtual'</span> =&gt; <span class="hljs-keyword">false</span>,
]);

var_dump($diagnosis[<span class="hljs-string">'errors'</span>], $seoAudit[<span class="hljs-string">'summary'</span>]);</code></pre>]]>
    </content>
  </entry>
</feed>
