data.toml:
----------
It is used to define variables for each file. Variables in the root are
-global and are inherited by their children. If a child has a variable
+global and are inherited by their children. If a child has a variable
of the same name, then the child's variable is used instead.
-----------------------------------------------------------------------
- `_TEMPLATES` specifies the template directory
- `_OUT` designates the directory where the output files go
- `_DATE_FORMAT` designates the date format to use when using `_date`
+- `_EXT` is used to find the file extension; it is assigned during
+ execution and should not be changed.
+ `self` the file which invoked the template
+ `_extend` the template which the file should invoke
│ ├─ _test.py
```
Where the file names inside the directory become the variables of the
- file. Python files are not run here, as they will often be used to
- write code which can then be imported into the _value variable. Files
- that are meant to be ran should go into the templates directory.
+ file. Python files are not run here, as they will often be used to
+ write code which can then be imported into the `_value` variable.
+ Files that are meant to be ran should go into the templates directory.
+
+
+- Ability to create html files on the fly using `_build.py` python
+ scripts. The `_value` variable when the script finishes will produce
+ the html files with their values.
+
+ The `_value` variable must be a list containing 2-tuples. Each 2-tuple
+ is an html file, the first element of the 2-tuple is a list containing
+ a split path to the html file, with the last value being the name of
+ the file without the extension; for example, the path `post/one.html`
+ will have the list ["post", "one"]. The second value of the 2-tuple is
+ the contents of the html file.
+
+ This is useful for cases where the amount of files changes dynamically
+ based on content. For example, having an html file for each tag to
+ group posts by.
return mtime
+def create_page_index(data: dict):
+ pages: list[tuple] = []
+ for root, _, files in os.walk(data["_PAGE_ROOT"]):
+ root = os.path.relpath(root, data["_PAGE_ROOT"])
+ if root.startswith(("_", ".")) and root != ".":
+ continue
+ if root == ".":
+ root = ""
+ root_name, root_ext = os.path.splitext(root)
+ if root_ext:
+ pages.append(split_path(root_name))
+ continue
+ for file in files:
+ if file.startswith(("_", ".")):
+ continue
+ file_name, _ = os.path.splitext(os.path.join(root, file))
+ pages.append(split_path(file_name))
+ data["_PAGES"] = pages
+
+
def initialize_values(data: dict):
for dir in os.walk(data["_PAGE_ROOT"]):
_, ext = os.path.splitext(dir[0])
time.strftime(data["_DATE_FORMAT"], time.localtime(mtime)),
False,
)
+ update_value(data, namespace, "_EXT", ext)
continue
for file in dir[2]:
path = os.path.join(dir[0], file)
rel_path = os.path.relpath(path, data["_PAGE_ROOT"])
mtime = os.path.getmtime(path)
- rel_path_no_type, _ = os.path.splitext(rel_path)
+ rel_path_no_type, rel_path_ext = os.path.splitext(rel_path)
namespace = split_path(rel_path_no_type)
update_value(data, namespace, "_name", namespace[-1], False)
update_value(
time.strftime(data["_DATE_FORMAT"], time.localtime(mtime)),
False,
)
+ if rel_path_ext == ".md":
+ update_value(data, namespace, "_EXT", ".html")
+ else:
+ update_value(data, namespace, "_EXT", rel_path_ext)
def get_value_from_file(
def get_value(data: dict, namespace: tuple, key: str, interpret_ok=True):
- if key != "_value" and (
- value := get_value_from_file(data, namespace, key, interpret_ok)
- ):
- return value
+ try:
+ if key != "_value" and (
+ value := get_value_from_file(data, namespace, key, interpret_ok)
+ ):
+ return value
+ except FileNotFoundError:
+ pass
value = data.get(key)
for namespace_item in namespace:
data = data.get(namespace_item, data)
return str(get_value(data, namespace, "_value"))
+def generate_builds(build_file: str, data: dict) -> list[tuple[tuple, str]]:
+ rel_path = os.path.relpath(build_file, data["_PAGE_ROOT"])
+ rel_path_no_type, _ = os.path.splitext(rel_path)
+ namespace = split_path(rel_path_no_type)[:-1]
+ d = {"data": data, "namespace": namespace, "get_value": get_value}
+ with open(build_file, "r") as f:
+ exec(f.read(), d)
+ for path, _ in d["_value"]:
+ rel_path = os.path.relpath(os.path.split(build_file)[0], data["_PAGE_ROOT"])
+ if rel_path != ".":
+ # path = split_path(rel_path) + path
+ path.insert(0, *split_path(rel_path))
+ update_value(data, path, "_EXT", ".html", False)
+ update_value(data, path, "_name", path[-1], False)
+ update_value(
+ data,
+ path,
+ "_date",
+ time.strftime(
+ data["_DATE_FORMAT"], time.localtime(os.path.getmtime(build_file))
+ ),
+ False,
+ )
+
+ data["_PAGES"].append(tuple(path))
+ for i in range(len(d["_value"])):
+ d["_value"][i] = (tuple(d["_value"][i][0]), d["_value"][i][1])
+ return d["_value"]
+
+
+def interpret_builds(build_data: list[tuple[tuple, str]], data: dict):
+ for path, _value in build_data:
+ path_with_ext = path[:-1] + (path[-1] + ".html",)
+ _value = interpret(_value, data, path)
+ update_value(data, path, "_value", _value)
+
+ if _extend := get_value(data, path, "_extend"):
+ update_value(data, path, "_extend", "")
+ generate_output(os.path.join(data["_TEMPLATES"], _extend), data, path)
+ update_value(
+ data,
+ path,
+ "_value",
+ interpret_no_recursion(str(get_value(data, path, "_value")), data, path),
+ )
+
+ os.makedirs(os.path.join(data["_OUT"], *path_with_ext[:-1]), exist_ok=True)
+ with open(os.path.join(data["_OUT"], *path_with_ext), "w") as out_file:
+ out_file.write(get_value(data, path, "_value"))
+
+
+
def main(args):
# Load toml file
data = tomllib.load(args.data)
initialize_values(data)
+ create_page_index(data)
+
+ builds = []
+ for root, _, files in os.walk(data["_PAGE_ROOT"]):
+ if root.startswith(("_", ".")):
+ continue
+ if "_build.py" not in files:
+ continue
+ builds.extend(generate_builds(os.path.join(root, "_build.py"), data))
+
+ interpret_builds(builds, data)
+
if not args.pages:
pages = []
for dir in os.walk(data["_PAGE_ROOT"]):
_, ext = os.path.splitext(dir[0])
+ if dir[0].startswith(("_", ".")):
+ continue
if ext:
pages.append(dir[0])
continue
for file in dir[2]:
+ if file.startswith(("_", ".")):
+ continue
pages.append(os.path.join(dir[0], file))
else:
pages = args.pages
os.makedirs(
os.path.join(data["_OUT"], os.path.split(rel_path)[0]), exist_ok=True
)
- if file_type == ".md":
+ if file_type == ".md" and not os.path.isdir(page):
rel_path = rel_path_no_type + ".html"
with open(os.path.join(data["_OUT"], rel_path), "w") as out_file:
out_file.write(generate_output(page, data, namespace))