Skip to content

Commit

Permalink
wip!
Browse files Browse the repository at this point in the history
  • Loading branch information
matze committed Feb 4, 2025
1 parent 23f2882 commit eeaabd4
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 331 deletions.
2 changes: 1 addition & 1 deletion src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::time::Duration;
pub struct Metadata<'a> {
pub title: String,
pub version: &'a str,
pub highlight: &'a highlight::Data<'a>,
pub highlight: &'a highlight::Data,
}

pub const DEFAULT_HTTP_TIMEOUT: Duration = Duration::from_secs(5);
Expand Down
114 changes: 2 additions & 112 deletions src/highlight.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
use crate::db::read::Entry;
use crate::env;
use crate::errors::Error;
use askama::Template;
use sha2::{Digest, Sha256};
use std::cmp::Ordering;
use std::io::Cursor;
use std::sync::LazyLock;
use syntect::highlighting::{Color, ThemeSet};
use syntect::html::{css_for_theme_with_class_style, line_tokens_to_classed_spans, ClassStyle};
use syntect::html::{line_tokens_to_classed_spans, ClassStyle};
use syntect::parsing::{ParseState, ScopeStack, SyntaxReference, SyntaxSet};
use syntect::util::LinesWithEndings;
use two_face::theme::EmbeddedThemeName;

const HIGHLIGHT_LINE_LENGTH_CUTOFF: usize = 2048;

Expand All @@ -25,109 +20,10 @@ pub enum Theme {
Solarized,
}

// #[derive(Template)]
// #[template(path = "style.css", escape = "none")]
// struct StyleCss {
// light_background: Color,
// light_foreground: Color,
// dark_background: Color,
// dark_foreground: Color,
// }

#[derive(Clone)]
pub struct Html(String);

pub static LIGHT_THEME: LazyLock<syntect::highlighting::Theme> = LazyLock::new(|| {
let theme_set = two_face::theme::extra();

match *env::THEME {
Theme::Ayu => {
let theme = include_str!("themes/ayu-light.tmTheme");
ThemeSet::load_from_reader(&mut Cursor::new(theme)).expect("loading theme")
}
Theme::Base16Ocean => theme_set.get(EmbeddedThemeName::Base16OceanLight).clone(),
Theme::Coldark => theme_set.get(EmbeddedThemeName::ColdarkCold).clone(),
Theme::Gruvbox => theme_set.get(EmbeddedThemeName::GruvboxLight).clone(),
Theme::Monokai => theme_set
.get(EmbeddedThemeName::MonokaiExtendedLight)
.clone(),
Theme::Onehalf => theme_set.get(EmbeddedThemeName::OneHalfLight).clone(),
Theme::Solarized => theme_set.get(EmbeddedThemeName::SolarizedLight).clone(),
}
});

pub static LIGHT_CSS: LazyLock<String> = LazyLock::new(|| {
css_for_theme_with_class_style(&LIGHT_THEME, ClassStyle::Spaced).expect("generating CSS")
});

pub static DARK_THEME: LazyLock<syntect::highlighting::Theme> = LazyLock::new(|| {
let theme_set = two_face::theme::extra();

match *env::THEME {
Theme::Ayu => {
let theme = include_str!("themes/ayu-dark.tmTheme");
ThemeSet::load_from_reader(&mut Cursor::new(theme)).expect("loading theme")
}
Theme::Base16Ocean => theme_set.get(EmbeddedThemeName::Base16OceanDark).clone(),
Theme::Coldark => theme_set.get(EmbeddedThemeName::ColdarkDark).clone(),
Theme::Gruvbox => theme_set.get(EmbeddedThemeName::GruvboxDark).clone(),
Theme::Monokai => theme_set.get(EmbeddedThemeName::MonokaiExtended).clone(),
Theme::Onehalf => theme_set.get(EmbeddedThemeName::OneHalfDark).clone(),
Theme::Solarized => theme_set.get(EmbeddedThemeName::SolarizedDark).clone(),
}
});

pub static DARK_CSS: LazyLock<String> = LazyLock::new(|| {
css_for_theme_with_class_style(&DARK_THEME, ClassStyle::Spaced).expect("generating CSS")
});

trait ColorExt {
fn new(r: u8, g: u8, b: u8, a: u8) -> Self;
}

impl ColorExt for Color {
fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
Self { r, g, b, a }
}
}

pub static STYLE_CSS: LazyLock<String> = LazyLock::new(|| {
let light_foreground = LIGHT_THEME
.settings
.foreground
.unwrap_or(Color::new(3, 3, 3, 100));

let light_background = LIGHT_THEME
.settings
.background
.unwrap_or(Color::new(250, 250, 250, 100));

let dark_foreground = DARK_THEME
.settings
.foreground
.unwrap_or(Color::new(230, 225, 207, 100));

let dark_background = DARK_THEME
.settings
.background
.unwrap_or(Color::new(15, 20, 25, 100));

String::from("hello")
//
// let style = StyleCss {
// light_background,
// light_foreground,
// dark_background,
// dark_foreground,
// };
//
// style.render().expect("rendering style css")
});

pub static DATA: LazyLock<Data> = LazyLock::new(|| {
let style = Hashed::new("style", "css", &STYLE_CSS);
let index = Hashed::new("index", "js", include_str!("javascript/index.js"));
let paste = Hashed::new("paste", "js", include_str!("javascript/paste.js"));
let syntax_set = two_face::syntax::extra_newlines();
let mut syntaxes = syntax_set.syntaxes().to_vec();
syntaxes.sort_by(|a, b| {
Expand All @@ -138,9 +34,6 @@ pub static DATA: LazyLock<Data> = LazyLock::new(|| {
});

Data {
style,
index,
paste,
syntax_set,
syntaxes,
}
Expand All @@ -152,10 +45,7 @@ pub struct Hashed<'a> {
pub content: &'a str,
}

pub struct Data<'a> {
pub style: Hashed<'a>,
pub index: Hashed<'a>,
pub paste: Hashed<'a>,
pub struct Data {
pub syntax_set: SyntaxSet,
pub syntaxes: Vec<SyntaxReference>,
}
Expand Down
21 changes: 18 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ use crate::cache::Cache;
use crate::db::Database;
use crate::errors::Error;
use axum::extract::{DefaultBodyLimit, FromRef, Request, State};
use axum::http::{HeaderName, HeaderValue, StatusCode};
use axum::http::{HeaderName, HeaderValue};
use axum::middleware::{from_fn, Next};
use axum::response::{IntoResponse, Response};
use axum::routing::get;
use axum::Router;
use axum_extra::extract::cookie::Key;
use highlight::DARK_CSS;
use http::header::{
CONTENT_SECURITY_POLICY, REFERRER_POLICY, SERVER, X_CONTENT_TYPE_OPTIONS, X_FRAME_OPTIONS,
X_XSS_PROTECTION,
Expand Down Expand Up @@ -42,6 +41,8 @@ static PACKAGE_NAME: &str = env!("CARGO_PKG_NAME");
pub struct Assets {
favicon: Asset,
css: assets::CssAssets,
index_js: Asset,
paste_js: Asset,
}

#[derive(Clone)]
Expand Down Expand Up @@ -142,6 +143,10 @@ async fn light_css(State(state): State<AppState>) -> impl IntoResponse {
state.assets.css.light.clone()
}

async fn index_js(State(state): State<AppState>) -> impl IntoResponse {
state.assets.index_js.clone()
}

async fn start() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();

Expand Down Expand Up @@ -170,14 +175,24 @@ async fn start() -> Result<(), Box<dyn std::error::Error>> {
include_bytes!("../assets/favicon.png").to_vec(),
),
css: CssAssets::new(&env::THEME),
index_js: Asset::new_hashed(
"index",
mime::TEXT_JAVASCRIPT,
include_bytes!("javascript/index.js").to_vec(),
),
paste_js: Asset::new_hashed(
"paste",
mime::TEXT_JAVASCRIPT,
include_bytes!("javascript/paste.js").to_vec(),
),
};
println!("{}", assets.css.style.route());

let app = routes::routes()
.route(assets.favicon.route(), get(favicon))
.route(assets.css.style.route(), get(style_css))
.route(assets.css.dark.route(), get(dark_css))
.route(assets.css.light.route(), get(light_css))
.route(assets.index_js.route(), get(index_js))
.layer(
ServiceBuilder::new()
.layer(DefaultBodyLimit::max(max_body_size))
Expand Down
19 changes: 17 additions & 2 deletions src/pages.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::cache::Key as CacheKey;
use crate::highlight::Html;
use crate::routes::paste::{Format, QueryData};
use crate::Assets;
use crate::{assets, env};
use crate::{env, errors, Assets};
use askama::Template;
use axum::http::StatusCode;
use std::num::NonZero;
Expand All @@ -22,6 +21,22 @@ pub struct Error<'a> {
/// Error response carrying a status code and the page itself.
pub type ErrorResponse<'a> = (StatusCode, Error<'a>);

/// Create an error response from `error` consisting of [`StatusCode`] derive from `error` as well
/// as a rendered page with a description.
pub fn make_error(error: errors::Error, assets: Arc<Assets>) -> ErrorResponse<'static> {
let description = error.to_string();

(
error.into(),
Error {
meta: &env::METADATA,
base_path: &env::BASE_PATH,
description,
assets,
},
)
}

impl Error<'_> {
/// Create new [`Error`] from `description`.
pub fn new(description: String, assets: Arc<Assets>) -> Self {
Expand Down
57 changes: 0 additions & 57 deletions src/routes/assets.rs
Original file line number Diff line number Diff line change
@@ -1,59 +1,2 @@
use crate::highlight::{self, DATA};
use crate::{AppState, Router};
use axum::response::IntoResponse;
use axum::routing::get;
use axum_extra::{headers, TypedHeader};
use bytes::Bytes;
use std::time::Duration;

/// Asset maximum age of six months.
const MAX_AGE: Duration = Duration::from_secs(60 * 60 * 24 * 30 * 6);

fn css_from(content: &'static str) -> impl IntoResponse {
(
(
TypedHeader(headers::ContentType::from(mime::TEXT_CSS)),
TypedHeader(headers::CacheControl::new().with_max_age(MAX_AGE)),
),
content,
)
}

fn js_from(content: &'static str) -> impl IntoResponse {
(
(
TypedHeader(headers::ContentType::from(mime::TEXT_JAVASCRIPT)),
TypedHeader(headers::CacheControl::new().with_max_age(MAX_AGE)),
),
content,
)
}

pub fn routes() -> Router<AppState> {
let style_url = format!("/{}", &DATA.style.name);
let index_url = format!("/{}", &DATA.index.name);
let paste_url = format!("/{}", &DATA.paste.name);

Router::new()
// .route(
// "/favicon.ico",
// get(|| async {
// (
// TypedHeader(headers::ContentType::png()),
// TypedHeader(headers::CacheControl::new().with_max_age(MAX_AGE)),
// Bytes::from_static(include_bytes!("../../assets/favicon.png")),
// )
// }),
// )
// .route(&style_url, get(|| async { css_from(DATA.style.content) }))
// .route(
// "/dark.css",
// get(|| async { css_from(highlight::DARK_CSS.as_str()) }),
// )
// .route(
// "/light.css",
// get(|| async { css_from(highlight::LIGHT_CSS.as_str()) }),
// )
.route(&index_url, get(|| async { js_from(DATA.index.content) }))
.route(&paste_url, get(|| async { js_from(DATA.paste.content) }))
}
Loading

0 comments on commit eeaabd4

Please sign in to comment.