diff --git a/Cargo.lock b/Cargo.lock
index 634eec6..a93d755 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1399,6 +1399,7 @@ dependencies = [
"ring",
"serde",
"serde_regex",
+ "text-template",
"url",
]
@@ -1563,6 +1564,12 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "text-template"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51bcc3e9514cba67c087126b18600010c7c29b0cb51a6f6bc75e5058c2369bba"
+
[[package]]
name = "time"
version = "0.3.17"
diff --git a/Cargo.toml b/Cargo.toml
index 565b496..95a7180 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,6 +34,7 @@ humantime-serde = "1.1.1"
glob = "0.3.1"
ring = "0.16.20"
hotwatch = "0.4.5"
+text-template = "0.1.0"
[dependencies.config]
version = "0.13.3"
diff --git a/README.md b/README.md
index 0beecd2..04b73c1 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
-**Rustypaste** is a minimal file upload/pastebin service.
+**Rustypaste-pretty** is a minimal file upload/pastebin service with client side highlighting provided by highlight.js.
+
+Just add `?pretty` to the end of a link to highlight!
```sh
$ echo "some text" > awesome.txt
diff --git a/config.toml b/config.toml
index a21a040..a169a49 100644
--- a/config.toml
+++ b/config.toml
@@ -2,12 +2,13 @@
refresh_rate="1s"
[server]
-address="127.0.0.1:8000"
+address="127.0.0.1:8020"
#workers=4
max_content_length="10MB"
upload_path="./upload"
timeout="30s"
expose_version=false
+style="monokai"
landing_page="""Submit files via HTTP POST here:
curl -F 'file=@example.txt' "
This will return the finished URL.
@@ -42,5 +43,10 @@ mime_blacklist = [
"application/java-archive",
"application/java-vm"
]
+
duplicate_files = true
delete_expired_files = { enabled = true, interval = "1h" }
+
+[paste.highlight_override]
+# For example, to force markdown rather than using highlight.js's autodetection
+#"text/markdown" = "markdown"
diff --git a/src/config.rs b/src/config.rs
index ca0aec0..3bc5b8e 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -2,6 +2,7 @@ use crate::mime::MimeMatcher;
use crate::random::RandomURLConfig;
use byte_unit::Byte;
use config::{self, ConfigError};
+use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::time::Duration;
@@ -45,6 +46,8 @@ pub struct ServerConfig {
pub landing_page: Option,
/// Expose version.
pub expose_version: Option,
+ /// Highlight.js style
+ pub style: Option,
}
/// Paste configuration.
@@ -64,6 +67,9 @@ pub struct PasteConfig {
pub duplicate_files: Option,
/// Delete expired files.
pub delete_expired_files: Option,
+ /// Highlight override.
+ #[serde(default)]
+ pub highlight_override: HashMap,
}
/// Cleanup configuration.
@@ -80,6 +86,7 @@ impl Config {
/// Parses the config file and returns the values.
pub fn parse(path: &Path) -> Result {
config::Config::builder()
+ .set_default("style", "default").unwrap()
.add_source(config::File::from(path))
.add_source(config::Environment::default().separator("__"))
.build()?
diff --git a/src/pretty.html b/src/pretty.html
new file mode 100644
index 0000000..1fa8779
--- /dev/null
+++ b/src/pretty.html
@@ -0,0 +1,23 @@
+
+
+
+ ${file}
+
+
+
+
+
+
+
+
+
diff --git a/src/server.rs b/src/server.rs
index 7993562..3f99765 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -6,6 +6,7 @@ use crate::mime as mime_util;
use crate::paste::{Paste, PasteType};
use crate::util;
use crate::AUTH_TOKEN_ENV;
+use text_template::*;
use actix_files::NamedFile;
use actix_multipart::Multipart;
use actix_web::{error, get, post, web, Error, HttpRequest, HttpResponse};
@@ -16,7 +17,9 @@ use serde::Deserialize;
use std::convert::TryFrom;
use std::env;
use std::fs;
+use std::str;
use std::sync::RwLock;
+use std::collections::HashMap;
/// Shows the landing page.
#[get("/")]
@@ -51,6 +54,7 @@ async fn serve(
let config = config
.read()
.map_err(|_| error::ErrorInternalServerError("cannot acquire config"))?;
+
let path = config.server.upload_path.join(&*file);
let mut path = util::glob_match_file(path)?;
let mut paste_type = PasteType::File;
@@ -78,6 +82,23 @@ async fn serve(
mime_util::get_mime_type(&config.paste.mime_override, file.to_string())
.map_err(error::ErrorInternalServerError)?
};
+
+ if request.query_string() == "pretty" {
+ let mut values = HashMap::new();
+ let tmpl_bytes = str::from_utf8(include_bytes!("pretty.html")).unwrap();
+ let tmpl = Template::from(tmpl_bytes);
+ values.insert("file", file.as_str());
+ values.insert("style", match &config.server.style {
+ Some(style) => style.as_str(),
+ None => "default",
+ });
+ let mime_str = mime_type.to_string();
+ let overrides = &config.paste.highlight_override;
+ values.insert("type", if overrides.contains_key(&mime_str) { overrides[&mime_str].as_str() } else { "" });
+ let rendered = tmpl.fill_in(&values);
+ return Ok(HttpResponse::Ok().body(rendered.to_string()))
+ }
+
let response = NamedFile::open(&path)?
.disable_content_disposition()
.set_content_type(mime_type)