157 lines
4.2 KiB
Rust
157 lines
4.2 KiB
Rust
use std::env;
|
|
use std::io::Write;
|
|
use std::path::{Path, PathBuf};
|
|
use std::str::FromStr;
|
|
|
|
use anyhow::{anyhow, Context, Error};
|
|
use chrono::Local;
|
|
use log::LevelFilter;
|
|
use structopt::StructOpt;
|
|
use tokio::fs;
|
|
|
|
use cyberstorm::registry::{DirectoryRegistry, SupportedRegistry};
|
|
#[cfg(feature = "mdbook-renderer")]
|
|
use cyberstorm::render::mdbook::MDBookEngine;
|
|
use cyberstorm::render::Renderer;
|
|
|
|
#[derive(Debug, StructOpt)]
|
|
#[structopt(name = "cyberstorm")]
|
|
struct Opt {
|
|
/// Registry to use.
|
|
registry: RegistryOpt,
|
|
|
|
#[structopt(subcommand)]
|
|
cmd: Cmd,
|
|
}
|
|
|
|
#[derive(Debug, StructOpt)]
|
|
enum Cmd {
|
|
/// Renders the content into a mdBook.
|
|
#[cfg(feature = "mdbook-renderer")]
|
|
MdbookRender(MdbookRenderOpt),
|
|
/// Renders the content into a mdBook and builds it.
|
|
#[cfg(feature = "mdbook-renderer")]
|
|
MdbookBuild(MdbookRenderOpt),
|
|
}
|
|
|
|
#[derive(Debug, StructOpt)]
|
|
#[cfg(feature = "mdbook-renderer")]
|
|
struct MdbookRenderOpt {
|
|
/// Path to the output mdBook root or `book.toml`.
|
|
#[structopt(parse(from_os_str), default_value = "./book.toml")]
|
|
book: PathBuf,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
enum RegistryOpt {
|
|
Directory(PathBuf),
|
|
}
|
|
|
|
impl FromStr for RegistryOpt {
|
|
type Err = &'static str;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
Ok(Self::Directory(PathBuf::from(s)))
|
|
}
|
|
}
|
|
|
|
async fn run(opt: Opt) -> Result<(), Error> {
|
|
let registry = match &opt.registry {
|
|
RegistryOpt::Directory(path) => SupportedRegistry::Directory(DirectoryRegistry::new(path)),
|
|
};
|
|
match &opt.cmd {
|
|
#[cfg(feature = "mdbook-renderer")]
|
|
Cmd::MdbookRender(render_opt) => {
|
|
let (root, config) = load_mdbook_config(&render_opt.book).await?;
|
|
render_mdbook(®istry, &root, &config).await
|
|
}
|
|
#[cfg(feature = "mdbook-renderer")]
|
|
Cmd::MdbookBuild(render_opt) => {
|
|
let (root, config) = load_mdbook_config(&render_opt.book).await?;
|
|
render_mdbook(®istry, &root, &config).await?;
|
|
mdbook::MDBook::load_with_config(root, config)?.build()
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "mdbook-renderer")]
|
|
async fn load_mdbook_config(book: &Path) -> Result<(PathBuf, mdbook::Config), Error> {
|
|
let (root, config_file) = book
|
|
.canonicalize()
|
|
.ok()
|
|
.and_then(|book| {
|
|
let (root, config) = if book.extension().is_some() {
|
|
(book.parent().unwrap().to_owned(), book.to_owned())
|
|
} else {
|
|
let config_file = book.join("book.toml");
|
|
(book, config_file)
|
|
};
|
|
if config.is_file() {
|
|
Some((root, config))
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.ok_or_else(|| {
|
|
anyhow!(
|
|
"expected mdbook config path (eg. `book.toml`) at `{}`",
|
|
book.display()
|
|
)
|
|
})?;
|
|
|
|
let config = fs::read_to_string(config_file)
|
|
.await
|
|
.context("failed to read mdbook configuration")?
|
|
.parse()?;
|
|
|
|
Ok((root, config))
|
|
}
|
|
|
|
#[cfg(feature = "mdbook-renderer")]
|
|
async fn render_mdbook(
|
|
registry: &SupportedRegistry,
|
|
root: &Path,
|
|
config: &mdbook::Config,
|
|
) -> Result<(), Error> {
|
|
let engine = MDBookEngine::new(root, config);
|
|
Renderer::new(engine, registry)
|
|
.generate()
|
|
.await
|
|
.context("failed to generate mdbook content")
|
|
}
|
|
|
|
fn init_logger() {
|
|
let mut builder = env_logger::Builder::new();
|
|
|
|
builder.format(|formatter, record| {
|
|
writeln!(
|
|
formatter,
|
|
"{} [{}] ({}): {}",
|
|
Local::now().format("%Y-%m-%d %H:%M:%S"),
|
|
record.level(),
|
|
record.target(),
|
|
record.args()
|
|
)
|
|
});
|
|
|
|
if let Ok(var) = env::var("RUST_LOG") {
|
|
builder.parse_filters(&var);
|
|
} else {
|
|
// if no RUST_LOG provided, default to logging at the Info level
|
|
builder.filter(None, LevelFilter::Info);
|
|
// Filter extraneous html5ever not-implemented messages
|
|
builder.filter(Some("html5ever"), LevelFilter::Error);
|
|
}
|
|
|
|
builder.init();
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
init_logger();
|
|
|
|
if let Err(err) = run(Opt::from_args()).await {
|
|
log::error!("{:#}", err);
|
|
}
|
|
}
|