{% extends "base_vue.html" %} {% block title %}{{ site_title }} — {{ billet.title or 'billet' }}{% endblock %} {% block head %} {% if og %} {% if og.image %}{% endif %} {% if og.image %}{% endif %} {% endif %} {% if oembed_url %}{% endif %} {% endblock %} {% block content %} {%- set eu = billet.embed_url or '' -%} {%- set is_pt = billet.embed_is_video and 'peertube' in eu -%} {%- set is_yt = billet.embed_is_video and ('youtube' in eu or 'youtu.be' in eu) -%} {%- set prov = 'pt' if is_pt else ('yt' if is_yt else '') -%} {%- set cover = (billet.media | selectattr('thumb') | list | first) if billet.media else None -%} {%- set poster = ('/media/' ~ cover.thumb) if cover else (billet.poster or billet.embed_snapshot_url) -%} {%- set joue = billet.embed_html and billet.embed_is_video -%} {#- MODE SOUVERAIN (#1372). Un embed PeerTube vient de NOTRE instance : le charger d'emblee ne fait sortir aucune donnee, et la lecture demarre tout de suite. Un embed YouTube, lui, part chez un tiers DES L'ANALYSE DE LA PAGE — avant tout clic, avant tout consentement, et pour un lecteur qui n'a peut-etre pas l'intention de regarder. Ce n'est pas qu'une question de principe : c'est aussi ce qui rendait visible l'erreur 153 du lecteur YouTube sur une page qu'on venait juste d'ouvrir. Un refus d'integration s'affichait a la place de l'image, sans que personne n'ait rien demande. On separe donc les deux : souverain -> l'iframe porte son `src`, elle charge tout de suite tiers -> l'iframe porte `data-src`, et n'est armee qu'au CLIC Le lecteur voit l'instantane local — present pour les 82 billets YouTube — et decide. S'il ne clique pas, aucune requete ne quitte la box. C'est exactement ce que la page 11 du guide produit promet. -#} {%- set souverain = is_pt or not is_yt -%} {%- set cadre_src = billet.embed_html|replace('www.youtube.com/embed/', 'www.youtube-nocookie.com/embed/')|replace('youtube.com/embed/', 'youtube-nocookie.com/embed/') -%}
{% if prov %}{{ 'PeerTube · souverain' if is_pt else 'YouTube · clic pour charger' }}{% endif %} {% if poster %}
{% else %}
{% endif %} {% if joue and souverain %}
{{ cadre_src|safe }}
{% elif joue %}{# tiers : arme, pas charge — voir MODE SOUVERAIN plus haut #}
{{ cadre_src|replace(' src=', ' data-src=')|safe }}
▶
{% else %}
{{ '▶' if billet.embed_is_video else '✎' }}
{% endif %}
{# Les jetons vivent ICI : c'est le seul formulaire de la page. Avec JS il est intercepté (la vidéo continue) ; sans JS il poste normalement et le serveur redirige comme avant — rien n'est perdu. #} {# Rempli par vue.js à l'envoi : la seconde de lecture visée. Vide sans JS ou hors lecture — le serveur enregistre alors « pas d'instant ». #} ▸ {% for e in ['👍','❤️','😂','😮','😢','🔥'] %}{% endfor %}
{{ comments|length }} messages ↓ console
{{ billet.cat }} {{ '📡' if billet.style=='communique' else ('🎬' if billet.embed_is_video else '📝') }} {% if billet.published_at %}{% endif %}

{{ billet.title or 'Billet' }}

{% if billet.ref_host %}↗ {{ billet.ref_host }}{% endif %}
{# LA FICHE : ce qui était une liste d'URLs nues devient des pastilles typées (l'hôte dit la nature, pas le libellé) plus une ligne de mini-stats. #} {% if billet.fiche %}
{% if billet.fiche.chaine %}👤 {{ billet.fiche.chaine }}{% endif %} {% if billet.fiche.duree %}⏱ {{ billet.fiche.duree }}{% endif %} 👁 {{ billet.view_count or 0 }} ♥ {{ reactions.counts.values()|sum if reactions else 0 }} 💬 {{ comments|length }}
{% endif %} {% if billet.body_html and billet.body_html.strip() %}
{% with b=billet %}{% include "_zani_stamp.html" %}{% endwith %} {{ billet.body_html|safe }}
{% else %}
{% with b=billet %}{% include "_zani_stamp.html" %}{% endwith %}
{% endif %} {# Galerie = IMAGES seules. L'audio/vidéo/pdf s'affiche EN LIGNE dans le corps (les refs /media/ y sont embarquées au rendu, #1094) : les remettre ici en ferait un doublon, et un sur un mp4 casserait. #} {% set images = billet.media | selectattr('thumb') | list %} {% if images %} {% endif %} {# Un embed NON-video (mastodon, bsky, soundcloud…) ne va pas dans l'écran 16/9 : il garde sa hauteur propre, dans un panneau au même grain. #} {% if billet.embed_html and not billet.embed_is_video %}
{{ billet.embed_html|safe }}
{% endif %} {# OBJET MEDIA (#1227) : un embed VIDEO gagne les actions du Hall (voir dans le lecteur souverain, diffuser au parc), comme le BBS. billets.js relaie. #} {% if billet.embed_is_video and billet.embed_url %}
🛰️ relayé ▢ voir 📡 diffuser
{% endif %} {% if reactions %}{% include "_reactions.html" %}{% endif %} {% if billet.share %} {% with share=billet.share, permalink=billet.permalink, title=billet.title %}{% include "_share_quick.html" %}{% endwith %} {% endif %}
▸

console des messages

{{ comments|length }} ligne{{ 's' if comments|length > 1 else '' }} en direct
{% if flash == 'pending' %}

Reçu — votre message attend la modération.

{% endif %} {% if flash == 'ok' %}

Message publié.

{% endif %} {% if flash == 'rate' %}

Trop de messages — réessayez plus tard.

{% endif %} {% if flash == 'slow' %}

Trop vite — réessayez dans un instant.

{% endif %}
    {% for c in comments %}
  1. {% if c.video_t is not none %} {% else %}{{ '%02d' % loop.index }}{% endif %} {{ c.author_name }} {{ c.body_html|safe }}
  2. {% else %}
  3. ▸aucune ligne sur ce billet — la vôtre serait la première
  4. {% endfor %}

↑ écrivez depuis la barre au bas de l'écran — votre ligne y passe aussitôt en sous-titre

{% endblock %}