Learning project: static site generator for ATproto PDS

Adds tangled repo, issue and PR support to mosaic #2

closed opened by hello.j23n.com targeting main from feature/tangled

Test 1,2,3

Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:enau5rzvrui4fx4dq5icgtle/sh.tangled.repo.pull/3m3phvvavup22
+156 -131
Diff #0
+13 -129
src/atproto/mod.rs
··· 1 1 use std::path::PathBuf; 2 2 3 - use atrium_api::{ 4 - app::bsky::embed::defs::AspectRatio, 5 - types::{BlobRef, Unknown}, 6 - }; 7 - 8 3 mod client; 9 4 mod renderable; 10 - pub use atrium_api::app::bsky::feed::post::RecordData as BskyPost; 5 + pub mod types; 6 + 11 7 pub use client::fetch_records; 12 8 pub use renderable::Renderable; 13 9 use tera::{Context, Tera}; 14 - 15 - #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 16 - pub struct Document { 17 - pub author: String, 18 - pub description: String, 19 - pub title: String, 20 - pub pages: Vec<Page>, 21 - #[serde(rename = "postRef")] 22 - pub post_ref: Option<Unknown>, 23 - pub publication: Unknown, 24 - #[serde(rename = "publishedAt")] 25 - pub published_at: String, 26 - #[serde(skip)] 27 - pub host: String, 28 - #[serde(skip)] 29 - pub did: String, 30 - } 31 - 32 - #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 33 - pub struct Page { 34 - pub blocks: Vec<BlockWrapper>, 35 - } 36 - 37 - #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 38 - pub struct BlockWrapper { 39 - pub block: Block, 40 - } 41 - 42 - #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 43 - #[serde(tag = "$type")] 44 - pub enum Block { 45 - #[serde(rename = "pub.leaflet.blocks.blockquote")] 46 - Blockquote { 47 - plaintext: String, 48 - // TODO facets: [&pub.leaflet.richtext.facet] 49 - }, 50 - 51 - #[serde(rename = "pub.leaflet.blocks.code")] 52 - Code { 53 - plaintext: String, 54 - language: Option<String>, 55 - #[serde(rename = "syntaxHighlightingTheme")] 56 - syntax_highlighting_theme: Option<String>, 57 - }, 58 - 59 - #[serde(rename = "pub.leaflet.blocks.bskyPost")] 60 - BskyPost { 61 - #[serde(rename = "postRef")] 62 - post_ref: String, 63 - }, 64 - 65 - #[serde(rename = "pub.leaflet.blocks.header")] 66 - Header { 67 - level: Option<u32>, 68 - plaintext: String, 69 - // TODO: facets: [&pub.leaflet.richtext.facet 70 - }, 71 - 72 - #[serde(rename = "pub.leaflet.blocks.horizontalRule")] 73 - HorizontalRule {}, 74 - 75 - #[serde(rename = "pub.leaflet.blocks.iframe")] 76 - IFrame { url: String, height: Option<u32> }, 77 - 78 - #[serde(rename = "pub.leaflet.blocks.image")] 79 - Image { 80 - image: BlobRef, 81 - alt: Option<String>, 82 - #[serde(rename = "aspectRatio")] 83 - aspect_ratio: AspectRatio, 84 - }, 85 - 86 - #[serde(rename = "pub.leaflet.blocks.math")] 87 - Math { tex: String }, 88 - 89 - #[serde(rename = "pub.leaflet.blocks.text")] 90 - Text { 91 - plaintext: String, 92 - // TODO: facets: [&pub.leaflet.richtext.facet] 93 - }, 94 - 95 - #[serde(rename = "pub.leaflet.blocks.unorderedList")] 96 - UnorderedList { children: Vec<ListItem> }, 97 - 98 - #[serde(other)] 99 - Unknown, 100 - } 101 - 102 - #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 103 - pub struct ListItem { 104 - content: ListItemContent, 105 - } 106 - 107 - #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 108 - #[serde(tag = "$type")] 109 - pub enum ListItemContent { 110 - #[serde(rename = "pub.leaflet.blocks.text")] 111 - Text { plaintext: String }, 112 - #[serde(rename = "pub.leaflet.blocks.header")] 113 - Header { 114 - level: Option<u32>, 115 - plaintext: String, 116 - }, 117 - #[serde(rename = "pub.leaflet.blocks.image")] 118 - Image { 119 - image: BlobRef, 120 - alt: Option<String>, 121 - #[serde(rename = "aspectRatio")] 122 - aspect_ratio: AspectRatio, 123 - }, 124 - } 125 - 126 - #[derive(Debug, serde::Deserialize, serde::Serialize)] 127 - pub struct Website { 128 - src: String, 129 - description: Option<String>, 130 - title: Option<String>, 131 - #[serde(rename = "previewImage")] 132 - preview_image: BlobRef, 133 - } 10 + use types::bsky::Post; 11 + use types::leaflet::Document; 12 + use types::tangled::Repo; 134 13 135 14 #[derive(Clone, serde::Serialize)] 136 15 pub enum ContentType { 137 16 Document(Document), 138 - BskyPost(BskyPost), 17 + Post(Post), 18 + Repo(Repo), 139 19 } 140 20 141 21 #[derive(Clone, serde::Serialize)] ··· 179 59 fn build_name(content: &ContentType) -> String { 180 60 match content { 181 61 ContentType::Document(doc) => doc.title.clone(), 182 - ContentType::BskyPost(post) => String::from(post.created_at.as_str()), 62 + ContentType::Post(post) => String::from(post.created_at.as_str()), 63 + ContentType::Repo(repo) => repo.name.clone(), 183 64 } 184 65 } 185 66 } ··· 238 119 context.insert("host", &doc.host); 239 120 context.insert("did", &doc.did); 240 121 } 241 - ContentType::BskyPost(post) => { 122 + ContentType::Post(post) => { 242 123 context.insert("post", post); 243 124 } 125 + ContentType::Repo(repo) => { 126 + context.insert("repo", repo); 127 + } 244 128 } 245 129 tera.render(&self.template, &context) 246 130 }
+1
src/atproto/types/bsky.rs
··· 1 + pub use atrium_api::app::bsky::feed::post::RecordData as Post;
+124
src/atproto/types/leaflet.rs
··· 1 + use atrium_api::{ 2 + app::bsky::embed::defs::AspectRatio, 3 + types::{BlobRef, Unknown}, 4 + }; 5 + 6 + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 7 + pub struct Document { 8 + pub author: String, 9 + pub description: String, 10 + pub title: String, 11 + pub pages: Vec<Page>, 12 + #[serde(rename = "postRef")] 13 + pub post_ref: Option<Unknown>, 14 + pub publication: Unknown, 15 + #[serde(rename = "publishedAt")] 16 + pub published_at: String, 17 + #[serde(skip)] 18 + pub host: String, 19 + #[serde(skip)] 20 + pub did: String, 21 + } 22 + 23 + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 24 + pub struct Page { 25 + pub blocks: Vec<BlockWrapper>, 26 + } 27 + 28 + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 29 + pub struct BlockWrapper { 30 + pub block: Block, 31 + } 32 + 33 + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 34 + #[serde(tag = "$type")] 35 + pub enum Block { 36 + #[serde(rename = "pub.leaflet.blocks.blockquote")] 37 + Blockquote { 38 + plaintext: String, 39 + // TODO facets: [&pub.leaflet.richtext.facet] 40 + }, 41 + 42 + #[serde(rename = "pub.leaflet.blocks.code")] 43 + Code { 44 + plaintext: String, 45 + language: Option<String>, 46 + #[serde(rename = "syntaxHighlightingTheme")] 47 + syntax_highlighting_theme: Option<String>, 48 + }, 49 + 50 + #[serde(rename = "pub.leaflet.blocks.bskyPost")] 51 + BskyPost { 52 + #[serde(rename = "postRef")] 53 + post_ref: String, 54 + }, 55 + 56 + #[serde(rename = "pub.leaflet.blocks.header")] 57 + Header { 58 + level: Option<u32>, 59 + plaintext: String, 60 + // TODO: facets: [&pub.leaflet.richtext.facet 61 + }, 62 + 63 + #[serde(rename = "pub.leaflet.blocks.horizontalRule")] 64 + HorizontalRule {}, 65 + 66 + #[serde(rename = "pub.leaflet.blocks.iframe")] 67 + IFrame { url: String, height: Option<u32> }, 68 + 69 + #[serde(rename = "pub.leaflet.blocks.image")] 70 + Image { 71 + image: BlobRef, 72 + alt: Option<String>, 73 + #[serde(rename = "aspectRatio")] 74 + aspect_ratio: AspectRatio, 75 + }, 76 + 77 + #[serde(rename = "pub.leaflet.blocks.math")] 78 + Math { tex: String }, 79 + 80 + #[serde(rename = "pub.leaflet.blocks.text")] 81 + Text { 82 + plaintext: String, 83 + // TODO: facets: [&pub.leaflet.richtext.facet] 84 + }, 85 + 86 + #[serde(rename = "pub.leaflet.blocks.unorderedList")] 87 + UnorderedList { children: Vec<ListItem> }, 88 + 89 + #[serde(other)] 90 + Unknown, 91 + } 92 + 93 + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 94 + pub struct ListItem { 95 + content: ListItemContent, 96 + } 97 + 98 + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] 99 + #[serde(tag = "$type")] 100 + pub enum ListItemContent { 101 + #[serde(rename = "pub.leaflet.blocks.text")] 102 + Text { plaintext: String }, 103 + #[serde(rename = "pub.leaflet.blocks.header")] 104 + Header { 105 + level: Option<u32>, 106 + plaintext: String, 107 + }, 108 + #[serde(rename = "pub.leaflet.blocks.image")] 109 + Image { 110 + image: BlobRef, 111 + alt: Option<String>, 112 + #[serde(rename = "aspectRatio")] 113 + aspect_ratio: AspectRatio, 114 + }, 115 + } 116 + 117 + #[derive(Debug, serde::Deserialize, serde::Serialize)] 118 + pub struct Website { 119 + src: String, 120 + description: Option<String>, 121 + title: Option<String>, 122 + #[serde(rename = "previewImage")] 123 + preview_image: BlobRef, 124 + }
+3
src/atproto/types/mod.rs
··· 1 + pub mod bsky; 2 + pub mod leaflet; 3 + pub mod tangled;
+10
src/atproto/types/tangled.rs
··· 1 + #[derive(serde::Deserialize, serde::Serialize, Clone)] 2 + #[serde(tag = "$type")] 3 + pub struct Repo { 4 + pub knot: String, 5 + pub name: String, 6 + pub labels: Vec<String>, 7 + #[serde(rename = "createdAt")] 8 + pub created_at: String, 9 + pub description: String, 10 + }
+5 -2
src/generator.rs
··· 7 7 use crate::config::Config; 8 8 use crate::templates::filters; 9 9 10 - use crate::atproto::{ 11 - BskyPost, ContentPage, ContentType, Document, IndexPage, Renderable, fetch_records, 10 + use crate::atproto::types::{ 11 + bsky::Post, 12 + leaflet::Document, 13 + tangled::{Issue, Repo}, 12 14 }; 15 + use crate::atproto::{ContentPage, ContentType, IndexPage, Renderable, fetch_records}; 13 16 14 17 use std::path::{Path, PathBuf}; 15 18

History

1 round 0 comments
sign up or login to add to the discussion
hello.j23n.com submitted #0
1 commit
expand
WIP: add tangled support
expand 0 comments
closed without merging