Add RSS and fixups
This commit is contained in:
parent
d95d764c4a
commit
4bfce7c928
|
@ -67,6 +67,21 @@ version = "0.2.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.95"
|
version = "1.0.95"
|
||||||
|
@ -346,6 +361,20 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.39"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
|
||||||
|
dependencies = [
|
||||||
|
"android-tzdata",
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cipher"
|
name = "cipher"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
|
@ -398,6 +427,12 @@ dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
@ -1042,6 +1077,29 @@ dependencies = [
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collections"
|
name = "icu_collections"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -2222,6 +2280,7 @@ dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
"blogdb",
|
"blogdb",
|
||||||
|
"chrono",
|
||||||
"constcat",
|
"constcat",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"futures",
|
"futures",
|
||||||
|
@ -3277,6 +3336,15 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
|
|
|
@ -46,6 +46,7 @@ tracing-subscriber = { version = "0.3.18", features = [
|
||||||
"std",
|
"std",
|
||||||
] }
|
] }
|
||||||
phf = "0.11.2"
|
phf = "0.11.2"
|
||||||
|
chrono = { version = "0.4.39", features = ["alloc"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
|
|
|
@ -17,7 +17,7 @@ fn main() {
|
||||||
println!("cargo:rustc-env={key}={value}");
|
println!("cargo:rustc-env={key}={value}");
|
||||||
}
|
}
|
||||||
let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
|
let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
|
||||||
let mut file = BufWriter::new(File::create(&path).unwrap());
|
let mut outfile = BufWriter::new(File::create(&path).unwrap());
|
||||||
let template_dir = [&env::var("CARGO_MANIFEST_DIR").unwrap(), "/src/templates"].concat();
|
let template_dir = [&env::var("CARGO_MANIFEST_DIR").unwrap(), "/src/templates"].concat();
|
||||||
println!("cargo:rerun-if-changed={}", template_dir);
|
println!("cargo:rerun-if-changed={}", template_dir);
|
||||||
let pattern = [&template_dir, "/**/*.html"].concat();
|
let pattern = [&template_dir, "/**/*.html"].concat();
|
||||||
|
@ -47,8 +47,24 @@ fn main() {
|
||||||
Err(_) => todo!(),
|
Err(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// this is all a mess cause i'm lazy lol
|
||||||
|
let feed_template_path = [&template_dir, "/feed.xml"].concat();
|
||||||
|
let mut feed_file = File::open(feed_template_path).unwrap();
|
||||||
|
let mut content = "r####\"".to_string();
|
||||||
|
feed_file.read_to_string(&mut content).unwrap();
|
||||||
|
content.push_str("\"####");
|
||||||
|
let feed_template = content;
|
||||||
|
map.entry("feed".to_string(), &feed_template);
|
||||||
|
let item_template_path = [&template_dir, "/item.xml"].concat();
|
||||||
|
let mut item_file = File::open(item_template_path).unwrap();
|
||||||
|
let mut content = "r####\"".to_string();
|
||||||
|
item_file.read_to_string(&mut content).unwrap();
|
||||||
|
content.push_str("\"####");
|
||||||
|
let item_template = content;
|
||||||
|
map.entry("item".to_string(), &item_template);
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
&mut file,
|
&mut outfile,
|
||||||
"static TEMPLATES: phf::Map<&'static str, &'static str> = {};",
|
"static TEMPLATES: phf::Map<&'static str, &'static str> = {};",
|
||||||
map.build()
|
map.build()
|
||||||
)
|
)
|
||||||
|
|
|
@ -91,6 +91,7 @@ main {
|
||||||
|
|
||||||
@media all and (max-width: 650px) {
|
@media all and (max-width: 650px) {
|
||||||
.ce-toolbar__actions {
|
.ce-toolbar__actions {
|
||||||
|
|
||||||
&>*:nth-child(1),
|
&>*:nth-child(1),
|
||||||
&>*:nth-child(2) {
|
&>*:nth-child(2) {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
@ -192,6 +193,11 @@ main {
|
||||||
background-color: var(--color-selection) !important;
|
background-color: var(--color-selection) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cdx-quote__text {
|
||||||
|
border-block-end: none !important;
|
||||||
|
margin-block-end: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.embed-tool__caption {
|
.embed-tool__caption {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3239,16 +3239,6 @@
|
||||||
static get sanitize() {
|
static get sanitize() {
|
||||||
return { text: { br: !0 }, caption: { br: !0 }, alignment: {} };
|
return { text: { br: !0 }, caption: { br: !0 }, alignment: {} };
|
||||||
}
|
}
|
||||||
renderSettings() {
|
|
||||||
const t = (n) => n && n[0].toUpperCase() + n.slice(1);
|
|
||||||
return this.settings.map((n) => ({
|
|
||||||
icon: n.icon,
|
|
||||||
label: this.api.i18n.t(`Align ${t(n.name)}`),
|
|
||||||
onActivate: () => this._toggleTune(n.name),
|
|
||||||
isActive: this._data.alignment === n.name,
|
|
||||||
closeOnActivate: !0,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
_toggleTune(t) {
|
_toggleTune(t) {
|
||||||
(this._data.alignment = t), this._block.dispatchChange();
|
(this._data.alignment = t), this._block.dispatchChange();
|
||||||
}
|
}
|
||||||
|
@ -13662,7 +13652,7 @@ var editor = new EditorJS({
|
||||||
inlineToolbar: true,
|
inlineToolbar: true,
|
||||||
config: {
|
config: {
|
||||||
quotePlaceholder: "Enter a quote",
|
quotePlaceholder: "Enter a quote",
|
||||||
captionPlaceholder: "Quote's author",
|
captionPlaceholder: "Add author or a caption, leave blank to hide",
|
||||||
},
|
},
|
||||||
shortcut: "CMD+SHIFT+O",
|
shortcut: "CMD+SHIFT+O",
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::borrow::Borrow;
|
use chrono::prelude::*;
|
||||||
use std::{env, vec};
|
use std::{env, vec};
|
||||||
|
|
||||||
use blogdb::posts::Post;
|
use blogdb::posts::Post;
|
||||||
|
@ -773,7 +773,7 @@ where
|
||||||
make_page(message, PageSettings::title("Not found"))
|
make_page(message, PageSettings::title("Not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn animate_anchors<S>(input: S) -> String
|
pub(crate) fn zhuzh_anchors<S>(input: S) -> String
|
||||||
where
|
where
|
||||||
S: AsRef<str>,
|
S: AsRef<str>,
|
||||||
{
|
{
|
||||||
|
@ -781,6 +781,11 @@ where
|
||||||
input.as_ref(),
|
input.as_ref(),
|
||||||
RewriteStrSettings {
|
RewriteStrSettings {
|
||||||
element_content_handlers: vec![element!("a", move |t| {
|
element_content_handlers: vec![element!("a", move |t| {
|
||||||
|
if let Some(href) = t.get_attribute("href") {
|
||||||
|
if !href.starts_with("/") {
|
||||||
|
t.set_attribute("target", "_blank").unwrap_or_default();
|
||||||
|
}
|
||||||
|
}
|
||||||
match t.get_attribute("class") {
|
match t.get_attribute("class") {
|
||||||
Some(class) => t
|
Some(class) => t
|
||||||
.set_attribute("class", &[&class, " animated-link-underline"].concat())
|
.set_attribute("class", &[&class, " animated-link-underline"].concat())
|
||||||
|
@ -811,3 +816,80 @@ pub(crate) fn sanitize<S: AsRef<str>>(input: S) -> String {
|
||||||
)
|
)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn rss(db: &BlogDb) -> String {
|
||||||
|
let posts = db.get_posts().await.unwrap_or_default();
|
||||||
|
let mut items = String::new();
|
||||||
|
for post in posts {
|
||||||
|
let url = {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
["http://localhost/blog/", &post.id].concat()
|
||||||
|
}
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
{
|
||||||
|
["https://", env!("DOMAIN"), "/blog/", &entry.id].concat()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let item = rewrite_str(
|
||||||
|
template!("item"),
|
||||||
|
RewriteStrSettings {
|
||||||
|
element_content_handlers: vec![
|
||||||
|
element!("title", |title| {
|
||||||
|
title.set_inner_content(&post.title, ContentType::Text);
|
||||||
|
Ok(())
|
||||||
|
}),
|
||||||
|
element!("link", |link| {
|
||||||
|
link.replace(&["<link>", &url, "</link>"].concat(), ContentType::Html); // slight hack to get around lol_html weirdness
|
||||||
|
Ok(())
|
||||||
|
}),
|
||||||
|
element!("guid", |guid| {
|
||||||
|
guid.set_inner_content(&url, ContentType::Text);
|
||||||
|
Ok(())
|
||||||
|
}),
|
||||||
|
element!("pubDate", |pub_date| {
|
||||||
|
let date = {
|
||||||
|
let date: [u32; 3] = post
|
||||||
|
.date
|
||||||
|
.splitn(3, "-")
|
||||||
|
.map(|d| d.parse::<u32>().unwrap_or_default())
|
||||||
|
.collect::<Vec<u32>>()
|
||||||
|
.try_into()
|
||||||
|
.unwrap_or_default();
|
||||||
|
let date_time: DateTime<Utc> = Utc
|
||||||
|
.with_ymd_and_hms(date[0] as i32, date[1], date[2], 0, 0, 0)
|
||||||
|
.unwrap();
|
||||||
|
date_time.to_rfc2822()
|
||||||
|
};
|
||||||
|
pub_date.set_inner_content(&date, ContentType::Text);
|
||||||
|
Ok(())
|
||||||
|
}),
|
||||||
|
element!("description", |description| {
|
||||||
|
let post_content: Blocks =
|
||||||
|
serde_json::from_str(&post.content).unwrap_or_default();
|
||||||
|
let desc = ["<![CDATA[", &post_content.to_html(), "]]>"].concat();
|
||||||
|
description.set_inner_content(&desc, ContentType::Html);
|
||||||
|
Ok(())
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
..RewriteStrSettings::new()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap_or_default();
|
||||||
|
items.push_str(&item);
|
||||||
|
}
|
||||||
|
|
||||||
|
let feed = rewrite_str(
|
||||||
|
template!("feed"),
|
||||||
|
RewriteStrSettings {
|
||||||
|
element_content_handlers: vec![element!("channel", move |channel| {
|
||||||
|
channel.append(&items, ContentType::Html);
|
||||||
|
Ok(())
|
||||||
|
})],
|
||||||
|
..RewriteStrSettings::new()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
feed
|
||||||
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ impl Block {
|
||||||
Block::delimiter {} => "<div style=\"inline-size: 100%; block-size: 1px; background: var(--color-text)\"></div>".to_string(),
|
Block::delimiter {} => "<div style=\"inline-size: 100%; block-size: 1px; background: var(--color-text)\"></div>".to_string(),
|
||||||
|
|
||||||
};
|
};
|
||||||
html::animate_anchors(html::remove_el(&text, "br"))
|
html::zhuzh_anchors(html::remove_el(&text, "br"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_plaintext(&self) -> String {
|
fn to_plaintext(&self) -> String {
|
||||||
|
|
|
@ -62,6 +62,7 @@ pub(super) async fn make_router(state: BlogState) -> Router {
|
||||||
.nest("/api", api(state.clone()))
|
.nest("/api", api(state.clone()))
|
||||||
.nest("/login", login(State(state.clone())))
|
.nest("/login", login(State(state.clone())))
|
||||||
.route("/", get(pages).with_state(state.clone()))
|
.route("/", get(pages).with_state(state.clone()))
|
||||||
|
.route("/feed.xml", get(rss).with_state(state.clone()))
|
||||||
.route("/*path", get(pages).with_state(state.clone()))
|
.route("/*path", get(pages).with_state(state.clone()))
|
||||||
.route("/search", get(search_empty))
|
.route("/search", get(search_empty))
|
||||||
.route("/search/*query", get(search).with_state(state.clone()))
|
.route("/search/*query", get(search).with_state(state.clone()))
|
||||||
|
@ -308,6 +309,15 @@ async fn admin(jar: PrivateCookieJar, State(state): State<BlogState>) -> Respons
|
||||||
(headers, Html(page)).into_response()
|
(headers, Html(page)).into_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn rss(State(state): State<BlogState>) -> Response {
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.append(
|
||||||
|
CONTENT_TYPE,
|
||||||
|
HeaderValue::from_str("application/xml").unwrap(),
|
||||||
|
);
|
||||||
|
(headers, html::rss(state.db()).await).into_response()
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Default, Debug)]
|
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||||
pub(crate) struct SearchResponse(Vec<SearchResponseEntry>);
|
pub(crate) struct SearchResponse(Vec<SearchResponseEntry>);
|
||||||
impl SearchResponse {
|
impl SearchResponse {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
|
<channel>
|
||||||
|
<title>Evie Ippolito's Blog</title>
|
||||||
|
<link>https://evieippolito.com/blog</link>
|
||||||
|
<atom:link href="https://evieippolito.com/feed.xml" rel="self" type="application/rss+xml" />
|
||||||
|
<description>Evie's blog!</description>
|
||||||
|
<language>en-us</language>
|
||||||
|
<ttl>720</ttl>
|
||||||
|
<managingEditor>evieippolito@duck.com (Evie Ippolito)</managingEditor>
|
||||||
|
<webMaster>me@augustkline.com (august kline)</webMaster>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<item>
|
||||||
|
<title></title>
|
||||||
|
<link>
|
||||||
|
<guid isPermaLink="true"></guid>
|
||||||
|
<pubDate></pubDate>
|
||||||
|
<description></description>
|
||||||
|
</item>
|
Loading…
Reference in New Issue