diff options
author | Case Duckworth | 2022-07-23 22:50:20 -0500 |
---|---|---|
committer | Case Duckworth | 2022-07-23 22:50:20 -0500 |
commit | 2222a1aa7306200528de3d00edc7330fb4400c4f (patch) | |
tree | f23a21e4d80b6bfba98f9270a922ad2a0f884f12 | |
parent | Add javascript to hide/show stale feeds (diff) | |
download | sfeed-2222a1aa7306200528de3d00edc7330fb4400c4f.tar.gz sfeed-2222a1aa7306200528de3d00edc7330fb4400c4f.zip |
Convert sfeed_html.sh to sfeed_html.awk
-rwxr-xr-x | sfeed_html.awk | 341 | ||||
-rwxr-xr-x | sfeed_html.sh | 223 |
2 files changed, 341 insertions, 223 deletions
diff --git a/sfeed_html.awk b/sfeed_html.awk new file mode 100755 index 0000000..8477677 --- /dev/null +++ b/sfeed_html.awk | |||
@@ -0,0 +1,341 @@ | |||
1 | #!/bin/awk -f | ||
2 | # Convert sfeed(1) formatted files into an HTML webpage. | ||
3 | # Usage: sfeed_html.awk -- FILES... | ||
4 | |||
5 | ## Set up variables | ||
6 | BEGIN { | ||
7 | # Sidebar | ||
8 | if (! ASIDE) { | ||
9 | ASIDE = envor("SFEED_HTML_ASIDE", "/tmp/sfeed-aside.html") | ||
10 | } | ||
11 | print > ASIDE # clear out ASIDE | ||
12 | in_aside = 0 # Don't show the feed in the sidebar | ||
13 | # Formatting | ||
14 | if (! DATEFMT) { | ||
15 | DATEFMT = envor("SFEED_HTML_DATEFMT", "<span class=date>%F</span> <span class=time>%RZ</span>") | ||
16 | } | ||
17 | if (! TITLE) { | ||
18 | TITLE = envor("SFEED_HTML_TITLE", "Planet ACDW") | ||
19 | } | ||
20 | if (! SEPARATOR) { | ||
21 | SEPARATOR = envor("SFEED_HTML_SEPARATOR", "//") | ||
22 | } | ||
23 | if (! ALT_LINK_STAMP) { | ||
24 | ALT_LINK_STAMP = envor("SFEED_ALT_LINK_STAMP", "&") | ||
25 | } | ||
26 | if (! ENCLOSURE_STAMP) { | ||
27 | ENCLOSURE_STAMP = envor("SFEED_ENCLOSURE_STAMP", "@") | ||
28 | } | ||
29 | if (! SILO_STAMP) { | ||
30 | SILO_STAMP = envor("SFEED_SILO_STAMP", "%") | ||
31 | } | ||
32 | # Limiting posts... | ||
33 | ## by time | ||
34 | if (! NOW) { | ||
35 | datecmd = "date +%s" | ||
36 | datecmd | getline NOW | ||
37 | close(datecmd) | ||
38 | } | ||
39 | if (! FRESHDAYS) { | ||
40 | FRESHDAYS = envor("SFEED_FRESHDAYS", 1.5) | ||
41 | } | ||
42 | if (! STALEDAYS) { | ||
43 | STALEDAYS = envor("SFEED_STALEDAYS", 4) | ||
44 | } | ||
45 | fresh_secs = FRESHDAYS * 24 * 60 * 60 | ||
46 | stale_secs = STALEDAYS * 24 * 60 * 60 | ||
47 | fresh_age = (NOW - fresh_secs) | ||
48 | stale_age = (NOW - stale_secs) | ||
49 | ## by number | ||
50 | if (! LIMIT) { | ||
51 | # If LIMIT == -1, ignore time limit as well. | ||
52 | LIMIT = envor("SFEED_LIMIT", 20) | ||
53 | } | ||
54 | # Alternate URLs for siloed content | ||
55 | if (! YOUTUBE_ALT_URL) { | ||
56 | YOUTUBE_ALT_URL = envor("SFEED_YOUTUBE_ALT_URL", "https://piped.kavin.rocks") | ||
57 | } | ||
58 | if (! TWITTER_ALT_URL) { | ||
59 | TWITTER_ALT_URL = envor("SFEED_TWITTER_ALT_URL", "https://nitter.net") | ||
60 | } | ||
61 | if (! REDDIT_ALT_URL) { | ||
62 | REDDIT_ALT_URL = envor("SFEED_REDDIT_ALT_URL", "https://libreddit.spike.codes") | ||
63 | } | ||
64 | # Awk and convenience constants | ||
65 | FS = "\t" | ||
66 | STDERR = "/dev/stderr" | ||
67 | } | ||
68 | |||
69 | ## Print HTML header | ||
70 | BEGIN { | ||
71 | fortunecmd = "fortune" | ||
72 | fortunecmd | getline LOGO_TITLE | ||
73 | close(fortunecmd) | ||
74 | sub(/"/, "", LOGO_TITLE) | ||
75 | datecmd = "date -u +'" DATEFMT "'" | ||
76 | datecmd | getline UPDATE_TIME | ||
77 | close(datecmd) | ||
78 | print "<!DOCTYPE html>" | ||
79 | print "<html>" | ||
80 | # <head> | ||
81 | print "<head>" | ||
82 | print "<meta charset=\"utf-8\">" | ||
83 | print "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">" | ||
84 | print "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">" | ||
85 | print "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" | ||
86 | print "<title>" TITLE "</title>" | ||
87 | print "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">" | ||
88 | print "<link rel=\"shortcut icon\" type=\"image/png\" href=\"mars-eyes.png\">" | ||
89 | print "<link rel=\"alternate\" type=\"application/atom+xml\" title=\"rss (full)\" href=\"feeds.xml\">" | ||
90 | print "<link rel=\"alternate\" type=\"application/atom+xml\" title=\"rss (short)\" href=\"feeds-short.xml\">" | ||
91 | print "<link rel=\"alternate\" type=\"application/xml\" title=\"opml\" href=\"feeds.opml\">" | ||
92 | print "<link rel=\"alternate\" type=\"text/plain\" title=\"twtxt\" href=\"feeds.txt\">" | ||
93 | print "</head>" | ||
94 | print "<body>" | ||
95 | # <header> | ||
96 | print "<header id=\"page-header\">" | ||
97 | print "<h1>" | ||
98 | printf "<a id=\"logo\" href=\"index.html\"><img src=\"mars-eyes.png\"" | ||
99 | printf " title=\"%s\" ", LOGO_TITLE | ||
100 | printf "width=\"40\" height=\"39\"" | ||
101 | print "alt=\"mars, but with eyes\" /></a>" | ||
102 | print TITLE "</h1>" | ||
103 | print "<p id=\"last-updated\">last updated at <time>" UPDATE_TIME "</time></p>" | ||
104 | print "</header>" | ||
105 | # <nav> | ||
106 | print "<nav id=\"page-nav\">" | ||
107 | print "<a href=\"#\" id=\"stalebutton\">hide stale</a>", SEPARATOR | ||
108 | print "<a href=\"feeds-short.xml\">rss</a>", SEPARATOR | ||
109 | print "<a href=\"feeds.html\">all</a>", "(<a href=\"feeds.xml\">rss</a>)", SEPARATOR | ||
110 | print "<a href=\"feeds.txt\">twtxt</a>", SEPARATOR | ||
111 | print "<a href=\"feeds.opml\">opml</a>" | ||
112 | print "</nav>" | ||
113 | # first part of <main> | ||
114 | print "<main>" | ||
115 | print "<section id=\"list\">" | ||
116 | } | ||
117 | |||
118 | FNR == 1 { | ||
119 | if (file_count) { | ||
120 | # End the previous file before beginning the current one | ||
121 | end_file() | ||
122 | } | ||
123 | # Filename | ||
124 | name = FILENAME | ||
125 | sub(/.*\//, "", name) | ||
126 | safe_name = name | ||
127 | sub(/\//, "_", safe_name) | ||
128 | dir = FILENAME | ||
129 | sub(/[^\/]*$/, "", dir) | ||
130 | if (name ~ /\[yt\]$/) { | ||
131 | sub(/ \[yt\]$/, "", name) | ||
132 | yt = " class=\"yt\"" | ||
133 | } else { | ||
134 | yt = "" | ||
135 | } | ||
136 | URLS = envor("SFEED_DATA", ENVIRON["HOME"] "/.sfeed") "/urls/" safe_name | ||
137 | # State variables | ||
138 | stamp = "." | ||
139 | buf = "" | ||
140 | ni = 0 | ||
141 | stale_count = 0 | ||
142 | fresh_count = 0 | ||
143 | item_count = 0 | ||
144 | file_count++ | ||
145 | siloed = 0 | ||
146 | } | ||
147 | |||
148 | { | ||
149 | # Skip if we have too many items | ||
150 | if ((LIMIT > 0) && (++ni > LIMIT)) { | ||
151 | next | ||
152 | } | ||
153 | # Collect fields | ||
154 | timestamp = $1 | ||
155 | title = $2 | ||
156 | silo = $3 | ||
157 | link = silo_link(silo) | ||
158 | content = unescape($4) | ||
159 | content_type = $5 | ||
160 | id = $6 | ||
161 | author = $7 | ||
162 | enclosure = $8 | ||
163 | category = $9 | ||
164 | # Skip if the item is too old | ||
165 | if ((LIMIT >= 0) && (timestamp < stale_age)) { | ||
166 | next | ||
167 | } | ||
168 | # Otherwise, we're showing it | ||
169 | stale_count++ | ||
170 | # Is this item fresh? | ||
171 | if (timestamp >= fresh_age) { | ||
172 | is_fresh = 1 | ||
173 | stamp = "!" | ||
174 | fresh_count++ | ||
175 | } else { | ||
176 | is_fresh = 0 | ||
177 | } | ||
178 | # Print! | ||
179 | bufprint("<tr class=\"entry " (is_fresh ? "fresh" : "stale") "\">") | ||
180 | # Timestamp | ||
181 | datecmd = "date -d \"@" timestamp "\" +'" DATEFMT "'" | ||
182 | if (timestamp) { | ||
183 | datecmd | getline timestamp | ||
184 | close(datecmd) | ||
185 | } | ||
186 | bufprint("<td class=\"entry-timestamp\"><time>" timestamp "</time></td>") | ||
187 | # Extra links | ||
188 | bufprint("<td class=\"entry-extra\">") | ||
189 | if (siloed) { | ||
190 | # "siloed" links like youtube, facebook, etc. --- I convert them | ||
191 | # to more privacy-friendly links, but sometimes those don't | ||
192 | # work. TODO: also try to circumvent paywalls. | ||
193 | stamp = SILO_STAMP | ||
194 | print_link(silo, "Silo: " silo, stamp) | ||
195 | } | ||
196 | if (enclosure) { | ||
197 | # enclosures --- podcast files, etc. | ||
198 | stamp = ENCLOSURE_STAMP | ||
199 | print_link(enclosure, "Enclosure: " enclosure, stamp) | ||
200 | } | ||
201 | if ((link != id) && (id != enclosure) && (id ~ /^https?:/)) { | ||
202 | # alternate links (comments, etc.) | ||
203 | stamp = ALT_LINK_STAMP | ||
204 | print_link(id, "alternate link", stamp) | ||
205 | } | ||
206 | bufprint("</td>") | ||
207 | # Title | ||
208 | bufprint("<td class=\"entry-title" silo_class(silo) "\">") | ||
209 | print_link(link, "", title) | ||
210 | bufprint("</td>") | ||
211 | # End row | ||
212 | bufprint("</tr>") | ||
213 | item_count++ | ||
214 | } | ||
215 | |||
216 | END { | ||
217 | # End the last file and the #list section | ||
218 | end_file() | ||
219 | print "</section>" | ||
220 | # Sidebar | ||
221 | print "<aside><ul id=\"feedlist\">" | ||
222 | system("cat " ASIDE) | ||
223 | close(ASIDE) | ||
224 | print "</ul></aside>" | ||
225 | # End of <main> | ||
226 | print "</main>" | ||
227 | # footer | ||
228 | printf "<footer>" | ||
229 | print "Generated by <a href=\"https://codemadness.org/sfeed-simple-feed-parser.html\">sfeed</a>" | ||
230 | print "using <a href=\"https://git.acdw.net/sfeed/\">this configuration</a>." | ||
231 | print "<a href=\"mailto:planet@me.acdw.net\">suggest a feed!</a></footer>" | ||
232 | # end of HTML | ||
233 | print "<script src=\"script.js\"> </script>" | ||
234 | print "</body>" | ||
235 | print "</html>" | ||
236 | printf(SEPARATOR) > STDERR | ||
237 | } | ||
238 | |||
239 | |||
240 | function bufprint(text, sep) | ||
241 | { | ||
242 | buf = buf text (sep ? sep : ((sep == 0) ? "" : "\n")) | ||
243 | } | ||
244 | |||
245 | function end_file() | ||
246 | { | ||
247 | if (! item_count) { | ||
248 | return 1 | ||
249 | } | ||
250 | # Header | ||
251 | printf "<section id=\"%s\" class=\"%s\">\n", name, (fresh_count ? "fresh" : "stale") | ||
252 | printf "<header><h2%s><a class=\"anchor\" href=\"#%s\">#</a> %s</h2>\n", yt, name, name | ||
253 | # Feed links | ||
254 | printf "<nav class=\"flinks\">" | ||
255 | feed_url = "" | ||
256 | site_url = "" | ||
257 | getline feed_url < URLS | ||
258 | getline site_url < URLS | ||
259 | if (site_url) { | ||
260 | printf "<a class=\"site-url\" href=\"%s\">%s</a>\n", site_url, (yt ? "chan" : "site") | ||
261 | } | ||
262 | if (feed_url) { | ||
263 | printf "<a class=\"feed-url\" href=\"%s\">feed</a>\n", feed_url | ||
264 | } | ||
265 | # Top link | ||
266 | printf "<a class=\"top\" href=\"#\">top</a>" | ||
267 | printf "</nav>" | ||
268 | printf "</header>\n" | ||
269 | # Feed entries | ||
270 | printf "<table class=\"entries\">\n" | ||
271 | printf "%s", buf | ||
272 | printf "</table>\n</section>\n" | ||
273 | # Sidebar | ||
274 | if (stale_count) { | ||
275 | printf("<li class=\"%s\">", (fresh_count ? "fresh" : "stale")) >> ASIDE | ||
276 | printf("<a href=\"#%s\"%s>%s</a></li>\n", name, (yt ? " class=\"yt\"" : ""), name) >> ASIDE | ||
277 | } | ||
278 | # Log | ||
279 | printf("%s", stamp) > STDERR | ||
280 | } | ||
281 | |||
282 | function envor(var, def) | ||
283 | { | ||
284 | return (ENVIRON[var] ? ENVIRON[var] : def) | ||
285 | } | ||
286 | |||
287 | function html_escape(t) | ||
288 | { | ||
289 | gsub(/</, "\\<", t) | ||
290 | gsub(/>/, "\\>", t) | ||
291 | gsub(/&/, "\\&", t) | ||
292 | return t | ||
293 | } | ||
294 | |||
295 | function print_link(href, title, text) | ||
296 | { | ||
297 | bufprint("<a href=\"" href "\" title=\"" title "\" target=\"_blank\">" text "</a>", 0) | ||
298 | } | ||
299 | |||
300 | function silo_class(link) | ||
301 | { | ||
302 | if (link ~ /youtube\.com/) { | ||
303 | return " youtube" | ||
304 | } | ||
305 | if (link ~ /facebook\.com/) { | ||
306 | return " facebook" | ||
307 | } | ||
308 | if (link ~ /twitter\.com/) { | ||
309 | return " twitter" | ||
310 | } | ||
311 | if (link ~ /reddit\.com/) { | ||
312 | return " reddit" | ||
313 | } | ||
314 | return "" | ||
315 | } | ||
316 | |||
317 | function silo_link(link) | ||
318 | { | ||
319 | ret = link | ||
320 | http = "https?://[^\\.]*\\.?" | ||
321 | siloed = 1 | ||
322 | if (ret ~ (http "youtube\\.com")) { | ||
323 | sub(http "youtube\\.com", YOUTUBE_ALT_URL, ret) | ||
324 | } else if (ret ~ (http "reddit\\.com")) { | ||
325 | sub(http "reddit\\.com", REDDIT_ALT_URL, ret) | ||
326 | } else if (ret ~ (http "twitter\\.com")) { | ||
327 | sub(http "twitter\\.com", TWITTER_ALT_URL, ret) | ||
328 | } else { | ||
329 | siloed = 0 | ||
330 | } | ||
331 | return ret | ||
332 | } | ||
333 | |||
334 | function unescape(t) | ||
335 | { | ||
336 | t = html_escape(t) | ||
337 | gsub(/\\\t/, "\t", t) | ||
338 | gsub(/\\\n/, "\n", t) | ||
339 | gsub(/\\\\/, "\\", t) | ||
340 | return t | ||
341 | } | ||
diff --git a/sfeed_html.sh b/sfeed_html.sh deleted file mode 100755 index 3965a87..0000000 --- a/sfeed_html.sh +++ /dev/null | |||
@@ -1,223 +0,0 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | echo() { printf '%s\n' "$*"; } | ||
4 | |||
5 | html() { | ||
6 | : "${LIMIT:=12}" | ||
7 | : "${FRESH_DAYS:=1}" | ||
8 | : "${STALE_DAYS:=4}" | ||
9 | aside="$(mktemp /tmp/sfeed_html_aside.XXXXXX)" | ||
10 | cat <<EOF | ||
11 | $(html_head) | ||
12 | <body> | ||
13 | <header> | ||
14 | <h1> | ||
15 | <a href="index.html"><img src="mars-eyes.png" | ||
16 | title="$(fortune | tr -d '"')" | ||
17 | width="40" height="39" | ||
18 | alt="mars, but with eyes" /></a> | ||
19 | Planet ACDW</h1> | ||
20 | <p class="last-updated">last updated at <time>$(date -R)</time></p> | ||
21 | </header> | ||
22 | <nav> | ||
23 | <a href="#" id="stalebutton">hide stale</a> | ||
24 | // | ||
25 | <a href="feeds-short.xml">rss</a> | ||
26 | // | ||
27 | <a href="feeds.html">all</a> | ||
28 | (<a href="feeds.xml">rss</a>) | ||
29 | // | ||
30 | <a href="feeds.txt">twtxt</a> | ||
31 | // | ||
32 | <a href="feeds.opml">opml</a> | ||
33 | </nav> | ||
34 | <main> | ||
35 | $(html_main "$@") | ||
36 | <aside><ul id="feedlist">$(cat "$aside")</ul></aside> | ||
37 | </main> | ||
38 | <footer> | ||
39 | Generated by <a href="https://codemadness.org/sfeed-simple-feed-parser.html">sfeed</a> | ||
40 | using <a href="https://git.acdw.net/sfeed/">this configuration</a>. | ||
41 | <a href="mailto:planet@me.acdw.net">suggest a feed!</a> | ||
42 | </footer> | ||
43 | <script> | ||
44 | var staleHidden = false; | ||
45 | var staleItems = new Set(document.getElementsByClassName("stale")); | ||
46 | var staleFeeds = new Set(document.getElementsByClassName("stale_feed")); | ||
47 | var feedlistFeeds = new Set(document.getElementById("feedlist").children); | ||
48 | function hideShowStale(){ | ||
49 | var display; | ||
50 | if (staleHidden) { | ||
51 | display = null; staleHidden = false; | ||
52 | flBG = null; flBB = null; | ||
53 | } else { | ||
54 | display = 'none'; staleHidden = true; | ||
55 | flBG = 'inherit'; flBB = '1px solid'; | ||
56 | } | ||
57 | staleItems.forEach(e => { e.style.display = display; }); | ||
58 | staleFeeds.forEach(e => { e.style.display = display; }); | ||
59 | if (window.innerWidth > 720) { | ||
60 | feedlistFeeds.forEach(e => { e.style.background = flBG; e.style.borderBottom = flBB; }); | ||
61 | } | ||
62 | } | ||
63 | var button = document.getElementById("stalebutton"); | ||
64 | button.addEventListener("click", function() { | ||
65 | hideShowStale(); | ||
66 | if (staleHidden) { button.textContent = "show stale"; } | ||
67 | else { button.textContent = "hide stale"; } | ||
68 | }); | ||
69 | </script> | ||
70 | </body> | ||
71 | </html> | ||
72 | EOF | ||
73 | rm "$aside" | ||
74 | } | ||
75 | |||
76 | html_head() { | ||
77 | cat <<EOF | ||
78 | <!DOCTYPE html> | ||
79 | <html> | ||
80 | <head> | ||
81 | <meta charset="utf-8"> | ||
82 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
83 | <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> | ||
84 | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
85 | <title>Planet ACDW</title> | ||
86 | <link rel="stylesheet" type="text/css" href="style.css"> | ||
87 | <link rel="shortcut icon" type="image/png" href="mars-eyes.png"> | ||
88 | <link rel="alternate" type="application/atom+xml" title="rss (full)" href="feeds.xml"> | ||
89 | <link rel="alternate" type="application/atom+xml" title="rss (short)" href="feeds-short.xml"> | ||
90 | <link rel="alternate" type="application/xml" title="opml" href="feeds.opml"> | ||
91 | <link rel="alternate" type="text/plain" title="twtxt" href="feeds.txt"> | ||
92 | </head> | ||
93 | EOF | ||
94 | } | ||
95 | |||
96 | html_main() { | ||
97 | cat <<EOF | ||
98 | <section id="list"> | ||
99 | $(for file in "$@"; do html_feed "$file"; done) | ||
100 | </section> | ||
101 | EOF | ||
102 | } | ||
103 | |||
104 | filter_invidious() { | ||
105 | # Convert youtube links to invidious links | ||
106 | sed -e "s@https://www\.youtube\.com@https://piped.kavin.rocks@" \ | ||
107 | -e 's@https://i\.reddit\.com@https://libreddit.spike.codes@' \ | ||
108 | -e 's@https://twitter\.com@https://nitter.net@' | ||
109 | } | ||
110 | |||
111 | html_feed() { # html_feed FEED(file) => HTML | ||
112 | filename="$(basename "$1")" | ||
113 | now="$(date +%s)" | ||
114 | fresh_secs="$((FRESH_DAYS * 24 * 60 * 60))" | ||
115 | stale_secs="$((STALE_DAYS * 24 * 60 * 60))" | ||
116 | |||
117 | ## ENTRIES | ||
118 | entries="$(awk -v NOW="$now" \ | ||
119 | -v FRESH_SECS="$fresh_secs" -v STALE_SECS="$stale_secs" \ | ||
120 | -v NAME="$filename" -v FNAME="$filename" \ | ||
121 | -v ASIDE="$aside" -v limit="$LIMIT" \ | ||
122 | 'BEGIN { FS="\t"; fresh_feed = 0; FRESH = (NOW - FRESH_SECS); } | ||
123 | FNR == 1 { nitem = 0; } | ||
124 | NAME ~ /\[yt\]$/ { sub(/ \[yt\]$/, "", NAME); yt = 1; } | ||
125 | function unescape(t) { | ||
126 | t = html_escape(t); | ||
127 | gsub(/\\\t/,"\t",t); | ||
128 | gsub(/\\\n/,"\n",t); | ||
129 | gsub(/\\\\/,"\\",t); | ||
130 | return t | ||
131 | } | ||
132 | function html_escape(t) { | ||
133 | gsub(/</,"\\<",t); | ||
134 | gsub(/>/,"\\>",t); | ||
135 | gsub(/&/,"\\&",t); | ||
136 | return t | ||
137 | } | ||
138 | { | ||
139 | if (limit && (++nitem > limit)) next; | ||
140 | timestamp=$1; | ||
141 | title=$2; | ||
142 | link=$3; | ||
143 | content=unescape($4); | ||
144 | content_type=$5; | ||
145 | id=$6; | ||
146 | author=$7; | ||
147 | enclosure=$8; | ||
148 | category=$9; | ||
149 | |||
150 | if (limit && (timestamp < (NOW - STALE_SECS))) next; | ||
151 | show_in_sidebar = 1; | ||
152 | #print timestamp, title, link > "/dev/stderr"; | ||
153 | |||
154 | date_cmd = "date -d \"@" timestamp "\" +\"%F %R\"" | ||
155 | if (timestamp) { | ||
156 | date_cmd | getline ts; | ||
157 | close(date_cmd); | ||
158 | } | ||
159 | |||
160 | fresh = (timestamp >= FRESH) | ||
161 | if (fresh) fresh_feed = 1; | ||
162 | |||
163 | print "<tr class=\"entry " (fresh ? "fresh" : "stale") "\">" | ||
164 | print "<td class=\"entry-timestamp\">" ts "</td>" | ||
165 | printf "%s", "<td class=\"entry-extra\">" | ||
166 | if (enclosure) { | ||
167 | stamp = "@" | ||
168 | extra_title = " title=\"enclosure\"" | ||
169 | printf "%s", "<a href=\"" enclosure "\"" extra_title " target=\"_blank\">" stamp "</a>" | ||
170 | } | ||
171 | if ((link != id) && (id != enclosure) && (id ~ /^https?:/)) { | ||
172 | stamp = "&" | ||
173 | extra_title = " title=\"alternate link\"" | ||
174 | printf "%s", "<a href=\"" id "\"" extra_title " target=\"_blank\">" stamp "</a>" | ||
175 | } | ||
176 | print "</td>" | ||
177 | printf "<td class=\"entry-title%s", silo_links(link) | ||
178 | print "\"><a href=\"" link "\" target=\"_blank\">" title "</a></td>" | ||
179 | print "</tr>" | ||
180 | } | ||
181 | END { | ||
182 | if (show_in_sidebar) { | ||
183 | printf "<li class=\"%s\">", (fresh_feed?"fresh":"stale") >> ASIDE | ||
184 | printf "<a%s href=\"#%s\">%s</a></li>\n", (yt ? " class=\"yt\"" : ""), FNAME, NAME >> ASIDE | ||
185 | } | ||
186 | printf "%s", (stamp ? stamp : ".") > "/dev/stderr" | ||
187 | } | ||
188 | function silo_links(link) { | ||
189 | if (link ~ /youtube\.com/) return " youtube" | ||
190 | if (link ~ /facebook\.com/) return " facebook" | ||
191 | if (link ~ /twitter\.com/) return " twitter" | ||
192 | if (link ~ /reddit\.com/) return " reddit" | ||
193 | return "" | ||
194 | } | ||
195 | ' "$1" | filter_invidious)" | ||
196 | if [ -z "$entries" ]; then return 1; fi | ||
197 | fresh_feed='stale_feed' | ||
198 | if echo "$entries" | grep -q 'class="[^"]*fresh"'; then fresh_feed='fresh_feed'; fi | ||
199 | printf '<section id="%s" class="%s">\n' "$filename" "$fresh_feed" | ||
200 | case "$filename" in | ||
201 | *\[yt\]) yt=" class=\"yt\"" ;; | ||
202 | *) yt="" ;; | ||
203 | esac | ||
204 | fn="$(echo "$filename" | sed 's@ \[yt\]$@@')" | ||
205 | printf '<header><h2%s><a href="#%s">#</a> %s</h2>\n' "$yt" "$filename" "$fn" | ||
206 | echo "<span class=\"flinks\">" | ||
207 | if [ -f "$SFEED_DATA/urls/$filename" ]; then | ||
208 | feed_url="$(sed -n '1p;1q' "$SFEED_DATA/urls/$filename")" | ||
209 | site_url="$(sed -n '2p;2q' "$SFEED_DATA/urls/$filename")" | ||
210 | [ -n "$site_url" ] && printf '<a class="site-url" href="%s">%s</a>\n//\n' "$site_url" site | ||
211 | [ -n "$feed_url" ] && printf '<a class="feed-url" href="%s">%s</a>\n//\n' "$feed_url" feed | ||
212 | fi | ||
213 | printf '<a class="top" href="#">%s</a>' top | ||
214 | echo "</span></header>" | ||
215 | echo "<table class=\"entries\">" | ||
216 | echo "$entries" | ||
217 | echo "</table>" | ||
218 | echo "</section>" | ||
219 | } | ||
220 | |||
221 | if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then | ||
222 | html "$@" | ||
223 | fi | ||