use std::path::PathBuf;
use std::sync::{Arc, RwLock};
use clap::{Parser, Subcommand};
use clap_verbosity_flag::{InfoLevel, Verbosity};
use glob::Pattern;
use iref::IriBuf;
use language_tags::LanguageTag;
use taganak_core::graphs::Graph;
use taganak_core::terms::{Term, path_to_file_iri};
use taganak_framework::datasets::memory::iridataset::IriDataset;
use taganak_framework::graphs::local::memory::simple::SimpleGraph;
use taganak_orm::re::BasicPrefixMap;
use tokio::io::AsyncWriteExt;
use tokio::task::spawn_blocking;
use tracing::info;
use trinja::Params;
use trinja::res::GraphObject;
use trinja::site::Site;
#[derive(Parser, Clone)]
#[command(
version,
author,
about,
help_template = "\
{before-help}{name} {version} - {about}
{author}
{usage-heading} {usage}
{all-args}{after-help}
"
)]
struct Cli {
#[command(flatten)]
verbosity: Verbosity<InfoLevel>,
#[arg(short, long)]
graphs: Option<Vec<IriBuf>>,
#[arg(short, long)]
lang: Option<LanguageTag>,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Clone)]
enum Commands {
Resource {
subject: Option<IriBuf>,
#[command(subcommand)]
command: ResourceCommands,
},
Site {
subject: Option<IriBuf>,
#[command(subcommand)]
command: SiteCommands,
},
}
#[derive(Subcommand, Clone)]
enum ResourceCommands {
Render {
#[arg(short, long)]
output: Option<PathBuf>,
},
}
pub fn default_subject() -> Result<IriBuf, std::io::Error> {
let mut path = std::env::current_dir()?;
path.push("");
Ok(path_to_file_iri(path).unwrap())
}
#[derive(Subcommand, Clone)]
enum SiteCommands {
Build {
#[arg(short, long)]
output: Option<PathBuf>,
},
Analyze {
#[arg(short, long, value_enum, default_value_t)]
format: AnalyzeFormat,
},
}
#[derive(Clone, Default, clap::ValueEnum)]
enum AnalyzeFormat {
#[default]
Pretty,
w,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let args = Cli::parse();
tracing_subscriber::fmt()
.with_writer(std::io::stderr)
.with_file(true)
.with_line_number(true)
.with_max_level(args.verbosity)
.init();
let curdir = std::env::current_dir()?
.to_str()
.ok_or(anyhow::anyhow!("could not convert path to string"))?
.to_string();
let default_subject = default_subject()?;
let dataset = match args.graphs {
Some(ref args) => IriDataset::from_iris(args).await?,
None => {
let default_iri = format!("{curdir}/**/*.ttl");
info!("Using default glob {default_iri}");
IriDataset::from_glob(&Pattern::new(&default_iri)?).await?
}
};
let mut graph = SimpleGraph::default();
graph.merge(dataset.view().await).await?;
match &args.command {
Commands::Resource { subject, command } => match &command {
ResourceCommands::Render { output } => {
let obj = GraphObject::new(Params {
graph: Arc::new(RwLock::new(graph)),
base: Some(Arc::new(Term::NamedNode(
subject.clone().unwrap_or(default_subject.clone()),
))),
prefix_map: Arc::new(BasicPrefixMap::new()),
language: args.lang,
environment: None,
});
let rendered = spawn_blocking(move || obj.into_rendered()).await?.unwrap();
if let Some(path) = output {
let mut file = tokio::fs::File::options()
.create(true)
.truncate(true)
.write(true)
.open(path)
.await?;
file.write_all(rendered.as_bytes()).await?;
} else {
println!("{rendered}");
}
}
},
Commands::Site {
subject: site_subject,
command,
} => match &command {
SiteCommands::Build { output } => {
let params = Site::make_params(
graph,
site_subject.clone().unwrap_or(default_subject.clone()),
args.lang,
)
.await;
let (site, params) = Site::new(params).await?;
site.build(
params,
&output
.clone()
.unwrap_or(std::env::current_dir().unwrap().join("output")),
)
.await?;
}
SiteCommands::Analyze { format } => {
let params = Site::make_params(
graph,
site_subject.clone().unwrap_or(default_subject.clone()),
args.lang,
)
.await;
let (site, params) = Site::new(params).await?;
let pages = site.pages_map(¶ms).await?;
let assets = site.assets(¶ms).await?;
println!("Site:");
println!("\t<{}>", params.base.as_ref().unwrap());
println!(
"\t\tTitle:\t{}",
site.title.as_ref().unwrap_or(&"<none>".to_string())
);
println!();
println!("Pages:");
for (term, (page, generic_page)) in pages {
println!("\t{}", term);
}
println!();
println!("Assets:");
for term in assets {
println!("\t{}", term);
}
}
},
}
Ok(())
}