124 lines
3 KiB
Rust
124 lines
3 KiB
Rust
use clap::Parser as Clap;
|
|
use std::{
|
|
io::{Error, ErrorKind},
|
|
path::{Path, PathBuf, StripPrefixError},
|
|
};
|
|
|
|
use glob::{glob, PatternError};
|
|
use roxy_core::roxy::{Html, Markdown, Parser, Roxy};
|
|
|
|
#[derive(Clap)]
|
|
#[command(name = "Roxy")]
|
|
#[command(author = "KitsuneCafe")]
|
|
#[command(version = "2.0")]
|
|
#[command(about = "A very small static site generator", long_about = None)]
|
|
pub struct Options {
|
|
pub input: String,
|
|
pub output: String,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct RoxyError {
|
|
message: String,
|
|
}
|
|
|
|
impl From<String> for RoxyError {
|
|
fn from(value: String) -> Self {
|
|
Self { message: value }
|
|
}
|
|
}
|
|
|
|
impl From<PatternError> for RoxyError {
|
|
fn from(value: PatternError) -> Self {
|
|
Self {
|
|
message: value.to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<StripPrefixError> for RoxyError {
|
|
fn from(value: StripPrefixError) -> Self {
|
|
Self {
|
|
message: value.to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<RoxyError> for Error {
|
|
fn from(value: RoxyError) -> Self {
|
|
Error::new(ErrorKind::Other, value.message)
|
|
}
|
|
}
|
|
|
|
fn get_files<P: AsRef<Path> + std::fmt::Debug>(path: &P) -> Result<Vec<PathBuf>, RoxyError> {
|
|
let path = path
|
|
.as_ref()
|
|
.to_str()
|
|
.ok_or_else(|| RoxyError::from(format!("{path:?} is not a valid path.")))?;
|
|
|
|
let files: Vec<PathBuf> = glob(path)?
|
|
.filter_map(|x| x.ok())
|
|
.filter(|f| Path::is_file(f))
|
|
.collect();
|
|
|
|
Ok(files)
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct FilePath<'a, P: AsRef<Path>> {
|
|
input: PathBuf,
|
|
root_dir: PathBuf,
|
|
output: &'a P,
|
|
}
|
|
|
|
impl<'a, P: AsRef<Path> + 'a> FilePath<'a, P> {
|
|
pub fn new(input: &'a P, output: &'a P) -> Self {
|
|
Self {
|
|
input: Self::make_recursive(input),
|
|
root_dir: Self::strip_wildcards(input),
|
|
output,
|
|
}
|
|
}
|
|
|
|
fn make_recursive(path: &'a P) -> PathBuf {
|
|
path.as_ref().join("**/*")
|
|
}
|
|
|
|
fn has_no_wildcard<S: AsRef<str>>(path: &S) -> bool {
|
|
!path.as_ref().contains("*")
|
|
}
|
|
|
|
fn strip_wildcards<P2: AsRef<Path> + ?Sized>(path: &'a P2) -> PathBuf {
|
|
path.as_ref()
|
|
.ancestors()
|
|
.map(Path::to_str)
|
|
.flatten()
|
|
.find(Self::has_no_wildcard)
|
|
.map_or_else(|| PathBuf::new(), PathBuf::from)
|
|
}
|
|
|
|
pub fn to_output<P2: AsRef<Path>>(&self, value: &'a P2) -> Result<PathBuf, RoxyError> {
|
|
value
|
|
.as_ref()
|
|
.strip_prefix(&self.root_dir)
|
|
.map(|path| self.output.as_ref().join(path))
|
|
.map_err(RoxyError::from)
|
|
}
|
|
}
|
|
|
|
fn main() -> Result<(), RoxyError> {
|
|
let opts = Options::parse();
|
|
let mut parser = Parser::new();
|
|
parser.push(Markdown::new());
|
|
let html = Html::default();
|
|
parser.push(html);
|
|
let file_path = FilePath::new(&opts.input, &opts.output);
|
|
|
|
for file in get_files(&file_path.input)? {
|
|
let file_name = file.with_extension("html");
|
|
let _ = Roxy::process_file(&file, &(&file_path.to_output(&file_name)?), &mut parser);
|
|
}
|
|
|
|
Ok(())
|
|
}
|