Broke up modules
This commit is contained in:
parent
2bebd0e540
commit
07f304066a
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -824,6 +824,7 @@ dependencies = [
|
|||
"roxy_core",
|
||||
"roxy_markdown_parser",
|
||||
"roxy_markdown_tera_rewriter",
|
||||
"roxy_syntect",
|
||||
"roxy_tera_parser",
|
||||
"serde",
|
||||
"syntect",
|
||||
|
@ -848,15 +849,28 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "roxy_markdown_tera_rewriter"
|
||||
version = "0.1.0"
|
||||
source = "git+https://fem.mint.lgbt/kitsunecafe/roxy-markdown-tera-rewriter.git#5c33c0c2625c239694c8b7bb16f5da902cfd5e44"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"regex",
|
||||
"roxy_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roxy_syntect"
|
||||
version = "0.1.0"
|
||||
source = "git+https://fem.mint.lgbt/kitsunecafe/roxy-syntect.git#0cdfa876f9ca13be475dfac77b0d37ebb7d45da3"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"regex",
|
||||
"roxy_core",
|
||||
"syntect",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roxy_tera_parser"
|
||||
version = "0.1.0"
|
||||
source = "git+https://fem.mint.lgbt/kitsunecafe/roxy-tera-parser.git#d8bd4aa1f0bbe4f9982ae17711ed69fead71c327"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"regex",
|
||||
|
@ -1370,9 +1384,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.36"
|
||||
version = "0.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "818ce546a11a9986bc24f93d0cdf38a8a1a400f1473ea8c82e59f6e0ffab9249"
|
||||
checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
|
@ -9,6 +9,7 @@ syntect = "5.1.0"
|
|||
roxy_markdown_parser = { git = "https://fem.mint.lgbt/kitsunecafe/roxy-markdown-parser.git" }
|
||||
roxy_tera_parser = { git = "https://fem.mint.lgbt/kitsunecafe/roxy-tera-parser.git" }
|
||||
roxy_markdown_tera_rewriter = { git = "https://fem.mint.lgbt/kitsunecafe/roxy-markdown-tera-rewriter.git" }
|
||||
roxy_syntect = { git = "https://fem.mint.lgbt/kitsunecafe/roxy-syntect.git" }
|
||||
roxy_core = { git = "https://fem.mint.lgbt/kitsunecafe/roxy-core.git" }
|
||||
clap = { version = "4.4.17", features = ["derive"] }
|
||||
toml = "0.8.8"
|
||||
|
|
31
src/config.rs
Normal file
31
src/config.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub(crate) struct Config {
|
||||
pub theme: Option<String>,
|
||||
pub themes: Vec<String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn merge(self, other: Config) -> Self {
|
||||
Self {
|
||||
theme: self.theme.or(other.theme),
|
||||
themes: if self.themes.is_empty() {
|
||||
other.themes
|
||||
} else {
|
||||
self.themes
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Config {
|
||||
type Err = toml::de::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
toml::from_str(s)
|
||||
}
|
||||
}
|
||||
|
39
src/context.rs
Normal file
39
src/context.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
use std::path::{Path, MAIN_SEPARATOR_STR};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Context {
|
||||
inner: tera::Context,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: tera::Context::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_inner(&self) -> &tera::Context {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn normalize_path<P: AsRef<Path>>(path: &P) -> String {
|
||||
path.as_ref()
|
||||
.with_extension("")
|
||||
.to_string_lossy()
|
||||
.trim()
|
||||
.split(MAIN_SEPARATOR_STR)
|
||||
.fold(String::new(), |a, b| format!("{a}.{b}"))
|
||||
.trim_matches('.')
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn insert<P: AsRef<Path>>(&mut self, path: &P, value: &tera::Value) {
|
||||
self.inner
|
||||
.insert(Self::normalize_path(path).trim_start_matches('.'), &value);
|
||||
}
|
||||
|
||||
pub fn get<P: AsRef<Path>>(&self, path: &P) -> Option<&tera::Value> {
|
||||
self.inner.get(&Self::normalize_path(path))
|
||||
}
|
||||
}
|
||||
|
36
src/error.rs
Normal file
36
src/error.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use std::{io::{Error as IOError, ErrorKind}, path::StripPrefixError};
|
||||
|
||||
use glob::PatternError;
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl From<String> for Error {
|
||||
fn from(value: String) -> Self {
|
||||
Self { message: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PatternError> for Error {
|
||||
fn from(value: PatternError) -> Self {
|
||||
Self {
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StripPrefixError> for Error {
|
||||
fn from(value: StripPrefixError) -> Self {
|
||||
Self {
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for IOError {
|
||||
fn from(value: Error) -> Self {
|
||||
IOError::new(ErrorKind::Other, value.message)
|
||||
}
|
||||
}
|
||||
|
52
src/file_path.rs
Normal file
52
src/file_path.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use std::path::{PathBuf, Path, StripPrefixError};
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct FilePath<'a, P: AsRef<Path>> {
|
||||
pub input: PathBuf,
|
||||
pub root_dir: PathBuf,
|
||||
pub 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, Error> {
|
||||
value
|
||||
.as_ref()
|
||||
.strip_prefix(&self.root_dir)
|
||||
.map(|path| self.output.as_ref().join(path))
|
||||
.map_err(Error::from)
|
||||
}
|
||||
|
||||
pub fn strip_root<P2: AsRef<Path>>(&self, value: &'a P2) -> Result<&Path, StripPrefixError> {
|
||||
value.as_ref().strip_prefix(&self.root_dir)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
159
src/main.rs
159
src/main.rs
|
@ -1,17 +1,29 @@
|
|||
pub mod error;
|
||||
pub mod context;
|
||||
pub mod config;
|
||||
mod file_path;
|
||||
|
||||
use clap::Parser as Clap;
|
||||
use config::Config;
|
||||
use context::Context;
|
||||
use file_path::FilePath;
|
||||
use crate::error::Error;
|
||||
use roxy_markdown_parser::MarkdownParser;
|
||||
use roxy_markdown_tera_rewriter::{MarkdownTeraRewriter, MarkdownTeraPreformatter};
|
||||
use roxy_markdown_tera_rewriter::{MarkdownTeraPreformatter, MarkdownTeraRewriter};
|
||||
use roxy_syntect::SyntectParser;
|
||||
use roxy_tera_parser::{TeraParser, TeraParserOptions};
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufReader, Error, ErrorKind, Read},
|
||||
path::{self, Path, PathBuf, StripPrefixError},
|
||||
fs::{self, File},
|
||||
io::{BufReader, Read},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use toml::Table;
|
||||
|
||||
use glob::{glob, PatternError};
|
||||
use glob::glob;
|
||||
use roxy_core::roxy::{Parser, Roxy};
|
||||
|
||||
const DEFAULT_THEME: &'static str = "base16-ocean.dark";
|
||||
|
||||
#[derive(Clap)]
|
||||
#[command(name = "Roxy")]
|
||||
#[command(author = "KitsuneCafe")]
|
||||
|
@ -22,44 +34,11 @@ pub struct Options {
|
|||
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> {
|
||||
fn get_files<P: AsRef<Path> + std::fmt::Debug>(path: &P) -> Result<Vec<PathBuf>, Error> {
|
||||
let path = path
|
||||
.as_ref()
|
||||
.to_str()
|
||||
.ok_or_else(|| RoxyError::from(format!("{path:?} is not a valid path.")))?;
|
||||
.ok_or_else(|| Error::from(format!("{path:?} is not a valid path.")))?;
|
||||
|
||||
let files: Vec<PathBuf> = glob(path)?
|
||||
.filter_map(|x| x.ok())
|
||||
|
@ -69,89 +48,21 @@ fn get_files<P: AsRef<Path> + std::fmt::Debug>(path: &P) -> Result<Vec<PathBuf>,
|
|||
Ok(files)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn strip_root<P2: AsRef<Path>>(&self, value: &'a P2) -> Result<&Path, StripPrefixError> {
|
||||
value.as_ref().strip_prefix(&self.root_dir)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Context {
|
||||
pub inner: tera::Context,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
inner: tera::Context::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_path<P: AsRef<Path>>(path: &P) -> String {
|
||||
path.as_ref()
|
||||
.with_extension("")
|
||||
.to_string_lossy()
|
||||
.trim()
|
||||
.split(path::MAIN_SEPARATOR_STR)
|
||||
.fold(String::new(), |a, b| format!("{a}.{b}"))
|
||||
.trim_matches('.')
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn insert<P: AsRef<Path>>(&mut self, path: &P, value: &tera::Value) {
|
||||
self.inner
|
||||
.insert(Self::normalize_path(path).trim_start_matches('.'), &value);
|
||||
}
|
||||
|
||||
fn get<P: AsRef<Path>>(&self, path: &P) -> Option<&tera::Value> {
|
||||
self.inner.get(&Self::normalize_path(path))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), RoxyError> {
|
||||
fn main() -> Result<(), Error> {
|
||||
let opts = Options::parse();
|
||||
|
||||
let file_path = FilePath::new(&opts.input, &opts.output);
|
||||
|
||||
let config_path = file_path.input.with_file_name("config.toml");
|
||||
let config = fs::read_to_string(&config_path).map_or_else(
|
||||
|_| Config::default(),
|
||||
|f| {
|
||||
toml::from_str::<Config>(f.as_str())
|
||||
.unwrap()
|
||||
.merge(Config::default())
|
||||
},
|
||||
);
|
||||
|
||||
let files = get_files(&file_path.input)?;
|
||||
let (meta, files): (Vec<&PathBuf>, Vec<&PathBuf>) =
|
||||
files.iter().partition(|f| f.extension().unwrap() == "toml");
|
||||
|
@ -172,11 +83,15 @@ fn main() -> Result<(), RoxyError> {
|
|||
);
|
||||
}
|
||||
|
||||
let theme = config.theme.unwrap_or(DEFAULT_THEME.to_string());
|
||||
for file in files {
|
||||
let mut parser = Parser::new();
|
||||
let mut preformatter = MarkdownTeraPreformatter::new();
|
||||
parser.push(&mut preformatter);
|
||||
|
||||
let mut syntect = SyntectParser::new(&theme.as_str());
|
||||
parser.push(&mut syntect);
|
||||
|
||||
let mut md = MarkdownParser::new();
|
||||
parser.push(&mut md);
|
||||
|
||||
|
@ -194,10 +109,10 @@ fn main() -> Result<(), RoxyError> {
|
|||
|
||||
let mut tera = tera::Tera::default();
|
||||
let mut html = TeraParser::new(&mut tera, TeraParserOptions::default());
|
||||
html.add_context(&context.inner);
|
||||
html.add_context(context.to_inner());
|
||||
parser.push(&mut html);
|
||||
|
||||
Roxy::process_file(&file, &output_path, &mut parser).unwrap();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue