Skip to content

Commit 4db3e9a

Browse files
authored
Merge pull request #313 from sunnywalker/lib
comply with WCAG 2.0 for footnote backlinks - Adding `fn_backlink_label`. - Adding `^^` and `%%` placeholders for footnote number and reference number.
2 parents 93fa687 + 07add12 commit 4db3e9a

File tree

2 files changed

+80
-24
lines changed

2 files changed

+80
-24
lines changed

.editorconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# EditorConfig is awesome: https://EditorConfig.org
2+
root = true
3+
4+
[*]
5+
end_of_line = lf
6+
charset = utf-8
7+
trim_trailing_whitespace = false
8+
9+
[*.php]
10+
indent_style = tab
11+
insert_final_newline = true

Michelf/MarkdownExtra.php

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ class MarkdownExtra extends \Michelf\Markdown {
2525
public $fn_id_prefix = "";
2626

2727
/**
28-
* Optional title attribute for footnote links and backlinks.
28+
* Optional title attribute for footnote links.
2929
* @var string
3030
*/
31-
public $fn_link_title = "";
32-
public $fn_backlink_title = "";
31+
public $fn_link_title = "";
3332

3433
/**
3534
* Optional class attribute for footnote links and backlinks.
@@ -42,10 +41,22 @@ class MarkdownExtra extends \Michelf\Markdown {
4241
* Content to be displayed within footnote backlinks. The default is '↩';
4342
* the U+FE0E on the end is a Unicode variant selector used to prevent iOS
4443
* from displaying the arrow character as an emoji.
44+
* Optionally use '^^' and '%%' to refer to the footnote number and
45+
* reference number respectively. {@see parseFootnotePlaceholders()}
4546
* @var string
4647
*/
4748
public $fn_backlink_html = '↩︎';
4849

50+
/**
51+
* Optional title and aria-label attributes for footnote backlinks for
52+
* added accessibility (to ensure backlink uniqueness).
53+
* Use '^^' and '%%' to refer to the footnote number and reference number
54+
* respectively. {@see parseFootnotePlaceholders()}
55+
* @var string
56+
*/
57+
public $fn_backlink_title = "";
58+
public $fn_backlink_label = "";
59+
4960
/**
5061
* Class name for table cell alignment (%% replaced left/center/right)
5162
* For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
@@ -1217,8 +1228,7 @@ protected function _doTable_leadingPipe_callback($matches) {
12171228
* @param string $alignname
12181229
* @return string
12191230
*/
1220-
protected function _doTable_makeAlignAttr($alignname)
1221-
{
1231+
protected function _doTable_makeAlignAttr($alignname) {
12221232
if (empty($this->table_align_class_tmpl)) {
12231233
return " align=\"$alignname\"";
12241234
}
@@ -1667,24 +1677,18 @@ protected function appendFootnotes($text) {
16671677

16681678

16691679
/**
1670-
* Generates the HTML for footnotes. Called by appendFootnotes, even if footnotes are not being appended.
1680+
* Generates the HTML for footnotes. Called by appendFootnotes, even if
1681+
* footnotes are not being appended.
16711682
* @return void
16721683
*/
16731684
protected function _doFootnotes() {
1674-
$attr = "";
1685+
$attr = array();
16751686
if ($this->fn_backlink_class !== "") {
16761687
$class = $this->fn_backlink_class;
16771688
$class = $this->encodeAttribute($class);
1678-
$attr .= " class=\"$class\"";
1679-
}
1680-
if ($this->fn_backlink_title !== "") {
1681-
$title = $this->fn_backlink_title;
1682-
$title = $this->encodeAttribute($title);
1683-
$attr .= " title=\"$title\"";
1684-
$attr .= " aria-label=\"$title\"";
1689+
$attr['class'] = " class=\"$class\"";
16851690
}
1686-
$attr .= " role=\"doc-backlink\"";
1687-
$backlink_text = $this->fn_backlink_html;
1691+
$attr['role'] = " role=\"doc-backlink\"";
16881692
$num = 0;
16891693

16901694
$text = "<ol>\n\n";
@@ -1701,19 +1705,43 @@ protected function _doFootnotes() {
17011705
$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
17021706
array($this, '_appendFootnotes_callback'), $footnote);
17031707

1704-
$attr = str_replace("%%", ++$num, $attr);
1708+
$num++;
17051709
$note_id = $this->encodeAttribute($note_id);
17061710

17071711
// Prepare backlink, multiple backlinks if multiple references
1708-
$backlink = "<a href=\"#fnref:$note_id\"$attr>$backlink_text</a>";
1709-
for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
1710-
$backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>$backlink_text</a>";
1712+
// Do not create empty backlinks if the html is blank
1713+
$backlink = "";
1714+
if (!empty($this->fn_backlink_html)) {
1715+
for ($ref_num = 1; $ref_num <= $ref_count; ++$ref_num) {
1716+
if (!empty($this->fn_backlink_title)) {
1717+
$attr['title'] = ' title="' . $this->encodeAttribute($this->fn_backlink_title) . '"';
1718+
}
1719+
if (!empty($this->fn_backlink_label)) {
1720+
$attr['label'] = ' aria-label="' . $this->encodeAttribute($this->fn_backlink_label) . '"';
1721+
}
1722+
$parsed_attr = $this->parseFootnotePlaceholders(
1723+
implode('', $attr),
1724+
$num,
1725+
$ref_num
1726+
);
1727+
$backlink_text = $this->parseFootnotePlaceholders(
1728+
$this->fn_backlink_html,
1729+
$num,
1730+
$ref_num
1731+
);
1732+
$ref_count_mark = $ref_num > 1 ? $ref_num : '';
1733+
$backlink .= " <a href=\"#fnref$ref_count_mark:$note_id\"$parsed_attr>$backlink_text</a>";
1734+
}
1735+
$backlink = trim($backlink);
17111736
}
1737+
17121738
// Add backlink to last paragraph; create new paragraph if needed.
1713-
if (preg_match('{</p>$}', $footnote)) {
1714-
$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
1715-
} else {
1716-
$footnote .= "\n\n<p>$backlink</p>";
1739+
if (!empty($backlink)) {
1740+
if (preg_match('{</p>$}', $footnote)) {
1741+
$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
1742+
} else {
1743+
$footnote .= "\n\n<p>$backlink</p>";
1744+
}
17171745
}
17181746

17191747
$text .= "<li id=\"fn:$note_id\" role=\"doc-endnote\">\n";
@@ -1773,6 +1801,23 @@ protected function _appendFootnotes_callback($matches) {
17731801
return "[^" . $matches[1] . "]";
17741802
}
17751803

1804+
/**
1805+
* Build footnote label by evaluating any placeholders.
1806+
* - ^^ footnote number
1807+
* - %% footnote reference number (Nth reference to footnote number)
1808+
* @param string $label
1809+
* @param int $footnote_number
1810+
* @param int $reference_number
1811+
* @return string
1812+
*/
1813+
protected function parseFootnotePlaceholders($label, $footnote_number, $reference_number) {
1814+
return str_replace(
1815+
array('^^', '%%'),
1816+
array($footnote_number, $reference_number),
1817+
$label
1818+
);
1819+
}
1820+
17761821

17771822
/**
17781823
* Abbreviations - strips abbreviations from text, stores titles in hash

0 commit comments

Comments
 (0)