introduced jinja2 templating engine for post parsing / template.html

updated a few unnecessary things
This commit is contained in:
2025-09-30 16:49:59 +02:00
parent cd5cda5f09
commit 1f46207a64
4 changed files with 82 additions and 78 deletions

View File

@@ -1,18 +1,19 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys import sys
import time
import subprocess import subprocess
import platform import platform
from pathlib import Path from pathlib import Path
from jinja2 import Environment, FileSystemLoader
import base64
import random
import marko import marko
from marko.ext.gfm import GFM from marko.ext.gfm import GFM
from watchdog.observers import Observer from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from log.Logger import * from log.Logger import *
from hashes.obfuscation.Obfuscator import Obfuscator from hashes.hashes import hash_list
from htmlhandler import htmlhandler as Handler from htmlhandler import htmlhandler as Handler
# Use absolute paths # Use absolute paths
@@ -28,7 +29,7 @@ RUST_PARSER_PATH = ROOT / "fastmd" / "target" / "release" / f"fastmd{exe_ext}"
if not RUST_PARSER_PATH.exists(): if not RUST_PARSER_PATH.exists():
RUST_PARSER_PATH = ROOT / "fastmd" / "target" / "debug" / f"fastmd{exe_ext}" RUST_PARSER_PATH = ROOT / "fastmd" / "target" / "debug" / f"fastmd{exe_ext}"
# Create Python markdown parser with table support (fallback for small files) # Create Python Markdown parser with table support (fallback for small files)
markdown_parser = marko.Markdown(extensions=[GFM]) markdown_parser = marko.Markdown(extensions=[GFM])
# Threshold for switching to Rust parser (number of lines) # Threshold for switching to Rust parser (number of lines)
@@ -100,96 +101,41 @@ def render_markdown(md_path: Path):
html_body = markdown_parser.convert(text) html_body = markdown_parser.convert(text)
else: else:
html_body = markdown_parser.convert(text) html_body = markdown_parser.convert(text)
# Extract title from filename or first H1 # Extract title from filename or first H1
title = md_path.stem title = md_path.stem
for line in text.splitlines(): for line in text.splitlines():
if line.startswith("# "): if line.startswith("# "):
title = line[2:].strip() title = line[2:].strip()
break break
import base64
import random
from hashes.hashes import hash_list
# Create clean HTML structure # Create clean HTML structure
# Pick two different hashes from hash_list # Pick two different hashes from hash_list
env = Environment(loader=FileSystemLoader("html/base"))
template = env.get_template("template.html")
hash1, hash2 = random.sample(hash_list, 2) hash1, hash2 = random.sample(hash_list, 2)
clean_html = f"""<!doctype html> # Load these variable for Jinja to use.
<html lang="en" style="height:100%; margin:0;"> clean_jinja_html = template.render(
<head> title=title,
<meta charset="utf-8"> html_body=html_body,
<meta name="viewport" content="width=device-width, initial-scale=1.0"> now=time.asctime(time.localtime()),
<title>{title}</title> hash1 = base64.b64encode(hash1.encode("utf-8")).decode("utf-8"),
<link rel="stylesheet" href="../css/main.css"> hash2 = base64.b64encode(hash2.encode("windows-1252")).decode("utf-8"),
<link rel="icon" type="image/x-icon" href="../css/favicon/favicon.ico"> timestamp=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
<script src="../js/post/download.js" defer></script> )
<!-- Prism.js CSS theme -->
<link href="https://cdn.jsdelivr.net/npm/prismjs/themes/prism.min.css" rel="stylesheet" />
<!-- Optional: different theme (e.g. dark) -->
<!-- <link href="https://cdn.jsdelivr.net/npm/prismjs/themes/prism-okaidia.min.css" rel="stylesheet" /> -->
<!-- Prism.js core + languages -->
<script src="https://cdn.jsdelivr.net/npm/prismjs/prism.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-python.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-javascript.min.js"></script>
<!-- remove if causing issues -->
<script src="../js/post/lazyimg.js"></script>
<script src="../js/shared/theme.js"></script>
<style>
a {{ text-decoration: none; color: #0066cc; }}
</style>
</head>
<body style="display:flex; flex-direction:column; min-height:100%; margin:0;">
<main class="container" style="flex:1;">
<h1 onclick="window.location.href=window.location.origin" style="cursor:pointer; display:flex; align-items:center; gap:8px; font-size:1.5em; margin:0;">
<img src="../css/icons/back.webp" width="32" height="32" alt="Back" style="display:block;" />
{title} <noscript>(Enable JavaScript!)</noscript>
</h1>
<img src="../css/icons/written.webp" width="32" height="32" alt="write_img" loading="lazy" style="vertical-align: middle;padding-left:12px; padding-left:40px;cursor:pointer;" onclick="toggleDarkMode();" />
<div class="meta" style="display: inline;cursor:pointer;" onclick="toggleDarkMode();">Written @{time.asctime(time.localtime())}</div>
<hr style="margin:10px 0;" />
<div class="html-content">
<!-- Injected by Marko or fastmd -->
{html_body}
</div>
</main>
<footer style="margin-top:auto; width:100%;">
<hr style="margin:10px 0;" />
<img src="../css/icons/date.webp" width="16" height="16" alt="date" loading="lazy" style="vertical-align: middle;" />
{time.strftime("%Y-%m-%d %H:%M:%S")}<br/>
<img src="../css/icons/magnifier.webp" width="16" height="16" alt="Hash1" loading="lazy" style="display:inline; vertical-align:middle;" />
Hash 1 (<b>UTF-8</b>)<i>:{base64.b64encode(hash1.encode("utf-8")).decode("utf-8")}</i><br />
<img src="../css/icons/magnifier.webp" width="16" height="16" alt="Hash2" loading="lazy" style="display:inline; vertical-align:middle;" />
Hash 2 (<b>Windows-1252</b>)<i>:{base64.b64encode(hash2.encode("windows-1252")).decode("windows-1252")}</i><br />
<img src="../css/icons/save.webp" width="16" height="16" alt="Hash2" loading="lazy" style="display:inline; vertical-align:middle;" />
<a id="download-md">Download as Markdown <noscript>Enable JavaScript for downloads</noscript></a>
</footer>
</body>
</html>"""
# Obfuscate the HTML for browser output
obfuscated_html = Obfuscator.obfuscate_html(clean_html)
# Ensure html directory exists # Ensure html directory exists
HTML_DIR.mkdir(exist_ok=True) HTML_DIR.mkdir(exist_ok=True)
# Maintain relative directory structure in html/ # Maintain relative directory structure in html/
relative_path = md_path.relative_to(MARKDOWN_DIR) relative_path = md_path.relative_to(MARKDOWN_DIR)
out_path = HTML_DIR / relative_path.with_suffix(".html") out_path = HTML_DIR / relative_path.with_suffix(".html")
# Create parent directories if needed # Create parent directories if needed
out_path.parent.mkdir(parents=True, exist_ok=True) out_path.parent.mkdir(parents=True, exist_ok=True)
# if obfuscate: out_path.write_text(clean_jinja_html, encoding="utf-8")
# out_path.write_text(obfuscated_html, encoding="utf-8")
# else:
# out_path.write_text(clean_html, encoding="utf-8")
out_path.write_text(clean_html, encoding="utf-8")
Logger.log_debug(f"Rendered: {md_path} -> {out_path}") Logger.log_debug(f"Rendered: {md_path} -> {out_path}")
def remove_html(md_path: Path): def remove_html(md_path: Path):

57
html/base/template.html Normal file
View File

@@ -0,0 +1,57 @@
<!doctype html>
<html lang="en" style="height:100%; margin:0;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<link rel="stylesheet" href="../css/main.css">
<link rel="icon" type="image/x-icon" href="../css/favicon/favicon.ico">
<script src="../js/post/download.js" defer></script>
<!-- Prism.js CSS theme -->
<link href="https://cdn.jsdelivr.net/npm/prismjs/themes/prism.min.css" rel="stylesheet" />
<!-- Prism.js core + languages -->
<script src="https://cdn.jsdelivr.net/npm/prismjs/prism.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-python.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs/components/prism-javascript.min.js"></script>
<!-- remove if causing issues -->
<script src="../js/post/lazyimg.js"></script>
<script src="../js/shared/theme.js"></script>
<style>
a { text-decoration: none; color: #0066cc; }
</style>
</head>
<body style="display:flex; flex-direction:column; min-height:100%; margin:0;">
<main class="container" style="flex:1;">
<h1 onclick="window.location.href=window.location.origin" style="cursor:pointer; display:flex; align-items:center; gap:8px; font-size:1.5em; margin:0;">
<img src="../css/icons/back.webp" width="32" height="32" alt="⬅" style="display:block;" />
{{ title }} <noscript>(Enable JavaScript!)</noscript>
</h1>
<img src="../css/icons/written.webp" width="32" height="32" alt="📄" loading="lazy" style="vertical-align: middle;padding-left:40px;cursor:pointer;" onclick="toggleDarkMode();" />
<div class="meta" style="display: inline;cursor:pointer;" onclick="toggleDarkMode();">
Written @{{ now }}
</div>
<hr style="margin:10px 0;" />
<div class="html-content">
{{ html_body | safe }}
</div>
</main>
<footer style="margin-top:auto; width:100%;">
<hr style="margin:10px 0;" />
<img src="../css/icons/date.webp" width="16" height="16" alt="date" loading="lazy" style="vertical-align: middle;" />
{{ timestamp }}<br/>
<img src="../css/icons/magnifier.webp" width="16" height="16" alt="Hash1" loading="lazy" style="display:inline; vertical-align:middle;" />
Hash 1 (<b>UTF-8</b>)<i>:{{ hash1 }}</i><br />
<img src="../css/icons/magnifier.webp" width="16" height="16" alt="Hash2" loading="lazy" style="display:inline; vertical-align:middle;" />
Hash 2 (<b>Windows-1252</b>)<i>:{{ hash2 }}</i><br />
<img src="../css/icons/save.webp" width="16" height="16" alt="Hash2" loading="lazy" style="display:inline; vertical-align:middle;" />
<a id="download-md">Download as Markdown <noscript>Enable JavaScript for downloads</noscript></a>
</footer>
</body>
</html>

Binary file not shown.

View File

@@ -5,11 +5,9 @@ import subprocess
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
import mimetypes import mimetypes
from jsmin import jsmin # pip install jsmin from jsmin import jsmin # pip install jsmin
import time
from log.Logger import * from log.Logger import *
logger = Logger() logger = Logger()
import PyPost
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
HTML_DIR = os.path.join(PROJECT_ROOT, "html") HTML_DIR = os.path.join(PROJECT_ROOT, "html")
@@ -58,6 +56,7 @@ H2 = random.choice(H2_CANDIDATES) if H2_CANDIDATES else H1
# cahcing was a bad, idea, servertime got stuck. it is now a variable ;) # cahcing was a bad, idea, servertime got stuck. it is now a variable ;)
def index_footer(): def index_footer():
tor_link = "http://7uhuxits7qfmiagkmpazxvh3rtk6aijs6pbawge3fl77y4xqjixlhkqd.onion/"
return f""" return f"""
<!-- Footer styling doesnt need to work with <!-- Footer styling doesnt need to work with
flex, or anything else, because pagnation. flex, or anything else, because pagnation.
@@ -79,7 +78,9 @@ def index_footer():
Hash 2 (<b>Windows-1252</b>)<i>:{base64.b64encode(H2.encode("windows-1252")).decode("windows-1252")}</i><br /> Hash 2 (<b>Windows-1252</b>)<i>:{base64.b64encode(H2.encode("windows-1252")).decode("windows-1252")}</i><br />
<!-- Git Repository Link --> <!-- Git Repository Link -->
<img src="../css/icons/written.webp" width="16" height="16" alt="Hash2" loading="lazy" style="display:inline; vertical-align:middle;" /> <img src="../css/icons/written.webp" width="16" height="16" alt="Hash2" loading="lazy" style="display:inline; vertical-align:middle;" />
<a style="text-decoration:none;color:#0066cc;font-style:italic;padding-top:5px;" href="https://rattatwinko.servecounterstrike.com/gitea/rattatwinko/PyPost">View Git-Repository</a> <a style="text-decoration:none;color:#0066cc;font-style:italic;padding-top:5px;" href="https://rattatwinko.servecounterstrike.com/gitea/rattatwinko/PyPost">View Git-Repository</a><br />
<img src="../css/icons/script.webp" width="16" height="16" alt="Hash2" loading="lazy" style="display:inline; vertical-align:middle;" />
<a style="text-decoration:none;color:#0066cc;font-style:italic;padding-top:5px;" href="{tor_link}">View Tor Site</a>
</p> </p>
</footer> </footer>
""" """