diff --git a/index.html b/index.html index 04c80141..7e33f4df 100644 --- a/index.html +++ b/index.html @@ -3,14 +3,15 @@
- - + + + - + diff --git a/public/apple-touch-icon copy.png b/public/apple-touch-icon.png similarity index 100% rename from public/apple-touch-icon copy.png rename to public/apple-touch-icon.png diff --git a/src/lib/__tests__/update-favicon.test.ts b/src/lib/__tests__/update-favicon.test.ts index 7d216261..e47297c7 100644 --- a/src/lib/__tests__/update-favicon.test.ts +++ b/src/lib/__tests__/update-favicon.test.ts @@ -7,23 +7,28 @@ describe('update-favicon', () => { vi.resetModules(); }); - it('replaces managed icon links and keeps both icon rel variants in sync', async () => { + it('replaces managed tab icon links without removing larger crawler icons', async () => { const { updateFavicon } = await import('../update-favicon'); - document.head.innerHTML = ''; + document.head.innerHTML = + ''; updateFavicon(false); - expect(document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"]')).toHaveLength(2); - expect(document.querySelector('link[rel="icon"]')?.getAttribute('href')).toBe('/favicon.ico?variant=nsfw'); - expect(document.querySelector('link[rel="shortcut icon"]')?.getAttribute('href')).toBe('/favicon.ico?variant=nsfw'); + expect(document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"], link[rel="apple-touch-icon"]')).toHaveLength(4); + expect(document.querySelector('link[rel="icon"][sizes="16x16"]')?.getAttribute('href')).toBe('/favicon.ico?variant=nsfw'); + expect(document.querySelector('link[rel="shortcut icon"][sizes="16x16"]')?.getAttribute('href')).toBe('/favicon.ico?variant=nsfw'); + expect(document.querySelector('link[rel="icon"][sizes="192x192"]')?.getAttribute('href')).toBe('/manifest-icon-192x192.png'); + expect(document.querySelector('link[rel="apple-touch-icon"]')?.getAttribute('href')).toBe('/apple-touch-icon.png'); updateFavicon(false); - expect(document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"]')).toHaveLength(2); + expect(document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"], link[rel="apple-touch-icon"]')).toHaveLength(4); updateFavicon(true); - expect(document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"]')).toHaveLength(2); - expect(document.querySelector('link[rel="icon"]')?.getAttribute('href')).toBe('/favicon2.ico?variant=sfw'); - expect(document.querySelector('link[rel="shortcut icon"]')?.getAttribute('href')).toBe('/favicon2.ico?variant=sfw'); + expect(document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"], link[rel="apple-touch-icon"]')).toHaveLength(4); + expect(document.querySelector('link[rel="icon"][sizes="16x16"]')?.getAttribute('href')).toBe('/favicon2.ico?variant=sfw'); + expect(document.querySelector('link[rel="shortcut icon"][sizes="16x16"]')?.getAttribute('href')).toBe('/favicon2.ico?variant=sfw'); + expect(document.querySelector('link[rel="icon"][sizes="192x192"]')?.getAttribute('href')).toBe('/manifest-icon-192x192.png'); + expect(document.querySelector('link[rel="apple-touch-icon"]')?.getAttribute('href')).toBe('/apple-touch-icon.png'); }); it('marks only non-special, non-routing aggregate sfw boards as sfw', async () => { diff --git a/src/lib/update-favicon.ts b/src/lib/update-favicon.ts index aabe909d..e431d1c7 100644 --- a/src/lib/update-favicon.ts +++ b/src/lib/update-favicon.ts @@ -1,18 +1,20 @@ const DEFAULT_FAVICON = '/favicon.ico?variant=nsfw'; const SFW_FAVICON = '/favicon2.ico?variant=sfw'; const FAVICON_RELS = ['icon', 'shortcut icon'] as const; -const FAVICON_SELECTOR = FAVICON_RELS.map((rel) => `link[rel="${rel}"]`).join(', '); +const FAVICON_SELECTOR = ['link[data-fivechan-tab-favicon="true"]', ...FAVICON_RELS.map((rel) => `link[rel="${rel}"][sizes="16x16"]`)].join(', '); let currentHref: string | null = null; -const hasExpectedFaviconLinks = (href: string): boolean => FAVICON_RELS.every((rel) => document.querySelector(`link[rel="${rel}"][href="${href}"]`)); +const hasExpectedFaviconLinks = (href: string): boolean => + FAVICON_RELS.every((rel) => document.querySelector(`link[rel="${rel}"][href="${href}"][data-fivechan-tab-favicon="true"]`)); const createFaviconLink = (rel: (typeof FAVICON_RELS)[number], href: string): HTMLLinkElement => { const link = document.createElement('link'); link.rel = rel; link.type = 'image/png'; - link.sizes = '16x16'; + link.setAttribute('sizes', '16x16'); link.href = href; + link.dataset.fivechanTabFavicon = 'true'; return link; };