Skip to content

Commit d3d19c3

Browse files
authored
Fix api collection icon rendering (#1343)
* Add test for API Collection icon rendering in external references Adds tests to verify that API Collections (articles with Topics sections) are correctly identified as .collectionGroup kind in linkable entities, ensuring cross-framework references display the correct icon. Includes regression test for explicit @pagekind(article) metadata override behavior to ensure the fix doesn't break existing functionality. The first test is temporarily skipped until the fix is implemented in the next commit. rdar://135837611 * Fix API Collection icon rendering for external references Ensures API Collections are correctly identified as collectionGroup kind in linkable entities by using DocumentationContentRenderer.roleForArticle logic. This fixes cross-framework references where API Collections were incorrectly showing Article icons instead of Collection Group icons. rdar://135837611
1 parent 5915e66 commit d3d19c3

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

Sources/SwiftDocC/LinkTargets/LinkDestinationSummary.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,18 @@ private extension DocumentationNode {
10171017
// specialized articles, like sample code pages, that benefit from being treated as articles in
10181018
// some parts of the compilation process (like curation) but not others (like link destination
10191019
// summary creation and render node translation).
1020-
return metadata?.pageKind?.kind.documentationNodeKind ?? kind
1020+
let baseKind = metadata?.pageKind?.kind.documentationNodeKind ?? kind
1021+
1022+
// For articles, check if they should be treated as API Collections (collectionGroup).
1023+
// This ensures that linkable entities have the same kind detection logic as the rendering system,
1024+
// fixing cross-framework references where API Collections were incorrectly showing as articles.
1025+
if baseKind == .article,
1026+
let article = semantic as? Article,
1027+
DocumentationContentRenderer.roleForArticle(article, nodeKind: kind) == .collectionGroup {
1028+
return .collectionGroup
1029+
}
1030+
1031+
return baseKind
10211032
}
10221033
}
10231034

Tests/SwiftDocCTests/LinkTargets/LinkDestinationSummaryTests.swift

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,4 +829,94 @@ class LinkDestinationSummaryTests: XCTestCase {
829829
"doc://com.example.mymodule/documentation/MyModule/MyClass/myFunc()-9a7po",
830830
])
831831
}
832+
833+
/// Tests that API Collections (articles with Topics sections) are correctly identified as `.collectionGroup`
834+
/// kind in linkable entities, ensuring cross-framework references display the correct icon.
835+
func testAPICollectionKindForLinkDestinationSummary() async throws {
836+
let symbolGraph = makeSymbolGraph(
837+
moduleName: "TestModule",
838+
symbols: [makeSymbol(id: "test-class", kind: .class, pathComponents: ["TestClass"])]
839+
)
840+
841+
let catalogHierarchy = Folder(name: "unit-test.docc", content: [
842+
TextFile(name: "APICollection.md", utf8Content: """
843+
# API Collection
844+
845+
This is an API Collection that curates symbols.
846+
847+
## Topics
848+
849+
- ``TestModule/TestClass``
850+
"""),
851+
JSONFile(name: "TestModule.symbols.json", content: symbolGraph)
852+
])
853+
854+
let (_, context) = try await loadBundle(catalog: catalogHierarchy)
855+
let converter = DocumentationNodeConverter(context: context)
856+
857+
let apiCollectionReference = ResolvedTopicReference(
858+
bundleID: context.inputs.id,
859+
path: "/documentation/unit-test/APICollection",
860+
sourceLanguage: .swift
861+
)
862+
let node = try context.entity(with: apiCollectionReference)
863+
let renderNode = converter.convert(node)
864+
865+
let summaries = node.externallyLinkableElementSummaries(context: context, renderNode: renderNode)
866+
let pageSummary = try XCTUnwrap(summaries.first)
867+
868+
XCTAssertEqual(pageSummary.kind, .collectionGroup)
869+
XCTAssertEqual(pageSummary.title, "API Collection")
870+
XCTAssertEqual(pageSummary.abstract, [.text("This is an API Collection that curates symbols.")])
871+
872+
// Verify round-trip encoding preserves the correct kind
873+
try assertRoundTripCoding(pageSummary)
874+
}
875+
876+
/// Tests that explicit `@PageKind(article)` metadata overrides API Collection detection,
877+
/// ensuring that explicit page kind directives take precedence over automatic detection.
878+
func testExplicitPageKindOverridesAPICollectionDetection() async throws {
879+
let symbolGraph = makeSymbolGraph(
880+
moduleName: "TestModule",
881+
symbols: [makeSymbol(id: "test-class", kind: .class, pathComponents: ["TestClass"])]
882+
)
883+
884+
let catalogHierarchy = Folder(name: "unit-test.docc", content: [
885+
TextFile(name: "ExplicitArticle.md", utf8Content: """
886+
# Explicit Article
887+
888+
This looks like an API Collection but is explicitly marked as an article.
889+
890+
@Metadata {
891+
@PageKind(article)
892+
}
893+
894+
## Topics
895+
896+
- ``TestModule/TestClass``
897+
"""),
898+
JSONFile(name: "TestModule.symbols.json", content: symbolGraph)
899+
])
900+
901+
let (_, context) = try await loadBundle(catalog: catalogHierarchy)
902+
let converter = DocumentationNodeConverter(context: context)
903+
904+
let explicitArticleReference = ResolvedTopicReference(
905+
bundleID: context.inputs.id,
906+
path: "/documentation/unit-test/ExplicitArticle",
907+
sourceLanguage: .swift
908+
)
909+
let node = try context.entity(with: explicitArticleReference)
910+
let renderNode = converter.convert(node)
911+
912+
let summaries = node.externallyLinkableElementSummaries(context: context, renderNode: renderNode)
913+
let pageSummary = try XCTUnwrap(summaries.first)
914+
915+
// Should be .article because of explicit @PageKind(article), not .collectionGroup
916+
XCTAssertEqual(pageSummary.kind, .article)
917+
XCTAssertEqual(pageSummary.title, "Explicit Article")
918+
919+
// Verify round-trip encoding preserves the correct kind
920+
try assertRoundTripCoding(pageSummary)
921+
}
832922
}

0 commit comments

Comments
 (0)