Skip to content

Commit e03f72c

Browse files
committed
Making the font configurable
1 parent dd603e3 commit e03f72c

File tree

7 files changed

+105
-82
lines changed

7 files changed

+105
-82
lines changed

.github/workflows/daily-feed.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
run: |
7373
cd blogroll
7474
curl -L https://raw.githubusercontent.com/unorsk/blogroll/refs/heads/main/blogroll.txt -o blogroll.txt
75-
./blogroll blogroll.txt
75+
./blogroll blogroll.txt "Good Stuff!" "IBMPlexSans-Regular.woff2"
7676
ls -la
7777
7878
# Ensure we have the required files for GitHub Pages

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Revision history for blogroll
22

3+
## 1.0.9 -- 2025-10-31
4+
5+
* Generating HTML with Lucid2
6+
* Making links a bit more typesafe by usin URI
7+
* Cutting off http/https with URI
8+
39
## 1.0.8 -- 2025-10-14
410

511
* Removing support for opml

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@ A simple RSS reader (written in Haskell btw)
77
The RSS reader is automatically deployed to: **https://unorsk.github.io/blogroll/**
88

99

10+
### Generating the blogroll
11+
```
12+
cabal run blogroll -- blogroll.txt "Test Blogroll" "IBMPlexSans-Regular.woff2"
13+
```
1014

1115
### My todo list. Sort of.
1216

1317
- [ ] Make adding new items to the blogroll easy (I just wanted to add this one: https://anchor.fm/s/10395bc40/podcast/rss)
14-
- [ ] The renderHtml and generateOpmlXml functions - use xml-conduit or lucid instead of concatenating strings (security)
1518
- [ ] Would be nice if it could understand stuff like `<itunes:explicit>`
16-
- [ ] Make it possible to use custom fonts
19+
- [ ] Make github jobs be more fork-friendly (configurable)
20+
- [ ] Setup nix
21+
- [x] Make it possible to use custom fonts
1722
- [ ] ...and styles
1823

1924
## License

app/Main.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ main :: IO ()
1414
main = do
1515
args <- getArgs
1616
case args of
17-
[blogrollPath, blogrollName] -> do
17+
[blogrollPath, blogrollName, pathToFontFile] -> do
1818
urls <- readUrlsFromFile (T.pack blogrollPath)
19-
let blogroll = Blogroll {title = T.pack blogrollName, urls = urls}
19+
let blogroll = Blogroll {title = T.pack blogrollName, pathToFontFile = pathToFontFile, urls = urls}
2020
putStrLn $ "Found " ++ show (length urls) ++ " feeds"
2121
-- TODO split this one into fetching and rendering
2222
renderAll blogroll
2323
_ -> do
2424
putStrLn "Usage:"
25-
putStrLn " blogroll <blogroll-file> <blogroll-title>"
25+
putStrLn " blogroll <blogroll-file> <blogroll-title> <font-path>"

blogroll.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cabal-version: 3.14
22
name: blogroll
33

4-
version: 1.0.8
4+
version: 1.0.9
55
license: MIT
66
license-file: LICENSE
77
author: unorsk

src/Blogroll/Html.hs

Lines changed: 86 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ loadFontAsBase64 fontPath = do
5454
let base64Text = TE.decodeUtf8 $ Base64.encode fontBytes
5555
return base64Text
5656
case result of
57-
Left (_ :: SomeException) -> return Nothing
57+
Left (_ :: SomeException) -> return Nothing -- TODO handle this situation properly
5858
Right base64 -> return $ Just base64
5959

6060
-- TODO split this one into fetching and rendering
6161
renderAll :: Blogroll -> IO ()
6262
renderAll blogroll = do
6363
let urls = blogroll.urls
64-
fontBase64 <- loadFontAsBase64 "IBMPlexSans-Regular.woff2"
64+
fontBase64 <- loadFontAsBase64 blogroll.pathToFontFile
6565
faviconMap <- fetchAllFavicons urls
6666
let faviconCss = generateFaviconCss faviconMap
6767
feeds <- mapConcurrently fetchFeed urls
@@ -87,87 +87,98 @@ renderAll blogroll = do
8787

8888
renderHtml :: [FeedEntry] -> Text -> Text -> Maybe Text -> Text
8989
renderHtml entries pageTitle faviconCss maybeFontBase64 =
90-
TL.toStrict $ renderText $ doctype_ <> html_ (do
91-
head_ (do
92-
meta_ [name_ "viewport", content_ "width=device-width, initial-scale=1.0"]
93-
title_ "RSS Reader"
94-
style_ [] (toHtmlRaw $ generateStyles faviconCss maybeFontBase64))
95-
body_ (do
96-
h1_ (toHtml pageTitle)
97-
ul_ (do
98-
mapM_ renderEntry entries
99-
li_ (a_ [href_ "all.html"] "See all"))))
90+
let css = generateStyles maybeFontBase64 <> faviconCss
91+
in TL.toStrict $
92+
renderText $
93+
doctype_
94+
<> html_
95+
( do
96+
head_
97+
( do
98+
meta_ [name_ "viewport", content_ "width=device-width, initial-scale=1.0"]
99+
title_ "RSS Reader"
100+
style_ [] (toHtmlRaw css)
101+
)
102+
body_
103+
( do
104+
h1_ (toHtml pageTitle)
105+
ul_
106+
( do
107+
mapM_ renderEntry entries
108+
li_ (a_ [href_ "all.html"] "See all")
109+
)
110+
)
111+
)
100112
where
101-
generateStyles :: Text -> Maybe Text -> Text
102-
generateStyles css maybeFontB64 =
113+
generateStyles :: Maybe Text -> Text
114+
generateStyles maybeFontB64 =
103115
let fontFace = case maybeFontB64 of
104116
Just fontBase64 ->
105117
"""@font-face {
106-
font-family: 'IBM Plex Sans';
107-
src: url(data:font/woff2;base64,"""
118+
font-family: 'A Very Nice Font';
119+
src: url(data:font/woff2;base64,"""
108120
<> fontBase64
109121
<> """) format('woff2');
110-
font-weight: 400;
111-
}"""
112-
Nothing ->
113-
"""@font-face {
114-
font-family: 'IBM Plex Sans';
115-
src: url('IBMPlexSans-Regular.woff2') format('woff2');
116-
font-weight: 400;
117-
}"""
122+
font-weight: 400;
123+
}"""
124+
Nothing -> "" -- we don't have font, so no style here
118125
in fontFace
119126
<> """
120-
body {
121-
font-family: 'IBM Plex Sans', -apple-system, sans-serif;
122-
max-width: 800px;
123-
margin: 0 auto;
124-
color: #333;
125-
display: flex;
126-
flex-flow: column;
127-
align-content: center;
128-
}
129-
h1 {
130-
color: #2c3e50;
131-
border-bottom: 2px solid #3498db;
132-
padding-bottom: 10px;
133-
}
134-
ul {
135-
list-style: none;
136-
padding: 0;
137-
margin-top: 0
138-
}
139-
li {
140-
padding-left: 8px;
141-
padding-bottom: 8px;
142-
}
143-
a {
144-
color: #2980b9;
145-
text-decoration: none;
146-
font-weight: 500;
147-
}
148-
a:hover {
149-
text-decoration: underline;
150-
}
151-
.date {
152-
color: #7f8c8d;
153-
font-size: 0.6em;
154-
}
155-
.source {
156-
color: #95a5a6;
157-
font-size: 0.8em;
158-
padding-left: 0.5em;
159-
}
160-
"""
161-
<> css
127+
body {
128+
font-family: 'A Very Nice Font', Helvetica, Arial, system-ui, -apple-system, sans-serif;
129+
font-weigth: 400;
130+
max-width: 800px;
131+
margin: 0 auto;
132+
color: #333;
133+
display: flex;
134+
flex-flow: column;
135+
align-content: center;
136+
}
137+
h1 {
138+
color: #2c3e50;
139+
border-bottom: 2px solid #3498db;
140+
padding-bottom: 10px;
141+
}
142+
ul {
143+
list-style: none;
144+
padding: 0;
145+
margin-top: 0
146+
}
147+
li {
148+
padding-left: 8px;
149+
padding-bottom: 8px;
150+
}
151+
a {
152+
color: #2980b9;
153+
text-decoration: none;
154+
font-weight: 500;
155+
}
156+
a:hover {
157+
text-decoration: underline;
158+
}
159+
.date {
160+
color: #7f8c8d;
161+
font-size: 0.6em;
162+
}
163+
.source {
164+
color: #95a5a6;
165+
font-size: 0.8em;
166+
padding-left: 0.5em;
167+
}
168+
"""
162169

163170
renderEntry :: FeedEntry -> Html ()
164171
renderEntry entry =
165-
li_ (do
166-
div_ (do
167-
a_
168-
[ href_ (T.pack $ show $ entryLink entry),
169-
class_ (generateDomainCssClass (extractDomain entry.entrySiteUrl))
170-
]
171-
(toHtml $ entryTitle entry)
172-
span_ [class_ "source"] (toHtml $ "(" <> extractDomain entry.entrySiteUrl <> ")"))
173-
div_ [class_ "date"] (toHtml $ T.pack $ formatTime defaultTimeLocale "%Y-%m-%d" entry.entryDate))
172+
li_
173+
( do
174+
div_
175+
( do
176+
a_
177+
[ href_ (T.pack $ show $ entryLink entry),
178+
class_ (generateDomainCssClass (extractDomain entry.entrySiteUrl))
179+
]
180+
(toHtml $ entryTitle entry)
181+
span_ [class_ "source"] (toHtml $ "(" <> extractDomain entry.entrySiteUrl <> ")")
182+
)
183+
div_ [class_ "date"] (toHtml $ T.pack $ formatTime defaultTimeLocale "%Y-%m-%d" entry.entryDate)
184+
)

src/Blogroll/Type.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Network.URI (URI)
88

99
data Blogroll = Blogroll
1010
{ title :: Text,
11+
pathToFontFile :: FilePath,
1112
urls :: [URI]
1213
}
1314
deriving (Show, Eq)

0 commit comments

Comments
 (0)