Inline mvp and custom override CSS when rendering RSS posts

This commit is contained in:
Bill Thiede 2024-08-05 15:47:31 -07:00
parent 359e798cfa
commit 530bd8e350
5 changed files with 315 additions and 274 deletions

8
server/src/custom.css Normal file
View File

@ -0,0 +1,8 @@
pre {
background-color: var(--color-bg);
color: var(--color-text);
}
code {
background-color: var(--color-bg-secondary);
}

View File

@ -13,10 +13,12 @@ use url::Url;
// TODO: figure out how to use Cow // TODO: figure out how to use Cow
trait Transformer { trait Transformer {
fn should_run(&self, input: &str) -> bool; fn should_run(&self, _html: &str) -> bool {
// TODO: should input be something like `html_escape` uses: true
}
// TODO: should html be something like `html_escape` uses:
// <S: ?Sized + AsRef<str>>(text: &S) -> Cow<str> // <S: ?Sized + AsRef<str>>(text: &S) -> Cow<str>
fn transform(&self, input: &str) -> Result<String, TransformError>; fn transform(&self, html: &str) -> Result<String, TransformError>;
} }
// TODO: how would we make this more generic to allow good implementations of Transformer outside // TODO: how would we make this more generic to allow good implementations of Transformer outside
@ -35,22 +37,50 @@ struct SanitizeHtml<'a> {
} }
impl<'a> Transformer for SanitizeHtml<'a> { impl<'a> Transformer for SanitizeHtml<'a> {
fn should_run(&self, _input: &str) -> bool { fn transform(&self, html: &str) -> Result<String, TransformError> {
true Ok(sanitize_html(html, self.cid_prefix, self.base_url)?)
}
fn transform(&self, input: &str) -> Result<String, TransformError> {
Ok(sanitize_html(input, self.cid_prefix, self.base_url)?)
} }
} }
struct EscapeHtml; struct EscapeHtml;
impl Transformer for EscapeHtml { impl Transformer for EscapeHtml {
fn should_run(&self, input: &str) -> bool { fn should_run(&self, html: &str) -> bool {
input.starts_with("&lt") html.starts_with("&lt")
} }
fn transform(&self, input: &str) -> Result<String, TransformError> { fn transform(&self, html: &str) -> Result<String, TransformError> {
Ok(html_escape::decode_html_entities(input).to_string()) Ok(html_escape::decode_html_entities(html).to_string())
}
}
struct InlineStyle;
impl Transformer for InlineStyle {
fn transform(&self, html: &str) -> Result<String, TransformError> {
let css = concat!(
"/* mvp.css */\n",
include_str!("mvp.css"),
"/* Xinu Specific overrides */\n",
include_str!("custom.css"),
);
let inline_opts = InlineOptions {
inline_style_tags: false,
keep_style_tags: false,
keep_link_tags: false,
base_url: None,
load_remote_stylesheets: false,
extra_css: Some(css.into()),
preallocate_node_capacity: 32,
..InlineOptions::default()
};
Ok(match CSSInliner::new(inline_opts).inline(&html) {
Ok(inlined_html) => inlined_html,
Err(err) => {
error!("failed to inline CSS: {err}");
html.to_string()
}
})
} }
} }

View File

@ -1,45 +1,6 @@
/* MVP.css v1.15 - https://github.com/andybrewer/mvp */ /* MVP.css v1.15 - https://github.com/andybrewer/mvp */
:root { /* :root content stored in client side index.html */
--active-brightness: 0.85;
--border-radius: 5px;
--box-shadow: 2px 2px 10px;
--color-accent: #118bee15;
--color-bg: #fff;
--color-bg-secondary: #e9e9e9;
--color-link: #118bee;
--color-secondary: #920de9;
--color-secondary-accent: #920de90b;
--color-shadow: #f4f4f4;
--color-table: #118bee;
--color-text: #000;
--color-text-secondary: #999;
--color-scrollbar: #cacae8;
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
--hover-brightness: 1.2;
--justify-important: center;
--justify-normal: left;
--line-height: 1.5;
--width-card: 285px;
--width-card-medium: 460px;
--width-card-wide: 800px;
--width-content: 1080px;
}
@media (prefers-color-scheme: dark) {
:root[color-mode="user"] {
--color-accent: #0097fc4f;
--color-bg: #333;
--color-bg-secondary: #555;
--color-link: #0097fc;
--color-secondary: #e20de9;
--color-secondary-accent: #e20de94f;
--color-shadow: #bbbbbb20;
--color-table: #0097fc;
--color-text: #f7f7f7;
--color-text-secondary: #aaa;
}
}
html { html {
scroll-behavior: smooth; scroll-behavior: smooth;
@ -425,8 +386,7 @@ textarea {
} }
input[type="text"], input[type="text"],
input[type="password"] input[type="password"] textarea {
textarea {
width: calc(100% - 1.6rem); width: calc(100% - 1.6rem);
} }

View File

@ -14,7 +14,7 @@ const THREAD_PREFIX: &'static str = "news:";
use crate::{ use crate::{
error::ServerError, error::ServerError,
graphql::{Body, Email, Html, Message, Tag, Thread, ThreadSummary}, graphql::{Body, Email, Html, Message, Tag, Thread, ThreadSummary},
EscapeHtml, SanitizeHtml, Transformer, EscapeHtml, InlineStyle, SanitizeHtml, Transformer,
}; };
pub fn is_newsreader_search(query: &str) -> bool { pub fn is_newsreader_search(query: &str) -> bool {
@ -213,6 +213,7 @@ pub async fn thread(pool: &PgPool, thread_id: String) -> Result<Thread, ServerEr
// * Some sites appear to be HTML encoded, unencode them, i.e. imperialviolent // * Some sites appear to be HTML encoded, unencode them, i.e. imperialviolent
let tranformers: Vec<Box<dyn Transformer>> = vec![ let tranformers: Vec<Box<dyn Transformer>> = vec![
Box::new(EscapeHtml), Box::new(EscapeHtml),
Box::new(InlineStyle),
Box::new(SanitizeHtml { Box::new(SanitizeHtml {
cid_prefix: "", cid_prefix: "",
base_url: &link, base_url: &link,
@ -224,7 +225,7 @@ pub async fn thread(pool: &PgPool, thread_id: String) -> Result<Thread, ServerEr
} }
} }
let body = Body::Html(Html { let body = Body::Html(Html {
html: html.to_string(), html,
content_tree: "".to_string(), content_tree: "".to_string(),
}); });
let title = r.title.unwrap_or("NO TITLE".to_string()); let title = r.title.unwrap_or("NO TITLE".to_string());

View File

@ -22,6 +22,48 @@
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@700&display=swap" rel="stylesheet">
<style>
:root {
--active-brightness: 0.85;
--border-radius: 5px;
--box-shadow: 2px 2px 10px;
--color-accent: #118bee15;
--color-bg: #fff;
--color-bg-secondary: #e9e9e9;
--color-link: #118bee;
--color-secondary: #920de9;
--color-secondary-accent: #920de90b;
--color-shadow: #f4f4f4;
--color-table: #118bee;
--color-text: #000;
--color-text-secondary: #999;
--color-scrollbar: #cacae8;
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
--hover-brightness: 1.2;
--justify-important: center;
--justify-normal: left;
--line-height: 1.5;
--width-card: 285px;
--width-card-medium: 460px;
--width-card-wide: 800px;
--width-content: 1080px;
}
@media (prefers-color-scheme: dark) {
:root[color-mode="user"] {
--color-accent: #0097fc4f;
--color-bg: #333;
--color-bg-secondary: #555;
--color-link: #0097fc;
--color-secondary: #e20de9;
--color-secondary-accent: #e20de94f;
--color-shadow: #bbbbbb20;
--color-table: #0097fc;
--color-text: #f7f7f7;
--color-text-secondary: #aaa;
}
}
</style>
</head> </head>
<body> <body>