about summary refs log tree commit diff
path: root/templates-neo/src/mf2.rs
diff options
context:
space:
mode:
Diffstat (limited to 'templates-neo/src/mf2.rs')
-rw-r--r--templates-neo/src/mf2.rs467
1 files changed, 0 insertions, 467 deletions
diff --git a/templates-neo/src/mf2.rs b/templates-neo/src/mf2.rs
deleted file mode 100644
index 3cf453f..0000000
--- a/templates-neo/src/mf2.rs
+++ /dev/null
@@ -1,467 +0,0 @@
-use std::{borrow::Cow, collections::HashMap};
-
-use html::{
-    content::builders::{ArticleBuilder, SectionBuilder},
-    inline_text::Anchor,
-    media::builders,
-};
-use microformats::types::{
-    temporal::Value as Temporal, Class, Fragment, Item, KnownClass, PropertyValue,
-};
-
-#[derive(Debug, thiserror::Error)]
-pub enum Error {
-    #[error("wrong mf2 class, expected {expected:?}, got {got:?}")]
-    WrongClass {
-        expected: Vec<KnownClass>,
-        got: Vec<Class>,
-    },
-    #[error("entry lacks `uid` property")]
-    NoUid,
-    #[error("unexpected type of property value: expected {expected}, got {got:?}")]
-    WrongValueType {
-        expected: &'static str,
-        got: PropertyValue,
-    },
-    #[error("missing property: {0}")]
-    MissingProperty(&'static str),
-}
-
-pub enum Image {
-    Plain(url::Url),
-    Accessible { src: url::Url, alt: String },
-}
-
-impl Image {
-    pub fn build(
-        self,
-        img: &mut html::media::builders::ImageBuilder,
-    ) -> &mut html::media::builders::ImageBuilder {
-        match self {
-            Image::Plain(url) => img.src(String::from(url)),
-            Image::Accessible { src, alt } => img.src(String::from(src)).alt(alt),
-        }
-    }
-}
-
-pub struct Card {
-    uid: url::Url,
-    urls: Vec<url::Url>,
-    name: String,
-    note: Option<String>,
-    photo: Image,
-    pronouns: Vec<String>,
-}
-
-impl TryFrom<Item> for Card {
-    type Error = Error;
-
-    fn try_from(card: Item) -> Result<Self, Self::Error> {
-        if card.r#type.as_slice() != [Class::Known(KnownClass::Card)] {
-            return Err(Error::WrongClass {
-                expected: vec![KnownClass::Card],
-                got: card.r#type,
-            });
-        }
-
-        let mut props = card.properties;
-        let uid = {
-            let uids = props.remove("uid").ok_or(Error::NoUid)?;
-            if let Some(PropertyValue::Url(uid)) = uids.into_iter().take(1).next() {
-                uid
-            } else {
-                return Err(Error::NoUid);
-            }
-        };
-
-        Ok(Self {
-            uid,
-            urls: props
-                .remove("url")
-                .unwrap_or_default()
-                .into_iter()
-                .filter_map(|v| {
-                    if let PropertyValue::Url(url) = v {
-                        Some(url)
-                    } else {
-                        None
-                    }
-                })
-                .collect(),
-            name: props
-                .remove("name")
-                .unwrap_or_default()
-                .into_iter()
-                .next()
-                .ok_or(Error::MissingProperty("name"))
-                .and_then(|v| match v {
-                    PropertyValue::Plain(plain) => Ok(plain),
-                    other => Err(Error::WrongValueType {
-                        expected: "string",
-                        got: other,
-                    }),
-                })?,
-            note: props
-                .remove("note")
-                .unwrap_or_default()
-                .into_iter()
-                .next()
-                .map(|v| match v {
-                    PropertyValue::Plain(plain) => Ok(plain),
-                    other => Err(Error::WrongValueType {
-                        expected: "string",
-                        got: other,
-                    }),
-                })
-                .transpose()?,
-            photo: props
-                .remove("photo")
-                .unwrap_or_default()
-                .into_iter()
-                .next()
-                .ok_or(Error::MissingProperty("photo"))
-                .and_then(|v| match v {
-                    PropertyValue::Url(url) => Ok(Image::Plain(url)),
-                    PropertyValue::Image(image) => match image.alt {
-                        Some(alt) => Ok(Image::Accessible {
-                            src: image.value,
-                            alt,
-                        }),
-                        None => Ok(Image::Plain(image.value))
-                    },
-                    other => Err(Error::WrongValueType {
-                        expected: "string",
-                        got: other,
-                    }),
-                })?,
-            pronouns: props
-                .remove("pronoun")
-                .unwrap_or_default()
-                .into_iter()
-                .map(|v| match v {
-                    PropertyValue::Plain(plain) => Ok(plain),
-                    other => Err(Error::WrongValueType {
-                        expected: "string",
-                        got: other,
-                    }),
-                })
-                .collect::<Result<Vec<String>, _>>()?,
-        })
-    }
-}
-
-impl Card {
-    pub fn build_section(
-        self,
-        section: &mut html::content::builders::SectionBuilder,
-    ) -> &mut html::content::builders::SectionBuilder {
-        section.class("mini-h-card").anchor(|a| {
-            a.class("larger u-author")
-                .href(String::from(self.uid))
-                .image(move |img| self.photo.build(img).loading("lazy"))
-                .text(self.name)
-        })
-    }
-
-    pub fn build(
-        self,
-        article: &mut html::content::builders::ArticleBuilder,
-    ) -> &mut html::content::builders::ArticleBuilder {
-        let urls: Vec<_> = self.urls.into_iter().filter(|u| *u != self.uid).collect();
-
-        article
-            .class("h-card")
-            .image(move |builder| self.photo.build(builder))
-            .heading_1(move |builder| {
-                builder.anchor(|builder| {
-                    builder
-                        .class("u-url u-uid p-name")
-                        .href(String::from(self.uid))
-                        .text(self.name)
-                })
-            });
-
-        if !self.pronouns.is_empty() {
-            article.span(move |span| {
-                span.text("(");
-                self.pronouns.into_iter().for_each(|p| {
-                    span.text(p);
-                });
-                span.text(")")
-            });
-        }
-
-        if let Some(note) = self.note {
-            article.paragraph(move |p| p.class("p-note").text(note));
-        }
-
-        if !urls.is_empty() {
-            article.paragraph(|p| p.text("Can be found elsewhere at:"));
-            article.unordered_list(move |ul| {
-                for url in urls {
-                    let url = String::from(url);
-                    ul.list_item(move |li| {
-                        li.push(Anchor::builder().href(url.clone()).text(url).build())
-                    });
-                }
-
-                ul
-            });
-        }
-
-        article
-    }
-}
-
-impl TryFrom<PropertyValue> for Card {
-    type Error = Error;
-
-    fn try_from(v: PropertyValue) -> Result<Self, Self::Error> {
-        match v {
-            PropertyValue::Item(item) => item.try_into(),
-            other => Err(Error::WrongValueType {
-                expected: "h-card",
-                got: other,
-            }),
-        }
-    }
-}
-
-pub struct Cite {
-    uid: url::Url,
-    url: Vec<url::Url>,
-    in_reply_to: Option<Vec<Citation>>,
-    author: Card,
-    published: Option<time::OffsetDateTime>,
-    content: Content,
-}
-
-impl TryFrom<Item> for Cite {
-    type Error = Error;
-
-    fn try_from(cite: Item) -> Result<Self, Self::Error> {
-        if cite.r#type.as_slice() != [Class::Known(KnownClass::Cite)] {
-            return Err(Error::WrongClass {
-                expected: vec![KnownClass::Cite],
-                got: cite.r#type,
-            });
-        }
-
-        todo!()
-    }
-}
-
-pub enum Citation {
-    Brief(url::Url),
-    Full(Cite),
-}
-
-impl TryFrom<PropertyValue> for Citation {
-    type Error = Error;
-    fn try_from(v: PropertyValue) -> Result<Self, Self::Error> {
-        match v {
-            PropertyValue::Url(url) => Ok(Self::Brief(url)),
-            PropertyValue::Item(item) => Ok(Self::Full(item.try_into()?)),
-            other => Err(Error::WrongValueType {
-                expected: "url or h-cite",
-                got: other,
-            }),
-        }
-    }
-}
-
-pub struct Content(Fragment);
-
-impl From<Content> for html::content::Main {
-    fn from(content: Content) -> Self {
-        let mut builder = Self::builder();
-        builder.class("e-content").text(content.0.html);
-        if let Some(lang) = content.0.lang {
-            builder.lang(Cow::Owned(lang));
-        }
-        builder.build()
-    }
-}
-
-pub struct Entry {
-    uid: url::Url,
-    url: Vec<url::Url>,
-    in_reply_to: Option<Citation>,
-    author: Card,
-    category: Vec<String>,
-    syndication: Vec<url::Url>,
-    published: time::OffsetDateTime,
-    content: Content,
-}
-
-impl TryFrom<Item> for Entry {
-    type Error = Error;
-    fn try_from(entry: Item) -> Result<Self, Self::Error> {
-        if entry.r#type.as_slice() != [Class::Known(KnownClass::Entry)] {
-            return Err(Error::WrongClass {
-                expected: vec![KnownClass::Entry],
-                got: entry.r#type,
-            });
-        }
-
-        let mut props = entry.properties;
-        let uid = {
-            let uids = props.remove("uid").ok_or(Error::NoUid)?;
-            if let Some(PropertyValue::Url(uid)) = uids.into_iter().take(1).next() {
-                uid
-            } else {
-                return Err(Error::NoUid);
-            }
-        };
-        Ok(Entry {
-            uid,
-            url: props
-                .remove("url")
-                .unwrap_or_default()
-                .into_iter()
-                .filter_map(|v| {
-                    if let PropertyValue::Url(url) = v {
-                        Some(url)
-                    } else {
-                        None
-                    }
-                })
-                .collect(),
-            in_reply_to: props
-                .remove("in-reply-to")
-                .unwrap_or_default()
-                .into_iter()
-                .next()
-                .map(|v| v.try_into())
-                .transpose()?,
-            author: props
-                .remove("author")
-                .unwrap_or_default()
-                .into_iter()
-                .next()
-                .map(|v| v.try_into())
-                .transpose()?
-                .ok_or(Error::MissingProperty("author"))?,
-            category: props
-                .remove("category")
-                .unwrap_or_default()
-                .into_iter()
-                .map(|v| match v {
-                    PropertyValue::Plain(string) => Ok(string),
-                    other => Err(Error::WrongValueType {
-                        expected: "string",
-                        got: other,
-                    }),
-                })
-                .collect::<Result<Vec<_>, _>>()?,
-            syndication: props
-                .remove("syndication")
-                .unwrap_or_default()
-                .into_iter()
-                .map(|v| match v {
-                    PropertyValue::Url(url) => Ok(url),
-                    other => Err(Error::WrongValueType {
-                        expected: "link",
-                        got: other,
-                    }),
-                })
-                .collect::<Result<Vec<_>, _>>()?,
-            published: props
-                .remove("published")
-                .unwrap_or_default()
-                .into_iter()
-                .next()
-                .map(
-                    |v| -> Result<time::OffsetDateTime, Error> {
-                        match v {
-                            PropertyValue::Temporal(Temporal::Timestamp(ref dt)) => {
-                                // This is incredibly sketchy.
-                                let (date, time, offset) = (
-                                    dt.date.to_owned().ok_or_else(|| Error::WrongValueType {
-                                        expected: "timestamp (date, time, offset)",
-                                        got: v.clone()
-                                    })?.data,
-                                    dt.time.to_owned().ok_or_else(|| Error::WrongValueType {
-                                        expected: "timestamp (date, time, offset)",
-                                        got: v.clone()
-                                    })?.data,
-                                    dt.offset.to_owned().ok_or_else(|| Error::WrongValueType {
-                                        expected: "timestamp (date, time, offset)",
-                                        got: v.clone()
-                                    })?.data,
-                                );
-
-                                Ok(date.with_time(time).assume_offset(offset))
-                            }
-                            other => Err(Error::WrongValueType {
-                                expected: "timestamp",
-                                got: other,
-                            }),
-                        }
-                    },
-                )
-                .ok_or(Error::MissingProperty("published"))??,
-            content: props
-                .remove("content")
-                .unwrap_or_default()
-                .into_iter()
-                .next()
-                .ok_or(Error::MissingProperty("content"))
-                .and_then(|v| match v {
-                    PropertyValue::Fragment(fragment) => Ok(Content(fragment)),
-                    other => Err(Error::WrongValueType {
-                        expected: "html",
-                        got: other,
-                    }),
-                })?,
-        })
-    }
-}
-
-impl Entry {
-    pub fn build(self, article: &mut ArticleBuilder) -> &mut ArticleBuilder {
-        article
-            .class("h-entry")
-            .header(|header| {
-                header
-                    .class("metadata")
-                    .section(|section| self.author.build_section(section))
-                    .section(|section| {
-                        section
-                            .division(|div| {
-                                div.anchor(|a| {
-                                    a.class("u-url u-uid").href(String::from(self.uid)).push(
-                                        html::inline_text::Time::builder()
-                                            .text(
-                                                self.published
-                                                    .format(&time::format_description::well_known::Rfc2822)
-                                                    .unwrap()
-                                            )
-                                            .date_time(self.published.format(&time::format_description::well_known::Rfc3339).unwrap())
-                                            .build(),
-                                    )
-                                })
-                            })
-                            .division(|div| {
-                                div.text("Tagged").unordered_list(|ul| {
-                                    for category in self.category {
-                                        ul.list_item(|li| li.class("p-category").text(category));
-                                    }
-
-                                    ul
-                                })
-                            })
-                    })
-            })
-            .main(|main| {
-                if let Some(lang) = self.content.0.lang {
-                    main.lang(lang);
-                }
-
-                // XXX .text() and .push() are completely equivalent
-                // since .text() does no escaping
-                main.push(self.content.0.html)
-            })
-            .footer(|footer| footer)
-    }
-}