+4
-33
src/http.rs
+4
-33
src/http.rs
···
82
slug: String,
83
title: String,
84
created_at: String,
85
}
86
87
impl TryFrom<Post> for PostDisplay {
···
89
90
fn try_from(post: Post) -> Result<Self> {
91
Ok(PostDisplay {
92
slug: format!("{}-{}", post.record_key, post.slug),
93
title: post.title,
94
created_at: post.created_at.format("%Y-%m-%d %H:%M UTC").to_string(),
95
})
96
}
97
}
···
304
.map(PostDisplay::try_from)
305
.collect::<Result<Vec<_>>>()
306
}
307
-
308
-
#[cfg(test)]
309
-
mod tests {
310
-
use super::*;
311
-
use crate::storage::Post;
312
-
use chrono::Utc;
313
-
use serde_json::Value;
314
-
315
-
#[tokio::test]
316
-
async fn test_post_display_creation() {
317
-
let post = Post {
318
-
aturi: "at://did:plc:test/com.example.blog/post1".to_string(),
319
-
cid: "bafy123".to_string(),
320
-
title: "Test Post".to_string(),
321
-
slug: "test-post".to_string(),
322
-
content: "bafy456".to_string(),
323
-
record_key: "post1".to_string(),
324
-
created_at: Utc::now(),
325
-
updated_at: Utc::now(),
326
-
record: Value::Null,
327
-
};
328
-
329
-
let display = PostDisplay {
330
-
slug: post.slug,
331
-
title: post.title,
332
-
created_at: post.created_at.format("%Y-%m-%d %H:%M UTC").to_string(),
333
-
};
334
-
335
-
assert_eq!(display.slug, "test-post");
336
-
assert_eq!(display.title, "Test Post");
337
-
assert!(display.created_at.contains("UTC"));
338
-
}
339
-
}
···
82
slug: String,
83
title: String,
84
created_at: String,
85
+
created_at_date: String,
86
+
aturi: String,
87
}
88
89
impl TryFrom<Post> for PostDisplay {
···
91
92
fn try_from(post: Post) -> Result<Self> {
93
Ok(PostDisplay {
94
+
aturi: post.aturi,
95
slug: format!("{}-{}", post.record_key, post.slug),
96
title: post.title,
97
created_at: post.created_at.format("%Y-%m-%d %H:%M UTC").to_string(),
98
+
created_at_date: post.created_at.format("%Y-%m-%d").to_string(),
99
})
100
}
101
}
···
308
.map(PostDisplay::try_from)
309
.collect::<Result<Vec<_>>>()
310
}
+20
-1
templates/index.html
+20
-1
templates/index.html
···
2
{% block title %}Smoke Signal Blog{% endblock %}
3
{% block head %}
4
<meta name="description" content="The Smoke Signal Events blog.">
5
-
<link rel="canonical" href="{{ external_base }}/">
6
<meta property="og:title" content="Smoke Signal Events Blog" />
7
<meta property="og:type" content="website" />
8
<meta property="og:url" content="{{ external_base }}/" />
9
<meta property="og:description" content="The Smoke Signal Events blog." />
10
<meta property="og:site_name" content="Smoke Signal Events Blog" />
11
{% endblock %}
12
{% block content %}
13
<main>
···
2
{% block title %}Smoke Signal Blog{% endblock %}
3
{% block head %}
4
<meta name="description" content="The Smoke Signal Events blog.">
5
<meta property="og:title" content="Smoke Signal Events Blog" />
6
<meta property="og:type" content="website" />
7
<meta property="og:url" content="{{ external_base }}/" />
8
<meta property="og:description" content="The Smoke Signal Events blog." />
9
<meta property="og:site_name" content="Smoke Signal Events Blog" />
10
+
<link rel="canonical" href="{{ external_base }}/">
11
+
<script type="application/ld+json">
12
+
{
13
+
"@context": "https://schema.org",
14
+
"@type": "Blog",
15
+
"name": "Smoke Signal Events Blog",
16
+
"description": "The Smoke Signal Events blog.",
17
+
"url": "{{ external_base }}/",
18
+
"author": {
19
+
"@type": "Person",
20
+
"name": "Nick Gerakines",
21
+
"url": "https://bsky.app/profile/ngerakines.me"
22
+
},
23
+
"publisher": {
24
+
"@type": "Organization",
25
+
"name": "Smoke Signal",
26
+
"url": "https://bsky.app/profile/smokesignal.events"
27
+
}
28
+
}
29
+
</script>
30
{% endblock %}
31
{% block content %}
32
<main>
+22
-1
templates/post.html
+22
-1
templates/post.html
···
2
{% block title %}{{ post.title }} - Blahg{% endblock %}
3
{% block head %}
4
<meta name="description" content="{{ post.title }} posted by @smokesignal.events on {{ post.created_at }}">
5
-
<link rel="canonical" href="{{ external_base }}/">
6
<meta property="og:title" content="{{ post.title }}" />
7
<meta property="og:type" content="website" />
8
<meta property="og:url" content="{{ external_base }}/posts/{{ post.slug }}" />
9
<meta property="og:description" content="{{ post.title }} posted by @smokesignal.events on {{ post.created_at }}" />
10
<meta property="og:site_name" content="Smoke Signal Events Blog" />
11
{% endblock %}
12
{% block content %}
13
<main>
···
2
{% block title %}{{ post.title }} - Blahg{% endblock %}
3
{% block head %}
4
<meta name="description" content="{{ post.title }} posted by @smokesignal.events on {{ post.created_at }}">
5
<meta property="og:title" content="{{ post.title }}" />
6
<meta property="og:type" content="website" />
7
<meta property="og:url" content="{{ external_base }}/posts/{{ post.slug }}" />
8
<meta property="og:description" content="{{ post.title }} posted by @smokesignal.events on {{ post.created_at }}" />
9
<meta property="og:site_name" content="Smoke Signal Events Blog" />
10
+
<link rel="canonical" href="{{ external_base }}/posts/{{ post.slug }}">
11
+
<link rel="alternate" href="{{ post.aturi }}" />
12
+
<script type="application/ld+json">
13
+
{
14
+
"@context": "https://schema.org",
15
+
"@type": "BlogPosting",
16
+
"headline": "{{ post.title }}",
17
+
"datePublished": "{{ post.created_at_date }}",
18
+
"dateModified": "{{ post.created_at_date }}",
19
+
"url": "{{ external_base }}/posts/{{ post.slug }}",
20
+
"author": {
21
+
"@type": "Person",
22
+
"name": "Nick Gerakines",
23
+
"url": "https://bsky.app/profile/ngerakines.me"
24
+
},
25
+
"publisher": {
26
+
"@type": "Organization",
27
+
"name": "Smoke Signal",
28
+
"url": "https://bsky.app/profile/smokesignal.events"
29
+
}
30
+
}
31
+
</script>
32
{% endblock %}
33
{% block content %}
34
<main>