From: John Keeping <j...@keeping.me.uk>

This allows applying filters to files in the repository, for example to
render Markdown or AsciiDoc as HTML.

Signed-off-by: John Keeping <j...@keeping.me.uk>
---
 cgit.css  |    5 +++
 cmd.c     |    4 +-
 ui-tree.c |  105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 ui-tree.h |    2 +
 4 files changed, 107 insertions(+), 9 deletions(-)

diff --git a/cgit.css b/cgit.css
index 217a05a..da8d9b0 100644
--- a/cgit.css
+++ b/cgit.css
@@ -274,6 +274,11 @@ div#cgit div#blob {
        border: solid 1px black;
 }
 
+div#cgit iframe {
+       width: 100%;
+       height: 40em;
+}
+
 div#cgit div.error {
        color: red;
        font-weight: bold;
diff --git a/cmd.c b/cmd.c
index 56e21df..ca48b2f 100644
--- a/cmd.c
+++ b/cmd.c
@@ -140,7 +140,7 @@ static void refs_fn(void)
 
 static void source_fn(void)
 {
-       cgit_print_tree(ctx.qry.sha1, ctx.qry.path);
+       cgit_print_tree(ctx.qry.sha1, ctx.qry.path, false);
 }
 
 static void snapshot_fn(void)
@@ -166,7 +166,7 @@ static void tag_fn(void)
 
 static void tree_fn(void)
 {
-       cgit_print_tree(ctx.qry.sha1, ctx.qry.path);
+       cgit_print_tree(ctx.qry.sha1, ctx.qry.path, true);
 }
 
 #define def_cmd(name, want_repo, want_vpath, is_clone) \
diff --git a/ui-tree.c b/ui-tree.c
index 009e201..723e16e 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -15,6 +15,7 @@ struct walk_tree_context {
        char *curr_rev;
        char *match_path;
        int state;
+       bool use_render;
 };
 
 static void print_text_buffer(const char *name, char *buf, unsigned long size)
@@ -98,10 +99,70 @@ static void print_buffer(const char *basename, char *buf, 
unsigned long size)
                print_text_buffer(basename, buf, size);
 }
 
-static void print_object(const unsigned char *sha1, char *path, const char 
*basename, const char *rev)
+static void render_buffer(struct cgit_filter *render, const char *name,
+               char *buf, unsigned long size)
+{
+       char *filter_arg = xstrdup(name);
+
+       html("<div class='blob'>");
+       cgit_open_filter(render, filter_arg);
+       html_raw(buf, size);
+       cgit_close_filter(render);
+       html("</div>");
+
+       free(filter_arg);
+}
+
+static void include_file(const unsigned char *sha1, const char *path,
+               const char *mimetype)
+{
+       const char *delim = "?";
+
+       html("<div class='blob'>");
+
+       if (!strncmp(mimetype, "image/", 6)) {
+               html("<img alt='");
+               html_attr(path);
+               html("' src='");
+       } else {
+               html("<iframe sandbox='allow-scripts' src='");
+       }
+
+       if (ctx.cfg.virtual_root) {
+               html_url_path(ctx.cfg.virtual_root);
+               html_url_path(ctx.repo->url);
+               if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
+                       html("/");
+               html("plain/");
+               html_url_path(path);
+       } else {
+               html_url_path(ctx.cfg.script_name);
+               html("?url=");
+               html_url_arg(ctx.repo->url);
+               if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
+                       html("/");
+               html("plain/");
+               if (path)
+                       html_url_arg(path);
+               delim = "&";
+       }
+       if (ctx.qry.head && ctx.repo->defbranch &&
+           strcmp(ctx.qry.head, ctx.repo->defbranch)) {
+               html(delim);
+               html("h=");
+               html_url_arg(ctx.qry.head);
+               delim = "&";
+       }
+
+       html("'></div>");
+}
+
+static void print_object(const unsigned char *sha1, char *path, const char 
*basename,
+                        const char *rev, bool use_render)
 {
        enum object_type type;
-       char *buf;
+       struct cgit_filter *render;
+       char *buf, *mimetype;
        unsigned long size;
 
        type = sha1_object_info(sha1, &size);
@@ -118,20 +179,49 @@ static void print_object(const unsigned char *sha1, char 
*path, const char *base
                return;
        }
 
+       render = get_render_for_filename(path);
+       mimetype = render ? NULL : get_mimetype_for_filename(path);
+
        cgit_set_title_from_path(path);
 
+       /*
+        * If we don't have a render filter or a mimetype, we won't include the
+        * file in the page.
+        */
+       if (!render && !mimetype)
+               use_render = false;
+
        cgit_print_layout_start();
        htmlf("blob: %s (", sha1_to_hex(sha1));
        cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
                        rev, path);
+
        if (ctx.cfg.enable_blame) {
                html(") (");
                cgit_blame_link("blame", NULL, NULL, ctx.qry.head,
                                rev, path);
        }
+       if (use_render) {
+               html(", ");
+               cgit_source_link("source", NULL, NULL, ctx.qry.head,
+                               rev, path);
+       } else if (render || mimetype) {
+               html(", ");
+               cgit_tree_link("render", NULL, NULL, ctx.qry.head,
+                              rev, path);
+       }
        html(")\n");
 
-       print_buffer(basename, buf, size);
+       if (use_render) {
+               if (render)
+                       render_buffer(render, basename, buf, size);
+               else
+                       include_file(sha1, path, mimetype);
+       } else {
+               print_buffer(basename, buf, size);
+       }
+
+       free(mimetype);
 }
 
 struct single_tree_ctx {
@@ -323,8 +413,10 @@ 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, pathname, 
walk_tree_ctx->curr_rev,
+                                    walk_tree_ctx->use_render);
                        strbuf_release(&buffer);
+
                        return 0;
                }
        }
@@ -337,7 +429,7 @@ static int walk_tree(const unsigned char *sha1, struct 
strbuf *base,
  *   rev:  the commit pointing at the root tree object
  *   path: path to tree or blob
  */
-void cgit_print_tree(const char *rev, char *path)
+void cgit_print_tree(const char *rev, char *path, bool use_render)
 {
        struct object_id oid;
        struct commit *commit;
@@ -351,7 +443,8 @@ void cgit_print_tree(const char *rev, char *path)
        };
        struct walk_tree_context walk_tree_ctx = {
                .match_path = path,
-               .state = 0
+               .state = 0,
+               .use_render = use_render,
        };
 
        if (!rev)
diff --git a/ui-tree.h b/ui-tree.h
index bbd34e3..a0fc8e2 100644
--- a/ui-tree.h
+++ b/ui-tree.h
@@ -1,6 +1,6 @@
 #ifndef UI_TREE_H
 #define UI_TREE_H
 
-extern void cgit_print_tree(const char *rev, char *path);
+extern void cgit_print_tree(const char *rev, char *path, bool use_render);
 
 #endif /* UI_TREE_H */

_______________________________________________
CGit mailing list
CGit@lists.zx2c4.com
https://lists.zx2c4.com/mailman/listinfo/cgit

Reply via email to