You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

169 lines
7.4 KiB

{% extends 'base.html.twig' %}
{% block title %}{{ article.title|trim }}{{ website_name }}{% endblock %}
{% block meta_description %}
{% set _desc = article.summary|default('')|striptags|u.truncate(159, '…') %}
<meta name="description" content="{{ _desc|e('html_attr') }}">
{% endblock %}
{% block ogtags %}
{# Upstream main only outputs og:image when article.image is set — unfurlers often show a blank card. Always set an absolute image + JSON-LD. #}
{% set _img = article.image|default('')|trim %}
{% if _img == '' %}
{% set _og_image = absolute_url(asset('og-image.jpg')) %}
{% set _og_default_dims = true %}
{% elseif _img starts with '//' %}
{% set _og_image = 'https:' ~ _img %}
{% set _og_default_dims = false %}
{% else %}
{% set _og_image = absolute_url(_img) %}
{% set _og_default_dims = false %}
{% endif %}
{% set _desc = article.summary|default('')|striptags|u.truncate(159, '…') %}
{% set _canonical = url('article', { npub: npub|default(npub_from_hex(article.pubkey)), slug: article.slug }) %}
{% set _author_name = '' %}
{% if author is defined and author %}
{% set _author_name = attribute(author, 'name')|default(attribute(author, 'display_name')|default('')) %}
{% endif %}
<meta property="og:title" content="{{ article.title|e('html_attr') }}">
<meta property="og:type" content="article">
<meta property="og:url" content="{{ _canonical|e('html_attr') }}">
<meta property="og:image" content="{{ _og_image|e('html_attr') }}">
{% if _og_image starts with 'https://' %}
<meta property="og:image:secure_url" content="{{ _og_image|e('html_attr') }}">
{% endif %}
{% if _og_default_dims %}
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
{% endif %}
<meta property="og:description" content="{{ _desc|e('html_attr') }}">
<meta property="og:site_name" content="{{ website_name|e('html_attr') }}">
<link rel="canonical" href="{{ _canonical|e('html_attr') }}">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ article.title|e('html_attr') }}">
<meta name="twitter:description" content="{{ _desc|e('html_attr') }}">
<meta name="twitter:image" content="{{ _og_image|e('html_attr') }}">
<script type="application/ld+json">{{ {
'@context': 'https://schema.org',
'@type': 'BlogPosting',
'headline': article.title,
'description': _desc,
'image': _og_image,
'url': _canonical,
'datePublished': article.displayDateTime|date('c'),
'mainEntityOfPage': {'@type': 'WebPage', '@id': _canonical},
'publisher': {'@type': 'Organization', 'name': website_name},
'author': {'@type': 'Person', 'name': _author_name != '' ? _author_name : (npub|default('Author'))}
}|json_encode|raw }}</script>
{% endblock %}
{% block body %}
<div
data-controller="article-highlight"
class="article-page-root"
data-action="click@window->article-highlight#closeOnOutside keydown@window->article-highlight#onKeydown"
>
{% if is_granted('ROLE_ADMIN') %}
<button class="btn btn-primary" onclick="navigator.clipboard.writeText('30023:{{ article.pubkey }}:{{ article.slug }}')">
Copy coordinates
</button>
{% endif %}
<div class="card">
<div class="card-header card-header--article">
<h1 class="card-title">{{ article.title }}</h1>
{% set _art_share = nostr_event_share(article) %}
{% if _art_share %}{% include 'components/Molecules/NostrShareMenu.html.twig' with { share: _art_share, event_menu: true } only %}{% endif %}
</div>
{% if author %}
<div class="byline">
<span class="byline__author">
{{ 'text.byline'|trans }}
<twig:Molecules:UserFromNpub ident="{{ article.pubkey }}" />
</span>
<span>
{% if article.displayDateTime %}
<small>{{ article.displayDateTime|date('F j, Y') }}</small>
{% endif %}
</span>
</div>
{% endif %}
</div>
<div class="card-body">
<div class="lede">
{{ article.summary }}
</div>
{% if article.image %}
<div class="article__image">
<img src="{{ article.image }}" alt="{{ article.title }}">
</div>
{% endif %}
<div class="article-main" data-article-highlight-target="article">
{{ content|raw }}
</div>
{% if article.topics|length > 0 %}
<hr class="divider" />
<div class="tags">
{% for tag in article.topics %}
<a class="tag" href="{{ path('topic', { topic: tag }) }}">{{ tag }}</a>
{% endfor %}
</div>
{% endif %}
</div>
{% if article_highlights_client_json|default('')|trim != '' %}
<script type="application/json" id="article-highlights-client-json" data-article-highlight-target="meta">{{ article_highlights_client_json|raw }}</script>
{% endif %}
<div
class="article-body-highlight__popover"
data-article-highlight-target="popover"
data-article-highlight-turbo-permanent
hidden
role="dialog"
aria-label="{{ 'highlight.popover'|trans }}"
>
<button type="button" class="article-body-highlight__close" data-action="article-highlight#closePopover" aria-label="{{ 'highlight.close'|trans }}">×</button>
<div class="article-body-highlight__inner" data-article-highlight-target="popoverInner"></div>
</div>
<hr class="divider" />
{# <pre>#}
{# {{ article.content }}#}
{# </pre>#}
{% set article_coordinate = (article.kind ? article.kind.value : 30023) ~ ':' ~ article.pubkey ~ ':' ~ article.slug %}
{% set comments_query = { coordinate: article_coordinate, title: article.title|default('') }|merge(article.eventId ? { e: article.eventId } : {}) %}
{% set _reply_ctx = comments_data.comment_reply_context|default(comment_reply_context|default(null)) %}
{% include 'components/Molecules/ArticleReplyComposer.html.twig' with { comment_reply_context: _reply_ctx } only %}
<section class="article-comments-async" id="article-comments" aria-label="Comments">
<div
data-controller="article-comments"
data-article-comments-wrapper
data-article-comments-url-value="{{ path('article_comments_fragment', comments_query)|e('html_attr') }}"
data-article-comments-preloaded-value="{{ (comments_preloaded|default(false)) ? 'true' : 'false' }}"
>
<div
data-article-comments-target="container"
class="comments {{ comments_preloaded|default(false) ? 'comments--from-cache' : 'comments--pending' }}"
>
{% if comments_preloaded|default(false) and comments_data is defined and comments_data is not null %}
{% include 'components/Organisms/Comments.html.twig' with comments_data %}
{% else %}
<p class="text-subtle">Loading comments…</p>
{% endif %}
</div>
</div>
</section>
</div>
{% endblock %}
{% block aside %}
{# <h1>Suggestions</h1>#}
{# <twig:Organisms:CardList :list="suggestions" />#}
{% endblock %}