generate atom feed in root
This commit is contained in:
parent
d211935539
commit
9746bc63ef
91
Cargo.lock
generated
91
Cargo.lock
generated
|
@ -70,7 +70,10 @@ dependencies = [
|
|||
"html-escaper",
|
||||
"orgize",
|
||||
"rowan",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"slugify",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -152,6 +155,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -214,6 +223,16 @@ dependencies = [
|
|||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jetscii"
|
||||
version = "0.5.3"
|
||||
|
@ -396,6 +415,35 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slugify"
|
||||
version = "0.1.0"
|
||||
|
@ -443,6 +491,40 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.40"
|
||||
|
@ -532,3 +614,12 @@ name = "version_check"
|
|||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
|
@ -13,4 +13,7 @@ git2 = { version = "0.18.3", default-features = false }
|
|||
html-escaper = "0.2.0"
|
||||
orgize = "=0.10.0-alpha.7"
|
||||
rowan = "0.15.15"
|
||||
serde = { version = "1.0.197", default-features = false }
|
||||
serde_derive = { version = "1.0.197" }
|
||||
slugify = "0.1.0"
|
||||
toml = { version = "0.8.12", default-features = false, features = ["parse"] }
|
||||
|
|
35
src/atom.rs
35
src/atom.rs
|
@ -1,18 +1,47 @@
|
|||
use crate::git::ModifyMap;
|
||||
use chrono::{offset::Utc, DateTime};
|
||||
use html_escaper::Escape;
|
||||
use std::{collections::BTreeMap, path::PathBuf};
|
||||
|
||||
#[derive(boilerplate::Boilerplate)]
|
||||
pub struct FeedXml<'a> {
|
||||
pub title: &'a str,
|
||||
pub id: &'a str,
|
||||
pub url: &'a str,
|
||||
pub updated: DateTime<Utc>,
|
||||
pub entries: Vec<AtomEntry<'a>>,
|
||||
pub updated: &'a DateTime<Utc>,
|
||||
pub entries: &'a [AtomEntry<'a>],
|
||||
}
|
||||
|
||||
pub struct AtomEntry<'a> {
|
||||
pub title: &'a str,
|
||||
pub path: String,
|
||||
pub path: &'a str,
|
||||
pub author: &'a str,
|
||||
pub updated: DateTime<Utc>,
|
||||
}
|
||||
|
||||
pub fn entries<'a>(
|
||||
titles: &'a BTreeMap<PathBuf, (String, PathBuf)>,
|
||||
mtime: &'a ModifyMap,
|
||||
) -> Result<Vec<AtomEntry<'a>>, Box<dyn std::error::Error>> {
|
||||
let mut entries = vec![];
|
||||
|
||||
for (path, (title, old)) in titles.iter() {
|
||||
let path = match path.to_str() {
|
||||
Some(p) => p,
|
||||
None => continue,
|
||||
};
|
||||
let (updated, author) = mtime.get(old).ok_or("missing modification info")?;
|
||||
let updated =
|
||||
DateTime::from_timestamp(updated.seconds(), 0).ok_or("broken modification date")?;
|
||||
|
||||
entries.push(AtomEntry {
|
||||
title,
|
||||
path,
|
||||
author,
|
||||
updated,
|
||||
});
|
||||
}
|
||||
|
||||
entries.sort_by(|x, y| x.updated.cmp(&y.updated));
|
||||
Ok(entries)
|
||||
}
|
||||
|
|
41
src/main.rs
41
src/main.rs
|
@ -4,7 +4,8 @@ use git2::{Oid, Repository};
|
|||
use html_escaper::{Escape, Trusted};
|
||||
use orgize::{ast::Keyword, ParseConfig};
|
||||
use rowan::ast::{support, AstNode};
|
||||
use std::{collections::BTreeMap, error::Error, fs, io::Write, path::PathBuf};
|
||||
use serde_derive::Deserialize;
|
||||
use std::{cmp::min, collections::BTreeMap, error::Error, fs, io::Write, path::PathBuf};
|
||||
|
||||
mod atom;
|
||||
mod git;
|
||||
|
@ -30,6 +31,13 @@ struct PageHtml<'a> {
|
|||
numdir: usize,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct ClamConfig {
|
||||
title: String,
|
||||
id: Option<String>,
|
||||
url: String,
|
||||
}
|
||||
|
||||
fn generate(
|
||||
org_cfg: &ParseConfig,
|
||||
repo: &Repository,
|
||||
|
@ -46,6 +54,8 @@ fn generate(
|
|||
f.write_all(include_bytes!("style.css"))?;
|
||||
}
|
||||
|
||||
let mut titles = BTreeMap::new();
|
||||
|
||||
for (dir, files) in dir_map.iter() {
|
||||
fs::create_dir_all(dir)?;
|
||||
|
||||
|
@ -66,7 +76,7 @@ fn generate(
|
|||
title = keyword.value().trim().to_string();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let (created, author) =
|
||||
ctime.get(&full_path).ok_or("missing creation time")?;
|
||||
|
@ -76,7 +86,7 @@ fn generate(
|
|||
res.traverse(&mut html_export);
|
||||
|
||||
let template = PageHtml {
|
||||
title,
|
||||
title: title.clone(),
|
||||
body: html_export.0.finish(),
|
||||
commit: short_id,
|
||||
author,
|
||||
|
@ -87,7 +97,9 @@ fn generate(
|
|||
numdir: full_path.iter().count(),
|
||||
};
|
||||
|
||||
let old_path = full_path.clone();
|
||||
full_path.set_extension("html");
|
||||
titles.insert(full_path.clone(), (title, old_path));
|
||||
|
||||
Some(template.to_string().into_bytes())
|
||||
}
|
||||
|
@ -103,6 +115,27 @@ fn generate(
|
|||
}
|
||||
}
|
||||
|
||||
if let Ok(config) = fs::read_to_string(".clam.toml") {
|
||||
let config: ClamConfig = toml::from_str(&config)?;
|
||||
|
||||
let feed = atom::entries(&titles, &mtime)?;
|
||||
|
||||
let mut f = fs::File::create("feed.xml")?;
|
||||
f.write_all(
|
||||
atom::FeedXml {
|
||||
title: &config.title,
|
||||
id: config.id.as_ref().unwrap_or(&config.url),
|
||||
url: &config.url,
|
||||
updated: &feed.first().ok_or("no entries in feed")?.updated,
|
||||
entries: &feed[..min(feed.len(), 10)],
|
||||
}
|
||||
.to_string()
|
||||
.as_bytes(),
|
||||
)?;
|
||||
} else {
|
||||
eprintln!("missing config file, skipping feed.xml creation");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -125,7 +158,7 @@ fn main() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
// TODO: get this stuff from clam.toml or something
|
||||
// TODO: get this stuff from .clam.toml or something
|
||||
let org_cfg = ParseConfig {
|
||||
todo_keywords: (
|
||||
["TODO", "PENDING", "DELAYED", "RERUN"]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<id>{{ self.id }}/feed.xml</id>
|
||||
<link rel="self" href="{{ self.url }}/feed.xml"/>
|
||||
<updated>{{ self.updated }}</updated>
|
||||
%% for entry in &self.entries {
|
||||
%% for entry in self.entries {
|
||||
<entry>
|
||||
<title>{{ entry.title }}</title>
|
||||
<id>{{ self.id }}/{{ entry.path }}</id>
|
||||
|
|
Loading…
Reference in New Issue
Block a user