diff --git a/src/dragonglass/template.py b/src/dragonglass/template.py index 3df6af9..67bf471 100644 --- a/src/dragonglass/template.py +++ b/src/dragonglass/template.py @@ -4,7 +4,7 @@ import sys from jinja2 import Environment, BaseLoader, ChoiceLoader, FunctionLoader, FileSystemLoader -from typing import Any +from typing import Any, Callable from urllib.parse import quote as urlquote from .config import Context, DEFAULT_TEMPLATE_NAME @@ -73,6 +73,28 @@ def _create_loader(ctxt: Context) -> BaseLoader: return ChoiceLoader(choices) +def makepath(ctxt: Context, node: SourceNode | None, s: str) -> str: + """ + Turn a string into a proper path reference, based on relative link settings and prefix. + + Args: + ctxt (Context): The context to use for the operation. + node (SourceNode): The current node being processed; if this is ``None``, it's taken from the context. + s (str): The string to interpret. + + Returns: + str: The resolved link. + """ + if not node: + node = ctxt.current_node + if ctxt.relative_links: + in_path = ctxt.source_dir / s + rel_path = ctxt.source_dir / node.path + return urlquote(in_path.relative_to(rel_path.parent, walk_up=True).as_posix()) + else: + return urlquote(ctxt.url_prefix + s) + + def create_template_environment(ctxt: Context) -> Environment: """ Create the template environment used to render the data to the destination. @@ -83,7 +105,23 @@ def create_template_environment(ctxt: Context) -> Environment: Returns: Environment: The new template environment. """ - return Environment(loader=_create_loader(ctxt)) + tenv = Environment(loader=_create_loader(ctxt)) + + # Add global variables easily calculated. + tenv.globals['dragonglass_version'] = __version__ + tenv.globals["python_version"] = f"{sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}" + + # Add values derived from configuration. + t = ctxt.site_base + if t: + tenv.globals["site_base"] = t + t = ctxt.site_title + if t: + tenv.globals["site_title"] = t + + # Add global functions. + tenv.globals['makepath'] = lambda s: makepath(ctxt, None, s) + return tenv def template_vars(node: SourceNode, ctxt: Context) -> dict[str, Any]: @@ -103,18 +141,6 @@ def template_vars(node: SourceNode, ctxt: Context) -> dict[str, Any]: if not tvars["description"] and ctxt.description_title: tvars["description"] = node.page_title - # Add easily-calculated "global" variables. - tvars["dragonglass_version"] = __version__ - tvars["python_version"] = f"{sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}" - - # Add values derived from configuration. - t = ctxt.site_base - if t: - tvars["site_base"] = t - t = ctxt.site_title - if t: - tvars["site_title"] = t - # Compute backlinks for this node. Don't include nodes that aren't published. backlinks = sorted([n for n in node.backlinks if n.publish], key=lambda n: n.page_title) tvars['backlinks'] = [{'title': n.page_title, @@ -122,12 +148,7 @@ def template_vars(node: SourceNode, ctxt: Context) -> dict[str, Any]: for n in backlinks] # Add reference to the default stylesheet. - if ctxt.relative_links: - stylesheet_path = ctxt.source_dir / ctxt.default_stylesheet - rel_path = ctxt.source_dir / node.path - tvars['default_stylesheet'] = urlquote(stylesheet_path.relative_to(rel_path.parent, walk_up=True).as_posix()) - else: - tvars['default_stylesheet'] = urlquote(ctxt.url_prefix + ctxt.default_stylesheet) + tvars['default_stylesheet'] = makepath(ctxt, node, ctxt.default_stylesheet) return tvars