From 96d0c238d68b147540085bc1e13f9f15fc444258 Mon Sep 17 00:00:00 2001 From: Peter Molnar Date: Thu, 2 Aug 2018 22:47:49 +0100 Subject: [PATCH] Back on prismjs for syntax highlighting. While Pandoc was generating something sane, the output of CodeHilite puts silly amount of extra text and makes the HTML output completely unreadable. In the end, it still looks like prism.js is a nice and solid solution, even if it's JS. I'll explore other options, but so far, it's either back to Pandoc, or sticking with Prism. --- html5_fenced_code.py | 57 ++++ nasg.py | 38 ++- run | 2 +- templates/base.j2.html | 205 +++++++------- templates/prism.css | 73 +++++ templates/prism.js | 26 ++ templates/style-alt.css | 29 ++ templates/style-dark.css | 583 -------------------------------------- templates/style-light.css | 115 -------- templates/style-print.css | 151 ++-------- templates/style.css | 337 ++++++++++++++++++++++ 11 files changed, 689 insertions(+), 927 deletions(-) create mode 100644 html5_fenced_code.py create mode 100644 templates/prism.css create mode 100644 templates/prism.js create mode 100644 templates/style-alt.css delete mode 100644 templates/style-dark.css delete mode 100644 templates/style-light.css create mode 100644 templates/style.css diff --git a/html5_fenced_code.py b/html5_fenced_code.py new file mode 100644 index 0000000..41ae561 --- /dev/null +++ b/html5_fenced_code.py @@ -0,0 +1,57 @@ +""" +This is a simplified FencedBlockPreprocessor which outputs "proper" +naming, eg. language-python, instead of just python, so prism.js understands +it. + +It doesn't deal with CodeHilite. + +""" + +from markdown.preprocessors import Preprocessor +from markdown.extensions import Extension +from markdown.extensions.fenced_code import FencedBlockPreprocessor + +class HTML5FencedBlockPreprocessor(Preprocessor): + FENCED_BLOCK_RE = FencedBlockPreprocessor.FENCED_BLOCK_RE + CODE_WRAP = '
%s
' + LANG_TAG = ' class="language-%s"' + + def __init__(self, md): + super(HTML5FencedBlockPreprocessor, self).__init__(md) + + def run(self, lines): + text = "\n".join(lines) + while 1: + m = self.FENCED_BLOCK_RE.search(text) + if m: + lang = '' + if m.group('lang'): + lang = self.LANG_TAG % (m.group('lang')) + + code = self.CODE_WRAP % ( + lang, + m.group('code') + ) + + placeholder = self.markdown.htmlStash.store(code) + text = '%s\n%s\n%s' % ( + text[:m.start()], + placeholder, + text[m.end():] + ) + else: + break + return text.split("\n") + + +class HTML5FencedCodeExtension(Extension): + def extendMarkdown(self, md, md_globals): + md.registerExtension(self) + md.preprocessors.add( + 'html5_fenced_code', + HTML5FencedBlockPreprocessor(md), + ">normalize_whitespace" + ) + +def makeExtension(*args, **kwargs): + return HTML5FencedCodeExtension(*args, **kwargs) diff --git a/nasg.py b/nasg.py index d2cb04e..04973af 100644 --- a/nasg.py +++ b/nasg.py @@ -35,6 +35,7 @@ import requests import exiftool import settings import keys +import html5_fenced_code from pprint import pprint @@ -63,13 +64,21 @@ RE_HTTP = re.compile( MD = markdown.Markdown( output_format='xhtml5', extensions=[ - 'extra', - 'codehilite', + 'html5_fenced_code', + 'abbr', + 'attr_list', + 'def_list', + 'footnotes', + 'tables', + 'smart_strong', 'headerid', - 'urlize' - ], + 'urlize', + ] ) +RE_CODE = re.compile( + r'(?:[~`]{3})(?:[^`]+)?' +) class MarkdownDoc(object): @property @@ -412,6 +421,13 @@ class Singular(MarkdownDoc): r[t][mtime] = c.tmplvars return r + @property + def has_code(self): + if RE_CODE.search(self.content): + return True + else: + return False + @property @cached() def tmplvars(self): @@ -433,6 +449,7 @@ class Singular(MarkdownDoc): 'syndicate': self.syndicate, 'url': self.url, 'review': self.meta.get('review', False), + 'has_code': self.has_code, } if (self.enclosure): v.update({'enclosure': self.enclosure}) @@ -521,8 +538,8 @@ class WebImage(object): return self.mdimg.match tmpl = J2.get_template("%s.j2.html" % (self.__class__.__name__)) return tmpl.render({ - 'src': self.displayed.relpath, - 'href': self.linked.relpath, + 'src': self.src, + 'href': self.href, 'width': self.displayed.width, 'height': self.displayed.height, 'title': self.title, @@ -1315,7 +1332,14 @@ def make(): logging.info('worker finished') # copy static - for e in glob.glob(os.path.join(content, '*.*')): + staticfiles = [] + staticpaths = [ + os.path.join(content, '*.*'), + os.path.join(settings.paths.get('tmpl'), '*.js') + ] + for p in staticpaths: + staticfiles = staticfiles + glob.glob(p) + for e in staticfiles: t = os.path.join( settings.paths.get('build'), os.path.basename(e) diff --git a/run b/run index e2d1678..acccff7 100755 --- a/run +++ b/run @@ -5,4 +5,4 @@ IFS=$'\n\t' source ./.venv/bin/activate python3 nasg.py "$@" -rsync -avu --delete-after ../www/ liveserver:/web/petermolnar.net/web/ +rsync -avuhH --delete-after ../www/ liveserver:/web/petermolnar.net/web/ diff --git a/templates/base.j2.html b/templates/base.j2.html index e06bf9b..25917ab 100644 --- a/templates/base.j2.html +++ b/templates/base.j2.html @@ -1,19 +1,19 @@ - {% block title %}{{ post.title }} - petermolnar.net{% endblock %} + {% block title %}{{ post.title }} - {{ site.domain }}{% endblock %} - + {% for key, value in meta.items() %} {% endfor %} {% block meta %}{% endblock %} - + + {% endif %} {% macro activemenu(name) %}{% if (post is defined and post.category == name ) or ( category is defined and category.name == name ) %}active{% endif %}{% endmacro %} -
-