From ae502fee357dad7cad3c4cf1c178a2d57053bf16 Mon Sep 17 00:00:00 2001 From: Jake <j.vondoemming@stud.uni-goettingen.de> Date: Wed, 12 Oct 2022 00:22:19 +0200 Subject: [PATCH] added support for TOC closes GAUMI-fginfo/fg-website#46 --- fgs/pandoc.py | 62 ++++++++++++++++++-- lang.json | 3 + theme/templates/macros/content_renderer.html | 34 ++++++++++- theme/templates/macros/renderers.html | 4 +- 4 files changed, 93 insertions(+), 10 deletions(-) diff --git a/fgs/pandoc.py b/fgs/pandoc.py index 2139783..541c8e0 100644 --- a/fgs/pandoc.py +++ b/fgs/pandoc.py @@ -51,11 +51,7 @@ def run_pandoc(source, factories, lang, base="markdown", extensions=[], extra_ar elementlist = convert_elements_to_list(blocks) contentmetadata = {} - contentmetadata["toc_list"] = [] - contentmetadata["toc_count"] = 0 - # TODO TOC - #contentmetadata["toc"] = build_toc(n["toc_list"].copy()) # Get all images on page images = [] @@ -67,13 +63,69 @@ def run_pandoc(source, factories, lang, base="markdown", extensions=[], extra_ar if contentmetadata["has_image"]: contentmetadata["image"] = images[0] + # Get all headers on page + headers = [] + for e in elementlist: + if e.etype == "header": + headers.append(e) + contentmetadata["headers"] = headers + contentmetadata["has_header"] = (len(headers) > 0) + # Add Table-of-Contents + contentmetadata["toc"] = build_toc(headers) #blocks = json.loads(json.dumps(blocks, cls=ElementEncoder)) # Reduce to 'simple' dict, which can be converted to JSON in Jinja2. return (blocks, contentmetadata) +def build_toc(headerslist): + cache = { + "l1": None, + "l2": None, + "l3": None, + "l4": None, + "l5": None, + "l6": None + } + + trees = [] + + for cur in headerslist: + lvl = cur.level + if lvl not in range(1,7): + raise Exception("Header has invalid Level.",lvl,cur) + higher_key = "l"+str(lvl-1) + + # Create new tree element + tree = { + "element": cur, + "children": [] + } + if lvl == 1 or cache[higher_key] == None: + # This is a new root tree + trees.append(tree) + else: + # This is just a child of another tree + cache[higher_key]["children"].append(tree) + + # Overwrite cache entries [lvl,6] + for curlevel in range(lvl, 7): + cache["l"+str(curlevel)] = tree + + #def print_toc(toc, indent): + # x=' ' + # for tree in toc: + # print(f"{x*indent}- h{tree['element'].level}({tree['element'].attr['id']}):") + # print_toc(tree["children"], indent+1) + #print("===TOC===") + #print_toc(trees,0) + #print("===/TOC===") + + return trees + + + def convert_elements_to_list(elements): res = [] for element in elements: @@ -706,7 +758,7 @@ class CustomSyntaxHandler: class CustomBlockTOC(Block): etype = "toc" def replace(self, origelement, custom_sytax_register_entry): - pass # TODO continue + pass # Necessary information for rendering can be found in page.metadata['toc'] ############################## REGISTER ####################################### diff --git a/lang.json b/lang.json index d752806..1ecf58e 100644 --- a/lang.json +++ b/lang.json @@ -56,6 +56,9 @@ "left": "‚", "right": "‘" } + }, + "toc": { + "header": "Inhaltsverzeichnis" } } } diff --git a/theme/templates/macros/content_renderer.html b/theme/templates/macros/content_renderer.html index 0793c8b..04a3233 100644 --- a/theme/templates/macros/content_renderer.html +++ b/theme/templates/macros/content_renderer.html @@ -1,8 +1,9 @@ {#- Siehe https://gitlab.gwdg.de/GAUMI-fginfo/fg-website/-/blob/better-content-renderer/docs/content.md -#} -{%- macro render_content(content, lang, header_level_offset, in_footer) -%} - {%- set meta = namespace(header_level_offset=header_level_offset, in_footer=in_footer) -%} +{%- macro render_content(page, lang, header_level_offset, in_footer) -%} + {%- set content = page.content -%} + {%- set meta = namespace(header_level_offset=header_level_offset, in_footer=in_footer, page=page) -%} {{ render_blocks(content, lang, meta) }} {%- endmacro -%} @@ -22,7 +23,11 @@ {%- macro render_header(content, level, attr, lang, in_footer) -%} {%- call common.render_header_raw(content, level, attr, lang, in_footer=in_footer) -%} - {{ render_inlines(content, lang) }} + {%- if content is string -%} + {{ common.encoded_span(content) }} + {%- else -%} + {{ render_inlines(content, lang) }} + {%- endif -%} {%- endcall -%} {%- endmacro -%} @@ -93,6 +98,8 @@ {{ render_block_definitionlist(block, lang, meta) }} {%- elif etype == "lineblock" -%} {{ render_block_lineblock(block, lang, meta) }} + {%- elif etype == "toc" -%} + {{ render_block_toc(block, lang, meta) }} {%- else -%} <br><strong>ERROR: Unhandled block type: '{{ etype|e }}'</strong><br> {%- endif -%} @@ -291,6 +298,27 @@ </div> {%- endmacro -%} +{%- macro render_toc(tree, lang, meta) -%} + {%- if tree.element is defined -%} + <a class="internal" href="#{{ tree.element.attr.id }}">{{ render_inlines(tree.element.content, lang) }}</a> + {%- endif -%} + + {%- if tree.children|length -%} + <ul> + {%- for tree in tree.children -%} + <li>{{ render_toc(tree, lang, meta) }}</li> + {%- endfor -%} + </ul> + {%- endif -%} +{%- endmacro -%} +{%- macro render_block_toc(block, lang, meta) -%} + {%- set toc = meta.page.metadata.toc -%} + <nav class="toc"> + {{ render_header(t[lang].toc.header, 2 + meta.header_level_offset, None, lang, meta.in_footer) }} + {{ render_toc({"children": toc}, lang, meta) }} + </nav> +{%- endmacro -%} + {#- ############################ INLINES ################################## -#} diff --git a/theme/templates/macros/renderers.html b/theme/templates/macros/renderers.html index 189cc56..2877ad5 100644 --- a/theme/templates/macros/renderers.html +++ b/theme/templates/macros/renderers.html @@ -21,7 +21,7 @@ {%- if 'before' in s.tag.page.metadata -%} {{ sections(s.tag.page.metadata.before, lang, header_level + 1, in_footer=in_footer) }} {%- endif -%} - {{ content_renderer.render_content(s.tag.page.content, lang, header_level - 1, in_footer=in_footer) }} + {{ content_renderer.render_content(s.tag.page, lang, header_level - 1, in_footer=in_footer) }} {%- if 'after' in s.tag.page.metadata -%} {{ sections(s.tag.page.metadata.after, lang, header_level + 1, in_footer=in_footer) }} {%- endif -%} @@ -39,7 +39,7 @@ {%- if 'before' in s.page.metadata -%} {{ sections(s.page.metadata.before, lang, header_level + 1, in_footer=in_footer) }} {%- endif -%} - {{ content_renderer.render_content(s.page.content, lang, header_level - 1, in_footer=in_footer) }} + {{ content_renderer.render_content(s.page, lang, header_level - 1, in_footer=in_footer) }} {%- if 'after' in s.page.metadata -%} {{ sections(s.page.metadata.after, lang, header_level + 1, in_footer=in_footer) }} {%- endif -%} -- GitLab