trinja 0.7.1

HTML templating / SSG for RDF(S) resources
Documentation
use std::{path::PathBuf, sync::Arc};

use minijinja::{State, Value, value::Object};
use taganak_core::graphs::Graph;
use taganak_orm::{GraphORM, GraphORMMeta};
use tokio::runtime::Handle;
use tracing::debug;

use crate::{
    Params,
    res::str_to_term,
    site::{Asset, Page},
};

#[derive(Debug, Clone)]
pub struct RdfAssetFn<G> {
    params: Params<'static, G>,
    page: GraphORMMeta<Page>,
}

impl<G> RdfAssetFn<G>
where
    G: Graph + std::fmt::Debug + Sync + 'static,
{
    pub fn new(params: Params<'static, G>, page: GraphORMMeta<Page>) -> Self {
        Self { params, page }
    }
}

impl<G> Object for RdfAssetFn<G>
where
    G: Graph + std::fmt::Debug + Sync + 'static,
{
    fn call(
        self: &Arc<Self>,
        _state: &State<'_, '_>,
        args: &[Value],
    ) -> Result<Value, minijinja::Error> {
        if args.is_empty() {
            return Err(minijinja::Error::new(
                minijinja::ErrorKind::MissingArgument,
                "needs subject",
            ));
        }

        if args.len() > 1 {
            return Err(minijinja::Error::new(
                minijinja::ErrorKind::TooManyArguments,
                "too many arguments",
            ));
        }

        let handle = Handle::current();
        let term_str = args[0].to_string();
        handle.block_on(async {
            let asset_subject = str_to_term(
                self.params.clone().base(Some(self.page.subject().unwrap())),
                &term_str,
            )
            .unwrap();
            debug!(
                "Finding asset {} relative to page {}",
                asset_subject,
                self.page.subject().unwrap()
            );
            let page_iri = self.page.subject().unwrap().to_iri().unwrap().clone();

            let graph_clone = self.params.graph.clone();
            let graph = graph_clone.read().unwrap();
            let view = graph.view().await;
            let asset = Asset::deserialize(view.clone(), &asset_subject)
                .await
                .unwrap()
                .into_deref();

            let out_rel = match asset.output {
                Some(output) => {
                    let page_path = match &self.page.output {
                        None => PathBuf::from(
                            page_iri
                                .relative_to(&self.params.base.as_ref().unwrap().to_iri().unwrap())
                                .to_string(),
                        ),
                        Some(output) => PathBuf::from(output),
                    };
                    let output_path = PathBuf::from(output.clone());
                    debug!(
                        ?page_path,
                        ?output_path,
                        "Asset has explicit output path, calculating relative to page output path"
                    );

                    let mut out_rel = PathBuf::new();

                    for (n, _) in page_path.components().enumerate() {
                        if n > 0 {
                            out_rel.push("..");
                        }
                    }
                    out_rel.push(output_path);

                    out_rel
                }
                None => {
                    debug!(
                        ?page_iri,
                        ?asset_subject,
                        "Calculating asset path relative to page"
                    );
                    PathBuf::from(
                        asset_subject
                            .to_iri()
                            .unwrap()
                            .relative_to(&page_iri)
                            .to_string(),
                    )
                }
            };

            Ok(Value::from(out_rel.to_str().unwrap().to_string()))
        })
    }
}