diff options
author | Thomas Koch <thomas@koch.ro> | 2025-01-12T18·12+0200 |
---|---|---|
committer | Thomas Koch <thomas@koch.ro> | 2025-01-12T18·13+0200 |
commit | 150314936c46fc438aebd74106f6f2a6a0f30b30 (patch) | |
tree | 10919149060028387d9eaa86a804279194f557f7 | |
parent | 4a9f5201d1360d5a2369224317b26c288b438236 (diff) |
get authors also from feed data + some css
-rw-r--r-- | web/planet-mars/planet.css | 67 | ||||
-rw-r--r-- | web/planet-mars/src/feed_store.rs | 27 | ||||
-rw-r--r-- | web/planet-mars/src/main.rs | 2 | ||||
-rw-r--r-- | web/planet-mars/src/template_engine.rs | 61 | ||||
-rw-r--r-- | web/planet-mars/templates/index.html | 20 |
5 files changed, 139 insertions, 38 deletions
diff --git a/web/planet-mars/planet.css b/web/planet-mars/planet.css index aca682fd3d12..31c5ca5fa5e8 100644 --- a/web/planet-mars/planet.css +++ b/web/planet-mars/planet.css @@ -1,5 +1,5 @@ p, h1, h2, h3, h4, h5, h6, small { - max-width: 48em; + max-width: 48em; } h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { @@ -9,34 +9,71 @@ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { ul, ol { /* account for the 1em -webkit-margin-start for the list icon */ - max-width: 45em; + max-width: 45em; } ul,ol,dl, p { - line-height: 1.4; + margin-top: 0.3em; + margin-bottom: 0.3em; + line-height: 1.2; } -body { - margin-top: 1em; - margin-bottom: 1em; +ul, ol { + padding-inline-start: 1.5em; } -#maincontainer { - display: flex; +#bodydiv { + margin: auto; max-width: 80em; } -#maincontainer main { - max-width: 50em; +#maincontainer aside img { + max-width: 10em; +} + +#maincontainer main blockquote { + margin-left: 0; + margin-right: 10px; + box-shadow: 10px 0px 0px 0px #C4C4C4; +} + +blockquote, pre code { + padding: 0.5ex 0; + display: block; + background-color: #EEE; } #maincontainer main * { + max-width: 100%; +} + +#maincontainer main pre { + overflow-x: auto; +} + +.entry_meta { + margin-bottom: 1em; +} + +@media only screen and (min-width: 1024px) { +#maincontainer { + display: flex; +} + +#maincontainer main { max-width: 50em; + flex: 5; } #maincontainer aside { margin-left: 5em; - max-width: 25em; + max-width: 15em; + flex: 1; +} + +#maincontainer aside img { + margin: auto; + display: block; } article > h2.entry_header { @@ -44,7 +81,6 @@ article > h2.entry_header { } .entry_meta { - border: 1px thin; padding: 3px 0; background-color: LightBlue; } @@ -53,7 +89,8 @@ hr.entry_sep { border: none; } hr.entry_sep::before { - content: '* * *'; - display: block; - text-align: center; + content: '* * *'; + display: block; + text-align: center; +} } diff --git a/web/planet-mars/src/feed_store.rs b/web/planet-mars/src/feed_store.rs index 621b06d86b25..ac0572307bf0 100644 --- a/web/planet-mars/src/feed_store.rs +++ b/web/planet-mars/src/feed_store.rs @@ -4,6 +4,7 @@ use feed_rs::model::Entry; use feed_rs::model::Feed; use ron::ser::{to_string_pretty, PrettyConfig}; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use std::convert::AsRef; use std::fs; use std::io::BufReader; @@ -13,9 +14,6 @@ use ureq::http::Response; use ureq::Body; use url::Url; -/// How many feed entries should be included in the planet -const ENTRIES_LEN: usize = 10; - #[derive(Deserialize, Serialize, Default)] pub struct FetchData { pub etag: String, @@ -135,8 +133,12 @@ impl FeedStore { Ok(Some(parser.parse(BufReader::new(file))?)) } - pub fn collect(&self, feed_configs: &Vec<super::FeedConfig>) -> (Vec<Feed>, Vec<Entry>) { - let mut feeds = Vec::new(); + pub fn collect( + &self, + feed_configs: &Vec<super::FeedConfig>, + max_entries: usize, + ) -> (HashMap<String, Feed>, Vec<Entry>) { + let mut feeds = HashMap::new(); let mut entries = Vec::new(); for feed_config in feed_configs { @@ -154,21 +156,24 @@ impl FeedStore { Ok(None) => continue, Ok(Some(f)) => f, }; + for entry in &mut feed.entries { + entry.source = Some(feed_config.url.clone()); + } entries.append(&mut std::mem::take(&mut feed.entries)); - feeds.push(feed); + feeds.insert(feed_config.url.clone(), feed); // optimization to reduce memory usage - if entries.len() > 4 * ENTRIES_LEN { - entries = trim_entries(entries); + if entries.len() > 4 * max_entries { + entries = trim_entries(entries, max_entries); } } - (feeds, trim_entries(entries)) + (feeds, trim_entries(entries, max_entries)) } } -fn trim_entries(mut entries: Vec<Entry>) -> Vec<Entry> { +fn trim_entries(mut entries: Vec<Entry>, max_entries: usize) -> Vec<Entry> { entries.sort_by_key(|e| std::cmp::Reverse(e.updated.or(e.published).unwrap_or_default())); - entries.truncate(ENTRIES_LEN); + entries.truncate(max_entries); entries } diff --git a/web/planet-mars/src/main.rs b/web/planet-mars/src/main.rs index ccbb0647f659..42ce8c35f2cb 100644 --- a/web/planet-mars/src/main.rs +++ b/web/planet-mars/src/main.rs @@ -66,6 +66,8 @@ struct Config { out_dir: String, /// templates folder templates_dir: String, + /// How many feed entries should be included in the planet + max_entries: usize, } pub fn to_checked_pathbuf(dir: &str) -> PathBuf { diff --git a/web/planet-mars/src/template_engine.rs b/web/planet-mars/src/template_engine.rs index 827ac23ffdbc..aecead9913c4 100644 --- a/web/planet-mars/src/template_engine.rs +++ b/web/planet-mars/src/template_engine.rs @@ -2,21 +2,25 @@ use crate::feed_store::FeedStore; use crate::to_checked_pathbuf; use crate::Config; use anyhow::Result; +use feed_rs::model::Feed; +use std::collections::HashMap; use std::fs::File; -use tera::Tera; +use tera::{from_value, Tera}; pub fn build(config: &Config, feed_store: &FeedStore) -> Result<()> { - let tera = create_tera(&config.templates_dir)?; + let mut tera = create_tera(&config.templates_dir)?; let out_dir = to_checked_pathbuf(&config.out_dir); let mut context = tera::Context::new(); - let (feeds, entries) = feed_store.collect(&config.feeds); + let (feeds, entries): (HashMap<String, Feed>, _) = + feed_store.collect(&config.feeds, config.max_entries); context.insert("feeds", &feeds); context.insert("entries", &entries); context.insert("PKG_AUTHORS", env!("CARGO_PKG_AUTHORS")); context.insert("PKG_HOMEPAGE", env!("CARGO_PKG_HOMEPAGE")); context.insert("PKG_NAME", env!("CARGO_PKG_NAME")); context.insert("PKG_VERSION", env!("CARGO_PKG_VERSION")); + tera.register_function("get_author", GetAuthorFunction { feeds }); for name in tera.get_template_names() { debug!("Processing template {name}"); @@ -33,3 +37,54 @@ fn create_tera(templates_dir: &str) -> Result<Tera> { tera.autoescape_on(vec![]); Ok(tera) } + +struct GetAuthorFunction { + feeds: HashMap<String, Feed>, +} + +impl tera::Function for GetAuthorFunction { + fn call(&self, args: &HashMap<String, tera::Value>) -> Result<tera::Value, tera::Error> { + let entry_val: tera::Map<_, _> = match args.get("entry") { + None => { + return Err(tera::Error::msg( + "No argument of name 'entry' given to function.", + )) + } + Some(val) => from_value(val.clone())?, + }; + + let feed_url: String = from_value(entry_val.get("source").unwrap().clone())?; + let authors_val: Vec<tera::Map<_, _>> = + from_value(entry_val.get("authors").unwrap().clone())?; + + let mut authors: Vec<String> = Vec::new(); + for author_val in authors_val { + let name: String = from_value(author_val.get("name").unwrap().clone())?; + if is_valid_name(&name) { + authors.push(name.clone()); + } + } + + if authors.is_empty() { + authors.append(&mut self.find_authors_from_feed(&feed_url)); + } + Ok(tera::Value::String(authors.join(", "))) + } +} + +impl GetAuthorFunction { + fn find_authors_from_feed(&self, feed_url: &str) -> Vec<String> { + let feed = self.feeds.get(feed_url).unwrap(); + + feed.authors + .clone() + .into_iter() + .map(|x| x.name) + .filter(is_valid_name) + .collect() + } +} + +fn is_valid_name(n: &String) -> bool { + !n.is_empty() && n != "unknown" && n != "author" +} diff --git a/web/planet-mars/templates/index.html b/web/planet-mars/templates/index.html index 767bfa3704c3..d72f10f532e6 100644 --- a/web/planet-mars/templates/index.html +++ b/web/planet-mars/templates/index.html @@ -1,5 +1,4 @@ {% set dateformat = "%d.%m.%Y %H:%M" -%} - <html> <head> <title>Planet TVL</title> @@ -10,6 +9,7 @@ <link rel="alternate" type="application/xml+atom" title="Planet Haskell Atom Feed" href="atom.xml"> </head> <body> + <div id="bodydiv"> <header> <h1>Planet TVL</h1> </header> @@ -42,20 +42,20 @@ <span>{{ entry.published | date(format=dateformat) }}</span> {% endif -%} </date> - {% if entry.authors -%} - — <span class="entry_author">{{ entry.authors.0.name | striptags }}</span> + {% set author = get_author(entry=entry) -%} + {% if author -%} + — <span class="entry_author">{{ author | striptags }}</span> {% endif -%} </div> - {% if entry.summary -%} - <div class="entry_summary"> - {{ entry.summary.content }} - </div> - {% endif -%} {% if entry.content -%} <div class="entry_content"> {{ entry.content.body }} </div> + {% elif entry.summary -%} + <div class="entry_summary"> + {{ entry.summary.content }} + </div> {% endif -%} </article> {% endfor -%} @@ -65,7 +65,7 @@ <img src="logo.svg"> <p>Last updated: {{now()|date(format="%Y-%m-%d %H:%M")}}</p> <ul> - {% for feed in feeds %} + {% for feed_url, feed in feeds %} <li> <a {% if feed.links.0 %}href="{{feed.links.0.href}}"{% endif -%}> {% if feed.title -%} @@ -74,10 +74,12 @@ {{ feed.authors.0.name }} {% endif -%} </a> + (<a href="{{feed_url}}">feed</a>) </li> {% endfor %} </ul> </aside> </div> + </div> </body> </html> |