diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Render README markdown in the browser
cgit had no markdown support of its own, so a readme was rendered through an external python filter or not at all. Escaping the source and formatting it in cgit.js keeps the work in the browser like the blob highlighter, and the page stays readable as plain text without scripting.
Diffstat (limited to '')
-rw-r--r--source/cgit.c3
-rw-r--r--source/cgit.h1
-rw-r--r--source/ui-blob.c7
-rw-r--r--source/ui-blob.h2
-rw-r--r--source/ui-summary.c48
5 files changed, 49 insertions, 12 deletions
diff --git a/source/cgit.c b/source/cgit.c
index 29b2131..8a7027c 100644
--- a/source/cgit.c
+++ b/source/cgit.c
@@ -201,6 +201,8 @@ static void config_cb(const char *name, const char *value)
ctx.cfg.enable_tree_linenumbers = atoi(value);
else if (!strcmp(name, "enable-tree-group-dirs"))
ctx.cfg.enable_tree_group_dirs = atoi(value);
+ else if (!strcmp(name, "enable-markdown"))
+ ctx.cfg.enable_markdown = atoi(value);
else if (!strcmp(name, "enable-git-config"))
ctx.cfg.enable_git_config = atoi(value);
else if (!strcmp(name, "enable-cache-list"))
@@ -394,6 +396,7 @@ static void prepare_context(void)
ctx.cfg.enable_http_clone = 1;
ctx.cfg.enable_index_owner = 1;
ctx.cfg.enable_tree_linenumbers = 1;
+ ctx.cfg.enable_markdown = 1;
ctx.cfg.enable_git_config = 0;
ctx.cfg.max_repo_count = 50;
ctx.cfg.max_commit_count = 50;
diff --git a/source/cgit.h b/source/cgit.h
index ab7b284..3cd0317 100644
--- a/source/cgit.h
+++ b/source/cgit.h
@@ -243,6 +243,7 @@ struct cgit_config {
int enable_html_serving;
int enable_tree_linenumbers;
int enable_tree_group_dirs;
+ int enable_markdown;
int enable_git_config;
int enable_cache_list;
int local_time;
diff --git a/source/ui-blob.c b/source/ui-blob.c
index bc91656..7720a28 100644
--- a/source/ui-blob.c
+++ b/source/ui-blob.c
@@ -67,7 +67,7 @@ done:
return walk_tree_ctx.found_path;
}
-int cgit_print_file(char *path, const char *head, int file_only)
+int cgit_print_file(char *path, const char *head, int file_only, int html_escape)
{
struct object_id oid;
enum object_type type;
@@ -106,7 +106,10 @@ int cgit_print_file(char *path, const char *head, int file_only)
if (!buf)
return -1;
buf[size] = '\0';
- html_raw(buf, size);
+ if (html_escape)
+ html_txt(buf);
+ else
+ html_raw(buf, size);
free(buf);
return 0;
}
diff --git a/source/ui-blob.h b/source/ui-blob.h
index 16847b2..efbc94e 100644
--- a/source/ui-blob.h
+++ b/source/ui-blob.h
@@ -2,7 +2,7 @@
#define UI_BLOB_H
extern int cgit_ref_path_exists(const char *path, const char *ref, int file_only);
-extern int cgit_print_file(char *path, const char *head, int file_only);
+extern int cgit_print_file(char *path, const char *head, int file_only, int html_escape);
extern void cgit_print_blob(const char *hex, char *path, const char *head, int file_only);
#endif /* UI_BLOB_H */
diff --git a/source/ui-summary.c b/source/ui-summary.c
index 947812a..7e533e1 100644
--- a/source/ui-summary.c
+++ b/source/ui-summary.c
@@ -99,6 +99,17 @@ static char* append_readme_path(const char *filename, const char *ref, const cha
return full_path;
}
+static int readme_is_markdown(const char *filename)
+{
+ const char *ext = strrchr(filename, '.');
+
+ if (!ext || !ext[1])
+ return 0;
+ ext++;
+ return !strcasecmp(ext, "md") || !strcasecmp(ext, "markdown") ||
+ !strcasecmp(ext, "mkd") || !strcasecmp(ext, "mdown");
+}
+
void cgit_print_repo_readme(const char *path)
{
char *filename, *ref, *mimetype;
@@ -128,16 +139,35 @@ void cgit_print_repo_readme(const char *path)
goto done;
}
- /* Print the calculated readme, either from the git repo or from the
- * filesystem, while applying the about-filter.
- */
html("<div id='summary'>");
- cgit_open_filter(ctx.repo->about_filter, filename);
- if (ref)
- cgit_print_file(filename, ref, 1);
- else
- html_include(filename);
- cgit_close_filter(ctx.repo->about_filter);
+ if (!ctx.repo->about_filter && ctx.cfg.enable_markdown &&
+ readme_is_markdown(filename)) {
+ /* No about-filter is set, so hand the markdown source to the
+ * built-in client-side renderer in cgit.js. The source is
+ * escaped here and rendered in the browser, and it degrades to
+ * readable plain text when scripting is off.
+ */
+ html("<div class='markdown' data-markdown>");
+ if (ref) {
+ cgit_print_file(filename, ref, 1, 1);
+ } else {
+ struct strbuf sb = STRBUF_INIT;
+ if (strbuf_read_file(&sb, filename, 0) >= 0)
+ html_txt(sb.buf);
+ strbuf_release(&sb);
+ }
+ html("</div>");
+ } else {
+ /* Otherwise print the readme through the about-filter, or raw
+ * when none is configured.
+ */
+ cgit_open_filter(ctx.repo->about_filter, filename);
+ if (ref)
+ cgit_print_file(filename, ref, 1, 0);
+ else
+ html_include(filename);
+ cgit_close_filter(ctx.repo->about_filter);
+ }
html("</div>");
if (free_filename)