Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ This serves two purposes:
- Added Vite facade in https://github.com/hydephp/develop/pull/2016
- Added a custom Blade-based heading renderer for Markdown conversions in https://github.com/hydephp/develop/pull/2047
- The `publish:views` command is now interactive for Unix-like systems in https://github.com/hydephp/develop/pull/2062
- Added a new simplified blog post image front matter schema using a new "caption" field in https://github.com/hydephp/develop/pull/2175

### Changed

Expand Down
15 changes: 13 additions & 2 deletions docs/creating-content/blog-posts.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ The image source will be used as-is, and no additional processing is done.
image: https://cdn.example.com/image.jpg
```

#### Data-rich image
#### Data-rich image and captions

You can also supply an array of data to construct a rich image with a fluent caption.

Expand All @@ -226,9 +226,20 @@ image:
licenseUrl: https://example.com/license/
authorUrl: https://photographer.example.com/
authorName: "John Doe"
caption: "Overrides the fluent caption feature"
```

>info See [posts/introducing-images](https://hydephp.com/posts/introducing-images) for a detailed blog post with examples and schema information!
The data will then be used for metadata and to render a fluently worded caption. If you just want to add a quick caption, you can instead simply set the "caption field" to override the caption; or if you simply want a caption and no metadata this is a quick option as well.
```yaml
image:
source: how-to-turn-your-github-readme-into-a-static-website-cropped.png
alt: Example of a static website created from a GitHub Readme
caption: Static website from GitHub Readme with **Markdown** support!
```

The caption field supports inline Markdown formatting like **bold**, *italic*, and [links](https://example.com). This makes it easy to add rich text formatting to your image captions.

If the `alt` field is missing, the caption will be used as the alt text as well.

## Using Images in Posts

Expand Down
2 changes: 1 addition & 1 deletion docs/creating-content/managing-assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,4 @@ To improve accessibility, you should always add an `alt` text. Here is a full ex

Hyde offers great support for creating data-rich and accessible featured images for blog posts.

You can read more about this on the [creating blog posts page](blog-posts#image).
You can read more about this on the [creating blog posts page](blog-posts#data-rich-image-and-captions).
46 changes: 26 additions & 20 deletions packages/framework/resources/views/components/post/image.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,39 @@
/** @var \Hyde\Pages\MarkdownPost $page */
/** @var \Hyde\Framework\Features\Blogging\Models\FeaturedImage $image */
$image = $page->image;

use Illuminate\Support\Str;
@endphp
<figure aria-label="Cover image" itemprop="image" itemscope itemtype="https://schema.org/ImageObject" role="doc-cover">
<img src="{{ $image->getSource() }}" alt="{{ $image->getAltText() ?? '' }}" title="{{ $image->getTitleText() ?? '' }}" itemprop="image" class="mb-0">
<figcaption aria-label="Image caption" itemprop="caption">
@if($image->hasAuthorName())
<span>Image by</span>
<span itemprop="creator" itemscope="" itemtype="https://schema.org/Person">
@if($image->hasAuthorUrl())
<a href="{{ $image->getAuthorUrl() }}" rel="author noopener nofollow" itemprop="url">
@if($image->hasCaption())
<span>{!! Str::inlineMarkdown($image->getCaption()) !!}</span>
@else
@if($image->hasAuthorName())
<span>Image by</span>
<span itemprop="creator" itemscope="" itemtype="https://schema.org/Person">
@if($image->hasAuthorUrl())
<a href="{{ $image->getAuthorUrl() }}" rel="author noopener nofollow" itemprop="url">
<span itemprop="name">{{ $image->getAuthorName() }}</span>.
</a>
@else
<span itemprop="name">{{ $image->getAuthorName() }}</span>.
</a>
@else
<span itemprop="name">{{ $image->getAuthorName() }}</span>.
@endif
</span>
@endif
@endif
</span>
@endif

@if($image->hasCopyrightText())
<span itemprop="copyrightNotice">{{ $image->getCopyrightText() }}</span>.
@endif
@if($image->hasCopyrightText())
<span itemprop="copyrightNotice">{{ $image->getCopyrightText() }}</span>.
@endif

@if($image->hasLicenseName())
<span>License</span>
@if($image->hasLicenseUrl())
<a href="{{ $image->getLicenseUrl() }}" rel="license nofollow noopener" itemprop="license">{{ $image->getLicenseName() }}</a>.
@else
<span itemprop="license">{{ $image->getLicenseName() }}</span>.
@if($image->hasLicenseName())
<span>License</span>
@if($image->hasLicenseUrl())
<a href="{{ $image->getLicenseUrl() }}" rel="license nofollow noopener" itemprop="license">{{ $image->getLicenseName() }}</a>.
@else
<span itemprop="license">{{ $image->getLicenseName() }}</span>.
@endif
@endif
@endif
</figcaption>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,25 @@ class FeaturedImageFactory extends Concerns\PageDataFactory implements FeaturedI
protected readonly ?string $copyrightText;
protected readonly ?string $licenseName;
protected readonly ?string $licenseUrl;
protected readonly ?string $caption;

public function __construct(
private readonly FrontMatter $matter,
private readonly ?string $filePath = null,
) {
$this->source = $this->makeSource();
$this->altText = $this->getStringMatter('image.altText');
$this->altText = $this->getStringMatter('image.altText') ?? $this->getStringMatter('image.alt');
$this->titleText = $this->getStringMatter('image.titleText');
$this->authorName = $this->getStringMatter('image.authorName');
$this->authorUrl = $this->getStringMatter('image.authorUrl');
$this->copyrightText = $this->getStringMatter('image.copyright');
$this->licenseName = $this->getStringMatter('image.licenseName');
$this->licenseUrl = $this->getStringMatter('image.licenseUrl');
$this->caption = $this->getStringMatter('image.caption');
}

/**
* @return array{source: string, altText: string|null, titleText: string|null, authorName: string|null, authorUrl: string|null, copyrightText: string|null, licenseName: string|null, licenseUrl: string|null}
* @return array{source: string, altText: string|null, titleText: string|null, authorName: string|null, authorUrl: string|null, copyrightText: string|null, licenseName: string|null, licenseUrl: string|null, caption: string|null}
*/
public function toArray(): array
{
Expand All @@ -57,6 +59,7 @@ public function toArray(): array
'copyrightText' => $this->copyrightText,
'licenseName' => $this->licenseName,
'licenseUrl' => $this->licenseUrl,
'caption' => $this->caption,
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public function __construct(
protected readonly ?string $authorUrl = null,
protected readonly ?string $licenseName = null,
protected readonly ?string $licenseUrl = null,
protected readonly ?string $copyrightText = null
protected readonly ?string $copyrightText = null,
protected readonly ?string $caption = null
) {
$this->type = Hyperlinks::isRemote($source) ? self::TYPE_REMOTE : self::TYPE_LOCAL;
$this->source = $this->setSource($source);
Expand Down Expand Up @@ -127,6 +128,10 @@ public function getMetadataArray(): array
$metadata['name'] = $this->getTitleText();
}

if ($this->hasCaption()) {
$metadata['caption'] = $this->getCaption();
}

$metadata['url'] = $this->getSource();
$metadata['contentUrl'] = $this->getSource();

Expand All @@ -135,7 +140,7 @@ public function getMetadataArray(): array

public function getAltText(): ?string
{
return $this->altText;
return $this->altText ?? $this->caption;
}

public function getTitleText(): ?string
Expand Down Expand Up @@ -168,6 +173,11 @@ public function getLicenseUrl(): ?string
return $this->licenseUrl;
}

public function getCaption(): ?string
{
return $this->caption;
}

public function hasAltText(): bool
{
return $this->has('altText');
Expand Down Expand Up @@ -203,6 +213,11 @@ public function hasLicenseUrl(): bool
return $this->has('licenseUrl');
}

public function hasCaption(): bool
{
return $this->has('caption');
}

protected function has(string $property): bool
{
return $this->$property !== null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ interface FeaturedImageSchema extends BlogPostSchema
{
public const FEATURED_IMAGE_SCHEMA = [
'source' => 'string', // Name of a file in _media/ or a remote URL (required)
'altText' => 'string', // The alt text (important for accessibility) // todo: Support alt, description
'titleText' => 'string', // The title text (hover tooltip & metadata) // todo: Support title, caption
'altText' => 'string', // The alt text (important for accessibility)
'alt' => 'string', // Alternative to altText (simplified schema)
'titleText' => 'string', // The title text (hover tooltip & metadata)
'caption' => 'string', // The caption text (simplified schema)
'licenseName' => 'string', // The name of the license (e.g. "CC BY 4.0")
'licenseUrl' => 'string', // The URL of the license (e.g. "https://creativecommons.org/licenses/by/4.0/")
'authorName' => 'string', // The name of the author/photographer of the image (e.g. "John Doe", Wikimedia Commons)
Expand Down
38 changes: 38 additions & 0 deletions packages/framework/tests/Feature/FeaturedImageFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function testWithDataFromSchema()
'copyrightText' => 'copyright',
'licenseName' => 'license',
'licenseUrl' => 'licenseUrl',
'caption' => null,
];

$factory = new FeaturedImageFactory(new FrontMatter($array));
Expand Down Expand Up @@ -146,6 +147,43 @@ public function testImagePathsWithCacheBusting()
$this->assertSourceIsSame('media/foo?v=00000000', ['image' => ['source' => '_media/foo']]);
}

public function testSupportsSimplifiedImageSchema()
{
$array = [
'image' => [
'source' => 'source',
'alt' => 'Alternative text',
'caption' => 'Static website from GitHub Readme',
],
];

$factory = new FeaturedImageFactory(new FrontMatter($array));
$image = FeaturedImageFactory::make(new FrontMatter($array));

$this->assertSame('source', $factory->toArray()['source']);
$this->assertSame('Alternative text', $factory->toArray()['altText']);
$this->assertSame('Static website from GitHub Readme', $factory->toArray()['caption']);

$this->assertSame('Alternative text', $image->getAltText());
$this->assertSame('Static website from GitHub Readme', $image->getCaption());
}

public function testFallsBackToCaptionWhenAltIsMissing()
{
$array = [
'image' => [
'source' => 'source',
'caption' => 'This caption should be used as alt text',
],
];

$image = FeaturedImageFactory::make(new FrontMatter($array));

$this->assertFalse($image->hasAltText());
$this->assertSame('This caption should be used as alt text', $image->getAltText());
$this->assertSame('This caption should be used as alt text', $image->getCaption());
}

protected function makeFromArray(array $matter): FeaturedImage
{
return FeaturedImageFactory::make(new FrontMatter($matter));
Expand Down
9 changes: 9 additions & 0 deletions packages/framework/tests/Feature/FeaturedImageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ public function testGetMetadataArray()
'contentUrl' => 'media/source',
], (new FilledImage)->getMetadataArray());

// Test with caption
$this->assertSame([
'text' => 'alt',
'name' => 'title',
'caption' => 'This is a caption',
'url' => 'media/source',
'contentUrl' => 'media/source',
], (new FeaturedImage('source', 'alt', 'title', null, null, null, null, null, 'This is a caption'))->getMetadataArray());

$this->assertSame([
'url' => 'media/source',
'contentUrl' => 'media/source',
Expand Down
2 changes: 2 additions & 0 deletions packages/framework/tests/Unit/SchemaContractsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ public function testSchemasAreNotAccidentallyChanged()
$this->assertSame([
'source' => 'string',
'altText' => 'string',
'alt' => 'string',
'titleText' => 'string',
'caption' => 'string',
'licenseName' => 'string',
'licenseUrl' => 'string',
'authorName' => 'string',
Expand Down
Loading
Loading