import Elementary import Foundation import Infrastructure import Localization /// The website's landing page, with its text localized to a given locale. struct IndexPage { // MARK: Properties /// The analytics tracker embedded as a deferred script in the document head, or `nil` to omit it. let analytics: Analytics? /// The version token appended to the page's asset URLs, or `nil` to leave them unversioned. let assetVersion: String? /// The locale the page content is localized to. let locale: Locale /// The public origin the page derives its canonical URL and language alternates from, or `nil` to omit them. let siteOrigin: String? /// Resolves the page's text from the bundled String Catalog for the page's ``locale``. private let localize: Localize // MARK: Initializers /// Creates a landing page localized to the given locale. /// - Parameters: /// - locale: the locale the page content is localized to. /// - assetVersion: the version token appended to the page's asset URLs, or `nil` (the default) to leave them unversioned. /// - siteOrigin: the public origin the page derives its canonical URL and language alternates from, or `nil` (the default) to omit them. /// - analytics: the analytics tracker embedded in the document head, or `nil` (the default) to omit it. init( locale: Locale, assetVersion: String? = nil, siteOrigin: String? = nil, analytics: Analytics? = nil ) { self.analytics = analytics self.assetVersion = assetVersion self.locale = locale self.siteOrigin = siteOrigin self.localize = .init(bundle: .module) } } // MARK: - Page extension IndexPage: Page { // MARK: Constants /// The path the page is served at; ``RootController`` registers its route against it, and the page builds its canonical URL from it. static let path = "/" // MARK: Computed /// The canonical URL of the page's edition in its language, or `nil` when the origin is unknown. /// /// The origin alone for the default language, since canonical URLs carry no trailing slash — `TrailingSlashRedirectMiddleware` enforces /// that on every path but the root, which has nothing to strip. var canonicalURL: String? { siteOrigin.map { Language(of: locale).url( origin: $0, path: Self.path ) } } /// The site-wide metadata, preceded by the `hreflang` alternates tying the page's language editions together. @HTMLBuilder var metadata: some HTML { languageAlternates( origin: siteOrigin, path: Self.path ) siteMetadata } // MARK: Properties /// The hero alone, until the listings exist. var content: some HTML { SiteLayout { div(.class("page")) { section(.class("hero")) { p(.class("type-eyebrow")) { "Single issues · Manga · Trades · Hardcovers" } h1(.class("type-hero")) { localize("index.heading", locale: locale) } p(.class("type-lead")) { "Search every listing by title, print and grade. Browse any seller's shop without an account — sign in with a passkey only when you're ready to buy, make an offer or message." } div(.class("hero__actions")) { a( .class("button button--primary button--lg"), .href(Format.singleIssues.path) ) { "Browse single issues" } a( .class("button button--outline button--lg"), .href(.Route.series) ) { "Browse by series" } } } } } } var scripts: [any Asset] { [StaticFile.index, StaticFile.shared] } var stylesheets: [any Asset] { [StaticFile.shared, StaticFile.index] } var title: String { localize("index.title", locale: locale) } }