about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThomas Koch <thomas@koch.ro>2025-01-12T18·12+0200
committerThomas Koch <thomas@koch.ro>2025-01-12T18·13+0200
commit150314936c46fc438aebd74106f6f2a6a0f30b30 (patch)
tree10919149060028387d9eaa86a804279194f557f7
parent4a9f5201d1360d5a2369224317b26c288b438236 (diff)
get authors also from feed data + some css
-rw-r--r--web/planet-mars/planet.css67
-rw-r--r--web/planet-mars/src/feed_store.rs27
-rw-r--r--web/planet-mars/src/main.rs2
-rw-r--r--web/planet-mars/src/template_engine.rs61
-rw-r--r--web/planet-mars/templates/index.html20
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 -%}
-                &mdash; <span class="entry_author">{{ entry.authors.0.name | striptags }}</span>
+              {% set author = get_author(entry=entry) -%}
+              {% if author -%}
+                &mdash; <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>