Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Added

- Rosé Pine theme, selectable with `WASTEBIN_THEME=rosepine`.

### Changed

- Top-align Markdown-rendered table cells.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ to released versions here:
* compresses pastes using [zstd](https://github.com/facebook/zstd)
* syntax highlighting for > 170 languages with [syntect](https://github.com/trishume/syntect)
* renders Markdown pastes to HTML, including GitHub-flavored tables, task lists and admonitions
* comes with [eight color themes](https://matze.github.io/wastebin/) in light and dark mode
* comes with [nine color themes](https://matze.github.io/wastebin/) in light and dark mode
* encrypts entries using ChaCha20Poly1305 and argon2 hashed passwords
* allows deletion after expiration, after reading or by anonymous owners
* shows QR code to browse a paste's URL on mobile devices
Expand Down Expand Up @@ -197,7 +197,7 @@ run-time behavior:
| `WASTEBIN_PASSWORD_SALT` | Salt used to hash user passwords used for encrypting pastes. | `somesalt` |
| `WASTEBIN_PASTE_EXPIRATIONS` | Possible paste expirations as a comma-separated list of seconds or values with duration magnitudes (`s`, `m`, `h`, `d`, `M`, `y` for seconds, minutes, hours, days, months and years respectively). Appending `=d` to one of the value makes it the default selection. | see [here](https://github.com/matze/wastebin/blob/eb61c78506a165605f145e8374ed64822405eda0/crates/wastebin_server/src/env.rs#L166) |
| `WASTEBIN_SIGNING_KEY` | Key to sign cookies. Must be at least 64 bytes long. | Random key generated at startup, i.e. cookies will become invalid after restarts and paste creators will not be able to delete their pastes. |
| `WASTEBIN_THEME` | Theme colors, one of `ayu`, `base16ocean`, `catppuccin`, `coldark`, `gruvbox`, `monokai`, `onehalf`, `solarized`. See [this page](https://matze.github.io/wastebin/) for a preview. | `ayu` |
| `WASTEBIN_THEME` | Theme colors, one of `ayu`, `base16ocean`, `catppuccin`, `coldark`, `gruvbox`, `monokai`, `onehalf`, `rosepine`, `solarized`. See [this page](https://matze.github.io/wastebin/) for a preview. | `ayu` |
| `WASTEBIN_TITLE` | HTML page title. | `wastebin` |
| `WASTEBIN_UNIX_SOCKET_PATH` | Path to a Unix socket to accept connections from. | |
| `RUST_LOG` | Log level. Besides the typical `trace`, `debug`, `info` etc. keys, you can also set the `tower_http` key to a log level to get additional request and response logs. | |
Expand Down
38 changes: 38 additions & 0 deletions crates/wastebin_highlight/src/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub enum Theme {
Gruvbox,
Monokai,
Onehalf,
RosePine,
Solarized,
}

Expand All @@ -35,6 +36,7 @@ impl FromStr for Theme {
"gruvbox" => Ok(Theme::Gruvbox),
"monokai" => Ok(Theme::Monokai),
"onehalf" => Ok(Theme::Onehalf),
"rosepine" => Ok(Theme::RosePine),
"solarized" => Ok(Theme::Solarized),
_ => Err(ParseThemeNameError),
}
Expand Down Expand Up @@ -64,6 +66,10 @@ impl Theme {
.get(EmbeddedThemeName::MonokaiExtendedLight)
.clone(),
Theme::Onehalf => theme_set.get(EmbeddedThemeName::OneHalfLight).clone(),
Theme::RosePine => {
let theme = include_str!("../themes/rose-pine-dawn.tmTheme");
ThemeSet::load_from_reader(&mut Cursor::new(theme)).expect("loading theme")
}
Theme::Solarized => theme_set.get(EmbeddedThemeName::SolarizedLight).clone(),
}
}
Expand All @@ -88,6 +94,10 @@ impl Theme {
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::RosePine => {
let theme = include_str!("../themes/rose-pine.tmTheme");
ThemeSet::load_from_reader(&mut Cursor::new(theme)).expect("loading theme")
}
Theme::Solarized => theme_set.get(EmbeddedThemeName::SolarizedDark).clone(),
}
}
Expand All @@ -103,6 +113,7 @@ impl Theme {
Theme::Gruvbox => "gruvbox",
Theme::Monokai => "monokai",
Theme::Onehalf => "onehalf",
Theme::RosePine => "rosepine",
Theme::Solarized => "solarized",
}
}
Expand All @@ -128,3 +139,30 @@ fn combined_css(color_scheme: &str, theme: &highlighting::Theme) -> Vec<u8> {
)
.into_bytes()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn rose_pine_round_trips() -> Result<(), Box<dyn std::error::Error>> {
let theme: Theme = "rosepine".parse()?;
assert_eq!(theme.name(), "rosepine");
Ok(())
}

#[test]
fn rose_pine_bundled_files_load() -> Result<(), Box<dyn std::error::Error>> {
let theme: Theme = "rosepine".parse()?;

// The bundled Dawn and main variants carry these background colors, so seeing them in the
// generated CSS proves the right file ended up on each side.
let light = String::from_utf8(theme.light_css())?;
assert!(light.contains("rgb(250, 244, 237"));

let dark = String::from_utf8(theme.dark_css())?;
assert!(dark.contains("rgb(25, 23, 36"));

Ok(())
}
}
Loading
Loading