FaviconFinder

repository·main·Indexed 42 days ago

https://github.com/will-lumley/faviconfinder

A pure Swift library for iOS, macOS, and Linux that automates the detection and retrieval of favicons from websites. It searches HTML headers, root directories, and web application manifests, with support for custom HTTP headers, meta-refresh redirect checking, and pre-fetched HTML via SwiftSoup. Version 5.1.5+ provides Swift 6 support with strict concurrency.

Tokens
2K
Snippets
8
Records
8
Agent score
3%

What's inside FaviconFinder

  1. Install FaviconFinder via Swift Package Manager

    main

    Add FaviconFinder as a dependency in your Package.swift file.

    Note on Versions:

    • Use version 5.1.5 or higher for Swift 6 support (data-race safe, strict concurrency).
    • Use version 5.0.4 if you are using Swift 5.9 or below.
    • Use version 3.3.0 if you need to support older iOS/macOS versions that do not support async/await (this version uses closures instead).
    ...
    dependencies: [
        .package(url: "https://github.com/will-lumley/FaviconFinder.git", from: "5.1.5"),
    ],
    targets: [
        .target( name: "YourTarget", dependencies: ["FaviconFinder"]),
    ]
    ...
  2. Sort favicon URLs by size without downloading

    main

    You can identify the largest or smallest favicon based on metadata (size tags in HTML or web app manifests) without downloading the actual image files. This optimizes performance by selecting the target URL first.

    Workflow:

    1. Call .fetchFaviconURLs().
    2. Call .largest() or .smallest() to get the URL.
    3. Call .download() on the resulting URL to fetch the image.

    Limitations: This relies on the accuracy of the size metadata provided by the source website.

    // 1. Get the URL only
    let faviconURL = try await FaviconFinder(url: url)
        .fetchFaviconURLs()
        .largest()  // or .smallest()
    
    print("Largest Favicon URL: \(faviconURL.source)")
    
    // 2. Download the identified URL
    let largestFavicon = try await FaviconFinder(url: url)
        .fetchFaviconURLs()
        .largest()
        .download()
    
    self.imageView.image = largestFavicon.image
  3. Use pre-fetched HTML with SwiftSoup

    main

    To optimize performance and avoid redundant HTTP requests, you can pass a pre-parsed SwiftSoup.Document directly to the configuration using the prefetchedHTML property. This is useful if you have already fetched the HTML via another part of your application or are working with local files.

    import SwiftSoup
    
    // Assuming you have already fetched and parsed the HTML
    let htmlString = "<html><head>...</head></html>"
    let document = try SwiftSoup.parse(htmlString)
    
    let favicon = try await FaviconFinder(
        url: url,
        configuration: .init(prefetchedHTML: document)
    )
        .fetchFaviconURLs()
        .download()
        .largest()
    
    self.imageView.image = favicon.image
  4. Install FaviconFinder via Swift Package Manager

    main

    To integrate FaviconFinder into your project, use the Swift Package Manager (SPM).

    Note: The README mentions support for CocoaPods and Carthage, but specific installation commands for those are not provided in this segment. For most modern Swift projects, SPM is the recommended method.

    // Use Swift Package Manager to add the dependency
    // Refer to the repository for the exact SPM URL
    ```swift
    // Example dependency declaration in Package.swift
    .package(url: "https://github.com/will-lumley/FaviconFinder.git", from: "5.1.5")
  5. Query favicons behind authentication using HTTP headers

    main

    If favicons are protected by an authentication layer, you can pass custom HTTP headers (such as Authorization or Cookie) via the httpHeaders property in the Configuration object. These headers will be included in every request made by FaviconFinder.

    let headers = [
        "Authorization": "Bearer your_token_here",
        "Cookie": "session_id=your_session_id_here"
    ]
    
    let favicon = try await FaviconFinder(
        url: url,
        configuration: .init(
            httpHeaders: headers
        )
    )
        .fetchFaviconURLs()
        .download()
        .largest()
    
    self.imageView.image = favicon.image
  6. Configure preferential favicon downloading

    main

    You can fine-tune which favicon sources and types FaviconFinder prioritizes. By setting preferredSource and providing a preferences dictionary, you can specify which sub-type to look for within each source (e.g., a specific rel type in HTML, a filename for .ico, or a specific key in a web application manifest).

    If the preferred source or type is not found, FaviconFinder will automatically attempt other available methods before returning an error.

    let favicon = try await FaviconFinder(
        url: url,
        configuration: .init(
            preferredSource: .html,
            preferences: [
                .html: FaviconFormatType.appleTouchIcon.rawValue,
                .ico: "favicon.ico",
                .webApplicationManifestFile: FaviconFormatType.launcherIcon4x.rawValue
            ]
        )
    )
        .fetchFaviconURLs()
        .download()
        .largest()
    
    self.imageView.image = favicon.image
  7. Fetch header or hero images

    main

    To allow FaviconFinder to attempt fetching header or hero images from a URL, set the acceptHeaderImage parameter to true in the configuration. This is an opt-in feature and is false by default.

    let favicon = try await FaviconFinder(
        url: url,
        configuration: .init(acceptHeaderImage: true)
    )
        .fetchFaviconURLs()
        .download()
        .largest()
    
    self.imageView.image = favicon.image
  8. Enable Meta-Refresh redirect checking

    main

    Standard HTTP redirects (like 301) are handled natively by URLSession, but meta-refresh redirects occur within the HTML content. To ensure FaviconFinder follows these front-end redirects, enable checkForMetaRefreshRedirect in the configuration.

    Note: This requires extra compute time for HTML parsing and is disabled by default.

    let favicon = try await FaviconFinder(
        url: url,
        configuration: .init(
            preferredSource: .html,
            preferences: [
                .html: FaviconFormatType.appleTouchIcon.rawValue,
                .ico: "favicon.ico",
                .webApplicationManifestFile: FaviconFormatType.launcherIcon4x.rawValue
            ],
            checkForMetaRefreshRedirect: true
        )
    )
        .fetchFaviconURLs()
        .download()
        .largest()
    
    self.imageView.image = favicon.image