Web Metadata#
Small Swift helpers for fetching and constructing metadata about web pages.
swift-web-metadata keeps common web-preview building blocks in focused
modules: favicon URL construction, oEmbed request/response models, and an
optional Point-Free Dependencies client for fetching metadata through an
injectable boundary.
import Favicon
import OEmbed
let faviconURL = Favicon.googleS2URL(host: "bsky.social", size: 64)
let request = OEmbedRequest(
endpointURL: OEmbedEndpoint.youtube,
resourceURL: URL(string: "https://www.youtube.com/watch?v=abc123")!,
maxWidth: 640,
maxHeight: 360
)
Installation#
Add the package to your Swift package dependencies:
.package(url: "https://tangled.org/woody.fm/swift-web-metadata", branch: "main")
Then add the products you need to your target dependencies:
.target(
name: "YourFeature",
dependencies: [
"Favicon",
"OEmbed",
]
)
Favicons#
Use Favicon to derive conventional favicon URLs from either a host string or
an existing page URL.
let googleURL = Favicon.googleS2URL(host: "example.com", size: 128)
// https://www.google.com/s2/favicons?domain=example.com&sz=128
let directURL = Favicon.directURL(host: "example.com")
// https://example.com/favicon.ico
The Google S2 helper is useful for previews that need a normalized icon source,
while the direct helper points at the site's conventional /favicon.ico
location.
oEmbed#
OEmbedRequest builds provider request URLs and OEmbedMetadata decodes the
standard oEmbed response fields.
let request = OEmbedRequest(
endpointURL: OEmbedEndpoint.spotify,
resourceURL: URL(string: "https://open.spotify.com/track/example")!
)
let url = request.url
Common provider endpoints are available through OEmbedEndpoint:
OEmbedEndpoint.youtube
OEmbedEndpoint.soundCloud
OEmbedEndpoint.spotify
OEmbedEndpoint.twitter
OEmbedEndpoint.tiktok
Dependencies#
Enable the Dependencies trait to use the WebMetadataClient product:
swift test --traits Dependencies
Then add WebMetadataClient and Dependencies to the targets that need an
injectable metadata boundary:
.target(
name: "YourFeature",
dependencies: [
"WebMetadataClient",
.product(name: "Dependencies", package: "swift-dependencies"),
]
)
The live client fetches oEmbed metadata through URLSession and delegates
favicon URL construction to the Favicon module.
import Dependencies
import WebMetadataClient
@Dependency(\.webMetadataClient) var webMetadataClient
let metadata = try await webMetadataClient.fetchOEmbed(request)
In tests, replace the client with closures that return the metadata your feature expects:
let expected = OEmbedMetadata(type: .link, title: "Example")
let metadata = try await withDependencies {
$0.webMetadataClient = WebMetadataClient(
fetchOEmbed: { _ in expected },
googleS2FaviconURL: { host, size in
Favicon.googleS2URL(host: host, size: size)
},
directFaviconURL: { host in
Favicon.directURL(host: host)
}
)
} operation: {
@Dependency(\.webMetadataClient) var client
return try await client.fetchOEmbed(request)
}
#expect(metadata == expected)
Requirements#
This package currently targets Swift 6.1 or later, iOS 17 or later, and macOS 14 or later.