Author: {{ metadata.author }}
Published: {{ get_time_iso8601(metadata.stat.ctime) }}
{% if metadata.stat.mtime-metadata.stat.ctime > 512 %}
diff --git a/examples/pixywerk.com/src/recurse.thtml b/examples/pixywerk.com/src/recurse.thtml
new file mode 100644
index 0000000..44cd412
--- /dev/null
+++ b/examples/pixywerk.com/src/recurse.thtml
@@ -0,0 +1,5 @@
+
+{% for i in get_hier('.', '*') %}
+- {{i}}
+{% endfor %}
+
\ No newline at end of file
diff --git a/pixywerk2/__main__.py b/pixywerk2/__main__.py
index ff2e88c..ad656e3 100644
--- a/pixywerk2/__main__.py
+++ b/pixywerk2/__main__.py
@@ -11,14 +11,15 @@ import os
import shutil
import sys
import time
-
from typing import Dict, List, cast
+from .metadata import MetaTree
from .processchain import ProcessorChains
from .processors.processors import PassthroughException
-from .metadata import MetaTree
-from .template_tools import date_iso8601, file_list, file_name, file_content, file_metadata, time_iso8601, file_raw
from .pygments import pygments_get_css, pygments_markup_contents_html
+from .template_tools import (date_iso8601, file_content, file_list,
+ file_list_hier, file_metadata, file_name,
+ file_raw, time_iso8601)
logger = logging.getLogger()
@@ -87,8 +88,10 @@ def main() -> int:
file_cont_cache = cast(Dict, {})
file_name_cache = cast(Dict, {})
file_raw_cache = cast(Dict, {})
+ flist = file_list(args.root, file_list_cache)
default_metadata["globals"] = {
- "get_file_list": file_list(args.root, file_list_cache),
+ "get_file_list": flist,
+ "get_hier": file_list_hier(args.root, flist),
"get_file_name": file_name(args.root, meta_tree, process_chains, file_name_cache),
"get_file_content": file_content(args.root, meta_tree, process_chains, file_cont_cache),
"get_raw": file_raw(args.root, file_raw_cache),
diff --git a/pixywerk2/metadata.py b/pixywerk2/metadata.py
index 9e45851..3549c35 100644
--- a/pixywerk2/metadata.py
+++ b/pixywerk2/metadata.py
@@ -5,8 +5,7 @@ import logging
import mimetypes
import os
import uuid
-
-from typing import Dict, Optional, Union, List, Tuple, Any, cast
+from typing import Any, Dict, List, Optional, Tuple, Union, cast
import jstyleson
diff --git a/pixywerk2/processchain.py b/pixywerk2/processchain.py
index d5952d0..5124809 100644
--- a/pixywerk2/processchain.py
+++ b/pixywerk2/processchain.py
@@ -3,8 +3,7 @@
import os
import os.path
import random
-
-from typing import List, Iterable, Optional, Any, Dict, Type, cast
+from typing import Any, Dict, Iterable, List, Optional, Type, cast
import yaml
diff --git a/pixywerk2/processors/jinja2.py b/pixywerk2/processors/jinja2.py
index 80b072b..6957306 100644
--- a/pixywerk2/processors/jinja2.py
+++ b/pixywerk2/processors/jinja2.py
@@ -1,6 +1,6 @@
"""Define a Jinja2 Processor which applies programmable templating to the input stream."""
-from typing import Iterable, Optional, Dict, cast
+from typing import Dict, Iterable, Optional, cast
from jinja2 import Environment, FileSystemLoader
@@ -22,7 +22,7 @@ class Jinja2(PassThrough):
iterable: The post-processed output stream
"""
ctx = cast(Dict, ctx)
- template_env = Environment(loader=FileSystemLoader(ctx["templates"]), extensions=['jinja2.ext.do'])
+ template_env = Environment(loader=FileSystemLoader(ctx["templates"]), extensions=["jinja2.ext.do"])
template_env.globals.update(ctx["globals"])
template_env.filters.update(ctx["filters"])
tmpl = template_env.from_string("".join([x for x in input_file]))
diff --git a/pixywerk2/processors/jinja2_page_embed.py b/pixywerk2/processors/jinja2_page_embed.py
index 21f6f3a..4f89b72 100644
--- a/pixywerk2/processors/jinja2_page_embed.py
+++ b/pixywerk2/processors/jinja2_page_embed.py
@@ -3,8 +3,7 @@
the target template is rendered)."""
import os
-
-from typing import Iterable, Optional, Dict, cast
+from typing import Dict, Iterable, Optional, cast
from jinja2 import Environment, FileSystemLoader
@@ -52,7 +51,7 @@ class Jinja2PageEmbed(Processor):
iterable: The post-processed output stream
"""
ctx = cast(Dict, ctx)
- template_env = Environment(loader=FileSystemLoader(ctx["templates"]), extensions=['jinja2.ext.do'])
+ template_env = Environment(loader=FileSystemLoader(ctx["templates"]), extensions=["jinja2.ext.do"])
template_env.globals.update(ctx["globals"])
template_env.filters.update(ctx["filters"])
tmpl = template_env.get_template(ctx["template"])
diff --git a/pixywerk2/processors/passthrough.py b/pixywerk2/processors/passthrough.py
index cc6511b..c3f34ae 100644
--- a/pixywerk2/processors/passthrough.py
+++ b/pixywerk2/processors/passthrough.py
@@ -1,10 +1,10 @@
"""Passthrough progcessor which takes input and returns it."""
import os
+from typing import Dict, Iterable, Optional, cast
-from .processors import Processor, PassthroughException
from ..utils import guess_mime
-from typing import Iterable, Optional, Dict, cast
+from .processors import PassthroughException, Processor
class PassThrough(Processor):
diff --git a/pixywerk2/processors/process_md.py b/pixywerk2/processors/process_md.py
index 0687bc6..30a1b01 100644
--- a/pixywerk2/processors/process_md.py
+++ b/pixywerk2/processors/process_md.py
@@ -2,8 +2,7 @@
import io
import os
-
-from typing import Iterable, Optional, Dict
+from typing import Dict, Iterable, Optional
import markdown
diff --git a/pixywerk2/processors/processors.py b/pixywerk2/processors/processors.py
index 0ff970e..552a872 100644
--- a/pixywerk2/processors/processors.py
+++ b/pixywerk2/processors/processors.py
@@ -1,6 +1,5 @@
import abc
-
-from typing import Iterable, Optional, Dict
+from typing import Dict, Iterable, Optional
class PassthroughException(Exception):
diff --git a/pixywerk2/pygments.py b/pixywerk2/pygments.py
index c96de3b..90938f6 100644
--- a/pixywerk2/pygments.py
+++ b/pixywerk2/pygments.py
@@ -4,18 +4,17 @@ from typing import Optional
import pygments
import pygments.formatters
import pygments.lexers
-import pygments.util
import pygments.styles
+import pygments.util
-
-def pygments_markup_contents_html(input_text: str, file_type: str, style: Optional[str]=None) -> str:
+def pygments_markup_contents_html(input_text: str, file_type: str, style: Optional[str] = None) -> str:
"""Format input string with Pygments and return HTML."""
if style is None:
- style = 'default'
+ style = "default"
style = pygments.styles.get_style_by_name(style)
- formatter = pygments.formatters.get_formatter_by_name('html', style=style)
+ formatter = pygments.formatters.get_formatter_by_name("html", style=style)
try:
lexer = pygments.lexers.get_lexer_for_filename(file_type)
except pygments.util.ClassNotFound:
@@ -26,11 +25,12 @@ def pygments_markup_contents_html(input_text: str, file_type: str, style: Option
return pygments.highlight(input_text, lexer, formatter)
-def pygments_get_css(style: Optional[str]=None) -> str:
+
+def pygments_get_css(style: Optional[str] = None) -> str:
"""Return the CSS styles associated with a particular style definition."""
if style is None:
- style = 'default'
+ style = "default"
style = pygments.styles.get_style_by_name(style)
- formatter = pygments.formatters.get_formatter_by_name('html', style=style)
+ formatter = pygments.formatters.get_formatter_by_name("html", style=style)
return formatter.get_style_defs()
diff --git a/pixywerk2/template_tools.py b/pixywerk2/template_tools.py
index 058fb76..641a698 100644
--- a/pixywerk2/template_tools.py
+++ b/pixywerk2/template_tools.py
@@ -2,8 +2,9 @@ import datetime
import glob
import itertools
import os
+from typing import Callable, Dict, Iterable, List, Union, cast
+
import pytz
-from typing import Callable, Dict, List, Iterable, Union, cast
from .metadata import MetaTree
from .processchain import ProcessorChains
@@ -40,6 +41,30 @@ def file_list(root: str, listcache: Dict) -> Callable:
return get_file_list
+def file_list_hier(root: str, flist: Callable) -> Callable:
+ """Return a callable which, given a directory, will walk the directory and return the files within
+ it that match the glob passed."""
+
+ def get_file_list_hier(path: str, glob: str, *, sort_order: str = "ctime", reverse: bool = False) -> Iterable:
+ output = []
+
+ def collect(pth):
+ print(arg, pth, files)
+
+ for pth in os.walk(os.path.join(root, path)):
+ output.extend(
+ flist(
+ os.path.join(os.path.relpath(os.path.realpath(pth[0]), root), glob),
+ sort_order=sort_order,
+ reverse=reverse,
+ )
+ )
+
+ return output
+
+ return get_file_list_hier
+
+
def file_name(root: str, metatree: MetaTree, processor_chains: ProcessorChains, namecache: Dict) -> Callable:
def get_file_name(file_name: str) -> Dict:
if file_name in namecache:
@@ -51,15 +76,17 @@ def file_name(root: str, metatree: MetaTree, processor_chains: ProcessorChains,
return get_file_name
+
def file_raw(root: str, contcache: Dict) -> Callable:
def get_raw(file_name: str) -> str:
if file_name in contcache:
return contcache[file_name]
- with open(os.path.join(root, file_name), 'r', encoding="utf-8") as f:
+ with open(os.path.join(root, file_name), "r", encoding="utf-8") as f:
return f.read()
return get_raw
+
def file_content(root: str, metatree: MetaTree, processor_chains: ProcessorChains, contcache: Dict) -> Callable:
def get_file_content(file_name: str) -> Iterable:
if file_name in contcache:
@@ -87,10 +114,11 @@ def time_iso8601(timezone: str) -> Callable:
return get_time_iso8601
+
def date_iso8601(timezone: str) -> Callable:
tz = pytz.timezone(timezone)
def get_date_iso8601(time_t: Union[int, float]) -> str:
- return datetime.datetime.fromtimestamp(time_t, tz).strftime('%Y-%m-%d')
+ return datetime.datetime.fromtimestamp(time_t, tz).strftime("%Y-%m-%d")
return get_date_iso8601
diff --git a/pixywerk2/utils.py b/pixywerk2/utils.py
index 962c9e2..2f16f66 100644
--- a/pixywerk2/utils.py
+++ b/pixywerk2/utils.py
@@ -1,6 +1,5 @@
import mimetypes
import os
-
from typing import Dict, Optional