Inline mvp and custom override CSS when rendering RSS posts
This commit is contained in:
parent
359e798cfa
commit
530bd8e350
8
server/src/custom.css
Normal file
8
server/src/custom.css
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
pre {
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background-color: var(--color-bg-secondary);
|
||||||
|
}
|
||||||
@ -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("<")
|
html.starts_with("<")
|
||||||
}
|
}
|
||||||
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()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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());
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user