diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/ui-blame.c4
-rw-r--r--source/ui-commit.c12
-rw-r--r--source/ui-diff.c71
-rw-r--r--source/ui-log.c41
-rw-r--r--source/ui-refs.c29
-rw-r--r--source/ui-repolist.c17
-rw-r--r--source/ui-shared.c51
-rw-r--r--source/ui-ssdiff.c11
-rw-r--r--source/ui-ssdiff.h7
-rw-r--r--source/ui-stats.c25
-rw-r--r--source/ui-summary.c20
-rw-r--r--source/ui-tag.c10
-rw-r--r--source/ui-tree.c32
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();
}