|
|
@@ -1,9 +1,9 @@
|
|
|
{{ define "title"}}{{ .entry.Title }}{{ end }}
|
|
|
|
|
|
-{{ define "content"}}
|
|
|
-<section class="entry" data-id="{{ .entry.ID }}">
|
|
|
- <header class="entry-header">
|
|
|
- <h1 dir="auto">
|
|
|
+{{ define "header"}}
|
|
|
+<header class="page-header" aria-labelledby="page-header-title">
|
|
|
+ <div class="entry-header">
|
|
|
+ <h1 id="page-header-title" dir="auto">
|
|
|
<a href="{{ .entry.URL | safeURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer">{{ .entry.Title }}</a>
|
|
|
</h1>
|
|
|
{{ if .user }}
|
|
|
@@ -34,40 +34,40 @@
|
|
|
>{{ 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></a>
|
|
|
</li>
|
|
|
{{ if .hasSaveEntry }}
|
|
|
- <li>
|
|
|
- <a href="#"
|
|
|
- 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></a>
|
|
|
- </li>
|
|
|
+ <li>
|
|
|
+ <a href="#"
|
|
|
+ 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></a>
|
|
|
+ </li>
|
|
|
{{ end }}
|
|
|
{{ if .entry.ShareCode }}
|
|
|
- <li>
|
|
|
- <a href="{{ route "sharedEntry" "shareCode" .entry.ShareCode }}"
|
|
|
- title="{{ t "entry.shared_entry.title" }}"
|
|
|
- data-share-status="shared"
|
|
|
- target="_blank">{{ icon "share" }}<span class="icon-label">{{ t "entry.shared_entry.label" }}</span></a>
|
|
|
- </li>
|
|
|
- <li>
|
|
|
- <a href="#"
|
|
|
- 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></a>
|
|
|
- </li>
|
|
|
+ <li>
|
|
|
+ <a href="{{ route "sharedEntry" "shareCode" .entry.ShareCode }}"
|
|
|
+ title="{{ t "entry.shared_entry.title" }}"
|
|
|
+ data-share-status="shared"
|
|
|
+ target="_blank">{{ icon "share" }}<span class="icon-label">{{ t "entry.shared_entry.label" }}</span></a>
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <a href="#"
|
|
|
+ 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></a>
|
|
|
+ </li>
|
|
|
{{ else }}
|
|
|
- <li>
|
|
|
- <a href="{{ route "shareEntry" "entryID" .entry.ID }}"
|
|
|
- title="{{ t "entry.share.title" }}"
|
|
|
- data-share-status="share"
|
|
|
- target="_blank">{{ icon "share" }}<span class="icon-label">{{ t "entry.share.label" }}</span></a>
|
|
|
- </li>
|
|
|
+ <li>
|
|
|
+ <a href="{{ route "shareEntry" "entryID" .entry.ID }}"
|
|
|
+ title="{{ t "entry.share.title" }}"
|
|
|
+ data-share-status="share"
|
|
|
+ target="_blank">{{ icon "share" }}<span class="icon-label">{{ t "entry.share.label" }}</span></a>
|
|
|
+ </li>
|
|
|
{{ end }}
|
|
|
<li>
|
|
|
<a href="{{ .entry.URL | safeURL }}"
|
|
|
@@ -85,15 +85,15 @@
|
|
|
>{{ icon "scraper" }}<span class="icon-label">{{ t "entry.scraper.label" }}</span></a>
|
|
|
</li>
|
|
|
{{ if .entry.CommentsURL }}
|
|
|
- <li>
|
|
|
- <a href="{{ .entry.CommentsURL | safeURL }}"
|
|
|
- title="{{ t "entry.comments.title" }}"
|
|
|
- target="_blank"
|
|
|
- rel="noopener noreferrer"
|
|
|
- referrerpolicy="no-referrer"
|
|
|
- data-comments-link="true"
|
|
|
+ <li>
|
|
|
+ <a href="{{ .entry.CommentsURL | safeURL }}"
|
|
|
+ title="{{ t "entry.comments.title" }}"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener noreferrer"
|
|
|
+ referrerpolicy="no-referrer"
|
|
|
+ data-comments-link="true"
|
|
|
>{{ icon "comment" }}<span class="icon-label">{{ t "entry.comments.label" }}</span></a>
|
|
|
- </li>
|
|
|
+ </li>
|
|
|
{{ end }}
|
|
|
</ul>
|
|
|
</div>
|
|
|
@@ -101,40 +101,40 @@
|
|
|
<div class="entry-meta" dir="auto">
|
|
|
<span class="entry-website">
|
|
|
{{ if and .user (ne .entry.Feed.Icon.IconID 0) }}
|
|
|
- <img src="{{ route "icon" "iconID" .entry.Feed.Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .entry.Feed.Title }}">
|
|
|
+ <img src="{{ route "icon" "iconID" .entry.Feed.Icon.IconID }}" 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>
|
|
|
+ <a href="{{ route "feedEntries" "feedID" .entry.Feed.ID }}">{{ .entry.Feed.Title }}</a>
|
|
|
{{ else }}
|
|
|
- <a href="{{ .entry.Feed.SiteURL | safeURL }}">{{ .entry.Feed.Title }}</a>
|
|
|
+ <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>
|
|
|
+ <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>
|
|
|
+ <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" }}
|
|
|
- {{range $i, $e := .entry.Tags}}{{if $i}}, {{end}}<strong>{{ $e }}</strong>{{end}}
|
|
|
- </div>
|
|
|
+ <div class="entry-tags">
|
|
|
+ {{ t "entry.tags.label" }}
|
|
|
+ {{range $i, $e := .entry.Tags}}{{if $i}}, {{end}}<strong>{{ $e }}</strong>{{end}}
|
|
|
+ </div>
|
|
|
{{ end }}
|
|
|
<div class="entry-date">
|
|
|
{{ if .user }}
|
|
|
- <time datetime="{{ isodate .entry.Date }}" title="{{ isodate .entry.Date }}">{{ elapsed $.user.Timezone .entry.Date }}</time>
|
|
|
+ <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>
|
|
|
+ <time datetime="{{ isodate .entry.Date }}" title="{{ isodate .entry.Date }}">{{ elapsed "UTC" .entry.Date }}</time>
|
|
|
{{ end }}
|
|
|
{{ if and .user.ShowReadingTime (gt .entry.ReadingTime 0) }}
|
|
|
·
|
|
|
@@ -143,106 +143,111 @@
|
|
|
</span>
|
|
|
{{ end }}
|
|
|
</div>
|
|
|
- </header>
|
|
|
- {{ if gt (len .entry.Content) 120 }}
|
|
|
- {{ if .user }}
|
|
|
- <div class="pagination-entry-top">
|
|
|
- {{ template "entry_pagination" . }}
|
|
|
</div>
|
|
|
- {{ end }}
|
|
|
- {{ end }}
|
|
|
- <article role="article" class="entry-content gesture-nav-{{ $.user.GestureNav }}" dir="auto">
|
|
|
- {{ if (and .entry.Enclosures (not .entry.Feed.NoMediaPlayer)) }}
|
|
|
- {{ range .entry.Enclosures }}
|
|
|
- {{ if ne .URL "" }}
|
|
|
- {{ if hasPrefix .MimeType "audio/" }}
|
|
|
- <div class="enclosure-audio" >
|
|
|
- <audio controls preload="metadata"
|
|
|
- data-last-position="{{ .MediaProgression }}"
|
|
|
- data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"
|
|
|
- >
|
|
|
- {{ if (and $.user (mustBeProxyfied "audio")) }}
|
|
|
- <source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
|
|
|
- {{ else }}
|
|
|
- <source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
|
|
|
- {{ end }}
|
|
|
- </audio>
|
|
|
- </div>
|
|
|
- {{ else if hasPrefix .MimeType "video/" }}
|
|
|
- <div class="enclosure-video">
|
|
|
- <video controls preload="metadata"
|
|
|
- data-last-position="{{ .MediaProgression }}"
|
|
|
- data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"
|
|
|
- >
|
|
|
- {{ if (and $.user (mustBeProxyfied "video")) }}
|
|
|
- <source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
|
|
|
- {{ else }}
|
|
|
- <source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
|
|
|
- {{ end }}
|
|
|
- </video>
|
|
|
- </div>
|
|
|
- {{ end }}
|
|
|
- {{ end }}
|
|
|
+</header>
|
|
|
+{{ end }}
|
|
|
+
|
|
|
+
|
|
|
+{{ define "content"}}
|
|
|
+{{ if gt (len .entry.Content) 120 }}
|
|
|
+{{ if .user }}
|
|
|
+<div class="pagination-entry-top">
|
|
|
+ {{ template "entry_pagination" . }}
|
|
|
+</div>
|
|
|
+{{ end }}
|
|
|
+{{ end }}
|
|
|
+<article role="article" class="entry-content gesture-nav-{{ $.user.GestureNav }}" dir="auto">
|
|
|
+ {{ if (and .entry.Enclosures (not .entry.Feed.NoMediaPlayer)) }}
|
|
|
+ {{ range .entry.Enclosures }}
|
|
|
+ {{ if ne .URL "" }}
|
|
|
+ {{ if hasPrefix .MimeType "audio/" }}
|
|
|
+ <div class="enclosure-audio" >
|
|
|
+ <audio controls preload="metadata"
|
|
|
+ data-last-position="{{ .MediaProgression }}"
|
|
|
+ data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"
|
|
|
+ >
|
|
|
+ {{ if (and $.user (mustBeProxyfied "audio")) }}
|
|
|
+ <source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
|
|
|
+ {{ else }}
|
|
|
+ <source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
|
|
|
{{ end }}
|
|
|
+ </audio>
|
|
|
+ </div>
|
|
|
+ {{ else if hasPrefix .MimeType "video/" }}
|
|
|
+ <div class="enclosure-video">
|
|
|
+ <video controls preload="metadata"
|
|
|
+ data-last-position="{{ .MediaProgression }}"
|
|
|
+ data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"
|
|
|
+ >
|
|
|
+ {{ if (and $.user (mustBeProxyfied "video")) }}
|
|
|
+ <source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
|
|
|
+ {{ else }}
|
|
|
+ <source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
|
|
|
+ {{ end }}
|
|
|
+ </video>
|
|
|
+ </div>
|
|
|
+ {{ end }}
|
|
|
+ {{ end }}
|
|
|
+ {{ end }}
|
|
|
{{end}}
|
|
|
{{ if .user }}
|
|
|
- {{ noescape (proxyFilter .entry.Content) }}
|
|
|
+ {{ noescape (proxyFilter .entry.Content) }}
|
|
|
{{ else }}
|
|
|
- {{ noescape .entry.Content }}
|
|
|
+ {{ 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 hasPrefix .MimeType "audio/" }}
|
|
|
- <div class="enclosure-audio">
|
|
|
- <audio controls preload="metadata"
|
|
|
- data-last-position="{{ .MediaProgression }}"
|
|
|
- data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"
|
|
|
- >
|
|
|
- {{ if (and $.user (mustBeProxyfied "audio")) }}
|
|
|
- <source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
|
|
|
- {{ else }}
|
|
|
- <source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
|
|
|
- {{ end }}
|
|
|
- </audio>
|
|
|
- </div>
|
|
|
- {{ else if hasPrefix .MimeType "video/" }}
|
|
|
- <div class="enclosure-video">
|
|
|
- <video controls preload="metadata"
|
|
|
- data-last-position="{{ .MediaProgression }}"
|
|
|
- data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"
|
|
|
- >
|
|
|
- {{ if (and $.user (mustBeProxyfied "video")) }}
|
|
|
- <source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
|
|
|
- {{ else }}
|
|
|
- <source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
|
|
|
- {{ end }}
|
|
|
- </video>
|
|
|
- </div>
|
|
|
- {{ else if hasPrefix .MimeType "image/" }}
|
|
|
- <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>
|
|
|
+</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 hasPrefix .MimeType "audio/" }}
|
|
|
+ <div class="enclosure-audio">
|
|
|
+ <audio controls preload="metadata"
|
|
|
+ data-last-position="{{ .MediaProgression }}"
|
|
|
+ data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"
|
|
|
+ >
|
|
|
+ {{ if (and $.user (mustBeProxyfied "audio")) }}
|
|
|
+ <source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
|
|
|
+ {{ else }}
|
|
|
+ <source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
|
|
|
{{ end }}
|
|
|
-
|
|
|
- <div class="entry-enclosure-download">
|
|
|
- <a href="{{ .URL | safeURL }}" title="{{ t "action.download" }}{{ if gt .Size 0 }} - {{ formatFileSize .Size }}{{ end }} ({{ .MimeType }})" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer">{{ .URL | safeURL }}</a>
|
|
|
- <small>{{ if gt .Size 0 }} - <strong>{{ formatFileSize .Size }}</strong>{{ end }}</small>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </audio>
|
|
|
+ </div>
|
|
|
+ {{ else if hasPrefix .MimeType "video/" }}
|
|
|
+ <div class="enclosure-video">
|
|
|
+ <video controls preload="metadata"
|
|
|
+ data-last-position="{{ .MediaProgression }}"
|
|
|
+ data-save-url="{{ route "saveEnclosureProgression" "enclosureID" .ID }}"
|
|
|
+ >
|
|
|
+ {{ if (and $.user (mustBeProxyfied "video")) }}
|
|
|
+ <source src="{{ proxyURL .URL }}" type="{{ .Html5MimeType }}">
|
|
|
+ {{ else }}
|
|
|
+ <source src="{{ .URL | safeURL }}" type="{{ .Html5MimeType }}">
|
|
|
+ {{ end }}
|
|
|
+ </video>
|
|
|
+ </div>
|
|
|
+ {{ else if hasPrefix .MimeType "image/" }}
|
|
|
+ <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 }}
|
|
|
- </details>
|
|
|
+
|
|
|
+ <div class="entry-enclosure-download">
|
|
|
+ <a href="{{ .URL | safeURL }}" title="{{ t "action.download" }}{{ if gt .Size 0 }} - {{ formatFileSize .Size }}{{ end }} ({{ .MimeType }})" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer">{{ .URL | safeURL }}</a>
|
|
|
+ <small>{{ if gt .Size 0 }} - <strong>{{ formatFileSize .Size }}</strong>{{ end }}</small>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
{{ end }}
|
|
|
-</section>
|
|
|
+ {{ end }}
|
|
|
+</details>
|
|
|
+{{ end }}
|
|
|
+
|
|
|
|
|
|
{{ if .user }}
|
|
|
<div class="pagination-entry-bottom">
|