Merge branch 'master' into public-path
This commit is contained in:
commit
43061699f5
11 changed files with 102 additions and 14 deletions
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
debug/
|
||||
target/
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
|
||||
pasta_data/*
|
|
@ -30,4 +30,7 @@ COPY --from=build \
|
|||
/app/target/release/microbin \
|
||||
/usr/bin/microbin
|
||||
|
||||
# Expose webport used for the webserver to the docker runtime
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["microbin"]
|
18
README.MD
18
README.MD
|
@ -11,8 +11,8 @@
|
|||
MicroBin is a super tiny, feature rich, configurable, self-contained and self-hosted paste bin web application. It is very easy to set up and use, and will only require a few megabytes of memory and disk storage. It takes only a couple minutes to set it up, why not give it a try now?
|
||||
|
||||
[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/szabodanika/microbin)
|
||||
|
||||
Or install from Cargo:
|
||||
|
||||
Or install from Cargo:
|
||||
|
||||
`cargo install microbin`
|
||||
|
||||
|
@ -37,7 +37,7 @@ And run with your custom configuration:
|
|||
- Automatic dark mode (follows system preferences)
|
||||
- Very little CSS and absolutely no JS (see [water.css](https://github.com/kognise/water.css))
|
||||
- Most of the above can be toggled on and off!
|
||||
|
||||
|
||||
## 1 Usage
|
||||
|
||||
### What is a "pasta" anyway?
|
||||
|
@ -222,7 +222,7 @@ server {
|
|||
listen 443 ssl; # managed by Certbot
|
||||
|
||||
server_name microbin.myserver.com;
|
||||
|
||||
|
||||
location / {
|
||||
# Make sure to change the port if you are not running MicroBin at 8080!
|
||||
proxy_pass http://127.0.0.1:8080$request_uri;
|
||||
|
@ -234,7 +234,7 @@ server {
|
|||
|
||||
# Limit content size - I have 1GB because my MicroBin server is private, no one else will use it.
|
||||
client_max_body_size 1024M;
|
||||
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/microbin.myserver.com/fullchain.pem; # managed by Certbot
|
||||
ssl_certificate_key /etc/letsencrypt/live/microbin.myserver.com/privkey.pem; # managed by Certbot
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
||||
|
@ -259,7 +259,7 @@ Require password for HTTP Basic Authentication when visiting the service. Will n
|
|||
|
||||
Enables editable pastas. You will still be able to make finalised pastas but there will be an extra checkbox to make your new pasta editable from the pasta list or the pasta view page.
|
||||
|
||||
### --footer_text [TEXT]
|
||||
### --footer-text [TEXT]
|
||||
|
||||
Replaces the default footer text with your own. If you want to hide the footer, use --hide-footer instead.
|
||||
|
||||
|
@ -386,4 +386,8 @@ example.com {
|
|||
reverse_proxy http://127.0.0.1:31333
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### --no-file-upload
|
||||
|
||||
Disables and hides the file upload option in the UI.
|
||||
|
|
|
@ -65,6 +65,9 @@ pub struct Args {
|
|||
|
||||
#[clap(long, env="MICROBIN_WIDE")]
|
||||
pub wide: bool,
|
||||
|
||||
#[clap(short, long, env="MICROBIN_NO_FILE_UPLOAD")]
|
||||
pub no_file_upload: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -83,4 +86,3 @@ impl FromStr for PublicUrl {
|
|||
let uri = s.strip_suffix('/').unwrap_or(s).to_owned();
|
||||
Ok(PublicUrl(uri))
|
||||
}
|
||||
}
|
|
@ -106,6 +106,10 @@ pub async fn create(
|
|||
continue;
|
||||
}
|
||||
"file" => {
|
||||
if ARGS.no_file_upload {
|
||||
continue;
|
||||
}
|
||||
|
||||
let path = field.content_disposition().get_filename();
|
||||
|
||||
let path = match path {
|
||||
|
|
|
@ -8,6 +8,12 @@ struct WaterCSS<'a> {
|
|||
_marker: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "favicon.svg", escape = "none")]
|
||||
struct Favicon<'a> {
|
||||
_marker: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
#[get("/static/{resource}")]
|
||||
pub async fn static_resources(resource_id: web::Path<String>) -> HttpResponse {
|
||||
match resource_id.into_inner().as_str() {
|
||||
|
@ -18,6 +24,13 @@ pub async fn static_resources(resource_id: web::Path<String>) -> HttpResponse {
|
|||
.render()
|
||||
.unwrap(),
|
||||
),
|
||||
"favicon.svg" => HttpResponse::Ok().content_type("image/svg+xml").body(
|
||||
Favicon {
|
||||
_marker: Default::default(),
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
),
|
||||
_ => HttpResponse::NotFound().content_type("text/html").finish(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,10 @@ impl Pasta {
|
|||
pub fn content_not_highlighted(&self) -> String {
|
||||
html_highlight(&self.content, "txt")
|
||||
}
|
||||
|
||||
pub fn content_escaped(&self) -> String {
|
||||
self.content.replace("`", "\\`").replace("$", "\\$")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Pasta {
|
||||
|
|
5
templates/favicon.svg
Normal file
5
templates/favicon.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg width="63" height="73" viewBox="0 0 63 73" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.806818 72.1932L12.7045 0.636362H25.0455L19.9659 30.9773C19.6023 33.3409 19.7955 35.4205 20.5455 37.2159C21.3182 38.9886 22.5682 40.3864 24.2955 41.4091C26.0227 42.4091 28.1364 42.9091 30.6364 42.9091C33.1591 42.9091 35.4432 42.4091 37.4886 41.4091C39.5568 40.3864 41.2614 38.9886 42.6023 37.2159C43.9432 35.4205 44.7955 33.3409 45.1591 30.9773L50.2386 0.636362H62.6136L53.8864 53H41.8864L43.2159 45.4318H42.8068C41.1932 47.8409 39.1591 49.7159 36.7045 51.0568C34.25 52.375 31.6477 53.0341 28.8977 53.0341C26.2386 53.0341 23.8864 52.375 21.8409 51.0568C19.8182 49.7159 18.4205 47.8409 17.6477 45.4318H17.2386L12.7727 72.1932H0.806818Z" fill="#868686"/>
|
||||
<path d="M0.806818 72.1932L12.7045 0.636362H25.0455L19.9659 30.9773C19.6023 33.3409 19.7955 35.4205 20.5455 37.2159C21.3182 38.9886 22.5682 40.3864 24.2955 41.4091C26.0227 42.4091 28.1364 42.9091 30.6364 42.9091C33.1591 42.9091 35.4432 42.4091 37.4886 41.4091C39.5568 40.3864 41.2614 38.9886 42.6023 37.2159C43.9432 35.4205 44.7955 33.3409 45.1591 30.9773L50.2386 0.636362H62.6136L53.8864 53H41.8864L43.2159 45.4318H42.8068C41.1932 47.8409 39.1591 49.7159 36.7045 51.0568C34.25 52.375 31.6477 53.0341 28.8977 53.0341C26.2386 53.0341 23.8864 52.375 21.8409 51.0568C19.8182 49.7159 18.4205 47.8409 17.6477 45.4318H17.2386L12.7727 72.1932H0.806818Z" fill="#868686"/>
|
||||
<path d="M0.806818 72.1932L12.7045 0.636362H25.0455L19.9659 30.9773C19.6023 33.3409 19.7955 35.4205 20.5455 37.2159C21.3182 38.9886 22.5682 40.3864 24.2955 41.4091C26.0227 42.4091 28.1364 42.9091 30.6364 42.9091C33.1591 42.9091 35.4432 42.4091 37.4886 41.4091C39.5568 40.3864 41.2614 38.9886 42.6023 37.2159C43.9432 35.4205 44.7955 33.3409 45.1591 30.9773L50.2386 0.636362H62.6136L53.8864 53H41.8864L43.2159 45.4318H42.8068C41.1932 47.8409 39.1591 49.7159 36.7045 51.0568C34.25 52.375 31.6477 53.0341 28.8977 53.0341C26.2386 53.0341 23.8864 52.375 21.8409 51.0568C19.8182 49.7159 18.4205 47.8409 17.6477 45.4318H17.2386L12.7727 72.1932H0.806818Z" fill="#868686"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
|
@ -9,6 +9,7 @@
|
|||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
||||
{% if !args.pure_html %}
|
||||
<link rel="stylesheet" href="{{ args.public_path }}/static/water.css">
|
||||
{%- endif %}
|
||||
|
|
|
@ -59,11 +59,13 @@
|
|||
<input type="hidden" name="syntax-highlight" value="none">
|
||||
{%- endif %}
|
||||
|
||||
{% if !args.no_file_upload %}
|
||||
<div>
|
||||
<label>File attachment</label>
|
||||
<br>
|
||||
<input style="width: 100%;" type="file" id="file" name="file">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<label>Content</label>
|
||||
<br>
|
||||
|
|
|
@ -16,13 +16,33 @@
|
|||
<a href="{{ args.public_path }}/pasta/{{pasta.id_as_animals()}}"><i>{{pasta.id_as_animals()}}</i></a>
|
||||
</div>
|
||||
<br>
|
||||
<div style="clear: both;">
|
||||
{% if args.highlightsyntax %}
|
||||
<pre><code>{{pasta.content_syntax_highlighted()}}</code></pre>
|
||||
{%- else %}
|
||||
<pre><code>{{pasta.content_not_highlighted()}}</code></pre>
|
||||
{%- endif %}
|
||||
<div class="code-container">
|
||||
<a role="button" id="copy-button" class="copy-button">
|
||||
Copy
|
||||
</a>
|
||||
<div style="clear: both;">
|
||||
{% if args.highlightsyntax %}
|
||||
<pre><code id="code">{{pasta.content_syntax_highlighted()}}</code></pre>
|
||||
{%- else %}
|
||||
<pre><code id="code">{{pasta.content_not_highlighted()}}</code></pre>
|
||||
{%- endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const btn = document.getElementById("copy-button")
|
||||
const content = `{{ pasta.content_escaped() }}`
|
||||
|
||||
btn.addEventListener("click", () => {
|
||||
navigator.clipboard.writeText(content)
|
||||
btn.innerHTML = "Copied"
|
||||
setTimeout(() => {
|
||||
btn.innerHTML = "Copy"
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
code-line {
|
||||
counter-increment: listing;
|
||||
|
@ -48,6 +68,24 @@ code-line::before {
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.code-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
position: absolute;
|
||||
background: transparent;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 3px;
|
||||
margin: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
{% include "footer.html" %}
|
||||
|
|
Loading…
Reference in a new issue