damn i definitely did something
This commit is contained in:
parent
696bfa0afe
commit
fbea17767b
39
Cargo.lock
generated
39
Cargo.lock
generated
|
@ -80,6 +80,12 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -134,9 +140,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.14.0"
|
version = "3.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
|
@ -189,9 +195,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.0"
|
version = "4.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f"
|
checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
@ -199,9 +205,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.0"
|
version = "4.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99"
|
checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
|
@ -303,9 +309,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deunicode"
|
name = "deunicode"
|
||||||
version = "1.4.2"
|
version = "1.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3ae2a35373c5c74340b79ae6780b498b2b183915ec5dacf263aac5a099bf485a"
|
checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
|
@ -813,6 +819,7 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
name = "roxy_cli"
|
name = "roxy_cli"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
"glob",
|
"glob",
|
||||||
"roxy_core",
|
"roxy_core",
|
||||||
|
@ -830,7 +837,11 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roxy_core"
|
name = "roxy_core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://fem.mint.lgbt/kitsunecafe/roxy-core.git#7839db8b062698adfe81a86d2a0cf041a6711456"
|
source = "git+https://fem.mint.lgbt/kitsunecafe/roxy-core.git#6b5b3520b0623af071ffd3053c60448c8a0b66d3"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roxy_markdown_parser"
|
name = "roxy_markdown_parser"
|
||||||
|
@ -854,7 +865,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roxy_syntect"
|
name = "roxy_syntect"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://fem.mint.lgbt/kitsunecafe/roxy-syntect.git#48601fc5e6e0ee0e753c892f0eb42a9b0b48be99"
|
source = "git+https://fem.mint.lgbt/kitsunecafe/roxy-syntect.git#4a872d3642a428fc91afe3a519e9e4d1f3a6d3d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -978,9 +989,9 @@ checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.48"
|
version = "2.0.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1105,9 +1116,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.22.5"
|
version = "0.22.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99e68c159e8f5ba8a28c4eb7b0c0c190d77bb479047ca713270048145a9ad28a"
|
checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -16,4 +16,5 @@ toml = "0.8.8"
|
||||||
tera = "1.19.1"
|
tera = "1.19.1"
|
||||||
serde = { version = "1.0.195", features = ["derive"]}
|
serde = { version = "1.0.195", features = ["derive"]}
|
||||||
slugify = "0.1.0"
|
slugify = "0.1.0"
|
||||||
|
anyhow = "1.0.79"
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
use std::{path::Path, borrow::BorrowMut};
|
use std::{
|
||||||
|
borrow::BorrowMut,
|
||||||
|
fs::File,
|
||||||
|
io::{BufReader, Read},
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use tera::{Map, Value};
|
use crate::{file_path::FilePath, iter_ext::Head};
|
||||||
use crate::iter_ext::Head;
|
use roxy_core::result::Result;
|
||||||
|
use tera::{to_value, Map, Value};
|
||||||
|
use toml::Table;
|
||||||
|
|
||||||
fn merge(a: &mut Value, b: Value) {
|
fn merge(a: &mut Value, b: Value) {
|
||||||
match (a, b) {
|
match (a, b) {
|
||||||
|
@ -24,17 +31,64 @@ pub(crate) struct Context {
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: tera::Value::Null
|
inner: tera::Value::Null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merge(&mut self, other: tera::Context) {
|
pub fn merge(&mut self, other: tera::Context) {
|
||||||
merge(
|
merge(self.inner.borrow_mut(), other.into_json())
|
||||||
self.inner.borrow_mut(),
|
|
||||||
other.into_json()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_formatted_path<P: AsRef<Path>>(path: &P) -> Option<PathBuf> {
|
||||||
|
let path = path.as_ref();
|
||||||
|
if path.with_extension("").file_name()? == "index" {
|
||||||
|
Some(path.with_file_name(""))
|
||||||
|
} else {
|
||||||
|
Some(path.with_extension(""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_files<'a, T: AsRef<Path>>(
|
||||||
|
files: Vec<&PathBuf>,
|
||||||
|
file_path: &'a FilePath<T>,
|
||||||
|
) -> Result<Context> {
|
||||||
|
let mut context = Context::new();
|
||||||
|
|
||||||
|
for path in files {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
|
||||||
|
let mut file = File::open(path).map(BufReader::new)?;
|
||||||
|
file.read_to_end(&mut buf)?;
|
||||||
|
let mut str = String::from_utf8(buf).map_err(anyhow::Error::from)?;
|
||||||
|
let toml: Table = toml::from_str(&mut str).map_err(anyhow::Error::from)?;
|
||||||
|
|
||||||
|
let path = file_path.strip_root(path).map_err(anyhow::Error::from)?;
|
||||||
|
|
||||||
|
context.insert(&path, &tera::to_value(toml).map_err(anyhow::Error::from)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_paths<'a, T: AsRef<Path>>(
|
||||||
|
&mut self,
|
||||||
|
files: &Vec<&PathBuf>,
|
||||||
|
file_path: &'a FilePath<T>,
|
||||||
|
) -> Result<()> {
|
||||||
|
for path in files {
|
||||||
|
let path = file_path.strip_root(path).map_err(anyhow::Error::from)?;
|
||||||
|
if let Some(path) = Self::as_formatted_path(&path) {
|
||||||
|
if let Some(slug) = file_path.as_slug(&path) {
|
||||||
|
let slug = PathBuf::from("/").join(slug);
|
||||||
|
if let Ok(slug) = to_value(slug) {
|
||||||
|
self.insert(&path.join("path"), &slug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn path_to_string<P: AsRef<Path>>(path: &P) -> String {
|
fn path_to_string<P: AsRef<Path>>(path: &P) -> String {
|
||||||
path.as_ref().to_string_lossy().to_string()
|
path.as_ref().to_string_lossy().to_string()
|
||||||
|
@ -57,9 +111,9 @@ impl Context {
|
||||||
Some(map.into())
|
Some(map.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert<P: AsRef<Path>>(&mut self, path: &P, value: &Value) {
|
fn as_key<P: AsRef<Path>>(path: &P) -> Option<&Path> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
let path = if path
|
if path
|
||||||
.with_extension("")
|
.with_extension("")
|
||||||
.file_name()
|
.file_name()
|
||||||
.map_or(false, |f| f.to_os_string() == "index")
|
.map_or(false, |f| f.to_os_string() == "index")
|
||||||
|
@ -67,7 +121,11 @@ impl Context {
|
||||||
path.parent()
|
path.parent()
|
||||||
} else {
|
} else {
|
||||||
Some(path)
|
Some(path)
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert<P: AsRef<Path>>(&mut self, path: &P, value: &Value) {
|
||||||
|
let path = Self::as_key(path).map(|p| p.with_extension(""));
|
||||||
|
|
||||||
if let Some(v) = Self::create_path(&path.unwrap(), value) {
|
if let Some(v) = Self::create_path(&path.unwrap(), value) {
|
||||||
if let Ok(ctx) = tera::Context::from_value(v) {
|
if let Ok(ctx) = tera::Context::from_value(v) {
|
||||||
|
@ -76,8 +134,12 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<P: AsRef<Path>>(&self, _path: &P) -> Option<&Value> {
|
pub fn get<P: AsRef<Path>>(&self, path: &P) -> Option<&Value> {
|
||||||
None
|
Self::as_key(path)?
|
||||||
|
.with_extension("")
|
||||||
|
.components()
|
||||||
|
.filter_map(|c| c.as_os_str().to_str())
|
||||||
|
.try_fold(&self.inner, |acc, i| acc.get(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +152,7 @@ impl Into<tera::Value> for Context {
|
||||||
impl TryInto<tera::Context> for Context {
|
impl TryInto<tera::Context> for Context {
|
||||||
type Error = tera::Error;
|
type Error = tera::Error;
|
||||||
|
|
||||||
fn try_into(self) -> Result<tera::Context, Self::Error> {
|
fn try_into(self) -> std::result::Result<tera::Context, Self::Error> {
|
||||||
tera::Context::from_value(self.inner)
|
tera::Context::from_value(self.inner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
69
src/main.rs
69
src/main.rs
|
@ -19,30 +19,21 @@ use roxy_tera_parser::{TeraParser, TeraParserOptions};
|
||||||
use clap::Parser as Clap;
|
use clap::Parser as Clap;
|
||||||
use std::{
|
use std::{
|
||||||
ffi,
|
ffi,
|
||||||
fs::{self, File},
|
fs,
|
||||||
io::{BufReader, Read},
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
use tera::to_value;
|
|
||||||
|
|
||||||
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet};
|
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet};
|
||||||
use toml::Table;
|
|
||||||
|
|
||||||
use glob::glob;
|
use glob::glob;
|
||||||
use roxy_core::roxy::{Parser, Roxy};
|
use roxy_core::roxy::{Parser, Roxy};
|
||||||
|
use roxy_core::result::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::iter_ext::{Head, MapFoldExt};
|
||||||
iter_ext::{Head, MapFoldExt},
|
|
||||||
result_ext::FilterExt,
|
|
||||||
};
|
|
||||||
|
|
||||||
const DEFAULT_THEME: &'static str = "base16-ocean.dark";
|
const DEFAULT_THEME: &'static str = "base16-ocean.dark";
|
||||||
const CONTENT_EXT: [&'static str; 4] = ["md", "tera", "html", "htm"];
|
const CONTENT_EXT: [&'static str; 4] = ["md", "tera", "html", "htm"];
|
||||||
|
|
||||||
fn handle_err<E: std::error::Error + 'static>(err: E) -> Error {
|
|
||||||
Error::new(err.to_string(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Clap)]
|
||||||
#[command(name = "Roxy")]
|
#[command(name = "Roxy")]
|
||||||
#[command(author = "KitsuneCafe")]
|
#[command(author = "KitsuneCafe")]
|
||||||
|
@ -53,14 +44,14 @@ pub struct Options {
|
||||||
pub output: String,
|
pub output: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_files<P: AsRef<Path> + std::fmt::Debug>(path: &P) -> Result<Vec<PathBuf>, Error> {
|
fn get_files<P: AsRef<Path> + std::fmt::Debug>(path: &P) -> Result<Vec<PathBuf>> {
|
||||||
let path = path
|
let path = path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok_or_else(|| Error::from(format!("{path:?} is not a valid path.")))?;
|
.ok_or_else(|| anyhow::Error::msg(format!("{path:?} is not a valid path.")))?;
|
||||||
|
|
||||||
let files: Vec<PathBuf> = glob(path)
|
let files: Vec<PathBuf> = glob(path)
|
||||||
.map_err(handle_err)?
|
.map_err(anyhow::Error::from)?
|
||||||
.filter_map(|x| x.ok())
|
.filter_map(|x| x.ok())
|
||||||
.filter(|f| Path::is_file(f))
|
.filter(|f| Path::is_file(f))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -101,49 +92,10 @@ fn load_config(path: &Path) -> Config {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_formatted_path<P: AsRef<Path>>(path: &P) -> Option<PathBuf> {
|
|
||||||
let path = path.as_ref();
|
|
||||||
if path.with_extension("").file_name()? == "index" {
|
|
||||||
Some(path.with_file_name(""))
|
|
||||||
} else {
|
|
||||||
Some(path.with_extension(""))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn context_from_meta_files<'a, T: AsRef<Path>>(
|
|
||||||
files: &Vec<&PathBuf>,
|
|
||||||
file_path: &'a FilePath<T>,
|
|
||||||
) -> Result<Context, Error> {
|
|
||||||
let mut context = Context::new();
|
|
||||||
|
|
||||||
for path in files {
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
|
|
||||||
let mut file = File::open(path).map(BufReader::new)?;
|
|
||||||
file.read_to_end(&mut buf)?;
|
|
||||||
let mut str = String::from_utf8(buf).map_err(handle_err)?;
|
|
||||||
let toml: Table = toml::from_str(&mut str).map_err(handle_err)?;
|
|
||||||
|
|
||||||
let path = file_path.strip_root(path)?;
|
|
||||||
|
|
||||||
context.insert(&path, &tera::to_value(toml).map_err(handle_err)?);
|
|
||||||
if let Some(path) = as_formatted_path(&path) {
|
|
||||||
if let Some(slug) = file_path.as_slug(&path) {
|
|
||||||
let slug = PathBuf::from("/").join(slug);
|
|
||||||
if let Ok(slug) = to_value(slug) {
|
|
||||||
context.insert(&path.join("path"), &slug);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn copy_static<T: AsRef<Path>>(
|
fn copy_static<T: AsRef<Path>>(
|
||||||
files: &Vec<&PathBuf>,
|
files: &Vec<&PathBuf>,
|
||||||
file_path: &FilePath<T>,
|
file_path: &FilePath<T>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<()> {
|
||||||
for file in files {
|
for file in files {
|
||||||
let output = file_path.to_output(file).unwrap();
|
let output = file_path.to_output(file).unwrap();
|
||||||
fs::create_dir_all(output.parent().unwrap())?;
|
fs::create_dir_all(output.parent().unwrap())?;
|
||||||
|
@ -153,7 +105,7 @@ fn copy_static<T: AsRef<Path>>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<()> {
|
||||||
let opts = Options::parse();
|
let opts = Options::parse();
|
||||||
|
|
||||||
let mut file_path = FilePath::new(&opts.input, &opts.output);
|
let mut file_path = FilePath::new(&opts.input, &opts.output);
|
||||||
|
@ -173,7 +125,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
CONTENT_EXT.contains(&ext)
|
CONTENT_EXT.contains(&ext)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut context: Context = context_from_meta_files(&meta, &file_path)?;
|
let mut context = Context::from_files(meta, &file_path)?;
|
||||||
|
context.build_paths(&content, &file_path)?;
|
||||||
|
|
||||||
let theme = config.syntect.theme;
|
let theme = config.syntect.theme;
|
||||||
|
|
||||||
|
@ -205,7 +158,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut rewriter = MarkdownTeraRewriter::new();
|
let mut rewriter = MarkdownTeraRewriter::new();
|
||||||
parser.push(&mut rewriter);
|
parser.push(&mut rewriter);
|
||||||
|
|
||||||
if let Ok(path) = &file_path.strip_root(&file_name) {
|
if let Ok(path) = &file_path.strip_root(&file) {
|
||||||
if let Some(current_context) = context.get(path) {
|
if let Some(current_context) = context.get(path) {
|
||||||
context.insert(&"this", ¤t_context.clone());
|
context.insert(&"this", ¤t_context.clone());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue