mirror of
https://github.com/archtechx/laravel-seo.git
synced 2025-12-12 18:04:03 +00:00
Add previewify image provider
This commit is contained in:
parent
754b3936d0
commit
d12038f207
5 changed files with 140 additions and 6 deletions
39
README.md
39
README.md
|
|
@ -7,7 +7,7 @@ By default, it uses `<title>` and OpenGraph tags. It also ships with a Twitter e
|
|||
**Features**:
|
||||
- Setting SEO tags from PHP
|
||||
- Setting SEO tags from Blade
|
||||
- Integration with [Flipp](https://useflipp.com), to automatically generate cover images
|
||||
- Integration with [Flipp](https://useflipp.com) and [Previewify](https://previewify.app), to automatically generate cover images
|
||||
- Custom extension support
|
||||
- Expressive & simple API
|
||||
- Customizable views
|
||||
|
|
@ -215,6 +215,43 @@ The `flipp()` method also returns a signed URL to the image, which lets you use
|
|||
<img alt="@seo('title')" src="@seo('flipp', 'blog')">
|
||||
```
|
||||
|
||||
### Previewify integration
|
||||
|
||||
First, you need to add your Previewify API keys:
|
||||
1. Add your API key to the `PREVIEWIFY_KEY` environment variable. You can get the key [here](https://previewify.app/app/account).
|
||||
2. Go to `config/services.php` and add:
|
||||
```php
|
||||
'previewify' => [
|
||||
'key' => env('PREVIEWIFY_KEY'),
|
||||
],
|
||||
```
|
||||
|
||||
Then, register your templates, for example in `AppServiceProvider`:
|
||||
```php
|
||||
seo()->previewify('blog', 24);
|
||||
seo()->previewify('page', 83);
|
||||
```
|
||||
|
||||
After that, you can use the templates by calling `seo()->previewify()` like this:
|
||||
```php
|
||||
seo()->previewify('blog', ['title' => 'Foo', 'content' => 'bar'])`
|
||||
```
|
||||
|
||||
The call will set the generated image as the OpenGraph and Twitter card images. The generated URLs are signed.
|
||||
|
||||
If no data array is provided, the method will use the `title` and `description` from the current SEO config:
|
||||
|
||||
```php
|
||||
seo()->title($post->title);
|
||||
seo()->description($post->excerpt);
|
||||
seo()->previewify('blog');
|
||||
```
|
||||
|
||||
The `previewify()` method also returns a signed URL to the image, which lets you use it in other places, such as blog cover images.
|
||||
```php
|
||||
<img alt="@seo('title')" src="@seo('previewify', 'blog')">
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Service Provider
|
||||
|
|
|
|||
|
|
@ -14,5 +14,6 @@ parameters:
|
|||
|
||||
ignoreErrors:
|
||||
# Waiting for https://github.com/phpstan/phpstan/issues/5706
|
||||
- '#^Cannot call method (flipp|get|set)\(\) on ArchTech\\SEO\\SEOManager\|array\|string\|null\.$#'
|
||||
- '#^Cannot call method (flipp|previewify|get|set)\(\) on ArchTech\\SEO\\SEOManager\|array\|string\|null\.$#'
|
||||
- '#^Method ArchTech\\SEO\\SEOManager::flipp\(\) should return static\(ArchTech\\SEO\\SEOManager\)\|string but returns array\|string\|null\.$#'
|
||||
- '#^Method ArchTech\\SEO\\SEOManager::previewify\(\) should return static\(ArchTech\\SEO\\SEOManager\)\|string but returns array\|string\|null\.$#'
|
||||
|
|
|
|||
|
|
@ -180,6 +180,32 @@ class SEOManager
|
|||
return $this->set('image', "https://s.useflipp.com/{$template}.png?s={$signature}&v={$query}");
|
||||
}
|
||||
|
||||
/** Configure or use Previewify. */
|
||||
public function previewify(string $alias, int|string|array $data = null): string|static
|
||||
{
|
||||
if (is_string($data) || is_int($data)) {
|
||||
$this->meta("previewify.templates.$alias", (string) $data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($data === null) {
|
||||
$data = [
|
||||
'title' => $this->raw('title'),
|
||||
'description' => $this->raw('description'),
|
||||
];
|
||||
}
|
||||
|
||||
$query = base64_encode(json_encode($data, JSON_THROW_ON_ERROR));
|
||||
|
||||
/** @var string $template */
|
||||
$template = $this->meta("previewify.templates.$alias");
|
||||
|
||||
$signature = hash_hmac('sha256', $query, config('services.previewify.key'));
|
||||
|
||||
return $this->set('image', "https://previewify.app/generate/templates/{$template}/signed?signature={$signature}&fields={$query}");
|
||||
}
|
||||
|
||||
/** Enable favicon extension. */
|
||||
public function favicon(): static
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ class SEOServiceProvider extends ServiceProvider
|
|||
], 'seo-views');
|
||||
|
||||
BladeHelper::directive('seo', function (...$args) {
|
||||
// Flipp supports more arguments
|
||||
if ($args[0] === 'flipp') {
|
||||
array_shift($args);
|
||||
// Flipp and Previewify support more arguments
|
||||
if (in_array($args[0], ['flipp', 'previewify'], true)) {
|
||||
$method = array_shift($args);
|
||||
|
||||
return seo()->flipp(...$args);
|
||||
return seo()->{$method}(...$args);
|
||||
}
|
||||
|
||||
// Two arguments indicate that we're setting a value, e.g. `@seo('title', 'foo')
|
||||
|
|
|
|||
70
tests/Pest/PreviewifyTest.php
Normal file
70
tests/Pest/PreviewifyTest.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
beforeEach(fn () => config(['services.previewify.key' => 'abc']));
|
||||
|
||||
test('previewify templates can be set', function () {
|
||||
seo()->previewify('blog', 1);
|
||||
|
||||
expect(seo()->meta('previewify.templates'))
|
||||
->toHaveCount(1)
|
||||
->toHaveKey('blog', '1');
|
||||
});
|
||||
|
||||
test('previewify makes a request to the template not the alias', function () {
|
||||
seo()->previewify('blog', 1);
|
||||
expect(seo()->previewify('blog'))
|
||||
->toContain('previewify.app/generate/templates/1');
|
||||
});
|
||||
|
||||
test('previewify templates can be given data', function () {
|
||||
seo()->previewify('blog', 1);
|
||||
expect(seo()->previewify('blog', ['title' => 'abc', 'excerpt' => 'def']))
|
||||
->toContain('previewify.app/generate/templates/1')
|
||||
->toContain(base64_encode(json_encode(['title' => 'abc', 'excerpt' => 'def'])));
|
||||
});
|
||||
|
||||
test('the previewify method returns a link to a signed url', function () {
|
||||
seo()->previewify('blog', 1);
|
||||
|
||||
expect(seo()->previewify('blog', ['title' => 'abc']))
|
||||
->toContain('?signature=' . hash_hmac('sha256', base64_encode(json_encode(['title' => 'abc'])), config('services.previewify.key')));
|
||||
});
|
||||
|
||||
test("previewify templates use default data when they're not passed any data explicitly", function () {
|
||||
seo()->previewify('blog', 1);
|
||||
|
||||
seo()->title('foo')->description('bar');
|
||||
|
||||
expect(seo()->previewify('blog'))
|
||||
->toContain('previewify.app/generate/templates/1')
|
||||
->toContain(base64_encode(json_encode(['title' => 'foo', 'description' => 'bar'])));
|
||||
});
|
||||
|
||||
test('previewify images are used as the cover images', function () {
|
||||
seo()->previewify('blog', 1);
|
||||
|
||||
seo()->title('foo')->description('bar');
|
||||
|
||||
expect(seo()->previewify('blog'))
|
||||
->toBe(seo('image'));
|
||||
});
|
||||
|
||||
test('the blade directive can be used with previewify', function () {
|
||||
seo()->previewify('blog', 1);
|
||||
|
||||
seo()->title('foo')->description('bar');
|
||||
|
||||
expect(blade("@seo('previewify', 'blog')"))->toBe(seo()->previewify('blog'));
|
||||
expect(blade("@seo('previewify', 'blog', ['title' => 'abc'])"))->toBe(seo()->previewify('blog', ['title' => 'abc']));
|
||||
});
|
||||
|
||||
test('previewify uses the raw title and description', function () {
|
||||
seo()->previewify('blog', 1);
|
||||
|
||||
seo()->title(modify: fn (string $title) => $title . ' - modified');
|
||||
seo()->title('foo')->description('bar');
|
||||
|
||||
expect(seo()->previewify('blog'))
|
||||
->toContain('previewify.app/generate/templates/1')
|
||||
->toContain(base64_encode(json_encode(['title' => 'foo', 'description' => 'bar'])));
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue