~alcinnz/Hearth

9e6825a2aaa3509e098aab05258c4b6f49736e5e — Adrian Cochrane 11 months ago 3871d4b
Basic favourites support, commit missing files.
A history.tsv => history.tsv +116 -0
@@ 0,0 1,116 @@
# From https://searchmysite.net/search/new/ As of 17 Jan 2024
https://www.ethanhein.com/wp/2024/as-it-turns-out-i-will-be-teaching-aural-skills-at-nyu-this-semester/		As it turns out, I will be teaching aural skills at NYU this semester | The Ethan Hein Blog	2024-01-15T21:46:07Z
https://rasterweb.net/raster/2024/01/15/using-the-shaper-trace/	Amazon appears to be selling OpenAI apologies disguised as chairs - The Braindump Blog	2024-01-15T10:19:18Z
https://box464.com/categories/	Categories | Jeff Sikes	2024-01-13T18:18:55Z
https://hacdias.com/articles/	Articles - Henrique Dias	2024-01-13T10:37:33Z
https://zhangluyao.com/blog/ganesha/	Luyao Zhang	2024-01-12T16:57:20Z
https://thedailywtf.com/articles/patience	Patience - The Daily WTF	2024-01-12T06:30:00Z
https://femtejuli.se/2024/01/11/chatcontrol-i-ministerradet-i-mars-vad-sager-eu-namnden/	Chatcontrol i ministerrådet i mars – vad säger EU-nämnden?	2024-01-11T13:38:40Z
https://v5.chriskrycho.com/journal/one-problem-with-my-kobo-aura-one/	One Problem With My Kobo Aura ONE — Sympolymathesy, by Chris Krycho	2024-01-11T08:30:00Z
https://www.postgresql.org/about/news/pgconfdev-2024-cfp-closing-registration-open-2787/	PostgreSQL: PGConf.dev 2024 - CFP Closing & Registration Open!	2024-01-11T00:00:00Z
https://daverupert.com/2024/01/accessible-fart-machines/	Accessible Fart Machines | daverupert.com	2024-01-10T17:55:00Z
https://retrocomputingforum.com/t/dream-computer-6800/3859	Dream computer - 6800 - Hardware - Retro Computing	2024-01-09T23:07:02Z

https://anderegg.ca/2024/01/09/oohdirectory-adds-blog-stats	ooh.directory Adds Blog Stats | anderegg.ca	2024-01-09T21:03:04Z
https://www.autisticasfxxk.com/blog/low-spoons/	Things I do differently when I’m low on spoons | Autistic As Fxxk	2024-01-09T20:31:07Z
https://danielprindii.com/2024/01/09/default-apps-of-2023/	My default apps of 2023	2024-01-09T16:05:31Z
https://tante.cc/2024/01/09/openais-copyright-defence/	OpenAI's copyright defence	2024-01-09T13:39:36Z
https://shkspr.mobi/blog/2024/01/book-review-you-look-like-a-thing-and-i-love-you-by-janelle-shane/	Book Review: You Look Like a Thing and I Love You by Janelle Shane – Terence Eden’s Blog	2024-01-09T12:34:18Z
https://dabblingwithdata.amedcalf.com/2024/01/09/the-ongoing-battle-between-human-creators-and-ai-trainers/	The ongoing battle between human creators and AI trainers – Dabbling with Data	2024-01-09T11:16:26Z
https://joshua.hu/on-google-account-persistence-exploit-malware-session-api-token-theft	On the Google Account Persistence Exploit | Joshua.Hu | Joshua Rogers' Scribbles	2024-01-09T00:00:00Z
https://arslan.io/2024/01/08/tesla-model-y-my-6-months-impressions/	Tesla Model Y: My 6 months impressions	2024-01-08T08:45:28Z
https://ben.balter.com/2024/01/08/dissenting-voices/	The “I don’t like what they’re saying, so they shouldn’t be allowed to say it” approach to crisis management | Ben Balter	2024-01-08T00:00:00Z
https://blog.zmh.org/2024/01/07/big-sky-montana.html	Zachary Hamed	2024-01-07T18:22:06Z
https://bascht.com/posts/2024/01/07/d%C3%B6ner-orient-express-plauen/	Döner Orient Express - Plauen	2024-01-07T17:48:39Z
https://slawek.art/fotografia-analogowa-2024/	Fotografia Analogowa 2024 – Sławomir Lewan	2024-01-07T14:20:58Z

https://winnielim.org/journal/2024-one-pull-up/	Winnie Lim » 2024: one pull up	2024-01-07T02:48:16Z
https://staysaasy.com/managementya/2024/01/07/performance-reviews.html	Performance Reviews Matter | Stay SaaSy	2024-01-07T00:59:22Z
https://rnikhil.com/2024/01/07/why-i-write.html	Why do I write? | Nikhil. R	2024-01-07T00:00:00Z
https://blog.matchu.dev/tech/2024/01/06/remove-bg3-spells-mod.html	Safely removing BG3 mods from an ongoing save | Matchu Says Words	2024-01-06T20:30:00Z
https://merlinjstar.com/2024/01/06/jan-6th-3-years-later/	Jan 6th, 3 years later – Merlin Star's Website	2024-01-06T17:00:00Z
https://pulpflakes.com/blog/2024/01/negatives-dragons-blood-and-acid-how-line-drawings-were-reproduced/	Negatives, Dragon’s Blood and Acid. How line drawings were reproduced - Pulpflakes	2024-01-06T13:00:00Z
https://michael-hudson.com/2024/01/comparing-feudal-to-financial/	Comparing Feudal to Financial | Michael Hudson	2024-01-06T12:32:57Z
https://lordmatt.co.uk/technology/the-internet/blogs-and-blogging/focus-on-others/focus-on-others-marcs-marvelous-missives/	https://lordmatt.co.uk/technology/the-internet/blogs-and-blogging/focus-on-others/focus-on-others-marcs-marvelous-missives/	2024-01-06T11:43:26Z
https://neilmadden.blog/2024/01/06/newsletter/	Newsletter – Neil Madden	2024-01-06T10:18:54Z
https://john.philpin.com/2024/01/06/the-first-collection.html	6/366 | 🗂️ The First Collection. // 💬 John Philpin	2024-01-06T08:05:49Z
https://rednafi.com/go/rate_limiting_via_nginx/	Rate limiting via Nginx | Redowan's Reflections	2024-01-06T00:00:00Z
https://birtles.blog/2024/01/06/weird-things-engineers-believe-about-development/	Weird things engineers believe about Web development - Brian Birtles’ Blog	2024-01-06T00:00:00Z

https://indieseek.xyz/2024/01/05/the-state-of-the-independent-web-2022-updated-2024/	The State of the Independent Web 2022: Updated 2024	2024-01-05T19:42:00Z
https://kentnerburn.com/my-take-on-killers-of-the-flower-moon/	My Take on Killers of the Flower Moon | Kent Nerburn	2024-01-05T17:40:10Z
https://riteshbabu.net/2024/01/05/comics-i-loved-in-2023/	Comics I Loved In 2023 – Ritesh Babu	2024-01-05T12:38:35Z
https://matduggan.com/fixing-macs-door-to-door/	Fixing Macs Door to Door	2024-01-05T11:57:37Z
https://glasgowgallivanter.com/2024/01/05/selkirk-and-the-haining/	Selkirk and The Haining – The Glasgow Gallivanter	2024-01-05T09:30:26Z
https://www.jonaharagon.com/posts/age-verification-is-incompatible-with-the-internet/	Age Verification is Incompatible with the Internet - Jonah Aragon	2024-01-04T19:05:20Z
https://galacticjourney.org/january-4-1969-not-following-through-february-1969-if/	[January 4, 1969] Not following through (February 1969 IF) - Galactic Journey	2024-01-04T17:00:11Z
http://www.georgettetan.com/2024/01/the-december-2023-review/	The December 2023 Review – Georgette Tan	2024-01-04T14:54:00Z
https://jlelse.blog/micro/2024/01/2024-01-04-gduob	I just noticed that I can c… - Jan-Lukas Else	2024-01-04T08:33:00Z
https://cloudappreciationsociety.org/thursday-4th-january-2024/	Thursday 4th January 2024 - Cloud Appreciation Society	2024-01-04T00:00:00Z
https://www.amitgawande.com/2024/01/03/the-last-few.html	Amit Gawande	2024-01-03T21:42:59Z
https://achor.net/diary/2163	회사 신년회 | achor Empire	2024-01-03T21:26:37Z

https://mattmazur.com/2024/01/03/is-the-chatgpt-api-refusing-to-summarize-academic-papers-not-so-fast/	Is the ChatGPT API Refusing to Summarize Academic Papers? Not so fast. | Matt Mazur	2024-01-03T17:09:57Z
https://www.chrisdeluca.me/2024/01/03/my-coworker-pauline.html	Chris DeLuca	2024-01-03T10:42:34Z
https://thisbuildscharacter.com/2024/01/02/re-so-you-wanna-de-bog-yourself/	Re: So you wanna de-bog yourself – This Builds Character	2024-01-03T01:53:50Z
https://kivikakk.ee/2024/01/03/lottia-notes/	lottia notes · kivikakk.ee	2024-01-03T00:00:00Z
https://luizdepra.dev/posts/retrospectiva-2023/	Retrospectiva 2023 · luizdepra	2024-01-03T00:00:00Z
https://www.jimwillis.org/2024/01/02/read-6-thoughts-on-commentary-cory-doctorow-social-quitting/	Read: 6 thoughts on “Commentary: Cory Doctorow: Social Quitting” - Jim Willis	2024-01-02T18:54:44Z
https://bernsteinbear.com/blog/lisp/	Lisp implementations | Max Bernstein	2024-01-02T16:02:53Z
https://netbros.com/1704225226/	Notes  - 1704225226	2024-01-02T14:53:46Z
https://boricj.net/atari-jaguar-sdk/2024/01/02/part-5.html	Porting the Atari Jaguar SDK part 5: I have a feeling we’re not on Linux anymore | boricj’s entropy-increasing blog	2024-01-02T13:00:00Z
https://cubicgarden.com/2024/01/02/public-service-internet-monthly-newsletter-jan-2024/	Public Service Internet monthly newsletter (Jan 2024) – Cubicgarden.com	2024-01-02T10:45:34Z
https://seths.blog/2024/01/pw1-two-hats-for-productivity/	PW1: Two hats for productivity | Seth's Blog	2024-01-02T09:54:00Z
https://www.spencerharston.com/posts/books-of-2024/	Books of 2024	2024-01-02T05:25:00Z

https://macarthur.me/posts/increase-plausible-rate-limits	Raise the API Rate Limit for a Self-Hosted Instance of Plausible | Alex MacArthur	2024-01-02T00:12:56Z
https://johnnyreilly.com/schemar-github-action-to-validate-structured-data	Schemar: a GitHub Action to validate structured data | johnnyreilly	2024-01-02T00:00:00Z
https://www.willem.dev/code-snippets/parse-unix-timestamp/	How to Parse Unix Timestamps in Go/Golang	2024-01-02T00:00:00Z
https://wilwheaton.net/2024/01/my-biggest-rpg-surprise-of-2023/	my biggest rpg surprise of 2023 – WIL WHEATON dot NET	2024-01-01T23:37:34Z
https://zhengdongwang.com/2024/01/01/2023-letter.html	2023 letter | Zhengdong	2024-01-01T21:44:59Z
https://paulrobichaux.com/2024/01/01/2023-year-in-review-books/	2023 year in review: books | Paul's Down-Home Page	2024-01-01T17:22:56Z
https://blog.davep.org/2024/01/01/oshit.html	blog.davep.org – Orange Site Hit	2024-01-01T10:17:00Z
https://lethain.com/predictability/	Predictability. | Irrational Exuberance	2024-01-01T05:00:00Z
https://michael-lewis.com/posts/today-i-learned-2023/	Today I Learned 2023 · Michael I Lewis	2024-01-01T00:00:00Z
https://nolanlawson.com/2023/12/31/2023-book-review/	2023 book review | Read the Tea Leaves	2023-12-31T20:28:04Z
https://neglectedbooks.com/?p=10114	The Mechanical Angel, by Donald Friede (1948) - The Neglected Books Page	2023-12-31T12:47:24Z
https://detgodasamhallet.com/2023/12/31/bitte-assarmo-2023-blev-aret-da-antisemiterna-kralade-fram-ur-alla-vrar/	BITTE ASSARMO: 2023 blev året då antisemiterna krälade fram ur alla vrår – DET GODA SAMHÄLLET	2023-12-31T04:15:00Z

https://chambers.io/2023/12/31/2023-year-in-review.html	2023 Year In Review - chambers.io	2023-12-31T00:00:00Z
https://swaits.com/books-read-this-year/	Books I read in 2023... for fun! · swaits.com	2023-12-31T00:00:00Z
https://forum.tfos.co/t/in-progress-changes-to-config-and-tasks/114	In-progress changes to config and tasks - Biff - Jacob's Forum	2023-12-30T23:15:16Z
https://tasteasianfood.com/chinese-chicken-dumpling-recipe/	Chinese chicken dumpling recipe- 鸡肉饺子	2023-12-30T16:30:23Z
https://juliette.page/2023/12/30/a-journey-through-ecosystems/	A Journey Through Ecosystems – Juliette’s Café	2023-12-30T14:27:58Z
https://www.fristad.eu/2023/12/tack-for-i-ar-3/?utm_source=rss&utm_medium=rss&utm_campaign=tack-for-i-ar-3	Tack för i år! - Fristad	2023-12-30T11:32:22Z
https://www.themarginalian.org/2023/12/30/john-odonohue-blessings-beginnings/	A Spell Against Stagnation: John O’Donohue on Beginnings – The Marginalian	2023-12-30T11:30:55Z
https://www.youtube.com/watch?v=Ga6x8hJqSsQ	Science & Technology Q&A for Kids (and others) [Part 138] - YouTube	2023-12-30T02:24:54Z
https://fatsackfails.com/posts/	Posts | Fatsack Fails	2023-12-29T22:06:31Z
https://robertvanbregt.nl/2023/12/29/watched-band-of-brothers-2001/	📺 Watched: Band of Brothers (2001) ⭐️⭐️⭐️⭐️⭐️ · Robert van Bregt	2023-12-29T21:19:00Z
https://www.johndcook.com/blog/2023/12/29/randomize-then-humanize/	Randomize, then humanize	2023-12-29T15:22:49Z
https://thejeshgn.com/2023/12/29/weekly-notes-52-2023/	Weekly Notes 52/2023 | Thejesh GN	2023-12-29T13:44:41Z

https://blog.lawrencejones.dev/2023/	Looking back at 2023 | Lawrence Jones	2023-12-29T12:00:00Z
https://avancemang.com/gomda-och-glomda-politiska-profilfragor/	Gömda och glömda politiska profilfrågor – Avancemang	2023-12-29T11:02:55Z
https://davidgomes.com/my-books-in-review-from-2023/	My Books in Review From 2023	2023-12-29T08:06:23Z
https://spacesettlementprogress.com/greater-earth-ge%e2%8a%95-lunar-power-station/	Greater Earth (GE⊕) Lunar Power Station – Space Settlement Progress	2023-12-28T21:33:43Z
https://justinsimoni.com/2023/12/28/pikes-peak-winter-solstice-bus-stop-backslap/	Pikes Peak Winter Solstice Bus Stop Backslap! - Justin Simoni as: THE LONG RANGER	2023-12-28T17:57:21Z
https://blog.alexellis.io/booting-the-raspberry-pi-5-from-nvme/	Booting the Raspberry Pi 5 from NVMe	2023-12-28T17:55:43Z
https://www.michaelgeist.ca/2023/12/the-year-in-review-top-ten-michael-geist-substacks/	The Year in Review: Top Ten Michael Geist Substacks - Michael Geist	2023-12-28T12:50:28Z
https://www.hailleygriffis.com/2023-books/	10 books I loved in 2023 and 6 I plan on reading in 2024 - Hailley Griffis @hailleymari	2023-12-28T12:44:46Z
https://petewarden.com/2023/12/28/why-i-love-my-chevy-bolt-ev/	Why I Love my Chevy Bolt EV « Pete Warden's blog	2023-12-28T01:38:47Z
https://andreasimonecosta.dev/posts/what-the-heck-is-a-homomorphic-mapped-type/	What the heck is a homomorphic mapped type? · andrea simone costa	2023-12-28T00:00:00Z
https://www.garysieling.com/blog/pa-senate-committees-2023-csv-download/	PA Senate Committees 2023 CSV Download - Gary Sieling	2023-12-27T18:24:12Z
https://journal.paoloamoroso.com/my-common-lisp-setup-on-linux	My Common Lisp setup on Linux — Paolo Amoroso's Journal	2023-12-27T13:30:34Z

https://zwischenzugs.com/2023/12/27/what-i-learned-using-private-llms-to-write-an-undergraduate-history-essay/	What I Learned Using Private LLMs to Write an Undergraduate History Essay – zwischenzugs	2023-12-27T11:03:54Z
https://www.frihetsportalen.se/2023/12/hur-mycket-ljuger-myndigheterna/	Hur mycket ljuger myndigheterna? | Frihetsportalen	2023-12-27T04:00:29Z
https://solar.lowtechmagazine.com/2023/12/how-to-build-a-small-solar-power-system/	How to Build a Small Solar Power System | LOW←TECH MAGAZINE	2023-12-27T00:00:00Z
https://pdbowman.studio/quareidfaciam/turning-point-usa/	Turning point: U.S.A. – paul bowman studio	2023-12-26T16:30:17Z
https://andrewpwheeler.com/2023/12/26/year-in-review-2023-how-did-crime-de-coder-do/	Year in Review 2023: How did CRIME De-Coder do? | Andrew Wheeler	2023-12-26T13:18:07Z
https://www.einsstark.tech/write-for-us/	Write for us – Tech Blog	2023-12-26T03:08:46Z
https://roman.pt/posts/handling-unset-values-in-fastapi-with-pydantic/	Handling Unset Values in Fastapi With Pydantic - Roman Imankulov	2023-12-26T00:00:00Z
https://danielbmarkham.com/a-christmas-story/	A Christmas Story	2023-12-25T17:22:59Z
https://musings.tychi.me/a-rust-equivalent-for-front-end	A Rust Equivalent For Front End — Musings	2023-12-25T16:08:59Z
https://dariusforoux.com/investing-principles/	4 Timeless Investing Principles That Never Change - Darius Foroux	2023-12-25T13:55:00Z
https://chriswiegman.com/2023/12/merry-christmas-2/	Merry Christmas - Chris Wiegman	2023-12-25T13:32:36Z
https://connortumbleson.com/2023/12/25/too-much-car-safety/	Too much Car Safety	2023-12-25T03:30:23Z

M i18n/en.json => i18n/en.json +2 -1
@@ 8,5 8,6 @@
    "Read Later": "Read Later",
    "Favourite": "Favourite",
    "Remove": "Remove",
    "Description": "Description"
    "Description": "Description",
    "Favourites": "Favourites"
}

M src-lib/Hearth.hs => src-lib/Hearth.hs +16 -3
@@ 1,10 1,10 @@
{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings, TemplateHaskell, FlexibleContexts #-}
module Hearth (renderPage, handleForm, markAsRead, utf8, Link) where

import Text.Ginger.Parse (parseGingerFile, SourcePos)
import Text.Ginger.Run (runGinger, makeContextHtml, Run)
import Text.Ginger.Html (htmlSource, Html)
import Text.Ginger.GVal as V (toGVal, orderedDict, (~>), GVal)
import Text.Ginger.GVal as V (toGVal, orderedDict, (~>), GVal(..), fromFunction)
import Control.Monad.Writer.Lazy (Writer)

import Data.ByteString (ByteString)


@@ 22,8 22,9 @@ import Data.Maybe (fromMaybe)
import Debug.Trace (traceShow) -- For error reporting!

import Hearth.TopSites
import Network.URI (uriToString)
import Network.URI (uriToString, parseAbsoluteURI)
import Data.Aeson (Value(..), Object, toJSON)
import Data.List (sortOn)

renderPage :: ByteString -> [(ByteString, Maybe ByteString)] -> [Txt.Text] ->
        [Link] -> Value -> Maybe Txt.Text


@@ 39,12 40,22 @@ renderPage path query langs hist db = case parseGingerFile resolveSource $ utf8 
    ctxt "_" = toGVal $ translations langs
    ctxt "tops" = list' [hist2gval entry | entry <- take 20 $ topsites hist]
    ctxt "hist" = list' $ map hist2gval $ siteHistory hist
    ctxt "sortByVisits" = fromFunction sortByVisits
    ctxt _ = toGVal ()
    hist2gval entry@(label, href, time) = orderedDict [
            "label"~>label,
            "href"~>uriToString id href "",
            "time"~>time,
            "count"~>countVisits entry hist]
    sortByVisits [(_, self)]
        | Just self' <- asList self = return $ toGVal $ reverse $ sortOn inner self'
      where
        inner entry
            | Just get <- asLookup entry, Just page <- get "href",
                    Just href <- parseAbsoluteURI $ Txt.unpack $ asText page =
                countVisitsPage href hist
            | otherwise = 0
    sortByVisits _ = return $ toGVal ()

resolveSource :: FilePath -> Maybe (Maybe [Char])
resolveSource path


@@ 97,6 108,8 @@ handleForm "/" query db = return (fromMaybe "/" $ lookup "url" query, db)
handleForm "/index.html" query db = return (fromMaybe "/" $ lookup "url" query, db)
handleForm "/bookmarks/read-later" query (Object db) =
    return ("/", Object $ insertConcat "readingList" (query2json query) db)
handleForm "/bookmarks/new.html" query (Object db) =
    return ("/", Object $ insertConcat "favs" (query2json query) db)
handleForm path _ db = return (path, db)

query2json :: [(ByteString, ByteString)] -> Value

M src-lib/Hearth/TopSites.hs => src-lib/Hearth/TopSites.hs +4 -1
@@ 1,4 1,4 @@
module Hearth.TopSites (topsites, Link, siteHistory, countVisits) where
module Hearth.TopSites (topsites, Link, siteHistory, countVisits, countVisitsPage) where

import qualified Data.Set as S
import Data.Containers.ListUtils (nubOrdOn)


@@ 40,3 40,6 @@ siteHistory = nubOrdOn link . map inner
countVisits :: Link -> [Link] -> Int
countVisits (_, page, _) = length . filter inner
    where inner (_, page', _) = uriAuthority page == uriAuthority page'

countVisitsPage :: URI -> [Link] -> Int
countVisitsPage page = length . filter (== page) . map link

A tpl/bookmarks/index.html => tpl/bookmarks/index.html +14 -0
@@ 0,0 1,14 @@
<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title>⭐️{{ _["Favourites"] }}</title>
</head>
<body>
  <h1>⭐️{{ _["Favourites"] }}</h1>
  <dl>{% for fav in D.favs|sortByVisits %}
    <dt><a href="{{ fav.href }}" title="{{ fav.title }}">{{ fav.label }}</a></dt>
    <dd>{{ fav.title }}</dd>
  {% endfor %}</dl>
</body>
</html>

A tpl/bookmarks/new.html => tpl/bookmarks/new.html +21 -0
@@ 0,0 1,21 @@
<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title>➕️{{ _["Add Bookmark"] }}</title>
</head>
<body><form method="POST">
  <dl>
    <dt><label for="input-name">{{ _["Name"] }}</label></dt>
    <dd><input type="text" name="label" value="{{ Q.label }}" required
            id="input-name" /></dd>
    <dt><label for="input-url">{{ _["Web Address"] }}</label></dt>
    <dd><input type="url" name="href" value="{{ Q.href }}" required id="input-url" /></dd>
    <dt><label for="input-title">{{ _["Description"] }}</label></dt>
    <dd><textarea id="input-title" name="title"></textarea></dd>
  </dl>
  <p><button type="submit" formaction="read-later">📚️{{ _["Read Later"] }}</button>
    <!-- TODO: Implement these! -->
    <button type="submit">⭐️{{ _["Favourite"] }}</button>
</form></body>
</html>

M tpl/index.html => tpl/index.html +6 -0
@@ 21,6 21,12 @@
        <li><a href="/read/{{ link.href }}" title="{{ link.title }}">{{ link.label }}</a></li>
      {% endfor %}</ul>
    </section>{% endif %}
    {% if D.favs %}<section>
      <h1><a href="bookmarks/">⭐️{{ _["Favourites"] }}</a></h1>
      <ul>{% for link in D.favs|sortByVisits|slice(0, 20) %}
        <li><a href="{{ link.href }}" title="{{ link.title }}">{{ link.label }}</a></li>
      {% endfor %}</ul>
    </section>{% endif %}
  </main>
</body>
</html>

A tpl/toread.html => tpl/toread.html +13 -0
@@ 0,0 1,13 @@
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>📚️{{ _["Reading List"] }}</title>
</head>
<body>
  <h1>📚️{{ _["Reading List"] }}</h1>
  <ul>{% for link in D.readingList %}
    <li><a href="/read/{{ link.href }}" title="{{ link.title }}">{{ link.label }}</a></li>
  {% endfor %}</ul>
</body>
</html>