implement atom syndication
This commit is contained in:
		
							parent
							
								
									bc5ac494c6
								
							
						
					
					
						commit
						ab52991784
					
				| 
						 | 
				
			
			@ -94,6 +94,19 @@ dependencies = [
 | 
			
		|||
 "syn 2.0.18",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "atom_syndication"
 | 
			
		||||
version = "0.12.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ca96cb38e3d8236f1573a84bbc55e130bd1ae07df770e36d0cf221ea7a50e36c"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "chrono",
 | 
			
		||||
 "derive_builder",
 | 
			
		||||
 "diligent-date-parser",
 | 
			
		||||
 "never",
 | 
			
		||||
 "quick-xml",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "atomic"
 | 
			
		||||
version = "0.5.1"
 | 
			
		||||
| 
						 | 
				
			
			@ -437,6 +450,72 @@ dependencies = [
 | 
			
		|||
 "syn 1.0.107",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "darling"
 | 
			
		||||
version = "0.14.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "darling_core",
 | 
			
		||||
 "darling_macro",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "darling_core"
 | 
			
		||||
version = "0.14.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "fnv",
 | 
			
		||||
 "ident_case",
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "strsim",
 | 
			
		||||
 "syn 1.0.107",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "darling_macro"
 | 
			
		||||
version = "0.14.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "darling_core",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 1.0.107",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "derive_builder"
 | 
			
		||||
version = "0.12.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "derive_builder_macro",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "derive_builder_core"
 | 
			
		||||
version = "0.12.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "darling",
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 1.0.107",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "derive_builder_macro"
 | 
			
		||||
version = "0.12.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "derive_builder_core",
 | 
			
		||||
 "syn 1.0.107",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "derive_deref"
 | 
			
		||||
version = "1.1.1"
 | 
			
		||||
| 
						 | 
				
			
			@ -498,6 +577,15 @@ dependencies = [
 | 
			
		|||
 "subtle",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "diligent-date-parser"
 | 
			
		||||
version = "0.1.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f6cf7fe294274a222363f84bcb63cdea762979a0443b4cf1f4f8fd17c86b1182"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "chrono",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "doc-comment"
 | 
			
		||||
version = "0.3.3"
 | 
			
		||||
| 
						 | 
				
			
			@ -972,6 +1060,12 @@ dependencies = [
 | 
			
		|||
 "cxx-build",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ident_case"
 | 
			
		||||
version = "1.0.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "idna"
 | 
			
		||||
version = "0.3.0"
 | 
			
		||||
| 
						 | 
				
			
			@ -1377,6 +1471,12 @@ dependencies = [
 | 
			
		|||
 "winapi 0.3.9",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "never"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "normpath"
 | 
			
		||||
version = "0.3.2"
 | 
			
		||||
| 
						 | 
				
			
			@ -1749,6 +1849,16 @@ dependencies = [
 | 
			
		|||
 "unicase",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "quick-xml"
 | 
			
		||||
version = "0.28.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "encoding_rs",
 | 
			
		||||
 "memchr",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "quote"
 | 
			
		||||
version = "1.0.28"
 | 
			
		||||
| 
						 | 
				
			
			@ -2179,6 +2289,7 @@ name = "site"
 | 
			
		|||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "async-trait",
 | 
			
		||||
 "atom_syndication",
 | 
			
		||||
 "chrono",
 | 
			
		||||
 "chrono-humanize",
 | 
			
		||||
 "listenbrainz",
 | 
			
		||||
| 
						 | 
				
			
			@ -2274,6 +2385,12 @@ version = "1.1.0"
 | 
			
		|||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "strsim"
 | 
			
		||||
version = "0.10.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "subtle"
 | 
			
		||||
version = "2.4.1"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,3 +23,4 @@ markdown = "1.0.0-alpha.10"
 | 
			
		|||
async-trait = "0.1.68"
 | 
			
		||||
toml = "0.7.4"
 | 
			
		||||
tokio-stream = { version = "0.1.14", features = ["fs"] }
 | 
			
		||||
atom_syndication = "0.12.1"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										9
									
								
								TODO.md
								
								
								
								
							
							
						
						
									
										9
									
								
								TODO.md
								
								
								
								
							| 
						 | 
				
			
			@ -1,8 +1,17 @@
 | 
			
		|||
# TODO:
 | 
			
		||||
 | 
			
		||||
[x] make sure posts are organised in date order
 | 
			
		||||
[x] atom feed
 | 
			
		||||
[x] tags
 | 
			
		||||
    [ ] multiple tag UI
 | 
			
		||||
[ ] more badges
 | 
			
		||||
[ ] site translations
 | 
			
		||||
[ ] comments
 | 
			
		||||
[ ] clean up spaghetti
 | 
			
		||||
[ ] brush font PLZ
 | 
			
		||||
[ ] deploy database yum
 | 
			
		||||
[ ] visitor counter
 | 
			
		||||
[ ] guestbook
 | 
			
		||||
 | 
			
		||||
badges to steal:
 | 
			
		||||
[x] keith
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								src/error.rs
								
								
								
								
							
							
						
						
									
										16
									
								
								src/error.rs
								
								
								
								
							| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
use std::string::FromUtf8Error;
 | 
			
		||||
 | 
			
		||||
use rocket::{http::Status, Responder};
 | 
			
		||||
 | 
			
		||||
#[derive(Responder, Debug)]
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +10,8 @@ pub enum BlossomError {
 | 
			
		|||
    Chrono(Status, #[response(ignore)] chrono::ParseError),
 | 
			
		||||
    Io(Status, #[response(ignore)] std::io::Error),
 | 
			
		||||
    Deserialization(Status, #[response(ignore)] toml::de::Error),
 | 
			
		||||
    Syndicator(Status, #[response(ignore)] atom_syndication::Error),
 | 
			
		||||
    Utf8Conversion(Status, #[response(ignore)] FromUtf8Error),
 | 
			
		||||
    NotFound(Status),
 | 
			
		||||
    NoMetadata(Status),
 | 
			
		||||
    Unimplemented(Status),
 | 
			
		||||
| 
						 | 
				
			
			@ -48,3 +52,15 @@ impl From<toml::de::Error> for BlossomError {
 | 
			
		|||
        BlossomError::Deserialization(Status::new(500), e)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<atom_syndication::Error> for BlossomError {
 | 
			
		||||
    fn from(e: atom_syndication::Error) -> Self {
 | 
			
		||||
        BlossomError::Syndicator(Status::new(500), e)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<FromUtf8Error> for BlossomError {
 | 
			
		||||
    fn from(e: FromUtf8Error) -> Self {
 | 
			
		||||
        BlossomError::Utf8Conversion(Status::new(500), e)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										16
									
								
								src/main.rs
								
								
								
								
							| 
						 | 
				
			
			@ -7,8 +7,9 @@ mod skweets;
 | 
			
		|||
use std::borrow::Cow;
 | 
			
		||||
use std::collections::HashSet;
 | 
			
		||||
 | 
			
		||||
use atom_syndication::Feed;
 | 
			
		||||
use rocket::fs::{relative, FileServer};
 | 
			
		||||
use rocket::http::Status;
 | 
			
		||||
use rocket::http::{ContentType, Status};
 | 
			
		||||
use rocket::{Request, State};
 | 
			
		||||
use rocket_dyn_templates::{context, Template};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -87,6 +88,17 @@ async fn blog(filter: Vec<String>) -> Result<Template> {
 | 
			
		|||
    ))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/feed")]
 | 
			
		||||
async fn feed() -> Result<(Status, (ContentType, String))> {
 | 
			
		||||
    let posts = posts::get_blogposts().await?;
 | 
			
		||||
    let feed = posts::syndication::atom(posts).await;
 | 
			
		||||
    let feed: String = String::from_utf8(feed.write_to(Vec::new())?)?;
 | 
			
		||||
    Ok((
 | 
			
		||||
        Status::new(200),
 | 
			
		||||
        (ContentType::new("application", "atom+xml"), feed),
 | 
			
		||||
    ))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/contact")]
 | 
			
		||||
async fn contact() -> Template {
 | 
			
		||||
    Template::render("contact", context! {})
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +142,7 @@ async fn main() -> std::result::Result<(), rocket::Error> {
 | 
			
		|||
        .attach(Template::custom(|engines| {
 | 
			
		||||
            engines.tera.autoescape_on(vec![]);
 | 
			
		||||
        }))
 | 
			
		||||
        .mount("/", routes![home, contact, blog, blogpost, plants])
 | 
			
		||||
        .mount("/", routes![home, contact, blog, blogpost, feed, plants])
 | 
			
		||||
        .register("/", catchers![catcher])
 | 
			
		||||
        .mount("/", FileServer::from(relative!("static")))
 | 
			
		||||
        .launch()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
mod article;
 | 
			
		||||
mod note;
 | 
			
		||||
pub mod syndication;
 | 
			
		||||
 | 
			
		||||
use std::collections::HashSet;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,96 @@
 | 
			
		|||
use atom_syndication::{Category, Content, Entry, Feed, Generator, Link, Person, Text, TextType};
 | 
			
		||||
 | 
			
		||||
use super::{Article, Post};
 | 
			
		||||
 | 
			
		||||
pub async fn atom(posts: Vec<Post<Article>>) -> Feed {
 | 
			
		||||
    let me = Person {
 | 
			
		||||
        name: "cel".into(),
 | 
			
		||||
        email: Some("cel@blos.sm".into()),
 | 
			
		||||
        uri: Some("https://blos.sm".into()),
 | 
			
		||||
    };
 | 
			
		||||
    let mut authors = Vec::new();
 | 
			
		||||
    authors.push(me);
 | 
			
		||||
    let link = Link {
 | 
			
		||||
        href: "https://blos.sm/feed".into(),
 | 
			
		||||
        rel: "self".into(),
 | 
			
		||||
        hreflang: Some("en".into()),
 | 
			
		||||
        mime_type: Some("application/atom+xml".into()),
 | 
			
		||||
        title: Some("atom feed".into()),
 | 
			
		||||
        length: None,
 | 
			
		||||
    };
 | 
			
		||||
    let mut links = Vec::new();
 | 
			
		||||
    links.push(link);
 | 
			
		||||
    let mut feed = Feed {
 | 
			
		||||
        title: Text {
 | 
			
		||||
            value: "cel's site".into(),
 | 
			
		||||
            base: None,
 | 
			
		||||
            lang: Some("en".into()),
 | 
			
		||||
            r#type: TextType::Text,
 | 
			
		||||
        },
 | 
			
		||||
        id: "https://blos.sm".into(),
 | 
			
		||||
        updated: posts[0].created_at.into(),
 | 
			
		||||
        authors: authors.clone(),
 | 
			
		||||
        categories: Vec::new(),
 | 
			
		||||
        contributors: authors.clone(),
 | 
			
		||||
        generator: Some(Generator {
 | 
			
		||||
            value: "blos.sm".into(),
 | 
			
		||||
            uri: Some("https://bunny.garden/cel/blos.sm".into()),
 | 
			
		||||
            version: None,
 | 
			
		||||
        }),
 | 
			
		||||
        icon: Some("/icon.png".into()),
 | 
			
		||||
        links: links.clone(),
 | 
			
		||||
        logo: Some("/logo.png".into()),
 | 
			
		||||
        rights: None,
 | 
			
		||||
        subtitle: None,
 | 
			
		||||
        entries: Vec::new(),
 | 
			
		||||
        base: Some("https://blos.sm".into()),
 | 
			
		||||
        lang: Some("en".into()),
 | 
			
		||||
        ..Default::default()
 | 
			
		||||
    };
 | 
			
		||||
    for mut post in posts {
 | 
			
		||||
        post.render().await.unwrap_or_default();
 | 
			
		||||
        let mut id = String::from("https://blos.sm/blog/");
 | 
			
		||||
        id.push_str(&post.data.name);
 | 
			
		||||
        let categories = post
 | 
			
		||||
            .tags
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .map(|tag| Category {
 | 
			
		||||
                term: tag.clone(),
 | 
			
		||||
                scheme: None,
 | 
			
		||||
                label: Some(tag.clone()),
 | 
			
		||||
            })
 | 
			
		||||
            .collect();
 | 
			
		||||
        let entry = Entry {
 | 
			
		||||
            title: Text {
 | 
			
		||||
                value: post.subject.unwrap_or_default(),
 | 
			
		||||
                base: None,
 | 
			
		||||
                lang: Some("en".into()),
 | 
			
		||||
                r#type: TextType::Text,
 | 
			
		||||
            },
 | 
			
		||||
            id: id.clone(),
 | 
			
		||||
            updated: if let Some(updated_at) = post.updated_at {
 | 
			
		||||
                updated_at.into()
 | 
			
		||||
            } else {
 | 
			
		||||
                post.created_at.into()
 | 
			
		||||
            },
 | 
			
		||||
            authors: authors.clone(),
 | 
			
		||||
            categories,
 | 
			
		||||
            contributors: authors.clone(),
 | 
			
		||||
            links: links.clone(),
 | 
			
		||||
            published: Some(post.created_at.into()),
 | 
			
		||||
            rights: None,
 | 
			
		||||
            source: None,
 | 
			
		||||
            summary: None,
 | 
			
		||||
            content: Some(Content {
 | 
			
		||||
                base: None,
 | 
			
		||||
                lang: Some("en".into()),
 | 
			
		||||
                value: post.render,
 | 
			
		||||
                src: Some(id),
 | 
			
		||||
                content_type: Some("html".to_string()),
 | 
			
		||||
            }),
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        };
 | 
			
		||||
        feed.entries.push(entry);
 | 
			
		||||
    }
 | 
			
		||||
    feed
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.7 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 199 B  | 
| 
						 | 
				
			
			@ -166,6 +166,14 @@ footer {
 | 
			
		|||
  background-color: #0000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.small-badge,
 | 
			
		||||
.small-badge * {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  border: 0;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  font-size: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* homepage css */
 | 
			
		||||
 | 
			
		||||
#title {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@
 | 
			
		|||
          <li><a class="{% block nav_blog %}{% endblock %}" style="font-family: Sligoil" href="/blog">girlblog</a></li>
 | 
			
		||||
          <li><a class="{% block nav_projects %}{% endblock %}" style="font-family: 'DeGerm LoCase';" href="/projects">projetos</a></li>
 | 
			
		||||
          <li><a class="{% block nav_sound %}{% endblock %}" style="font-family: 'kirieji'" href="/sound">音</a></li>
 | 
			
		||||
          <li><a class="{% block nav_listens %}{% endblock %}" style="font-family: 'Almendra Display'; font-weight: 900;" href="https://listenbrainz.org/celblossom">écoute</a></li>
 | 
			
		||||
          <li><a class="{% block nav_listens %}{% endblock %}" style="font-family: 'Almendra Display'; font-weight: 900;" href="https://listenbrainz.org/user/celblossom">écoute</a></li>
 | 
			
		||||
          <li><a href="https://bimbo.video/a/cel" style="font-family: 'Mon Hugo In'">video</a></li>
 | 
			
		||||
          <li><a href="https://weirdstar.stream" style="font-family: id_kana018" >🔴ライブ</a></li>
 | 
			
		||||
          <li><a class="{% block nav_pix %}{% endblock %}" style="font-family: Minecraftia" href="/pix">pix</a></li>
 | 
			
		||||
| 
						 | 
				
			
			@ -70,6 +70,7 @@
 | 
			
		|||
      </main>
 | 
			
		||||
 | 
			
		||||
      <footer class="panel">
 | 
			
		||||
          <a class="badge" href="https://blos.sm"><img src="https://blos.sm/badges/cel.png"></a>
 | 
			
		||||
          <a class="badge" href="https://skinnyver.se"><img src="https://skinnyver.se/instance/skinnyversebadge.png"></a>
 | 
			
		||||
          <img class="badge" src="/badges/mothracompat.gif">
 | 
			
		||||
          <img class="badge" src="/badges/flexbox.png">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,9 +15,8 @@
 | 
			
		|||
<div class="content panel h-card" rel="author">
 | 
			
		||||
  <h1 class="p-name">cel</h1>
 | 
			
		||||
        
 | 
			
		||||
  <h3>pronouns: <a class="u-url" rel="me" href="https://en.pronouns.page/@celblossom"><span class="p-x-pronoun-nominative">she</span>/<span class="p-x-pronoun-accusative">her</span></a></h3>
 | 
			
		||||
        
 | 
			
		||||
  <ul>
 | 
			
		||||
    <li><h3>pronouns: <span class="p-x-pronoun-nominative">she</span>/<span class="p-x-pronoun-accusative">her</span></h3></li>
 | 
			
		||||
    <li>email: <a class="u-email" href="mailto:cel@blos.sm">cel@blos.sm</a> <a href="cel.asc" class="u-key" rel="pgpkey">pgp key</a></li>
 | 
			
		||||
    <li>xmpp: <a class="u-impp" href="xmpp:cel@blos.sm?message">cel@blos.sm</a></li>
 | 
			
		||||
    <li>fedi: <a class="u-url" rel="me" href="https://skinnyver.se/cel">cel@skinnyver.se</a></li>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,10 +30,10 @@
 | 
			
		|||
 | 
			
		||||
<div class="panel content">
 | 
			
		||||
  <h2>hallo i am celeste welcome 2 my site 🌟</h2>
 | 
			
		||||
  <p>this is where i dump everything</p>
 | 
			
		||||
  <p>this is where i do the posting</p>
 | 
			
		||||
  <p>i wish u a wonderful day</p>
 | 
			
		||||
  <br>
 | 
			
		||||
  <img src="https://s3.eu-west-1.wasabisys.com/skinnyverse/f28c467a-0ee1-4d49-a638-08a010fd9927/quinntyping.png">
 | 
			
		||||
  <img src="/quinntyping.png">
 | 
			
		||||
  <p>perpetually under construction</p>
 | 
			
		||||
  <img style="border: 0;" src="/barraconstruction.gif">
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
<div class="panel" id="posts">
 | 
			
		||||
  <h2>latest posts <!--<a class="badge" href="/feed.xml"><img class="badge" src="/rssbadge.png" alt="rss newsfeed"></a>--></h2>
 | 
			
		||||
  <h2>latest posts <a class="small-badge" href="/feed"><img class="small-badge" src="/atombadge.png" alt="atom newsfeed"></a></h2>
 | 
			
		||||
  <table id="post-list">
 | 
			
		||||
    {% for blogpost in blogposts %}
 | 
			
		||||
    <tr>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue