org-static/src/lib.rs

118 lines
3.2 KiB
Rust

#![allow(non_snake_case)]
mod article;
mod config;
mod error;
mod site;
mod template;
use article::{Article, ArticleContext};
use std::path::PathBuf;
use template::TemplateEngine;
use walkdir::WalkDir;
use emacs::{defun, Env, IntoLisp, Result, Vector};
emacs::plugin_is_GPL_compatible!();
#[emacs::module(name = "liborg_static", defun_prefix = "org-static")]
fn init(e: &Env) -> Result<()> {
e.message("orgstatic loaded")?;
Ok(())
}
fn find_articles(env: &Env, config: &config::Config) -> Result<Vec<Article>> {
let mut articles: Vec<Article> = vec![];
for entry in WalkDir::new(&config.get_articles_path())
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().map(|ex| ex == "org").unwrap_or(false))
{
let file_path = entry.path().canonicalize()?;
let article_data = Vector::from_value_unchecked(
env.call(
"org-static-file-info",
[file_path
.to_str()
.unwrap_or_default()
.to_string()
.into_lisp(env)?],
)?,
3,
);
let title = article_data.get::<String>(0)?;
let author = article_data.get::<String>(1)?;
let date = article_data.get::<String>(2)?;
let slug = {
let s = article_data.get::<String>(3)?;
if s.is_empty() {
file_path
.file_name()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
.to_string()
} else {
s
}
};
let tags = article_data
.get::<String>(4)?
.split(':')
.filter(|i| !i.is_empty())
.map(|i| i.to_string())
.collect();
articles.push(Article {
title,
slug,
date,
author,
file_path,
tags,
});
}
Ok(articles)
}
fn publish_articles(env: &Env, config: &config::Config, articles: &[Article]) -> Result<()> {
let eng = TemplateEngine::new(config.get_partials_path())?;
for article in articles {
std::fs::create_dir_all(article.get_build_path(config))?;
let content = env
.call(
"org-static-file-contents",
[article
.file_path
.to_str()
.unwrap_or_default()
.to_string()
.into_lisp(env)?],
)?
.into_rust::<String>()?;
let ctx = ArticleContext::new(article.clone(), content);
eng.render_file(
config.get_theme_path().join("articles.html"),
article.get_build_path(config).join("index.html"),
&ctx,
)?;
}
Ok(())
}
#[defun]
pub fn publish(env: &Env, starting_path: String) -> Result<()> {
let cfg = config::Config::find(PathBuf::from(starting_path))?;
println!("{:?}", cfg);
let articles = find_articles(env, &cfg)?;
env.message(format!("{} articles found", articles.len()))?;
publish_articles(env, &cfg, &articles)?;
Ok(())
}