Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify the $page property and add a fluent metadata helper #388

Merged
merged 22 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9d1134b
Create a helper for fluent metadata configuration
caendesilva May 17, 2022
4b35532
Apply fixes from StyleCI
StyleCIBot May 17, 2022
03fcc9f
Merge pull request #380 from hydephp/analysis-KZENe2
May 17, 2022
7982f9d
Add array_unique
caendesilva May 17, 2022
ab21c60
Add deprecations
caendesilva May 17, 2022
3c80366
Merge branch 'fluent-metadata-handler' of github.com:hydephp/framewor…
caendesilva May 17, 2022
90e9edc
Apply fixes from StyleCI
StyleCIBot May 17, 2022
aaac5be
Merge pull request #383 from hydephp/analysis-J2vnKa
May 17, 2022
683a5a7
Fix #382: Unify the $page property
caendesilva May 17, 2022
a2d79b9
Merge branch 'fluent-metadata-handler' of github.com:hydephp/framewor…
caendesilva May 17, 2022
8574d39
Use view()->share to reduce boilerplate
caendesilva May 17, 2022
2c4f28a
Fix needsDirectory order
caendesilva May 17, 2022
15ccd27
Add test for, and improve Meta helper
caendesilva May 17, 2022
dde528a
Apply fixes from StyleCI
StyleCIBot May 17, 2022
aeaf7eb
Merge pull request #386 from hydephp/analysis-QMbvd3
May 17, 2022
c954bcb
Format and add todo
caendesilva May 17, 2022
e54f3ed
Merge branch 'fluent-metadata-handler' of github.com:hydephp/framewor…
caendesilva May 17, 2022
d7a55ac
Move deprecated method to AuthorService
caendesilva May 17, 2022
e0525ad
Remove unused property
caendesilva May 17, 2022
2b038ba
Apply fixes from StyleCI
StyleCIBot May 17, 2022
a1cce02
Merge pull request #387 from hydephp/analysis-GD9naA
May 17, 2022
cbc07a9
Merge branch 'master' into fluent-metadata-handler
caendesilva May 17, 2022
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
25 changes: 12 additions & 13 deletions config/hyde.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

use Hyde\Framework\Features;
use Hyde\Framework\Meta;

return [

Expand Down Expand Up @@ -70,24 +71,22 @@
| Global Site Meta Tags
|--------------------------------------------------------------------------
|
| While you can add any number of meta tags in the meta.blade.php component,
| these settings allow you to easily add tags for the meta component.
| While you can add any number of meta tags in the meta.blade.php component
| using standard HTML, you can also use the Meta helper. To add a regular
| meta tag, use Meta::name() helper. To add an Open Graph property, use
| Meta::property() helper which also adds the `og:` prefix for you.
|
| The `meta` array is for standard meta tags. See the examples below.
| The `og` array is for Open Graph properties. Do not include the `og:` prefix.
| Please note that these tags might conflict with blog post tags.
|
*/

'meta' => [
// 'author' => 'Mr. Hyde',
// 'twitter:creator' => '@hyde_php',
// 'description' => 'My Hyde Blog',
// 'keywords' => 'Static Sites, Blogs, Documentation',
'generator' => 'HydePHP '.Hyde\Framework\Hyde::version(),
],

'ogProperties' => [
'site_name' => $siteName,
// Meta::name('author', 'Mr. Hyde'),
// Meta::name('twitter:creator', '@hyde_php'),
// Meta::name('description', 'My Hyde Blog'),
// Meta::name('keywords', 'Static Sites, Blogs, Documentation'),
Meta::name('generator', 'HydePHP '.Hyde\Framework\Hyde::version()),
Meta::property('site_name', $siteName),
],

/*
Expand Down
14 changes: 7 additions & 7 deletions resources/views/components/post/article.blade.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<article aria-label="Article" id="{{ Hyde::uriPath() ?? '' }}posts/{{ $post->slug }}" itemscope itemtype="https://schema.org/Article"
<article aria-label="Article" id="{{ Hyde::uriPath() ?? '' }}posts/{{ $page->slug }}" itemscope itemtype="https://schema.org/Article"
@class(['post-article mx-auto prose dark:prose-invert', 'torchlight-enabled' => Hyde\Framework\Features::hasTorchlight()])>
<meta itemprop="identifier" content="{{ $post->slug }}">
<meta itemprop="identifier" content="{{ $page->slug }}">
@if(Hyde::uriPath())
<meta itemprop="url" content="{{ Hyde::uriPath('posts/' . $post->slug) }}">
<meta itemprop="url" content="{{ Hyde::uriPath('posts/' . $page->slug) }}">
@endif

<header aria-label="Header section" role="doc-pageheader">
<h1 itemprop="headline" class="mb-4">{{ $title ?? 'Blog Post' }}</h1>
<div id="byline" aria-label="About the post" role="doc-introduction">
@includeWhen(isset($post->date), 'hyde::components.post.date')
@includeWhen(isset($post->author), 'hyde::components.post.author')
@includeWhen(isset($post->category), 'hyde::components.post.category')
@includeWhen(isset($page->date), 'hyde::components.post.date')
@includeWhen(isset($page->author), 'hyde::components.post.author')
@includeWhen(isset($page->category), 'hyde::components.post.category')
</div>
</header>
@includeWhen(isset($post->image), 'hyde::components.post.image')
@includeWhen(isset($page->image), 'hyde::components.post.image')
<div aria-label="Article body" itemprop="articleBody">
{!! $markdown !!}
</div>
Expand Down
8 changes: 4 additions & 4 deletions resources/views/components/post/author.blade.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
by author
<address itemprop="author" itemscope itemtype="https://schema.org/Person" aria-label="The post author" style="display: inline;">
@if($post->author->website)
<a href="{{ $post->author->website }}" rel="author" itemprop="url" aria-label="The author's website">
@if($page->author->website)
<a href="{{ $page->author->website }}" rel="author" itemprop="url" aria-label="The author's website">
@endif
<span itemprop="name" aria-label="The author's name" {{ ($post->author->username && ($post->author->username !== $post->author->name)) ? 'title=@'. urlencode($post->author->username) .'' : '' }}>{{ $post->author->name ?? $post->author->username }}</span>
@if($post->author->website)
<span itemprop="name" aria-label="The author's name" {{ ($page->author->username && ($page->author->username !== $page->author->name)) ? 'title=@'. urlencode($page->author->username) .'' : '' }}>{{ $page->author->name ?? $page->author->username }}</span>
@if($page->author->website)
</a>
@endif
</address>
2 changes: 1 addition & 1 deletion resources/views/components/post/category.blade.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
in the category "{{ $post->category }}"
in the category "{{ $page->category }}"
2 changes: 1 addition & 1 deletion resources/views/components/post/date.blade.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Posted <time itemprop="dateCreated datePublished" datetime="{{ $post->date->datetime }}" title="{{ $post->date->sentence }}">{{ $post->date->short }}</time>
Posted <time itemprop="dateCreated datePublished" datetime="{{ $page->date->datetime }}" title="{{ $page->date->sentence }}">{{ $page->date->short }}</time>
2 changes: 1 addition & 1 deletion resources/views/components/post/description.blade.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<p itemprop="abstract">
{{ $post->matter['description'] }}
{{ $page->matter['description'] }}
</p>
6 changes: 3 additions & 3 deletions resources/views/components/post/image.blade.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<figure aria-label="Cover image" role="doc-cover" itemprop="image" itemscope itemtype="https://schema.org/ImageObject">
<img src="{{ $post->image->getSource() }}" alt="{{ $post->image->description ?? '' }}" title="{{ $post->image->title ?? '' }}" itemprop="image" class="mb-0">
<img src="{{ $page->image->getSource() }}" alt="{{ $page->image->description ?? '' }}" title="{{ $page->image->title ?? '' }}" itemprop="image" class="mb-0">
<figcaption aria-label="Image caption" itemprop="caption">
{!! $post->image->getFluentAttribution() !!}
{!! $page->image->getFluentAttribution() !!}
</figcaption>
@foreach ($post->image->getMetadataArray() as $name => $value)
@foreach ($page->image->getMetadataArray() as $name => $value)
<meta itemprop="{{ $name }}" content="{{ $value }}">
@endforeach
</figure>
9 changes: 1 addition & 8 deletions resources/views/layouts/meta.blade.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
{{-- Config Defined Meta Tags --}}
@foreach (config('hyde.meta', []) as $name => $content)
<meta name="{{ $name }}" content="{{ $content }}">
@endforeach

@foreach (config('hyde.ogProperties', []) as $property => $content)
<meta property="og:{{ $property }}" content="{{ $content }}">
@endforeach
{!! Hyde\Framework\Meta::render() !!}

{{-- Add any extra tags to include in the <head> section --}}
@stack('meta')

4 changes: 2 additions & 2 deletions resources/views/layouts/post.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

@push('meta')
<!-- Blog Post Meta Tags -->
@foreach ($post->getMetadata() as $name => $content)
@foreach ($page->getMetadata() as $name => $content)
<meta name="{{ $name }}" content="{{ $content }}">
@endforeach
@foreach ($post->getMetaProperties() as $name => $content)
@foreach ($page->getMetaProperties() as $name => $content)
<meta property="{{ $name }}" content="{{ $content }}">
@endforeach
@endpush
Expand Down
39 changes: 16 additions & 23 deletions src/Concerns/HasMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Hyde\Framework\Hyde;
use Hyde\Framework\Models\Metadata;
use Hyde\Framework\Services\AuthorService;
use JetBrains\PhpStorm\ArrayShape;

/**
Expand All @@ -12,6 +13,9 @@
*
* @see \Hyde\Framework\Models\Metadata
* @see \Tests\Feature\Concerns\HasMetadataTest
*
* @todo Unify the $page property and handle metadata through it
* @todo Only add blog post properties if the page is a blog post
*/
trait HasMetadata
{
Expand All @@ -25,14 +29,14 @@ public function constructMetadata(): void
}

#[ArrayShape(['name' => "\content"])]
public function getMetadata(): array
{
if (! isset($this->metadata)) {
return [];
}
public function getMetadata(): array
{
if (! isset($this->metadata)) {
return [];
}

return $this->metadata->metadata;
}
return $this->metadata->metadata;
}

#[ArrayShape(['property' => 'content'])]
public function getMetaProperties(): array
Expand All @@ -46,6 +50,8 @@ public function getMetaProperties(): array

/**
* Generate metadata from the front matter that can be used in standard <meta> tags.
*
* @deprecated Will be refactored to parseFrontMatterMetadata
*/
protected function makeMetadata(): void
{
Expand All @@ -54,7 +60,7 @@ protected function makeMetadata(): void
}

if (isset($this->matter['author'])) {
$this->metadata->add('author', $this->getAuthor($this->matter['author']));
$this->metadata->add('author', AuthorService::getAuthorName($this->matter['author']));
}

if (isset($this->matter['category'])) {
Expand All @@ -65,6 +71,8 @@ protected function makeMetadata(): void
/**
* Generate metadata from the front matter that can be used for og:type <meta> tags.
* Note that this currently assumes that the object using it is a Blog Post.
*
* @deprecated Will be refactored to parseFrontMatterMetadata
*/
protected function makeMetaProperties(): void
{
Expand Down Expand Up @@ -96,19 +104,4 @@ protected function makeMetaProperties(): void
}
}
}

/**
* Parse the author string from the front matter with support for both flat and array notation.
*
* @param string|array $author
* @return string
*/
protected function getAuthor(string|array $author): string
{
if (is_string($author)) {
return $author;
}

return $author['username'] ?? $author['name'] ?? 'Guest';
}
}
62 changes: 62 additions & 0 deletions src/Meta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Hyde\Framework;

/**
* Helpers to fluently declare HTML meta tags.
*
* @see \Tests\Feature\MetadataHelperTest
*/
class Meta
{
public static function name(string $name, string $content): string
{
return '<meta name="'.e($name).'" content="'.e($content).'">';
}

public static function property(string $property, string $content): string
{
$property = static::formatOpenGraphProperty($property);

return '<meta property="'.e($property).'" content="'.e($content).'">';
}

public static function render(array $overridesGlobalMeta = []): string
{
return implode("\n",
static::filterUnique(
array_merge(
static::getGlobalMeta(),
$overridesGlobalMeta
)
)
);
}

protected static function filterUnique(array $meta): array
{
$array = [];
$existing = [];

foreach ($meta as $metaItem) {
$substring = substr($metaItem, 6, strpos($metaItem, ' content="') - 6);

if (! in_array($substring, $existing)) {
$array[] = $metaItem;
$existing[] = $substring;
}
}

return $array;
}

public static function getGlobalMeta(): array
{
return config('hyde.meta', []);
}

protected static function formatOpenGraphProperty(string $property): string
{
return str_starts_with($property, 'og:') ? $property : 'og:'.$property;
}
}
2 changes: 2 additions & 0 deletions src/Models/Metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
/**
* Metadata class for storing metadata about a model.
* Is used in Blade views to create <meta> tags.
*
* @deprecated Will be merged with Meta class
*/
class Metadata
{
Expand Down
15 changes: 15 additions & 0 deletions src/Services/AuthorService.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,19 @@ public static function find(string $username, bool $forgiving = true): Author|fa

return $service->authors->firstWhere('username', $username) ?? false;
}

/**
* Parse the author name string from front matter with support for both flat and array notation.
*
* @param string|array $author
* @return string
*/
public static function getAuthorName(string|array $author): string
{
if (is_string($author)) {
return $author;
}

return $author['name'] ?? $author['username'] ?? 'Guest';
}
}
8 changes: 4 additions & 4 deletions src/StaticPageBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ class StaticPageBuilder
*/
public function __construct(protected MarkdownDocument|BladePage $page, bool $selfInvoke = false)
{
$this->needsDirectory(static::$outputPath);

if ($selfInvoke) {
$this->__invoke();
}

$this->needsDirectory(static::$outputPath);
}

/**
Expand All @@ -44,6 +44,8 @@ public function __construct(protected MarkdownDocument|BladePage $page, bool $se
*/
public function __invoke()
{
view()->share('page', $this->page);

if ($this->page instanceof BladePage) {
return $this->save($this->page->view, $this->compileView());
}
Expand Down Expand Up @@ -98,7 +100,6 @@ private function compileView(): string
private function compilePost(): string
{
return view('hyde::layouts/post')->with([
'post' => $this->page,
'title' => $this->page->title,
'markdown' => MarkdownConverter::parse($this->page->body),
'currentPage' => 'posts/'.$this->page->slug,
Expand Down Expand Up @@ -127,7 +128,6 @@ private function compilePage(): string
private function compileDocs(): string
{
return view('hyde::layouts/docs')->with([
'docs' => $this->page,
'title' => $this->page->title,
'markdown' => MarkdownConverter::parse($this->page->body, DocumentationPage::class),
'currentPage' => Hyde::docsDirectory().'/'.$this->page->slug,
Expand Down
17 changes: 17 additions & 0 deletions tests/Feature/AuthorServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,21 @@ public function test_get_yaml_method_returns_empty_array_if_file_does_not_contai

$this->assertEquals([], $service->getYaml());
}

public function test_get_author_name_helper_returns_string_for_string()
{
$this->assertEquals('foo', AuthorService::getAuthorName('foo'));
}

public function test_get_author_name_helper_returns_string_for_array()
{
$this->assertEquals('foo', AuthorService::getAuthorName(['name' => 'foo']));
}

public function test_get_author_name_helper_returns_string_for_array_with_proper_fallback_priorities()
{
$this->assertEquals('foo', AuthorService::getAuthorName(['name' => 'foo', 'username' => 'bar']));
$this->assertEquals('bar', AuthorService::getAuthorName(['username' => 'bar']));
$this->assertEquals('Guest', AuthorService::getAuthorName([]));
}
}
Loading