All checks were successful
Deploy / Deploy to Production (push) Successful in 22s
- Ajout de tobimori/kirby-seo via Composer
- snippet('seo/head') dans header.php (remplace les meta manuels)
- snippet('seo/schemas') dans footer.php pour JSON-LD
- Onglet SEO ajouté dans site.yml et tous les blueprints de pages
- Configuration SEO dans config.php (sitemap, robots, canonicalBase TODO)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
86 lines
1.7 KiB
PHP
86 lines
1.7 KiB
PHP
<?php
|
|
|
|
namespace tobimori\Seo\Ai;
|
|
|
|
use Imagick;
|
|
use Kirby\Cms\File;
|
|
|
|
/**
|
|
* Fluent builder for AI message content.
|
|
* Each instance represents a single message with a role and content blocks.
|
|
*/
|
|
class Content
|
|
{
|
|
private string $role;
|
|
private array $blocks = [];
|
|
|
|
private function __construct(string $role)
|
|
{
|
|
$this->role = $role;
|
|
}
|
|
|
|
public static function user(): static
|
|
{
|
|
return new static('user');
|
|
}
|
|
|
|
public static function assistant(): static
|
|
{
|
|
return new static('assistant');
|
|
}
|
|
|
|
public static function system(): static
|
|
{
|
|
return new static('system');
|
|
}
|
|
|
|
public function text(string $text): static
|
|
{
|
|
$this->blocks[] = ['type' => 'text', 'text' => $text];
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Adds an image block from a Kirby File, converted to WebP for smaller payloads.
|
|
* Non-resizable formats (SVG, etc.) are rasterized via Imagick.
|
|
*/
|
|
public function image(File $file, int $maxDimension = 1024): static
|
|
{
|
|
if ($file->isResizable()) {
|
|
$thumb = $file->thumb([
|
|
'width' => $maxDimension,
|
|
'height' => $maxDimension,
|
|
'format' => 'webp',
|
|
]);
|
|
|
|
$data = base64_encode($thumb->read());
|
|
} else {
|
|
// TODO: better handling without ext-imagick
|
|
$imagick = new Imagick();
|
|
$imagick->readImage($file->root());
|
|
$imagick->setImageFormat('webp');
|
|
$imagick->thumbnailImage($maxDimension, $maxDimension, true);
|
|
$data = base64_encode($imagick->getImageBlob());
|
|
$imagick->clear();
|
|
$imagick->destroy();
|
|
}
|
|
|
|
$this->blocks[] = [
|
|
'type' => 'image',
|
|
'data' => $data,
|
|
'mediaType' => 'image/webp',
|
|
];
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function role(): string
|
|
{
|
|
return $this->role;
|
|
}
|
|
|
|
public function blocks(): array
|
|
{
|
|
return $this->blocks;
|
|
}
|
|
}
|