generate subpage listings automatically

right now very barebones!

- doesn't sort pages quite correctly
- no search function
- still not sure about the UI design aspects

includes refactor of tree generation code
This commit is contained in:
りき萌 2025-01-15 20:27:00 +01:00
parent 9a86b5f98e
commit fbb9f39353
8 changed files with 508 additions and 187 deletions

View file

@ -1,6 +1,6 @@
use std::collections::HashMap;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use ulid::Ulid;
use crate::{state::FileId, vfs::VPathBuf};
@ -18,6 +18,11 @@ pub struct RootAttributes {
#[serde(default)]
pub title: String,
/// Page icon used in indexes.
/// This is an emoji name, such as `page` (default).
#[serde(default = "default_icon")]
pub icon: String,
/// Summary of the generated .html page.
#[serde(default)]
pub description: Option<String>,
@ -36,6 +41,15 @@ pub struct RootAttributes {
#[serde(default)]
pub styles: Vec<String>,
/// Visibility of a page in the parent page's index.
#[serde(default)]
pub visibility: Visibility,
/// The page's timestamps. These are automatically populated if a page has at least one branch
/// with an ID that includes a timestamp.
#[serde(default)]
pub timestamps: Option<Timestamps>,
/// When specified, this page will have a corresponding Atom feed under `rss/{feed}.xml`.
///
/// In feeds, top-level branches are expected to have a single heading containing the post title.
@ -55,6 +69,28 @@ pub struct Picture {
pub alt: Option<String>,
}
/// Visibility of a page.
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum Visibility {
#[default]
Public,
/// Hidden from the parent page's index.
Private,
}
/// Timestamps for a page.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
pub struct Timestamps {
/// When the page was created. By default, this is the timestamp of the least recent branch.
pub created: DateTime<Utc>,
/// When the page was last updated. By default, this is the timestamp of the most recent branch.
pub updated: DateTime<Utc>,
}
fn default_icon() -> String {
String::from("page")
}
/// Branch attributes.
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize)]
pub struct Attributes {
@ -96,16 +132,24 @@ pub struct Attributes {
#[serde(default)]
pub cast: String,
/// List of extra `data` attributes to add to the block.
#[serde(default)]
pub data: HashMap<String, String>,
/// In feeds, specifies the list of tags to attach to an entry.
/// This only has an effect on top-level branches.
#[serde(default)]
pub tags: Vec<String>,
}
impl Attributes {
/// Parses the timestamp out of the branch's ID.
/// Returns `None` if the ID does not contain a timestamp.
pub fn timestamp(&self) -> Option<DateTime<Utc>> {
Ulid::from_string(&self.id)
.ok()
.as_ref()
.map(Ulid::timestamp_ms)
.and_then(|ms| DateTime::from_timestamp_millis(ms as i64))
}
}
/// Controls for block content presentation.
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "snake_case")]