Finalize new page -command

This commit is contained in:
Sofia 2018-04-17 00:31:44 +03:00
parent 5b69245697
commit cb09cb694b
8 changed files with 174 additions and 19 deletions

7
Cargo.lock generated
View File

@ -71,6 +71,11 @@ dependencies = [
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "pathdiff"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.3.6" version = "0.3.6"
@ -193,6 +198,7 @@ name = "teascade-generator"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pathdiff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
@ -304,6 +310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum pathdiff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3bf70094d203e07844da868b634207e71bfab254fe713171fae9a6e751ccf31"
"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" "checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a"

View File

@ -11,3 +11,4 @@ serde = "*"
serde_derive = "*" serde_derive = "*"
regex = "*" regex = "*"
ansi_term = "*" ansi_term = "*"
pathdiff = "*"

View File

@ -9,13 +9,13 @@ use std::collections::HashMap;
use logger::LogLevel; use logger::LogLevel;
use error::Error; use error::Error;
#[derive(Deserialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
pub struct GlobalConfigToml { pub struct GlobalConfigToml {
pub website: WebsiteConfig, pub website: WebsiteConfig,
pub navbar: Option<NavbarConfig>, pub navbar: Option<NavbarConfig>,
} }
#[derive(Deserialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
pub struct WebsiteConfig { pub struct WebsiteConfig {
pub website_name: String, pub website_name: String,
pub built_pages: Vec<String>, pub built_pages: Vec<String>,
@ -31,14 +31,14 @@ pub struct WebsiteConfig {
pub google_site_verification: Option<String>, pub google_site_verification: Option<String>,
} }
#[derive(Deserialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
pub struct NavbarConfig { pub struct NavbarConfig {
pub items: Vec<String>, pub items: Vec<String>,
#[serde(rename = "item")] #[serde(rename = "item")]
pub item_map: HashMap<String, NavbarItem>, pub item_map: HashMap<String, NavbarItem>,
} }
#[derive(Deserialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
pub struct NavbarItem { pub struct NavbarItem {
pub title: String, pub title: String,
pub link: String, pub link: String,
@ -69,7 +69,7 @@ impl GlobalConfigToml {
} }
} }
#[derive(Deserialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
pub struct PageConfigToml { pub struct PageConfigToml {
pub page: PageConfig, pub page: PageConfig,
} }
@ -118,7 +118,7 @@ impl PageConfigToml {
} }
} }
#[derive(Deserialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
pub struct PageConfig { pub struct PageConfig {
pub html_path: String, pub html_path: String,
pub title: String, pub title: String,

View File

@ -8,7 +8,6 @@ use logger::LogLevel;
pub fn add_to_beginning<T: Into<String>>(path: PathBuf, to_add: T) -> Result<PathBuf, Error> { pub fn add_to_beginning<T: Into<String>>(path: PathBuf, to_add: T) -> Result<PathBuf, Error> {
if let (Some(parent), Some(file_name)) = (path.clone().parent(), path.clone().file_name()) { if let (Some(parent), Some(file_name)) = (path.clone().parent(), path.clone().file_name()) {
let parent = Path::new(&to_add.into()).join(parent); let parent = Path::new(&to_add.into()).join(parent);
create_dir_all(parent.clone())?;
Ok(parent.join(file_name)) Ok(parent.join(file_name))
} else { } else {
return Err(Error::new( return Err(Error::new(
@ -23,6 +22,15 @@ pub fn write_file<T: Into<String>>(
content: T, content: T,
overwrite: bool, overwrite: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
if let Some(parent) = path.clone().parent() {
create_dir_all(parent.clone())?;
} else {
return Err(Error::new(
LogLevel::SEVERE,
format!("Could not find parent folder for {:?}", path),
));
}
let content = content.into(); let content = content.into();
if path.exists() && !overwrite { if path.exists() && !overwrite {
Err(Error::new( Err(Error::new(

View File

@ -1,4 +1,5 @@
extern crate ansi_term; extern crate ansi_term;
extern crate pathdiff;
extern crate pulldown_cmark; extern crate pulldown_cmark;
extern crate regex; extern crate regex;
#[macro_use] #[macro_use]
@ -15,6 +16,7 @@ mod config;
mod template; mod template;
mod renderer; mod renderer;
mod builder; mod builder;
mod new_page;
mod file_writer; mod file_writer;
use structopt::StructOpt; use structopt::StructOpt;
@ -36,16 +38,15 @@ fn main() {
logger.log(LogLevel::SEVERE, "Aborting building due to error."); logger.log(LogLevel::SEVERE, "Aborting building due to error.");
} }
}, },
Subcommands::New(ops) => { Subcommands::New(ops) => match new_page::generate_new_page(ops, &logger) {
logger.log( Ok(_) => logger.log(
LogLevel::DETAIL, LogLevel::DETAILER,
format!("Creating a new .toml file at {:?}", ops.toml_path), "Generating the new page finished successfully.",
); ),
Err(err) => {
match file_writer::write_file(ops.toml_path, "Hello!", ops.overwrite) { logger.log(err.severity(), err.description());
Ok(_) => logger.log(LogLevel::INFO, "Done."), logger.log(LogLevel::SEVERE, "Aborting building due to error.");
Err(err) => logger.log(err.severity(), err.description()), }
} },
}
} }
} }

133
src/new_page.rs Normal file
View File

@ -0,0 +1,133 @@
use std::path::PathBuf;
use std::error::Error as STDError;
use options::NewOps;
use logger::{LogLevel, Logger};
use file_writer;
use error::Error;
use config_toml::{PageConfig, PageConfigToml};
use toml;
use pathdiff;
const PLACEHOLDER_MARKDOWN: &'static str =
r#"# Placeholder title
This is the markdown file, where you will insert this page's contents.
- This is an example list
- And in lists
- You can even make inner lists, as well as **bold**, and _italics_
See [CommonMark](http://commonmark.org/help/) for reference."#;
pub fn generate_new_page(ops: NewOps, logger: &Logger) -> Result<(), Error> {
logger.log(
LogLevel::DETAILER,
format!("Starting to create paths for given files"),
);
let toml_path = ensure_extension(ops.toml_path, "toml", false)?;
let markdown_path;
if let Some(markdown) = ops.markdown_path {
markdown_path = ensure_extension(markdown, "md", false)?;
} else {
markdown_path = ensure_extension(toml_path.clone(), "md", true)?;
}
logger.log(
LogLevel::DETAIL,
format!("Creating a new .toml file at {:?}", toml_path),
);
let html_path;
if let Some(path) = ops.html_path {
html_path = ensure_extension(path, "html", false)?;
} else {
html_path = ensure_extension(toml_path.clone(), "html", true)?;
}
let title: String;
if let Some(t) = ops.title {
title = t;
} else {
let mut parts = toml_path.file_name().unwrap().to_str().unwrap().split(".");
title = parts.next().unwrap().to_owned();
}
let mut relative_markdown_path = markdown_path.clone();
if let Some(toml_parent) = toml_path.parent() {
if let Some(relative) = pathdiff::diff_paths(markdown_path.as_path(), toml_parent) {
relative_markdown_path = relative;
}
}
let page_config = PageConfigToml {
page: PageConfig {
html_path: html_path.to_str().unwrap().to_owned(),
title: title,
description: String::new(),
content_path: relative_markdown_path.to_str().unwrap().to_owned(),
favicon: None,
before_navbar_url: None,
before_content_url: None,
after_content_url: None,
javascript: None,
css: None,
},
};
match toml::ser::to_string_pretty(&page_config) {
Ok(text) => file_writer::write_file(toml_path.clone(), text, ops.overwrite)?,
Err(err) => {
return Err(Error::new(
LogLevel::SEVERE,
format!(
"Failed to serialize page config: {}",
err.description().to_owned()
),
))
}
}
logger.log(
LogLevel::DETAIL,
format!("Creating a new .md file at {:?}", markdown_path),
);
file_writer::write_file(markdown_path, PLACEHOLDER_MARKDOWN, ops.overwrite)?;
Ok(())
}
fn ensure_extension<T: Into<String>>(
mut path: PathBuf,
extension: T,
replace_extension: bool,
) -> Result<PathBuf, Error> {
let extension = extension.into();
if let (Some(parent), Some(file_name)) = (path.clone().parent(), path.clone().file_name()) {
let mut filename = file_name.to_str().unwrap().to_owned();
let clone = filename.clone();
let mut split = clone.split(".");
if split.clone().count() == 1 as usize {
path = parent.join(format!("{}.{}", filename, extension));
} else if replace_extension {
let amount = split.clone().count() - 1;
filename = split
.clone()
.take(amount)
.map(|i| format!("{}.", i))
.collect::<String>();
path = parent.join(format!("{}{}", filename, extension));
}
Ok(path)
} else {
Err(Error::new(
LogLevel::SEVERE,
format!("Could not find parent/file_name for {:?}", path),
))
}
}

View File

@ -41,6 +41,12 @@ pub struct NewOps {
/// File path for the markdown file created /// File path for the markdown file created
#[structopt(short = "m", long = "markdown", parse(from_os_str))] #[structopt(short = "m", long = "markdown", parse(from_os_str))]
pub markdown_path: Option<PathBuf>, pub markdown_path: Option<PathBuf>,
/// Outpuh html file path of the generated page
#[structopt(short = "h", long = "html", parse(from_os_str))]
pub html_path: Option<PathBuf>,
/// Sets the title of the generated page
#[structopt(short = "t", long = "title")]
pub title: Option<String>,
/// Overwrites existing .toml / .md files /// Overwrites existing .toml / .md files
#[structopt(short = "o", long = "overwrite")] #[structopt(short = "o", long = "overwrite")]
pub overwrite: bool, pub overwrite: bool,

View File

@ -1 +0,0 @@
Hello!