Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Fetch, convert, and cache favicons for any website in your Laravel app.

Given a site URL, the package discovers the best available icon source (preferring an SVG over an ICO over a raster PNG/WebP/AVIF over a JPG), downloads it, and converts it into whichever size/format you ask for — caching the result on disk so subsequent requests are instant until the TTL expires.
Given a site URL, the package discovers the best available icon source (preferring an SVG over the largest PNG/WebP/AVIF over an ICO over a JPG), downloads it, and converts it into whichever size/format you ask for — caching the result on disk so subsequent requests are instant until the TTL expires.

## Requirements

Expand Down
11 changes: 7 additions & 4 deletions config/favicon.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,17 @@
|
| Lower number = preferred. Used to rank candidate favicon sources found
| on the page (<link> tags, manifest icons, /favicon.ico fallback).
| Format outranks declared size, so 'ico' sits below the modern rasters:
| a favicon.ico rarely holds more than 64px and would otherwise beat a
| site's 512px PNG, leaving every larger variant upscaled.
|
*/
'source_priority' => [
'svg' => 0,
'ico' => 1,
'png' => 2,
'webp' => 2,
'avif' => 2,
'png' => 1,
'webp' => 1,
'avif' => 1,
'ico' => 2,
'jpg' => 3,
'jpeg' => 3,
'gif' => 4,
Expand Down
19 changes: 19 additions & 0 deletions tests/Feature/FaviconResolutionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ function sampleSvg(): string
expect($info[0])->toBe(32)->and($info[1])->toBe(32);
});

it('prefers the largest declared png over a declared favicon.ico', function () {
$ico = (new \Backstage\Favicon\ImagickConverter(config('favicon')))
->toIco(samplePng(), 'png', [16, 32]);

Http::fake([
'https://icoandpng.test/' => Http::response(
'<html><head><link rel="icon" href="/favicon.ico" sizes="any"><link rel="icon" href="/icon-32.png" sizes="32x32" type="image/png"><link rel="icon" href="/icon-512.png" sizes="512x512" type="image/png"></head></html>'
),
'https://icoandpng.test/favicon.ico' => Http::response($ico),
'https://icoandpng.test/icon-512.png' => Http::response(samplePng(512)),
]);

Favicon::for('https://icoandpng.test')->get('png', 32);

$meta = Favicon::readMeta(Favicon::domainKey('https://icoandpng.test'));

expect($meta['source_url'])->toBe('https://icoandpng.test/icon-512.png');
});

it('falls back to /favicon.ico when no link tags are present', function () {
$ico = (new \Backstage\Favicon\ImagickConverter(config('favicon')))
->toIco(samplePng(), 'png', [16, 32]);
Expand Down
Loading