from variables import check_variables
from jinja2 import Template, Environment, FileSystemLoader
import markdown
from pathlib import Path
import importlib
import os
import shutil
import html
import frontmatter
import subprocess
modules = [check_variables]
all_vars = {}
for mod in modules:
if hasattr(mod, "__all__"):
all_vars.update({name: getattr(mod, name) for name in mod.__all__})
subprocess.run(["python", "create_snippets.py"])
output_dir = "output"
# Create the folder if it doesn't exist
os.makedirs(output_dir, exist_ok=True)
# Clear contents safely
for filename in os.listdir(output_dir):
file_path = os.path.join(output_dir, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path) # remove file or symlink
elif os.path.isdir(file_path):
shutil.rmtree(file_path) # remove subdirectory
except Exception as e:
print(f"Failed to delete {file_path}: {e}")
# load up a series of mappings and pages from files
# a mapping is a LIST of DICTIONARIES from a .py file
mappings = []
folder = os.path.join(os.path.dirname(__file__), "pages_python")
for filename in os.listdir(folder):
print(filename)
if filename.endswith(".py") and not filename.startswith("__"):
module_name = f"pages_python.{filename[:-3]}" # package.module style
module = importlib.import_module(module_name)
mappings.append({"title": module.meta["title"], "name": module.meta["name"], "nav_order": module.meta["nav_order"], "mapping": module.mapping})
# order the mappings list by nav_order
mappings.sort(key=lambda x: x["nav_order"])
# we now want to create pages from mappings
# a page is a list of dictionaries, on dictionary for each final webpage
# each page has blocks where blocks is a list of html strings
pages = []
for mapping in mappings:
page_title = mapping['title']
page_name = mapping['name']
page_mapping = mapping['mapping']
page_nav_order = mapping['nav_order']
html_blocks = []
for block in page_mapping:
block_type = block["type"]
if block_type == "markdown":
if Path(block["file"]).exists():
with Path(block["file"]).open("r", encoding="utf-8") as f:
md_text = f.read()
block["content"] = markdown.markdown(md_text)
# del block["file"] # remove file key, keep only type & content
html_blocks.append(block)
elif block_type == "dataframe":
html_blocks.append(block)
elif block_type == "pycode":
if Path(block["file"]).exists():
with Path(block["file"]).open("r", encoding="utf-8") as f:
md_text = f.read()
block["content"] = f"<pre><code>{html.escape(md_text)}</code></pre>"
html_blocks.append(block)
pages.append({"title": page_title, "nav_order": page_nav_order, "name": page_name, "blocks": html_blocks, "type": "python_page"})
# we now want to add our pages_markdown to the pages list so that the nav bar works
# each element in pages is a dictionary and has the following
# {'title': 'Aims', 'nav_order': 0, 'name': 'Aims', 'blocks': [{'type': 'markdown', 'file': 'markdown/aims.md', 'content': ''}]}
folder = os.path.join(os.path.dirname(__file__), "pages_markdown")
for filename in os.listdir(folder):
print("test")
with open("pages_markdown/"+filename) as f:
post = frontmatter.load(f)
meta = post.metadata
pages.append({"title": meta['title'], "nav_order": meta['nav_order'], "name": meta["page_name"], "blocks": "empty", "type": "markdown_page"})
# order the mappings list by nav_order
pages.sort(key=lambda x: x["nav_order"])
# this should loop through pages_python only
# START_SNIPPET
# 1. Load templates from the templates folder
env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('multi-content.html')
# Loop through pages and render each separately
for page in pages:
if page['type'] == "python_page":
html_output = template.render(pages=pages,current_name=page["name"],nav_order=page["nav_order"],title=page["title"], blocks=page["blocks"])
filename = f"output/{page['name'].replace(' ', '_')}.html"
with open(filename, "w", encoding="utf-8") as f:
f.write(html_output)
print(f"Saved {filename}")
# END_SNIPPET
directory = Path("dataframes")
dataframe_py_files = [
{
"filename": file.name,
"py_file_text": file.read_text(encoding="utf-8")
}
for file in directory.rglob("*.py")
if file.is_file()
]
template2 = env.get_template("markdown-content.html")
# Load markdown file (can contain Liquid)
folder = os.path.join(os.path.dirname(__file__), "pages_markdown")
for filename in os.listdir(folder):
with open("pages_markdown/"+filename) as f:
post = frontmatter.load(f)
meta = post.metadata
content = post.content
md_template = env.from_string(content)
# Render Liquid inside markdown
#rendered_md = md_template.render(**meta)
rendered_md = md_template.render(**meta, dataframe_py_files = dataframe_py_files,all_vars = all_vars)
# Convert markdown -> HTML
html_content = markdown.markdown(rendered_md)
# Render main template and inject HTML
# **meta could go in the render function
final = template2.render(pages=pages,html_content=html_content, current_name="name",nav_order=5,title="title")
with open("output/"+meta["page_name"]+".html", "w", encoding="utf-8") as f:
f.write(final)
print("Report generated successfully!")