Skip to content

Icon class labels - #9

Open
jsnjack wants to merge 6 commits into
mainfrom
icon-class-labels
Open

jsnjack wants to merge 6 commits into
mainfrom
icon-class-labels

Conversation

@jsnjack

@jsnjack jsnjack commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

No description provided.

An icon font renders through a vendor class in the markup, so that class is
the only description an icon-only control carries. The carrier is usually a
span, which the Markdown pass renders away two passes before attribute scoring
runs, so rating the class attribute higher cannot preserve it.

Extend replaceWithLabel with a classPatterns list. An empty element whose class
matches is claimed by the pass and lifted as a text label, after labelAttrs and
labelChildTags have both missed. The fallback applies only when the enclosing
control has no name of its own, so a decorative icon beside visible text is not
duplicated into the label.

Two adjacent fixes the change depends on:

- The pass was gated on replaceWithLabel.tagNames being non-empty, so a
  patterns-only configuration skipped it entirely.
- A lifted label replaced its element with a bare text node, gluing it to an
  adjacent text sibling ("arrow" + "WSW" -> "arrowWSW"). The replacement is now
  padded and the minifier collapses the runs.

Omitting classPatterns leaves output byte-identical, verified across 21 pages.
A control named through aria-labelledby carries no name of its own, so the
icon class fallback claimed it and appended a token next to a name the page
already provides. GitHub's toolbar is the clear case: its buttons point at a
tooltip element, and 13 of them took an octicon token they did not need.
Ground truths rate aria-labelledby above the id it points at, so downsampling
keeps the reference and drops its target. Detecting the attribute was not
enough: the control ended up with a pointer to nothing and no name at all.

Resolve the reference against the working tree while both still exist and use
the referenced text as the label, falling back to the icon class when nothing
resolves. On github.com at cobro q=0.1 this names 13 toolbar controls with
Copy path, Dismiss alert and the like, where the reference alone left them
empty and the icon class gave only octicon-copy.
A wrapper can match the same class patterns as the icon it holds, and parents
are visited before children, so a matching wrapper was replaced before the
element carrying the real name was reached. <button><div class="icon-container">
<svg aria-label="Search"></svg></div></button> collapsed to "icon-container",
discarding the accessible name the page did provide.

An icon carrier has no element children. Require that before a class token is
read, so a wrapper is left to the passes that handle its contents.
Turndown picks its blank rule before any custom rule, and its list of elements
that are meaningful when blank holds A but not BUTTON, SELECT or TEXTAREA. A
control left without text — an icon button whose icon was just lifted away —
was dropped before the retain rule could keep it, and so was every control
inside a textless wrapper, since the wrapper itself counted as blank.

Give Turndown a blank replacement that emits the outermost retained elements
at or below the node. On console.uat07.malauzai.com the Download Queue button
vanished entirely at every quality; across a 39 page corpus this restores 148
controls, 61 of which carry a name.

Also resolve aria-labelledby for any unnamed control, not only one holding an
icon class. That names the same Download Queue button from the sibling it
points at, and a control with no icon at all is no longer left anonymous.
A void element holds no children, so the text node carrying a materialized
name was dropped by serialization and an <input> came out unnamed. Set
aria-label on void controls instead, leaving every other control as text.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant