fix(cli): score apple-touch-icon-precomposed at the 180px default (#3607)

declaredSize() matched the rel token "apple-touch-icon" exactly, so the
legacy "apple-touch-icon-precomposed" spelling (one token, not two) fell
through to 0 instead of the 180px Apple default, even though the selector
already collects it. Same page, one spelling apart, opposite winner inside
tier 1 — it never drops a candidate and never beats the .ico tier.

Switch to a startsWith check on the token. Exact-token matching stays for
mask-icon, where a longer rel really would be a different asset.
This commit is contained in:
Miguel Ángel
2026-09-03 00:21:05 -04:00
committed by GitHub
parent da09428af1
commit 7dc31bd2cc
2 changed files with 27 additions and 1 deletions
@@ -108,6 +108,24 @@ describe("rankIconCandidates", () => {
expect(hrefs([{ rel: "icon", href: "" }, ...NOTION])).toHaveLength(2);
});
it("scores apple-touch-icon-precomposed at the same 180px default as apple-touch-icon", () => {
// Precomposed is one token longer, not a different rel: it must win against a small
// sized png the same way a plain apple-touch-icon would.
const precomposed: IconCandidate[] = [
{
rel: "apple-touch-icon-precomposed",
href: "https://x.test/apple-touch-icon-precomposed.png",
sizes: null,
type: null,
},
{ rel: "icon", href: "https://x.test/favicon-32.png", sizes: "32x32", type: "image/png" },
];
expect(hrefs(precomposed)).toEqual([
"https://x.test/apple-touch-icon-precomposed.png",
"https://x.test/favicon-32.png",
]);
});
it("keeps DOM order between candidates of equal rank", () => {
const same: IconCandidate[] = [
{ rel: "icon", href: "https://x.test/a.png", sizes: "32x32" },
+9 -1
View File
@@ -68,7 +68,15 @@ function isIco(c: IconCandidate): boolean {
function declaredSize(c: IconCandidate): number {
const parsed = parseSizes(c.sizes);
if (parsed > 0) return parsed;
return c.rel.toLowerCase().split(/\s+/).includes("apple-touch-icon") ? APPLE_TOUCH_DEFAULT_PX : 0;
// `startsWith`, not an exact-token match: `apple-touch-icon-precomposed` is the same
// 180px default, one spelling later. Exact match is right for `mask-icon` (isMaskIcon),
// where a longer rel really would be a different asset.
return c.rel
.toLowerCase()
.split(/\s+/)
.some((t) => t.startsWith("apple-touch-icon"))
? APPLE_TOUCH_DEFAULT_PX
: 0;
}
function tierOf(c: IconCandidate): number {