Diffstat (limited to 'ui-shared.c')
| -rw-r--r-- | ui-shared.c | 205 |
1 files changed, 28 insertions, 177 deletions
diff --git a/ui-shared.c b/ui-shared.c index 686fde0..acd8ab5 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -1,26 +1,15 @@ /* ui-shared.c: common web output functions * * Copyright (C) 2006-2017 cgit Development Team <cgit@lists.zx2c4.com> - * Copyright (C) 2026 Saya Andy <saya.andy@posteo.com> - * - * Modified 2026 by Saya Andy: - * 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) */ -#define USE_THE_REPOSITORY_VARIABLE - #include "cgit.h" #include "ui-shared.h" #include "cmd.h" #include "html.h" -#include "ui-ci.h" #include "version.h" static const char cgit_doctype[] = @@ -351,12 +340,6 @@ void cgit_tag_link(const char *name, const char *title, const char *class, reporevlink("tag", name, title, class, tag, NULL, NULL); } -void cgit_ci_link(const char *name, const char *title, const char *class, - const char *head) -{ - reporevlink("ci", name, title, class, head, NULL, NULL); -} - void cgit_tree_link(const char *name, const char *title, const char *class, const char *head, const char *rev, const char *path) { @@ -679,18 +662,18 @@ void cgit_submodule_link(const char *class, char *path, const char *rev) path[len - 1] = tail; } -const struct date_mode cgit_date_mode(enum date_mode_type type) +const struct date_mode *cgit_date_mode(enum date_mode_type type) { static struct date_mode mode; mode.type = type; mode.local = ctx.cfg.local_time; - return mode; + return &mode; } static void print_rel_date(time_t t, int tz, double value, const char *class, const char *suffix) { - htmlf("<span class='%s' data-ut='%" PRIu64 "' title='", class, (uint64_t)t); + htmlf("<span class='%s' title='", class); html_attr(show_date(t, tz, cgit_date_mode(DATE_ISO8601))); htmlf("'>%.0f %s</span>", value, suffix); } @@ -776,51 +759,6 @@ 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("<link rel='vcs-git' href='"); @@ -830,59 +768,6 @@ static void print_rel_vcs_link(const char *url) html(" Git repository'/>\n"); } -static int emit_css_link(struct string_list_item *s, void *arg) -{ - /* Do not emit anything if css= is specified. */ - if (s && *s->string == '\0') - return 0; - - html("<link rel='stylesheet' type='text/css' href='"); - if (s) - html_attr(s->string); - else - html_attr((const char *)arg); - html("'/>\n"); - - return 0; -} - -static int emit_js_link(struct string_list_item *s, void *arg) -{ - /* Do not emit anything if js= is specified. */ - if (s && *s->string == '\0') - return 0; - - html("<script type='text/javascript' src='"); - if (s) - html_attr(s->string); - else - html_attr((const char *)arg); - html("'></script>\n"); - - return 0; -} - -static int emit_favicon_link(struct string_list_item *s, void *arg) -{ - const char *url = s ? s->string : (const char *)arg; - const char *mimetype; - - /* Do not emit anything if favicon= is specified. */ - if (!*url) - return 0; - - html("<link rel='shortcut icon' href='"); - html_attr(url); - mimetype = favicon_mimetype(url); - if (mimetype) { - html("' type='"); - html_attr(mimetype); - } - html("'/>\n"); - - return 0; -} - void cgit_print_docstart(void) { char *host = cgit_hosturl(); @@ -902,23 +787,14 @@ void cgit_print_docstart(void) htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); if (ctx.cfg.robots && *ctx.cfg.robots) htmlf("<meta name='robots' content='%s'/>\n", ctx.cfg.robots); - - if (ctx.cfg.css.items) - for_each_string_list(&ctx.cfg.css, emit_css_link, NULL); - else - emit_css_link(NULL, "/cgit.css"); - - if (ctx.cfg.js.items) - for_each_string_list(&ctx.cfg.js, emit_js_link, NULL); - else - emit_js_link(NULL, "/cgit.js"); - - 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"); - + html("<link rel='stylesheet' type='text/css' href='"); + html_attr(ctx.cfg.css); + html("'/>\n"); + if (ctx.cfg.favicon) { + html("<link rel='shortcut icon' href='"); + html_attr(ctx.cfg.favicon); + html("'/>\n"); + } if (host && ctx.repo && ctx.qry.head) { char *fileurl; struct strbuf sb = STRBUF_INIT; @@ -959,7 +835,7 @@ void cgit_print_docend(void) if (ctx.cfg.footer) html_include(ctx.cfg.footer); else { - htmlf("<div class='footer'>generated by <a href='https://sayag.it/cgitext.git/about/'>cgitext %s</a> " + htmlf("<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit %s</a> " "(<a href='https://git-scm.com/'>git %s</a>) at ", cgit_version, git_version_string); html_txt(show_date(time(NULL), 0, cgit_date_mode(DATE_ISO8601))); html("</div>\n"); @@ -971,18 +847,13 @@ void cgit_print_docend(void) void cgit_print_error_page(int code, const char *msg, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - cgit_vprint_error_page(code, msg, fmt, ap); - va_end(ap); -} - -void cgit_vprint_error_page(int code, const char *msg, const char *fmt, va_list ap) -{ ctx.page.expires = ctx.cfg.cache_dynamic_ttl; ctx.page.status = code; ctx.page.statusmsg = msg; cgit_print_layout_start(); + va_start(ap, fmt); cgit_vprint_error(fmt, ap); + va_end(ap); cgit_print_layout_end(); } @@ -1023,9 +894,10 @@ void cgit_add_clone_urls(void (*fn)(const char *)) add_clone_urls(fn, ctx.cfg.clone_prefix, ctx.repo->url); } -static int print_branch_option(const struct reference *ref, void *cb_data) +static int print_branch_option(const char *refname, const struct object_id *oid, + int flags, void *cb_data) { - char *name = (char *)ref->name; + char *name = (char *)refname; html_option(name, name, ctx.qry.head); return 0; } @@ -1123,17 +995,15 @@ static void print_header(void) if (ctx.repo) { cgit_index_link("index", NULL, NULL, NULL, NULL, 0, 1); html(" : "); - cgit_summary_link(ctx.repo->name, NULL, NULL, NULL); - if (ctx.env.authenticated && cgit_have_repository()) { + cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL); + if (ctx.env.authenticated) { html("</td><td class='form'>"); html("<form method='get'>\n"); cgit_add_hidden_formfields(0, 1, ctx.qry.page); html("<select name='h' onchange='this.form.submit();'>\n"); - refs_for_each_branch_ref(get_main_ref_store(the_repository), - print_branch_option, ctx.qry.head); + for_each_branch_ref(print_branch_option, ctx.qry.head); if (ctx.repo->enable_remote_branches) - refs_for_each_remote_ref(get_main_ref_store(the_repository), - print_branch_option, ctx.qry.head); + for_each_remote_ref(print_branch_option, ctx.qry.head); html("</select> "); html("<input type='submit' value='switch'/>"); html("</form>"); @@ -1146,13 +1016,7 @@ static void print_header(void) if (ctx.repo) { html_txt(ctx.repo->desc); html("</td><td class='sub right'>"); - if (ctx.repo->owner_filter) { - cgit_open_filter(ctx.repo->owner_filter); - html_txt(ctx.repo->owner); - cgit_close_filter(ctx.repo->owner_filter); - } else { - html_txt(ctx.repo->owner); - } + html_txt(ctx.repo->owner); } else { if (ctx.cfg.root_desc) html_txt(ctx.cfg.root_desc); @@ -1192,8 +1056,6 @@ void cgit_print_pageheader(void) if (ctx.repo->max_stats) cgit_stats_link("stats", NULL, hc("stats"), ctx.qry.head, ctx.qry.vpath); - if (cgit_ci_available()) - cgit_ci_link("ci", NULL, hc("ci"), ctx.qry.head); if (ctx.repo->homepage) { html("<a href='"); html_attr(ctx.repo->homepage); @@ -1242,7 +1104,7 @@ void cgit_print_pageheader(void) html("<div class='path'>"); html("path: "); cgit_print_path_crumbs(ctx.qry.vpath); - if (ctx.repo->enable_follow_links && !strcmp(ctx.qry.page, "log")) { + if (ctx.cfg.enable_follow_links && !strcmp(ctx.qry.page, "log")) { html(" ("); ctx.qry.follow = !ctx.qry.follow; cgit_self_link(ctx.qry.follow ? "follow" : "unfollow", @@ -1280,11 +1142,11 @@ void cgit_compose_snapshot_prefix(struct strbuf *filename, const char *base, * name starts with {v,V}[0-9] and the prettify mapping is injective, * i.e. each stripped tag can be inverted without ambiguities. */ - if (repo_get_oid(the_repository, fmt("refs/tags/%s", ref), &oid) == 0 && + if (get_oid(fmt("refs/tags/%s", ref), &oid) == 0 && (ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1]) && - ((repo_get_oid(the_repository, fmt("refs/tags/%s", ref + 1), &oid) == 0) + - (repo_get_oid(the_repository, fmt("refs/tags/v%s", ref + 1), &oid) == 0) + - (repo_get_oid(the_repository, fmt("refs/tags/V%s", ref + 1), &oid) == 0) == 1)) + ((get_oid(fmt("refs/tags/%s", ref + 1), &oid) == 0) + + (get_oid(fmt("refs/tags/v%s", ref + 1), &oid) == 0) + + (get_oid(fmt("refs/tags/V%s", ref + 1), &oid) == 0) == 1)) ref++; strbuf_addf(filename, "%s-%s", base, ref); @@ -1331,17 +1193,6 @@ void cgit_print_snapshot_links(const struct cgit_repo *repo, const char *ref, strbuf_release(&filename); } -/* Locate the last '/' within the first len bytes of path, or NULL if - * there is none. Avoids memrchr(), which is a GNU extension. - */ -static const char *find_last_slash(const char *path, size_t len) -{ - while (len > 0) - if (path[--len] == '/') - return path + len; - return NULL; -} - void cgit_set_title_from_path(const char *path) { struct strbuf sb = STRBUF_INIT; @@ -1350,7 +1201,7 @@ void cgit_set_title_from_path(const char *path) if (!path) return; - for (last_slash = path + strlen(path); (slash = find_last_slash(path, last_slash - path)) != NULL; last_slash = slash) { + for (last_slash = path + strlen(path); (slash = memrchr(path, '/', last_slash - path)) != NULL; last_slash = slash) { strbuf_add(&sb, slash + 1, last_slash - slash - 1); strbuf_addstr(&sb, " \xc2\xab "); } |