Compare commits
8 commits
custom_con
...
main
Author | SHA1 | Date | |
---|---|---|---|
9fb372574d | |||
35ea2679a7 | |||
cf89b8db7f | |||
f7977412bc | |||
74f7ba968a | |||
e50501c588 | |||
7fc60fdc5e | |||
af07b57dc6 |
11 changed files with 87 additions and 37 deletions
10
CONFIG.md
10
CONFIG.md
|
@ -8,7 +8,9 @@ title = "bingus-blog" # title of the blog
|
||||||
description = "blazingly fast markdown blog software written in rust memory safe"
|
description = "blazingly fast markdown blog software written in rust memory safe"
|
||||||
markdown_access = true # allow users to see the raw markdown of a post
|
markdown_access = true # allow users to see the raw markdown of a post
|
||||||
# endpoint: /posts/<name>.md
|
# endpoint: /posts/<name>.md
|
||||||
js_enable = true # enable javascript (required for below 2 options)
|
js_enable = true # enable javascript (required for sorting and dates)
|
||||||
|
|
||||||
|
[style]
|
||||||
date_format = "RFC3339" # format string used to format dates in the backend
|
date_format = "RFC3339" # format string used to format dates in the backend
|
||||||
# it's highly recommended to leave this as default,
|
# it's highly recommended to leave this as default,
|
||||||
# so the date can be formatted by the browser.
|
# so the date can be formatted by the browser.
|
||||||
|
@ -16,6 +18,10 @@ date_format = "RFC3339" # format string used to format dates in the backend
|
||||||
default_sort = "date" # default sorting method ("date" or "name")
|
default_sort = "date" # default sorting method ("date" or "name")
|
||||||
#default_color = "#f5c2e7" # default embed color, optional
|
#default_color = "#f5c2e7" # default embed color, optional
|
||||||
|
|
||||||
|
[style.display_dates]
|
||||||
|
creation = true # display creation ("written") dates
|
||||||
|
modification = true # display modified ("last modified") dates
|
||||||
|
|
||||||
[rss]
|
[rss]
|
||||||
enable = false # serve an rss field under /feed.xml
|
enable = false # serve an rss field under /feed.xml
|
||||||
# this may be a bit resource intensive
|
# this may be a bit resource intensive
|
||||||
|
@ -54,7 +60,7 @@ a default value
|
||||||
you don't have to copy the whole thing from here,
|
you don't have to copy the whole thing from here,
|
||||||
it's generated by the program if it doesn't exist
|
it's generated by the program if it doesn't exist
|
||||||
|
|
||||||
## Specifying Configuration
|
## Specifying the configuration file
|
||||||
|
|
||||||
the configuration file is loaded from `config.toml` by default, but the path
|
the configuration file is loaded from `config.toml` by default, but the path
|
||||||
can be overriden by setting the environment variable `BINGUS_BLOG_CONFIG`,
|
can be overriden by setting the environment variable `BINGUS_BLOG_CONFIG`,
|
||||||
|
|
|
@ -17,7 +17,7 @@ for bingus-blog viewers: [see original document](https://git.slonk.ing/slonk/bin
|
||||||
can write posts from anywhere and sync it with the server without headache
|
can write posts from anywhere and sync it with the server without headache
|
||||||
- RSS is supported
|
- RSS is supported
|
||||||
- the look of the blog is extremely customizable, with support for
|
- the look of the blog is extremely customizable, with support for
|
||||||
[custom drop-ins](/CUSTOM.md) for both templates and static content
|
[custom drop-ins](CUSTOM.md) for both templates and static content
|
||||||
- really easy to deploy (the server is one executable file)
|
- really easy to deploy (the server is one executable file)
|
||||||
- blazingly fast
|
- blazingly fast
|
||||||
|
|
||||||
|
@ -26,18 +26,20 @@ for bingus-blog viewers: [see original document](https://git.slonk.ing/slonk/bin
|
||||||
- [ ] blog thumbnail and favicon
|
- [ ] blog thumbnail and favicon
|
||||||
- [ ] sort asc/desc
|
- [ ] sort asc/desc
|
||||||
- [ ] extend syntect options
|
- [ ] extend syntect options
|
||||||
|
- [ ] ^ fix syntect mutex poisoning
|
||||||
- [ ] better error reporting and error pages
|
- [ ] better error reporting and error pages
|
||||||
- [ ] better tracing
|
- [ ] better tracing
|
||||||
- [ ] replace HashMap with HashCache once i implement [this](https://github.com/wvwwvwwv/scalable-concurrent-containers/issues/139)
|
- [ ] replace HashMap with HashCache once i implement [this](https://github.com/wvwwvwwv/scalable-concurrent-containers/issues/139)
|
||||||
- [ ] make date parsing less strict
|
- [ ] make date parsing less strict
|
||||||
- [ ] improve home page
|
- [ ] improve home page
|
||||||
- [ ] multi-language support
|
- [ ] multi-language support
|
||||||
|
- [ ] add credits
|
||||||
- [x] be blazingly fast
|
- [x] be blazingly fast
|
||||||
- [x] 100+ MiB binary size
|
- [x] 100+ MiB binary size
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
see [CONFIG.md](/CONFIG.md)
|
see [CONFIG.md](CONFIG.md)
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
@ -52,7 +54,7 @@ cargo +nightly build --release
|
||||||
|
|
||||||
the executable will be located at `target/release/bingus-blog`.
|
the executable will be located at `target/release/bingus-blog`.
|
||||||
|
|
||||||
see [BUILDING.md](/BUILDING.md) for more information and detailed instructions.
|
see [BUILDING.md](BUILDING.md) for more information and detailed instructions.
|
||||||
|
|
||||||
## Writing Posts
|
## Writing Posts
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<div class="table">
|
<div class="table">
|
||||||
{{#if (ne this.created_at null)}}
|
{{#if (and (ne this.created_at null) style.display_dates.creation)}}
|
||||||
<div class="created">written</div>
|
<div class="created">written</div>
|
||||||
<div class="created value">{{>span_date date_time=this.created_at}}</div>
|
<div class="created value">{{>span_date dt=this.created_at df=style.date_format}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (ne this.modified_at null)}}
|
{{#if (and (ne this.modified_at null) style.display_dates.modification)}}
|
||||||
<div class="modified">last modified</div>
|
<div class="modified">last modified</div>
|
||||||
<div class="modified value">{{>span_date date_time=this.modified_at}}</div>
|
<div class="modified value">{{>span_date dt=this.modified_at df=style.date_format}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (gt (len this.tags) 0)}}
|
{{#if (gt (len this.tags) 0)}}
|
||||||
<div class="tags">tags</div>
|
<div class="tags">tags</div>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<span class="date {{#if (eq df "RFC3339")}}date-rfc3339{{/if}}">{{date date_time df}}</span>
|
<span class="date {{#if (eq df "RFC3339")}}date-rfc3339{{/if}}">{{date dt df}}</span>
|
||||||
|
|
19
src/app.rs
19
src/app.rs
|
@ -19,7 +19,7 @@ use tower_http::services::ServeDir;
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
use tracing::{info, info_span, Span};
|
use tracing::{info, info_span, Span};
|
||||||
|
|
||||||
use crate::config::{Config, DateFormat, Sort};
|
use crate::config::{Config, StyleConfig};
|
||||||
use crate::error::{AppError, AppResult};
|
use crate::error::{AppError, AppResult};
|
||||||
use crate::post::{MarkdownPosts, PostManager, PostMetadata, RenderStats, ReturnedPost};
|
use crate::post::{MarkdownPosts, PostManager, PostMetadata, RenderStats, ReturnedPost};
|
||||||
use crate::serve_dir_included::handle;
|
use crate::serve_dir_included::handle;
|
||||||
|
@ -40,12 +40,10 @@ struct IndexTemplate<'a> {
|
||||||
description: &'a str,
|
description: &'a str,
|
||||||
posts: Vec<PostMetadata>,
|
posts: Vec<PostMetadata>,
|
||||||
rss: bool,
|
rss: bool,
|
||||||
df: &'a DateFormat,
|
|
||||||
js: bool,
|
js: bool,
|
||||||
color: Option<&'a str>,
|
|
||||||
sort: Sort,
|
|
||||||
tags: Map<String, serde_json::Value>,
|
tags: Map<String, serde_json::Value>,
|
||||||
joined_tags: String,
|
joined_tags: String,
|
||||||
|
style: &'a StyleConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -54,10 +52,10 @@ struct PostTemplate<'a> {
|
||||||
rendered: String,
|
rendered: String,
|
||||||
rendered_in: RenderStats,
|
rendered_in: RenderStats,
|
||||||
markdown_access: bool,
|
markdown_access: bool,
|
||||||
df: &'a DateFormat,
|
|
||||||
js: bool,
|
js: bool,
|
||||||
color: Option<&'a str>,
|
color: Option<&'a str>,
|
||||||
joined_tags: String,
|
joined_tags: String,
|
||||||
|
style: &'a StyleConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -128,12 +126,10 @@ async fn index<'a>(
|
||||||
description: &config.description,
|
description: &config.description,
|
||||||
posts,
|
posts,
|
||||||
rss: config.rss.enable,
|
rss: config.rss.enable,
|
||||||
df: &config.date_format,
|
|
||||||
js: config.js_enable,
|
js: config.js_enable,
|
||||||
color: config.default_color.as_deref(),
|
|
||||||
sort: config.default_sort,
|
|
||||||
tags,
|
tags,
|
||||||
joined_tags,
|
joined_tags,
|
||||||
|
style: &config.style,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
drop(reg);
|
drop(reg);
|
||||||
|
@ -228,10 +224,13 @@ async fn post(
|
||||||
rendered,
|
rendered,
|
||||||
rendered_in,
|
rendered_in,
|
||||||
markdown_access: config.markdown_access,
|
markdown_access: config.markdown_access,
|
||||||
df: &config.date_format,
|
|
||||||
js: config.js_enable,
|
js: config.js_enable,
|
||||||
color: meta.color.as_deref().or(config.default_color.as_deref()),
|
color: meta
|
||||||
|
.color
|
||||||
|
.as_deref()
|
||||||
|
.or(config.style.default_color.as_deref()),
|
||||||
joined_tags,
|
joined_tags,
|
||||||
|
style: &config.style,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
drop(reg);
|
drop(reg);
|
||||||
|
|
|
@ -76,6 +76,23 @@ pub enum Sort {
|
||||||
Name,
|
Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(default)]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct StyleConfig {
|
||||||
|
pub display_dates: DisplayDates,
|
||||||
|
pub date_format: DateFormat,
|
||||||
|
pub default_sort: Sort,
|
||||||
|
pub default_color: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct DisplayDates {
|
||||||
|
pub creation: bool,
|
||||||
|
pub modification: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
@ -83,9 +100,7 @@ pub struct Config {
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub markdown_access: bool,
|
pub markdown_access: bool,
|
||||||
pub js_enable: bool,
|
pub js_enable: bool,
|
||||||
pub date_format: DateFormat,
|
pub style: StyleConfig,
|
||||||
pub default_sort: Sort,
|
|
||||||
pub default_color: Option<String>,
|
|
||||||
pub rss: RssConfig,
|
pub rss: RssConfig,
|
||||||
pub dirs: DirsConfig,
|
pub dirs: DirsConfig,
|
||||||
pub http: HttpConfig,
|
pub http: HttpConfig,
|
||||||
|
@ -100,9 +115,7 @@ impl Default for Config {
|
||||||
description: "blazingly fast markdown blog software written in rust memory safe".into(),
|
description: "blazingly fast markdown blog software written in rust memory safe".into(),
|
||||||
markdown_access: true,
|
markdown_access: true,
|
||||||
js_enable: true,
|
js_enable: true,
|
||||||
date_format: Default::default(),
|
style: Default::default(),
|
||||||
default_sort: Default::default(),
|
|
||||||
default_color: None,
|
|
||||||
// i have a love-hate relationship with serde
|
// i have a love-hate relationship with serde
|
||||||
// it was engimatic at first, but then i started actually using it
|
// it was engimatic at first, but then i started actually using it
|
||||||
// writing my own serialize and deserialize implementations.. spending
|
// writing my own serialize and deserialize implementations.. spending
|
||||||
|
@ -121,6 +134,16 @@ impl Default for Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for DisplayDates {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
creation: true,
|
||||||
|
modification: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Default for DirsConfig {
|
impl Default for DirsConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -29,7 +29,7 @@ fn is_ext(path: impl AsRef<Path>, ext: &str) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(self) fn get_template_name<'a>(path: &'a Path) -> Option<&'a str> {
|
fn get_template_name(path: &Path) -> Option<&str> {
|
||||||
if !is_ext(path, "hbs") {
|
if !is_ext(path, "hbs") {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -47,10 +47,10 @@ fn register_included_file(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_path<'a>(
|
fn register_path(
|
||||||
path: impl AsRef<std::path::Path>,
|
path: impl AsRef<std::path::Path>,
|
||||||
name: &str,
|
name: &str,
|
||||||
registry: &mut Handlebars<'a>,
|
registry: &mut Handlebars<'_>,
|
||||||
) -> Result<(), TemplateError> {
|
) -> Result<(), TemplateError> {
|
||||||
let template = compile_path(path)?;
|
let template = compile_path(path)?;
|
||||||
registry.register_template(name, template);
|
registry.register_template(name, template);
|
||||||
|
@ -85,7 +85,7 @@ fn compile_path(path: impl AsRef<std::path::Path>) -> Result<Template, TemplateE
|
||||||
Ok(template)
|
Ok(template)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(self) async fn compile_path_async_io(
|
async fn compile_path_async_io(
|
||||||
path: impl AsRef<std::path::Path>,
|
path: impl AsRef<std::path::Path>,
|
||||||
) -> Result<Template, TemplateError> {
|
) -> Result<Template, TemplateError> {
|
||||||
use tokio::fs::OpenOptions;
|
use tokio::fs::OpenOptions;
|
||||||
|
|
|
@ -54,3 +54,22 @@ th,
|
||||||
td:nth-child(1) {
|
td:nth-child(1) {
|
||||||
word-break: keep-all;
|
word-break: keep-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin-left: 1em;
|
||||||
|
padding-left: 1.5em;
|
||||||
|
border-left: 0.5em solid;
|
||||||
|
border-color: var(--blue);
|
||||||
|
& > blockquote {
|
||||||
|
border-color: var(--mauve);
|
||||||
|
& > blockquote {
|
||||||
|
border-color: var(--pink);
|
||||||
|
& > blockquote {
|
||||||
|
border-color: var(--rosewater);
|
||||||
|
& > blockquote {
|
||||||
|
border-color: var(--text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* colors */
|
/* colors from catppuccin https://github.com/catppuccin/catppuccin
|
||||||
|
licensed under the MIT license, available in the source tree */
|
||||||
:root {
|
:root {
|
||||||
--base: #1e1e2e;
|
--base: #1e1e2e;
|
||||||
--text: #cdd6f4;
|
--text: #cdd6f4;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<meta property="og:description" content="{{description}}" />
|
<meta property="og:description" content="{{description}}" />
|
||||||
<meta name="keywords" content="{{joined_tags}}" />
|
<meta name="keywords" content="{{joined_tags}}" />
|
||||||
{{#if (ne color null)}}
|
{{#if (ne color null)}}
|
||||||
<meta name="theme-color" content="{{color}}" />
|
<meta name="theme-color" content="{{style.color}}" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<title>{{title}}</title>
|
<title>{{title}}</title>
|
||||||
<link rel="stylesheet" href="/static/style.css" />
|
<link rel="stylesheet" href="/static/style.css" />
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
<form id="sort" style="display: none">
|
<form id="sort" style="display: none">
|
||||||
sort by: {{sort}}
|
sort by: {{sort}}
|
||||||
<br />
|
<br />
|
||||||
<input type="radio" name="sort" id="sort-date" value="date" {{#if (eq sort "date")}}checked{{/if}} />
|
<input type="radio" name="sort" id="sort-date" value="date" {{#if (eq style.default_sort "date")}}checked{{/if}} />
|
||||||
<label for="sort-date">date</label>
|
<label for="sort-date">date</label>
|
||||||
<input type="radio" name="sort" id="sort-name" value="name" {{#if (eq sort "name")}}checked{{/if}} />
|
<input type="radio" name="sort" id="sort-name" value="name" {{#if (eq style.default_sort "name")}}checked{{/if}} />
|
||||||
<label for="sort-name">name</label>
|
<label for="sort-name">name</label>
|
||||||
</form>
|
</form>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
<span class="post-author">- by {{author}}</span>
|
<span class="post-author">- by {{author}}</span>
|
||||||
<br />
|
<br />
|
||||||
{{description}}<br />
|
{{description}}<br />
|
||||||
{{>post_table post df=@root.df}}
|
{{>post_table post style=@root.style}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{else}} there are no posts right now. check back later! {{/each}}
|
{{else}} there are no posts right now. check back later! {{/each}}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<meta property="twitter:image:alt" content="{{meta.icon_alt}}" />
|
<meta property="twitter:image:alt" content="{{meta.icon_alt}}" />
|
||||||
{{/if}}{{/if}}
|
{{/if}}{{/if}}
|
||||||
{{#if (ne color null)}}
|
{{#if (ne color null)}}
|
||||||
<meta name="theme-color" content="{{meta.color}}" />
|
<meta name="theme-color" content="{{color}}" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<title>{{meta.title}}</title>
|
<title>{{meta.title}}</title>
|
||||||
<link rel="stylesheet" href="/static/style.css" />
|
<link rel="stylesheet" href="/static/style.css" />
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
</h1>
|
</h1>
|
||||||
<p class="post-desc">{{meta.description}}</p>
|
<p class="post-desc">{{meta.description}}</p>
|
||||||
<div class="post">
|
<div class="post">
|
||||||
{{>post_table meta df=@root.df}}
|
{{>post_table meta style=@root.style}}
|
||||||
<a href="/posts/{{meta.name}}">link</a><br />
|
<a href="/posts/{{meta.name}}">link</a><br />
|
||||||
<a href="/">back to home</a>
|
<a href="/">back to home</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue