will-lumley / FaviconFinder

A small swift library for iOS & macOS to detect favicons used by a website.
MIT License
161 stars 33 forks source link

Add Support for Custom FaviconFinders #90

Open will-lumley opened 1 month ago

will-lumley commented 1 month ago

Description To extend the flexibility of FaviconFinder, we would like to allow users to create their own custom FaviconFinder implementations. This would enable users to define new ways of retrieving favicons for more niche or specific use cases beyond the provided implementations (e.g., HTMLFaviconFinder, ICOFaviconFinder, WebApplicationManifestFaviconFinder).

Proposed API • Users should be able to create classes conforming to the FaviconFinderProtocol, which would allow them to define: • A custom find() function that locates favicons using the user’s unique logic. • The preferred favicon type, such as different file types or sizes, and how to handle relative URLs. • How favicons should be downloaded or parsed based on their custom use case.

Protocol for Custom FaviconFinder The existing FaviconFinderProtocol already provides a good foundation, but we would need to extend it slightly to accommodate custom finders easily. Here is an outline of the requirements: • FaviconFinderProtocol: • var url: URL { get set } — The URL of the website we’re querying the favicon for. • var configuration: FaviconFinder.Configuration { get set } — The configuration object that contains user-defined preferences. • var preferredType: String { get } — A property for specifying the preferred favicon type (e.g., specific image size, filename, or key in a manifest file). • func find() async throws -> [FaviconURL] — The function that will contain the logic for locating and returning favicon URLs based on the user’s implementation.

Example Usage

To use a custom FaviconFinder, a user would implement their class as follows:


class CustomFaviconFinder: FaviconFinderProtocol {
    var url: URL
    var configuration: FaviconFinder.Configuration

    var preferredType: String {
        return "custom-favicon"  // User-defined type
    }

    required init(url: URL, configuration: FaviconFinder.Configuration) {
        self.url = url
        self.configuration = configuration
    }

    func find() async throws -> [FaviconURL] {
        // Custom logic to locate and return favicon URLs
        return []
    }
}

Integration • Custom Finder Registration: Users should be able to register their custom finder in the configuration, which will allow the library to use it when fetching favicons. This could be done by passing the custom FaviconFinder to the FaviconFinder initializer. • FaviconFinder: Allow FaviconFinder to check the configuration and utilize the user’s custom finder if specified.

let customFinder = CustomFaviconFinder(url: url, configuration: .default)
let favicons = try await customFinder.find()

Advantages • Enables developers to handle unique or edge-case favicon retrieval logic that the built-in finders may not cover. • Supports additional flexibility and extensibility for developers integrating FaviconFinder into their apps.

Tasks

  1. Expose FaviconFinderProtocol for public use, ensuring users can implement their own logic safely.
  2. Document the process of creating a custom FaviconFinder in the README or Wiki.
  3. Add example usage to guide users in building their own FaviconFinder.
  4. Allow users to register and use their custom finder through the existing configuration system.

This issue outlines the plan for allowing users to add their own custom FaviconFinder, enhancing flexibility and addressing edge cases where built-in logic may not suffice.