Automatiser la Création de Screenshots de Code avec Carbon.now
der 31. August 2024
La création de captures d'écran de code est une tâche courante pour les développeurs, que ce soit pour documenter des projets, partager des extraits de code sur les réseaux sociaux ou illustrer des articles de blog. Carbon.now est un outil populaire qui permet de générer des captures d'écran esthétiques de code. Cependant, lorsque vous avez besoin de créer ces images en grande quantité ou de manière automatisée, le faire manuellement devient fastidieux.
Dans cet article, nous allons explorer comment automatiser la génération de ces captures d'écran en utilisant Carbon.now et Symfony Panther. Panther est un outil de navigation web headless qui nous permettra de manipuler et d'interagir avec Carbon.now de manière programmatique.
Pourquoi Automatiser avec Carbon.now ?
Carbon.now est un service en ligne simple et efficace pour créer des images de code avec un style personnalisable. Automatiser ce processus présente plusieurs avantages : cela permet de gagner du temps en évitant de répéter la même tâche pour la création de nombreuses images, d'assurer une consistance visuelle en appliquant les mêmes paramètres (thème, police, taille, etc.) à toutes les images, et de faciliter l'intégration de la création d'images de code dans des workflows tels que des pipelines CI/CD, des scripts de publication de blogs, ou des bots de réseaux sociaux.
Prérequis
Avant de commencer, assurez-vous d'avoir les éléments suivants :
- PHP installé sur votre machine.
- Symfony Panther installé. Si ce n'est pas encore fait, vous pouvez l'installer via Composer :
composer require symfony/panther
Configurer un Projet PHP avec Panther
Commencez par créer une nouvelle classe PHP qui encapsulera toute la logique pour interagir avec Carbon.now. Voici un exemple de classe que nous allons utiliser :
<?php
declare(strict_types=1);
namespace App\Job;
use Symfony\Component\Panther\Client;
use Flow\JobInterface;
use RuntimeException;
class CarbonImageJob implements JobInterface
{
private const CARBON_URL = 'https://carbon.now.sh/';
private Client $client;
private string $type;
public function __construct(string $type = 'png', bool $disableHeadless = false)
{
if (!in_array($type, ['png', 'svg'], true)) {
throw new \InvalidArgumentException('Type invalide. Seuls les types png et svg sont supportés.');
}
$this->type = $type;
$this->client = Client::createChromeClient(null, null, ['headless' => !$disableHeadless]);
}
public function generateScreenshot(string $code, string $path): void
{
try {
$url = $this->getCarbonUrl($code);
$this->download($url, $path);
} catch (\Exception $e) {
throw new RuntimeException('Échec de la génération de la capture d\'écran : ' . $e->getMessage());
} finally {
$this->client->quit();
}
}
private function getCarbonUrl(string $code): string
{
$encodedCode = rawurlencode($code);
return self::CARBON_URL . '?code=' . $encodedCode . '&t=night-owl';
}
private function download(string $url, string $path): void
{
$this->client->request('GET', $url);
// Script pour cliquer sur le menu d'exportation
$this->client->executeScript('document.querySelector("#export-menu").click();');
sleep(1); // Petite pause pour que l'interface réponde
// Script pour cliquer sur le bouton d'exportation correspondant (png/svg)
$this->client->executeScript(sprintf('document.querySelector("#export-%s").click();', $this->type));
// Attendre que le fichier soit téléchargé
$this->waitForFile($path);
}
private function waitForFile(string $filePath, int $timeout = 30): void
{
$elapsed = 0;
while (!file_exists($filePath) && $elapsed < $timeout) {
sleep(1);
$elapsed++;
}
if (!file_exists($filePath)) {
throw new RuntimeException('Le fichier n\'a pas été téléchargé dans le temps imparti.');
}
}
}
Générer une Capture d'Écran avec Flow
Au lieu de générer une capture d'écran de manière directe, vous pouvez utiliser la puissance de la bibliothèque Flow pour orchestrer et paralléliser la création de plusieurs captures d'écran de code avec Carbon.now. Flow est une bibliothèque qui permet d'exécuter des tâches asynchrones et parallèles de manière efficace.
Configuration de Flow pour Générer des Captures d'Écran
Dans cette étape, nous allons créer une commande Symfony qui utilisera Flow pour générer plusieurs images de code en parallèle. Voici un exemple de commande que vous pouvez ajouter à votre projet Symfony :
<?php
declare(strict_types=1);
namespace App\Command;
use App\Job\FlowExamples\CarbonImageJob;
use App\Model\CarbonImage;
use Flow\Driver\AmpDriver;
use Flow\Driver\FiberDriver;
use Flow\Driver\ReactDriver;
use Flow\Driver\SwooleDriver;
use Flow\Flow\Flow;
use Flow\Ip;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use function sprintf;
#[AsCommand(
name: 'app:carbon-image',
description: 'Cette commande permet de générer des captures d\'écran de code en utilisant Carbon.now.sh avec Flow',
)]
class CarbonImageCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
// Sélection du driver Flow aléatoire
$driver = match (random_int(1, 4)) {
1 => new AmpDriver(),
2 => new FiberDriver(),
3 => new ReactDriver(),
4 => new SwooleDriver(),
};
// Configuration du Flow pour exécuter les tâches
$flow = Flow::do(static function () use ($io) {
yield new CarbonImageJob(__DIR__ . '/../../data/carbon-image/carbon-config.json');
yield static function (CarbonImage $carbonImage) use ($io) {
$io->info(sprintf('Capture d\'écran générée pour : %s (%s)', $carbonImage->code, $carbonImage->url));
};
}, ['driver' => $driver]);
// Création des instances CarbonImage avec le code à capturer
$ip1 = new Ip(new CarbonImage("<?php echo 'Hello, World!'; ?>", __DIR__ . '/../../hello.png'));
$ip2 = new Ip(new CarbonImage("<?php
\$name = 'User';
echo 'Welcome, ' . htmlspecialchars(\$name) . '!';
echo '<br/>Today\'s date is ' . date('Y-m-d');
?>", __DIR__ . '/../../welcome_user.png'));
$ip3 = new Ip(new CarbonImage("<?php
\$colors = ['Red', 'Green', 'Blue'];
foreach(\$colors as \$color) {
echo '<div style=\"color:' . strtolower(\$color) . '\">' . \$color . '</div>';
}
?>", __DIR__ . '/../../colors_list.png'));
$ip4 = new Ip(new CarbonImage("<?php
\$error_message = 'Error 404: Page not found';
echo '<h1 style=\"color: red;\">' . \$error_message . '</h1>';
echo '<p>Please check the URL or return to the <a href=\"/\">homepage</a>.</p>';
?>", __DIR__ . '/../../error404_message.png'));
$ip5 = new Ip(new CarbonImage("<?php
\$items = ['Home', 'About', 'Contact'];
echo '<ul>';
foreach(\$items as \$item) {
echo '<li>' . \$item . '</li>';
}
echo '</ul>';
?>", __DIR__ . '/../../navigation_menu.png'));
// Exécution des tâches en parallèle
$flow($ip1);
$flow($ip2);
$flow($ip3);
$flow($ip4);
$flow($ip5);
// Attente de la fin de toutes les tâches
$flow->await();
$io->success('Les captures d\'écran ont été générées avec succès.');
return Command::SUCCESS;
}
}
Explication
- Command : La commande
app:carbon-image
permet de générer plusieurs captures d'écran de code en parallèle en utilisant des instances de CarbonImage. - Flow : Flow orchestre l'exécution parallèle des tâches, ce qui est particulièrement utile pour traiter plusieurs extraits de code à la fois.
- Drivers : Flow propose plusieurs drivers pour gérer l'asynchronisme. Ici, un driver est choisi aléatoirement pour démontrer la flexibilité, mais vous pouvez spécifier un driver spécifique selon vos besoins.
- CarbonImage : Chaque instance de
CarbonImage
représente un extrait de code à convertir en image. Le code source et le chemin de sauvegarde sont spécifiés pour chaque instance.
Personnaliser Votre Capture d'Écran
La classe CarbonImageJob
peut être facilement étendue pour accepter différentes configurations de thème, de police, de taille, etc. Voici comment vous pouvez le faire :
- Ajouter des paramètres au constructeur pour la configuration.
- Modifier la méthode
getCarbonUrl
pour inclure ces paramètres dans l'URL de la requête.
Conclusion
Grâce à Symfony Panther et Flow, vous pouvez facilement automatiser la création de captures d'écran de code avec Carbon.now. Cette automatisation peut être particulièrement utile pour les blogueurs, les formateurs, ou tout développeur souhaitant partager du code de manière visuelle.
En intégrant ce processus dans vos workflows, vous gagnerez en temps, en consistance, et en efficacité. N'hésitez pas à adapter cette approche à vos besoins spécifiques et à expérimenter avec les nombreuses options de personnalisation offertes par Carbon.now.
Se former à Flow
Si vous souhaitez approfondir vos connaissances sur le framework Flow et découvrir d'autres moyens d'améliorer votre productivité en tant que développeur, je propose une formation complète sur Flow disponible sur
https://www.bonzai.pro/matyo91/shop