diff --git a/Sources/SwiftDocC/Infrastructure/Link Resolution/ExternalPathHierarchyResolver.swift b/Sources/SwiftDocC/Infrastructure/Link Resolution/ExternalPathHierarchyResolver.swift index 44477ca52..4378130aa 100644 --- a/Sources/SwiftDocC/Infrastructure/Link Resolution/ExternalPathHierarchyResolver.swift +++ b/Sources/SwiftDocC/Infrastructure/Link Resolution/ExternalPathHierarchyResolver.swift @@ -165,7 +165,7 @@ extension LinkDestinationSummary { /// Create a topic render render reference for this link summary and its content variants. func makeTopicRenderReference() -> TopicRenderReference { - let (kind, role) = DocumentationContentRenderer.renderKindAndRole(kind, semantic: nil) + let (kind, role) = DocumentationContentRenderer.renderKindAndRole(kind, semantic: nil, linkSummary: self) var titleVariants = VariantCollection(defaultValue: title) var abstractVariants = VariantCollection(defaultValue: abstract ?? []) diff --git a/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift b/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift index 0d6ee8dd4..20fcf8d73 100644 --- a/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift +++ b/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift @@ -247,7 +247,7 @@ public class DocumentationContentRenderer { return true } - static func renderKindAndRole(_ kind: DocumentationNode.Kind?, semantic: Semantic?) -> (RenderNode.Kind, String) { + static func renderKindAndRole(_ kind: DocumentationNode.Kind?, semantic: Semantic? = nil, linkSummary: LinkDestinationSummary? = nil) -> (RenderNode.Kind, String) { guard let kind else { return (.article, role(for: .article).rawValue) } @@ -270,6 +270,9 @@ public class DocumentationContentRenderer { default: if let article = semantic as? Article { return (.article, roleForArticle(article, nodeKind: kind).rawValue) + } else if kind == .article, let summary = linkSummary, summary.taskGroups != nil { + // For external references: Articles with task groups are API Collections and should have collectionGroup role + return (.article, Self.role(for: .collectionGroup).rawValue) } else { return (.article, role) } diff --git a/Tests/SwiftDocCTests/Rendering/DocumentationContentRendererTests.swift b/Tests/SwiftDocCTests/Rendering/DocumentationContentRendererTests.swift index daf92c4e1..a04678f09 100644 --- a/Tests/SwiftDocCTests/Rendering/DocumentationContentRendererTests.swift +++ b/Tests/SwiftDocCTests/Rendering/DocumentationContentRendererTests.swift @@ -131,6 +131,24 @@ class DocumentationContentRendererTests: XCTestCase { ] ) } + + func testRenderKindAndRoleForAPICollection() throws { + // Articles with task groups should get collectionGroup role for external references + let apiCollectionSummary = LinkDestinationSummary( + kind: .article, + language: .swift, + relativePresentationURL: URL(string: "/documentation/test/external/api-collection")!, + referenceURL: URL(string: "doc://com.example.test/documentation/test/external/api-collection")!, + title: "External API Collection", + availableLanguages: [.swift], + taskGroups: [LinkDestinationSummary.TaskGroup(title: "Symbols", identifiers: ["doc://com.example.test/symbol1"])], + variants: [] + ) + + let (kind, role) = DocumentationContentRenderer.renderKindAndRole(.article, semantic: nil, linkSummary: apiCollectionSummary) + XCTAssertEqual(kind, RenderNode.Kind.article) + XCTAssertEqual(role, "collectionGroup") + } } private extension DocumentationDataVariantsTrait {