From 8a90bca75c8d8755016b46747ca943bb7b37140c Mon Sep 17 00:00:00 2001 From: Saya Andy Date: Sat, 1 Aug 2026 13:15:38 +0700 Subject: logo: include svg variant for both favicon and logo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reasoning behind using svg as primary defaults is simple – at close-up it is much neater, plus svg favicon is supported since 2015 in Firefox, 2020 in Chromium, 2025 in Safari. For old browsers ico is still kept as a fallback. The svg was auto-generated using a Python script and then simplified to a path, but kept close to an original. --- ui-shared.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 5 deletions(-) (limited to 'ui-shared.c') diff --git a/ui-shared.c b/ui-shared.c index 97d1839..686fde0 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -7,6 +7,8 @@ * Implement ci link tab * Check repo existence * Replace memrchr() for macOS compatibility + * Allow multiple favicons of different mime types to be used + * Include favicon.svg as default * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -774,6 +776,51 @@ void cgit_redirect(const char *url, bool permanent) html("\n\n"); } +static const struct { + const char *ext; + const char *mimetype; +} favicon_mimetypes[] = { + { "ico", "image/x-icon" }, + { "png", "image/png" }, + { "svg", "image/svg+xml" }, + { "gif", "image/gif" }, + { "jpg", "image/jpeg" }, + { "jpeg", "image/jpeg" }, + { "webp", "image/webp" }, + { "avif", "image/avif" }, +}; + +/* Deduce the mimetype of a favicon from the extension of its url, ignoring + * any query string or fragment. Returns NULL for unknown extensions. + */ +static const char *favicon_mimetype(const char *url) +{ + const char *p, *end, *ext = NULL; + size_t len; + int i; + + end = strpbrk(url, "?#"); + if (!end) + end = url + strlen(url); + + for (p = url; p < end; p++) { + if (*p == '/') + ext = NULL; + else if (*p == '.') + ext = p + 1; + } + if (!ext) + return NULL; + len = end - ext; + + for (i = 0; i < ARRAY_SIZE(favicon_mimetypes); i++) { + if (strlen(favicon_mimetypes[i].ext) == len && + !strncasecmp(favicon_mimetypes[i].ext, ext, len)) + return favicon_mimetypes[i].mimetype; + } + return NULL; +} + static void print_rel_vcs_link(const char *url) { html("\n"); + + return 0; +} + void cgit_print_docstart(void) { char *host = cgit_hosturl(); @@ -845,11 +913,12 @@ void cgit_print_docstart(void) else emit_js_link(NULL, "/cgit.js"); - if (ctx.cfg.favicon && *ctx.cfg.favicon) { - html("\n"); - } + if (ctx.cfg.favicon.items) + for_each_string_list(&ctx.cfg.favicon, emit_favicon_link, NULL); + else + emit_favicon_link(NULL, "/favicon.svg"); + emit_favicon_link(NULL, "/favicon.ico"); + if (host && ctx.repo && ctx.qry.head) { char *fileurl; struct strbuf sb = STRBUF_INIT; -- cgit v1.3.1+13