feat: intégration plugin Kirby SEO
All checks were successful
Deploy / Deploy to Production (push) Successful in 22s
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>
This commit is contained in:
parent
baab2fb3a1
commit
58c31ea391
133 changed files with 9201 additions and 253 deletions
86
site/plugins/kirby-seo/classes/Ai/Content.php
Normal file
86
site/plugins/kirby-seo/classes/Ai/Content.php
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue