commonmark icon indicating copy to clipboard operation
commonmark copied to clipboard

HeadingPermalinkRenderer Accessibility

Open ceford opened this issue 1 year ago • 6 comments

Description

My System - Joomla Accessibility Checker tells me there is a problem with empty links. I fixed it in:

league/commonmark/src/Extension/HeadingPermalink/HeadingPermalinkRenderer.php

by commenting out line 70 so the href attribute does not appear in the anchor. Could that be right?

Example

    //$attrs->set('href', '#' . $fragmentPrefix . $slug);

Did this project help you today? Did it make you happy in any way?

No response

ceford avatar May 22 '24 08:05 ceford

You might be better off finding the markdown that contains an empty link (e.g. Lorem [ipsum]() dolor.) and fixing that instead. Or are you saying that CommonMark should never add an href attribute that's empty?

samwilson avatar May 22 '24 14:05 samwilson

What I am saying is that the Heading PermaLink Extension (https://commonmark.thephpleague.com/2.4/extensions/heading-permalinks/) creates an empty link before or after a heading as the destination of each item in the Contents and accessibility tools flag empty links as a serious error (https://webaim.org/techniques/hypertext/hypertext_links). The destination should not be a link at all and removing the href attribute from the destination tag seems to do just that. But is that the best way to do it?

ceford avatar May 22 '24 16:05 ceford

Ah, that makes sense. So you're saying that there are circumstances in which $fragmentPrefix and $slug are both empty strings and the result is just href="#"?

samwilson avatar May 22 '24 18:05 samwilson

This is the code of a heading:

<h2>Introduction<a id="content-introduction" href="#content-introduction" class="heading-permalink" title="Permalink">¶</a></h2>

And this is the Contents item:

<li>
<a href="#content-introduction">Introduction</a>
</li>

It works fine but does not pass accessibility validation.

ceford avatar May 22 '24 19:05 ceford

The links are technically not empty, as they do contain a clickable character. (You can also change this string to anything you'd like using the symbol config setting.)

Could you share more details about why Joomla thinks this link is empty? Are they expecting a certain minimum number of characters or something?

colinodell avatar Jul 22 '24 17:07 colinodell

Going back to the code of a heading I quoted:

<h2>Introduction<a id="content-introduction" href="#content-introduction" class="heading-permalink" title="Permalink">¶</a></h2>

This is a link that points to itself! I think the heading should really be a target, like this:

<h2 id="content-introduction" class="heading-permalink" >Introduction</h2>

Not sure if the class is really needed!

ceford avatar Jul 22 '24 18:07 ceford

This is a link that points to itself!

That's not a problem at all. A permalink is supposed to link to itself. Some people prefer just having an anchor (like your second example), that is perfectly fine too.

Not sure if the class is really needed!

It just makes it more convenient to style it. I wouldn't remove it, but it could be made optional.


It's not accessible because a screen reader would announce the link as just "paragraph symbol". The title (attribute) shows up as a tooltip and is not guaranteed to affect the screen reader. This is even worse with the aria-hidden option, where it is completely inaccessible (but I guess that's by design).

As it is right now, this extension does make it a bit difficult to have correct (IMO!) accessible permalinks. I happened to be reading about the topic here: https://www.codejam.info/2021/06/you-re-probably-doing-anchor-links-wrong.html

I would favour one of these two approaches:

  1. very simple link in heading containing heading text
  2. or a link before/after the heading

That 2nd approach can be simpler though: you can have an empty link (no content) with an aria-label and an icon or symbol from css (e.g. ::after { content: '#' }) instead of all that "html for/not-for screen reader" boilerplate. The aria-label might be a bit tricky to get right though, for best results it should say "Permalink to <section title>".

uuf6429 avatar Oct 10 '25 18:10 uuf6429

In my application I left out the inbuilt ToC and rolled my own.

ceford avatar Oct 10 '25 18:10 ceford

I've been trying to adapt HeadingPermalinkRenderer unsuccessfully. Apparently only the processor can do does changes - which can't be swapped without a reimplementation of the extension class. Seems like build it from scratch might be the easiest approach for now.

uuf6429 avatar Oct 10 '25 18:10 uuf6429