124 lines
6.9 KiB
Plaintext
124 lines
6.9 KiB
Plaintext
---
|
|
layout: layouts/base.njk
|
|
withBlogSidebar: true
|
|
---
|
|
<article class="h-entry post">
|
|
{% if title %}
|
|
<h1 class="p-name text-3xl font-bold text-surface-900 dark:text-surface-100 mb-4">{{ title }}</h1>
|
|
{% endif %}
|
|
|
|
<div class="post-meta mb-6">
|
|
<time class="dt-published" datetime="{{ date.toISOString() }}">
|
|
{{ date | dateDisplay }}
|
|
</time>
|
|
{% if category %}
|
|
<span class="post-categories">
|
|
{# Handle both string and array categories #}
|
|
{% if category is string %}
|
|
<a href="/categories/{{ category | slugify }}/" class="p-category">{{ category }}</a>
|
|
{% else %}
|
|
{% for cat in category %}
|
|
<a href="/categories/{{ cat | slugify }}/" class="p-category">{{ cat }}</a>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{# Bridgy syndication content - controls what gets posted to social networks #}
|
|
{# Uses description/summary if available, otherwise first 280 chars of content #}
|
|
{% set bridgySummary = description or summary or (content | ogDescription(280)) %}
|
|
{% if bridgySummary %}
|
|
<p class="p-summary e-bridgy-mastodon-content e-bridgy-bluesky-content hidden">{{ bridgySummary }}</p>
|
|
{% endif %}
|
|
|
|
<div class="e-content prose prose-surface dark:prose-invert max-w-none">
|
|
{{ content | safe }}
|
|
</div>
|
|
|
|
{# Rich reply context with h-cite microformat #}
|
|
{% include "components/reply-context.njk" %}
|
|
|
|
{# Syndication Footer - shows where this post was also published #}
|
|
{% if syndication %}
|
|
<footer class="post-footer mt-8 pt-6 border-t border-surface-200 dark:border-surface-700">
|
|
<div class="flex flex-wrap items-center gap-4">
|
|
<span class="text-sm text-surface-500 dark:text-surface-400">Also on:</span>
|
|
<div class="flex flex-wrap gap-3">
|
|
{% for url in syndication %}
|
|
{% if "bsky.app" in url or "bluesky" in url %}
|
|
<a class="u-syndication inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-[#0085ff]/10 text-[#0085ff] hover:bg-[#0085ff]/20 transition-colors text-sm font-medium" href="{{ url }}" target="_blank" rel="noopener syndication" title="View on Bluesky">
|
|
<svg class="w-4 h-4" viewBox="0 0 568 501" fill="currentColor" aria-hidden="true">
|
|
<path d="M123.121 33.664C188.241 82.553 258.281 181.68 284 234.873c25.719-53.192 95.759-152.32 160.879-201.21C491.866-1.611 568-28.906 568 57.947c0 17.346-9.945 145.713-15.778 166.555-20.275 72.453-94.155 90.933-159.875 79.748C507.222 323.8 536.444 388.56 473.333 453.32c-119.86 122.992-172.272-30.859-185.702-70.281-2.462-7.227-3.614-10.608-3.631-7.733-.017-2.875-1.169.506-3.631 7.733-13.43 39.422-65.842 193.273-185.702 70.281-63.111-64.76-33.89-129.52 80.986-149.071-65.72 11.185-139.6-7.295-159.875-79.748C9.945 203.659 0 75.291 0 57.946 0-28.906 76.135-1.612 123.121 33.664Z"/>
|
|
</svg>
|
|
<span>Bluesky</span>
|
|
</a>
|
|
{% elif "mstdn" in url or "mastodon" in url or "social" in url %}
|
|
<a class="u-syndication inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-[#6364ff]/10 text-[#6364ff] hover:bg-[#6364ff]/20 transition-colors text-sm font-medium" href="{{ url }}" target="_blank" rel="noopener syndication" title="View on Mastodon">
|
|
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
<path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.668 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z"/>
|
|
</svg>
|
|
<span>Mastodon</span>
|
|
</a>
|
|
{% else %}
|
|
<a class="u-syndication inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-300 hover:bg-surface-200 dark:hover:bg-surface-700 transition-colors text-sm font-medium" href="{{ url }}" target="_blank" rel="noopener syndication">
|
|
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
|
|
<polyline points="15 3 21 3 21 9"/>
|
|
<line x1="10" y1="14" x2="21" y2="3"/>
|
|
</svg>
|
|
<span>{{ url | replace("https://", "") | truncate(20) }}</span>
|
|
</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
{% endif %}
|
|
|
|
<a class="u-url" href="{{ page.url }}" hidden>Permalink</a>
|
|
|
|
{# Author h-card for IndieWeb authorship #}
|
|
<span class="p-author h-card hidden">
|
|
<a class="p-name u-url" href="{{ site.author.url }}">{{ site.author.name }}</a>
|
|
<img class="u-photo" src="{{ site.author.avatar }}" alt="{{ site.author.name }}" hidden>
|
|
</span>
|
|
|
|
{# JSON-LD Structured Data for SEO #}
|
|
{% set postImage = photo or image or (content | extractFirstImage) %}
|
|
{% set postDesc = description | default(content | ogDescription(160)) %}
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "Article",
|
|
"headline": {{ (title or "Untitled") | dump | safe }},
|
|
"url": "{{ site.url }}{{ page.url }}",
|
|
"mainEntityOfPage": {
|
|
"@type": "WebPage",
|
|
"@id": "{{ site.url }}{{ page.url }}"
|
|
},
|
|
"datePublished": "{{ date.toISOString() }}",
|
|
"dateModified": "{{ date.toISOString() }}",
|
|
"author": {
|
|
"@type": "Person",
|
|
"name": "{{ site.author.name }}",
|
|
"url": "{{ site.author.url }}"
|
|
},
|
|
"publisher": {
|
|
"@type": "Organization",
|
|
"name": "{{ site.name }}",
|
|
"url": "{{ site.url }}",
|
|
"logo": {
|
|
"@type": "ImageObject",
|
|
"url": "{{ site.url }}/images/og-default.png"
|
|
}
|
|
},
|
|
"description": {{ postDesc | dump | safe }}{% if postImage %},
|
|
"image": ["{{ site.url }}{% if postImage.startsWith('/') %}{{ postImage }}{% else %}/{{ postImage }}{% endif %}"]{% endif %}
|
|
}
|
|
</script>
|
|
</article>
|
|
|
|
{# Webmentions display - likes, reposts, replies #}
|
|
{% include "components/webmentions.njk" %}
|