Paged.js

Paged.js est une bibliothèque JavaScript open-source permettant de concevoir un contenu paginé dans un navigateur et de générer des documents PDF destinés à l’impression, en utilisant les langages du web (HTML, CSS et JavaScript).

Elle est aujourd’hui l’un des outils les plus performants pour le web to print, particulièrement lorsque l’on veut concevoir des documents multi-pages.

Par où commencer ?

1 — Un navigateur web: Ungoogled Chromium ou Chromium (à défaut, Edge ou Chrome)

2 — Un serveur web : Paged.js a besoin d’un server web pour être exécuté. Sur Windows ou sur OSX : utiliser l’extension live server (Go Live) de VSCode ou pour OSX / linux, dans un terminal :

cd votre/dossier/de/travail
php -S localhost:8888  
# ou bien    
python -m SimpleHTTPServer 8888
# ou bien    
python3 -m http.server 8888
# ces 3 commandes permettent d’accéder à la page web sur http://localhost:8888

3 — Un code source de base grâce au Minute Hack de Raphaël Bastide ou en téléchargeant ce fichier zip.

4 — Une bonne documentation ! RTFM sur pagedjs.org/documentation.

Comment ça marche ?

La librairie Paged.js permet de transformer un document “flux” en un document “paginé”, capable d’utiliser différents gabarits de pages, d’afficher des titres courants ou des numéros de pages, de générer une table des matières, etc.

L’exécution de paged.js va transformr le code-source HTML & CSS en un ensemble complexe d’éléments et de styles qui permettent de prévisualiser dans le navigateur le comportement de l’impression ou la génération de PDF.

Paged.js utilise les spécifications CSS prévues depuis CSS 2.1 (voir la section précédente).

Définir le format du document

On peut définir le format de page et les marges grâce à la règle @page.

@page {
  size: 148mm 210mm;
  margin: 1cm;
}
/* on peut également définir des comportements différents pour les 
pages de gauche et de droite ; ici, les “petits” et “grands fonds”
– marges intérieures et extérieures – sont inversés */
@page :left{
  margin: 33mm 23mm 65mm 45mm; 
}
@page :right{
  margin: 33mm 45mm 65mm 23mm;
}

On peut également déterminer des repères de coupe et une marge de fond perdu :

@page {
  /* … */
  marks: crop;
  bleed: 4mm;
}

Paged.js générera alors un ensemble d’éléments HTML et de variables CSS qui permettront de mettre en pages le contenu et ses marges. Lire dans la documentation, la règle @page.

Voir exemple 01.

Définir des gabarits de page

Pour spécifier des “types” de pages singuliers (entrées de chapitre, couverture, page d’iconographie, etc.), on affecte une class à un élément du HTML. En CSS, on déclare une nouvelle page-type, puis on affecte cette page-type à cette .class grâce à une déclaration page: typedepage. Lire dans la documentation, les pages nommées.

<header class="couverture">
  <h1>Titre</h1>
  <h2>Sous-titre</h2>  
</header>
@page macouverture {
  margin: 0;
  background: black;
}
.couverture { 
  page: macouverture;
  color: white;
}

Voir exemple 02.

Ajouter des numéros de page et des titres courants

Les margin boxes créées par Paged.js peuvent accuillir du contenu: généré automatiquement, tels des numéros de page, ou présents dans le HTML (section courante, titre du document, etc.).

@page :left{ 
  @bottom-left {
    content: counter(page);
  }
}
@page :right{ 
  @bottom-right {
    content: counter(page);
  }
}
/* pas de numéro de page pour la couverture */
@page macouverture {
  @bottom-right { content: none; }
  @bottom-left { content: none; }
}

Voir exemple 03.

Paged.js offre d’autres possibilités que les compteurs de page, notamment grâce aux propriétés string-set et position: running (lire la documentation :). Ici, un exemple avec position: running() :

<section>
  <p class="title">Titre courant</p>
  <h1>…</h1>
  <p>…</p>
</section>
/* supprime l’élément .title de l’affichage grâce à la déclaration position: running() */
.title {
  position: running(monTitreCourant);
}
/* injecte l’élément définit dans running() dans une margin-box */
@page {
  @top-center {
    content: element(monTitreCourant)
  }
}

Voir exemple 04.

Aller plus loin

Ces principes de base permettent de mettre en pages un contenu relativement rapidement. Mais de nombreuses possibilités graphiques peuvent encore être explorées, chacune demandant une approche spécifique. Ci-dessous viendront s’ajouter des liens vers des résolutions concrètes, des exemples plus complexes ou des problèmes courants.

Pour comprendre, téléchargez les examples et examinez leur code source.

On peut aussi parcourir les exemples de Julien Taquet sur gitlab.pagedmedia.org ou sur codepen.io/julientaq, les experiments sur le gitlab de PagedMedia, ou les démos de Raphaël Bastide / PrePostPrint.

Un espace de discussion et de support est accessible sur le Mattermost de coko.foundation. Julien Taquet et l’équipe de Paged.js y répondent aux questions des utilisateur·ices, quelque soit leur niveau de compétences ;)