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
trait Transformer {
fn should_run(&self, input: &str) -> bool;
// TODO: should input be something like `html_escape` uses:
fn should_run(&self, _html: &str) -> bool {
true
}
// TODO: should html be something like `html_escape` uses:
// <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
@ -35,22 +37,50 @@ struct SanitizeHtml<'a> {
}
impl<'a> Transformer for SanitizeHtml<'a> {
fn should_run(&self, _input: &str) -> bool {
true
}
fn transform(&self, input: &str) -> Result<String, TransformError> {
Ok(sanitize_html(input, self.cid_prefix, self.base_url)?)
fn transform(&self, html: &str) -> Result<String, TransformError> {
Ok(sanitize_html(html, self.cid_prefix, self.base_url)?)
}
}
struct EscapeHtml;
impl Transformer for EscapeHtml {
fn should_run(&self, input: &str) -> bool {
input.starts_with("&lt")
fn should_run(&self, html: &str) -> bool {
html.starts_with("&lt")
}
fn transform(&self, input: &str) -> Result<String, TransformError> {
Ok(html_escape::decode_html_entities(input).to_string())
fn transform(&self, html: &str) -> Result<String, TransformError> {
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 */
: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;
}
}
/* :root content stored in client side index.html */
html {
scroll-behavior: smooth;
@ -425,8 +386,7 @@ textarea {
}
input[type="text"],
input[type="password"]
textarea {
input[type="password"] textarea {
width: calc(100% - 1.6rem);
}

View File

@ -14,7 +14,7 @@ const THREAD_PREFIX: &'static str = "news:";
use crate::{
error::ServerError,
graphql::{Body, Email, Html, Message, Tag, Thread, ThreadSummary},
EscapeHtml, SanitizeHtml, Transformer,
EscapeHtml, InlineStyle, SanitizeHtml, Transformer,
};
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
let tranformers: Vec<Box<dyn Transformer>> = vec![
Box::new(EscapeHtml),
Box::new(InlineStyle),
Box::new(SanitizeHtml {
cid_prefix: "",
base_url: &link,
@ -224,7 +225,7 @@ pub async fn thread(pool: &PgPool, thread_id: String) -> Result<Thread, ServerEr
}
}
let body = Body::Html(Html {
html: html.to_string(),
html,
content_tree: "".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.gstatic.com" crossorigin>
<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>
<body>