diff --git a/app/BlogPosts/TableOfContents.php b/app/BlogPosts/TableOfContents.php new file mode 100644 index 00000000..563917d4 --- /dev/null +++ b/app/BlogPosts/TableOfContents.php @@ -0,0 +1,44 @@ +raw = $html; + $this->_process(); + } + + public function toc () + { + return $this->_toc; + } + + public function html () + { + return $this->_parsedHtml; + } + + private function _process () + { + $this->_toc = []; + + $html = preg_replace_callback("/([^<]+)<\/h/", function($matches) { + $id = Str::random(8); + $this->_toc[] = (object) [ + 'priority' => intval($matches[1]), + 'id' => $id, + 'text' => $matches[3] + ]; + return ''.$matches[3].'raw); + + $this->_parsedHtml = $html; + } +} diff --git a/app/Http/Controllers/Website/BlogController.php b/app/Http/Controllers/Website/BlogController.php index 6db1212f..65243a34 100644 --- a/app/Http/Controllers/Website/BlogController.php +++ b/app/Http/Controllers/Website/BlogController.php @@ -5,6 +5,7 @@ use App\Http\Controllers\Controller; use App\Models\BlogPost; use Illuminate\Http\Request; +use Spatie\SchemaOrg\Schema; class BlogController extends Controller { @@ -17,17 +18,30 @@ public function index(): \Illuminate\Contracts\View\View public function detail(BlogPost $blog): \Illuminate\Contracts\View\View { - if (! auth()->user()?->emailIsFromCodex()) { - abort_if(! $blog->is_visible, 404); + if (!auth()->user()?->emailIsFromCodex()) { + abort_if(!$blog->is_visible, 404); } $blogIds = collect($blog->related_blogs); $otherBlogs = BlogPost::query()->whereIn('id', $blogIds)->get(); + $schema = Schema::blogPosting() + ->headline($blog->title) + ->articleBody($blog->markdown_content) + ->author(Schema::person()->name(config('codex.blog_author'))) + ->datePublished($blog->published_at->toIso8601String()) + ->dateModified($blog->updated_at->toIso8601String()) + ->mainEntityOfPage(Schema::webPage()->url(url()->current())) + ->publisher(Schema::organization() + ->name('CodexAtlas Blog') + ->logo(Schema::imageObject()->url(asset('images/logo.png')))) + ->image($blog->image_url); + return view('blog.blog-detail', [ 'blog' => $blog, 'otherBlogs' => $otherBlogs, + 'schema' => $schema, ]); } } diff --git a/app/Models/BlogPost.php b/app/Models/BlogPost.php index df46aa2e..ac398f1f 100644 --- a/app/Models/BlogPost.php +++ b/app/Models/BlogPost.php @@ -2,12 +2,14 @@ namespace App\Models; +use App\BlogPosts\TableOfContents; use App\Models\Traits\HasUserFeedback; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Str; use Spatie\Sluggable\HasSlug; use Spatie\Sluggable\SlugOptions; @@ -105,4 +107,11 @@ public function getTailGraphUrl(): string return $image; } + + public function transformedContent(): Attribute + { + return Attribute::make( + get: fn () => new TableOfContents(Str::markdown($this->markdown_content)) + ); + } } diff --git a/composer.json b/composer.json index 058f1f89..51e3cbe1 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "borah/knowledge-base-laravel": "^0.7", "borahlabs/aws-marketplace-saas-laravel": "^1.0", "convertkit/convertkitapi": "^1.3", + "diglactic/laravel-breadcrumbs": "^9.0", "filament/filament": "^3.2", "filament/forms": "^3.2", "graham-campbell/bitbucket": "^10.4", @@ -30,8 +31,9 @@ "lorisleiva/laravel-actions": "^2.8", "openai-php/laravel": "^0.8", "spatie/laravel-sitemap": "^7.2", - "wire-elements/modal": "^2.0", - "spatie/laravel-sluggable": "^3.6" + "spatie/laravel-sluggable": "^3.6", + "spatie/schema-org": "^3.23", + "wire-elements/modal": "^2.0" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.13", diff --git a/composer.lock b/composer.lock index 3e5a1a31..75de5aad 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e467ec6a5c5b92e8e21e1b80c7cbfcda", + "content-hash": "41728e10c95b0c305cdf3b82dcbd45ee", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -1168,6 +1168,77 @@ }, "time": "2022-10-27T11:44:00+00:00" }, + { + "name": "diglactic/laravel-breadcrumbs", + "version": "v9.0.0", + "source": { + "type": "git", + "url": "https://github.com/diglactic/laravel-breadcrumbs.git", + "reference": "88e8f01e013e811215770e27b40a74014c28f2c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/diglactic/laravel-breadcrumbs/zipball/88e8f01e013e811215770e27b40a74014c28f2c4", + "reference": "88e8f01e013e811215770e27b40a74014c28f2c4", + "shasum": "" + }, + "require": { + "facade/ignition-contracts": "^1.0", + "laravel/framework": "^8.0 || ^9.0 || ^10.0 || ^11.0", + "php": "^7.3 || ^8.0" + }, + "conflict": { + "davejamesmiller/laravel-breadcrumbs": "*" + }, + "require-dev": { + "orchestra/testbench": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "php-coveralls/php-coveralls": "^2.7", + "phpunit/phpunit": "^9.5 || ^10.5", + "spatie/phpunit-snapshot-assertions": "^4.2 || ^5.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Diglactic\\Breadcrumbs\\ServiceProvider" + ], + "aliases": { + "Breadcrumbs": "Diglactic\\Breadcrumbs\\Breadcrumbs" + } + } + }, + "autoload": { + "psr-4": { + "Diglactic\\Breadcrumbs\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sheng Slogar", + "email": "sheng@diglactic.com", + "role": "Maintainer" + }, + { + "name": "Dave James Miller", + "email": "dave@davejamesmiller.com", + "role": "Original Creator" + } + ], + "description": "A simple Laravel-style way to create breadcrumbs.", + "homepage": "https://github.com/diglactic/laravel-breadcrumbs", + "keywords": [ + "laravel" + ], + "support": { + "issues": "https://github.com/diglactic/laravel-breadcrumbs/issues", + "source": "https://github.com/diglactic/laravel-breadcrumbs/tree/v9.0.0" + }, + "time": "2024-03-12T00:42:39+00:00" + }, { "name": "doctrine/cache", "version": "2.2.0", @@ -1870,6 +1941,59 @@ ], "time": "2023-10-06T06:47:41+00:00" }, + { + "name": "facade/ignition-contracts", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/facade/ignition-contracts.git", + "reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facade/ignition-contracts/zipball/3c921a1cdba35b68a7f0ccffc6dffc1995b18267", + "reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^v2.15.8", + "phpunit/phpunit": "^9.3.11", + "vimeo/psalm": "^3.17.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Facade\\IgnitionContracts\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://flareapp.io", + "role": "Developer" + } + ], + "description": "Solution contracts for Ignition", + "homepage": "https://github.com/facade/ignition-contracts", + "keywords": [ + "contracts", + "flare", + "ignition" + ], + "support": { + "issues": "https://github.com/facade/ignition-contracts/issues", + "source": "https://github.com/facade/ignition-contracts/tree/1.0.2" + }, + "time": "2020-10-16T08:27:54+00:00" + }, { "name": "filament/actions", "version": "v3.2.85", @@ -9311,6 +9435,79 @@ ], "time": "2024-04-22T14:28:40+00:00" }, + { + "name": "spatie/schema-org", + "version": "3.23.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/schema-org.git", + "reference": "c95abf7da59f16570aec18ca11d861255e645c39" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/schema-org/zipball/c95abf7da59f16570aec18ca11d861255e645c39", + "reference": "c95abf7da59f16570aec18ca11d861255e645c39", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.6", + "graham-campbell/analyzer": "^3.0.5", + "illuminate/collections": "^8.62.0", + "league/flysystem": "^2.3.0 || ^3.0", + "pestphp/pest": "^1.21", + "symfony/console": "^5.3.7 || 6.0", + "twig/twig": "^3.3.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\SchemaOrg\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sebastian De Deyne", + "email": "sebastian@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Tom Witkowski", + "email": "dev.gummibeer@gmail.com", + "homepage": "https://gummibeer.de", + "role": "Developer" + } + ], + "description": "A fluent builder Schema.org types and ld+json generator", + "homepage": "https://github.com/spatie/schema-org", + "keywords": [ + "schema-org", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/schema-org/issues", + "source": "https://github.com/spatie/schema-org/tree/3.23.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-01-11T14:58:44+00:00" + }, { "name": "spatie/temporary-directory", "version": "2.2.1", diff --git a/config/breadcrumbs.php b/config/breadcrumbs.php new file mode 100644 index 00000000..3f2837c3 --- /dev/null +++ b/config/breadcrumbs.php @@ -0,0 +1,75 @@ + 'breadcrumbs::tailwind', + + /* + |-------------------------------------------------------------------------- + | Breadcrumbs File(s) + |-------------------------------------------------------------------------- + | + | The file(s) where breadcrumbs are defined. e.g. + | + | - base_path('routes/breadcrumbs.php') + | - glob(base_path('breadcrumbs/*.php')) + | + */ + + 'files' => base_path('routes/breadcrumbs.php'), + + /* + |-------------------------------------------------------------------------- + | Exceptions + |-------------------------------------------------------------------------- + | + | Determine when to throw an exception. + | + */ + + // When route-bound breadcrumbs are used but the current route doesn't have a name (UnnamedRouteException) + 'unnamed-route-exception' => true, + + // When route-bound breadcrumbs are used and the matching breadcrumb doesn't exist (InvalidBreadcrumbException) + 'missing-route-bound-breadcrumb-exception' => true, + + // When a named breadcrumb is used but doesn't exist (InvalidBreadcrumbException) + 'invalid-named-breadcrumb-exception' => true, + + /* + |-------------------------------------------------------------------------- + | Classes + |-------------------------------------------------------------------------- + | + | Subclass the default classes for more advanced customisations. + | + */ + + // Manager + 'manager-class' => Diglactic\Breadcrumbs\Manager::class, + + // Generator + 'generator-class' => Diglactic\Breadcrumbs\Generator::class, + +]; diff --git a/config/codex.php b/config/codex.php index 70e79176..b1575347 100644 --- a/config/codex.php +++ b/config/codex.php @@ -1,4 +1,4 @@ - [ @@ -69,4 +69,5 @@ 'support_email' => env('SUPPORT_EMAIL', 'support@codexatlas.app'), 'llm' => env('CODEX_LLM', 'openai'), 'company_domain' => env('COMPANY_DOMAIN', '@codexatlas.app'), + 'blog_author' => env('BLOG_AUTHOR', 'CodexAtlas'), ]; diff --git a/package-lock.json b/package-lock.json index fd481ff9..803244ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "@alpinejs/collapse": "^3.14.1", "@alpinejs/focus": "^3.14.0", "@tsparticles/engine": "^3.3.0", "@tsparticles/preset-firefly": "^3.0.2", @@ -35,6 +36,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@alpinejs/collapse": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@alpinejs/collapse/-/collapse-3.14.1.tgz", + "integrity": "sha512-aI0pq8SjK7c43/nMIVL1Lt8naowPRepqQGNSb9KaG7adEneOwj/vq4ZaeZYjuGbd8sq1LKPwWU+klIZIXXujUA==" + }, "node_modules/@alpinejs/focus": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.14.0.tgz", @@ -2069,6 +2075,11 @@ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", "dev": true }, + "@alpinejs/collapse": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@alpinejs/collapse/-/collapse-3.14.1.tgz", + "integrity": "sha512-aI0pq8SjK7c43/nMIVL1Lt8naowPRepqQGNSb9KaG7adEneOwj/vq4ZaeZYjuGbd8sq1LKPwWU+klIZIXXujUA==" + }, "@alpinejs/focus": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.14.0.tgz", diff --git a/package.json b/package.json index ab19d08a..c958074d 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "vite": "^4.0.0" }, "dependencies": { + "@alpinejs/collapse": "^3.14.1", "@alpinejs/focus": "^3.14.0", "@tsparticles/engine": "^3.3.0", "@tsparticles/preset-firefly": "^3.0.2", diff --git a/resources/css/app.css b/resources/css/app.css index 669494e2..c3384db9 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -36,6 +36,10 @@ text-fill-color: transparent; } +.bg-primary-gradient { + background: linear-gradient(179deg, #6042FF 31.93%, rgba(255, 255, 255, 0.50) 122.37%); +} + .bg-input-gradient { background: linear-gradient(#FFFFFF 1%, #9A88F5 100%); } @@ -56,6 +60,14 @@ text-fill-color: transparent; } +.border-secondary-gradient { + border-image: linear-gradient(180deg, #FFFFFF -91.67%, #9A88F5 77.96%) 1; +} + +.bg-secondary-gradient { + background: linear-gradient(180deg, #FFFFFF -91.67%, #9A88F5 77.96%); +} + .title-gradient { background: linear-gradient(180deg, #FFF -91.67%, #9A88F5 77.96%); background-clip: text; diff --git a/resources/js/app.js b/resources/js/app.js index 7d0d4e6d..29556d03 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,3 +1,4 @@ + import './bootstrap'; import hljs from 'highlight.js'; import hljsBlade from 'highlightjs-blade'; @@ -5,9 +6,11 @@ import 'highlight.js/styles/atom-one-dark.css'; import { tsParticles } from "@tsparticles/engine"; import '@tsparticles/preset-firefly'; import { Livewire, Alpine } from '../../vendor/livewire/livewire/dist/livewire.esm'; +import { collapse } from '@alpinejs/collapse'; Livewire.start() Alpine.plugin(focus) +Alpine.plugin(collapse) hljs.registerLanguage("blade", hljsBlade); hljs.initHighlightingOnLoad(); diff --git a/resources/views/blog/blog-detail.blade.php b/resources/views/blog/blog-detail.blade.php index f3ff02c3..dc95f555 100644 --- a/resources/views/blog/blog-detail.blade.php +++ b/resources/views/blog/blog-detail.blade.php @@ -4,11 +4,21 @@ @section('metadescription', $blog->seo_description) {{-- Hacer la og image de tailgraph en el modelo --}} @section('og_image', $blog->getTailGraphUrl()) -
-
-

{{ $blog->title }}

+
+ {{ Breadcrumbs::render('blogDetail', $blog) }} +
+ + +
+

{{ $blog->title }}

-
{{ $blog->image_alt }} @@ -16,17 +26,27 @@ class="absolute left-0 top-0 w-full h-full object-cover" /> class="absolute top-4 right-4 bg-violet-500 text-white text-sm font-medium rounded-md px-2 py-1">{{ $blog->published_at->format('d-m-Y') }}
-
- {!! Str::markdown($blog->markdown_content) !!} +
+ + + +
+ +
+ {!! $blog->transformed_content->html() !!}
+ +
-
-
+ +
+ + @if ($otherBlogs->count() > 0) -
+

{{ __('Other blogs') }}

@@ -39,4 +59,54 @@ class="absolute top-4 right-4 bg-violet-500 text-white text-sm font-medium round
@endif + + + {!! $schema->toScript() !!} diff --git a/resources/views/blog/blog-list.blade.php b/resources/views/blog/blog-list.blade.php index b5f0f817..2423ebfd 100644 --- a/resources/views/blog/blog-list.blade.php +++ b/resources/views/blog/blog-list.blade.php @@ -1,5 +1,9 @@ -
+
+
+ {{ Breadcrumbs::render('blog') }} +
+

Blog

diff --git a/resources/views/components/atlas/blog/navigation.blade.php b/resources/views/components/atlas/blog/navigation.blade.php new file mode 100644 index 00000000..d4fd31b3 --- /dev/null +++ b/resources/views/components/atlas/blog/navigation.blade.php @@ -0,0 +1,62 @@ +
+ @if (!empty($blog->transformed_content->toc())) +
+ + +
+ +
+
+ +
+ + + + @endif +
diff --git a/resources/views/components/atlas/blog/share.blade.php b/resources/views/components/atlas/blog/share.blade.php new file mode 100644 index 00000000..2371627d --- /dev/null +++ b/resources/views/components/atlas/blog/share.blade.php @@ -0,0 +1,45 @@ +
+

Share this page

+ +
+ @php + $pageTitle = $blog->title; + $pageUrl = url()->current(); + @endphp + + + + + + + +
+
diff --git a/resources/views/components/icons/arrow.blade.php b/resources/views/components/icons/arrow.blade.php new file mode 100644 index 00000000..6f43ea5c --- /dev/null +++ b/resources/views/components/icons/arrow.blade.php @@ -0,0 +1,5 @@ + + + diff --git a/resources/views/components/icons/facebook-filled.blade.php b/resources/views/components/icons/facebook-filled.blade.php new file mode 100644 index 00000000..e34b2150 --- /dev/null +++ b/resources/views/components/icons/facebook-filled.blade.php @@ -0,0 +1,9 @@ + + + + diff --git a/resources/views/components/icons/facebook-outlined.blade.php b/resources/views/components/icons/facebook-outlined.blade.php new file mode 100644 index 00000000..14dc0d8e --- /dev/null +++ b/resources/views/components/icons/facebook-outlined.blade.php @@ -0,0 +1,9 @@ + + + + diff --git a/resources/views/components/icons/linkedin-filled.blade.php b/resources/views/components/icons/linkedin-filled.blade.php new file mode 100644 index 00000000..c54410d8 --- /dev/null +++ b/resources/views/components/icons/linkedin-filled.blade.php @@ -0,0 +1,12 @@ + + + + + diff --git a/resources/views/components/icons/linkedin-outlined.blade.php b/resources/views/components/icons/linkedin-outlined.blade.php new file mode 100644 index 00000000..a2ec20c7 --- /dev/null +++ b/resources/views/components/icons/linkedin-outlined.blade.php @@ -0,0 +1,12 @@ + + + + + diff --git a/resources/views/components/icons/twitter-filled.blade.php b/resources/views/components/icons/twitter-filled.blade.php new file mode 100644 index 00000000..06ce0732 --- /dev/null +++ b/resources/views/components/icons/twitter-filled.blade.php @@ -0,0 +1,9 @@ + + + + diff --git a/resources/views/components/icons/twitter-outlined.blade.php b/resources/views/components/icons/twitter-outlined.blade.php new file mode 100644 index 00000000..4e196e9e --- /dev/null +++ b/resources/views/components/icons/twitter-outlined.blade.php @@ -0,0 +1,9 @@ + + + + diff --git a/resources/views/components/icons/whatsapp-filled.blade.php b/resources/views/components/icons/whatsapp-filled.blade.php new file mode 100644 index 00000000..772a744f --- /dev/null +++ b/resources/views/components/icons/whatsapp-filled.blade.php @@ -0,0 +1,12 @@ + + + + + diff --git a/resources/views/components/icons/whatsapp-outlined.blade.php b/resources/views/components/icons/whatsapp-outlined.blade.php new file mode 100644 index 00000000..b6890fd9 --- /dev/null +++ b/resources/views/components/icons/whatsapp-outlined.blade.php @@ -0,0 +1,11 @@ + + + + + diff --git a/resources/views/vendor/breadcrumbs/bootstrap4.blade.php b/resources/views/vendor/breadcrumbs/bootstrap4.blade.php new file mode 100644 index 00000000..59a820d2 --- /dev/null +++ b/resources/views/vendor/breadcrumbs/bootstrap4.blade.php @@ -0,0 +1,15 @@ +@unless ($breadcrumbs->isEmpty()) + +@endunless diff --git a/resources/views/vendor/breadcrumbs/bootstrap5.blade.php b/resources/views/vendor/breadcrumbs/bootstrap5.blade.php new file mode 100644 index 00000000..13fb1b1d --- /dev/null +++ b/resources/views/vendor/breadcrumbs/bootstrap5.blade.php @@ -0,0 +1,15 @@ +@unless ($breadcrumbs->isEmpty()) + +@endunless diff --git a/resources/views/vendor/breadcrumbs/bulma.blade.php b/resources/views/vendor/breadcrumbs/bulma.blade.php new file mode 100644 index 00000000..26e478ef --- /dev/null +++ b/resources/views/vendor/breadcrumbs/bulma.blade.php @@ -0,0 +1,23 @@ +@unless ($breadcrumbs->isEmpty()) + +@endunless diff --git a/resources/views/vendor/breadcrumbs/foundation6.blade.php b/resources/views/vendor/breadcrumbs/foundation6.blade.php new file mode 100644 index 00000000..06294668 --- /dev/null +++ b/resources/views/vendor/breadcrumbs/foundation6.blade.php @@ -0,0 +1,17 @@ +@unless ($breadcrumbs->isEmpty()) + +@endunless diff --git a/resources/views/vendor/breadcrumbs/json-ld.php b/resources/views/vendor/breadcrumbs/json-ld.php new file mode 100644 index 00000000..5f75225d --- /dev/null +++ b/resources/views/vendor/breadcrumbs/json-ld.php @@ -0,0 +1,23 @@ + 'https://schema.org', + '@type' => 'BreadcrumbList', + 'itemListElement' => [], +]; + +foreach ($breadcrumbs as $i => $breadcrumb) { + $json['itemListElement'][] = [ + '@type' => 'ListItem', + 'position' => $i + 1, + 'item' => [ + '@id' => $breadcrumb->url ?: Request::fullUrl(), + 'name' => $breadcrumb->title, + 'image' => $breadcrumb->image ?? null, + ], + ]; +} +?> + diff --git a/resources/views/vendor/breadcrumbs/materialize.blade.php b/resources/views/vendor/breadcrumbs/materialize.blade.php new file mode 100644 index 00000000..7d89a9f4 --- /dev/null +++ b/resources/views/vendor/breadcrumbs/materialize.blade.php @@ -0,0 +1,17 @@ +@unless ($breadcrumbs->isEmpty()) + +@endunless diff --git a/resources/views/vendor/breadcrumbs/tailwind.blade.php b/resources/views/vendor/breadcrumbs/tailwind.blade.php new file mode 100644 index 00000000..f845520c --- /dev/null +++ b/resources/views/vendor/breadcrumbs/tailwind.blade.php @@ -0,0 +1,29 @@ +@unless ($breadcrumbs->isEmpty()) + + @endunless diff --git a/resources/views/vendor/breadcrumbs/uikit.blade.php b/resources/views/vendor/breadcrumbs/uikit.blade.php new file mode 100644 index 00000000..920183db --- /dev/null +++ b/resources/views/vendor/breadcrumbs/uikit.blade.php @@ -0,0 +1,13 @@ +@unless ($breadcrumbs->isEmpty()) + +@endunless diff --git a/routes/breadcrumbs.php b/routes/breadcrumbs.php new file mode 100644 index 00000000..97b58f78 --- /dev/null +++ b/routes/breadcrumbs.php @@ -0,0 +1,22 @@ +push('Home', route('homepage')); +}); + +// Home > Blog +Breadcrumbs::for('blog', function (BreadcrumbTrail $trail) { + $trail->parent('home'); + $trail->push('Blog', route('blog.index')); +}); + +// Home > Blog +Breadcrumbs::for('blogDetail', function (BreadcrumbTrail $trail, BlogPost $blog) { + $trail->parent('blog'); + $trail->push($blog->title, route('blog.detail', $blog)); +});