From 72b9bc7bf15d31ce1b8315ec002c51acc415b32a Mon Sep 17 00:00:00 2001
From: Greenscreener <git@grsc.cz>
Date: Wed, 21 Feb 2024 21:43:49 +0100
Subject: [PATCH] Add special StandaloneHTMLGenerator. Also handle prepending
 the document in a more pandocy way.

---
 src/formatitko/formatitko.py       | 27 ++++++++++++++++---------
 src/formatitko/html_generator.py   | 32 ++++++++++++++++++++++++++++++
 src/formatitko/images.py           |  2 ++
 src/formatitko/output_generator.py |  3 ++-
 test/test-top.html                 |  8 --------
 test/test.md                       | 11 +++++-----
 6 files changed, 60 insertions(+), 23 deletions(-)
 delete mode 100644 test/test-top.html

diff --git a/src/formatitko/formatitko.py b/src/formatitko/formatitko.py
index 486c5a4..4038b9d 100755
--- a/src/formatitko/formatitko.py
+++ b/src/formatitko/formatitko.py
@@ -8,11 +8,10 @@ import shutil
 
 # Import local files
 from .util import import_md
-from .context import Context, BlockGroup
 from .katex import KatexClient
 from .images import ImageProcessor, ImageProcessorNamespace
 from .output_generator import OutputGenerator, FormatitkoRecursiveError
-from .html_generator import HTMLGenerator
+from .html_generator import HTMLGenerator, StandaloneHTMLGenerator
 from .transform_processor import TransformProcessor
 from .pandoc_processor import PandocProcessor
 from .tex_generator import UCWTexGenerator
@@ -27,6 +26,7 @@ def main():
 	parser.add_argument("-c", "--img-cache-dir", help="Directory to cache processed images and intermediate products. The program will overwrite files, whose dependencies are newer.", default="cache")
 	parser.add_argument("-i", "--img-web-path", help="Path where the processed images are available on the website.", default="/")
 	parser.add_argument("-w", "--output-html", help="The HTML file (for Web) to write into.")
+	parser.add_argument("-s", "--output-standalone-html", help="The Standalone HTML file to write into. A full page is generated instead of just a fragment.")
 	parser.add_argument("-t", "--output-tex", help="The TEX file to write into.")
 	parser.add_argument("-m", "--output-md", help="The Markdown file to write into. (Uses pandoc to generate markdown)")
 	parser.add_argument("-j", "--output-json", help="The JSON file to dump the pandoc-compatible AST into.")
@@ -35,6 +35,7 @@ def main():
 	parser.add_argument("-k", "--katex-socket", help="The KaTeX server socket filename obtained by running with `--katex-server`.")
 	parser.add_argument("input_filename", help="The markdown file to process.", nargs="?" if "--katex-server" in sys.argv else None)
 	parser.add_argument("--debug", action='store_true')
+	parser.add_argument("--traceback-limit", help="Traceback limit for when errors happen, defaults to 0, as it is only useful for internal debugging.", default=0)
 	args = parser.parse_args()
 
 	if args.katex_server:
@@ -54,12 +55,12 @@ def main():
 		try:
 			OutputGenerator(sys.stdout).generate(doc)
 		except FormatitkoRecursiveError as e:
-			e.pretty_print()
+			e.pretty_print(tracebacklimit=args.traceback_limit)
 
 	try:
 		doc = TransformProcessor(args.input_filename).transform(doc)
 	except FormatitkoRecursiveError as e:
-		e.pretty_print()
+		e.pretty_print(tracebacklimit=args.traceback_limit)
 
 	# Initialize the image processor (this just keeps some basic state)
 	imageProcessor = ImageProcessor({"": ImageProcessorNamespace(args.img_public_dir, args.img_web_path, args.img_cache_dir, args.img_lookup_dirs, True)})
@@ -71,15 +72,23 @@ def main():
 				try:
 					HTMLGenerator(file, katexClient, imageProcessor).generate(doc)
 				except FormatitkoRecursiveError as e:
-					e.pretty_print()
+					e.pretty_print(tracebacklimit=args.traceback_limit)
+
+	if args.output_standalone_html is not None:
+		# Initialize KaTeX client (this runs the node app and connects to a unix socket)
+		with KatexClient(socket=args.katex_socket) as katexClient:
+			with open(args.output_standalone_html, "w") as file:
+				try:
+					StandaloneHTMLGenerator(file, katexClient, imageProcessor).generate(doc)
+				except FormatitkoRecursiveError as e:
+					e.pretty_print(tracebacklimit=args.traceback_limit)
 
 	if args.output_tex is not None:
 		with open(args.output_tex, "w") as file:
 			try:
 				UCWTexGenerator(file, imageProcessor).generate(doc)
 			except FormatitkoRecursiveError as e:
-				e.pretty_print()
-
+				e.pretty_print(tracebacklimit=args.traceback_limit)
 
 	if args.output_md is not None:
 		with open(args.output_md, "w") as file:
@@ -96,7 +105,7 @@ def main():
 				try:
 					UCWTexGenerator(file, imageProcessor).generate(doc)
 				except FormatitkoRecursiveError as e:
-					e.pretty_print()
+					e.pretty_print(tracebacklimit=args.traceback_limit)
 			filename = fd.name
 		else:
 			filename = args.output_tex
@@ -109,7 +118,7 @@ def main():
 		try:
 			OutputGenerator(sys.stdout).generate(doc)
 		except FormatitkoRecursiveError as e:
-			e.pretty_print()
+			e.pretty_print(tracebacklimit=args.traceback_limit)
 
 
 if __name__ == "__main__":
diff --git a/src/formatitko/html_generator.py b/src/formatitko/html_generator.py
index 3373a25..28f49de 100644
--- a/src/formatitko/html_generator.py
+++ b/src/formatitko/html_generator.py
@@ -20,6 +20,7 @@ from .katex import KatexClient
 from .images import ImageProcessor, ImageProcessorNamespaceSearcher
 from .util import inlinify
 
+
 class HTMLGenerator(OutputGenerator):
 	imageProcessor: ImageProcessor
 	katexClient: KatexClient
@@ -317,3 +318,34 @@ class HTMLGenerator(OutputGenerator):
 
 	def generate_DefinitionList(self, e: DefinitionList):
 		self.writeln("<!-- FIXME: DefinitionLists not implemented -->")
+
+
+class StandaloneHTMLGenerator(HTMLGenerator):
+	def generate_Doc(self, e: Doc):
+		self.writeraw("<!DOCTYPE html>")
+		self.writeln(self.start_tag("html", attributes={"lang": e.get_metadata("lang", None, True)}))
+		self.writeln(self.start_tag("head"))
+		self.indent_more()
+		self.writeln(self.single_tag("meta", attributes={"charset": "utf-8"}))
+		self.writeln(self.single_tag("meta", attributes={"viewport": "width=device-width, initial-scale=1.0"}))
+		self.writeln(self.single_tag("link", attributes={"href": "https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css", "integrity":"sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0", "crossorigin":"anonymous"}))
+		if "title" in e.metadata:
+			self.write(self.start_tag("title"))
+			self.generate(e.metadata["title"])
+			self.write(self.end_tag("title"))
+			self.endln()
+		if "html-head-includes" in e.metadata:
+			self.generate(e.metadata["html-head-includes"])
+		self.indent_less()
+		self.writeln(self.end_tag("head"))
+		self.writeln(self.start_tag("body"))
+		self.indent_more()
+		super().generate_Doc(e)
+		self.indent_less()
+		self.writeln(self.end_tag("body"))
+		self.writeln(self.end_tag("html"))
+
+
+
+
+
diff --git a/src/formatitko/images.py b/src/formatitko/images.py
index 93bc2bc..d7741f0 100644
--- a/src/formatitko/images.py
+++ b/src/formatitko/images.py
@@ -150,6 +150,8 @@ class ImageProcessor:
 		return self.namespaces[path.split(":")[0] if ":" in path else ""]
 
 	def get_path_without_namespace(self, path: str) -> str:
+		if len(path.split(":")) <= 1:
+			return path
 		return ":".join(path.split(":")[1:])
 
 	def get_searcher_by_path(self, path: str, rel_dir: str, source_dir: str) -> ImageProcessorNamespaceSearcher:
diff --git a/src/formatitko/output_generator.py b/src/formatitko/output_generator.py
index 7ba1278..71dbebf 100644
--- a/src/formatitko/output_generator.py
+++ b/src/formatitko/output_generator.py
@@ -478,12 +478,13 @@ class OutputGenerator:
 		self.generate_simple_tag(e)
 
 	def generate_Doc(self, e: Doc):
+		if "header-includes" in e.metadata:  # This is the pandoc way of doing things
+			self.generate(e.metadata["header-includes"])
 		if "header_content" in e.metadata:
 			self.generate(e.metadata["header_content"])
 		self.generate_simple_tag(e)
 		if "footer_content" in e.metadata:
 			self.generate(e.metadata["footer_content"])
-	
 	def generate_BlockGroup(self, e: BlockGroup):
 		self.generate_simple_tag(e)
 
diff --git a/test/test-top.html b/test/test-top.html
deleted file mode 100644
index 0cea640..0000000
--- a/test/test-top.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<meta name="viewport" content="width=device-width, initial-scale=1">
-	<meta charset='utf-8'>
-	<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css' integrity='sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0' crossorigin='anonymous'>
-</head>
-<body>
diff --git a/test/test.md b/test/test.md
index 80be954..563687c 100644
--- a/test/test.md
+++ b/test/test.md
@@ -3,12 +3,13 @@ title: 'Wooooo a title'
 subtitle: 'A subtitle'
 are_we_there_yet: False
 lang: "en"
+header-includes: |
+	<style>
+		body {
+			color: forestgreen;
+		}
+	</style>
 ---
-:::: {.header_content}
-::: {partial="test-top.html" type="html"}
-:::
-::::
-
 [#test-files/test-import.md]{type=md}
 
 [#test.json]{type=metadata key=orgs}