summaryrefslogtreecommitdiff
path: root/parser.py
diff options
context:
space:
mode:
Diffstat (limited to 'parser.py')
-rwxr-xr-xparser.py166
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()