Skip to content

Commit

Permalink
Implement table row headings
Browse files Browse the repository at this point in the history
Sometimes, tables have row-level headings as well as column level
headings.

To be accessible, these need to be marked up as `<th>` tags. Otherwise
users of screen readers and other assistive technology may not be able
to work out that they're table headings rather than ordinary table
cells.
  • Loading branch information
richardTowers committed Mar 11, 2021
1 parent 9e8160d commit 9f6c0b9
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
29 changes: 29 additions & 0 deletions lib/govuk_tech_docs/tech_docs_html_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,34 @@ def table(header, body)
</table>
</div>)
end

def table_row(body)
# Post-processing the table_cell HTML to implement row headings.
#
# Doing this in table_row instead of table_cell is a hack.
#
# Ideally, we'd use the table_cell callback like:
#
# def table_cell(content, alignment, header)
# if header
# "<th>#{content}</th>"
# elsif content.start_with? "# "
# "<th scope="row">#{content.sub(/^# /, "")}</th>"
# else
# "<td>#{content}</td>"
# end
# end
#
# Sadly, Redcarpet's table_cell callback doesn't allow you to distinguish
# table cells and table headings until https://github.com/vmg/redcarpet/commit/27dfb2a738a23aadd286ac9e7ecd61c4545d29de
# (which is not yet released). This means we can't use the table_cell callback
# without breaking column headers, so we're having to hack it in table_row.
#
# Despite the hackiness, this substitution should work for all cases
# where the table cell just includes simple text (with no other markup).

body_with_row_headers = body.gsub(/<td># ([^<]*)<\/td>/, "<th scope=\"row\">\\1</th>")
"<tr>#{body_with_row_headers}</tr>"
end
end
end
35 changes: 35 additions & 0 deletions spec/govuk_tech_docs/tech_docs_html_renderer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
RSpec.describe GovukTechDocs::TechDocsHTMLRenderer do
describe "#render a table" do
it "renders tables with row headings" do
app = double("app")
context = double("context")
allow(context).to receive(:app) { app }
allow(app).to receive(:api)

processor = Redcarpet::Markdown.new(described_class.new(context: context), tables: true)
output = processor.render <<~MARKDOWN
| A | B |
|------|---|
|# C | D |
| E | F |
|# *G* | H |
MARKDOWN

# Cells in the heading row should be treated as headings
expect(output).to include("<th>A</th>")
expect(output).to include("<th>B</th>")

# Cells starting with `# ` should be treated as row headings
expect(output).to include('<th scope="row">C</th>')

# Other cells should be treated as ordinary cells
expect(output).to include("<td>D</td>")
expect(output).to include("<td>E</td>")
expect(output).to include("<td>F</td>")
expect(output).to include("<td>H</td>")

# Heading cells with more complex markup aren't handled yet
expect(output).to include("<td># <em>G</em></td>")
end
end
end

0 comments on commit 9f6c0b9

Please sign in to comment.