Compare commits

..

No commits in common. "6f7b9b73506ae4a2e298db8d44807b9f2f0ccbd2" and "41228d55b6c5370c797fd54c829bd1ea374b4e63" have entirely different histories.

9 changed files with 35 additions and 76 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,8 +14,6 @@ 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
@ -48,7 +46,6 @@ 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
@ -58,7 +55,6 @@ 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
@ -129,22 +125,15 @@ 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.
full example:
example:
```md
---
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
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
---
```

View file

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

View file

@ -75,7 +75,6 @@ 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,
@ -91,7 +90,6 @@ 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,8 +27,6 @@ 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)]
@ -48,8 +46,6 @@ 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,8 +17,6 @@ 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,16 +7,11 @@
<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 %}
<!-- prettier-br -->
{% if js %}
{% endif %} {% if js %}
<script src="/static/main.js" defer></script>
{% endif %}
</head>

View file

@ -7,26 +7,11 @@
<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 }}" />
<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 }}" />
<link rel="shortcut icon" href="{{ url }}" />
{% when None %} {% endmatch %}
<title>{{ meta.title }}</title>
<link rel="stylesheet" href="/static/style.css" />

0
templates/post_list.html Normal file
View file

View file