| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | README.md | 14 | ||||
| -rw-r--r-- | cgit.c | 14 | ||||
| -rw-r--r-- | cgit.css | 423 | ||||
| -rw-r--r-- | cgit.h | 4 | ||||
| -rw-r--r-- | cgit.svg | 5 | ||||
| -rw-r--r-- | cgitrc.5.txt | 18 | ||||
| -rw-r--r-- | favicon.svg | 5 | ||||
| -rwxr-xr-x | filters/html-converters/md2html | 84 | ||||
| -rwxr-xr-x | filters/syntax-highlighting.py | 45 | ||||
| -rwxr-xr-x | filters/syntax-highlighting.sh | 14 | ||||
| -rw-r--r-- | solarized.css | 140 | ||||
| -rwxr-xr-x | tests/t0106-diff.sh | 154 | ||||
| -rw-r--r-- | ui-diff.c | 155 | ||||
| -rw-r--r-- | ui-shared.c | 98 |
16 files changed, 184 insertions, 996 deletions
@@ -10,4 +10,3 @@ cgitrc.5.pdf cgitrc.5.xml *.o *.d -__pycache__/ @@ -87,12 +87,9 @@ install: all $(INSTALL) -m 0755 cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_DATA_PATH) $(INSTALL) -m 0644 cgit.css $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css - $(INSTALL) -m 0644 solarized.css $(DESTDIR)$(CGIT_DATA_PATH)/solarized.css $(INSTALL) -m 0644 cgit.js $(DESTDIR)$(CGIT_DATA_PATH)/cgit.js $(INSTALL) -m 0644 cgit.png $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png - $(INSTALL) -m 0644 cgit.svg $(DESTDIR)$(CGIT_DATA_PATH)/cgit.svg $(INSTALL) -m 0644 favicon.ico $(DESTDIR)$(CGIT_DATA_PATH)/favicon.ico - $(INSTALL) -m 0644 favicon.svg $(DESTDIR)$(CGIT_DATA_PATH)/favicon.svg $(INSTALL) -m 0644 robots.txt $(DESTDIR)$(CGIT_DATA_PATH)/robots.txt $(INSTALL) -m 0755 -d $(DESTDIR)$(filterdir) $(COPYTREE) filters/* $(DESTDIR)$(filterdir) @@ -119,12 +116,9 @@ endef uninstall: rm -f $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css - rm -f $(DESTDIR)$(CGIT_DATA_PATH)/solarized.css rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.js rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png - rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.svg rm -f $(DESTDIR)$(CGIT_DATA_PATH)/favicon.ico - rm -f $(DESTDIR)$(CGIT_DATA_PATH)/favicon.svg rm -f $(DESTDIR)$(CGIT_DATA_PATH)/robots.txt $(foreach file,$(patsubst filters/%,%,$(shell find filters/ ! -type d)), \ $(call rm_f,$(DESTDIR)$(filterdir)/$(file))) @@ -1,22 +1,12 @@ -## cgitext – CGI for Git extension by Saya Andy +## cgitext - CGI for Git extension by Saya Andy This is a custom expansion to cgit. Its most prominent changes by now are: * CI/CD tab, linking to an external service on ref pages by using template. The Jenkins plugin is added to support a scenario when a ref lacks a pipeline. -* Theming now relies on CSS variables set in cgit.css, to allow easier custom additions and implicit filter theming. - -* Allow to use multiple favicons and of MIME type different from x-icon (f.ex. svg/png/webp). - -* Use vector-based format for favicon and cgit logo and make it default. - -* Include optional solarized.css addon theme. - -* Allow user to pick variable refs for diff in web ui. - The original cgit project is hosted at [git.zx2c4.com](https://git.zx2c4.com/cgit/about/) -## cgit – CGI for Git +## cgit - CGI for Git This is an attempt to create a fast web interface for the Git SCM, using a built-in cache to decrease server I/O pressure. @@ -5,7 +5,6 @@ * * Modified 2026 by Saya Andy: * Always check there is git repo on repo.path - * Allow to include multiple favicons * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -171,7 +170,7 @@ static void config_cb(const char *name, const char *value) else if (!strcmp(name, "js")) string_list_append(&ctx.cfg.js, strdup_first_line(value)); else if (!strcmp(name, "favicon")) - string_list_append(&ctx.cfg.favicon, strdup_first_line(value)); + ctx.cfg.favicon = strdup_first_line(value); else if (!strcmp(name, "footer")) ctx.cfg.footer = strdup_first_line(value); else if (!strcmp(name, "head-include")) @@ -393,14 +392,6 @@ static void querystring_cb(const char *name, const char *value) ctx.qry.ignorews = atoi(value); } else if (!strcmp(name, "follow")) { ctx.qry.follow = atoi(value); - } else if (!strcmp(name, "idoff")) { - ctx.qry.idoff = atoi(value); - if (ctx.qry.idoff < 0) - ctx.qry.idoff = 0; - } else if (!strcmp(name, "id2off")) { - ctx.qry.id2off = atoi(value); - if (ctx.qry.id2off < 0) - ctx.qry.id2off = 0; } } @@ -421,7 +412,8 @@ static void prepare_context(void) ctx.cfg.case_sensitive_sort = 1; ctx.cfg.branch_sort = 0; ctx.cfg.commit_sort = 0; - ctx.cfg.logo = "/cgit.svg"; + ctx.cfg.logo = "/cgit.png"; + ctx.cfg.favicon = "/favicon.ico"; ctx.cfg.local_time = 0; ctx.cfg.enable_http_clone = 1; ctx.cfg.enable_index_owner = 1; @@ -1,88 +1,15 @@ div#cgit { - --bg: white; - --bg-zebra: #f7f7f7; - --bg-hl: #eee; - --bg-hl2: #ccc; - --fg: #333; - --fg-strong: #000; - --fg-mid: #444; - --fg-mute: #777; - --fg-dim: #888; - --fg-faint: #bbb; - --fg-faintest: #ccc; - --fg-on-tint: black; - --fg-linenum: gray; - --border: #ccc; - --border-mid: #aaa; - --border-dark: #777; - --border-strong: black; - - --red: red; - --red-mid: #c00; - --red-dark: #800; - --green: green; - --green-mid: #080; - --green-dark: #040; - --blue: blue; - --blue-dark: #009; - - --graph-col1: #a00; - --graph-col2: #0a0; - --graph-col3: #aa0; - --graph-col4: #00a; - --graph-col5: #a0a; - --graph-col6: #0aa; - - --graph-add-bg: #5c5; - --graph-rem-bg: #c55; - - --notes-bg: #ffd; - --notes-border: #ee9; - --add-bg: #cfc; - --add-bg-dark: #aca; - --del-bg: #fcc; - --del-bg-dark: #caa; - --changed-bg: #ffc; - --changed-bg-dark: #cca; - --hunk-bg: #ccf; - - --deco-branch-bg: #8f8; - --deco-branch-border: #070; - --deco-tag-bg: #ff8; - --deco-tag-border: #770; - --deco-tag-annotated-bg: #fc8; - --deco-tag-annotated-border: #770; - --deco-remote-bg: #ccf; - --deco-remote-border: #007; - --deco-other-bg: #f88; - --deco-other-border: #700; - - --syn-keyword: #000; - --syn-keyword-alt: #0057ae; - --syn-type: #010181; - --syn-string: #bf0303; - --syn-string-alt: #818100; - --syn-escape: #f0f; - --syn-comment: #838183; - --syn-number: #b07e00; - --syn-preproc: #008200; - --syn-operator: #000; - --syn-interpolation: #0057ae; - --syn-linenum: #555; - --syn-error: #bf0303; - --syn-mark-bg: #ffb; - padding: 0em; margin: 0em; font-family: sans-serif; font-size: 10pt; - color: var(--fg); - background: var(--bg); + color: #333; + background: white; padding: 4px; } div#cgit a { - color: var(--blue); + color: blue; text-decoration: none; } @@ -111,7 +38,7 @@ div#cgit table#header td.main { } div#cgit table#header td.main a { - color: var(--fg-strong); + color: #000; } div#cgit table#header td.form { @@ -129,13 +56,13 @@ div#cgit table#header td.form select { } div#cgit table#header td.sub { - color: var(--fg-mute); - border-top: solid 1px var(--border); + color: #777; + border-top: solid 1px #ccc; padding-left: 10px; } div#cgit table.tabs { - border-bottom: solid 3px var(--border); + border-bottom: solid 3px #ccc; border-collapse: collapse; margin-top: 2em; margin-bottom: 0px; @@ -149,13 +76,13 @@ div#cgit table.tabs td { div#cgit table.tabs td a { padding: 2px 0.75em; - color: var(--fg-mute); + color: #777; font-size: 110%; } div#cgit table.tabs td a.active { - color: var(--fg-strong); - background-color: var(--bg-hl2); + color: #000; + background-color: #ccc; } div#cgit table.tabs a[href^="http://"]:after, div#cgit table.tabs a[href^="https://"]:after { @@ -182,14 +109,14 @@ div#cgit table.tabs td.form select { div#cgit div.path { margin: 0px; padding: 5px 2em 2px 2em; - color: var(--fg-strong); - background-color: var(--bg-hl); + color: #000; + background-color: #eee; } div#cgit div.content { margin: 0px; padding: 2em; - border-bottom: solid 3px var(--border); + border-bottom: solid 3px #ccc; } @@ -200,46 +127,46 @@ div#cgit table.list { } div#cgit table.list tr { - background: var(--bg); + background: white; } div#cgit table.list tr.logheader { - background: var(--bg-hl); + background: #eee; } div#cgit table.list tr:nth-child(even) { - background: var(--bg-zebra); + background: #f7f7f7; } div#cgit table.list tr:nth-child(odd) { - background: var(--bg); + background: white; } div#cgit table.list tr:hover { - background: var(--bg-hl); + background: #eee; } div#cgit table.list tr.nohover { - background: var(--bg); + background: white; } div#cgit table.list tr.nohover:hover { - background: var(--bg); + background: white; } div#cgit table.list tr.nohover-highlight:hover:nth-child(even) { - background: var(--bg-zebra); + background: #f7f7f7; } div#cgit table.list tr.nohover-highlight:hover:nth-child(odd) { - background: var(--bg); + background: white; } div#cgit table.list th { font-weight: bold; - /* color: var(--fg-dim); - border-top: dashed 1px var(--fg-dim); - border-bottom: dashed 1px var(--fg-dim); + /* color: #888; + border-top: dashed 1px #888; + border-bottom: dashed 1px #888; */ padding: 0.1em 0.5em 0.05em 0.5em; vertical-align: baseline; @@ -256,27 +183,27 @@ div#cgit table.list td.commitgraph { } div#cgit table.list td.commitgraph .column1 { - color: var(--graph-col1); + color: #a00; } div#cgit table.list td.commitgraph .column2 { - color: var(--graph-col2); + color: #0a0; } div#cgit table.list td.commitgraph .column3 { - color: var(--graph-col3); + color: #aa0; } div#cgit table.list td.commitgraph .column4 { - color: var(--graph-col4); + color: #00a; } div#cgit table.list td.commitgraph .column5 { - color: var(--graph-col5); + color: #a0a; } div#cgit table.list td.commitgraph .column6 { - color: var(--graph-col6); + color: #0aa; } div#cgit table.list td.logsubject { @@ -291,16 +218,16 @@ div#cgit table.list td.logmsg { } div#cgit table.list td a { - color: var(--fg-strong); + color: black; } div#cgit table.list td a.ls-dir { font-weight: bold; - color: var(--blue); + color: #00f; } div#cgit table.list td a:hover { - color: var(--blue); + color: #00f; } div#cgit img { @@ -334,21 +261,21 @@ div#cgit div#summary { div#cgit table#downloads { float: right; border-collapse: collapse; - border: solid 1px var(--border-dark); + border: solid 1px #777; margin-left: 0.5em; margin-bottom: 0.5em; } div#cgit table#downloads th { - background-color: var(--bg-hl2); + background-color: #ccc; } div#cgit div#blob { - border: solid 1px var(--border-strong); + border: solid 1px black; } div#cgit div.error { - color: var(--red); + color: red; font-weight: bold; margin: 1em 2em; } @@ -370,21 +297,21 @@ div#cgit td.ls-mode { div#cgit table.blob { margin-top: 0.5em; - border-top: solid 1px var(--border-strong); + border-top: solid 1px black; } div#cgit table.blob td.hashes, div#cgit table.blob td.lines { margin: 0; padding: 0 0 0 0.5em; vertical-align: top; - color: var(--fg-strong); + color: black; } div#cgit table.blob td.linenumbers { margin: 0; padding: 0 0.5em 0 0.5em; vertical-align: top; text-align: right; - border-right: 1px solid var(--fg-linenum); + border-right: 1px solid gray; } div#cgit table.blob pre { @@ -393,18 +320,18 @@ div#cgit table.blob pre { div#cgit table.blob td.linenumbers a, div#cgit table.ssdiff td.lineno a { - color: var(--fg-linenum); + color: gray; text-align: right; text-decoration: none; } div#cgit table.blob td.linenumbers a:hover, div#cgit table.ssdiff td.lineno a:hover { - color: var(--fg-strong); + color: black; } div#cgit table.blob td.linenumbers a:target:before { - color: var(--red); + color: red; content: "\2BA9"; } @@ -424,11 +351,11 @@ div#cgit table.blame td.linenumbers div.alt { } div#cgit table.blame div.alt:nth-child(even) { - background: var(--bg-hl); + background: #eee; } div#cgit table.blame div.alt:nth-child(odd) { - background: var(--bg); + background: white; } div#cgit table.blame td.lines > div { @@ -447,20 +374,20 @@ div#cgit table.blame .oid { div#cgit table.bin-blob { margin-top: 0.5em; - border: solid 1px var(--border-strong); + border: solid 1px black; } div#cgit table.bin-blob th { font-family: monospace; white-space: pre; - border: solid 1px var(--border-dark); + border: solid 1px #777; padding: 0.5em 1em; } div#cgit table.bin-blob td { font-family: monospace; white-space: pre; - border-left: solid 1px var(--border-dark); + border-left: solid 1px #777; padding: 0em 1em; } @@ -478,18 +405,10 @@ div#cgit div.cgit-panel { margin-top: 1.5em; } -div#cgit form.diff-ctrls div.cgit-panel { - float: none; -} - -div#cgit form.diff-ctrls { - float: right; -} - div#cgit div.cgit-panel table { border-collapse: collapse; - border: solid 1px var(--border-mid); - background-color: var(--bg-hl); + border: solid 1px #aaa; + background-color: #eee; } div#cgit div.cgit-panel th { @@ -540,8 +459,8 @@ div#cgit div.notes-header { div#cgit div.notes { white-space: pre; font-family: monospace; - border: solid 1px var(--notes-border); - background-color: var(--notes-bg); + border: solid 1px #ee9; + background-color: #ffd; padding: 0.3em 2em 0.3em 1em; float: left; } @@ -557,8 +476,8 @@ div#cgit div.diffstat-header { div#cgit table.diffstat { border-collapse: collapse; - border: solid 1px var(--border-mid); - background-color: var(--bg-hl); + border: solid 1px #aaa; + background-color: #eee; } div#cgit table.diffstat th { @@ -581,19 +500,19 @@ div#cgit table.diffstat td.mode { div#cgit table.diffstat td span.modechange { padding-left: 1em; - color: var(--red); + color: red; } div#cgit table.diffstat td.add a { - color: var(--green); + color: green; } div#cgit table.diffstat td.del a { - color: var(--red); + color: red; } div#cgit table.diffstat td.upd a { - color: var(--blue); + color: blue; } div#cgit table.diffstat td.graph { @@ -612,15 +531,15 @@ div#cgit table.diffstat td.graph td { } div#cgit table.diffstat td.graph td.add { - background-color: var(--graph-add-bg); + background-color: #5c5; } div#cgit table.diffstat td.graph td.rem { - background-color: var(--graph-rem-bg); + background-color: #c55; } div#cgit div.diffstat-summary { - color: var(--fg-dim); + color: #888; padding-top: 0.5em; } @@ -636,19 +555,19 @@ div#cgit table.diff td { div#cgit table.diff td div.head { font-weight: bold; margin-top: 1em; - color: var(--fg-strong); + color: black; } div#cgit table.diff td div.hunk { - color: var(--blue-dark); + color: #009; } div#cgit table.diff td div.add { - color: var(--green); + color: green; } div#cgit table.diff td div.del { - color: var(--red); + color: red; } div#cgit .oid { @@ -666,7 +585,7 @@ div#cgit .right { div#cgit table.list td.reposection { font-style: italic; - color: var(--fg-dim); + color: #888; } div#cgit a.button { @@ -674,22 +593,6 @@ div#cgit a.button { padding: 0em 0.5em; } -div#cgit form.diff-ctrls div.cgit-panel a.button, -div#cgit form.diff-ctrls div.cgit-panel input[type=submit] { - border: solid 1px var(--border-mid); - background-color: var(--bg-hl); -} - -div#cgit form.diff-ctrls div.cgit-panel input[type=submit] { - font-size: 80%; - padding: 0em 0.5em; -} - -div#cgit span.hint { - color: var(--fg-mute); - font-size: 80%; -} - div#cgit a.primary { font-size: 100%; } @@ -719,7 +622,7 @@ div#cgit ul.pager li { } div#cgit ul.pager a { - color: var(--fg-mute); + color: #777; } div#cgit ul.pager .current { @@ -728,46 +631,46 @@ div#cgit ul.pager .current { div#cgit span.age-mins { font-weight: bold; - color: var(--green-mid); + color: #080; } div#cgit span.age-hours { - color: var(--green-mid); + color: #080; } div#cgit span.age-days { - color: var(--green-dark); + color: #040; } div#cgit span.age-weeks { - color: var(--fg-mid); + color: #444; } div#cgit span.age-months { - color: var(--fg-dim); + color: #888; } div#cgit span.age-years { - color: var(--fg-faint); + color: #bbb; } div#cgit span.insertions { - color: var(--green-mid); + color: #080; } div#cgit span.deletions { - color: var(--red-dark); + color: #800; } div#cgit div.footer { margin-top: 0.5em; text-align: center; font-size: 80%; - color: var(--fg-faintest); + color: #ccc; } div#cgit div.footer a { - color: var(--fg-faintest); + color: #ccc; text-decoration: none; } @@ -776,47 +679,47 @@ div#cgit div.footer a:hover { } div#cgit a.branch-deco { - color: var(--fg-strong); + color: #000; margin: 0px 0.5em; padding: 0px 0.25em; - background-color: var(--deco-branch-bg); - border: solid 1px var(--deco-branch-border); + background-color: #88ff88; + border: solid 1px #007700; border-radius: 2px; } div#cgit a.tag-deco { - color: var(--fg-strong); + color: #000; margin: 0px 0.5em; padding: 0px 0.25em; - background-color: var(--deco-tag-bg); - border: solid 1px var(--deco-tag-border); + background-color: #ffff88; + border: solid 1px #777700; border-radius: 2px; } div#cgit a.tag-annotated-deco { - color: var(--fg-strong); + color: #000; margin: 0px 0.5em; padding: 0px 0.25em; - background-color: var(--deco-tag-annotated-bg); - border: solid 1px var(--deco-tag-annotated-border); + background-color: #ffcc88; + border: solid 1px #777700; border-radius: 2px; } div#cgit a.remote-deco { - color: var(--fg-strong); + color: #000; margin: 0px 0.5em; padding: 0px 0.25em; - background-color: var(--deco-remote-bg); - border: solid 1px var(--deco-remote-border); + background-color: #ccccff; + border: solid 1px #000077; border-radius: 2px; } div#cgit a.deco { - color: var(--fg-strong); + color: #000; margin: 0px 0.5em; padding: 0px 0.25em; - background-color: var(--deco-other-bg); - border: solid 1px var(--deco-other-border); + background-color: #ff8888; + border: solid 1px #770000; border-radius: 2px; } @@ -830,21 +733,21 @@ div#cgit div.commit-subject a.deco { } div#cgit table.stats { - border: solid 1px var(--border-strong); + border: solid 1px black; border-collapse: collapse; } div#cgit table.stats th { text-align: left; padding: 1px 0.5em; - background-color: var(--bg-hl); - border: solid 1px var(--border-strong); + background-color: #eee; + border: solid 1px black; } div#cgit table.stats td { text-align: right; padding: 1px 0.5em; - border: solid 1px var(--border-strong); + border: solid 1px black; } div#cgit table.stats td.total { @@ -853,9 +756,9 @@ div#cgit table.stats td.total { } div#cgit table.stats td.sum { - color: var(--red-mid); + color: #c00; font-weight: bold; -/* background-color: var(--bg-hl); */ +/* background-color: #eee; */ } div#cgit table.stats td.left { @@ -864,14 +767,14 @@ div#cgit table.stats td.left { div#cgit table.vgraph { border-collapse: separate; - border: solid 1px var(--border-strong); + border: solid 1px black; height: 200px; } div#cgit table.vgraph th { - background-color: var(--bg-hl); + background-color: #eee; font-weight: bold; - border: solid 1px var(--bg); + border: solid 1px white; padding: 1px 0.5em; } @@ -881,18 +784,18 @@ div#cgit table.vgraph td { } div#cgit table.vgraph div.bar { - background-color: var(--bg-hl); + background-color: #eee; } div#cgit table.hgraph { - border: solid 1px var(--border-strong); + border: solid 1px black; width: 800px; } div#cgit table.hgraph th { - background-color: var(--bg-hl); + background-color: #eee; font-weight: bold; - border: solid 1px var(--border-strong); + border: solid 1px black; padding: 1px 0.5em; } @@ -902,7 +805,7 @@ div#cgit table.hgraph td { } div#cgit table.hgraph div.bar { - background-color: var(--bg-hl); + background-color: #eee; height: 1em; } @@ -915,83 +818,83 @@ div#cgit table.ssdiff td { font-family: monospace; white-space: pre; padding: 1px 4px 1px 4px; - border-left: solid 1px var(--border-mid); - border-right: solid 1px var(--border-mid); + border-left: solid 1px #aaa; + border-right: solid 1px #aaa; } div#cgit table.ssdiff td.add { - color: var(--fg-on-tint); - background: var(--add-bg); + color: black; + background: #cfc; min-width: 50%; } div#cgit table.ssdiff td.add_dark { - color: var(--fg-on-tint); - background: var(--add-bg-dark); + color: black; + background: #aca; min-width: 50%; } div#cgit table.ssdiff span.add { - background: var(--add-bg); + background: #cfc; font-weight: bold; } div#cgit table.ssdiff td.del { - color: var(--fg-on-tint); - background: var(--del-bg); + color: black; + background: #fcc; min-width: 50%; } div#cgit table.ssdiff td.del_dark { - color: var(--fg-on-tint); - background: var(--del-bg-dark); + color: black; + background: #caa; min-width: 50%; } div#cgit table.ssdiff span.del { - background: var(--del-bg); + background: #fcc; font-weight: bold; } div#cgit table.ssdiff td.changed { - color: var(--fg-on-tint); - background: var(--changed-bg); + color: black; + background: #ffc; min-width: 50%; } div#cgit table.ssdiff td.changed_dark { - color: var(--fg-on-tint); - background: var(--changed-bg-dark); + color: black; + background: #cca; min-width: 50%; } div#cgit table.ssdiff td.lineno { - color: var(--fg-on-tint); - background: var(--bg-hl); + color: black; + background: #eee; text-align: right; width: 3em; min-width: 3em; } div#cgit table.ssdiff td.hunk { - color: var(--fg-on-tint); - background: var(--hunk-bg); - border-top: solid 1px var(--border-mid); - border-bottom: solid 1px var(--border-mid); + color: black; + background: #ccf; + border-top: solid 1px #aaa; + border-bottom: solid 1px #aaa; } div#cgit table.ssdiff td.head { - border-top: solid 1px var(--border-mid); - border-bottom: solid 1px var(--border-mid); + border-top: solid 1px #aaa; + border-bottom: solid 1px #aaa; } div#cgit table.ssdiff td.head div.head { font-weight: bold; - color: var(--fg-on-tint); + color: black; } div#cgit table.ssdiff td.foot { - border-top: solid 1px var(--border-mid); + border-top: solid 1px #aaa; border-left: none; border-right: none; border-bottom: none; @@ -1004,63 +907,3 @@ div#cgit table.ssdiff td.space { div#cgit table.ssdiff td.space div { min-height: 3em; } - -div#cgit .hl.kwa, -div#cgit .hl.kwc { - color: var(--syn-keyword); - font-weight: bold; -} - -div#cgit .hl.kwb { - color: var(--syn-keyword-alt); -} - -div#cgit .hl.kwd { - color: var(--syn-type); -} - -div#cgit .hl.str { - color: var(--syn-string); -} - -div#cgit .hl.dstr, -div#cgit .hl.pps { - color: var(--syn-string-alt); -} - -div#cgit .hl.esc { - color: var(--syn-escape); -} - -div#cgit .hl.com, -div#cgit .hl.slc { - color: var(--syn-comment); - font-style: italic; -} - -div#cgit .hl.num { - color: var(--syn-number); -} - -div#cgit .hl.dir, -div#cgit .hl.ppc { - color: var(--syn-preproc); -} - -div#cgit .hl.opt, -div#cgit .hl.sym { - color: var(--syn-operator); -} - -div#cgit .hl.ipl { - color: var(--syn-interpolation); -} - -div#cgit .hl.lin, -div#cgit .hl.line { - color: var(--syn-linenum); -} - -div#cgit .hl.mark { - background-color: var(--syn-mark-bg); -} @@ -181,8 +181,6 @@ struct cgit_query { char *head; char *oid; char *oid2; - int idoff; - int id2off; char *path; char *name; char *url; @@ -207,7 +205,7 @@ struct cgit_config { char *ci_tag_url; char *clone_prefix; char *clone_url; - struct string_list favicon; + char *favicon; char *footer; char *head_include; char *header; diff --git a/cgit.svg b/cgit.svg deleted file mode 100644 index 43fee2c..0000000 --- a/cgit.svg +++ /dev/null @@ -1,5 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="96" height="64" viewBox="0 0 96 64" fill="none" stroke="#a00" stroke-width="5"> - <title>cgit</title> - <path d="M31.5 27.5A9 9 0 0 0 22.5 18.5h-5A9 9 0 0 0 8.5 27.5V38a9 9 0 0 0 9 9h5a9 9 0 0 0 9-9M31.5 38v12.5a8 8 0 0 1-8 8H17a8 8 0 0 1-8-8M46.5 3v5m0 8v33M62.5 9v29.75a7.75 7.75 0 0 0 15.5 0V37"/> - <path stroke-width="4" d="M56 18h25"/> -</svg> diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 527233d..76b2085 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -240,14 +240,9 @@ enable-tree-linenumbers:: for plaintext blobs printed in the tree view. Default value: "1". favicon:: - Url used as link to a shortcut icon for cgit. It is suggested to - always include the value "/favicon.ico" since certain browsers will - ignore other values. May be given multiple times, each favicon URL - path is added in the head section of the document in turn, letting - the browser pick the icon it prefers. The mimetype of each icon is - deduced from the extension of its url ("ico", "png", "svg", "gif", - "jpg", "jpeg", "webp" and "avif" are recognized) and emitted as a - "type" attribute. Default value: "/favicon.svg", "/favicon.ico". + Url used as link to a shortcut icon for cgit. It is suggested to use + the value "/favicon.ico" since certain browsers will ignore other + values. Default value: "/favicon.ico". footer:: The content of the file specified with this option will be included @@ -277,7 +272,7 @@ local-time:: logo:: Url which specifies the source of an image which will be used as a logo - on all cgit pages. Default value: "/cgit.svg". + on all cgit pages. Default value: "/cgit.png". logo-link:: Url loaded when clicking on the cgit logo image. If unspecified the @@ -921,10 +916,8 @@ cache-size=1000 # Specify some default clone urls using macro expansion clone-url=git://foo.org/$CGIT_REPO_URL git@foo.org:$CGIT_REPO_URL - # Specify the css url css=/css/cgit.css -css=/css/solarized.css # Add a "ci" tab pointing at a Jenkins multibranch pipeline @@ -964,8 +957,7 @@ enable-log-linecount=1 branch-sort=age -# Add cgit favicons -favicon=/favicon.svg +# Add a cgit favicon favicon=/favicon.ico diff --git a/favicon.svg b/favicon.svg deleted file mode 100644 index 6be3df4..0000000 --- a/favicon.svg +++ /dev/null @@ -1,5 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 52 52" fill="none" stroke-width="6"> - <title>cgit</title> - <g stroke="#f33"><path id="g" d="M37.5 15A9 9 0 0 0 28.5 6h-5A9 9 0 0 0 14.5 15v10.5a9 9 0 0 0 9 9h5a9 9 0 0 0 9-9M37.5 25.5V38a8 8 0 0 1-8 8H23a8 8 0 0 1-8-8"/></g> - <use href="#g" stroke="#a00" stroke-width="4"/> -</svg> diff --git a/filters/html-converters/md2html b/filters/html-converters/md2html index 4f6ad37..59f43a8 100755 --- a/filters/html-converters/md2html +++ b/filters/html-converters/md2html @@ -2,46 +2,8 @@ import markdown import sys import io +from pygments.formatters import HtmlFormatter from markdown.extensions.toc import TocExtension - -# Pygments' token classes, mapped onto the --syn-* custom properties that -# cgit.css defines. The fallbacks are the palette those properties default to, -# so that the output stays readable under a stylesheet without them. -SYNTAX_COLORS = ( - (('k', 'kc', 'kd', 'kn', 'kr'), '--syn-keyword', '#000', - 'font-weight: bold'), - (('kp',), '--syn-keyword', '#000', None), - (('kt',), '--syn-type', '#010181', None), - (('nc', 'nf', 'nn', 'ne'), '--syn-keyword-alt', '#0057ae', None), - (('s', 'sa', 'sb', 'sc', 'dl', 'sd', 's2', 'sh', 'sx', 'sr', 's1', 'ss'), - '--syn-string', '#bf0303', None), - (('se',), '--syn-escape', '#f0f', None), - (('si',), '--syn-interpolation', '#0057ae', None), - (('c', 'ch', 'cm', 'c1', 'cs'), '--syn-comment', '#838183', - 'font-style: italic'), - (('cp', 'cpf'), '--syn-preproc', '#008200', None), - (('m', 'mb', 'mf', 'mh', 'mi', 'mo', 'il'), '--syn-number', '#b07e00', - None), - (('o', 'ow', 'p'), '--syn-operator', '#000', None), - (('err',), '--syn-error', '#bf0303', None), - (('gd',), '--red', 'red', None), - (('gi',), '--green', 'green', None), - (('lineno', 'linenos'), '--syn-linenum', '#555', None), -) - - -def style_defs(prefix='.highlight'): - rules = [] - for classes, prop, fallback, extra in SYNTAX_COLORS: - selector = ', '.join('%s .%s' % (prefix, c) for c in classes) - decls = 'color: var(%s, %s)' % (prop, fallback) - if extra: - decls += '; ' + extra - rules.append('%s { %s }' % (selector, decls)) - rules.append('%s .hll { background-color: var(--syn-mark-bg, #ffb) }' - % prefix) - return '\n'.join(rules) + '\n' - sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8') sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') sys.stdout.write(''' @@ -58,7 +20,7 @@ sys.stdout.write(''' margin-bottom: 0 !important; } .markdown-body a.absent { - color: var(--red-mid, #c00); + color: #c00; } .markdown-body a.anchor { display: block; @@ -80,7 +42,7 @@ sys.stdout.write(''' } .markdown-body h1 .mini-icon-link, .markdown-body h2 .mini-icon-link, .markdown-body h3 .mini-icon-link, .markdown-body h4 .mini-icon-link, .markdown-body h5 .mini-icon-link, .markdown-body h6 .mini-icon-link { display: none; - color: var(--fg-strong, #000); + color: #000; } .markdown-body h1:hover a.anchor, .markdown-body h2:hover a.anchor, .markdown-body h3:hover a.anchor, .markdown-body h4:hover a.anchor, .markdown-body h5:hover a.anchor, .markdown-body h6:hover a.anchor { text-decoration: none; @@ -93,19 +55,19 @@ sys.stdout.write(''' display: inline-block; } div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div#cgit .markdown-body h3 a.toclink, div#cgit .markdown-body h4 a.toclink, div#cgit .markdown-body h5 a.toclink, div#cgit .markdown-body h6 a.toclink { - color: var(--fg-strong, #000); + color: black; } .markdown-body h1 tt, .markdown-body h1 code, .markdown-body h2 tt, .markdown-body h2 code, .markdown-body h3 tt, .markdown-body h3 code, .markdown-body h4 tt, .markdown-body h4 code, .markdown-body h5 tt, .markdown-body h5 code, .markdown-body h6 tt, .markdown-body h6 code { font-size: inherit; } .markdown-body h1 { font-size: 28px; - color: var(--fg-strong, #000); + color: #000; } .markdown-body h2 { font-size: 24px; - border-bottom: 1px solid var(--border, #ccc); - color: var(--fg-strong, #000); + border-bottom: 1px solid #ccc; + color: #000; } .markdown-body h3 { font-size: 18px; @@ -117,14 +79,14 @@ div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div# font-size: 14px; } .markdown-body h6 { - color: var(--fg-mute, #777); + color: #777; font-size: 14px; } .markdown-body p, .markdown-body blockquote, .markdown-body ul, .markdown-body ol, .markdown-body dl, .markdown-body table, .markdown-body pre { margin: 15px 0; } .markdown-body hr { - border: 2px solid var(--border, #ccc); + border: 2px solid #ccc; } .markdown-body>h2:first-child, .markdown-body>h1:first-child, .markdown-body>h1:first-child+h2, .markdown-body>h3:first-child, .markdown-body>h4:first-child, .markdown-body>h5:first-child, .markdown-body>h6:first-child { margin-top: 0; @@ -186,9 +148,9 @@ div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div# margin-bottom: 0px; } .markdown-body blockquote { - border-left: 4px solid var(--border, #ddd); + border-left: 4px solid #DDD; padding: 0 15px; - color: var(--fg-mute, #777); + color: #777; } .markdown-body blockquote>:first-child { margin-top: 0px; @@ -200,15 +162,15 @@ div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div# font-weight: bold; } .markdown-body table th, .markdown-body table td { - border: 1px solid var(--border, #ccc); + border: 1px solid #ccc; padding: 6px 13px; } .markdown-body table tr { - border-top: 1px solid var(--border, #ccc); - background-color: var(--bg, #fff); + border-top: 1px solid #ccc; + background-color: #fff; } .markdown-body table tr:nth-child(2n) { - background-color: var(--bg-zebra, #f8f8f8); + background-color: #f8f8f8; } .markdown-body img { max-width: 100%; @@ -220,7 +182,7 @@ div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div# overflow: hidden; } .markdown-body span.frame>span { - border: 1px solid var(--border, #ddd); + border: 1px solid #ddd; display: block; float: left; overflow: hidden; @@ -234,7 +196,7 @@ div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div# } .markdown-body span.frame span span { clear: both; - color: var(--fg, #333); + color: #333; display: block; padding: 5px 0 0; } @@ -292,8 +254,8 @@ div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div# .markdown-body code, .markdown-body tt { margin: 0 2px; padding: 0px 5px; - border: 1px solid var(--border, #eaeaea); - background-color: var(--bg-zebra, #f8f8f8); + border: 1px solid #eaeaea; + background-color: #f8f8f8; border-radius: 3px; } .markdown-body code { @@ -307,8 +269,8 @@ div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div# background: transparent; } .markdown-body .highlight pre, .markdown-body pre { - background-color: var(--bg-zebra, #f8f8f8); - border: 1px solid var(--border, #ccc); + background-color: #f8f8f8; + border: 1px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; @@ -322,9 +284,9 @@ div#cgit .markdown-body h1 a.toclink, div#cgit .markdown-body h2 a.toclink, div# border: none; } ''') -sys.stdout.write(style_defs('.highlight')) +sys.stdout.write(HtmlFormatter(style='pastie').get_style_defs('.highlight')) sys.stdout.write(''' -</style> +</style> ''') sys.stdout.write("<div class='markdown-body'>") sys.stdout.flush() diff --git a/filters/syntax-highlighting.py b/filters/syntax-highlighting.py index d757e2d..e912594 100755 --- a/filters/syntax-highlighting.py +++ b/filters/syntax-highlighting.py @@ -30,50 +30,11 @@ from pygments.lexers import guess_lexer_for_filename from pygments.formatters import HtmlFormatter -# Pygments' token classes, mapped onto the --syn-* custom properties that -# cgit.css defines. The fallbacks are the palette those properties default to, -# so that the output stays readable under a stylesheet without them. -SYNTAX_COLORS = ( - (('k', 'kc', 'kd', 'kn', 'kr'), '--syn-keyword', '#000', - 'font-weight: bold'), - (('kp',), '--syn-keyword', '#000', None), - (('kt',), '--syn-type', '#010181', None), - (('nc', 'nf', 'nn', 'ne'), '--syn-keyword-alt', '#0057ae', None), - (('s', 'sa', 'sb', 'sc', 'dl', 'sd', 's2', 'sh', 'sx', 'sr', 's1', 'ss'), - '--syn-string', '#bf0303', None), - (('se',), '--syn-escape', '#f0f', None), - (('si',), '--syn-interpolation', '#0057ae', None), - (('c', 'ch', 'cm', 'c1', 'cs'), '--syn-comment', '#838183', - 'font-style: italic'), - (('cp', 'cpf'), '--syn-preproc', '#008200', None), - (('m', 'mb', 'mf', 'mh', 'mi', 'mo', 'il'), '--syn-number', '#b07e00', - None), - (('o', 'ow', 'p'), '--syn-operator', '#000', None), - (('err',), '--syn-error', '#bf0303', None), - (('gd',), '--red', 'red', None), - (('gi',), '--green', 'green', None), - (('lineno', 'linenos'), '--syn-linenum', '#555', None), -) - - -def style_defs(prefix='.highlight'): - rules = [] - for classes, prop, fallback, extra in SYNTAX_COLORS: - selector = ', '.join('%s .%s' % (prefix, c) for c in classes) - decls = 'color: var(%s, %s)' % (prop, fallback) - if extra: - decls += '; ' + extra - rules.append('%s { %s }' % (selector, decls)) - rules.append('%s .hll { background-color: var(--syn-mark-bg, #ffb) }' - % prefix) - return '\n'.join(rules) + '\n' - - sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8', errors='replace') sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') data = sys.stdin.read() filename = sys.argv[1] -formatter = HtmlFormatter(nobackground=True) +formatter = HtmlFormatter(style='pastie', nobackground=True) try: lexer = guess_lexer_for_filename(filename, data) @@ -87,8 +48,8 @@ except TypeError: lexer = TextLexer() # highlight! :-) -# printout the css definitions for pygments' token classes as well +# printout pygments' css definitions as well sys.stdout.write('<style>') -sys.stdout.write(style_defs('.highlight')) +sys.stdout.write(formatter.get_style_defs('.highlight')) sys.stdout.write('</style>') sys.stdout.write(highlight(data, lexer, formatter, outfile=None)) diff --git a/filters/syntax-highlighting.sh b/filters/syntax-highlighting.sh index bb8d60c..840bc34 100755 --- a/filters/syntax-highlighting.sh +++ b/filters/syntax-highlighting.sh @@ -8,10 +8,8 @@ # might have to use an external call to sed instead. # # Note: the highlight command (http://www.andre-simon.de/) uses css for syntax -# highlighting. cgit.css defines these classes in terms of its --syn-* custom -# properties, so nothing has to be added when using the default stylesheet. -# The palette below, from highlight 3.13, is what those properties default to; -# a custom stylesheet wanting the same colors can use it directly: +# highlighting, so you'll probably want something like the following included +# in your css file: # # Style definition file generated by highlight 2.4.8, http://www.andre-simon.de/ # @@ -116,12 +114,8 @@ EXTENSION="${BASENAME##*.}" # Version 2 can be found (for example) on EPEL 5, while version 3 can be # found (for example) on EPEL 6. # -# Note that -I (--include-style) is not used: the stylesheet it embeds in the -# output would override the .hl rules in cgit.css and with them any theming -# done through the --syn-* custom properties. -# # This is for version 2 -exec highlight --force -f -X -S "$EXTENSION" 2>/dev/null +exec highlight --force -f -I -X -S "$EXTENSION" 2>/dev/null # This is for version 3 -#exec highlight --force -f -O xhtml -S "$EXTENSION" 2>/dev/null +#exec highlight --force -f -I -O xhtml -S "$EXTENSION" 2>/dev/null diff --git a/solarized.css b/solarized.css deleted file mode 100644 index 2e6e3d4..0000000 --- a/solarized.css +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Solarized theme (Ethan Schoonover) with automatic light/dark selection - * based on the prefers-color-scheme media query. - * - * Must be listed after cgit.css, e.g. - * - * css=/cgit.css - * css=/solarized.css - */ - -:root { - --sol-base03: #002b36; - --sol-base02: #073642; - --sol-base01: #586e75; - --sol-base00: #657b83; - --sol-base0: #839496; - --sol-base1: #93a1a1; - --sol-base2: #eee8d5; - --sol-base3: #fdf6e3; - - --sol-yellow: #b58900; - --sol-orange: #cb4b16; - --sol-red: #dc322f; - --sol-magenta: #d33682; - --sol-violet: #6c71c4; - --sol-blue: #268bd2; - --sol-cyan: #2aa198; - --sol-green: #859900; - - --sol-canvas: var(--sol-base3); - --sol-panel: var(--sol-base2); - --sol-body: var(--sol-base00); - --sol-emph: var(--sol-base01); - --sol-muted: var(--sol-base0); - --sol-secondary: var(--sol-base1); - --sol-shade: var(--sol-base03); - --sol-page: var(--sol-panel); - - --sol-tint-soft: 18%; - --sol-tint: 25%; - --sol-tint-strong: 45%; - - color-scheme: light dark; -} - -@media (prefers-color-scheme: dark) { - :root { - --sol-canvas: var(--sol-base03); - --sol-panel: var(--sol-base02); - --sol-body: var(--sol-base0); - --sol-emph: var(--sol-base1); - --sol-muted: var(--sol-base00); - --sol-secondary: var(--sol-base01); - --sol-shade: var(--sol-base3); - - --sol-tint-soft: 30%; - --sol-tint: 35%; - --sol-tint-strong: 55%; - } -} - -body:has(> div#cgit) { - margin: 0; - background-color: var(--sol-page); -} - -div#cgit { - --bg: var(--sol-canvas); - --bg-zebra: color-mix(in srgb, var(--sol-panel) 40%, var(--sol-canvas)); - --bg-hl: var(--sol-panel); - --bg-hl2: color-mix(in srgb, var(--sol-panel) 85%, var(--sol-shade)); - --fg: var(--sol-body); - --fg-strong: var(--sol-emph); - --fg-mid: var(--sol-body); - --fg-mute: var(--sol-muted); - --fg-dim: var(--sol-secondary); - --fg-faint: color-mix(in srgb, var(--sol-secondary) 65%, var(--sol-canvas)); - --fg-faintest: color-mix(in srgb, var(--sol-secondary) 45%, var(--sol-canvas)); - --fg-on-tint: var(--sol-emph); - --fg-linenum: var(--sol-secondary); - --border: var(--sol-panel); - --border-mid: var(--sol-secondary); - --border-dark: var(--sol-muted); - --border-strong: var(--sol-emph); - - --red: var(--sol-red); - --red-mid: color-mix(in srgb, var(--sol-red) 75%, var(--sol-shade)); - --red-dark: color-mix(in srgb, var(--sol-red) 55%, var(--sol-shade)); - --green: var(--sol-green); - --green-mid: color-mix(in srgb, var(--sol-green) 70%, var(--sol-shade)); - --green-dark: color-mix(in srgb, var(--sol-green) 50%, var(--sol-shade)); - --blue: var(--sol-blue); - --blue-dark: color-mix(in srgb, var(--sol-blue) 70%, var(--sol-shade)); - - --graph-col1: var(--sol-red); - --graph-col2: var(--sol-green); - --graph-col3: var(--sol-yellow); - --graph-col4: var(--sol-blue); - --graph-col5: var(--sol-magenta); - --graph-col6: var(--sol-cyan); - - --graph-add-bg: var(--sol-green); - --graph-rem-bg: var(--sol-red); - - --notes-bg: color-mix(in srgb, var(--sol-yellow) var(--sol-tint-soft), var(--sol-canvas)); - --notes-border: var(--sol-yellow); - --add-bg: color-mix(in srgb, var(--sol-green) var(--sol-tint), var(--sol-canvas)); - --add-bg-dark: color-mix(in srgb, var(--sol-green) var(--sol-tint-strong), var(--sol-canvas)); - --del-bg: color-mix(in srgb, var(--sol-red) var(--sol-tint), var(--sol-canvas)); - --del-bg-dark: color-mix(in srgb, var(--sol-red) var(--sol-tint-strong), var(--sol-canvas)); - --changed-bg: color-mix(in srgb, var(--sol-yellow) var(--sol-tint), var(--sol-canvas)); - --changed-bg-dark: color-mix(in srgb, var(--sol-yellow) var(--sol-tint-strong), var(--sol-canvas)); - --hunk-bg: color-mix(in srgb, var(--sol-blue) var(--sol-tint), var(--sol-canvas)); - - --deco-branch-bg: color-mix(in srgb, var(--sol-green) var(--sol-tint-soft), var(--sol-canvas)); - --deco-branch-border: var(--sol-green); - --deco-tag-bg: color-mix(in srgb, var(--sol-yellow) var(--sol-tint-soft), var(--sol-canvas)); - --deco-tag-border: var(--sol-yellow); - --deco-tag-annotated-bg: color-mix(in srgb, var(--sol-orange) var(--sol-tint-soft), var(--sol-canvas)); - --deco-tag-annotated-border: var(--sol-yellow); - --deco-remote-bg: color-mix(in srgb, var(--sol-violet) var(--sol-tint-soft), var(--sol-canvas)); - --deco-remote-border: var(--sol-violet); - --deco-other-bg: color-mix(in srgb, var(--sol-red) var(--sol-tint-soft), var(--sol-canvas)); - --deco-other-border: var(--sol-red); - - --syn-keyword: var(--sol-emph); - --syn-keyword-alt: var(--sol-blue); - --syn-type: var(--blue-dark); - --syn-string: var(--sol-red); - --syn-string-alt: var(--sol-green); - --syn-escape: var(--sol-magenta); - --syn-comment: var(--sol-secondary); - --syn-number: var(--sol-yellow); - --syn-preproc: var(--green-mid); - --syn-operator: var(--sol-emph); - --syn-interpolation: var(--sol-blue); - --syn-linenum: var(--sol-secondary); - --syn-error: var(--sol-red); - --syn-mark-bg: color-mix(in srgb, var(--sol-yellow) var(--sol-tint), var(--sol-canvas)); -} diff --git a/tests/t0106-diff.sh b/tests/t0106-diff.sh index 4490ecc..82b645e 100755 --- a/tests/t0106-diff.sh +++ b/tests/t0106-diff.sh @@ -16,158 +16,4 @@ test_expect_success 'find added line' ' grep "<div class=.add.>+5</div>" tmp ' -test_expect_success 'ref picker: from: select present' ' - grep "<select name=.id2." tmp -' - -test_expect_success 'ref picker: to: select present' ' - grep "<select name=.id." tmp -' - -test_expect_success 'ref picker: from: label present' ' - grep "from:" tmp -' - -test_expect_success 'ref picker: to: label present' ' - grep "to:" tmp -' - -test_expect_success 'ref pickers live in a separate refs panel' ' - grep "<b>diff refs</b>" tmp && - grep "<b>diff options</b>" tmp -' - -test_expect_success 'ref picker: master branch listed' ' - grep "master" tmp -' - -test_expect_success 'ref picker: auto-submit on change' ' - grep "onchange=.this.form.submit()." tmp -' - -test_expect_success 'flip link present' ' - grep "<a title=.swap from and to. class=.button. href=./foo/diff/?" tmp -' - -test_expect_success 'flip link swaps the default refs' ' - grep "/foo/diff/?id2=master&idoff=1" tmp -' - -test_expect_success 'compare two refs: foo/diff?id=master&id2=HEAD' ' - cgit_query "url=foo/diff&id=master&id2=HEAD" >tmp -' - -test_expect_success 'diff with explicit refs shows diffstat' ' - grep "diffstat" tmp -' - -test_expect_success 'diff with oid2 parameter uses it for old ref' ' - cgit_query "url=foo/diff&id=master&id2=HEAD" >tmp && - grep "from:" tmp -' - -test_expect_success 'ref picker: to: shows master when id=master' ' - cgit_query "url=foo/diff&id=master" >tmp && - grep "master" tmp -' - -test_expect_success 'ref picker: from: preselects the to ref when no id2' ' - cgit_query "url=foo/diff" >tmp && - grep "<select name=.id2. onchange=.this.form.submit();.><option value=.master. selected=.selected.>master</option>" tmp -' - -test_expect_success 'from offset: one back when no id2' ' - grep "name=.id2off. title=.N commits back from the selected ref. value=.1.>" tmp -' - -test_expect_success 'to offset: empty when idoff unset' ' - grep "name=.idoff. title=.N commits back from the selected ref.>" tmp -' - -test_expect_success 'compare initial commit with HEAD' ' - root=$(git --git-dir="$PWD/repos/foo/.git" rev-list --max-parents=0 HEAD) && - cgit_query "url=foo/diff&id=HEAD&id2=$root" >tmp -' - -test_expect_success 'diff with HEAD and root shows content' ' - grep "diffstat" tmp -' - -test_expect_success 'flip link swaps explicit refs' ' - cgit_query "url=foo/diff&id=master&id2=HEAD" >tmp && - grep "/foo/diff/?id=HEAD&id2=master" tmp -' - -test_expect_success 'flip link omits id for a diff against a root commit' ' - root=$(git --git-dir="$PWD/repos/foo/.git" rev-list --max-parents=0 HEAD) && - cgit_query "url=foo/diff&id=$root" >tmp && - grep "href=./foo/diff/?id2=$root." tmp -' - -test_expect_success 'offset input: to: present' ' - grep "name=.idoff." tmp -' - -test_expect_success 'offset input: from: present' ' - grep "name=.id2off." tmp -' - -test_expect_success 'apply button present' ' - grep "value=.apply." tmp -' - -test_expect_success 'offset: idoff steps back the to ref' ' - cgit_query "url=foo/diff&id=master&idoff=1" >tmp && - grep "a/file-4 b/file-4" tmp -' - -test_expect_success 'offset: id2off steps back the from ref' ' - cgit_query "url=foo/diff&id=master&id2=master&id2off=2" >tmp && - grep "a/file-5 b/file-5" tmp -' - -test_expect_success 'offset: filled input and hidden field' ' - cgit_query "url=foo/diff&id=master&idoff=1" >tmp && - grep "title=.N commits back from the selected ref. value=.1.>" tmp && - grep "type=.hidden. name=.idoff. value=.1./>" tmp -' - -test_expect_success 'offset: too large 404s with the stepped rev' ' - cgit_query "url=foo/diff&id=master&id2=master&id2off=9" >tmp && - grep "Bad object name: master~9" tmp -' - -test_expect_success 'empty id2 does not 404' ' - cgit_query "url=foo/diff&id=master&id2=" >tmp && - grep "diffstat" tmp && - ! grep "Bad object name" tmp -' - -test_expect_success 'file link carries the offsets' ' - cgit_query "url=foo/diff&id=master&id2=master&id2off=2" >tmp && - grep "/foo/diff/file-5?id2=master&id2off=2" tmp -' - -test_expect_success 'flip link carries the offsets' ' - cgit_query "url=foo/diff&id=master&id2=master&idoff=1&id2off=2" >tmp && - grep "/foo/diff/?id2=master&idoff=2&id2off=1" tmp -' - -test_expect_success 'from ref: follows the stepped to ref' ' - cgit_query "url=foo/diff&id=master&idoff=2" >tmp && - grep "name=.id2off. title=.N commits back from the selected ref. value=.3.>" tmp && - grep "name=.idoff. title=.N commits back from the selected ref. value=.2.>" tmp -' - -test_expect_success 'from ref: shows the given offset' ' - cgit_query "url=foo/diff&id=master&id2=master&id2off=2" >tmp && - grep "name=.id2off. title=.N commits back from the selected ref. value=.2.>" tmp -' - -test_expect_success 'from ref: empty when the to ref is the root' ' - root=$(git --git-dir="$PWD/repos/foo/.git" rev-list --max-parents=0 HEAD) && - cgit_query "url=foo/diff&id=$root" >tmp && - grep "name=.id2off. title=.N commits back from the selected ref.>" tmp -' - test_done @@ -1,10 +1,6 @@ /* ui-diff.c: show diff between two blobs * * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com> - * Copyright (C) 2026 Saya Andy <saya.andy@posteo.com> - * - * Modified 2026 by Saya Andy: - * Select variable refs from web ui for diff * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -340,143 +336,16 @@ static void filepair_cb(struct diff_filepair *pair) cgit_ssdiff_footer(); } -static int print_ref_option(const struct reference *ref, void *cb_data) -{ - const char **sel = (const char **)cb_data; - - html_option(ref->name, ref->name, sel[0]); - return 0; -} - -static void cgit_print_ref_select(const char *name, const char *selected) -{ - /* - * Offer every branch and tag so that any two refs can be compared. - */ - html("<select name='"); - html_attr(name); - html("' onchange='this.form.submit();'>"); - refs_for_each_branch_ref(get_main_ref_store(the_repository), - print_ref_option, (void *)&selected); - if (ctx.repo->enable_remote_branches) - refs_for_each_remote_ref(get_main_ref_store(the_repository), - print_ref_option, (void *)&selected); - refs_for_each_tag_ref(get_main_ref_store(the_repository), - print_ref_option, (void *)&selected); - html("</select>"); -} - -/* - * The number of commits to step back from the selected ref, so that any - * ancestor of a branch or tag can be picked without typing a rev into - * the url by hand. - */ -static void cgit_print_ref_offset(const char *name, int value) -{ - html(" <input type='text' size='2' name='"); - html_attr(name); - html("' title='N commits back from the selected ref'"); - if (value) - htmlf(" value='%d'", value); - html("> <span class='hint'>back</span>"); -} - void cgit_print_diff_ctrls(void) { int i, curr; - html("<form class='diff-ctrls' method='get'>"); - /* - * Emit the same hidden fields as cgit_add_hidden_formfields(), except - * id/id2, which are carried by the ref-picker selects below. One - * form wraps both panels so any submission carries all controls. - */ - if (!ctx.cfg.virtual_root) { - struct strbuf url = STRBUF_INIT; - strbuf_addf(&url, "%s/%s", ctx.qry.repo, ctx.qry.page); - if (ctx.qry.vpath) - strbuf_addf(&url, "/%s", ctx.qry.vpath); - html_hidden("url", url.buf); - strbuf_release(&url); - } - if (ctx.qry.head && ctx.repo->defbranch && - strcmp(ctx.qry.head, ctx.repo->defbranch)) - html_hidden("h", ctx.qry.head); - if (ctx.qry.showmsg) - html_hidden("showmsg", "1"); - - html("<div class='cgit-panel'>"); - html("<b>diff refs</b>"); - html("<table>"); - html("<tr><td colspan='2'/></tr>"); - - /* ref pickers: compare any two refs (branches/tags) */ - { - const char *new_ref = ctx.qry.oid && *ctx.qry.oid ? - ctx.qry.oid : ctx.qry.head; - const char *old_ref = ctx.qry.oid2; - const char *disp_old_ref; - int idoff = ctx.qry.idoff; - int id2off = ctx.qry.id2off; - int disp_id2off; - - if (old_ref && *old_ref) { - disp_old_ref = old_ref; - disp_id2off = id2off; - } else if (!is_null_oid(old_rev_oid)) { - /* - * No from ref given: the diff compares the (stepped) - * to rev against its parent, i.e. new_ref~(idoff+1); - * show that instead of leaving the picker empty. Keep - * the ref name rather than a materialized parent sha. - */ - disp_old_ref = new_ref; - disp_id2off = idoff + 1; - } else { - /* to rev is the root: diff against the empty tree */ - disp_old_ref = NULL; - disp_id2off = 0; - } - - html("<tr>"); - html("<td class='label'>from:</td>"); - html("<td class='ctrl'>"); - cgit_print_ref_select("id2", disp_old_ref); - cgit_print_ref_offset("id2off", disp_id2off); - html("</td></tr><tr>"); - html("<td class='label'>to:</td>"); - html("<td class='ctrl'>"); - cgit_print_ref_select("id", new_ref); - cgit_print_ref_offset("idoff", ctx.qry.idoff); - html("</td></tr>"); - - html("<tr><td/><td class='ctrl'>"); - html("<input type='submit' value='apply'>"); - html(" | "); - /* - * The flip link swaps the displayed refs, so the displayed - * from ref becomes the to ref. cgit_diff_link() emits the - * offsets from ctx.qry; swap them around the call so they - * follow the refs. - */ - ctx.qry.idoff = disp_id2off; - ctx.qry.id2off = idoff; - cgit_diff_link("flip", "swap from and to", "button", - ctx.qry.head, - disp_old_ref, new_ref, - ctx.qry.path); - ctx.qry.idoff = idoff; - ctx.qry.id2off = id2off; - html("</td></tr>"); - } - html("</table>"); - html("</div>"); - html("<div class='cgit-panel'>"); html("<b>diff options</b>"); + html("<form method='get'>"); + cgit_add_hidden_formfields(1, 0, ctx.qry.page); html("<table>"); html("<tr><td colspan='2'/></tr>"); - html("<tr>"); html("<td class='label'>context:</td>"); html("<td class='ctrl'>"); @@ -510,8 +379,8 @@ void cgit_print_diff_ctrls(void) html("<tr><td/><td class='ctrl'>"); html("<noscript><input type='submit' value='reload'/></noscript>"); html("</td></tr></table>"); - html("</div>"); html("</form>"); + html("</div>"); } void cgit_print_diff(const char *new_rev, const char *old_rev, @@ -519,7 +388,6 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, { struct commit *commit, *commit2; const struct object_id *old_tree_oid, *new_tree_oid; - struct strbuf new_refbuf = STRBUF_INIT, old_refbuf = STRBUF_INIT; diff_type difftype; /* @@ -534,16 +402,8 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, current_prefix = NULL; } - /* - * An empty rev is the same as no rev; a zero offset means the ref - * itself. - */ - if (!new_rev || !*new_rev) + if (!new_rev) new_rev = ctx.qry.head; - if (ctx.qry.idoff) { - strbuf_addf(&new_refbuf, "%s~%d", new_rev, ctx.qry.idoff); - new_rev = new_refbuf.buf; - } if (repo_get_oid(the_repository, new_rev, new_rev_oid)) { cgit_print_error_page(404, "Not found", "Bad object name: %s", new_rev); @@ -557,12 +417,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, } new_tree_oid = get_commit_tree_oid(commit); - if (old_rev && *old_rev) { - if (ctx.qry.id2off) { - strbuf_addf(&old_refbuf, "%s~%d", old_rev, - ctx.qry.id2off); - old_rev = old_refbuf.buf; - } + if (old_rev) { if (repo_get_oid(the_repository, old_rev, old_rev_oid)) { cgit_print_error_page(404, "Not found", "Bad object name: %s", old_rev); diff --git a/ui-shared.c b/ui-shared.c index 9eb48a9..97d1839 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -7,8 +7,6 @@ * 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) @@ -494,21 +492,6 @@ void cgit_diff_link(const char *name, const char *title, const char *class, html_url_arg(old_rev); delim = "&"; } - /* - * Emit the ref offsets after the refs so that they follow the - * refs through file-level links; a zero offset means the ref - * itself. - */ - if (ctx.qry.idoff) { - html(delim); - htmlf("idoff=%d", ctx.qry.idoff); - delim = "&"; - } - if (ctx.qry.id2off) { - html(delim); - htmlf("id2off=%d", ctx.qry.id2off); - delim = "&"; - } if (ctx.qry.difftype) { html(delim); htmlf("dt=%d", ctx.qry.difftype); @@ -791,51 +774,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='"); @@ -877,27 +815,6 @@ static int emit_js_link(struct string_list_item *s, void *arg) 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(); @@ -928,12 +845,11 @@ void cgit_print_docstart(void) 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"); - + if (ctx.cfg.favicon && *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; @@ -1066,10 +982,6 @@ void cgit_add_hidden_formfields(int incl_head, int incl_search, html_hidden("id", ctx.qry.oid); if (ctx.qry.oid2) html_hidden("id2", ctx.qry.oid2); - if (ctx.qry.idoff) - html_hidden("idoff", fmt("%d", ctx.qry.idoff)); - if (ctx.qry.id2off) - html_hidden("id2off", fmt("%d", ctx.qry.id2off)); if (ctx.qry.showmsg) html_hidden("showmsg", "1"); |