diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..522acb3108446c625e338adfc5bc78b397d2d1fe --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "mathjax"] + path = mathjax + url = https://github.com/mathjax/MathJax.git diff --git a/Makefile b/Makefile index bdfdb460dca80e7e2f615ea6373000b0fdd122e3..71ecb485ad059da37b4e4c5730e5e7cc58f78d8d 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,18 @@ .PHONY: html -html: run +html: build .PHONY: publish -publish: run +publish: build + +.PHONY: build +build: mathjax + cd fgs && python3 __main__.py + +.PHONY: mathjax +mathjax: + [ ! -d output/mathjax ] && mkdir -p output && cp -vr mathjax/es5 output/mathjax || true + +.PHONY: devserver +devserver: + cd output && python -m http.server 8000 -.PHONY: run -run: - make -C fgs diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..86d1c18cbc716e8fc5ce61a8e4e1aabaafbaa075 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,4 @@ + +content.md: content.json gen_content.py + ./gen_content.py > content.md + diff --git a/docs/content.json b/docs/content.json new file mode 100644 index 0000000000000000000000000000000000000000..9335e0983c30aca80dbbdaaef38ed01e36db47c2 --- /dev/null +++ b/docs/content.json @@ -0,0 +1,156 @@ +{ + "header": { + "eclass": "block", + "level": "int", + "attr": "attr", + "content": "inlines" + }, + "rawblock": { + "eclass": "block", + "format": "text", + "raw": "text" + }, + "bulletlist": { + "eclass": "block", + "items": "[blocks]", + "count": "int" + }, + "orderedlist": { + "eclass": "block", + "items": "[blocks]", + "count": "int", + "start": "int", + "style": [ + "default", + "example", + "decimal", + "lower_roman", + "upper_roman", + "lower_alpha", + "upper_alpha" + ], + "delim": [ + "default", + "period", + "one_parenthesis", + "two_parentheses" + ] + }, + "blockquote": { + "eclass": "block", + "content": "blocks" + }, + "plain": { + "eclass": "block", + "content": "inlines" + }, + "paragraph": { + "eclass": "block", + "content": "inlines" + }, + "codeblock": { + "eclass": "block", + "attr": "attr", + "code": "text", + "code_lines": "[text]" + }, + "horizontalrule": { + "eclass": "block" + }, + "blockcontainer": { + "eclass": "block", + "attr": "attr", + "content": "blocks" + }, + "space": { + "eclass": "inline" +}, + "linebreak": { + "eclass": "inline" +}, + "softbreak": { + "eclass": "inline" +}, + "string": { + "eclass": "inline", + "text": "text" + }, + "strong": { + "eclass": "inline", + "content": "inlines" + }, + "emph": { + "eclass": "inline", + "content": "inlines" + }, + "underline": { + "eclass": "inline", + "content": "inlines" + }, + "strikeout": { + "eclass": "inline", + "content": "inlines" + }, + "superscript": { + "eclass": "inline", + "content": "inlines" + }, + "subscript": { + "eclass": "inline", + "content": "inlines" + }, + "smallcaps": { + "eclass": "inline", + "content": "inlines" + }, + "link": { + "eclass": "inline", + "attr": "attr", + "content": "inlines", + "url": "text", + "title": "text" + }, + "image": { + "eclass": "inline", + "attr": "attr", + "alt": "inlines", + "url": "text", + "title": "text" + }, + "quoted": { + "eclass": "inline", + "quotetype": [ + "single", + "double" + ], + "content": "inlines" + }, + "math": { + "eclass": "inline", + "mathtype": [ + "display", + "inline" + ], + "math": "text" + }, + "code": { + "eclass": "inline", + "attr": "attr", + "code": "text", + "code_lines": "[text]" + }, + "inlinecontainer": { + "eclass": "inline", + "attr": "attr", + "content": "inlines" + }, + "rawinline": { + "eclass": "inline", + "format": "text", + "raw": "text" + }, + "footnote": { + "eclass": "inline", + "content": "blocks" + } +} diff --git a/docs/content.md b/docs/content.md new file mode 100644 index 0000000000000000000000000000000000000000..f417821d35c3e0a1a16290bb7f328880a3be92fd --- /dev/null +++ b/docs/content.md @@ -0,0 +1,302 @@ + +# Content Format + + + + + + +## Attr + + +| Key | Parser | Comment | +|-----|--------|---------| +| id | String | | +| classes | \[String\] | | +| extra | {foo: bar, alice: bob, ...} | | + + +## Blocks + + +### header + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `header` | | +| eclass | `block` | | +| level | Integer | | +| attr | [Attr](#attr) | | +| content | \[[Inline](#inlines)\] | | + + +### rawblock + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `rawblock` | | +| eclass | `block` | | +| format | String | | +| raw | String | | + + +### bulletlist + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `bulletlist` | | +| eclass | `block` | | +| items | \[\[[Block](#blocks)\]\] | | +| count | Integer | | + + +### orderedlist + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `orderedlist` | | +| eclass | `block` | | +| items | \[\[[Block](#blocks)\]\] | | +| count | Integer | | +| start | Integer | | +| style | `default` \| `example` \| `decimal` \| `lower_roman` \| `upper_roman` \| `lower_alpha` \| `upper_alpha` | | +| delim | `default` \| `period` \| `one_parenthesis` \| `two_parentheses` | | + + +### blockquote + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `blockquote` | | +| eclass | `block` | | +| content | \[[Block](#blocks)\] | | + + +### plain + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `plain` | | +| eclass | `block` | | +| content | \[[Inline](#inlines)\] | | + + +### paragraph + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `paragraph` | | +| eclass | `block` | | +| content | \[[Inline](#inlines)\] | | + + +### codeblock + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `codeblock` | | +| eclass | `block` | | +| attr | [Attr](#attr) | | +| code | String | | +| code_lines | \[String\] | | + + +### horizontalrule + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `horizontalrule` | | +| eclass | `block` | | + + +### blockcontainer + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `blockcontainer` | | +| eclass | `block` | | +| attr | [Attr](#attr) | | +| content | \[[Block](#blocks)\] | | + + +## Inlines + + +### space + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `space` | | +| eclass | `inline` | | + + +### linebreak + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `linebreak` | | +| eclass | `inline` | | + + +### softbreak + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `softbreak` | | +| eclass | `inline` | | + + +### string + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `string` | | +| eclass | `inline` | | +| text | String | | + + +### strong + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `strong` | | +| eclass | `inline` | | +| content | \[[Inline](#inlines)\] | | + + +### emph + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `emph` | | +| eclass | `inline` | | +| content | \[[Inline](#inlines)\] | | + + +### underline + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `underline` | | +| eclass | `inline` | | +| content | \[[Inline](#inlines)\] | | + + +### strikeout + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `strikeout` | | +| eclass | `inline` | | +| content | \[[Inline](#inlines)\] | | + + +### superscript + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `superscript` | | +| eclass | `inline` | | +| content | \[[Inline](#inlines)\] | | + + +### subscript + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `subscript` | | +| eclass | `inline` | | +| content | \[[Inline](#inlines)\] | | + + +### smallcaps + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `smallcaps` | | +| eclass | `inline` | | +| content | \[[Inline](#inlines)\] | | + + +### link + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `link` | | +| eclass | `inline` | | +| attr | [Attr](#attr) | | +| content | \[[Inline](#inlines)\] | | +| url | String | | +| title | String | | + + +### image + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `image` | | +| eclass | `inline` | | +| attr | [Attr](#attr) | | +| alt | \[[Inline](#inlines)\] | | +| url | String | | +| title | String | | + + +### quoted + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `quoted` | | +| eclass | `inline` | | +| quotetype | `single` \| `double` | | +| content | \[[Inline](#inlines)\] | | + + +### math + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `math` | | +| eclass | `inline` | | +| mathtype | `display` \| `inline` | | +| math | String | | + + +### code + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `code` | | +| eclass | `inline` | | +| attr | [Attr](#attr) | | +| code | String | | +| code_lines | \[String\] | | + + +### inlinecontainer + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `inlinecontainer` | | +| eclass | `inline` | | +| attr | [Attr](#attr) | | +| content | \[[Inline](#inlines)\] | | + + +### rawinline + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `rawinline` | | +| eclass | `inline` | | +| format | String | | +| raw | String | | + + +### footnote + +| Key | Parser | Comment | +|-----|--------|---------| +| etype | `footnote` | | +| eclass | `inline` | | +| content | \[[Block](#blocks)\] | | diff --git a/docs/gen_content.py b/docs/gen_content.py new file mode 100755 index 0000000000000000000000000000000000000000..6cb27e3262cdbb7d12b5342a5b445e6f87d4e5b1 --- /dev/null +++ b/docs/gen_content.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 + +import json +import os + +header = """ +# Content Format + + + +""" + +def print_entry(key, parser_raw): + # | key | parser | comment | + parser = '`' + str(parser_raw) + '`' + + if parser_raw == "text": + parser = "String" + elif parser_raw == "int": + parser = "Integer" + elif parser_raw == "[text]": + parser = "\[String\]" + elif parser_raw == "attr": + parser = "[Attr](#attr)" + elif parser_raw == "blocks": + parser = "\[[Block](#blocks)\]" + elif parser_raw == "[blocks]": + parser = "\[\[[Block](#blocks)\]\]" + elif parser_raw == "inlines": + parser = "\[[Inline](#inlines)\]" + elif parser_raw == "kvps": + parser = "{foo: bar, alice: bob, ...}" + elif isinstance(parser_raw,list): + parser = '`' + '` \| `'.join(parser_raw) + '`' + + print("| {key} | {parser} | {comment} |".format(key=key, parser=parser, comment="")) + +def print_table_header(): + print("| Key | Parser | Comment |") + print("|-----|--------|---------|") + + +def print_etype(etype, c): + print("") + print("") + print("### {etype}".format(etype=etype)) + print("") + print_table_header() + print_entry("etype", etype) + for key, value in c.items(): + print_entry(key, value) + + +if __name__ == '__main__': + j = {} + with open('content.json') as f: + j = json.loads(f.read()) + + print(header) + print("") + print("") + print("## Attr") + print("") + print("") + print_table_header() + print_entry("id", "text") + print_entry("classes", "[text]") + print_entry("extra", "kvps") + + + print("") + print("") + print("## Blocks") + is_blocks = True + for etype, c in j.items(): + if c['eclass'] != 'block' and is_blocks: + is_blocks = False + print("") + print("") + print("## Inlines") + print_etype(etype, c) + + diff --git a/fgs/Makefile b/fgs/Makefile index 6cfa260bbf2297c11be043f09ddb62a9ada3e30e..61357d60c72710f07dfe8358631094058ec73efe 100644 --- a/fgs/Makefile +++ b/fgs/Makefile @@ -1,4 +1,4 @@ .PHONY: run run: - python3 __main__.py + make -C .. diff --git a/fgs/page.py b/fgs/page.py index 801b5959f0795e08ed237509f302746723fe7f96..cc2c7a308a0626e421084cc96b79fd1c4afdf3b9 100644 --- a/fgs/page.py +++ b/fgs/page.py @@ -5,7 +5,6 @@ class Page: #raw = None #metadata = None #content = None - #toc = None #title = None #category = None #slug = None @@ -18,13 +17,12 @@ class Page: #template = None - def __init__(self, filename, subpath, raw, metadata, content, toc, title, category, slug, lang, date_created, date_modified, authors, last_modification_author, status, config): + def __init__(self, filename, subpath, raw, metadata, content, title, category, slug, lang, date_created, date_modified, authors, last_modification_author, status, config): self.filename = filename self.subpath = subpath self.raw = raw self.metadata = metadata self.content = content - self.toc = toc self.title = title self.category = category self.slug = slug diff --git a/fgs/pandoc.py b/fgs/pandoc.py new file mode 100644 index 0000000000000000000000000000000000000000..d3ebc20b9518093968246e0a2c2be0c73d53036e --- /dev/null +++ b/fgs/pandoc.py @@ -0,0 +1,436 @@ +#!/usr/bin/env python3 + +import subprocess +import json +import sys + +def run_pandoc(source, base="markdown", extensions=[], extra_args=[]): + to = "json" + ext_str = "" + if isinstance(extensions, list): + for ext in extensions: + if ext.startswith('#'): + continue + if ext.startswith('+') or ext.startswith('-'): + ext_str = ext_str + ext + elif len(ext) > 0: + ext_str = ext_str + '+' + ext + elif isinstance(extensions, dict): + for ext_key in extensions: + # TODO catch 'illegal' ext_keys (containing spaces for example) + ext = extensions[ext_key] + if "ignore" in ext and ext["ignore"]: + continue + flag='+' + if "enabled" in ext and not ext["enabled"]: + flag='-' + ext_str = ext_str + flag + ext_key + + #print(ext_str) + pandoc_bin = "pandoc" + args = [pandoc_bin, "-f", base + ext_str, "-t", to] + extra_args + p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + out, _ = p.communicate(source.encode('utf-8', errors='strict')) + out_str = out.decode('utf-8') + out_dict = json.loads(out.decode('utf-8')) + + if json.dumps(out_dict["pandoc-api-version"]) != "[1, 22, 2]": + raise Exception("Unsupported pandoc-api version", out_dict["pandoc-api-version"]) + + # parse blocks + raw_blocks = out_dict['blocks'] + blocks = [] + for raw_block in raw_blocks: + #print('raw_block: ', type(raw_block), raw_block) + block = parse_from_register(block_parsing_register, raw_block) + if block != None: + blocks.append(block) + + contentmetadata = {} + contentmetadata["toc_list"] = [] + contentmetadata["toc_count"] = 0 + + # TODO TOC + #contentmetadata["toc"] = build_toc(n["toc_list"].copy()) + + blocks = json.loads(json.dumps(blocks, cls=ElementEncoder)) # Reduce to 'simple' dict, which can be converted to JSON in Jinja2. + + return (blocks, contentmetadata) + +def parse_from_register(reg: dict, h: dict): + t = h['t'] # pandoc type + if t not in reg: + raise Exception("pandoc type not in register", t, h) + entry = reg[t] # registry entry + + c = None + if 'c' in h: + c = h['c'] + + res = None + + if isinstance(entry, dict): + if "TODO" in entry and entry["TODO"]: + print("Warning: entry is marked as TODO: ",t, entry,file=sys.stderr) + return None + + handler = entry['handler'] + res = handler(entry['etype']) + else: + handler = entry + res = handler() + + res.parse(c) + + return res + + +class ElementEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, Element): + res = {} + for key, name in obj.export.items(): + res[name] = getattr(obj, key) + return res + return super().default(obj) + +class Element(): + def __init__(self, etype = None): + if etype != None: + self.etype = etype + self.children = [] + self.export = {} + + self.export_key('etype', 'type') + self.export_key('eclass', 'class') + self.export_key('children') + + def addChild(self, child): + if child != None: + self.children.append(child) + + def parse_internal(self, pandocraw): + raise Exception("parse_internal not overridden: ", self) + + def parse(self, pandocraw): + prevkeys = dir(self) + self.parse_internal(pandocraw) + afterkeys = dir(self) + for key in afterkeys: + if key not in prevkeys: + self.export_key(key) + + + def export_key(self, key, name=None): + if name == None: + name = key + self.export[key] = name + + + + def parse_blocks(self, raw_blocks): + if not isinstance(raw_blocks, list): + raise Exception("raw_blocks is not a list: ", raw_blocks) + res = [] + for raw_block in raw_blocks: + block = self.parse_block(raw_block) + if block != None: + res.append(block) + return res + def parse_inlines(self, raw_inlines): + if not isinstance(raw_inlines, list): + raise Exception("raw_inlines is not a list: ", raw_inlines) + res = [] + for raw_inline in raw_inlines: + inline = self.parse_inline(raw_inline) + if inline != None: + res.append(inline) + return res + + def parse_block(self, raw_block): + res = parse_from_register(block_parsing_register, raw_block) + self.addChild(res) + return res + def parse_inline(self, raw_inline): + res = parse_from_register(inline_parsing_register, raw_inline) + self.addChild(res) + return res + + def parse_attr(self, raw_attr): + #print("called parse_attr: ", raw_attr) + res = {} + res['id'] = self.parse_text(raw_attr[0]) + classes = [] + for c in raw_attr[1]: + classes.append(self.parse_text(c)) + res['classes'] = classes + # convert [ "key1", "value1", "key2", "value2" ] to {"key1":"value1", "key2", "value2"} + it = iter(raw_attr[2]) + kvp = dict(zip(it, it)) # key-value pairs + extra = {} + for key, value in kvp.items(): + res[key] = self.parse_text(value) + res['extra'] = extra + + return res + + def parse_text(self, raw_text): + if len(raw_text) > 0: + return raw_text + else: + return None + + def parse_int(self, raw_num): + return raw_num # TODO + + def parse_target(self, raw_target): # For URLs + res = {} + res['url'] = self.parse_text(raw_target[0]) + res['title'] = self.parse_text(raw_target[1]) + return res + + def parse_code(self, code): + res = {} + res["code"] = self.parse_text(code) + res["code_lines"] = code.splitlines() + return res + + def parse_enum(self, mapping, enum): + if len(enum.keys()) != 1 or "t" not in enum: + raise Exception("enum is not a valid enum", enum, mapping) + enum = enum["t"] + if enum not in mapping: + raise Exception("enum not found in mapping") + return mapping[enum] + + def update(self, d): # Like dict.update() + for key, value in d.items(): + setattr(self, key, value) + + + +################################ BLOCK ######################################### + +class Block(Element): + eclass = "block" + + +class BlockHeader(Block): # Int Attr [Inline] + etype = "header" + def parse_internal(self, pandocraw): + self.level = self.parse_int(pandocraw[0]) + self.attr = self.parse_attr(pandocraw[1]) + self.content = self.parse_inlines(pandocraw[2]) + +class BlockRaw(Block): # Format Text + etype = "rawblock" + def parse_internal(self, pandocraw): + self.format = self.parse_text(pandocraw[0]) + self.raw = self.parse_text(pandocraw[1]) + +class BlockList(Block): # [[Block]] + def parse_listitems(self, rawitems): + res = {} + res['items'] = [] + for itemrawblocks in rawitems: + item = self.parse_blocks(itemrawblocks) + res['items'].append(item) + res['count'] = len(res['items']) + return res + +class BlockBulletList(BlockList): # [[Block]] + etype = "bulletlist" + def parse_internal(self, pandocraw): + self.update(self.parse_listitems(pandocraw)) + +class BlockOrderedList(BlockList): # ListAttributes [[Block]] + etype = "orderedlist" + def parse_internal(self, pandocraw): + self.update(self.parse_orderedlist_attr(pandocraw[0])) + self.update(self.parse_listitems(pandocraw[1])) + + def parse_orderedlist_attr(self, attrs: list): + res = {} + res["start"] = self.parse_int(attrs[0]) + + styles = { + "DefaultStyle": "default", + "Example" : "example" , + "Decimal" : "decimal" , + "LowerRoman" : "lower_roman" , + "UpperRoman" : "upper_roman" , + "LowerAlpha" : "lower_alpha" , + "UpperAlpha" : "upper_alpha" , + } + res["style"] = self.parse_enum(styles, attrs[1]) + + delims = { + "DefaultDelim" : "default" , + "Period" : "period" , + "OneParen" : "one_parenthesis" , + "TwoParens" : "two_parentheses" , + } + res["delim"] = self.parse_enum(delims, attrs[2]) + + return res + +class BlockQuote(Block): # [Block] + etype = "blockquote" + def parse_internal(self, pandocraw): + self.content = self.parse_blocks(pandocraw) + # TODO add name, color, time + +class BlockPlain(Block): # [Inline] + etype = "plain" + def parse_internal(self, pandocraw): + self.content = self.parse_inlines(pandocraw) + +class BlockParagraph(Block): # [Inline] + etype = "paragraph" + def parse_internal(self, pandocraw): + self.content = self.parse_inlines(pandocraw) + +class BlockCode(Block): # Attr Text + etype = "codeblock" + def parse_internal(self, pandocraw): + self.attr = self.parse_attr(pandocraw[0]) + self.update(self.parse_code(pandocraw[1])) + +class BlockHorizontalRule(Block): # + etype = "horizontalrule" + def parse_internal(self, pandocraw): + pass + +class BlockContainer(Block): # Attr [Block] + # a div + etype = "blockcontainer" + def parse_internal(self, pandocraw): + self.attr = self.parse_attr(pandocraw[0]) + self.content = self.parse_blocks(pandocraw[1]) + # TODO handle alerts + +############################## INLINE ######################################### + +class Inline(Element): + eclass = "inline" + +class InlineSpace(Inline): # + etype = "space" + def parse_internal(self, pandocraw): + pass + +class InlineLineBreak(Inline): # + etype = "linebreak" + def parse_internal(self, pandocraw): + pass + +class InlineSoftBreak(Inline): # + etype = "softbreak" + def parse_internal(self, pandocraw): + pass + +class InlineString(Inline): # Text + etype = "string" + def parse_internal(self, pandocraw): + self.text = self.parse_text(pandocraw) + # TODO handle abbreviations + +class InlineSimple(Inline): # [Inline] + def __init__(self, etype): + self.etype = etype + super().__init__() + + def parse_internal(self, pandocraw): + self.content = self.parse_inlines(pandocraw) + +class InlineLink(Inline): # Attr [Inline] Target + etype = "link" + def parse_internal(self, pandocraw): + self.attr = self.parse_attr(pandocraw[0]) + self.content = self.parse_inlines(pandocraw[1]) + self.update(self.parse_target(pandocraw[2])) + +class InlineImage(Inline): # Attr [Inline] Target + etype = "image" + def parse_internal(self, pandocraw): + self.attr = self.parse_attr(pandocraw[0]) + self.alt = self.parse_inlines(pandocraw[1]) + self.update(self.parse_target(pandocraw[2])) + +class InlineQuoted(Inline): # QuoteType Text + etype = "quoted" + def parse_internal(self, pandocraw): + self.quotetype = self.parse_enum({"SingleQuote": "single", "DoubleQuote": "double"}, pandocraw[0]) + self.content = self.parse_inlines(pandocraw[1]) + +class InlineMath(Inline): # MathType Text + etype = "math" + def parse_internal(self, pandocraw): + self.mathtype = self.parse_enum({"DisplayMath": "display", "InlineMath": "inline"}, pandocraw[0]) + self.math = self.parse_text(pandocraw[1]) + +class InlineCode(Inline): # Attr Text + etype = "code" + def parse_internal(self, pandocraw): + self.attr = self.parse_attr(pandocraw[0]) + self.update(self.parse_code(pandocraw[1])) + +class InlineContainer(Inline): # Attr [Inline] + etype = "inlinecontainer" + def parse_internal(self, pandocraw): + self.attr = self.parse_attr(pandocraw[0]) + self.content = self.parse_inlines(pandocraw[1]) + # TODO handle emojis + +class InlineFootnote(Inline): # [Block] + etype = "footnote" + def parse_internal(self, pandocraw): + self.content = self.parse_blocks(pandocraw) + # TODO add footnote ids # TODO add back references # TODO handle duplicates + +class InlineRaw(Inline): # Format Text + etype = "rawinline" + def parse_internal(self, pandocraw): + self.format = self.parse_text(pandocraw[0]) + self.raw = self.parse_text(pandocraw[1]) + + +inline_parsing_register = { + "Space" : InlineSpace, + "Str" : InlineString, + "Strong" :{"handler" : InlineSimple, "etype":"strong" }, + "Emph" :{"handler" : InlineSimple, "etype":"emph" }, + "Underline" :{"handler" : InlineSimple, "etype":"underline" }, + "Strikeout" :{"handler" : InlineSimple, "etype":"strikeout" }, + "Superscript":{"handler" : InlineSimple, "etype":"superscript"}, + "Subscript" :{"handler" : InlineSimple, "etype":"subscript" }, + "SmallCaps" :{"handler" : InlineSimple, "etype":"smallcaps" }, + "Link" : InlineLink, + "Image" : InlineImage, + "Quoted" : InlineQuoted, + "Math" : InlineMath, + "Code" : InlineCode, + "Span" : InlineContainer, + "RawInline" : InlineRaw, + "Note" : InlineFootnote, + #"Cite" :{"type":"citation","TODO": True, "c" : [] }, # [Citation] [Inline] # TODO find file that triggers Cite + "SoftBreak" : InlineSoftBreak, + "LineBreak" : InlineLineBreak, +} +block_parsing_register = { + "Plain" : BlockPlain, + "Para" : BlockParagraph, + "BlockQuote" : BlockQuote, + "BulletList" : BlockBulletList, + "RawBlock" : BlockRaw, + "Header" : BlockHeader, + "CodeBlock" : BlockCode, + "Div" : BlockContainer, + "OrderedList" : BlockOrderedList, + "HorizontalRule": BlockHorizontalRule, + "Table" : {"TODO": True,}, # Attr Caption [ColSpec] TableHead [TableBody] TableFoot + "DefinitionList": {"TODO": True,}, # [([Inline], [[Block]])] + #"LineBlock" :{"type":"lineblock", "TODO": True, "c" : [] }, # [[Inline]] # TODO find file that triggers LineBlock + #"Null" :{"type":"nothing" }, # TODO find file that triggers Null +} + diff --git a/fgs/pandoc_toc.html b/fgs/pandoc_toc.html deleted file mode 100644 index 2fd5a7bd68b1d9474ccc9e42a8dc058a8801e06b..0000000000000000000000000000000000000000 --- a/fgs/pandoc_toc.html +++ /dev/null @@ -1 +0,0 @@ -$table-of-contents$ diff --git a/fgs/reader.py b/fgs/reader.py index 9cc14065d9781c638546842e82415482dac9354a..1e8058f379df96aefb334802b74bec0aadc1f4bc 100644 --- a/fgs/reader.py +++ b/fgs/reader.py @@ -1,4 +1,5 @@ import page +import pandoc import frontmatter @@ -24,22 +25,19 @@ class MarkdownReader: print("parsing file: ", path, subpath) f = open(path) - rawcontent = f.read() + rawfile = f.read() f.close() - metadata, _ = frontmatter.parse(rawcontent) + metadata, rawcontent = frontmatter.parse(rawfile) #print(metadata) category_name = self.get_category_name(metadata, subpath) # content - content = self.run_pandoc(rawcontent, self.config['pandoc']['base'], self.config['pandoc']['extensions'], "html5") + content, contentmetadata = pandoc.run_pandoc(source=rawcontent, base=self.config['pandoc']['base'], extensions=self.config['pandoc']['extensions']) + metadata.update(contentmetadata) # merge content specific metadata into metadata #print(content) - # TOC - toc = self.run_pandoc(rawcontent, self.config['pandoc']['base'], self.config['pandoc']['extensions'], "html5", ["--template", "./pandoc_toc.html", "--toc", "--toc-depth", str(self.config['toc_depth'])]) - #print((toc)) - # title if 'title' not in metadata: raise Exception("File is missing title in metadata: ", path, subpath) @@ -117,10 +115,9 @@ class MarkdownReader: p = page.Page( filename, subpath, - rawcontent, + rawfile, metadata, content, - toc, title, category_name, slug, @@ -182,37 +179,3 @@ class MarkdownReader: return out_str - def run_pandoc(self, source, base="markdown", extensions=[], to="json", extra_args=[]): - ext_str = "" - if isinstance(extensions, list): - for ext in extensions: - if ext.startswith('#'): - continue - if ext.startswith('+') or ext.startswith('-'): - ext_str = ext_str + ext - elif len(ext) > 0: - ext_str = ext_str + '+' + ext - elif isinstance(extensions, dict): - for ext_key in extensions: - # TODO catch 'illegal' ext_keys (containing spaces for example) - ext = extensions[ext_key] - if "ignore" in ext and ext["ignore"]: - continue - flag='+' - if "enabled" in ext and not ext["enabled"]: - flag='-' - ext_str = ext_str + flag + ext_key - - #print(ext_str) - pandoc_bin = "pandoc" - args = [pandoc_bin, "-f", base + ext_str, "-t", to] + extra_args - p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) - out, _ = p.communicate(source.encode('utf-8', errors='strict')) - out_str = out.decode('utf-8') - #print("----------------------") - #print(out_str) - #print("----------------------") - #json_dict = json.loads(out.decode('utf-8')) - return out_str - - diff --git a/lang.json b/lang.json index 56055dc73d694c7ec93b3c53a18cc55145f2511f..5382dd7e64cbbbb75c24d5b34bd2ab7ece7ca586 100644 --- a/lang.json +++ b/lang.json @@ -48,6 +48,16 @@ "only_pages": { "title": "Seiten" }, - "no_content": "Diese Seite hat noch keine Inhalte." + "no_content": "Diese Seite hat noch keine Inhalte.", + "quotations": { + "double": { + "left": "„", + "right": "“" + }, + "single": { + "left": "‚", + "right": "‘" + } + } } } diff --git a/mathjax b/mathjax new file mode 160000 index 0000000000000000000000000000000000000000..600692ad9d3552cc25f85510d5797bc942ecc9f7 --- /dev/null +++ b/mathjax @@ -0,0 +1 @@ +Subproject commit 600692ad9d3552cc25f85510d5797bc942ecc9f7 diff --git a/theme/old-templates/article.html b/theme/old-templates/article.html new file mode 100644 index 0000000000000000000000000000000000000000..1a2c28ab4adf8e48fd37a66eaa57e7d741091353 --- /dev/null +++ b/theme/old-templates/article.html @@ -0,0 +1,69 @@ +{% extends "base.html" %} + +{%- macro article_translation_link(translation, is_current=False) -%} +<a href="{{ SITEURL }}/{{ translation.url }}" hreflang="{{ translation.lang }}" title="{{ l[translation.lang].langname|e }}"> + <img alt="{{ l[translation.lang].langname|e }}" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/images/flags/{{ translation.lang }}.svg"> +</a> +{%- endmacro -%} + +{% block html_lang %}{{ article.lang }}{% endblock %} + +{% block title %}{{ article.title|striptags }}{% endblock %} + +{% block extra_head %} + {%- for translation in article.translations -%} + <link rel="alternate" hreflang="{{ translation.lang }}" href="{{ SITEURL }}/{{ translation.url }}"> + {%- endfor -%} + + {% if article.summary %} + <meta name="description" content="{{ article.summary | striptags | safe | truncate(150) }}" /> + {% endif %} +{% endblock %} + +{% block content %} + <article> + <header> + <h1>{{ article.title }}</h1> + </header> + {{ article.content }} + <footer> + {%- if article.authors -%} + <address> + {{ l[lang].article.authors_prefix }} + {% for author in article.authors %} + <a href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a> + {% endfor %} + {{ l[lang].article.authors_suffix }} + </address> + {%- endif -%} + + <span>{{ l[lang].article.published_prefix }} + <abbr title="{{ article.date.isoformat() }}"> + {{ article.locale_date }} + </abbr>{{ l[lang].article.published_suffix }}</span> + + {%- if article.modified -%} + <br /> + <span>{{ l[lang].article.modified_prefix }} + <abbr title="{{ article.modified.isoformat() }}">{{ article.locale_modified }}</abbr> + {{ l[lang].article.modified_suffix }}</span> + {%- endif -%} + + <br /> + <span>{{ l[lang].article.category_prefix }}<a href="{{ SITEURL }}/{{ article.category.url }}">{{ article.category }}</a>{{ l[lang].article.category_suffix }}</span> + <br /> + <span>{{ l[lang].article.languages_prefix }}</span> + <ul class="languages"> + {%- for translation in article.translations -%} + <li> + {{ article_translation_link(translation) }} + </li> + {%- endfor -%} + <li> + {{ article_translation_link(article, True) }} + </li> + </ul> + {{ l[lang].article.languages_suffix }} + </footer> + </article> +{% endblock %} diff --git a/theme/old-templates/base.html b/theme/old-templates/base.html new file mode 100644 index 0000000000000000000000000000000000000000..6466a8f7566c435c8e4cba8909ab67d03bbc5a38 --- /dev/null +++ b/theme/old-templates/base.html @@ -0,0 +1,92 @@ +<!DOCTYPE html> +{#- TODO lang irgendwie vernünftig setzen/erkennen -#} +{%- if lang is not defined -%} + {%- set lang = DEFAULT_LANG -%} +{%- else -%} +Hurra!!! lang ist definiert als {{ lang }}. +{{ diese_variable_existiert_nicht_werfe_fehler }} +{%- endif -%} + +{%- import 'macros/getters.html' as get with context -%} +{%- import 'macros/cards.html' as cards with context -%} +{%- import 'macros/renderers.html' as render with context -%} + +<html lang="{%- block html_lang -%}{{ DEFAULT_LANG }}{%- endblock html_lang -%}"> +<head> + {% block head %} + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{% block title %}{{ l[lang].title_prefix }}{{ l[lang].sitename }}{{ l[lang].title_suffix }}{%endblock%}</title> + <!-- <base target="_blank"> --> + <!-- <meta HTTP-EQUIV="REFRESH" content="500; url=#"> --> + <link rel="preload" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/css/{{ CSS_FILE }}" as="style" /> + <link rel="stylesheet" type="text/css" href="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/css/{{ CSS_FILE }}" /> + {#- TODO load javascript? -#} + {#- TODO og: meta tags -#} + {#- TODO favicon -#} + <!-- <link rel="icon" type="image/png" sizes="192x192" href="static/img/favicon-192x192.png"/> + <link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png"/>--> + <!-- <link rel="icon" type="image/x-icon" sizes="16x16" href="static/img/favicon.ico"/> --> + {%- if FEED_ALL_ATOM %} + <link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_ATOM_URL %}{{ FEED_ALL_ATOM_URL }}{% else %}{{ FEED_ALL_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ l[lang].atom.title|e }}" /> + {% endif -%} + {% block extra_head %}{% endblock extra_head %} + {% endblock head %} +</head> +<body> + <header> + {% block header %} + <h1><a href="{{ SITEURL }}/" title="{{ l[lang].banner.title|e }}" ><img alt="{{ l[lang].banner.alt|e }}" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/images/banner-logo.png"><span>{{ l[lang].banner.prefix|e }}{{ l[lang].sitename|e }}{{ l[lang].banner.suffix|e }}</span></a></h1> + {% block extra_header %}{% endblock extra_header %} + {% endblock header %} + </header> + <div class="nav-container"> + <label for="show-header-menu" class="show-header-menu">☰</label> + <input type="checkbox" id="show-header-menu" role="button"> + <label for="show-header-menu" class="show-header-menu-bg"> </label> + <nav> + <ul> + {% for item in sc.menuitems -%} + {%- if item.category is defined -%} + {%- call(nativecat, sccat, _) get.category_by_name(item.category) -%} + <li style="--category-color: {{ sccat.color }}"><a href="{{ SITEURL }}/{{ nativecat.url }}">{{ sccat[lang]|e }}</a></li> + {%- endcall -%} + {%- elif item.tag is defined -%} + {%- call(nativetag, sccat, _) get.tag_by_name(item.tag) -%} + <li style="--category-color: {{ sccat.color }}"><a href="{{ SITEURL }}/{{ nativetag.url }}">{{ sccat[lang]|e }}</a></li> + {%- endcall -%} + {%- elif item.slug is defined -%} + {%- call(aop, _) get.article_or_page_by_slug(item.slug, lang) -%} + {%- call(__, sccat, ___) get.category_by_name(aop.category.name, True) -%} + <li style="--category-color: {{ sccat.color }}"><a href="{{ SITEURL }}/{{ aop.url }}">{{ aop.title }}</a></li> + {%- endcall -%} + {%- endcall -%} + {%- else -%} + <br /> + <strong>ERROR: menuitems: Cannot parse item: {{ item|string|e }}</strong><br /> + <br /> + {%- endif -%} + {#- TODO add active class if this is the current site -#} + {%- endfor %} + </ul> + </nav> + </div> + <main> + {% block content %} + {% endblock content %} + </main> + <footer> + {% block footer %} + {#- TODO besserer footer -#} + <div> + <a href="https://asta.uni-goettingen.de/impressum/datenschutz/">Datenschutz</a> + <a href="/fg-website/Impressum.md">Impressum</a> + <div> + <div>Fachgruppe Informatik Göttingen, 2022.</div> + <!-- blablabla datenschutz,impressum etc... --> + {% block extra_footer %}{% endblock extra_footer %} + {% endblock footer %} + </footer> +</body> +<!-- The Cake Is A Lie! --> +</html> diff --git a/theme/old-templates/category.html b/theme/old-templates/category.html new file mode 100644 index 0000000000000000000000000000000000000000..0c2b6e0ff9f6a25c9462dc5910bfcccf62a7aaf7 --- /dev/null +++ b/theme/old-templates/category.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block title %}{{ l[lang].title_prefix }}{{ l[lang].sitename }}{{ l[lang].title_suffix }} - {{ category }}{%endblock%} +{% block content %} + <section> + {{ render.section({"type": "category", "category": category.slug, "num": None}) }} + </section> +{% endblock content %} diff --git a/theme/old-templates/index.html b/theme/old-templates/index.html new file mode 100644 index 0000000000000000000000000000000000000000..d4f2b290de95d8c0f5e42938e0348405c51773ec --- /dev/null +++ b/theme/old-templates/index.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} +{% block content_title %}{% endblock %} + + +{% block content %} +{%- for s in sc.startpage -%} + <section> + {{ render.section(s) }} + </section> +{%- endfor -%} +{% endblock content %} diff --git a/theme/old-templates/macros/README.md b/theme/old-templates/macros/README.md new file mode 100644 index 0000000000000000000000000000000000000000..75ed3122989219278ca7cac37db4a07f01cc2e7a --- /dev/null +++ b/theme/old-templates/macros/README.md @@ -0,0 +1,184 @@ +# Macros + +[TOC] + +## [getters.html](getters.html) + +``` +{%- import 'macros/getters.html' as get with context -%} +``` + +Mit diesen Macros können Informationen abgefragt werden. + +### `category_by_name(catname, ignore_native = False)` + +**Argumente:** + +- `catname` (String): Der Name der Kategorie. +- `ignore_native` (Boolean): Setzt den ersten und dritten Rückgabewert zu `None`. (Verkürzt die Laufzeit dieser Funktion.) + +**Rückgabewerte:** + +1. ([Category](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#object-author-cat-tag)): Die native Kategorie. +2. (Dict): Der Eintrag zu der Kategorie aus der config.json-Datei aus dem Inhaltsrepo. +3. (List\<[Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article)\>): Die Artikel in der Kategorie. + +**Beispiel Aufruf:** + +``` +{%- call(nativecat, sccat, catarticles) get.category_by_name(article.category.name) -%} + <ul> + <li>Kategorie: {{ nativecat.name }}</li> + <li>Farbe: {{ sccat.color }}</li> + <li>Anzahl Artikel: {{ catarticles|length }}</li> + </ul> +{%- endcall -%} +``` + +### `tag_by_name(tagname)` + +**Argumente:** + +- `catname` (String): Der Name des Tags. + +**Rückgabewerte:** + +1. ([Tag](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#object-author-cat-tag)): Der native Tag. +2. (Dict): Falls der Tag gleichnamig zu einer Kategorie ist, dann der Eintrag zu der Kategorie aus der config.json-Datei aus dem Inhaltsrepo, sonst `None`. +3. (List\<[Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article)\>): Die Artikel die diesen Tag haben. + +**Beispiel Aufruf:** + +``` +{%- call(nativetag, sccat, tagarticles) get.tag_by_name("event") -%} + <ul> + <li>Tag: {{ nativetag.name }}</li> + <li>Farbe: {% if sccat %}{{ sccat.color }}{% else %}Dieser Tag ist nicht gleichnamig zu einer Kategorie und hat deshalb keine Farbe.{% endif %}</li> + <li>Anzahl Artikel mit diesem Tag: {{ tagarticles|length }}</li> + </ul> +{%- endcall -%} +``` + + +### `article_by_slug(slug, lang)` + +**Argumente:** + +- `slug` (String): Der Slug von dem Artikel. +- `lang` (String): Die Sprache von dem Artikel. + +**Rückgabewerte:** + +1. ([Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article)): Der Artikel. + +### `page_by_slug(slug, lang)` + +**Argumente:** + +- `slug` (String): Der Slug von der Seite. +- `lang` (String): Die Sprache von der Seite. + +**Rückgabewerte:** + +1. ([Page](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#page)): Die Seite. + +### `article_or_page_by_slug(slug, lang)` + +**Argumente:** + +- `slug` (String): Der Slug von dem Artikel oder der Seite. +- `lang` (String): Die Sprache von dem Artikel oder der Seite. + +**Rückgabewerte:** + +1. ([Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article) | [Page](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#page)): Der Artikel oder die Seite. +2. (String): "article" falls es ein Artikel ist. "page" falls es eine Seite ist. + +## [cards.html](cards.html) + +``` +{%- import 'macros/cards.html' as cards with context -%} +``` + +Mit diesen Macros können Kachelblöcke erstellt werden. + +In einem Kachelblock dürfen nur Kacheln sein und sonst nichts! + +**Beispiel:** + +``` +{{ cards.open() }} + +{%- for article in all_articles -%} + {{ cards.card_from_article_or_page(article) }} +{%- endfor -%} + +{{ cards.card(title="Dies ist auch eine Kachel", url="https://www.youtube.com/watch?v=dQw4w9WgXcQ", catcolor="green") }} + +{{ cards.close() }} +``` + +### `open(id = None, classes = None)` + +Beginnt einen Kachelblock. + +**Argumente:** + +- `id` (String): Die ID von dem Kachelblock. +- `classes` (List\<String\>): Zusätzliche Klassen für den Kachelblock. + +### `close()` + +Schließt einen Kachelblock. + +### `card(title, url, catcolor, escape_title = True, is_url_external = True)` + +Erstellt eine Kachel. + +**Argumente:** + +- `title` (String): Der Titel. +- `url` (String): Der URL. +- `catcolor` (String): Die Farbe. +- `escape_title` (Boolean): Ob `title` escaped werden soll. +- `is_url_external` (Boolean): Ob `url` auf eine externe Resource zeigt, oder als relativen Link interpretiert werden soll. + +### `card_from_article_or_page(aop)` + +Erstellt eine Kachel von einem Artikel oder einer Seite. + +**Argumente:** + +1. `aop` ([Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article) | [Page](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#page)): Der Artikel oder die Seite. + + +### `cards_from_articles_or_pages(asops, max = None, standalone = True)` + +Erstellt mehrere Kacheln oder einen vollständigen Kachelblock von mehreren Artikeln oder Seiten. + +**Argumente:** + +1. `asops` (List\<[Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article) | [Page](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#page)\>): Die Artikel oder Seiten. Kann auch gemischt sein. +2. `max` (Int | None): Falls vorhanden werden maximal `max` Kacheln gerendert. +3. `standalone` (Boolean): Ob `open()` und `close()` automatisch mit ausgeführt werden soll. + +**Beispiel Aufruf:** + +``` +{{ cards_from_articles_or_pages(all_articles, max=5) }} +``` + +## [renderers.html](renderers.html) + +``` +{%- import 'macros/renderers.html' as render with context -%} +``` + +**TODO: ** Die Dokumentation für diese Macros ist abhängig von der Dokumentation von der config.json-Datei im Inhaltsrepo. + +### `section_news(s)` +### `section_custom(s)` +### `section_iframe(s)` +### `section_category(s)` +### `section_tag(s)` +### `section(s)` diff --git a/theme/old-templates/macros/cards.html b/theme/old-templates/macros/cards.html new file mode 100644 index 0000000000000000000000000000000000000000..bea528c91af935481ca7b08df074b8c83a0c8876 --- /dev/null +++ b/theme/old-templates/macros/cards.html @@ -0,0 +1,35 @@ +{%- import 'macros/getters.html' as get with context -%} + + +{%- macro open(id = None, classes = None) -%} + <ul {%- if id %} id="{{ id|e }}"{% endif %} class="cards {%- if classes %}{% for class in classes %} {{ class|e }}{% endfor %}{% endif %}"> +{%- endmacro -%} + +{%- macro close() -%} + </ul> +{%- endmacro -%} + +{%- macro card(title, url, catcolor, escape_title = True, is_url_external = True) -%} + <li style="--category-color: {{ catcolor }}"><a href="{% if not is_url_external %}{{ SITEURL }}/{% endif %}{{ url }}">{% if escape_title %}{{ title|e }}{% else %}{{ title }}{% endif %}</a></li> +{%- endmacro -%} + +{%- macro card_from_article_or_page(aop) -%} + {%- call(_, sccat, __) get.category_by_name(aop.category.name, True) -%} + {{ card(title=aop.title, url=aop.url, catcolor=sccat.color, escape_title=False, is_url_external = False) }} + {%- endcall -%} +{%- endmacro -%} + +{%- macro cards_from_articles_or_pages(asops, max = None, standalone = True) -%} + {%- if standalone -%} + {{ open() }} + {%- endif -%} + {%- for aop in asops -%} + {%- if max == None or loop.index < max -%} + {{ cards.card_from_article_or_page(aop) }} + {%- endif -%} + {%- endfor -%} + {%- if standalone -%} + {{ close() }} + {%- endif -%} +{%- endmacro -%} + diff --git a/theme/old-templates/macros/getters.html b/theme/old-templates/macros/getters.html new file mode 100644 index 0000000000000000000000000000000000000000..1c1088d4e26ed72f34c271193e9883acf3d3a986 --- /dev/null +++ b/theme/old-templates/macros/getters.html @@ -0,0 +1,53 @@ +{%- macro category_by_name(catname, ignore_native = False) -%} + {%- if ignore_native -%} + {{- caller(None, sc.categories[catname], None) -}} + {%- else -%} + {%- for nativecat, catarticles in categories -%} + {%- if nativecat.name == catname -%} + {{- caller(nativecat, sc.categories[catname], catarticles) -}} + {%- endif -%} + {%- endfor -%} + {%- endif -%} +{%- endmacro -%} + +{%- macro tag_by_name(tagname) -%} + {%- for nativetag, tagarticles in tags -%} + {%- if nativetag.name == tagname -%} + {%- if tagname in sc.categories -%} + {{- caller(nativetag, sc.categories[tagname], tagarticles) -}} + {%- else -%} + {{- caller(nativetag, None, tagarticles) -}} + {%- endif -%} + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{%- macro article_by_slug(slug, lang) -%} + {%- for a in all_articles -%} + {%- if a.slug == slug and a.lang == lang -%} + {{- caller(a) -}} + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{%- macro page_by_slug(slug, lang) -%} + {%- for p in pages -%} + {%- if p.slug == slug and p.lang == lang -%} + {{- caller(p) -}} + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + +{%- macro article_or_page_by_slug(slug, lang) -%} + {%- for a in all_articles -%} + {%- if a.slug == slug and a.lang == lang -%} + {{- caller(a, "article") -}} + {%- endif -%} + {%- endfor -%} + {%- for p in pages -%} + {%- if p.slug == slug and p.lang == lang -%} + {{- caller(p, "page") -}} + {%- endif -%} + {%- endfor -%} +{%- endmacro -%} + diff --git a/theme/old-templates/macros/renderers.html b/theme/old-templates/macros/renderers.html new file mode 100644 index 0000000000000000000000000000000000000000..698dbcccbd9ad24f5a77b13e2687ebff69bce05d --- /dev/null +++ b/theme/old-templates/macros/renderers.html @@ -0,0 +1,71 @@ +{%- import 'macros/getters.html' as get with context -%} +{%- import 'macros/cards.html' as cards with context -%} + +{%- macro section_news(s) -%} + {{ cards.cards_from_articles_or_pages(all_articles, max=s.num) }} +{%- endmacro -%} + +{%- macro section_custom(s) -%} + {{ cards.open() }} + {%- for c in s.content -%} + {{ cards.card(title=c[lang], url=c.url, catcolor=c.color) }} + {%- endfor -%} + {{ cards.close() }} +{%- endmacro -%} + +{%- macro section_iframe(s) -%} + <iframe src="{{ s.url }}"></iframe> +{%- endmacro -%} + +{%- macro section_category(s) -%} + {%- call(nativecat, sccat, catarticles) get.category_by_name(s.category) -%} + {%- if s.title is not defined -%} + <header> + <h2 {% if s.id is defined -%}id="{{ s.id }}"{%- endif %}>{{ sccat[lang]|e }}</h2> + </header> + {%- endif -%} + {{ cards.cards_from_articles_or_pages(catarticles, max=s.num) }} + {%- endcall -%} +{%- endmacro -%} + +{%- macro section_tag(s) -%} + {%- call(nativetag, sccat, tagarticles) get.tag_by_name(s.tag) -%} + {%- if s.title is not defined -%} + <header> + <h2 {% if s.id is defined -%}id="{{ s.id }}"{%- endif %}> + {%- if sccat -%} + {{- sccat[lang]|e -}} + {%- else -%} + {{- s.tag|e -}} + {%- endif -%} + </h2> + </header> + {%- endif -%} + {{ cards.cards_from_articles_or_pages(tagarticles, max=s.num) }} + + + {%- endcall -%} +{%- endmacro -%} + +{%- macro section(s) -%} + {%- if s.title is defined -%} + <header> + <h2 {% if s.id is defined -%}id="{{ s.id }}"{%- endif %}>{{ s.title[lang]|e }}</h2> + </header> + {%- endif -%} + {%- if s.type == "news" -%} + {{ section_news(s) }} + {%- elif s.type == "iframe" -%} + {{ section_iframe(s) }} + {%- elif s.type == "custom" -%} + {{ section_custom(s) }} + {%- elif s.type == "category" -%} + {{ section_category(s) }} + {%- elif s.type == "tag" -%} + {{ section_tag(s) }} + {%- else -%} + <br /> + <strong>ERROR: render.section: Unknown section type: {{ s.type|e }}</strong><br /> + <br /> + {%- endif -%} +{%- endmacro -%} diff --git a/theme/old-templates/page.html b/theme/old-templates/page.html new file mode 100644 index 0000000000000000000000000000000000000000..af4e389ee2929cd5d3155aac3a7f8cd914899e2f --- /dev/null +++ b/theme/old-templates/page.html @@ -0,0 +1,69 @@ +{% extends "base.html" %} + +{%- macro page_translation_link(translation, is_current=False) -%} +<a href="{{ SITEURL }}/{{ translation.url }}" hreflang="{{ translation.lang }}" title="{{ l[translation.lang].langname|e }}"> + <img alt="{{ l[translation.lang].langname|e }}" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/images/flags/{{ translation.lang }}.svg"> +</a> +{%- endmacro -%} + +{% block html_lang %}{{ page.lang }}{% endblock %} + +{% block title %}{{ page.title|striptags }}{% endblock %} + +{% block extra_head %} + {%- for translation in page.translations -%} + <link rel="alternate" hreflang="{{ translation.lang }}" href="{{ SITEURL }}/{{ translation.url }}"> + {%- endfor -%} + + {% if page.summary %} + <meta name="description" content="{{ page.summary | striptags | safe | truncate(150) }}" /> + {% endif %} +{% endblock %} + +{% block content %} + <article> + <header> + <h1>{{ page.title }}</h1> + </header> + {{ page.content }} + <footer> + {%- if page.authors -%} + <address> + {{ l[lang].page.authors_prefix }} + {% for author in page.authors %} + <a href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a> + {% endfor %} + {{ l[lang].page.authors_suffix }} + </address> + {%- endif -%} + + <span>{{ l[lang].page.published_prefix }} + <abbr title="{{ page.date.isoformat() }}"> + {{ page.locale_date }} + </abbr>{{ l[lang].page.published_suffix }}</span> + + {%- if page.modified -%} + <br /> + <span>{{ l[lang].page.modified_prefix }} + <abbr title="{{ page.modified.isoformat() }}">{{ page.locale_modified }}</abbr> + {{ l[lang].page.modified_suffix }}</span> + {%- endif -%} + + <br /> + <span>{{ l[lang].page.category_prefix }}<a href="{{ SITEURL }}/{{ page.category.url }}">{{ page.category }}</a>{{ l[lang].page.category_suffix }}</span> + <br /> + <span>{{ l[lang].page.languages_prefix }}</span> + <ul class="languages"> + {%- for translation in page.translations -%} + <li> + {{ page_translation_link(translation) }} + </li> + {%- endfor -%} + <li> + {{ page_translation_link(page, True) }} + </li> + </ul> + {{ l[lang].page.languages_suffix }} + </footer> + </article> +{% endblock %} diff --git a/theme/old-templates/tag.html b/theme/old-templates/tag.html new file mode 100644 index 0000000000000000000000000000000000000000..6a636023257c22e38fb88b74bb4d631af4718362 --- /dev/null +++ b/theme/old-templates/tag.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block title %}{{ l[lang].title_prefix }}{{ l[lang].sitename }}{{ l[lang].title_suffix }} - {{ tag }}{%endblock%} +{% block content %} + <section> + {{ render.section({"type": "tag", "tag": tag.slug, "num": None}) }} + </section> +{% endblock content %} diff --git a/theme/templates/base.html b/theme/templates/base.html index 8a346355e90b1416b3231d6471c7890cf684ffc1..b798077b55fe0fcfad98567359fb547ebcef5f63 100644 --- a/theme/templates/base.html +++ b/theme/templates/base.html @@ -3,6 +3,7 @@ {%- import 'macros/getters.html' as get with context -%} {%- import 'macros/cards.html' as cards with context -%} {%- import 'macros/renderers.html' as render with context -%} +{%- import 'macros/content_renderer.html' as content_renderer with context -%} <html lang="{%- block html_lang -%}{{ l }}{%- endblock html_lang -%}"> <head> @@ -14,6 +15,7 @@ <!-- <meta HTTP-EQUIV="REFRESH" content="500; url=#"> --> <link rel="preload" href="{{ siteurl }}/{{ theme.static_dir }}/css/{{ theme.css_file }}" as="style" /> <link rel="stylesheet" type="text/css" href="{{ siteurl }}/{{ theme.static_dir }}/css/{{ theme.css_file }}" /> + <script src="{{ siteurl }}/mathjax/tex-chtml.js" id="MathJax-script" async></script> {#- TODO load javascript? -#} {#- TODO og: meta tags -#} {#- TODO favicon -#} diff --git a/theme/templates/macros/README.md b/theme/templates/macros/README.md new file mode 100644 index 0000000000000000000000000000000000000000..75ed3122989219278ca7cac37db4a07f01cc2e7a --- /dev/null +++ b/theme/templates/macros/README.md @@ -0,0 +1,184 @@ +# Macros + +[TOC] + +## [getters.html](getters.html) + +``` +{%- import 'macros/getters.html' as get with context -%} +``` + +Mit diesen Macros können Informationen abgefragt werden. + +### `category_by_name(catname, ignore_native = False)` + +**Argumente:** + +- `catname` (String): Der Name der Kategorie. +- `ignore_native` (Boolean): Setzt den ersten und dritten Rückgabewert zu `None`. (Verkürzt die Laufzeit dieser Funktion.) + +**Rückgabewerte:** + +1. ([Category](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#object-author-cat-tag)): Die native Kategorie. +2. (Dict): Der Eintrag zu der Kategorie aus der config.json-Datei aus dem Inhaltsrepo. +3. (List\<[Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article)\>): Die Artikel in der Kategorie. + +**Beispiel Aufruf:** + +``` +{%- call(nativecat, sccat, catarticles) get.category_by_name(article.category.name) -%} + <ul> + <li>Kategorie: {{ nativecat.name }}</li> + <li>Farbe: {{ sccat.color }}</li> + <li>Anzahl Artikel: {{ catarticles|length }}</li> + </ul> +{%- endcall -%} +``` + +### `tag_by_name(tagname)` + +**Argumente:** + +- `catname` (String): Der Name des Tags. + +**Rückgabewerte:** + +1. ([Tag](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#object-author-cat-tag)): Der native Tag. +2. (Dict): Falls der Tag gleichnamig zu einer Kategorie ist, dann der Eintrag zu der Kategorie aus der config.json-Datei aus dem Inhaltsrepo, sonst `None`. +3. (List\<[Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article)\>): Die Artikel die diesen Tag haben. + +**Beispiel Aufruf:** + +``` +{%- call(nativetag, sccat, tagarticles) get.tag_by_name("event") -%} + <ul> + <li>Tag: {{ nativetag.name }}</li> + <li>Farbe: {% if sccat %}{{ sccat.color }}{% else %}Dieser Tag ist nicht gleichnamig zu einer Kategorie und hat deshalb keine Farbe.{% endif %}</li> + <li>Anzahl Artikel mit diesem Tag: {{ tagarticles|length }}</li> + </ul> +{%- endcall -%} +``` + + +### `article_by_slug(slug, lang)` + +**Argumente:** + +- `slug` (String): Der Slug von dem Artikel. +- `lang` (String): Die Sprache von dem Artikel. + +**Rückgabewerte:** + +1. ([Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article)): Der Artikel. + +### `page_by_slug(slug, lang)` + +**Argumente:** + +- `slug` (String): Der Slug von der Seite. +- `lang` (String): Die Sprache von der Seite. + +**Rückgabewerte:** + +1. ([Page](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#page)): Die Seite. + +### `article_or_page_by_slug(slug, lang)` + +**Argumente:** + +- `slug` (String): Der Slug von dem Artikel oder der Seite. +- `lang` (String): Die Sprache von dem Artikel oder der Seite. + +**Rückgabewerte:** + +1. ([Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article) | [Page](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#page)): Der Artikel oder die Seite. +2. (String): "article" falls es ein Artikel ist. "page" falls es eine Seite ist. + +## [cards.html](cards.html) + +``` +{%- import 'macros/cards.html' as cards with context -%} +``` + +Mit diesen Macros können Kachelblöcke erstellt werden. + +In einem Kachelblock dürfen nur Kacheln sein und sonst nichts! + +**Beispiel:** + +``` +{{ cards.open() }} + +{%- for article in all_articles -%} + {{ cards.card_from_article_or_page(article) }} +{%- endfor -%} + +{{ cards.card(title="Dies ist auch eine Kachel", url="https://www.youtube.com/watch?v=dQw4w9WgXcQ", catcolor="green") }} + +{{ cards.close() }} +``` + +### `open(id = None, classes = None)` + +Beginnt einen Kachelblock. + +**Argumente:** + +- `id` (String): Die ID von dem Kachelblock. +- `classes` (List\<String\>): Zusätzliche Klassen für den Kachelblock. + +### `close()` + +Schließt einen Kachelblock. + +### `card(title, url, catcolor, escape_title = True, is_url_external = True)` + +Erstellt eine Kachel. + +**Argumente:** + +- `title` (String): Der Titel. +- `url` (String): Der URL. +- `catcolor` (String): Die Farbe. +- `escape_title` (Boolean): Ob `title` escaped werden soll. +- `is_url_external` (Boolean): Ob `url` auf eine externe Resource zeigt, oder als relativen Link interpretiert werden soll. + +### `card_from_article_or_page(aop)` + +Erstellt eine Kachel von einem Artikel oder einer Seite. + +**Argumente:** + +1. `aop` ([Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article) | [Page](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#page)): Der Artikel oder die Seite. + + +### `cards_from_articles_or_pages(asops, max = None, standalone = True)` + +Erstellt mehrere Kacheln oder einen vollständigen Kachelblock von mehreren Artikeln oder Seiten. + +**Argumente:** + +1. `asops` (List\<[Article](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#article) | [Page](https://gaumi-fginfo.pages.gwdg.de/pelican/_build/html/themes.html#page)\>): Die Artikel oder Seiten. Kann auch gemischt sein. +2. `max` (Int | None): Falls vorhanden werden maximal `max` Kacheln gerendert. +3. `standalone` (Boolean): Ob `open()` und `close()` automatisch mit ausgeführt werden soll. + +**Beispiel Aufruf:** + +``` +{{ cards_from_articles_or_pages(all_articles, max=5) }} +``` + +## [renderers.html](renderers.html) + +``` +{%- import 'macros/renderers.html' as render with context -%} +``` + +**TODO: ** Die Dokumentation für diese Macros ist abhängig von der Dokumentation von der config.json-Datei im Inhaltsrepo. + +### `section_news(s)` +### `section_custom(s)` +### `section_iframe(s)` +### `section_category(s)` +### `section_tag(s)` +### `section(s)` diff --git a/theme/templates/macros/cards.html b/theme/templates/macros/cards.html index 2360ed07469635ba2ecd8c8afb39b029938caa0a..13f78d5c954d54c4a04c8847fb419da4fac7dfc1 100644 --- a/theme/templates/macros/cards.html +++ b/theme/templates/macros/cards.html @@ -10,7 +10,7 @@ {%- endmacro -%} {%- macro card(title, url, catcolor, is_url_external = True) -%} - <li style="--category-color: {{ catcolor }}"><a href="{% if not is_url_external %}{{ SITEURL }}/{% endif %}{{ url }}">{{ title|e }}</a></li> + <li style="--category-color: {{ catcolor }}"><a href="{% if not is_url_external %}{{ siteurl }}/{% endif %}{{ url }}">{{ title|e }}</a></li> {%- endmacro -%} {%- macro card_from_page(page, lang) -%} diff --git a/theme/templates/macros/content_renderer.html b/theme/templates/macros/content_renderer.html new file mode 100644 index 0000000000000000000000000000000000000000..610e05f96bdbda1872189542e470edf2a7d15e48 --- /dev/null +++ b/theme/templates/macros/content_renderer.html @@ -0,0 +1,346 @@ + +{#- Siehe https://gitlab.gwdg.de/GAUMI-fginfo/fg-website/-/blob/better-content-renderer/docs/content.md -#} + +{%- macro render_content(content, lang) -%} + {{ render_blocks(content, lang) }} +{%- endmacro -%} + +{%- macro render_attr_extra(key, value, lang) %} + {%- if value != None -%} + {%- if value is mapping and value['value'] != None -%} + {%- if value['escape'] %} {{ key }}="{{ value['value']|e }}" + {%- else %} {{ key }}="{{ value['value'] }}" + {%- endif -%} + {%- elif value is string %} {{ key }}="{{ value }}" + {%- endif -%} + {%- endif -%} +{%- endmacro -%} + +{%- macro render_attr(attr, lang, extra_classes = [], extra = {}) -%} + {%- set id = attr['id']|d("") -%} + {%- set classes = attr['classes']|d([]) + extra_classes -%} + {%- set attr_extra = attr['extra']|d({}) -%} + + {%- if id %} id="{{ id }}"{%- endif -%} + {%- if classes|length > 0 %} class="{{ classes|join(' ') }}"{%- endif -%} + {%- for key, value in attr_extra.items() -%} + {%- if key not in extra -%} + {{ render_attr_extra(key, value, lang) }} + {%- endif -%} + {%- endfor -%} + {%- for key, value in extra.items() -%} + {{ render_attr_extra(key, value, lang) }} + {%- endfor -%} +{%- endmacro -%} + +{%- macro render_orderedlist_type(style, delim) -%} + {#- TODO also use delim: default | period | one_parenthesis | two_parentheses -#} + {%- if style == "default" -%}1 + {%- elif style == "lower_alpha" -%}a + {%- elif style == "upper_alpha" -%}A + {%- elif style == "lower_roman" -%}i + {%- elif style == "upper_roman" -%}I + {%- elif style == "example" -%}1 + {%- else -%}1 + {%- endif -%} +{%- endmacro -%} + +{%- macro render_link(url, content, lang, attr = None, title = None) -%} + <a {{ render_attr(attr, lang, extra={"href": url, "title": {"value":title, "escape": true}}) }}> + {%- if content is string -%} + {{ content|e }} + {%- else -%} + {{ render_blocks_or_inlines(content, lang) }} + {%- endif -%} + </a> +{%- endmacro -%} + +{%- macro render_image(url, alt, lang, attr = None, title = None) -%} + <img {{ render_attr(attr, lang, extra={"src": url, "title": {"value":title, "escape": true}}) }} alt=" + {%- if alt is string -%} + {{ alt|e }} + {%- else -%} + {{ render_inlines(alt, lang) }} + {%- endif -%} + "> +{%- endmacro -%} + +{%- macro render_blocks_or_inlines(bsois, lang) -%} + {%- for boi in bsois -%} + {{ render_block_or_inline(boi, lang) }} + {%- endfor -%} +{%- endmacro -%} + +{%- macro render_block_or_inline(boi, lang) -%} + {%- set eclass = boi['class'] -%} + {%- if eclass == "block" -%} + {{ render_block(boi,lang) }} + {%- elif eclass == "inline" -%} + {{ render_inline(boi,lang) }} + {%- else -%} + <br><strong>ERROR: Cannot render block or inline: '{{ boi|e }}'</strong><br> + {%- endif -%} +{%- endmacro -%} + +{#- ############################ BLOCKS ################################### -#} + +{%- macro render_blocks(blocks, lang) -%} + {%- for block in blocks -%} + {{ render_block(block,lang) }} + {%- endfor -%} +{%- endmacro -%} + +{%- macro render_block(block, lang) -%} + {%- set etype = block['type'] -%} + {%- if etype == "header" -%} + {{ render_block_header(block, lang) }} + {%- elif etype == "paragraph" -%} + {{ render_block_paragraph(block, lang) }} + {%- elif etype == "bulletlist" -%} + {{ render_block_bulletlist(block, lang) }} + {%- elif etype == "plain" -%} + {{ render_block_plain(block, lang) }} + {%- elif etype == "codeblock" -%} + {{ render_block_codeblock(block, lang) }} + {%- elif etype == "blockquote" -%} + {{ render_block_blockquote(block, lang) }} + {%- elif etype == "blockcontainer" -%} + {{ render_block_blockcontainer(block, lang) }} + {%- elif etype == "horizontalrule" -%} + {{ render_block_horizontalrule(block, lang) }} + {%- elif etype == "rawblock" -%} + {{ render_block_rawblock(block, lang) }} + {%- elif etype == "orderedlist" -%} + {{ render_block_orderedlist(block, lang) }} + {%- else -%} + <br><strong>ERROR: Unhandled block type: '{{ etype|e }}'</strong><br> + {%- endif -%} +{%- endmacro -%} + +{%- macro render_block_header(block, lang) -%} + {%- set level = block['level'] -%} + {%- set attr = block['attr'] -%} + {%- set content = block['content'] -%} + <header {{ render_attr(attr, lang) }}> + <h{{ level }}> + {{ render_inlines(content, lang) }} + </h{{ level }}> + </header> +{%- endmacro -%} + +{%- macro render_block_paragraph(block, lang) -%} + {%- set content = block['content'] -%} + <p> + {{ render_inlines(content, lang) }} + </p> +{%- endmacro -%} + +{%- macro render_block_bulletlist(block, lang) -%} + {%- set items = block['items'] -%} + {%- set count = block['count'] -%} + <ul> + {%- for item in items -%} + <li>{{ render_blocks(item, lang) }}</li> + {%- endfor -%} + </ul> +{%- endmacro -%} + +{%- macro render_block_plain(block, lang) -%} + {%- set content = block['content'] -%} + {{ render_inlines(content, lang) }} +{%- endmacro -%} + +{%- macro render_block_codeblock(block, lang) -%} + {%- set attr = block['attr'] -%} + {%- set code = block['code'] -%} + {%- set code_lines = block['code_lines'] -%} + <pre {{ render_attr(attr, lang, extra_classes=["codeblock"]) }}>{{ code|e }}</pre> +{%- endmacro -%} + +{%- macro render_block_blockquote(block, lang) -%} + {%- set content = block['content'] -%} + <blockquote> + {{ render_blocks(content, lang) }} + </blockquote> +{%- endmacro -%} + +{%- macro render_block_blockcontainer(block, lang) -%} + {%- set attr = block['attr'] -%} + {%- set content = block['content'] -%} + <div {{ render_attr(attr, lang) }}> + {{ render_blocks(content, lang) }} + </div> +{%- endmacro -%} + +{%- macro render_block_horizontalrule(block, lang) -%} + <hr> +{%- endmacro -%} + +{%- macro render_block_rawblock(block, lang) -%} + {%- set format = block['format'] -%} + {%- set raw = block['raw'] -%} + {%- if format == "html" -%} + <div class="rawblock {{ format|e }}"> + {{ raw }} + </div> + {%- else -%} + <div class="rawblock {{ format|e }}">{{ raw | e }}</div> + {%- endif -%} +{%- endmacro -%} + +{%- macro render_block_orderedlist(block, lang) -%} + {%- set items = block['items'] -%} + {%- set count = block['count'] -%} + {%- set start = block['start'] -%} + {%- set style = block['style'] -%} + {%- set delim = block['delim'] -%} + {#- ol start="{{ start|e }}" style="list-style-type: {{ render_orderedlist_type(style, delim) }};" -#} + <ol start="{{ start|e }}" type="{{ render_orderedlist_type(style, delim) }}"> + {%- for item in items -%} + <li>{{ render_blocks(item, lang) }}</li> + {%- endfor -%} + </ol> +{%- endmacro -%} + + +{#- ############################ INLINES ################################## -#} + +{%- macro render_inlines(inlines, lang) -%} + {%- for inline in inlines -%} + {{ render_inline(inline,lang) }} + {%- endfor -%} +{%- endmacro -%} + +{%- macro render_inline(inline, lang) -%} + {%- set etype = inline['type'] -%} + {%- if etype == "space" -%} + {{ render_inline_space(inline, lang) }} + {%- elif etype == "string" -%} + {{ render_inline_string(inline, lang) }} + {%- elif etype == "linebreak" -%} + {{ render_inline_linebreak(inline, lang) }} + {%- elif etype == "strong" -%}{{ render_inline_simple(inline, lang, "b") }} + {%- elif etype == "emph" -%}{{ render_inline_simple(inline, lang, "i") }} + {%- elif etype == "strikeout" -%}{{ render_inline_simple(inline, lang, "s") }} + {%- elif etype == "superscript" -%}{{ render_inline_simple(inline, lang, "sup") }} + {%- elif etype == "subscript" -%}{{ render_inline_simple(inline, lang, "sub") }} + {%- elif etype == "underline" -%}{{ render_inline_underline(inline, lang) }} + {%- elif etype == "smallcaps" -%}{{ render_inline_smallcaps(inline, lang) }} + {%- elif etype == "inlinecontainer" -%} + {{ render_inline_inlinecontainer(inline, lang) }} + {%- elif etype == "rawinline" -%} + {{ render_inline_rawinline(inline, lang) }} + {%- elif etype == "code" -%} + {{ render_inline_code(inline, lang) }} + {%- elif etype == "quoted" -%} + {{ render_inline_quoted(inline, lang) }} + {%- elif etype == "footnote" -%} + {{ render_inline_footnote(inline, lang) }} + {%- elif etype == "link" -%} + {{ render_inline_link(inline, lang) }} + {%- elif etype == "image" -%} + {{ render_inline_image(inline, lang) }} + {%- elif etype == "math" -%} + {{ render_inline_math(inline, lang) }} + {%- else -%} + <br><strong>ERROR: Unhandled inline type: '{{ etype|e }}'</strong><br> + {%- endif -%} +{%- endmacro -%} + +{%- macro render_inline_space(inline, lang) %} {% endmacro -%} + +{%- macro render_inline_string(inline, lang) -%} + {%- set text = inline['text'] -%} + {{ text|e }} +{%- endmacro -%} + +{%- macro render_inline_linebreak(inline, lang) -%} + <br> +{%- endmacro -%} + +{%- macro render_inline_simple(inline, lang, tag) -%} + {%- set content = inline['content'] -%} + <{{ tag }}>{{ render_inlines(content, lang) }}</{{ tag }}> +{%- endmacro -%} + +{%- macro render_inline_underline(inline, lang) -%} + {%- set content = inline['content'] -%} + <span class="underline">{{ render_inlines(content, lang) }}</span> +{%- endmacro -%} + +{%- macro render_inline_smallcaps(inline, lang) -%} + {%- set content = inline['content'] -%} + <span class="smallcaps">{{ render_inlines(content, lang) }}</span> +{%- endmacro -%} + +{%- macro render_inline_inlinecontainer(inline, lang) -%} + {%- set attr = inline['attr'] -%} + {%- set content = inline['content'] -%} + <span {{ render_attr(attr, lang) }}> + {{ render_inlines(content, lang) }} + </span> +{%- endmacro -%} + +{%- macro render_inline_rawinline(inline, lang) -%} + {%- set format = inline['format'] -%} + {%- set raw = inline['raw'] -%} + {%- if format == "html" -%} + <span class="rawinline {{ format|e }}"> + {{ raw }} + </span> + {%- else -%} + <span class="rawinline {{ format|e }}">{{ raw | e }}</span> + {%- endif -%} +{%- endmacro -%} + +{%- macro render_inline_code(inline, lang) -%} + {%- set attr = inline['attr'] -%} + {%- set code = inline['code'] -%} + {%- set code_lines = inline['code_lines'] -%} + <code {{ render_attr(attr, lang, extra_classes=["codeinline"]) }}>{{ code|e }}</code> +{%- endmacro -%} + +{%- macro render_inline_quoted(inline, lang) -%} + {%- set quotetype = inline['quotetype'] -%} + {%- set content = inline['content'] -%} + {%- if quotetype == "single" -%} + {{ t[lang].quotations.single.left }}{{ render_inlines(content, lang) }}{{ t[lang].quotations.single.right }} + {%- elif quotetype == "double" -%} + {{ t[lang].quotations.double.left }}{{ render_inlines(content, lang) }}{{ t[lang].quotations.double.right }} + {%- else -%} + "{{ render_inlines(content, lang) }}" + {%- endif -%} +{%- endmacro -%} + +{%- macro render_inline_footnote(inline, lang) -%} + {%- set content = inline['content'] -%} + <sup>[TODO FOOTNOTES]</sup> +{%- endmacro -%} + +{%- macro render_inline_link(inline, lang) -%} + {%- set attr = inline['attr'] -%} + {%- set content = inline['content'] -%} + {%- set url = inline['url'] -%} + {%- set title = inline['title'] -%} + {{ render_link(url, content, lang, attr, title) }} +{%- endmacro -%} + +{%- macro render_inline_image(inline, lang) -%} + {%- set attr = inline['attr'] -%} + {%- set alt = inline['alt'] -%} + {%- set url = inline['url'] -%} + {%- set title = inline['title'] -%} + {{ render_image(url, alt, lang, attr, title) }} +{%- endmacro -%} + +{%- macro render_inline_math(inline, lang) -%} + {%- set mathtype = inline['mathtype'] -%} + {%- set math = inline['math'] -%} + {%- if mathtype == "inline" -%} + <span class="math inline">\({{ math|e }}\)</span> + {%- elif mathtype == "display" -%} + <span class="math display">\[{{ math|e }}\]</span> + {%- else -%} + <br><strong>ERROR: Unhandled mathtype: '{{ mathtype|e }}'</strong><br> + {%- endif -%} +{%- endmacro -%} diff --git a/theme/templates/macros/renderers.html b/theme/templates/macros/renderers.html index 56351467715cfd0882aceb9394b91c9f9936dc82..ea366c2b6072efb80d2262eeecd331ea3cf0d74b 100644 --- a/theme/templates/macros/renderers.html +++ b/theme/templates/macros/renderers.html @@ -1,5 +1,6 @@ {%- import 'macros/getters.html' as get with context -%} {%- import 'macros/cards.html' as cards with context -%} +{%- import 'macros/content_renderer.html' as content_renderer with context -%} {%- macro section_news(s, lang) -%} {{ cards.cards_from_pages(pages_modified, max=s.num) }} @@ -27,7 +28,7 @@ {{ cards.cards_from_pages(tagpages, lang, max=s.num) }} {%- if tagpage -%} - {{ tagpage.content }} + {{ content_renderer.render_content(tagpage.content, lang) }} {%- endif -%} {%- endcall -%} {%- endmacro -%} diff --git a/theme/templates/page.html b/theme/templates/page.html index fdbef287039e822a368a5f6e0702340bd424aaaa..1ddee6adc5b961adf0e97c276f0b6b18ac2e5978 100644 --- a/theme/templates/page.html +++ b/theme/templates/page.html @@ -28,7 +28,7 @@ {%- call(s) get.metadata_entry(page.slug, l, 'before') -%} {{ render.sections(s, l) }} {%- endcall -%} - {{ page.content }} + {{ content_renderer.render_content(page.content, l) }} {%- call(s) get.metadata_entry(page.slug, l, 'after') -%} {{ render.sections(s, l) }} {%- endcall -%}