shtola

ssg in rust
git clone https://tilde.team/~marisa/repo/shtola.git
Log | Files | Refs | LICENSE

commit e87fa32275c5cc8f8aa96feeb44ebb476c396537
parent d5b3aa12f550cd7447d3c2a5cdad353546e9a1c7
Author: marisa <mokou@posteo.de>
Date:   Thu,  7 Nov 2019 17:35:12 +0100

Implement directory read

Diffstat:
MCargo.lock | 23+++++++++++++++++++++++
Afixtures/simple/hello.txt | 1+
Mshtola/Cargo.toml | 2++
Ashtola/src/frontmatter.rs | 28++++++++++++++++++++++++++++
Mshtola/src/lib.rs | 73+++++++++++++++++++++++++++++++++++++++++++++++++------------------------
5 files changed, 103 insertions(+), 24 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -16,6 +16,11 @@ dependencies = [ ] [[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -24,6 +29,11 @@ dependencies = [ ] [[package]] +name = "pathdiff" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -58,8 +68,10 @@ version = "0.1.0" dependencies = [ "im 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pathdiff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "ware 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -121,10 +133,20 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "yaml-rust" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum im 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8db49f8bc08d5cc4e2bb0f7d25a6d1db2c79bc6f7d7c86c96c657eb3d214125f" +"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum pathdiff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3bf70094d203e07844da868b634207e71bfab254fe713171fae9a6e751ccf31" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" @@ -137,3 +159,4 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/fixtures/simple/hello.txt b/fixtures/simple/hello.txt @@ -0,0 +1 @@ +test diff --git a/shtola/Cargo.toml b/shtola/Cargo.toml @@ -15,3 +15,5 @@ log = "0.4.8" walkdir = "2.2.9" ware = "0.1.0" im = "13.0.0" +yaml-rust = "0.4.3" +pathdiff = "0.1.0" diff --git a/shtola/src/frontmatter.rs b/shtola/src/frontmatter.rs @@ -0,0 +1,28 @@ +use yaml_rust::{Yaml, YamlLoader}; + +#[allow(dead_code)] +pub fn lexer(text: &str) -> (String, String) { + if text.starts_with("---\n") { + let slice_after_marker = &text[4..]; + let marker_end = slice_after_marker.find("---\n").unwrap(); + let yaml_slice = &text[4..marker_end + 4]; + let content_slice = &text[marker_end + 2 * 4..]; + ( + yaml_slice.trim().to_string(), + content_slice.trim().to_string(), + ) + } else { + ( + String::new(), + text.to_string(), + ) + } +} + +#[allow(dead_code)] +pub fn to_yaml(matter: &str) -> Vec<Yaml> { + if matter.len() == 0 { + return Vec::new(); + } + YamlLoader::load_from_str(matter).unwrap() +} diff --git a/shtola/src/lib.rs b/shtola/src/lib.rs @@ -1,17 +1,23 @@ use ware::Ware; use im::HashMap; +use walkdir::WalkDir; +use yaml_rust::Yaml; +use pathdiff::diff_paths; use std::path::PathBuf; +use std::fs::{File, canonicalize}; +use std::io::Read; use std::default::Default; +mod frontmatter; + pub struct Shtola { ware: Ware<IR>, ir: IR, } impl Shtola { - pub fn new<T: Into<PathBuf>>(dir: T) -> Shtola { - let mut config: Config = Default::default(); - config.directory = dir.into(); + pub fn new() -> Shtola { + let config: Config = Default::default(); let ir = IR { files: HashMap::new(), config }; Shtola { ware: Ware::new(), ir } } @@ -22,11 +28,11 @@ impl Shtola { } pub fn source<T: Into<PathBuf>>(&mut self, path: T) { - self.ir.config.source = path.into(); + self.ir.config.source = canonicalize(path.into()).unwrap(); } pub fn destination<T: Into<PathBuf>>(&mut self, path: T) { - self.ir.config.destination = path.into(); + self.ir.config.destination = canonicalize(path.into()).unwrap(); } pub fn clean(&mut self, b: bool) { @@ -41,25 +47,25 @@ impl Shtola { self.ware.wrap(func); } - pub fn build(&mut self) -> IR { - // if clean is set, remove dest dir - // read files + pub fn build(&mut self) -> Result<IR, std::io::Error> { + // clean if set + let files = read_dir(&self.ir.config.source)?; + self.ir.files = files; let result_ir = self.ware.run(self.ir.clone()); // write files - result_ir + Ok(result_ir) } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct IR { files: HashMap<PathBuf, ShFile>, config: Config, } -#[derive(Clone, Default)] +#[derive(Debug, Clone, Default)] pub struct Config { ignores: Vec<PathBuf>, - directory: PathBuf, source: PathBuf, destination: PathBuf, clean: bool, @@ -67,23 +73,42 @@ pub struct Config { } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct ShFile { - frontmatter: HashMap<String, String>, + frontmatter: Vec<Yaml>, content: Vec<u8>, } +fn read_dir(source: &PathBuf) -> Result<HashMap<PathBuf, ShFile>, std::io::Error> { + let mut result = HashMap::new(); + let iters = WalkDir::new(source) + .into_iter() + .filter_map(|e| e.ok()) + .filter(|e| !e.path().is_dir()); + for entry in iters { + let path = entry.path(); + let mut content = String::new(); + File::open(path)?.read_to_string(&mut content)?; + let (matter, content) = frontmatter::lexer(&content); + let yaml = frontmatter::to_yaml(&matter); + let file = ShFile { + frontmatter: yaml, + content: content.into(), + }; + let rel_path = diff_paths(path, source).unwrap(); + result.insert(rel_path, file); + } + Ok(result) +} + #[test] -fn it_works() { - let mut s = Shtola::new("./"); - s.source("./"); - s.destination("./dest"); - s.register(Box::new(|mut ir| { - ir.files.insert(PathBuf::from("cool.md"), ShFile { frontmatter: HashMap::new(), content: Vec::new() }); - ir - })); - let r = s.build(); +fn read_works() { + let mut s = Shtola::new(); + s.source("../fixtures/simple"); + s.destination("./"); + s.clean(true); + let r = s.build().unwrap(); assert_eq!(r.files.len(), 1); let keys: Vec<&PathBuf> = r.files.keys().collect(); - assert_eq!(keys[0].to_str().unwrap(), "cool.md"); + assert_eq!(keys[0].to_str().unwrap(), "hello.txt"); }