Hey there, First of all, thanks for all the great work on cgit. Awesome stuff!
In my setup, I like to have the markdown files in the repos rendered as HTML instead of having them highlighted as code. Turns out it's fairly easy to achieve using filters. I attach the necessary patches. Feel free to commit if you think they are generally useful. Cheers, Lukasz
From 85974aaa1725ba1d94fe2b2093d9e838864b7804 Mon Sep 17 00:00:00 2001 From: Lukasz Janyst <[email protected]> Date: Thu, 8 Dec 2016 06:06:05 -0800 Subject: [PATCH 1/3] ui-tree: don't assume that a source filter must render code It may be useful to render general HTML instead of just colorized code for formats such as Markdown. Source filters may easily add "<pre><code>" tags themselves. Signed-off-by: Lukasz Janyst <[email protected]> --- ui-tree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-tree.c b/ui-tree.c index b310242..7b9df3a 100644 --- a/ui-tree.c +++ b/ui-tree.c @@ -45,12 +45,12 @@ static void print_text_buffer(const char *name, char *buf, unsigned long size) if (ctx.repo->source_filter) { char *filter_arg = xstrdup(name); - html("<td class='lines'><pre><code>"); + html("<td class='lines'>"); cgit_open_filter(ctx.repo->source_filter, filter_arg); html_raw(buf, size); cgit_close_filter(ctx.repo->source_filter); free(filter_arg); - html("</code></pre></td></tr></table>\n"); + html("</td></tr></table>\n"); return; } -- 2.7.3
From 1cae0fb2aebea80640ba9838c19bab4035530fd1 Mon Sep 17 00:00:00 2001 From: Lukasz Janyst <[email protected]> Date: Thu, 8 Dec 2016 06:16:07 -0800 Subject: [PATCH 2/3] ui-tree: pass full file path to source filters This is useful when rendering files that may reference other files in the repo and need to calculate a link to the 'plain' view. An example of this is Markdown, where:  needs to end up being: <img alt="text" src="../../plain/root/relative/path/image.jpg" /> Filters may easily compute basename themselves. Signed-off-by: Lukasz Janyst <[email protected]> --- ui-tree.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui-tree.c b/ui-tree.c index 7b9df3a..3bdfd26 100644 --- a/ui-tree.c +++ b/ui-tree.c @@ -17,7 +17,7 @@ struct walk_tree_context { int state; }; -static void print_text_buffer(const char *name, char *buf, unsigned long size) +static void print_text_buffer(const char *path, char *buf, unsigned long size) { unsigned long lineno, idx; const char *numberfmt = "<a id='n%1$d' href='#n%1$d'>%1$d</a>\n"; @@ -44,7 +44,7 @@ static void print_text_buffer(const char *name, char *buf, unsigned long size) } if (ctx.repo->source_filter) { - char *filter_arg = xstrdup(name); + char *filter_arg = xstrdup(path); html("<td class='lines'>"); cgit_open_filter(ctx.repo->source_filter, filter_arg); html_raw(buf, size); @@ -115,7 +115,7 @@ static void set_title_from_path(const char *path) ctx.page.title = new_title; } -static void print_object(const unsigned char *sha1, char *path, const char *basename, const char *rev) +static void print_object(const unsigned char *sha1, char *path, const char *rev) { enum object_type type; char *buf; @@ -152,7 +152,7 @@ static void print_object(const unsigned char *sha1, char *path, const char *base if (buffer_is_binary(buf, size)) print_binary_buffer(buf, size); else - print_text_buffer(basename, buf, size); + print_text_buffer(path, buf, size); } struct single_tree_ctx { @@ -341,7 +341,7 @@ static int walk_tree(const unsigned char *sha1, struct strbuf *base, return READ_TREE_RECURSIVE; } else { walk_tree_ctx->state = 2; - print_object(sha1, buffer.buf, pathname, walk_tree_ctx->curr_rev); + print_object(sha1, buffer.buf, walk_tree_ctx->curr_rev); strbuf_release(&buffer); return 0; } -- 2.7.3
From 465b7cad599ac74e50620159722f12c380007c82 Mon Sep 17 00:00:00 2001 From: Lukasz Janyst <[email protected]> Date: Thu, 8 Dec 2016 06:46:49 -0800 Subject: [PATCH 3/3] filters: add source filter highlighting code and rendering markdown The filter uses pygments to highlight code file and misaka to render Markdown ('.md' files) as HTML. The markdown renderer supports image links, highlighting embedded code snippets and math formulas with MathJax. Signed-off-by: Lukasz Janyst <[email protected]> --- filters/syntax-highlighting-with-markdown.py | 143 +++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100755 filters/syntax-highlighting-with-markdown.py diff --git a/filters/syntax-highlighting-with-markdown.py b/filters/syntax-highlighting-with-markdown.py new file mode 100755 index 0000000..e25565c --- /dev/null +++ b/filters/syntax-highlighting-with-markdown.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +#------------------------------------------------------------------------------- +# The filter highlights code and renders '.md' files as html also highlighting +# the embedded code snippets. It assumes that you have python3, pygments and +# misaka installed. +#------------------------------------------------------------------------------- + +import sys +import os +import io +from pygments import highlight +from pygments.util import ClassNotFound +from pygments.lexers import TextLexer +from pygments.lexers import guess_lexer +from pygments.lexers import guess_lexer_for_filename +from pygments.lexers import get_lexer_by_name +from pygments.formatters import HtmlFormatter +import misaka +import html + +#------------------------------------------------------------------------------- +# Globals +#------------------------------------------------------------------------------- +mathjax = 'https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default' +style = 'default' +path = os.path.dirname(sys.argv[1]) +path_comp = len(path.split('/')) +input = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8') +output = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') + +markdown_style = """ +.markdown { + max-width: 800px; +} + +.markdown .highlighted { + border: solid 1px #ccc; + margin: 1em; + padding: 1em; +} + +.markdown blockquote { + margin-left: 1em; + padding-left: 0.5em; + border-left: solid 3px #ccc; +} + +.markdown em { + text-decoration: underline; +} +""" + +extra_highlight_style = """ +.linenodiv pre { + margin: 6px 0px; + color: #aaa; + border-radius: 0; + border: none; + border-right: solid 1px; + word-wrap: normal; +} + +.linenos { + width: 40px; + vertical-align: top; +} +""" + +#------------------------------------------------------------------------------- +def build_plain_link(link): + plain_link = '../' + for i in range(path_comp): + plain_link += '../' + plain_link += 'plain/' + path + '/' + link + return plain_link + +#------------------------------------------------------------------------------- +def highlight_pygments(filename, data): + formatter = HtmlFormatter(linenos='table', lineanchors='l') + + try: + lexer = guess_lexer_for_filename(filename, data) + except ClassNotFound: + # check if there is any shebang + if data[0:2] == '#!': + lexer = guess_lexer(data) + else: + lexer = TextLexer() + except TypeError: + lexer = TextLexer() + + highlight(data, lexer, formatter, outfile=output) + +#------------------------------------------------------------------------------- +class CGitRenderer(misaka.HtmlRenderer): + def blockcode(self, text, lang): + if not lang: + ret = '<div class="highlighted">' + ret += '<pre>%s</pre>' + ret += '</div>' + return ret % (html.escape(text)) + + lexer = get_lexer_by_name(lang, stripall = True) + formatter = HtmlFormatter() + ret = '<div class="highlighted">' + ret += highlight(text, lexer, formatter) + ret += '</div>' + return ret + + def image(self, link, title='', alt=''): + return '<img src="%s" alt="%s"/>' % \ + (build_plain_link(link), alt) + +#------------------------------------------------------------------------------- +def render_markdown(filename, data): + renderer = CGitRenderer() + md = misaka.Markdown(renderer, extensions=('fenced-code', 'math', 'tables')) + output.write('<script type="text/javascript" src="%s"></script>' % (mathjax)) + output.write('<style>') + output.write(markdown_style) + output.write('</style>') + output.write('<div class="markdown">') + output.write(md(data)) + output.write('</div>') + +#------------------------------------------------------------------------------- +def emit_highlight_style(): + formatter = HtmlFormatter(style=style) + + output.write('<style>') + output.write(formatter.get_style_defs('.highlight')) + output.write(formatter.get_style_defs('.highlighttable')) + output.write(extra_highlight_style) + output.write('</style>') + +data = input.read() +filename = sys.argv[1] + +emit_highlight_style() +if filename.split('.')[-1] == 'md': + render_markdown(filename, data) +else: + highlight_pygments(filename, data) -- 2.7.3
_______________________________________________ CGit mailing list [email protected] https://lists.zx2c4.com/mailman/listinfo/cgit
