diff --git a/Sources/CLI/client/AppleDocumentationClient+DTO.swift b/Sources/CLI/client/AppleDocumentationClient+DTO.swift index c627531..e5dbf44 100644 --- a/Sources/CLI/client/AppleDocumentationClient+DTO.swift +++ b/Sources/CLI/client/AppleDocumentationClient+DTO.swift @@ -111,7 +111,7 @@ struct DocumentationMetadataDTO: Decodable, Sendable { let modules: [DocumentationModule] let platforms: [DocumentationPlatform] let roleHeading: String - let symbolKind: String + let symbolKind: String? let title: String private enum CodingKeys: CodingKey { @@ -124,10 +124,10 @@ struct DocumentationMetadataDTO: Decodable, Sendable { init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - modules = try container.decode([DocumentationModule].self, forKey: .modules) + modules = try container.decodeIfPresent([DocumentationModule].self, forKey: .modules) ?? [] platforms = try container.decodeIfPresent([DocumentationPlatform].self, forKey: .platforms) ?? [] roleHeading = try container.decode(String.self, forKey: .roleHeading) - symbolKind = try container.decode(String.self, forKey: .symbolKind) + symbolKind = try container.decodeIfPresent(String.self, forKey: .symbolKind) title = try container.decode(String.self, forKey: .title) } } diff --git a/Sources/CLI/renderer/TextTypeDocumentationRenderer.swift b/Sources/CLI/renderer/TextTypeDocumentationRenderer.swift index 3f827c3..94d0de4 100644 --- a/Sources/CLI/renderer/TextTypeDocumentationRenderer.swift +++ b/Sources/CLI/renderer/TextTypeDocumentationRenderer.swift @@ -5,10 +5,11 @@ struct TextTypeDocumentationRenderer: Sendable { let content = DocumentationContentRenderer(references: page.references) let metadata = ([page.metadata.roleHeading] + page.metadata.modules.map(\.name)) .filter { !$0.isEmpty }.joined(separator: " · ") - var sections = [ - layout.heading(page.metadata.title, prominent: true) + "\n" + metadata - + "\nSymbol kind: " + page.metadata.symbolKind - ] + var header = layout.heading(page.metadata.title, prominent: true) + "\n" + metadata + if let symbolKind = page.metadata.symbolKind { + header += "\nSymbol kind: " + symbolKind + } + var sections = [header] let abstract = content.inlineText(page.abstract) if !abstract.isEmpty { diff --git a/Tests/CLITests/renderer/DefaultTypeDocumentationRendererTests.swift b/Tests/CLITests/renderer/DefaultTypeDocumentationRendererTests.swift index 878d983..9110a80 100644 --- a/Tests/CLITests/renderer/DefaultTypeDocumentationRendererTests.swift +++ b/Tests/CLITests/renderer/DefaultTypeDocumentationRendererTests.swift @@ -76,6 +76,46 @@ struct DefaultTypeDocumentationRendererTests { ) } + @Test("renders articles without module or symbol metadata") + func rendersArticleWithoutSymbolMetadata() throws { + // -- Arrange -- + let rawJSON = """ + { + "kind": "article", + "abstract": [{"text": "Distribute binaries in Swift packages.", "type": "text"}], + "metadata": { + "role": "article", + "roleHeading": "Article", + "title": "Distributing binary frameworks as Swift packages" + }, + "primaryContentSections": [{ + "kind": "content", + "content": [ + {"type": "heading", "level": 2, "text": "Overview"}, + { + "type": "paragraph", + "inlineContent": [{"type": "text", "text": "Create an XCFramework bundle."}] + } + ] + }], + "references": {} + } + """ + let document = try makeDocument(rawJSON) + let renderer = DefaultTypeDocumentationRenderer(output: .text) + + // -- Act -- + let output = try renderer.render(document) + + // -- Assert -- + #expect(output.hasPrefix("Distributing binary frameworks as Swift packages\n")) + #expect(output.contains("\nArticle\n\n Distribute binaries in Swift packages.")) + #expect(output.contains("Overview\n────────\n\n Create an XCFramework bundle.")) + #expect(!output.contains("Symbol kind:")) + #expect(!output.contains("Availability")) + #expect(!output.contains("Declaration")) + } + @Test("returns Apple's DocC JSON unchanged") func rendersRawJSON() throws { // -- Arrange --