feat: enriched media model with ALT badges (Release 3+4)

Change photo storage from bare URL strings to objects with url, alt,
width, height (AP) plus blurhash and focus (Mastodon API). Templates
handle both old string and new object format for backward compat.

Add ALT text badges on gallery images — click to expand the full
alt text in an overlay. Renders in both reader and explore views.

Also pass alt text through to lightbox and quote embed photos.

Bump version to 2.5.3.

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
This commit is contained in:
Ricardo
2026-03-03 13:46:58 +01:00
parent e34d9c124d
commit c243b70629
6 changed files with 83 additions and 12 deletions

View File

@@ -6,14 +6,23 @@
{% set extraCount = item.photo.length - 4 %}
{% set totalPhotos = item.photo.length %}
<div x-data="{ lightbox: false, idx: 0 }" class="ap-card__gallery ap-card__gallery--{{ displayCount }}">
{% for photoUrl in item.photo %}
{% for photo in item.photo %}
{# Support both old string format and new object format #}
{% set photoSrc = photo.url if photo.url else photo %}
{% set photoAlt = photo.alt if photo.alt else "" %}
{% if loop.index0 < 4 %}
<button type="button" @click="idx = {{ loop.index0 }}; lightbox = true" class="ap-card__gallery-link{% if loop.index0 == 3 and extraCount > 0 %} ap-card__gallery-link--more{% endif %}">
<img src="{{ photoUrl }}" alt="" loading="lazy">
{% if loop.index0 == 3 and extraCount > 0 %}
<span class="ap-card__gallery-more">+{{ extraCount }}</span>
<div class="ap-card__gallery-item" x-data="{ showAlt: false }">
<button type="button" @click="idx = {{ loop.index0 }}; lightbox = true" class="ap-card__gallery-link{% if loop.index0 == 3 and extraCount > 0 %} ap-card__gallery-link--more{% endif %}">
<img src="{{ photoSrc }}" alt="{{ photoAlt }}" loading="lazy">
{% if loop.index0 == 3 and extraCount > 0 %}
<span class="ap-card__gallery-more">+{{ extraCount }}</span>
{% endif %}
</button>
{% if photoAlt %}
<button type="button" class="ap-media__alt-badge" @click.stop="showAlt = !showAlt" :aria-expanded="showAlt">ALT</button>
<div class="ap-media__alt-text" x-show="showAlt" x-cloak @click.stop>{{ photoAlt }}</div>
{% endif %}
</button>
</div>
{% endif %}
{% endfor %}
@@ -24,7 +33,9 @@
{% if totalPhotos > 1 %}
<button type="button" @click="idx = (idx - 1 + {{ totalPhotos }}) % {{ totalPhotos }}" class="ap-lightbox__prev" aria-label="Previous image">&lsaquo;</button>
{% endif %}
<img :src="[{% for p in item.photo %}'{{ p }}'{% if not loop.last %},{% endif %}{% endfor %}][idx]" class="ap-lightbox__img" alt="">
<img :src="[{% for photo in item.photo %}'{{ photo.url if photo.url else photo }}'{% if not loop.last %},{% endif %}{% endfor %}][idx]"
:alt="[{% for photo in item.photo %}'{{ (photo.alt if photo.alt else '') | replace(\"'\", \"\\'\") }}'{% if not loop.last %},{% endif %}{% endfor %}][idx]"
class="ap-lightbox__img">
{% if totalPhotos > 1 %}
<button type="button" @click="idx = (idx + 1) % {{ totalPhotos }}" class="ap-lightbox__next" aria-label="Next image">&rsaquo;</button>
<div class="ap-lightbox__counter" x-text="(idx + 1) + ' / ' + {{ totalPhotos }}"></div>

View File

@@ -25,8 +25,9 @@
<div class="ap-quote-embed__content">{{ item.quote.content.html | safe }}</div>
{% endif %}
{% if item.quote.photo and item.quote.photo.length > 0 %}
{% set qPhoto = item.quote.photo[0] %}
<div class="ap-quote-embed__media">
<img src="{{ item.quote.photo[0] }}" alt="" loading="lazy" class="ap-quote-embed__photo">
<img src="{{ qPhoto.url if qPhoto.url else qPhoto }}" alt="{{ qPhoto.alt if qPhoto.alt else '' }}" loading="lazy" class="ap-quote-embed__photo">
</div>
{% endif %}
</a>