diff options
| author | yuzu-eva <cafebabe@disroot.org> | 2025-03-11 00:20:43 +0100 |
|---|---|---|
| committer | yuzu-eva <cafebabe@disroot.org> | 2025-03-11 00:20:43 +0100 |
| commit | 1d1383ce943cf6b1ddb32b031a9c9a10e29f98fe (patch) | |
| tree | afd3bd4627ecfcfac6e16714eecb6e4516df7485 /parser.py | |
| parent | 85f1c648e09e200a11ae442c8b284b24818f9239 (diff) | |
first iteration of flask-app; index is working
Diffstat (limited to 'parser.py')
| -rwxr-xr-x | parser.py | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/parser.py b/parser.py new file mode 100755 index 0000000..41ff65b --- /dev/null +++ b/parser.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 + +from pygments import highlight +from pygments.lexers import get_lexer_by_name +from pygments.formatters import HtmlFormatter +from urllib.parse import urlparse + +import urllib.parse +import lxml.html +import argparse +import database +import mistune +import houdini +import jinja2 +import parser +import shutil +import sys + +ENV = jinja2.Environment(loader=jinja2.FileSystemLoader('templates')) + +class MyRenderer(mistune.HTMLRenderer): + def block_code(self, code, info=None): + if not info: + return '\n<pre><code>{}</code></pre>\n'.format(houdini.escape_html(code.strip())) + lexer = get_lexer_by_name(info, stripall=True) + formatter = HtmlFormatter() + return highlight(code, lexer, formatter) + + def block_quote(self, content): + content = content[3:-5] + out = '\n<blockquote>' + for line in houdini.escape_html(content.strip()).split("\n"): + out += '\n<span class="quote">{}</span><br>'.format(line) + return out + '\n</blockquote>' + + def image(self, link, text, title): + return "<a href='%s' target='_blank'><img alt='%s' src='%s'></a>" % ( + urlparse(link)._replace(query='').geturl(), text, link + ) + + def heading(self, text, level): + hash_ = urllib.parse.quote_plus(text) + return "<h%d id='%s'>%s <a class='header_linker' href='#%s'>[#]</a></h%d>\n" % ( + level, hash_, text, hash_, level + ) + +def get_thought_from_id(db, id_): + title, datetime, markdown, redirect = db.get_thought(id_) + html, headers = parse_text(markdown) + return title, datetime, html, headers, redirect + +def parse_file(path): + with open(path, "r") as f: + unformatted = f.read() + + return parse_text(unformatted)[0] + +def parse_text(unformatted): + md = mistune.create_markdown( + renderer = MyRenderer(), + plugins = ["strikethrough", "table", "url", "task_lists", "def_list"] + ) + html = md(unformatted) + if html == "": + return "", "" + + return html, get_headers(html) + +def get_headers(html): + root = lxml.html.fromstring(html) + + headers = [] + thesmallestlevel = 7 + for node in root.xpath('//h1|//h2|//h3|//h4|//h5//h6'): + level = int(node.tag[-1]) + if level < thesmallestlevel: + thesmallestlevel = level + headers.append(( + urllib.parse.unquote_plus(node.attrib["id"]), + level, + "#%s" % node.attrib["id"]) + ) + + headers = [(i[0], i[1] - thesmallestlevel, i[2]) for i in headers] + md_template = jinja2.Template(""" + {% for text, depth, link in contents %} + {{ " " * depth }} - [{{ text }}]({{ link }}) + {% endfor %} + """) + + return mistune.html(md_template.render(contents = headers)) + +def main(): + p = argparse.ArgumentParser() + subparse = p.add_subparsers(help = "sub-command help") + save_parser = subparse.add_parser("save", help = "Add a markdown file to the database") + echo_parser = subparse.add_parser("echo", help = "Print markdown render to stdout") + update_parser = subparse.add_parser("update", help = "Replace a markdown file") + export_parser = subparse.add_parser("export", help = "Export a database markdown file to disk") + list_parser = subparse.add_parser("list", help = "List all the markdowns in the database") + + for s in [save_parser, echo_parser, update_parser]: + s.add_argument( + "-m", "--markdown", + help = "Path to a markdown file", + type = str, + required = True + ) + + for s in [save_parser]: + s.add_argument( + "-t", "--title", + help = "Article title", + type = str, + required = True + ) + + for s in [export_parser, update_parser]: + s.add_argument( + "-i", "--id", + help = "Article's id", + type = int, + required = True + ) + + export_parser.add_argument( + "-o", "--out", + help = "Path to write the markdown file to", + type = str, + required = True + ) + + args = vars(p.parse_args()) + + try: + verb = sys.argv[1] + except IndexError: + print("Error! No verb specified. Nothing to do... Exiting...") + exit() + + if verb in ["save", "export", "update", "list"]: + with database.Database() as db: + match verb: + case "save": + with open(args["markdown"], "r") as f: + db.add_thought(args["title"], f.read()) + print("Added thought.") + case "export": + with open(args["out"], "w") as f: + f.writelines(db.get_thought(args["id"])) + print(f"Written to {args["out"]}") + case "update": + with open(args["markdown"], "r") as f: + db.update_thought_markdown(args["id"], f.read()) + print("Updated thought.") + case "list": + for id_, title, datetime in db.get_all_thoughts(): + print(f"{id_}, {title}, {datetime}") + case _: + print("Error! Unknown verb... Exiting...") + exit() + elif verb == "echo": + print(parse_file(args["markdown"])) + +if __name__ == '__main__': + main() |
