Compare commits

...

9 commits

Author SHA1 Message Date
6f7b9b7350
remove unused templates 2024-07-01 03:24:11 +03:00
a8a1dca444
add alt text 2024-07-01 03:21:33 +03:00
cee11ba07a
add TODO 2024-07-01 03:17:21 +03:00
38d93a66ba
add color to index 2024-07-01 03:16:17 +03:00
3623b61fbe
optimization 2024-07-01 03:14:26 +03:00
bd093e7c20
add default color 2024-07-01 02:53:04 +03:00
658ddaf820
document options 2024-07-01 02:44:43 +03:00
342a353b36
better post icon and color support 2024-07-01 02:34:40 +03:00
602f57581a
remove shortcut icon 2024-07-01 02:24:32 +03:00
9 changed files with 76 additions and 35 deletions

View file

@ -1,7 +1,7 @@
---
title: "README"
description: "the README.md file of this project"
author: "slonkazoid"
title: README
description: the README.md file of this project
author: slonkazoid
created_at: 2024-04-18T04:15:26+03:00
---
@ -14,6 +14,8 @@ blazingly fast markdown blog software written in rust memory safe
- [x] RSS
- [x] finish writing this document
- [x] document config
- [ ] blog thumbnail and favicon
- [x] alt text for post icon
- [ ] extend syntect options
- [ ] general cleanup of code
- [ ] better error reporting and error pages
@ -46,6 +48,7 @@ date_format = "RFC3339" # format string used to format dates in the backend
# so the date can be formatted by the browser.
# format: https://docs.rs/chrono/latest/chrono/format/strftime/index.html#specifiers
js_enable = true # enable javascript (required for above)
default_color = "#f5c2e7" # default embed color, optional
[rss]
enable = false # serve an rss field under /feed.xml
@ -55,6 +58,7 @@ link = "https://..." # public url of the blog, required if rss is enabled
[dirs]
posts = "posts" # where posts are stored
media = "media" # directory served under /media/
static = "static" # directory server under /static/ (css and js)
[http]
host = "0.0.0.0" # ip to listen on
@ -125,15 +129,22 @@ every post **must** begin with a **valid** front matter. else it wont be listed
in / & /posts, and when you navigate to it, you will be met with an error page.
the error page will tell you what the problem is.
example:
full example:
```md
---
title: "README"
description: "the README.md file of this project"
author: "slonkazoid"
created_at: 2024-04-18T04:15:26+03:00
#modified_at: ... # see above
title: My first post # title of the post
description: The first post on this awesome blog! # short description of the post
author: Blubber256 # author of the post
icon: /media/first-post/icon.png # icon/thumbnail of post used in embeds
icon_alt: Picture of a computer running DOOM
color: "#00aacc" # color of post, also used in embeds
created_at: 2024-04-18T04:15:26+03:00 # date of writing, this is highly
# recommended if you are on a system which doesnt have btime (like musl),
# because this is fetched from file stats by default
#modified_at: ... # see above. this is also fetched from the filesystem
tags: # tags, or keywords, used in meta and also in the ui
- lifestyle
---
```

View file

@ -27,24 +27,26 @@ pub struct AppState {
#[derive(Template)]
#[template(path = "index.html")]
struct IndexTemplate {
title: String,
description: String,
struct IndexTemplate<'a> {
title: &'a str,
description: &'a str,
posts: Vec<PostMetadata>,
rss: bool,
df: DateFormat,
df: &'a DateFormat,
js: bool,
color: Option<&'a str>,
}
#[derive(Template)]
#[template(path = "post.html")]
struct PostTemplate {
meta: PostMetadata,
struct PostTemplate<'a> {
meta: &'a PostMetadata,
rendered: String,
rendered_in: RenderStats,
markdown_access: bool,
df: DateFormat,
df: &'a DateFormat,
js: bool,
color: Option<&'a str>,
}
#[derive(Deserialize)]
@ -54,22 +56,24 @@ struct QueryParams {
num_posts: Option<usize>,
}
async fn index(
async fn index<'a>(
State(AppState { config, posts }): State<AppState>,
Query(query): Query<QueryParams>,
) -> AppResult<IndexTemplate> {
) -> AppResult<Response> {
let posts = posts
.get_max_n_post_metadata_with_optional_tag_sorted(query.num_posts, query.tag.as_ref())
.await?;
Ok(IndexTemplate {
title: config.title.clone(),
description: config.description.clone(),
title: &config.title,
description: &config.description,
posts,
rss: config.rss.enable,
df: config.date_format.clone(),
df: &config.date_format,
js: config.js_enable,
})
color: config.default_color.as_deref(),
}
.into_response())
}
async fn all_posts(
@ -147,18 +151,16 @@ async fn post(
Path(name): Path<String>,
) -> AppResult<Response> {
match posts.get_post(&name).await? {
ReturnedPost::Rendered(meta, rendered, rendered_in) => {
let page = PostTemplate {
meta,
rendered,
rendered_in,
markdown_access: config.markdown_access,
df: config.date_format.clone(),
js: config.js_enable,
};
Ok(page.into_response())
ReturnedPost::Rendered(ref meta, rendered, rendered_in) => Ok(PostTemplate {
meta,
rendered,
rendered_in,
markdown_access: config.markdown_access,
df: &config.date_format,
js: config.js_enable,
color: meta.color.as_deref().or(config.default_color.as_deref()),
}
.into_response()),
ReturnedPost::Raw(body, content_type) => {
Ok(([(CONTENT_TYPE, content_type)], body).into_response())
}

View file

@ -75,6 +75,7 @@ pub struct Config {
pub markdown_access: bool,
pub date_format: DateFormat,
pub js_enable: bool,
pub default_color: Option<String>,
pub rss: RssConfig,
pub dirs: DirsConfig,
pub http: HttpConfig,
@ -90,6 +91,7 @@ impl Default for Config {
markdown_access: true,
date_format: Default::default(),
js_enable: true,
default_color: Some("#f5c2e7".into()),
// i have a love-hate relationship with serde
// it was engimatic at first, but then i started actually using it
// writing my own serialize and deserialize implementations.. spending

View file

@ -27,6 +27,8 @@ struct FrontMatter {
pub description: String,
pub author: String,
pub icon: Option<String>,
pub icon_alt: Option<String>,
pub color: Option<String>,
pub created_at: Option<DateTime<Utc>>,
pub modified_at: Option<DateTime<Utc>>,
#[serde(default)]
@ -46,6 +48,8 @@ impl FrontMatter {
description: self.description,
author: self.author,
icon: self.icon,
icon_alt: self.icon_alt,
color: self.color,
created_at: self.created_at.or_else(|| created.map(|t| t.into())),
modified_at: self.modified_at.or_else(|| modified.map(|t| t.into())),
tags: self.tags.into_iter().collect(),

View file

@ -17,6 +17,8 @@ pub struct PostMetadata {
pub description: String,
pub author: String,
pub icon: Option<String>,
pub icon_alt: Option<String>,
pub color: Option<String>,
pub created_at: Option<DateTime<Utc>>,
pub modified_at: Option<DateTime<Utc>>,
pub tags: Vec<String>,

View file

@ -7,11 +7,16 @@
<meta name="description" content="{{ title }}" />
<meta property="og:title" content="{{ title }}" />
<meta property="og:description" content="{{ description }}" />
{% match color %} {% when Some with (color) %}
<meta name="theme-color" content="{{ color }}" />
{% when None %} {% endmatch %}
<title>{{ title }}</title>
<link rel="stylesheet" href="/static/style.css" />
{% if rss %}
<link rel="alternate" type="application/rss+xml" title="{{ title }}" href="/feed.xml" />
{% endif %} {% if js %}
{% endif %}
<!-- prettier-br -->
{% if js %}
<script src="/static/main.js" defer></script>
{% endif %}
</head>

View file

@ -7,11 +7,26 @@
<meta name="author" content="{{ meta.author }}" />
<meta name="keywords" content="{{ meta.tags|join(", ") }}" />
<meta name="description" content="{{ meta.title }}" />
<!-- you know what I really love? platforms like discord
favoring twitter embeds over the open standard. to color
your embed or have large images, you have to do _this_. lmao -->
<meta property="og:title" content="{{ meta.title }}" />
<meta property="twitter:title" content="{{ meta.title }}" />
<meta property="og:description" content="{{ meta.description }}" />
<meta property="twitter:description" content="{{ meta.description }}" />
{% match meta.icon %} {% when Some with (url) %}
<meta property="og:image" content="{{ url }}" />
<link rel="shortcut icon" href="{{ url }}" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:image:src" content="{{ url }}" />
{% match meta.icon_alt %} {% when Some with (alt) %}
<meta property="og:image:alt" content="{{ alt }}" />
<meta property="twitter:image:alt" content="{{ alt }}" />
{% when None %} {% endmatch %}
<!-- prettier-br -->
{% when None %} {% endmatch %}
<!-- prettier is annoying -->
{% match color %} {% when Some with (color) %}
<meta name="theme-color" content="{{ color }}" />
{% when None %} {% endmatch %}
<title>{{ meta.title }}</title>
<link rel="stylesheet" href="/static/style.css" />