118 lines
3.2 KiB
Rust
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(())
|
|
}
|