mirror of
https://github.com/amigan/rustypaste-pretty.git
synced 2024-11-21 11:59:48 -05:00
Add prettyness.
This commit is contained in:
parent
9ead53097e
commit
3789caf68f
7 changed files with 70 additions and 19 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -2385,6 +2385,7 @@ dependencies = [
|
||||||
"shuttle-actix-web",
|
"shuttle-actix-web",
|
||||||
"shuttle-runtime",
|
"shuttle-runtime",
|
||||||
"shuttle-static-folder",
|
"shuttle-static-folder",
|
||||||
|
"text-template",
|
||||||
"tokio",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
@ -2778,6 +2779,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "text-template"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51bcc3e9514cba67c087126b18600010c7c29b0cb51a6f6bc75e5058c2369bba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.40"
|
version = "1.0.40"
|
||||||
|
|
|
@ -52,6 +52,7 @@ shuttle-actix-web = { version = "0.16.0", optional = true }
|
||||||
shuttle-runtime = { version = "0.16.0", optional = true }
|
shuttle-runtime = { version = "0.16.0", optional = true }
|
||||||
shuttle-static-folder = { version = "0.16.0", optional = true }
|
shuttle-static-folder = { version = "0.16.0", optional = true }
|
||||||
tokio = { version = "1.28.1", optional = true }
|
tokio = { version = "1.28.1", optional = true }
|
||||||
|
text-template = "0.1.0"
|
||||||
|
|
||||||
[dependencies.config]
|
[dependencies.config]
|
||||||
version = "0.13.3"
|
version = "0.13.3"
|
||||||
|
@ -72,6 +73,7 @@ actix-rt = "2.8.0"
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 0
|
opt-level = 0
|
||||||
debug = true
|
debug = true
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
[profile.test]
|
[profile.test]
|
||||||
opt-level = 0
|
opt-level = 0
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
[![Docker Builds](https://img.shields.io/github/actions/workflow/status/orhun/rustypaste/docker.yml?style=flat&labelColor=823213&color=2c2c2c&label=docker&logo=Docker&logoColor=white)](https://hub.docker.com/r/orhunp/rustypaste)
|
[![Docker Builds](https://img.shields.io/github/actions/workflow/status/orhun/rustypaste/docker.yml?style=flat&labelColor=823213&color=2c2c2c&label=docker&logo=Docker&logoColor=white)](https://hub.docker.com/r/orhunp/rustypaste)
|
||||||
[![Documentation](https://img.shields.io/docsrs/rustypaste?style=flat&labelColor=823213&color=2c2c2c&logo=Rust&logoColor=white)](https://docs.rs/rustypaste/)
|
[![Documentation](https://img.shields.io/docsrs/rustypaste?style=flat&labelColor=823213&color=2c2c2c&logo=Rust&logoColor=white)](https://docs.rs/rustypaste/)
|
||||||
|
|
||||||
**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
|
```sh
|
||||||
$ echo "some text" > awesome.txt
|
$ echo "some text" > awesome.txt
|
||||||
|
|
25
config.toml
25
config.toml
|
@ -2,34 +2,18 @@
|
||||||
refresh_rate = "1s"
|
refresh_rate = "1s"
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
address = "127.0.0.1:8000"
|
address="127.0.0.1:8020"
|
||||||
#url = "https://rustypaste.shuttleapp.rs"
|
#url = "https://rustypaste.shuttleapp.rs"
|
||||||
#workers=4
|
#workers=4
|
||||||
max_content_length = "10MB"
|
max_content_length = "10MB"
|
||||||
upload_path = "./upload"
|
upload_path = "./upload"
|
||||||
timeout = "30s"
|
timeout = "30s"
|
||||||
expose_version = false
|
expose_version = false
|
||||||
|
style="monokai"
|
||||||
landing_page = """
|
landing_page = """
|
||||||
┬─┐┬ ┬┌─┐┌┬┐┬ ┬┌─┐┌─┐┌─┐┌┬┐┌─┐
|
┬─┐┬ ┬┌─┐┌┬┐┬ ┬┌─┐┌─┐┌─┐┌┬┐┌─┐
|
||||||
├┬┘│ │└─┐ │ └┬┘├─┘├─┤└─┐ │ ├┤
|
├┬┘│ │└─┐ │ └┬┘├─┘├─┤└─┐ │ ├┤
|
||||||
┴└─└─┘└─┘ ┴ ┴ ┴ ┴ ┴└─┘ ┴ └─┘
|
┴└─└─┘└─┘ ┴ ┴ ┴ ┴ ┴└─┘ ┴ └─┘
|
||||||
|
|
||||||
Submit files via HTTP POST here:
|
|
||||||
curl -F 'file=@example.txt' <server>
|
|
||||||
This will return the URL of the uploaded file.
|
|
||||||
|
|
||||||
The server administrator might remove any pastes that they do not personally
|
|
||||||
want to host.
|
|
||||||
|
|
||||||
If you are the server administrator and want to change this page, just go
|
|
||||||
into your config file and change it! If you change the expiry time, it is
|
|
||||||
recommended that you do.
|
|
||||||
|
|
||||||
By default, pastes expire every hour. The server admin may or may not have
|
|
||||||
changed this.
|
|
||||||
|
|
||||||
Check out the GitHub repository at https://github.com/orhun/rustypaste
|
|
||||||
Command line tool is available at https://github.com/orhun/rustypaste-cli
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[paste]
|
[paste]
|
||||||
|
@ -50,6 +34,11 @@ mime_blacklist = [
|
||||||
"application/java-archive",
|
"application/java-archive",
|
||||||
"application/java-vm",
|
"application/java-vm",
|
||||||
]
|
]
|
||||||
|
|
||||||
duplicate_files = true
|
duplicate_files = true
|
||||||
# default_expiry = "1h"
|
# default_expiry = "1h"
|
||||||
delete_expired_files = { enabled = true, interval = "1h" }
|
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"
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::mime::MimeMatcher;
|
||||||
use crate::random::RandomURLConfig;
|
use crate::random::RandomURLConfig;
|
||||||
use byte_unit::Byte;
|
use byte_unit::Byte;
|
||||||
use config::{self, ConfigError};
|
use config::{self, ConfigError};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -47,6 +48,8 @@ pub struct ServerConfig {
|
||||||
pub landing_page: Option<String>,
|
pub landing_page: Option<String>,
|
||||||
/// Expose version.
|
/// Expose version.
|
||||||
pub expose_version: Option<bool>,
|
pub expose_version: Option<bool>,
|
||||||
|
/// Highlight.js style
|
||||||
|
pub style: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Paste configuration.
|
/// Paste configuration.
|
||||||
|
@ -69,6 +72,9 @@ pub struct PasteConfig {
|
||||||
pub default_expiry: Option<Duration>,
|
pub default_expiry: Option<Duration>,
|
||||||
/// Delete expired files.
|
/// Delete expired files.
|
||||||
pub delete_expired_files: Option<CleanupConfig>,
|
pub delete_expired_files: Option<CleanupConfig>,
|
||||||
|
/// Highlight override.
|
||||||
|
#[serde(default)]
|
||||||
|
pub highlight_override: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cleanup configuration.
|
/// Cleanup configuration.
|
||||||
|
@ -85,6 +91,7 @@ impl Config {
|
||||||
/// Parses the config file and returns the values.
|
/// Parses the config file and returns the values.
|
||||||
pub fn parse(path: &Path) -> Result<Config, ConfigError> {
|
pub fn parse(path: &Path) -> Result<Config, ConfigError> {
|
||||||
config::Config::builder()
|
config::Config::builder()
|
||||||
|
.set_default("style", "default").unwrap()
|
||||||
.add_source(config::File::from(path))
|
.add_source(config::File::from(path))
|
||||||
.add_source(config::Environment::default().separator("__"))
|
.add_source(config::Environment::default().separator("__"))
|
||||||
.build()?
|
.build()?
|
||||||
|
|
23
src/pretty.html
Normal file
23
src/pretty.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>${file}</title>
|
||||||
|
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/${style}.min.css">
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var xhr= new XMLHttpRequest();
|
||||||
|
xhr.open('GET', '${file}', true);
|
||||||
|
xhr.onreadystatechange= function() {
|
||||||
|
if (this.readyState!==4) return;
|
||||||
|
if (this.status!==200) return; // or whatever error handling you want
|
||||||
|
document.getElementById('h').innerHTML= this.responseText;
|
||||||
|
hljs.highlightAll();
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre><code id="h" class="${type}">
|
||||||
|
</code></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -6,6 +6,7 @@ use crate::mime as mime_util;
|
||||||
use crate::paste::{Paste, PasteType};
|
use crate::paste::{Paste, PasteType};
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use crate::AUTH_TOKEN_ENV;
|
use crate::AUTH_TOKEN_ENV;
|
||||||
|
use text_template::*;
|
||||||
use actix_files::NamedFile;
|
use actix_files::NamedFile;
|
||||||
use actix_multipart::Multipart;
|
use actix_multipart::Multipart;
|
||||||
use actix_web::{error, get, post, web, Error, HttpRequest, HttpResponse};
|
use actix_web::{error, get, post, web, Error, HttpRequest, HttpResponse};
|
||||||
|
@ -16,7 +17,9 @@ use serde::Deserialize;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::str;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
/// Shows the landing page.
|
/// Shows the landing page.
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
|
@ -53,6 +56,7 @@ async fn serve(
|
||||||
let config = config
|
let config = config
|
||||||
.read()
|
.read()
|
||||||
.map_err(|_| error::ErrorInternalServerError("cannot acquire config"))?;
|
.map_err(|_| error::ErrorInternalServerError("cannot acquire config"))?;
|
||||||
|
|
||||||
let path = config.server.upload_path.join(&*file);
|
let path = config.server.upload_path.join(&*file);
|
||||||
let mut path = util::glob_match_file(path)?;
|
let mut path = util::glob_match_file(path)?;
|
||||||
let mut paste_type = PasteType::File;
|
let mut paste_type = PasteType::File;
|
||||||
|
@ -80,6 +84,23 @@ async fn serve(
|
||||||
mime_util::get_mime_type(&config.paste.mime_override, file.to_string())
|
mime_util::get_mime_type(&config.paste.mime_override, file.to_string())
|
||||||
.map_err(error::ErrorInternalServerError)?
|
.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().content_type(mime::TEXT_HTML).body(rendered.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
let response = NamedFile::open(&path)?
|
let response = NamedFile::open(&path)?
|
||||||
.disable_content_disposition()
|
.disable_content_disposition()
|
||||||
.set_content_type(mime_type)
|
.set_content_type(mime_type)
|
||||||
|
|
Loading…
Reference in a new issue