From 39c8cd2ae5eadec313661227055fe6d07246ca4e Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Wed, 15 Jul 2026 11:12:30 -1000 Subject: 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. --- source/ui-summary.c | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'source/ui-summary.c') 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("
"); - 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("
"); + 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("
"); + } 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("
"); if (free_filename) -- cgit v2.8.0