1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-31 18:31:01 +00:00
miniflux-v2/internal/template/templates/views/entry.html
jvoisin 14cd5e9c0d refactor(template): reduce the amount of code in common templates
There is no need to have templates used only used in a single file be part of
every single other ones. This should reduce a bit the resident memory
consumption of miniflux.
2025-08-07 17:36:41 -07:00

323 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{{ define "title"}}{{ .entry.Title }}{{ end }}
{{ define "entry_pagination" }}
<div class="pagination">
<div class="pagination-prev {{ if not .prevEntry }}disabled{{end}}">
{{ if .prevEntry }}
<a href="{{ .prevEntryRoute }}{{ if .searchQuery }}?q={{ .searchQuery }}{{ end }}" title="{{ .prevEntry.Title }}" data-page="previous" rel="prev">{{ t "pagination.previous" }}</a>
{{ else }}
{{ t "pagination.previous" }}
{{ end }}
</div>
<div class="pagination-next {{ if not .nextEntry }}disabled{{end}}">
{{ if .nextEntry }}
<a href="{{ .nextEntryRoute }}{{ if .searchQuery }}?q={{ .searchQuery }}{{ end }}" title="{{ .nextEntry.Title }}" data-page="next" rel="next">{{ t "pagination.next" }}</a>
{{ else }}
{{ t "pagination.next" }}
{{ end }}
</div>
</div>
{{ end }}
{{ define "enclosure_media_controls" }}
<div class="media-controls">
<div class="media-seek-control">
<div class="media-control-label">{{ t "enclosure_media_controls.seek" }} </div>
<button class="page-button" data-enclosure-id="{{.ID}}" data-enclosure-action="seek" data-action-value="-30" title="{{ t "enclosure_media_controls.seek.title" "-30" }}" ><span class="icon-label" >-30s</span></button>
<button class="page-button" data-enclosure-id="{{.ID}}" data-enclosure-action="seek" data-action-value="-10" title="{{ t "enclosure_media_controls.seek.title" "-10" }}" ><span class="icon-label" >-10s</span></button>
<button class="page-button" data-enclosure-id="{{.ID}}" data-enclosure-action="seek" data-action-value="+10" title="{{ t "enclosure_media_controls.seek.title" "+10" }}" ><span class="icon-label" >+10s</span></button>
<button class="page-button" data-enclosure-id="{{.ID}}" data-enclosure-action="seek" data-action-value="+30" title="{{ t "enclosure_media_controls.seek.title" "+30" }}" ><span class="icon-label" >+30s</span></button>
</div>
<div class="media-speed-control">
<div class="media-control-label">{{ t "enclosure_media_controls.speed" }} (<span class="speed-indicator" data-enclosure-id="{{.ID}}">1.00x</span>)</div> <!-- Need JS to display the current speed unfortunately -->
<button class="page-button" data-enclosure-id="{{.ID}}" data-enclosure-action="speed" data-action-value="-0.25" title="{{ t "enclosure_media_controls.speed.slower.title" "0.25" }}"><span class="icon-label" >{{ t "enclosure_media_controls.speed.slower" }}</span></button>
<button class="page-button" data-enclosure-id="{{.ID}}" data-enclosure-action="speed-reset" data-action-value="1" title="{{ t "enclosure_media_controls.speed.reset.title"}}"><span class="icon-label" >{{ t "enclosure_media_controls.speed.reset" }}</span></button>
<button class="page-button" data-enclosure-id="{{.ID}}" data-enclosure-action="speed" data-action-value="+0.25" title="{{ t "enclosure_media_controls.speed.faster.title" "0.25" }}"><span class="icon-label" >{{ t "enclosure_media_controls.speed.faster" }}</span></button>
</div>
</div>
{{ end }}
{{ define "page_header"}}
<section class="entry" data-id="{{ .entry.ID }}" aria-labelledby="page-header-title">
<header class="entry-header">
<h1 id="page-header-title" dir="auto">
<a href="{{ .entry.URL | safeURL }}" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }} rel="noopener noreferrer" referrerpolicy="no-referrer">{{ .entry.Title }}</a>
</h1>
{{ if .user }}
<div class="entry-actions">
<ul>
<li>
<button
class="page-button"
title="{{ t "entry.status.title" }}"
data-toggle-status="true"
data-label-loading="{{ t "entry.state.saving" }}"
data-label-unread="{{ t "entry.status.mark_as_unread" }}"
data-label-read="{{ t "entry.status.mark_as_read" }}"
data-toast-unread="{{ t "entry.status.toast.unread" }}"
data-toast-read="{{ t "entry.status.toast.read" }}"
data-value="{{ if eq .entry.Status "read" }}read{{ else }}unread{{ end }}"
>{{ if eq .entry.Status "unread" }}{{ icon "read" }}{{ else }}{{ icon "unread" }}{{ end }}<span class="icon-label">{{ if eq .entry.Status "unread" }}{{ t "entry.status.mark_as_read" }}{{ else }}{{ t "entry.status.mark_as_unread" }}{{ end }}</span></button>
</li>
<li>
<button
class="page-button"
data-toggle-bookmark="true"
data-bookmark-url="{{ route "toggleBookmark" "entryID" .entry.ID }}"
data-label-loading="{{ t "entry.state.saving" }}"
data-label-star="{{ t "entry.bookmark.toggle.on" }}"
data-label-unstar="{{ t "entry.bookmark.toggle.off" }}"
data-toast-star="{{ t "entry.bookmark.toast.on" }}"
data-toast-unstar="{{ t "entry.bookmark.toast.off" }}"
data-value="{{ if .entry.Starred }}star{{ else }}unstar{{ end }}"
>{{ if .entry.Starred }}{{ icon "unstar" }}{{ else }}{{ icon "star" }}{{ end }}<span class="icon-label">{{ if .entry.Starred }}{{ t "entry.bookmark.toggle.off" }}{{ else }}{{ t "entry.bookmark.toggle.on" }}{{ end }}</span></button>
</li>
{{ if .hasSaveEntry }}
<li>
<button
class="page-button"
title="{{ t "entry.save.title" }}"
data-save-entry="true"
data-save-url="{{ route "saveEntry" "entryID" .entry.ID }}"
data-label-loading="{{ t "entry.state.saving" }}"
data-label-done="{{ t "entry.save.completed" }}"
data-toast-done="{{ t "entry.save.toast.completed" }}"
>{{ icon "save" }}<span class="icon-label">{{ t "entry.save.label" }}</span></button>
</li>
{{ end }}
{{ if .entry.ShareCode }}
<li>
<a href="{{ route "sharedEntry" "shareCode" .entry.ShareCode }}"
title="{{ t "entry.shared_entry.title" }}"
data-share-status="shared"
{{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}>{{ icon "share" }}<span class="icon-label">{{ t "entry.shared_entry.label" }}</span></a>
</li>
<li>
<button
class="page-button"
data-confirm="true"
data-url="{{ route "unshareEntry" "entryID" .entry.ID }}"
data-label-question="{{ t "confirm.question" }}"
data-label-yes="{{ t "confirm.yes" }}"
data-label-no="{{ t "confirm.no" }}"
data-label-loading="{{ t "confirm.loading" }}">{{ icon "delete" }}<span class="icon-label">{{ t "entry.unshare.label" }}</span></button>
</li>
{{ else }}
<li>
<form method="post" action="{{route "shareEntry" "entryID" .entry.ID }}">
<input type="hidden" name="csrf" value="{{ .csrf }}">
<button type="submit" class="page-button">
{{ icon "share" }}<span class="icon-label">{{ t "entry.share.label" }}</span>
</button>
</form>
</li>
{{ end }}
<li>
<button
class="page-button"
title="{{ t "entry.scraper.title" }}"
data-fetch-content-entry="true"
data-fetch-content-url="{{ route "fetchContent" "entryID" .entry.ID }}"
data-label-loading="{{ t "entry.state.loading" }}"
>{{ icon "scraper" }}<span class="icon-label">{{ t "entry.scraper.label" }}</span></button>
</li>
{{ if .entry.CommentsURL }}
<li>
<a href="{{ .entry.CommentsURL | safeURL }}"
class="page-link"
title="{{ t "entry.comments.title" }}"
{{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}
rel="noopener noreferrer"
referrerpolicy="no-referrer"
data-comments-link="true"
>{{ icon "comment" }}<span class="icon-label">{{ t "entry.comments.label" }}</span></a>
</li>
{{ end }}
</ul>
</div>
{{ end }}
<div class="entry-meta" dir="auto">
<span class="entry-website">
{{ if ne .entry.Feed.Icon.IconID 0 }}
<img src="{{ route "feedIcon" "externalIconID" .entry.Feed.Icon.ExternalIconID }}" width="16" height="16" loading="lazy" alt="{{ .entry.Feed.Title }}">
{{ end }}
{{ if .user }}
<a href="{{ route "feedEntries" "feedID" .entry.Feed.ID }}">{{ .entry.Feed.Title }}</a>
{{ else }}
<a href="{{ .entry.Feed.SiteURL | safeURL }}">{{ .entry.Feed.Title }}</a>
{{ end }}
</span>
{{ if .entry.Author }}
<span class="entry-author">
{{ if isEmail .entry.Author }}
- <a href="mailto:{{ .entry.Author }}">{{ .entry.Author }}</a>
{{ else }}
<em>{{ .entry.Author }}</em>
{{ end }}
</span>
{{ end }}
{{ if .user }}
<span class="category">
<a href="{{ route "categoryEntries" "categoryID" .entry.Feed.Category.ID }}">{{ .entry.Feed.Category.Title }}</a>
</span>
{{ end }}
</div>
{{ if .entry.Tags }}
<div class="entry-tags">
{{ t "entry.tags.label" }}
{{ $allTags := .entry.Tags }}
{{ $numTags := len $allTags }}
{{ $tagsLimit := 5 }}
{{ $numerOfAdditionalTags := subtract $numTags $tagsLimit }}
<ul class="entry-tags-list">
{{ range $i, $tagName := $allTags }}
{{ if lt $i $tagsLimit }}
{{ if $.user }}
<li><a href="{{ route "tagEntriesAll" "tagName" (urlEncode $tagName) }}"><strong>{{ $tagName }}</strong></a></li>
{{ else }}
<li><strong>{{ $tagName }}</strong></li>
{{ end }}
{{ end }}
{{ end }}
</ul>
{{ if gt $numTags $tagsLimit }}
<details class="entry-additional-tags">
<summary>
{{ plural "entry.tags.more_tags_label" $numerOfAdditionalTags $numerOfAdditionalTags }}
</summary>
<ul class="entry-tags-list">
{{ range $idx, $tagName := $allTags }}
{{ if ge $idx $tagsLimit }}
{{ if $.user }}
<li><a href="{{ route "tagEntriesAll" "tagName" (urlEncode $tagName) }}"><strong>{{ $tagName }}</strong></a></li>
{{ else }}
<li><strong>{{ $tagName }}</strong></li>
{{ end }}
{{ end }}
{{ end }}
</ul>
</details>
{{ end }}
</div>
{{ end }}
<div class="entry-external-link">
<a
href="{{ .entry.URL | safeURL }}"
{{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }}
rel="noopener noreferrer"
referrerpolicy="no-referrer"
data-original-link="{{ $.user.MarkReadOnView }}">{{ .entry.URL }}</span></a>
</div>
<div class="entry-date">
{{ if .user }}
<time datetime="{{ isodate .entry.Date }}" title="{{ isodate .entry.Date }}">{{ elapsed $.user.Timezone .entry.Date }}</time>
{{ else }}
<time datetime="{{ isodate .entry.Date }}" title="{{ isodate .entry.Date }}">{{ elapsed "UTC" .entry.Date }}</time>
{{ end }}
{{ if and .user.ShowReadingTime (gt .entry.ReadingTime 0) }}
&centerdot;
<span class="entry-reading-time">
{{ plural "entry.estimated_reading_time" .entry.ReadingTime .entry.ReadingTime }}
</span>
{{ end }}
</div>
</header>
</section>
{{ end }}
{{ define "content"}}
{{ if gt (len .entry.Content) 120 }}
{{ if .user }}
<div class="pagination-entry-top">
{{ template "entry_pagination" . }}
</div>
{{ end }}
{{ end }}
<article class="entry-content {{ if ne $.user.GestureNav "none" }}gesture-nav-{{ $.user.GestureNav }}{{ end }}" dir="auto">
{{ if not .entry.Feed.NoMediaPlayer }}
{{ $mediaPlayerEnclosure := .entry.Enclosures.FindMediaPlayerEnclosure }}
{{ if $mediaPlayerEnclosure }}
{{ with $mediaPlayerEnclosure }}
{{ if .IsAudio }}
<div class="enclosure-audio" >
<audio controls preload="metadata"
{{ if $.user }}data-last-position="{{ .MediaProgression }}"{{ end }}
{{ if $.user.MediaPlaybackRate }}data-playback-rate="{{ $.user.MediaPlaybackRate }}"{{ end }}
{{ if $.user.MarkReadOnMediaPlayerCompletion }}data-mark-read-on-completion="0.9"{{ end }}
{{ if $.user }}data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"{{ end }}
data-enclosure-id="{{ .ID }}"
>
{{ if (and $.user (mustBeProxyfied "audio")) }}
<source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
{{ else }}
<source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
{{ end }}
</audio>
{{ template "enclosure_media_controls" . }}
</div>
{{ else if .IsVideo }}
<div class="enclosure-video">
<video controls preload="metadata"
{{ if $.user }}data-last-position="{{ .MediaProgression }}"{{ end }}
{{ if $.user.MediaPlaybackRate }}data-playback-rate="{{ $.user.MediaPlaybackRate }}"{{ end }}
{{ if $.user.MarkReadOnMediaPlayerCompletion }}data-mark-read-on-completion="0.9"{{ end }}
{{ if $.user }}data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"{{ end }}
data-enclosure-id="{{ .ID }}"
>
{{ if (and $.user (mustBeProxyfied "video")) }}
<source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
{{ else }}
<source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
{{ end }}
</video>
{{ template "enclosure_media_controls" . }}
</div>
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ if .user }}
{{ noescape (proxyFilter .entry.Content) }}
{{ else }}
{{ noescape .entry.Content }}
{{ end }}
</article>
{{ if .entry.Enclosures }}
<details class="entry-enclosures">
<summary>{{ t "page.entry.attachments" }} ({{ len .entry.Enclosures }})</summary>
{{ range .entry.Enclosures }}
{{ if ne .URL "" }}
<div class="entry-enclosure">
{{ if .IsImage }}
<div class="enclosure-image">
{{ if (and $.user (mustBeProxyfied "image")) }}
<img src="{{ proxyURL .URL }}" title="{{ .URL }} ({{ .MimeType }})" loading="lazy" alt="{{ .URL }} ({{ .MimeType }})">
{{ else }}
<img src="{{ .URL | safeURL }}" title="{{ .URL }} ({{ .MimeType }})" loading="lazy" alt="{{ .URL }} ({{ .MimeType }})">
{{ end }}
</div>
{{ end }}
<div class="entry-enclosure-download">
<a href="{{ .URL | safeURL }}" title="{{ t "action.download" }}{{ if gt .Size 0 }} - {{ formatFileSize .Size }}{{ end }}" {{ if $.user.OpenExternalLinksInNewTab }}target="_blank"{{ end }} rel="noopener noreferrer" referrerpolicy="no-referrer">{{ .URL | safeURL }}</a>
<small>{{ if gt .Size 0 }} - <strong>{{ formatFileSize .Size }}</strong>{{ end }}</small>
</div>
</div>
{{ end }}
{{ end }}
</details>
{{ end }}
{{ if .user }}
<div class="pagination-entry-bottom">
{{ template "entry_pagination" . }}
</div>
{{ end }}
{{ end }}