markdowndocs 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/app/services/markdowndocs/markdown_renderer.rb +39 -3
- data/app/views/markdowndocs/docs/_breadcrumb.html.erb +2 -1
- data/app/views/markdowndocs/docs/_mode_switcher.html.erb +3 -1
- data/app/views/markdowndocs/docs/_navigation.html.erb +6 -2
- data/config/locales/en.yml +1 -0
- data/lib/markdowndocs/version.rb +1 -1
- metadata +3 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eb123f5ef96df8917be85966728453e124ae2f418acb7458a583c3d42254b068
|
|
4
|
+
data.tar.gz: e672f4cf03ee6a4fbb37a5cd2d924be8fb903256de7834adf36bfcf4e8877541
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a7f53ed3821883f3f858b50039a1ca03ba4bbfafdbf9302dedfb9a0c150ab1f25e198c3ca602e13cec493a469135bdc5b0fb28b9157182e1278409136928171
|
|
7
|
+
data.tar.gz: 15f9aa8cda587f9239ec84290d2fb1e3f3d6cf28c9b208b33d6081af842a5ce15eb5dcfa2a131905f41a228a03d19ea1dacd97fb3e80d35aa4a79f722cf4795a
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.11.1] - 2026-07-13
|
|
9
|
+
|
|
10
|
+
### Accessibility (follow-up review)
|
|
11
|
+
|
|
12
|
+
- **Caption-less tables get a numbered, localized accessible name.** v0.11.0
|
|
13
|
+
labelled every un-captioned table the hardcoded English `"Table"`, so a
|
|
14
|
+
page of tables was undifferentiated to a screen reader and unlocalized.
|
|
15
|
+
They are now `"Table 1"`, `"Table 2"`, … via the new
|
|
16
|
+
`markdowndocs.table_label` I18n key (`"Table %{number}"`).
|
|
17
|
+
|
|
18
|
+
## [0.11.0] - 2026-07-13
|
|
19
|
+
|
|
20
|
+
### Accessibility
|
|
21
|
+
|
|
22
|
+
- **Keyboard-scrollable tables (WCAG 2.1.1).** A wide GFM table overflows and
|
|
23
|
+
becomes horizontally scrollable via the host's typography CSS. The renderer
|
|
24
|
+
now marks every `<table>` with `tabindex="0"` so keyboard-only users can
|
|
25
|
+
scroll it with the arrow keys (axe `scrollable-region-focusable`). The
|
|
26
|
+
table's implicit `role="table"` is preserved — no `role="region"` is added,
|
|
27
|
+
which would strip row/column semantics — and an un-captioned table gets a
|
|
28
|
+
minimal `aria-label="Table"` so the focus stop is announced. `tabindex` is
|
|
29
|
+
now in the sanitizer's base attribute allow-list.
|
|
30
|
+
- **44px chrome target sizes (WCAG 2.5.5 AAA).** Sidebar table-of-contents
|
|
31
|
+
links, related-documentation links, breadcrumb links, and the audience
|
|
32
|
+
mode-switcher buttons now meet the 44×44 minimum target size (they measured
|
|
33
|
+
~20–28px). Purely additive utility classes; no visual change beyond the
|
|
34
|
+
taller hit area.
|
|
35
|
+
|
|
8
36
|
## [0.10.0] - 2026-06-24
|
|
9
37
|
|
|
10
38
|
### Added
|
|
@@ -48,7 +48,7 @@ module Markdowndocs
|
|
|
48
48
|
options = markdown_render_options
|
|
49
49
|
doc = Commonmarker.parse(markdown, options: options)
|
|
50
50
|
html = doc.to_html(options: options)
|
|
51
|
-
html =
|
|
51
|
+
html = post_process_html(html)
|
|
52
52
|
sanitize_html(html)
|
|
53
53
|
rescue => e
|
|
54
54
|
# Bare rescue is intentional: third-party errors from commonmarker,
|
|
@@ -66,7 +66,7 @@ module Markdowndocs
|
|
|
66
66
|
%(<pre class="markdowndocs-render-error">#{escaped}</pre>)
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
def
|
|
69
|
+
def post_process_html(html)
|
|
70
70
|
# HTML5 parsing preserves case-sensitive SVG/MathML foreign-content
|
|
71
71
|
# attributes (e.g. viewBox) that Nokogiri::HTML would lowercase.
|
|
72
72
|
doc = Nokogiri::HTML5.fragment(html)
|
|
@@ -84,9 +84,44 @@ module Markdowndocs
|
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
mark_tables_keyboard_accessible(doc)
|
|
88
|
+
|
|
87
89
|
doc.to_html
|
|
88
90
|
end
|
|
89
91
|
|
|
92
|
+
# A wide GFM table overflows its column and becomes horizontally
|
|
93
|
+
# scrollable — via the host's typography/prose CSS, which the engine
|
|
94
|
+
# does not control and cannot inspect at render time. A scrollable
|
|
95
|
+
# region that isn't keyboard-focusable strands keyboard-only users
|
|
96
|
+
# (WCAG 2.1.1; axe `scrollable-region-focusable`).
|
|
97
|
+
#
|
|
98
|
+
# `tabindex="0"` directly on the <table> makes it focusable so a
|
|
99
|
+
# keyboard user can scroll it with the arrow keys, whether the host CSS
|
|
100
|
+
# scrolls the table itself or a wrapper. We deliberately do NOT add
|
|
101
|
+
# `role="region"`: on a <table> that would override the implicit
|
|
102
|
+
# `role="table"` and strip row/column semantics from screen readers.
|
|
103
|
+
# A <caption> already names the table for AT; when absent we add a
|
|
104
|
+
# minimal aria-label so the focus stop is announced. The focus ring is
|
|
105
|
+
# the user-agent default (no engine CSS suppresses it).
|
|
106
|
+
#
|
|
107
|
+
# Trade-off: every table becomes a tab stop, not only the ones that
|
|
108
|
+
# actually overflow — scroll state is unknowable without a browser, and
|
|
109
|
+
# a static (JS-free) engine fix is worth that small amount of extra tab
|
|
110
|
+
# travel.
|
|
111
|
+
def mark_tables_keyboard_accessible(doc)
|
|
112
|
+
doc.css("table").each_with_index do |table, index|
|
|
113
|
+
table["tabindex"] = "0"
|
|
114
|
+
next if table.at_css("caption") || table["aria-label"]
|
|
115
|
+
|
|
116
|
+
# A caption-less table still needs an accessible name for its focus
|
|
117
|
+
# stop — but a page of identically-named "Table" regions is
|
|
118
|
+
# undifferentiated to a screen reader tabbing through. Number them,
|
|
119
|
+
# and route the label through I18n so non-English docs localize it.
|
|
120
|
+
table["aria-label"] = I18n.t("markdowndocs.table_label", number: index + 1,
|
|
121
|
+
default: "Table %{number}")
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
90
125
|
def lexer_exists?(language)
|
|
91
126
|
Rouge::Lexer.find(language).present?
|
|
92
127
|
rescue
|
|
@@ -131,6 +166,7 @@ module Markdowndocs
|
|
|
131
166
|
href title src alt align class lang
|
|
132
167
|
role aria-label aria-labelledby aria-describedby aria-hidden
|
|
133
168
|
open
|
|
169
|
+
tabindex
|
|
134
170
|
].freeze
|
|
135
171
|
|
|
136
172
|
# Curated structural SVG subset. Deliberately excludes script,
|
|
@@ -159,7 +195,7 @@ module Markdowndocs
|
|
|
159
195
|
transform opacity text-anchor dominant-baseline
|
|
160
196
|
font-size font-family font-weight
|
|
161
197
|
marker-start marker-end markerWidth markerHeight refX refY orient
|
|
162
|
-
id xmlns focusable
|
|
198
|
+
id xmlns focusable
|
|
163
199
|
].freeze
|
|
164
200
|
|
|
165
201
|
def sanitize_html(html)
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
<% if item[:current] %>
|
|
20
20
|
<span class="font-medium text-gray-900 dark:text-slate-100" aria-current="page"><%= item[:name] %></span>
|
|
21
21
|
<% elsif item[:path] %>
|
|
22
|
-
|
|
22
|
+
<%# inline-flex min-h-11 (44px) meets WCAG 2.5.5 AAA target size. %>
|
|
23
|
+
<%= link_to item[:name], item[:path], class: "hover:text-indigo-700 dark:hover:text-indigo-300 transition-colors inline-flex min-h-11 items-center" %>
|
|
23
24
|
<% else %>
|
|
24
25
|
<span class="text-gray-700 dark:text-slate-300"><%= item[:name] %></span>
|
|
25
26
|
<% end %>
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
aria-pressed="<%= current_mode == mode %>"
|
|
22
22
|
data-mode="<%= mode %>"
|
|
23
23
|
data-action="click->docs-mode#rememberFocus"
|
|
24
|
-
|
|
24
|
+
<%# inline-flex min-h-11 (44px) meets WCAG 2.5.5 AAA target size — the
|
|
25
|
+
toggle buttons measured ~28px tall. %>
|
|
26
|
+
class="inline-flex min-h-11 items-center justify-center px-3 py-1.5 text-sm font-medium rounded-md border transition-colors <%= (current_mode == mode) ? 'border-cyan-500 bg-cyan-50 text-cyan-900 dark:bg-cyan-900/40 dark:border-cyan-400 dark:text-cyan-100' : 'border-slate-200 text-slate-700 hover:bg-slate-50 dark:border-slate-700 dark:text-slate-300 dark:hover:bg-slate-700' %>"
|
|
25
27
|
>
|
|
26
28
|
<%= t("markdowndocs.modes.#{mode}", default: mode.titleize) %>
|
|
27
29
|
</button>
|
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
<ul class="space-y-2">
|
|
8
8
|
<% toc_items.each do |item| %>
|
|
9
9
|
<li class="<%= 'ml-4' if item[:level] == 3 %>">
|
|
10
|
-
|
|
10
|
+
<%# min-h-11 (44px) meets WCAG 2.5.5 AAA target size — sidebar TOC links
|
|
11
|
+
measured ~20px. flex + items-center keeps the label vertically
|
|
12
|
+
centered in the taller hit area. %>
|
|
13
|
+
<a href="#<%= item[:slug] %>" class="text-sm text-gray-700 dark:text-slate-300 hover:text-indigo-700 dark:hover:text-indigo-300 transition-colors flex min-h-11 items-center">
|
|
11
14
|
<%= item[:text] %>
|
|
12
15
|
</a>
|
|
13
16
|
</li>
|
|
@@ -23,7 +26,8 @@
|
|
|
23
26
|
<ul class="space-y-3">
|
|
24
27
|
<% related_docs.each do |related_doc| %>
|
|
25
28
|
<li>
|
|
26
|
-
|
|
29
|
+
<%# inline-flex min-h-11 (44px) meets WCAG 2.5.5 AAA target size. %>
|
|
30
|
+
<%= link_to related_doc.title, markdowndocs.doc_path(related_doc.slug), class: "text-sm text-indigo-700 dark:text-indigo-300 hover:text-indigo-800 dark:hover:text-indigo-200 font-medium transition-colors inline-flex min-h-11 items-center" %>
|
|
27
31
|
<p class="text-xs text-gray-700 dark:text-slate-300 mt-1"><%= related_doc.description %></p>
|
|
28
32
|
</li>
|
|
29
33
|
<% end %>
|
data/config/locales/en.yml
CHANGED
data/lib/markdowndocs/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: markdowndocs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dave Chmura
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rails
|
|
@@ -115,7 +114,6 @@ metadata:
|
|
|
115
114
|
homepage_uri: https://github.com/dschmura/markdowndocs
|
|
116
115
|
source_code_uri: https://github.com/dschmura/markdowndocs
|
|
117
116
|
changelog_uri: https://github.com/dschmura/markdowndocs/blob/main/CHANGELOG.md
|
|
118
|
-
post_install_message:
|
|
119
117
|
rdoc_options: []
|
|
120
118
|
require_paths:
|
|
121
119
|
- lib
|
|
@@ -130,8 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
130
128
|
- !ruby/object:Gem::Version
|
|
131
129
|
version: '0'
|
|
132
130
|
requirements: []
|
|
133
|
-
rubygems_version: 3.
|
|
134
|
-
signing_key:
|
|
131
|
+
rubygems_version: 3.6.9
|
|
135
132
|
specification_version: 4
|
|
136
133
|
summary: A drop-in markdown documentation site for Rails apps
|
|
137
134
|
test_files: []
|