Depuis la v16, Dodock embarque un Chromium headless pour la génération PDF. Ce même Chromium peut désormais être réutilisé pour capturer une image de prévisualisation (screenshot) à partir d'un contenu HTML ou d'une URL — sans installer de dépendance supplémentaire, sans appel réseau externe, et avec un accès complet aux ressources locales (/assets, /files).
Cette fonctionnalité est une API Python réservée aux développeurs. Elle n'expose pas d'endpoint HTTP : l'appel se fait exclusivement depuis du code Python (extension, hook, script serveur).
Avant cette fonctionnalité, générer une image de prévisualisation nécessitait l'application séparée preview_generator, qui embarquait Playwright et un second Chromium, et effectuait un appel HTTP vers preview.frappe.cloud. Cela impliquait :
Le Chromium déjà présent dans Dodock pour la génération PDF est désormais réutilisé directement, ce qui supprime ces contraintes.
from frappe.utils.preview import get_preview_from_html, get_preview_from_url
# Capturer une image à partir d'un HTML
image_bytes = get_preview_from_html("<h1>Bonjour</h1>", format="webp")
# Capturer une image à partir d'une URL
image_bytes = get_preview_from_url("https://example.com", format="jpg")
Les deux fonctions retournent des bytes représentant l'image encodée dans le format demandé.
| Format | Valeur à passer |
|---|---|
| JPEG | "jpg" ou "jpeg" |
| WebP | "webp" |
Chrome capture nativement JPEG et WebP — aucune conversion via Pillow n'est nécessaire.
Points clés :
screen (et non print)/assets, /files) sont interceptées et servies depuis le disque — elles s'affichent correctement, contrairement à un appel vers un service externeChromium doit être installé sur le bench. Il est téléchargé automatiquement lorsque le moteur Chrome est activé pour la génération PDF (voir Moteurs de génération PDF).
Si Chromium n'est pas disponible, les appels à get_preview_from_html et get_preview_from_url échouent avec une erreur explicite.
get_preview_from_url accepte n'importe quelle URL et ordonne à Chromium de la charger côté serveur. Cela constitue une surface d'attaque SSRF (Server-Side Request Forgery) si l'URL est fournie par un utilisateur non contrôlé. Cette API est volontairement non exposée comme endpoint HTTP : elle doit uniquement être appelée depuis du code de confiance (extension, hook, script serveur maîtrisé).Ne jamais passer directement une URL fournie par un utilisateur sans validation préalable.import frappe
from frappe.utils.preview import get_preview_from_html
def generer_apercu_modele(nom_modele: str) -> str:
"""Génère un aperçu WebP d'un modèle HTML et le sauvegarde comme fichier Dokos."""
modele = frappe.get_doc("Mon Modele", nom_modele)
html = frappe.render_template(modele.contenu_html, {"doc": modele})
image_bytes = get_preview_from_html(html, format="webp")
fichier = frappe.get_doc({
"doctype": "File",
"file_name": f"apercu_{nom_modele}.webp",
"content": image_bytes,
"is_private": 0,
})
fichier.insert()
return fichier.file_url