[#1] Blog metadata can be stored using serde.
Created the initial blog data, posts and authors, and allows it to be stored using serde.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
# Added by cargo
|
||||
*.swp
|
||||
|
||||
/target
|
||||
|
||||
142
Cargo.lock
generated
Normal file
142
Cargo.lock
generated
Normal file
@ -0,0 +1,142 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tavern"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
"toml_writer",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
||||
@ -11,3 +11,5 @@ license = "Apache-2.0"
|
||||
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
toml = "0.9.5"
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
# tavern
|
||||
|
||||
A blogging system that will allow you to write your blog in Markdown and then display it in HTML using Dioxus.
|
||||
|
||||
# Tavern
|
||||
|
||||
A blogging system that will allow you to write your blog in Markdown and then
|
||||
display it in HTML using Dioxus.
|
||||
|
||||
---
|
||||
|
||||
|
||||
32
src/adventurer.rs
Normal file
32
src/adventurer.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
|
||||
/// Represents an author or contributor of a tale.
|
||||
///
|
||||
/// An `Adventurer` contains identifying and descriptive information
|
||||
/// such as their name, handle, profile URL, image, and a short blurb.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Adventurer
|
||||
{
|
||||
/// The full name of the adventurer.
|
||||
pub name: String,
|
||||
|
||||
/// A unique handle or username for the adventurer (e.g., used in URLs or mentions).
|
||||
pub handle: String,
|
||||
|
||||
/// A link to the adventurer's profile (e.g., personal website, GitHub, etc.).
|
||||
pub profile: String,
|
||||
|
||||
/// A URL or path to an image representing the adventurer (e.g., avatar or portrait).
|
||||
pub image: String,
|
||||
|
||||
/// A short descriptive text or tagline about the adventurer.
|
||||
pub blurb: String
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Adventurer
|
||||
{
|
||||
}
|
||||
15
src/lib.rs
Normal file
15
src/lib.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//! A blogging system that will allow you to write your blog in Markdown and then display it in HTML using Dioxus.
|
||||
|
||||
mod info;
|
||||
|
||||
mod adventurer;
|
||||
mod tale;
|
||||
mod tavern;
|
||||
|
||||
|
||||
|
||||
pub use crate::info::{get_name, get_version};
|
||||
|
||||
pub use crate::adventurer::Adventurer;
|
||||
pub use crate::tale::Tale;
|
||||
pub use crate::tavern::Tavern;
|
||||
18
src/main.rs
18
src/main.rs
@ -1,18 +0,0 @@
|
||||
//! A blogging system that will allow you to write your blog in Markdown and then display it in HTML using Dioxus.
|
||||
|
||||
mod info;
|
||||
|
||||
|
||||
|
||||
/// Print the version.
|
||||
fn print_version()
|
||||
{
|
||||
println!("{} v{}", info::get_name(), info::get_version());
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn main()
|
||||
{
|
||||
print_version();
|
||||
}
|
||||
40
src/tale.rs
Normal file
40
src/tale.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
|
||||
/// A type alias representing the path to a Markdown file.
|
||||
/// This type is used to point to the location of the content of a `Tale`.
|
||||
pub type Markdown = std::path::PathBuf;
|
||||
|
||||
|
||||
/// Represents a post or story in the application.
|
||||
///
|
||||
/// A `Tale` contains metadata about the post such as its title, author,
|
||||
/// and tags, along with a path to its Markdown content.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Tale
|
||||
{
|
||||
/// The title of the tale.
|
||||
pub title: String,
|
||||
|
||||
/// A URL-friendly version of the title, used for routing and linking.
|
||||
pub slug: String,
|
||||
|
||||
/// The name of the author who wrote the tale.
|
||||
pub author: String,
|
||||
|
||||
/// A short summary or description of the tale.
|
||||
pub summary: String,
|
||||
|
||||
/// A list of tags associated with the tale for categorization and searching.
|
||||
pub tags: Vec<String>,
|
||||
|
||||
/// The file path to the Markdown content of the tale.
|
||||
pub content: Markdown
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Tale
|
||||
{
|
||||
}
|
||||
20
src/tavern.rs
Normal file
20
src/tavern.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::adventurer::Adventurer;
|
||||
use crate::tale::Tale;
|
||||
|
||||
|
||||
|
||||
/// Represents the entire blog or collection of content.
|
||||
///
|
||||
/// A `Tavern` contains a list of all tales (posts) and their respective authors.
|
||||
/// It serves as the central structure for organizing and serializing the site's content.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Tavern
|
||||
{
|
||||
/// A list of all published tales (posts) in the tavern.
|
||||
pub tales: Vec<Tale>,
|
||||
|
||||
/// A list of all adventurers (authors) who have contributed tales.
|
||||
pub authors: Vec<Adventurer>
|
||||
}
|
||||
84
tests/serde.rs
Normal file
84
tests/serde.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use tavern::{Adventurer, Tale, Tavern};
|
||||
|
||||
|
||||
|
||||
fn generate_tavern() -> Tavern
|
||||
{
|
||||
let author: Adventurer = Adventurer
|
||||
{
|
||||
name: String::from("Jason Smith"),
|
||||
handle: String::from("myrddin"),
|
||||
profile: String::from("https://cybermages.tech/about/myrddin"),
|
||||
image: String::from("https://cybermages.tech/about/myrddin/pic"),
|
||||
blurb: String::from("I love code!")
|
||||
};
|
||||
|
||||
let tale: Tale = Tale
|
||||
{
|
||||
title: String::from("Test post"),
|
||||
slug: String::from("test_post"),
|
||||
author: author.handle.clone(),
|
||||
summary: String::from("The Moon is made of cheese!"),
|
||||
tags: vec![String::from("Space"), String::from("Cheese")],
|
||||
content: std::path::PathBuf::from("posts/test_post.md")
|
||||
};
|
||||
|
||||
Tavern { tales: vec![tale], authors: vec![author]}
|
||||
}
|
||||
|
||||
fn cleanup_temp_file(path: &std::path::PathBuf)
|
||||
{
|
||||
if path.exists()
|
||||
{
|
||||
let _ = std::fs::remove_file(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn to_file()
|
||||
{
|
||||
let tavern = generate_tavern();
|
||||
|
||||
let toml_string = toml::to_string_pretty(&tavern)
|
||||
.expect("Serialization to TOML should succeed");
|
||||
|
||||
// Save the TOML to a temporary file.
|
||||
let mut path = std::env::temp_dir();
|
||||
path.push("tavern_test_out.toml");
|
||||
std::fs::write(&path, &toml_string)
|
||||
.expect("Failed to write TOML to file");
|
||||
|
||||
cleanup_temp_file(&path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_file()
|
||||
{
|
||||
let tavern = generate_tavern();
|
||||
|
||||
let toml_string = toml::to_string_pretty(&tavern)
|
||||
.expect("Serialization to TOML should succeed");
|
||||
|
||||
// Save the TOML to a temporary file.
|
||||
let mut path = std::env::temp_dir();
|
||||
path.push("tavern_test_in.toml");
|
||||
std::fs::write(&path, &toml_string)
|
||||
.expect("Failed to write TOML to file");
|
||||
|
||||
// Read the previously written TOML file
|
||||
let toml_data = std::fs::read_to_string(&path)
|
||||
.expect("Failed to read TOML file");
|
||||
|
||||
// Deserialize it
|
||||
let tavern: Tavern = toml::from_str(&toml_data)
|
||||
.expect("Failed to parse TOML");
|
||||
|
||||
// Assert some known values to make this a real test
|
||||
let tale = &tavern.tales[0];
|
||||
assert_eq!(tale.title, "Test post");
|
||||
assert_eq!(tale.slug, "test_post");
|
||||
assert_eq!(tale.author, "myrddin");
|
||||
|
||||
cleanup_temp_file(&path);
|
||||
}
|
||||
Reference in New Issue
Block a user