Skip to content

Commit fd549d4

Browse files
authored
Revert "Revert "Minimally integrate per-page HTML content into each "index.ht…" (#1393)
This reverts commit db163a1.
1 parent db163a1 commit fd549d4

16 files changed

+900
-39
lines changed

Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ let package = Package(
4444
name: "SwiftDocC",
4545
dependencies: [
4646
.target(name: "DocCCommon"),
47+
.target(name: "DocCHTML"),
4748
.product(name: "Markdown", package: "swift-markdown"),
4849
.product(name: "SymbolKit", package: "swift-docc-symbolkit"),
4950
.product(name: "CLMDB", package: "swift-lmdb"),

Sources/SwiftDocC/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ add_library(SwiftDocC
175175
Model/Rendering/Diffing/Differences.swift
176176
Model/Rendering/Diffing/RenderNode+Diffable.swift
177177
Model/Rendering/DocumentationContentRenderer.swift
178+
Model/Rendering/HTML/HTMLContentConsumer.swift
179+
Model/Rendering/HTML/HTMLRenderer.swift
178180
Model/Rendering/LinkTitleResolver.swift
179181
"Model/Rendering/Navigation Tree/RenderHierarchy.swift"
180182
"Model/Rendering/Navigation Tree/RenderHierarchyChapter.swift"
@@ -465,6 +467,8 @@ add_library(SwiftDocC
465467
Utility/Version.swift)
466468
target_link_libraries(SwiftDocC PRIVATE
467469
DocCCommon)
470+
target_link_libraries(SwiftDocC PRIVATE
471+
DocCHTML)
468472
target_link_libraries(SwiftDocC PUBLIC
469473
SwiftMarkdown::Markdown
470474
DocC::SymbolKit

Sources/SwiftDocC/Infrastructure/ConvertActionConverter.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ package enum ConvertActionConverter {
2626
/// - Parameters:
2727
/// - context: The context that the bundle is a part of.
2828
/// - outputConsumer: The consumer that the conversion passes outputs of the conversion to.
29+
/// - htmlContentConsumer: The consumer for HTML content that the conversion produces, or `nil` if the conversion shouldn't produce any HTML content.
2930
/// - sourceRepository: The source repository where the documentation's sources are hosted.
3031
/// - emitDigest: Whether the conversion should pass additional metadata output––such as linkable entities information, indexing information, or asset references by asset type––to the consumer.
3132
/// - documentationCoverageOptions: The level of experimental documentation coverage information that the conversion should pass to the consumer.
3233
/// - Returns: A list of problems that occurred during the conversion (excluding the problems that the context already encountered).
3334
package static func convert(
3435
context: DocumentationContext,
3536
outputConsumer: some ConvertOutputConsumer & ExternalNodeConsumer,
37+
htmlContentConsumer: (any HTMLContentConsumer)?,
3638
sourceRepository: SourceRepository?,
3739
emitDigest: Bool,
3840
documentationCoverageOptions: DocumentationCoverageOptions
@@ -103,15 +105,27 @@ package enum ConvertActionConverter {
103105

104106
let renderSignpostHandle = signposter.beginInterval("Render", id: signposter.makeSignpostID(), "Render \(context.knownPages.count) pages")
105107

106-
var conversionProblems: [Problem] = context.knownPages.concurrentPerform { identifier, results in
108+
var conversionProblems: [Problem] = context.knownPages.concurrentPerform { [htmlContentConsumer] identifier, results in
107109
// If cancelled skip all concurrent conversion work in this block.
108110
guard !Task.isCancelled else { return }
109111

110112
// Wrap JSON encoding in an autorelease pool to avoid retaining the autoreleased ObjC objects returned by `JSONSerialization`
111113
autoreleasepool {
112114
do {
113115
let entity = try context.entity(with: identifier)
114-
116+
117+
if let htmlContentConsumer {
118+
var renderer = HTMLRenderer(reference: identifier, context: context, goal: .conciseness)
119+
120+
if let symbol = entity.semantic as? Symbol {
121+
let renderedPageInfo = renderer.renderSymbol(symbol)
122+
try htmlContentConsumer.consume(pageInfo: renderedPageInfo, forPage: identifier)
123+
} else if let article = entity.semantic as? Article {
124+
let renderedPageInfo = renderer.renderArticle(article)
125+
try htmlContentConsumer.consume(pageInfo: renderedPageInfo, forPage: identifier)
126+
}
127+
}
128+
115129
guard let renderNode = converter.renderNode(for: entity) else {
116130
// No render node was produced for this entity, so just skip it.
117131
return
@@ -247,3 +261,16 @@ package enum ConvertActionConverter {
247261
return conversionProblems
248262
}
249263
}
264+
265+
private extension HTMLContentConsumer {
266+
func consume(pageInfo: HTMLRenderer.RenderedPageInfo, forPage reference: ResolvedTopicReference) throws {
267+
try consume(
268+
mainContent: pageInfo.content,
269+
metadata: (
270+
title: pageInfo.metadata.title,
271+
description: pageInfo.metadata.plainDescription
272+
),
273+
forPage: reference
274+
)
275+
}
276+
}

Sources/SwiftDocC/Infrastructure/ConvertOutputConsumer.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
import Foundation
12-
1311
/// A consumer for output produced by a documentation conversion.
1412
///
1513
/// Types that conform to this protocol manage what to do with documentation conversion products, for example persist them to disk
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2025 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See https://swift.org/LICENSE.txt for license information
8+
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
#if canImport(FoundationXML)
12+
// TODO: Consider other HTML rendering options as a future improvement (rdar://165755530)
13+
package import FoundationXML
14+
#else
15+
package import Foundation
16+
#endif
17+
18+
/// A consumer for HTML content produced during documentation conversion.
19+
package protocol HTMLContentConsumer {
20+
// One reason that this is its own protocol, rather than an extension of ConvertOutputConsumer, is so that we can avoid exposing `XMLNode` in any public API.
21+
// That way, we are completely free to replace the entire internal HTML rendering implementation with something else in the future, without breaking API.
22+
23+
/// Consumes the HTML content and metadata for a given page.
24+
///
25+
/// The content and metadata doesn't make up a full valid HTML page.
26+
/// It's the consumers responsibility to insert the information into a template or skeletal structure to produce a valid HTML file for each page.
27+
///
28+
/// - Parameters:
29+
/// - mainContent: The contents for this page as an XHTML node.
30+
/// - metadata: Metadata information (title and description) about this page.
31+
/// - reference: The resolved topic reference that identifies this page.
32+
func consume(
33+
mainContent: XMLNode,
34+
metadata: (
35+
title: String,
36+
description: String?
37+
),
38+
forPage reference: ResolvedTopicReference
39+
) throws
40+
}

0 commit comments

Comments
 (0)