Python – Install WeasyPrint on a linux (Webfaction) server

WeasyPrint is a great python library to generate PDFs from HTML. It beats hands down xhtml2pdf, by interpreting CSS and HTML the right way.

However, it has a lot of dependencies and it just can’t fit in a simple python virtual environment. It took me a whole day to install on Webfaction, so I think it would be helpful to show how to do it properly.

These steps has been tested on a Webfaction CentOS 6 server (python2.7), and they should be the same for others Linux systems. If your system is not exactly the same, you might have to install other dependencies manually. Linux From Scratch is your helpful friend in this kind of situation.

(more…)

Un PDF à l’image de votre CV en ligne avec wkpdf

Tout comme il est intéressant pour un employeur d’avoir accès au CV en ligne d’une potentielle nouvelle recrue, il est également pratique de pouvoir imprimer ce CV dans un format qui convient.

La génération automatique d’un PDF associé au contenu de votre site présente plusieurs avantages:

  • Le PDF est constamment à jour du contenu de votre site
  • Le PDF adopte le design de votre site
  • C’est totalement la classe

Voici donc un petit aperçu hautement égocentré de ce que vous pourrez faire:

       

Comme vous l’aurez remarqué, divers détails graphiques comme l’arrière-plan gris ou le ruban bleu ont été effacés afin de proposer une version épurée prête à l’impression.

Pour parvenir à ce résultat, nous allons utiliser un petit logiciel nommé wkpdf associé à une feuille de style spéciale.

La feuille de style

Depuis la version 4 de la norme HTML, il est possible d’inclure une feuille de style en précisant le type de périphérique auquel elle est adressée. On peut ainsi inclure une une feuille de style spécifique aux télévisions:

1
<link rel="stylesheet" media="tv" href="css/tv.css" />

Il est même possible depuis la version 2 de la norme CSS de déclarer des règles spécifiques à un media directement dans votre feuille de style principale:

1
2
3
4
5
6
7
/* Avec @import */
@import url("tv.css") tv;

/* Ou avec @media */
@media print {
  /* Règles spécifiques */
}

Voici la liste des valeurs de l’attribut media:


1
2
3
4
5
6
7
8
9
10
all         Suitable for all devices.
braille     Intended for braille tactile feedback devices.
embossed    Intended for paged braille printers.
handheld    Intended for handheld devices (typically small screen, limited bandwidth).
print       Intended for paged material and for documents viewed on screen in print preview mode.
projection  Intended for projected presentations, for example projectors.
screen      Intended primarily for color computer screens.
speech      Intended for speech synthesizers.
tty         Intended for media using a fixed-pitch character grid (such as teletypes, terminals, or portable devices with limited display capabilities).
tv          Intended for television-type devices (low resolution, color, limited-scrollability screens, sound available).

Il est à noter que si vous ne précisez pas de media, la valeur de l’attribut est “all” (pour tous les périphériques).
Nous voyons ici que la valeur “print” permet de personnaliser un document destiné à être imprimé, c’est donc celui-ci que nous allons utiliser:

1
<link rel="stylesheet" media="print" href="css/print.css" />

Dans cette feuille de style, supprimons tout ce qui n’est plus nécessaire, par exemple:

1
2
3
4
5
6
7
8
9
/* Suppression d'un élément inutile */
.classe-de-l-element {
  display:none;
}

/* Suppression de l'arrière plan */
body {
  background: none;
}

Vous pouvez tester ces nouvelles règles en modifiant temporairement l’attribut media de “print” à “all”.

Génération du PDF

Nous allons utiliser wkpdf pour générer notre fichier. Malheureusement ce dernier n’est disponible que sur Mac, mais il existe une alternative multiplateforme, wkhtmltopdf, qui semble fonctionner sur le même principe.

Ces logiciel a un énorme avantage: au lieu de posséder son propre moteur d’interprétation de la structure HTML, il utilise le fameux Webkit (le moteur de rendu de Chrome et Safari, notamment). Le rendu sera donc fidèle à ce que vous pourrez voir dans un navigateur web conventionnel.

Il vous suffit donc d’exécuter wkpdf en ligne de commande:


1
$ wkpdf --source http://monsite.com/ --output cv.pdf --margins 0 --stylesheet-media print --print-background

De plus, si votre site met en place des éléments graphiques à l’aide de Javascript, ajoutez les arguments suivants:


1
--enable-javascript --save-delay [temps_avant_capture_en_secondes]

Vous devriez ainsi obtenir un beau PDF prêt à l’emploi. Il vous faudra sûrement adapter certaines règles CSS pour que tout tienne sur une page, etc…

Bonus: impression directe à partir du site

La feuille de style “media=print” sert également à votre navigateur lors de l’impression d’une page. Néanmoins, certaines limitations sont mises en place par la plupart des navigateurs:

  • Les arrières-plans ne sont pas pris en compte. background-color et background-image ne fonctionneront donc pas.
  • Le Javascript n’est pas pris en charge, aucune modification ne pourra être faite dynamiquement avant l’impression.

Note concernant le comportement des navigateurs lors de l’impression:

  • Aucune référence ou documentation n’est disponible à ce sujet, du moins pour le moment
  • Dans certaines versions de Firefox, et sous certains systèmes d’exploitation, il est possible d’activer la prise en charge des arrière-plans (couleur et image) ainsi que le Javascript. Là encore, aucune documentation.
  • Internet Explorer propose un event onbeforeprint permettant de modifier le DOM lorsque le navigateur s’apprête à imprimer. Plus d’informations par ici.

Si vous avez des renseignements supplémentaires concernant les différents comportements adoptés par les navigateurs, n’hésitez pas à m’en informer !

Toute l’astuce consistera donc à remplacer les arrières plans par des images (qui elles seront affichées), ou de tenter de mettre en place une sorte de “graceful degradation” afin de simuler certains éléments graphiques. Par exemple, les barres de compétences mises en place sur mon CV ne sont pas pleines lors de leur impression, j’ai donc dû ajouter un border-color pour symboliser les limites de ces dernières.

Et après ?

On peut maintenant aisément imaginer un système qui génèrerait automatiquement votre PDF à chaque modification du site web. Si vous utilisez un système de versioning, aucun soucis. Je vous invite à chercher du côté de pre-commit si vous gérez tout ça avec svn ou git. Il vous suffira de modifier ces hooks en insérant la commande de génération, et d’ajouter au commit le fichier PDF ainsi généré.