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("") + + +class StandaloneHTMLGenerator(HTMLGenerator): + def generate_Doc(self, e: Doc): + self.writeraw("") + 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 @@ - - - - - - - - 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: | + --- -:::: {.header_content} -::: {partial="test-top.html" type="html"} -::: -:::: - [#test-files/test-import.md]{type=md} [#test.json]{type=metadata key=orgs}