diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Add stable markup hooks for site themes
Diffstat (limited to 'source')
| -rw-r--r-- | source/ui-blame.c | 4 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-commit.c | 12 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-diff.c | 71 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-log.c | 41 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-refs.c | 29 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-repolist.c | 17 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-shared.c | 51 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-ssdiff.c | 11 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-ssdiff.h | 7 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-stats.c | 25 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-summary.c | 20 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-tag.c | 10 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-tree.c | 32 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
13 files changed, 194 insertions, 136 deletions
diff --git a/source/ui-blame.c b/source/ui-blame.c index c020dbc..5d88f94 100644 --- a/source/ui-blame.c +++ b/source/ui-blame.c @@ -294,11 +294,11 @@ static void print_blame_page(const struct object_id *oid, const char *path, cgit_set_title_from_path(path); cgit_print_layout_start(); - htmlf("blob: %s (", oid_to_hex(oid)); + htmlf("<div class='blob-header'>blob: %s (", oid_to_hex(oid)); cgit_plain_link("plain", NULL, NULL, ctx.qry.head, rev, path); html(") ("); cgit_tree_link("tree", NULL, NULL, ctx.qry.head, rev, path); - html(")\n"); + html(")</div>\n"); // A NUL past the window buffer_is_binary sniffs would end html_txt // early while the hash and line number columns still cover the whole diff --git a/source/ui-commit.c b/source/ui-commit.c index 1fdc5fa..1ac96aa 100644 --- a/source/ui-commit.c +++ b/source/ui-commit.c @@ -31,7 +31,7 @@ static void print_ident_row(const char *role, const char *name, const char *email, timestamp_t date, int tz) { - htmlf("<tr><th>%s</th><td>", role); + htmlf("<tr><th scope='row'>%s</th><td>", role); cgit_open_filter(ctx.repo->email_filter, email ? email : "", "commit"); html_txt(name); if (ctx.cfg.enable_plain_email) { @@ -69,7 +69,7 @@ static int print_parent_rows(struct commit *commit, const char *rev, const char } if (!parents) oidcpy(first, &p->item->object.oid); - html("<tr><th>parent</th><td colspan='2' class='oid'><div class='spanning'>"); + html("<tr><th scope='row'>parent</th><td colspan='2' class='oid'><div class='spanning'>"); parent_hex = label = oid_to_hex(&p->item->object.oid); info = ctx.repo->enable_subject_links ? cgit_parse_commit(parent) : NULL; if (info) @@ -178,7 +178,7 @@ static void print_trailers(const char *msg) html("</td></tr>\n"); strbuf_reset(&key); strbuf_addbuf(&key, &iter.key); - html("<tr><th>"); + html("<tr><th scope='row'>"); html_txt(key.buf); html("</th><td>"); open = 1; @@ -279,7 +279,7 @@ void cgit_print_commit(char *hex, const char *prefix) // The spanning cells are kept out of the column widths, so a hash row // never pushes the dates away from the names above it. - html("<tr><th>commit</th><td colspan='2' class='oid'><div class='spanning'>"); + html("<tr><th scope='row'>commit</th><td colspan='2' class='oid'><div class='spanning'>"); commit_hex = oid_to_hex(&commit->object.oid); cgit_commit_link(commit_hex, NULL, NULL, ctx.qry.head, commit_hex, prefix); html(" ("); @@ -290,7 +290,7 @@ void cgit_print_commit(char *hex, const char *prefix) // together, leaving the tree beside the download links. parents = print_parent_rows(commit, hex, prefix, &first_oid); - html("<tr><th>tree</th><td colspan='2' class='oid'><div class='spanning'>"); + html("<tr><th scope='row'>tree</th><td colspan='2' class='oid'><div class='spanning'>"); tree_rev = xstrdup(hex); cgit_tree_link(oid_to_hex(get_commit_tree_oid(commit)), NULL, NULL, ctx.qry.head, tree_rev, NULL); if (prefix) { @@ -301,7 +301,7 @@ void cgit_print_commit(char *hex, const char *prefix) html("</div></td></tr>\n"); if (ctx.repo->snapshots) { - html("<tr><th>download</th><td colspan='2' class='oid'><div class='spanning'>"); + html("<tr><th scope='row'>download</th><td colspan='2' class='oid'><div class='spanning'>"); cgit_print_snapshot_links(ctx.repo, hex, "<br>"); html("</div></td></tr>\n"); } diff --git a/source/ui-diff.c b/source/ui-diff.c index f258e9f..5c9cd1c 100644 --- a/source/ui-diff.c +++ b/source/ui-diff.c @@ -234,6 +234,13 @@ static void print_file_header(const struct object_id *old_oid, char *old_path, u int subproject; subproject = (S_ISGITLINK(old_mode) || S_ISGITLINK(new_mode)); + // The side by side view opens its file group before the header row, + // so only the unified view opens one here. + if (!use_ssdiff) { + html("<div class='file' data-path='"); + html_attr(new_path); + html("'>"); + } html("<div class='head'>"); html("diff --git a/"); html_txt(old_path); @@ -282,6 +289,20 @@ static void print_file_header(const struct object_id *old_oid, char *old_path, u } /* + * Closes the group print_file_header or cgit_ssdiff_header_begin opened. The + * side by side footer closes its own, so the unified view is the only one with + * work to do here. + */ +static void end_file(void) +{ + // The unified table keeps its whitespace, so no newline follows. + if (use_ssdiff) + cgit_ssdiff_footer(); + else + html("</div>"); +} + +/* * The length passed counts the terminator, because a renderer strips the last * byte of every line it is given. */ @@ -315,12 +336,11 @@ static void print_truncated(const char *path) cgit_diff_link("View it on its own page", NULL, NULL, ctx.qry.head, ctx.qry.oid, ctx.qry.oid2, path); html("."); - if (use_ssdiff) { + if (use_ssdiff) html("</td></tr>"); - cgit_ssdiff_footer(); - } else { + else html("</div>"); - } + end_file(); } static struct fileinfo *reserve_item(void) @@ -353,7 +373,7 @@ static void collect_body(struct diff_filepair *pair, struct fileinfo *item, int html_capture_begin(body); if (use_ssdiff) - cgit_ssdiff_header_begin(); + cgit_ssdiff_header_begin(pair->two->path); print_file_header(&pair->one->oid, pair->one->path, pair->one->mode, &pair->two->oid, pair->two->path, pair->two->mode); if (use_ssdiff) @@ -383,8 +403,7 @@ static void collect_body(struct diff_filepair *pair, struct fileinfo *item, int if (*binary) print_binary_differs(); } - if (use_ssdiff) - cgit_ssdiff_footer(); + end_file(); if (render_suppressed) { // Setting the length back would keep the grown allocation, @@ -491,7 +510,7 @@ static void filepair_cb(struct diff_filepair *pair) idx = item_idx++; current_filepair = pair; if (use_ssdiff) { - cgit_ssdiff_header_begin(); + cgit_ssdiff_header_begin(pair->two->path); line_fn = cgit_ssdiff_line_cb; } print_file_header(&pair->one->oid, pair->one->path, pair->one->mode, @@ -505,8 +524,7 @@ static void filepair_cb(struct diff_filepair *pair) } if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { print_subproject_lines(pair, line_fn); - if (use_ssdiff) - cgit_ssdiff_footer(); + end_file(); return; } if (cgit_diff_files(&pair->one->oid, &pair->two->oid, &old_size, &new_size, @@ -514,8 +532,7 @@ static void filepair_cb(struct diff_filepair *pair) cgit_print_error("Error running diff"); if (binary) print_binary_differs(); - if (use_ssdiff) - cgit_ssdiff_footer(); + end_file(); } static void print_raw_patch(const struct object_id *old_tree_oid, const struct object_id *new_tree_oid) @@ -553,14 +570,11 @@ void cgit_print_diff_ctrls(void) html("<div class='cgit-panel'>\n"); html("<strong>diff options</strong>"); - html("<form method='get'>"); + html("<form method='get' aria-label='Diff options'>"); cgit_add_hidden_formfields(1, 0, ctx.qry.page); - html("<table>"); - html("<tr><td colspan='2'></td></tr>"); - html("<tr>"); - html("<td class='label'>context:</td>"); - html("<td class='ctrl'>"); - html("<select name='context'>"); + html("<div class='fields'>"); + html("<label for='diff-context'>context:</label>"); + html("<select id='diff-context' name='context'>"); selected = ctx.qry.context; if (!selected) selected = DEFAULT_DIFF_CONTEXT; @@ -569,27 +583,20 @@ void cgit_print_diff_ctrls(void) for (i = 15; i <= MAX_DIFF_CONTEXT_LINES; i += 5) html_intoption(i, cgit_fmt("%d", i), selected); html("</select>"); - html("</td>"); - html("</tr><tr>"); - html("<td class='label'>space:</td>"); - html("<td class='ctrl'>"); - html("<select name='ignorews'>"); + html("<label for='diff-space'>space:</label>"); + html("<select id='diff-space' name='ignorews'>"); html_intoption(0, "include", ctx.qry.ignorews); html_intoption(1, "ignore", ctx.qry.ignorews); html("</select>"); - html("</td>"); - html("</tr><tr>"); - html("<td class='label'>mode:</td>"); - html("<td class='ctrl'>"); - html("<select name='dt'>"); + html("<label for='diff-mode'>mode:</label>"); + html("<select id='diff-mode' name='dt'>"); selected = ctx.qry.has_difftype ? ctx.qry.difftype : ctx.cfg.difftype; html_intoption(0, "unified", selected); html_intoption(1, "ssdiff", selected); html_intoption(2, "stat only", selected); - html("</select></td></tr>"); - html("<tr><td></td><td class='ctrl'>"); + html("</select>"); html("<input type='submit' value='reload'>"); - html("</td></tr></table>"); + html("</div>"); html("</form>\n"); html("</div>\n"); } diff --git a/source/ui-log.c b/source/ui-log.c index 86cb756..9f21114 100644 --- a/source/ui-log.c +++ b/source/ui-log.c @@ -227,7 +227,7 @@ static void print_commit(struct commit *commit, struct rev_info *revs) print_graph_above(revs, &graphbuf, columns); info = cgit_parse_commit(commit); - htmlf("<tr%s>", ctx.qry.showmsg ? " class='logheader'" : ""); + htmlf("<tr class='commit%s'>", ctx.qry.showmsg ? " logheader" : ""); if (revs->graph) { html("<td class='commitgraph'>"); @@ -372,11 +372,11 @@ static void print_pager(struct rev_info *revs, int ofs, int cnt) { struct commit *more = get_revision(revs); - html("</table>\n"); + html("</tbody>\n</table>\n"); // A single page needs no pager, and an empty list has nothing to page. if (ofs <= 0 && !more) return; - html("<ul class='pager'>"); + html("<nav class='pager' aria-label='Pager'><ul>"); if (ofs > 0) { html("<li>"); cgit_log_link( @@ -393,7 +393,7 @@ static void print_pager(struct rev_info *revs, int ofs, int cnt) ); html("</li>"); } - html("</ul>"); + html("</ul></nav>"); } /* @@ -562,15 +562,15 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern if (pager) { cgit_print_layout_start(); - html("<table class='list'>\n"); + html("<table class='list log' aria-label='Commits'>\n"); } - html("<tr class='nohover'>"); + html("<tbody class='log'>\n<tr class='nohover'>"); if (commit_graph) html("<th></th>"); else - html("<th class='left'>Age</th>"); - html("<th class='left'>Commit message"); + html("<th class='left' scope='col'>Age</th>"); + html("<th class='left' scope='col'>Commit message"); if (pager) { html(" ("); cgit_log_link( @@ -580,15 +580,15 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern ); html(")"); } - html("</th><th class='left col-author'>Author</th>"); + html("</th><th class='left col-author' scope='col'>Author</th>"); if (rev.graph) - html("<th class='left'>Age</th>"); + html("<th class='left' scope='col'>Age</th>"); if (ctx.repo->enable_log_filecount) { - html("<th class='left col-count'>Files</th>"); + html("<th class='left col-count' scope='col'>Files</th>"); columns++; } if (ctx.repo->enable_log_linecount) { - html("<th class='left col-count'>Lines</th>"); + html("<th class='left col-count' scope='col'>Lines</th>"); columns++; } html("</tr>\n"); @@ -617,13 +617,16 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern if (pager) { print_pager(&rev, ofs, cnt); cgit_print_layout_end(); - } else if ((commit = get_revision(&rev))) { - htmlf("<tr class='nohover'><td colspan='%d'>", columns); - cgit_log_link( - "[...]", NULL, NULL, ctx.qry.head, NULL, ctx.qry.vpath, 0, - NULL, NULL, ctx.qry.showmsg, ctx.qry.follow - ); - html("</td></tr>\n"); + } else { + if ((commit = get_revision(&rev))) { + htmlf("<tr class='nohover'><td colspan='%d'>", columns); + cgit_log_link( + "[...]", NULL, NULL, ctx.qry.head, NULL, ctx.qry.vpath, 0, + NULL, NULL, ctx.qry.showmsg, ctx.qry.follow + ); + html("</td></tr>\n"); + } + html("</tbody>\n"); } if (must_free_tip) diff --git a/source/ui-refs.c b/source/ui-refs.c index d89e3ea..e4a0dd0 100644 --- a/source/ui-refs.c +++ b/source/ui-refs.c @@ -79,10 +79,11 @@ static void collect_branches(struct reflist *list) static void print_branch_header(void) { html( - "<tr class='nohover'><th class='left'>Branch</th>" - "<th class='left'>Commit message</th>" - "<th class='left col-author'>Author</th>" - "<th colspan='2' class='left'>Age</th></tr>\n" + "<tbody class='branches'>\n" + "<tr class='nohover'><th class='left' scope='col'>Branch</th>" + "<th class='left' scope='col'>Commit message</th>" + "<th class='left col-author' scope='col'>Author</th>" + "<th colspan='2' class='left' scope='col'>Age</th></tr>\n" ); } @@ -93,7 +94,7 @@ static int print_branch(struct refinfo *ref) if (!info) return 1; - html("<tr><td>"); + html("<tr class='branch'><td>"); cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0, NULL, NULL, ctx.qry.showmsg, 0); html("</td><td>"); @@ -128,10 +129,11 @@ static void collect_tags(struct reflist *list) static void print_tag_header(void) { html( - "<tr class='nohover'><th class='left'>Tag</th>" - "<th class='left'>Download</th>" - "<th class='left col-author'>Author</th>" - "<th colspan='2' class='left'>Age</th></tr>\n" + "<tbody class='tags'>\n" + "<tr class='nohover'><th class='left' scope='col'>Tag</th>" + "<th class='left' scope='col'>Download</th>" + "<th class='left col-author' scope='col'>Author</th>" + "<th colspan='2' class='left' scope='col'>Age</th></tr>\n" ); } @@ -152,7 +154,7 @@ static int print_tag(struct refinfo *ref) return 1; } - html("<tr><td>"); + html("<tr class='tag'><td>"); cgit_tag_link(name, NULL, NULL, name); html("</td><td>"); if (ctx.repo->snapshots && (obj->type == OBJ_COMMIT)) @@ -255,6 +257,7 @@ static void print_branches_page(int pagesize) if (page.size < list.count) print_ref_pager(page.start, page.size, list.count, "heads"); + html("</tbody>\n"); cgit_free_reflist_inner(&list); } @@ -278,6 +281,7 @@ static void print_tags_page(int pagesize) if (page.size < list.count) print_ref_pager(page.start, page.size, list.count, "tags"); + html("</tbody>\n"); cgit_free_reflist_inner(&list); } @@ -305,6 +309,7 @@ void cgit_print_branches(int maxcount) if (maxcount < list.count) print_refs_link("heads"); + html("</tbody>\n"); cgit_free_reflist_inner(&list); } @@ -328,6 +333,7 @@ void cgit_print_tags(int maxcount) if (maxcount < list.count) print_refs_link("tags"); + html("</tbody>\n"); cgit_free_reflist_inner(&list); } @@ -335,7 +341,7 @@ void cgit_print_tags(int maxcount) void cgit_print_refs(void) { cgit_print_layout_start(); - html("<table class='list'>\n"); + html("<table class='list refs' aria-label='Branches and tags'>\n"); if (ctx.qry.path && starts_with(ctx.qry.path, "heads")) { print_branches_page(ctx.cfg.max_ref_count); @@ -343,7 +349,6 @@ void cgit_print_refs(void) print_tags_page(ctx.cfg.max_ref_count); } else { cgit_print_branches(ctx.cfg.max_ref_count); - html("<tr class='nohover'><td colspan='5'></td></tr>\n"); cgit_print_tags(ctx.cfg.max_ref_count); } html("</table>\n"); diff --git a/source/ui-repolist.c b/source/ui-repolist.c index 031cb0d..6dcc976 100644 --- a/source/ui-repolist.c +++ b/source/ui-repolist.c @@ -181,7 +181,7 @@ static int any_repos_visible(void) */ static void print_column_header(const char *title, const char *column, const char *currenturl) { - htmlf("<th class='left col-%s'><a href='", column); + htmlf("<th class='left col-%s' scope='col'><a href='", column); html_attr(currenturl); htmlf("?s=%s", column); if (ctx.qry.search) { @@ -193,14 +193,14 @@ static void print_column_header(const char *title, const char *column, const cha static void print_header_row(const char *currenturl) { - html("<tr class='nohover'>"); + html("<tbody class='repos'>\n<tr class='nohover'>"); print_column_header("Name", "name", currenturl); print_column_header("Description", "desc", currenturl); if (ctx.cfg.enable_index_owner) print_column_header("Owner", "owner", currenturl); print_column_header("Idle", "idle", currenturl); if (ctx.cfg.enable_index_links) - html("<th class='left col-links'>Links</th>"); + html("<th class='left col-links' scope='col'>Links</th>"); html("</tr>\n"); } @@ -224,7 +224,8 @@ static void print_repo_row(const char *currenturl, int sublevel) { char *repourl; - htmlf("<tr><td class='col-name %s'>", sublevel ? "sublevel-repo" : "toplevel-repo"); + htmlf("<tr class='repo'><td class='col-name %s'>", + sublevel ? "sublevel-repo" : "toplevel-repo"); cgit_summary_link(ctx.repo->name, NULL, NULL, NULL); html("</td><td class='col-desc'>"); repourl = cgit_repourl(ctx.repo->url); @@ -267,7 +268,7 @@ static void print_pager(int total, int pagelen, char *search, char *sort) int i, ofs; char *class; - html("<ul class='pager'>\n"); + html("<nav class='pager' aria-label='Pager'><ul>\n"); for (i = 0, ofs = 0; ofs < total; i++, ofs = i * pagelen) { class = (ctx.qry.ofs == ofs) ? "current" : NULL; html("<li>"); @@ -275,7 +276,7 @@ static void print_pager(int total, int pagelen, char *search, char *sort) ofs, 0); html("</li>"); } - html("</ul>\n"); + html("</ul></nav>\n"); } static int cmp_str(const char *s1, const char *s2) @@ -420,7 +421,7 @@ void cgit_print_repolist(void) sort_repolist("section"); currenturl = cgit_currenturl(); - html("<table class='list repolist'>\n"); + html("<table class='list repolist' aria-label='Repositories'>\n"); for (i = 0; i < cgit_repolist.count; i++) { char *section; @@ -448,6 +449,8 @@ void cgit_print_repolist(void) } print_repo_row(currenturl, !column_sorted && section); } + if (shown) + html("</tbody>\n"); html("</table>\n"); if (hits > ctx.cfg.max_repo_count) print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search, ctx.qry.sort); diff --git a/source/ui-shared.c b/source/ui-shared.c index 4417975..0f2f1e3 100644 --- a/source/ui-shared.c +++ b/source/ui-shared.c @@ -104,6 +104,22 @@ static void site_url(const char *page, const char *search, const char *sort, int } } +/* + * Write the class of a link, and mark the link as the current one for + * assistive technology when the class says it is the active tab or the + * current page of a pager. + */ +static void link_class(const char *class) +{ + if (!class) + return; + html(" class='"); + html_attr(class); + html("'"); + if (!strcmp(class, "active") || !strcmp(class, "current")) + html(" aria-current='page'"); +} + static void site_link(const char *page, const char *name, const char *title, const char *class, const char *search, const char *sort, int ofs, int always_root) { @@ -113,11 +129,7 @@ static void site_link(const char *page, const char *name, const char *title, html_attr(title); html("'"); } - if (class) { - html(" class='"); - html_attr(class); - html("'"); - } + link_class(class); html(" href='"); site_url(page, search, sort, ofs, always_root); html("'>"); @@ -142,11 +154,7 @@ static const char *repolink(const char *title, const char *class, const char *pa html_attr(title); html("'"); } - if (class) { - html(" class='"); - html_attr(class); - html("'"); - } + link_class(class); html(" href='"); if (ctx.cfg.virtual_root) { html_url_path(ctx.cfg.virtual_root); @@ -631,7 +639,7 @@ static void print_repo_tabs(void) static void print_repo_search(void) { - html("<form class='search' method='get' action='"); + html("<form class='search' role='search' method='get' action='"); if (ctx.cfg.virtual_root) { char *fileurl = cgit_fileurl(ctx.qry.repo, "log", ctx.qry.vpath, NULL); html_url_path(fileurl); @@ -669,7 +677,7 @@ static void print_site_search(void) { char *currenturl = cgit_currenturl(); - html("<form class='search' method='get' action='"); + html("<form class='search' role='search' method='get' action='"); html_attr(currenturl); html("'>\n"); html("<input class='txt' type='search' name='q' aria-label='Search' value='"); @@ -1703,12 +1711,27 @@ void cgit_print_pageheader(void) { const struct object_id *pinned; - html("<div id='cgit'>\n"); + // The root names the page and the repository so a stylesheet or script + // can tell them apart without reading the tabs. + html("<div id='cgit'"); + if (ctx.cfg.embedded) + html(" class='cgit-embedded'"); + if (ctx.qry.page) { + html(" data-page='"); + html_attr(ctx.qry.page); + html("'"); + } + if (ctx.repo) { + html(" data-repo='"); + html_attr(ctx.repo->url); + html("'"); + } + html(">\n"); if (!ctx.env.authenticated || ctx.cfg.enable_header) print_header(); if (ctx.env.authenticated) - html("<nav class='tabs'>\n"); + html("<nav class='tabs' aria-label='Pages'>\n"); if (ctx.env.authenticated && ctx.repo && ctx.empty_repo) { // Every other tab needs a commit to render and the search form // has nothing to search, so an empty repo gets summary alone. diff --git a/source/ui-ssdiff.c b/source/ui-ssdiff.c index ad543f4..afa25ea 100644 --- a/source/ui-ssdiff.c +++ b/source/ui-ssdiff.c @@ -201,7 +201,7 @@ static void print_row(const char *class, int old_line_no, char *old_line, } else if (old_line) { htmlf("<td class='lineno'></td><td class='%s'>", class); } else { - htmlf("<td class='lineno'></td><td class='%s_dark'>", class); + htmlf("<td class='lineno'></td><td class='%s-dark'>", class); } if (old_line) { if (lcs) @@ -217,7 +217,7 @@ static void print_row(const char *class, int old_line_no, char *old_line, } else if (new_line) { htmlf("<td class='lineno'></td><td class='%s'>", class); } else { - htmlf("<td class='lineno'></td><td class='%s_dark'>", class); + htmlf("<td class='lineno'></td><td class='%s-dark'>", class); } if (new_line) { if (lcs) @@ -401,10 +401,13 @@ void cgit_ssdiff_line_cb(char *line, int len) line[len - 1] = terminator; } -void cgit_ssdiff_header_begin(void) +void cgit_ssdiff_header_begin(const char *path) { current_old_line = -1; current_new_line = -1; + html("<tbody class='file' data-path='"); + html_attr(path); + html("'>\n"); html("<tr><td class='space' colspan='4'></td></tr>\n"); html("<tr><td class='head' colspan='4'>"); } @@ -417,5 +420,5 @@ void cgit_ssdiff_header_end(void) void cgit_ssdiff_footer(void) { print_deferred_lines(); - html("<tr><td class='foot' colspan='4'></td></tr>\n"); + html("<tr><td class='foot' colspan='4'></td></tr>\n</tbody>\n"); } diff --git a/source/ui-ssdiff.h b/source/ui-ssdiff.h index f6489c8..9417277 100644 --- a/source/ui-ssdiff.h +++ b/source/ui-ssdiff.h @@ -22,9 +22,12 @@ extern void cgit_ssdiff_line_cb(char *line, int len); -extern void cgit_ssdiff_header_begin(void); +/* + * Open the group of rows one file's diff occupies, header row included, and + * close it again after the last line. path lands on the group as data-path. + */ +extern void cgit_ssdiff_header_begin(const char *path); extern void cgit_ssdiff_header_end(void); - extern void cgit_ssdiff_footer(void); #endif // CGIT_UI_SSDIFF_H diff --git a/source/ui-stats.c b/source/ui-stats.c index 3960b14..55ed370 100644 --- a/source/ui-stats.c +++ b/source/ui-stats.c @@ -332,10 +332,10 @@ static void print_authors(struct string_list *authors, int max_rows, const struc size_t i, column, rows; long total; - html("<table class='stats'>\n<tr><th>Author</th>"); + html("<table class='stats'>\n<tr><th scope='col'>Author</th>"); for (column = 0; column < labels->nr; column++) - htmlf("<th>%s</th>", labels->items[column].string); - html("<th>Total</th></tr>\n"); + htmlf("<th scope='col'>%s</th>", labels->items[column].string); + html("<th scope='col'>Total</th></tr>\n"); // The row count arrives through ofs, which carries -1 for "all". rows = (max_rows <= 0 || (size_t)max_rows > authors->nr) ? authors->nr : (size_t)max_rows; @@ -375,29 +375,28 @@ static void print_options_form(const struct cgit_period *period, int top) html("<div class='cgit-panel'>\n"); html("<strong>stat options</strong>"); - html("<form method='get'>"); + html("<form method='get' aria-label='Stat options'>"); cgit_add_hidden_formfields(1, 0, "stats"); - html("<table><tr><td colspan='2'></td></tr>\n"); + html("<div class='fields'>"); if (ctx.repo->max_stats > 1) { choices = ctx.repo->max_stats; - html("<tr><td class='label'>Period:</td>"); - html("<td class='ctrl'><select name='period'>"); + html("<label for='stats-period'>Period:</label>"); + html("<select id='stats-period' name='period'>"); for (i = 0; i < choices; i++) html_option(cgit_fmt("%c", periods[i].code), periods[i].name, cgit_fmt("%c", period->code)); - html("</select></td></tr>\n"); + html("</select>\n"); } - html("<tr><td class='label'>Authors:</td>"); - html("<td class='ctrl'><select name='ofs'>"); + html("<label for='stats-authors'>Authors:</label>"); + html("<select id='stats-authors' name='ofs'>"); html_intoption(10, "10", top); html_intoption(25, "25", top); html_intoption(50, "50", top); html_intoption(100, "100", top); html_intoption(-1, "all", top); - html("</select></td></tr>\n"); - html("<tr><td></td><td class='ctrl'>"); + html("</select>\n"); html("<input type='submit' value='reload'>"); - html("</td></tr></table>"); + html("</div>"); html("</form>\n"); html("</div>\n"); } diff --git a/source/ui-summary.c b/source/ui-summary.c index 0b33a96..eb04ecd 100644 --- a/source/ui-summary.c +++ b/source/ui-summary.c @@ -44,8 +44,9 @@ static void print_clone_url(const char *url) // cgit_add_clone_urls may call back no times at all, so the heading // waits for a first url rather than being printed ahead of the walk. if (clone_urls_printed++ == 0) { - htmlf("<tr class='nohover'><td colspan='%d'></td></tr>\n", columns); - htmlf("<tr class='nohover'><th colspan='%d' class='left'>Clone</th></tr>\n", columns); + html("<tbody class='clone'>\n"); + htmlf("<tr class='nohover'><th colspan='%d' class='left' scope='col'>Clone</th></tr>\n", + columns); } cgit_print_clone_row(url, columns); @@ -113,19 +114,18 @@ static char *resolve_about_path(const char *filename, const char *ref, const cha void cgit_print_summary(void) { - int columns = log_columns(); - cgit_print_layout_start(); - html("<table class='list'>\n"); + // One table, so the columns line up across the sections, each of + // which is a body of its own. + html("<table class='list summary' aria-label='Summary'>\n"); cgit_print_branches(ctx.cfg.summary_branches); - htmlf("<tr class='nohover'><td colspan='%d'></td></tr>\n", columns); cgit_print_tags(ctx.cfg.summary_tags); - if (ctx.cfg.summary_log > 0) { - htmlf("<tr class='nohover'><td colspan='%d'></td></tr>\n", columns); + if (ctx.cfg.summary_log > 0) cgit_print_log(ctx.qry.head, 0, ctx.cfg.summary_log, NULL, NULL, NULL, 0, 0, 0); - } clone_urls_printed = 0; cgit_add_clone_urls(print_clone_url); + if (clone_urls_printed) + html("</tbody>\n"); html("</table>\n"); cgit_print_layout_end(); } @@ -159,7 +159,7 @@ void cgit_print_repo_readme(const char *path) goto done; } - html("<div id='summary'>"); + html("<div id='about'>"); if (!ctx.repo->about_filter) { // With no about-filter there is nothing to turn the readme // into safe HTML, so it is escaped rather than served raw. diff --git a/source/ui-tag.c b/source/ui-tag.c index 6811e0c..559cb54 100644 --- a/source/ui-tag.c +++ b/source/ui-tag.c @@ -19,7 +19,7 @@ static void print_name_row(const char *revname, const struct object_id *oid) { - html("<tr><th>tag name</th><td>"); + html("<tr><th scope='row'>tag name</th><td>"); html_txt(revname); if (oid) htmlf(" (<span class='oid'>%s</span>)", oid_to_hex(oid)); @@ -28,7 +28,7 @@ static void print_name_row(const char *revname, const struct object_id *oid) static void print_date_row(struct taginfo *info) { - html("<tr><th>tag date</th><td><time datetime='"); + html("<tr><th scope='row'>tag date</th><td><time datetime='"); html_attr(show_date(info->tagger_date, info->tagger_tz, cgit_date_mode(DATE_ISO8601_STRICT))); html("'>"); html_txt(show_date(info->tagger_date, info->tagger_tz, cgit_date_mode(DATE_ISO8601))); @@ -37,7 +37,7 @@ static void print_date_row(struct taginfo *info) static void print_tagger_row(struct taginfo *info) { - html("<tr><th>tagged by</th><td>"); + html("<tr><th scope='row'>tagged by</th><td>"); // A tag can carry a tagger with no address, and a filter must not be // handed a NULL argument. cgit_open_filter(ctx.repo->email_filter, info->tagger_email ? info->tagger_email : "", "tag"); @@ -52,14 +52,14 @@ static void print_tagger_row(struct taginfo *info) static void print_object_row(struct object *obj) { - html("<tr><th>tagged object</th><td class='oid'>"); + html("<tr><th scope='row'>tagged object</th><td class='oid'>"); cgit_object_link(obj, 1); html("</td></tr>\n"); } static void print_download_row(const char *revname) { - html("<tr><th>download</th><td class='oid'>"); + html("<tr><th scope='row'>download</th><td class='oid'>"); cgit_print_snapshot_links(ctx.repo, revname, "<br>"); html("</td></tr>\n"); } diff --git a/source/ui-tree.c b/source/ui-tree.c index 4d829fe..5b0cdea 100644 --- a/source/ui-tree.c +++ b/source/ui-tree.c @@ -197,13 +197,13 @@ static bool print_object(const struct object_id *oid, const char *path, cgit_set_title_from_path(path); cgit_print_layout_start(); - htmlf("blob: %s (", oid_to_hex(oid)); + htmlf("<div class='blob-header'>blob: %s (", oid_to_hex(oid)); cgit_plain_link("plain", NULL, NULL, ctx.qry.head, rev, path); if (ctx.repo->enable_blame && !is_binary) { html(") ("); cgit_blame_link("blame", NULL, NULL, ctx.qry.head, rev, path); } - html(")\n"); + html(")</div>\n"); if (is_binary) print_binary_buffer(buf, size); @@ -300,7 +300,14 @@ static void print_ls_row(const struct object_id *oid, const char *pathname, } } - html("<tr><td class='ls-mode'>"); + if (S_ISGITLINK(mode)) + html("<tr class='mod'><td class='ls-mode'>"); + else if (S_ISDIR(mode)) + html("<tr class='dir'><td class='ls-mode'>"); + else if (S_ISLNK(mode)) + html("<tr class='link'><td class='ls-mode'>"); + else + html("<tr class='blob'><td class='ls-mode'>"); cgit_print_filemode(mode); html("</td><td>"); if (S_ISGITLINK(mode)) { @@ -309,9 +316,14 @@ static void print_ls_row(const struct object_id *oid, const char *pathname, print_dir_chain(oid, name, walk->rev, &fullpath); } else { char *ext = strrchr(name, '.'); + strbuf_addstr(&class, "ls-blob"); - if (ext) - strbuf_addf(&class, " %s", ext + 1); + // The extension becomes a class a stylesheet can pick files out + // by, prefixed so that a name such as x.button cannot land on a + // class of the theme's own. + if (ext && ext[1] && strspn(ext + 1, "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-") == strlen(ext + 1)) + strbuf_addf(&class, " ext-%s", ext + 1); cgit_tree_link(name, NULL, class.buf, ctx.qry.head, walk->rev, fullpath.buf); } // A target longer than any path is no link, and reading it would pull @@ -404,18 +416,18 @@ static void ls_flush(struct walk_tree_context *walk) static void ls_head(void) { cgit_print_layout_start(); - html("<table class='list'>\n"); + html("<table class='list tree' aria-label='Files'>\n<tbody class='tree'>\n"); html("<tr class='nohover'>"); - html("<th class='left ls-mode'>Mode</th>"); - html("<th class='left'>Name</th>"); - html("<th class='right'>Size</th>"); + html("<th class='left ls-mode' scope='col'>Mode</th>"); + html("<th class='left' scope='col'>Name</th>"); + html("<th class='right' scope='col'>Size</th>"); html("<th class='ls-links'></th>"); html("</tr>\n"); } static void ls_tail(void) { - html("</table>\n"); + html("</tbody>\n</table>\n"); cgit_print_layout_end(); } |
