03-comment-je-travaille/tutos/epub.md

Tutoriel : Créer un EPUB 3 Accessible par le code

Public visé : Développeurs Web, Intégrateurs, Experts en accessibilité numérique.

L'objectif de ce tutoriel est de construire manuellement un fichier EPUB 3 minimal mais 100% conforme aux normes d'accessibilité (WCAG, Daisy).

1. Structure et Fichiers de Base

Un EPUB est un document structuré. Commençons par créer l'arborescence et les fichiers système obligatoires.

1.1 Le fichier mimetype

Ce fichier est crucial : il doit être le premier de l'archive ZIP et ne doit pas être compressé.

application/epub+zip

1.2 Le conteneur (META-INF/container.xml)

Il indique au lecteur où se trouve le fichier de description (OPF).

<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
  <rootfiles>
    <rootfile full-path="EPUB/content.opf" media-type="application/oebps-package+xml"/>
  </rootfiles>
</container>

2. Le Cerveau : EPUB/content.opf

C'est ici que l'on définit l'identité du livre et son accessibilité.

Points d'attention pour l'accessibilité :

  • Langue : dc:language doit être présent (indispensable pour la synthèse vocale).
  • Identifiant : Un UUID unique.
  • Métadonnées d'accessibilité : Indiquer explicitement que le livre est accessible.
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="pub-id" version="3.0" xml:lang="fr">
  <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
    <dc:identifier id="pub-id">urn:uuid:12345-6789-0abcde</dc:identifier>
    <dc:title>Mon Premier EPUB Accessible</dc:title>
    <dc:creator>Codexia</dc:creator>
    <dc:language>fr</dc:language>
    <meta property="dcterms:modified">2026-03-02T10:00:00Z</meta>
    <!-- Métadonnées d'accessibilité (Daisy/Ace) -->
    <meta property="schema:accessibilityFeature">structuralNavigation</meta>
    <meta property="schema:accessibilityFeature">alternativeText</meta>
    <meta property="schema:accessibilityHazard">none</meta>
    <meta property="schema:accessMode">textual</meta>
    <meta property="schema:accessModeSufficient">textual</meta>
  </metadata>
  <manifest>
    <item id="nav" href="toc.xhtml" media-type="application/xhtml+xml" properties="nav"/>
    <item id="ch1" href="chapter1.xhtml" media-type="application/xhtml+xml"/>
    <item id="style" href="style.css" media-type="text/css"/>
  </manifest>
  <spine>
    <itemref idref="nav"/>
    <itemref idref="ch1"/>
  </spine>
</package>

3. Le Contenu : EPUB/chapter1.xhtml (HTML5 en syntaxe XML)

L'EPUB 3 utilise officiellement le HTML5. Cependant, comme l'EPUB est une structure basée sur le XML, ce HTML5 doit être "sérialisé" en syntaxe XML (XHTML5).

Pourquoi cette syntaxe ?

  1. Validité XML : Tous les outils EPUB (liseuses, validateurs) utilisent des parseurs XML. Ils s'attendent à ce que chaque balise soit correctement ouverte et fermée.
  2. Rigueur : Contrairement au HTML5 "souple" du navigateur, le XHTML5 ne tolère aucune erreur de syntaxe. Si une balise n'est pas fermée, l'EPUB est corrompu.

Différences clés à respecter :

  • Namespace : Toujours inclure xmlns="http://www.w3.org/1999/xhtml".
  • Fermeture forcée : Toutes les balises doivent être fermées, même les auto-fermantes (<br />, <hr />, <img ... />).
  • Minuscules : Les noms des balises et des attributs doivent être en minuscules.
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="fr">
  <head>
    <title>Chapitre 1</title>
    <link rel="stylesheet" type="text/css" href="style.css"/>
  </head>
  <body>
    <section epub:type="chapter" role="doc-chapter">
      <h1>Introduction à l'accessibilité</h1>
      <p>L'accessibilité n'est pas une option, c'est une <strong>obligation technique et éthique</strong>.</p>
      
      <figure>
        <img src="img/example.jpg" alt="Description textuelle de l'image" />
        <figcaption>L'accessibilité pour tous.</figcaption>
      </figure>
      
      <p>Même si on utilise les balises modernes de l'HTML5 (<code>&lt;section&gt;</code>, <code>&lt;nav&gt;</code>), on respecte la rigueur syntaxique du XML.</p>
    </section>
  </body>
</html>

4. La Navigation : EPUB/toc.xhtml

C'est la table des matières visuelle et structurelle.

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="fr">
  <head>
    <title>Table des matières</title>
  </head>
  <body>
    <nav epub:type="toc" id="toc" role="doc-toc">
      <h1>Table des matières</h1>
      <ol>
        <li><a href="chapter1.xhtml">Introduction</a></li>
      </ol>
    </nav>
  </body>
</html>

5. Qualité, Validation et Outils

Un EPUB accessible se teste avec des outils professionnels :

  1. EpubCheck : Valide la conformité XML et la structure ZIP.
  2. Ace by DAISY : Scanne les métadonnées et la sémantique pour certifier l'accessibilité.
  3. Thorium Reader : Lecteur de référence pour vérifier le rendu et la synthèse vocale.

La Commande de Compression (Critique)

La création manuelle de l'archive ZIP est délicate car le fichier mimetype doit être le premier et non compressé.

Sur Linux/macOS :

# 1. Créer l'archive avec mimetype (non compressé -0)
zip -0Xq mon-livre.epub mimetype
# 2. Ajouter le reste du contenu (compressé -r)
zip -rgq mon-livre.epub META-INF EPUB

Sur Windows (PowerShell) : Il est recommandé d'utiliser l'utilitaire zip (via Git Bash ou WSL) car l'explorateur Windows ou Compress-Archive ne garantissent pas l'ordre ni l'absence de compression pour mimetype.

Depuis Symfony (Bundle codexia-epub) : Pour automatiser la création dans un bundle, utilisez ZipArchive en PHP. L'ordre et l'absence de compression sont critiques.

// Exemple de logique pour CodexiaEpubBundle
$zip = new \ZipArchive();
$zip->open('mon-livre.epub', \ZipArchive::CREATE | \ZipArchive::OVERWRITE);

// 1. Ajouter le mimetype SANS compression (CM_STORE)
$zip->addFromString('mimetype', 'application/epub+zip');
$zip->setCompressionName('mimetype', \ZipArchive::CM_STORE);

// 2. Ajouter les répertoires récursivement
// Note : Les fichiers suivants peuvent être compressés (par défaut)
$zip->addFile('META-INF/container.xml', 'META-INF/container.xml');
$zip->addFile('EPUB/content.opf', 'EPUB/content.opf');
$zip->addFile('EPUB/toc.xhtml', 'EPUB/toc.xhtml');
$zip->addFile('EPUB/chapter1.xhtml', 'EPUB/chapter1.xhtml');
$zip->addFile('EPUB/style.css', 'EPUB/style.css');

$zip->close();

À retenir pour l'accessibilité (Daisy) :

  • Ne jamais utiliser d'unités fixes (px) en CSS, préférez em ou rem.
  • Toujours déclarer la langue du document et des extraits de texte étrangers (xml:lang).
  • Assurer un contraste minimal de 4.5:1 entre le texte et le fond.

Exercice Pratique

  1. Créez les fichiers ci-dessus dans un dossier mon-livre/.
  2. Ouvrez un terminal dans ce dossier.
  3. Exécutez les commandes de compression ci-dessus.
  4. Passez le fichier .epub généré au validateur EpubCheck.
  5. Passez-le ensuite au validateur Ace by DAISY.

Assistant documentaire

Posez une question sur la documentation. Les réponses citent leurs sources — un clic ouvre le document à gauche.

Loading…
Loading the web debug toolbar…
Attempt #