vault backup: 2025-12-07 12:39:26
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 1m21s
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 1m21s
This commit is contained in:
185
wip/static.py
185
wip/static.py
@@ -1,16 +1,27 @@
|
||||
import argparse
|
||||
import http.server
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
|
||||
import shutil
|
||||
import jinja2
|
||||
|
||||
from markdown.core import Markdown
|
||||
from markdown.extensions import Extension
|
||||
from markdown.preprocessors import Preprocessor
|
||||
from obsidian_parser import Vault
|
||||
from obsidian_parser import Note, Vault
|
||||
|
||||
|
||||
def out_content(self):
|
||||
content = self.content
|
||||
if content.startswith("---\n"):
|
||||
content = content.split("---\n", 2)[2]
|
||||
return content
|
||||
Note.our_content = property(out_content)
|
||||
|
||||
root_dir = pathlib.Path(__file__).parent
|
||||
vault = Vault(root_dir.parent / "content")
|
||||
note = vault.get_note("Biokemi/Cellulära processer/Transport över cellmembran/Anteckningar.md")
|
||||
loader = jinja2.FileSystemLoader(root_dir / "templates")
|
||||
env = jinja2.Environment(loader=loader)
|
||||
|
||||
@@ -23,9 +34,9 @@ class ObsidianImage(Preprocessor):
|
||||
if m:
|
||||
if "|" in m.group(1):
|
||||
img, width = m.group(1).split("|")
|
||||
new_lines.append("<img src='../content/attachments/" + img + "' style='width:" + width + ";'/>")
|
||||
new_lines.append(f"<img src='attachments/{img}' style='width:{width};'/>")
|
||||
else:
|
||||
new_lines.append("<img src='../content/attachments/" + m.group(1) + "'/>")
|
||||
new_lines.append(f"<img src='attachments/{m.group(1)}'/>")
|
||||
else:
|
||||
new_lines.append(line)
|
||||
return new_lines
|
||||
@@ -35,35 +46,145 @@ class ObsidianImageExtension(Extension):
|
||||
def extendMarkdown(self, md):
|
||||
md.preprocessors.register(ObsidianImage(md), 'obsidianimage', 175)
|
||||
|
||||
m = Markdown(
|
||||
extensions=[
|
||||
"mdx_math",
|
||||
"nl2br",
|
||||
ObsidianImageExtension(),
|
||||
],
|
||||
extension_configs={
|
||||
"mdx_math": {
|
||||
"enable_dollar_delimiter": True
|
||||
}
|
||||
},
|
||||
tab_length=2,
|
||||
)
|
||||
env.filters["markdown"] = m.convert
|
||||
def make_markdown():
|
||||
return Markdown(
|
||||
extensions=[
|
||||
"fenced_code",
|
||||
"mdx_math",
|
||||
"nl2br",
|
||||
"tables",
|
||||
ObsidianImageExtension(),
|
||||
],
|
||||
extension_configs={
|
||||
"mdx_math": {
|
||||
"enable_dollar_delimiter": True
|
||||
}
|
||||
},
|
||||
tab_length=2,
|
||||
)
|
||||
|
||||
def markdown_filter(text):
|
||||
md = make_markdown()
|
||||
return md.convert(text)
|
||||
|
||||
env.filters["markdown"] = markdown_filter
|
||||
|
||||
output = root_dir / "test.html"
|
||||
template = env.get_template("base.html")
|
||||
output_dir = root_dir / "output"
|
||||
|
||||
def out_content(self):
|
||||
content = note.content
|
||||
if content.startswith("---\n"):
|
||||
content = content.split("---\n", 2)[2]
|
||||
return content
|
||||
|
||||
note.__class__.our_content = property(out_content)
|
||||
with output.open("w", encoding="utf-8") as f:
|
||||
data = template.render(note=note, vault=vault)
|
||||
f.write(data)
|
||||
def build_tree(vault: Vault):
|
||||
root = vault.path
|
||||
tree = {}
|
||||
for folder, dirnames, filenames in root.walk():
|
||||
for dirname in dirnames[:]:
|
||||
if dirname.startswith(".") or dirname == "attachments":
|
||||
dirnames.remove(dirname)
|
||||
cur = tree
|
||||
for part in folder.relative_to(root).parts:
|
||||
cur = cur.setdefault(part, {"children": {}})["children"]
|
||||
|
||||
import webbrowser
|
||||
webbrowser.open(output.as_uri())
|
||||
print(f"Written to {output}")
|
||||
for filename in filenames:
|
||||
# .DS_Store etc
|
||||
if filename.startswith("."):
|
||||
continue
|
||||
item = {
|
||||
"filename": filename,
|
||||
"folder": str(folder.relative_to(root)),
|
||||
}
|
||||
note = vault.get_note((folder / filename).relative_to(root))
|
||||
if note:
|
||||
item["title"] = note.title
|
||||
# TODO: for search add tags, modified time, content etc
|
||||
|
||||
cur[filename] = item
|
||||
return tree
|
||||
|
||||
|
||||
def write_note(item, tree_json):
|
||||
if "children" in item:
|
||||
for child in item["children"].values():
|
||||
write_note(child, tree_json)
|
||||
else:
|
||||
path = pathlib.Path(item["folder"]) / item["filename"]
|
||||
note = vault.get_note(path)
|
||||
if note:
|
||||
out_path = output_dir / item["folder"] / (item["title"] + ".html")
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Calculate relative base_path based on folder depth
|
||||
folder = item["folder"]
|
||||
if folder == ".":
|
||||
base_path = ""
|
||||
else:
|
||||
depth = len(pathlib.Path(folder).parts)
|
||||
base_path = "../" * depth
|
||||
|
||||
with out_path.open("w", encoding="utf-8") as f:
|
||||
data = template.render(note=note, vault=vault, base_path=base_path, index_json=tree_json)
|
||||
f.write(data)
|
||||
else:
|
||||
print(f"Note not found for {path}")
|
||||
|
||||
|
||||
def build():
|
||||
"""Build the static site."""
|
||||
print("Building...")
|
||||
|
||||
# 1. Create output dir
|
||||
shutil.rmtree(output_dir, ignore_errors=True)
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
|
||||
# 1b. Symlink CSS/JS to output root
|
||||
(output_dir / "style.css").symlink_to(root_dir / "style.css")
|
||||
(output_dir / "script.js").symlink_to(root_dir / "script.js")
|
||||
|
||||
# 1c. Symlink attachments directory
|
||||
attachments_src = root_dir.parent / "content" / "attachments"
|
||||
attachments_dst = output_dir / "attachments"
|
||||
attachments_dst.symlink_to(attachments_src)
|
||||
|
||||
# 2. Build tree and write index json
|
||||
tree = build_tree(vault)
|
||||
tree_json = json.dumps(tree)
|
||||
with (output_dir / "index.json").open("w") as f:
|
||||
f.write(tree_json)
|
||||
|
||||
# 3. Write out each note as html
|
||||
write_note({"children": tree}, tree_json)
|
||||
|
||||
print(f"Built to {output_dir}")
|
||||
|
||||
|
||||
def serve(port):
|
||||
"""Build and serve the site."""
|
||||
build()
|
||||
|
||||
os.chdir(output_dir)
|
||||
print(f"Serving at http://localhost:{port}")
|
||||
server = http.server.HTTPServer(("", port), http.server.SimpleHTTPRequestHandler)
|
||||
try:
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print("\nStopped.")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Static site generator for medical notes")
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
subparsers.add_parser("build", help="Build the static site")
|
||||
|
||||
serve_parser = subparsers.add_parser("serve", help="Build and serve the site")
|
||||
serve_parser.add_argument("-p", "--port", type=int, default=8000, help="Port to serve on")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "build":
|
||||
build()
|
||||
elif args.command == "serve":
|
||||
serve(args.port)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user