Add RSS and fixups
This commit is contained in:
@@ -91,6 +91,7 @@ main {
|
||||
|
||||
@media all and (max-width: 650px) {
|
||||
.ce-toolbar__actions {
|
||||
|
||||
&>*:nth-child(1),
|
||||
&>*:nth-child(2) {
|
||||
border-radius: 0;
|
||||
@@ -141,7 +142,7 @@ main {
|
||||
}
|
||||
|
||||
* {
|
||||
border-radius: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.ce-block__content {
|
||||
@@ -192,6 +193,11 @@ main {
|
||||
background-color: var(--color-selection) !important;
|
||||
}
|
||||
|
||||
.cdx-quote__text {
|
||||
border-block-end: none !important;
|
||||
margin-block-end: 0 !important;
|
||||
}
|
||||
|
||||
.embed-tool__caption {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -3239,16 +3239,6 @@
|
||||
static get sanitize() {
|
||||
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) {
|
||||
(this._data.alignment = t), this._block.dispatchChange();
|
||||
}
|
||||
@@ -13662,7 +13652,7 @@ var editor = new EditorJS({
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
quotePlaceholder: "Enter a quote",
|
||||
captionPlaceholder: "Quote's author",
|
||||
captionPlaceholder: "Add author or a caption, leave blank to hide",
|
||||
},
|
||||
shortcut: "CMD+SHIFT+O",
|
||||
},
|
||||
|
||||
+84
-2
@@ -1,4 +1,4 @@
|
||||
use std::borrow::Borrow;
|
||||
use chrono::prelude::*;
|
||||
use std::{env, vec};
|
||||
|
||||
use blogdb::posts::Post;
|
||||
@@ -773,7 +773,7 @@ where
|
||||
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
|
||||
S: AsRef<str>,
|
||||
{
|
||||
@@ -781,6 +781,11 @@ where
|
||||
input.as_ref(),
|
||||
RewriteStrSettings {
|
||||
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") {
|
||||
Some(class) => t
|
||||
.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()
|
||||
}
|
||||
|
||||
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(),
|
||||
|
||||
};
|
||||
html::animate_anchors(html::remove_el(&text, "br"))
|
||||
html::zhuzh_anchors(html::remove_el(&text, "br"))
|
||||
}
|
||||
|
||||
fn to_plaintext(&self) -> String {
|
||||
|
||||
@@ -62,6 +62,7 @@ pub(super) async fn make_router(state: BlogState) -> Router {
|
||||
.nest("/api", api(state.clone()))
|
||||
.nest("/login", login(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("/search", get(search_empty))
|
||||
.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()
|
||||
}
|
||||
|
||||
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)]
|
||||
pub(crate) struct SearchResponse(Vec<SearchResponseEntry>);
|
||||
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>
|
||||
Reference in New Issue
Block a user