From 0ee8368e1ab0f27d71db5fc4981fd2950979f6da Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 23 Aug 2026 12:48:24 +0200 Subject: [PATCH] Added the organization identifier helper to the StructuredData type in the Infrastructure package target. --- .../Sources/Public/Types/StructuredData.swift | 16 +++++++++++++++- .../Cases/Public/Types/StructuredDataTests.swift | 13 +++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Packages/Infrastructure/Sources/Public/Types/StructuredData.swift b/Packages/Infrastructure/Sources/Public/Types/StructuredData.swift index d86fbcb..9f5d219 100644 --- a/Packages/Infrastructure/Sources/Public/Types/StructuredData.swift +++ b/Packages/Infrastructure/Sources/Public/Types/StructuredData.swift @@ -23,6 +23,20 @@ public struct StructuredData: Equatable, Sendable { self.nodes = nodes } + // MARK: Methods + + /// The `@id` of the `Organization` node ``init(name:url:alternateName:description:areaServed:email:logo:profiles:)`` builds. + /// + /// A page on another path that asserts a relationship to the organization — a `Person`'s `worksFor`, say — references this rather than + /// spelling the fragment a second time, so the two can never drift apart. + /// - Parameter url: the absolute URL the site is served at, as passed to that initializer. + /// - Returns: the organization node's `@id`. + public static func organizationID( + forSiteURL url: String + ) -> String { + url + "#organization" + } + // MARK: Computed /// The minified JSON-LD payload: the schema.org `@context`, and the ``nodes`` in a `@graph`. @@ -62,7 +76,7 @@ public extension StructuredData { logo: String? = nil, profiles: [String] = [] ) { - let id = url + "#organization" + let id = Self.organizationID(forSiteURL: url) var organization: [Property] = [ .init(.name, value: .string(name)), diff --git a/Packages/Infrastructure/Tests/Cases/Public/Types/StructuredDataTests.swift b/Packages/Infrastructure/Tests/Cases/Public/Types/StructuredDataTests.swift index 74be9d3..26638ed 100644 --- a/Packages/Infrastructure/Tests/Cases/Public/Types/StructuredDataTests.swift +++ b/Packages/Infrastructure/Tests/Cases/Public/Types/StructuredDataTests.swift @@ -46,6 +46,19 @@ struct StructuredDataTests { )) } + @Test + func `derives the organization's identifier from the site URL`() { + let url = "https://site.example/" + let data = StructuredData( + name: "A Site", + url: url + ) + + // The helper is what another page references the organization by, so it has to name the node this actually builds. + #expect(StructuredData.organizationID(forSiteURL: url) == "https://site.example/#organization") + #expect(data.payload.contains(##""@id":"\##(StructuredData.organizationID(forSiteURL: url))""##)) + } + @Test func `omits the properties of the facts minimal data does not carry`() { let data = StructuredData(