Skip to content

Commit 9ae016c

Browse files
committed
Add navigator title to LinkDestinationSummary
The navigator title, which contains abbreviated fragments of a symbol's declaration for display in navigation [1], was missing from LinkDestinationSummary. The navigator title is used here [2], but the information wasn't being populated anywhere [3]. This commit captures the navigator title information from the render metadata, and stores it as part of `LinkDestinationSummary`. While the original information comes from the symbol graph [4], the `DocumentationContentRenderer` has some special logic to sanitise the declaration fragments, particularly for Swift [5]. In order to ensure that we have parity between internal and external navigator titles, used the render metadata rather than the original information from the symbol graph. This mirrors what we're already doing with the shortened declaration fragments, which also are processed with the same logic. Finally, `LinkDestinationSummary.makeTopicRenderReference()` has been updated to populate the navigator title variants, such that after this commit navigator titles will be correctly populated for external links in the navigator. Fixes rdar://156488184. [1]: https://github.com/swiftlang/swift-docc/blob/257c62d1ef11efc023667fda89c0cd4419a8afa3/Sources/SwiftDocC/Model/Rendering/References/TopicRenderReference.swift#L60-L63 [2]: https://github.com/swiftlang/swift-docc/blob/257c62d1ef11efc023667fda89c0cd4419a8afa3/Sources/SwiftDocC/Indexing/Navigator/RenderNode%2BNavigatorIndex.swift#L153 [3]: https://github.com/swiftlang/swift-docc/blob/257c62d1ef11efc023667fda89c0cd4419a8afa3/Sources/SwiftDocC/Infrastructure/Link%20Resolution/ExternalPathHierarchyResolver.swift#L225 [4]: https://github.com/swiftlang/swift-docc-symbolkit/blob/3fc0c6880f712ce38137d0752f24b568fce1522e/Sources/SymbolKit/SymbolGraph/Symbol/Names.swift#L23-L26 [5]: https://github.com/swiftlang/swift-docc/blob/257c62d1ef11efc023667fda89c0cd4419a8afa3/Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift#L87-L105
1 parent aa7f7dd commit 9ae016c

File tree

5 files changed

+81
-15
lines changed

5 files changed

+81
-15
lines changed

Sources/SwiftDocC/Infrastructure/Link Resolution/ExternalPathHierarchyResolver.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ extension LinkDestinationSummary {
172172
var titleVariants = VariantCollection(defaultValue: title)
173173
var abstractVariants = VariantCollection(defaultValue: abstract ?? [])
174174
var fragmentVariants = VariantCollection(defaultValue: declarationFragments)
175+
var navigatorTitleVariants = VariantCollection(defaultValue: navigatorTitle)
175176

176177
for variant in variants {
177178
let traits = variant.traits
@@ -184,6 +185,9 @@ extension LinkDestinationSummary {
184185
if let fragment = variant.declarationFragments {
185186
fragmentVariants.variants.append(.init(traits: traits, patch: [.replace(value: fragment)]))
186187
}
188+
if let navigatorTitle = variant.navigatorTitle {
189+
navigatorTitleVariants.variants.append(.init(traits: traits, patch: [.replace(value: navigatorTitle)]))
190+
}
187191
}
188192

189193
return TopicRenderReference(
@@ -195,7 +199,7 @@ extension LinkDestinationSummary {
195199
required: false,
196200
role: role,
197201
fragmentsVariants: fragmentVariants,
198-
navigatorTitleVariants: .init(defaultValue: nil),
202+
navigatorTitleVariants: navigatorTitleVariants,
199203
estimatedTime: nil,
200204
conformance: nil,
201205
isBeta: isBeta,

Sources/SwiftDocC/LinkTargets/LinkDestinationSummary.swift

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,12 @@ public struct LinkDestinationSummary: Codable, Equatable {
140140

141141
/// The rendered fragments of a symbol's declaration.
142142
public typealias DeclarationFragments = [DeclarationRenderSection.Token]
143-
/// The abbreviated fragments for this symbol's declaration, or `nil` if the summarized element isn't a symbol.
143+
/// The abbreviated fragments for this symbol's declaration, to display in links, or `nil` if the summarized element isn't a symbol.
144144
public let declarationFragments: DeclarationFragments?
145145

146+
/// The abbreviated fragments for this symbol's declaration, to display in navigation, or `nil` if the summarized element isn't a symbol.
147+
public let navigatorTitle: DeclarationFragments?
148+
146149
/// Any previous URLs for this element.
147150
///
148151
/// A web server can use this list of URLs to redirect to the current URL.
@@ -201,11 +204,16 @@ public struct LinkDestinationSummary: Codable, Equatable {
201204
/// If the summarized element has a full name but the variant doesn't, this property will be `Optional.some(nil)`.
202205
public let fullName: VariantValue<String?>
203206

204-
/// The abbreviated declaration of the variant or `nil` if the declaration is the same as the summarized element.
207+
/// The abbreviated declaration of the variant, to display in links, or `nil` if the declaration is the same as the summarized element.
205208
///
206209
/// If the summarized element has a declaration but the variant doesn't, this property will be `Optional.some(nil)`.
207210
public let declarationFragments: VariantValue<DeclarationFragments?>
208211

212+
/// The abbreviated declaration for this symbol's declaration, to display in navigation, or `nil` if the navigator title is the same as the summarized element.
213+
///
214+
/// If the summarized element has a navigator title but the variant doesn't, this property will be `Optional.some(nil)`.
215+
public let navigatorTitle: VariantValue<DeclarationFragments?>
216+
209217
/// Images that are used to represent the summarized element or `nil` if the images are the same as the summarized element.
210218
///
211219
/// If the summarized element has an image but the variant doesn't, this property will be `Optional.some(nil)`.
@@ -224,7 +232,8 @@ public struct LinkDestinationSummary: Codable, Equatable {
224232
/// - taskGroups: The taskGroups of the variant or `nil` if the taskGroups is the same as the summarized element.
225233
/// - usr: The precise symbol identifier of the variant or `nil` if the precise symbol identifier is the same as the summarized element.
226234
/// - fullName: The full name of this symbol, derived from its full declaration fragments, or `nil` if the precise symbol identifier is the same as the summarized element.
227-
/// - declarationFragments: The abbreviated declaration of the variant or `nil` if the declaration is the same as the summarized element.
235+
/// - declarationFragments: The abbreviated declaration of the variant, to display in links, or `nil` if the declaration is the same as the summarized element.
236+
/// - navigatorTitle: The abbreviated declaration for this symbol's declaration, to display in navigation, or `nil` if the declaration is the same as the summarized element.
228237
public init(
229238
traits: [RenderNode.Variant.Trait],
230239
kind: VariantValue<DocumentationNode.Kind> = nil,
@@ -235,7 +244,8 @@ public struct LinkDestinationSummary: Codable, Equatable {
235244
taskGroups: VariantValue<[LinkDestinationSummary.TaskGroup]?> = nil,
236245
usr: VariantValue<String?> = nil,
237246
fullName: VariantValue<String?> = nil,
238-
declarationFragments: VariantValue<LinkDestinationSummary.DeclarationFragments?> = nil
247+
declarationFragments: VariantValue<LinkDestinationSummary.DeclarationFragments?> = nil,
248+
navigatorTitle: VariantValue<LinkDestinationSummary.DeclarationFragments?> = nil
239249
) {
240250
self.traits = traits
241251
self.kind = kind
@@ -247,9 +257,10 @@ public struct LinkDestinationSummary: Codable, Equatable {
247257
self.usr = usr
248258
self.fullName = fullName
249259
self.declarationFragments = declarationFragments
260+
self.navigatorTitle = navigatorTitle
250261
}
251262

252-
@available(*, deprecated, renamed: "init(traits:kind:language:relativePresentationURL:title:abstract:taskGroups:usr:fullName:declarationFragments:)", message: "Use `init(traits:kind:language:relativePresentationURL:title:abstract:taskGroups:usr:fullName:declarationFragments:)` instead. `TopicRenderReference` doesn't support variant specific topic images. This property will be removed after 6.3 is released")
263+
@available(*, deprecated, renamed: "init(traits:kind:language:relativePresentationURL:title:abstract:taskGroups:usr:fullName:declarationFragments:navigatorTitle:)", message: "Use `init(traits:kind:language:relativePresentationURL:title:abstract:taskGroups:usr:fullName:declarationFragments:navigatorTitle:)` instead. `TopicRenderReference` doesn't support variant specific topic images. This property will be removed after 6.3 is released")
253264
public init(
254265
traits: [RenderNode.Variant.Trait],
255266
kind: VariantValue<DocumentationNode.Kind> = nil,
@@ -261,6 +272,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
261272
usr: VariantValue<String?> = nil,
262273
fullName: VariantValue<String?> = nil,
263274
declarationFragments: VariantValue<LinkDestinationSummary.DeclarationFragments?> = nil,
275+
navigatorTitle: VariantValue<LinkDestinationSummary.DeclarationFragments?> = nil,
264276
topicImages: VariantValue<[TopicImage]?> = nil
265277
) {
266278
self.init(
@@ -273,7 +285,8 @@ public struct LinkDestinationSummary: Codable, Equatable {
273285
taskGroups: taskGroups,
274286
usr: usr,
275287
fullName: fullName,
276-
declarationFragments: declarationFragments
288+
declarationFragments: declarationFragments,
289+
navigatorTitle: navigatorTitle
277290
)
278291
}
279292
}
@@ -295,7 +308,8 @@ public struct LinkDestinationSummary: Codable, Equatable {
295308
/// - taskGroups: The reference URLs of the summarized element's children, grouped by their task groups.
296309
/// - usr: The unique, precise identifier for this symbol that you use to reference it across different systems, or `nil` if the summarized element isn't a symbol.
297310
/// - fullName: The full name of this symbol, derived from its full declaration fragments, or `nil` if the summarized element isn't a symbol.
298-
/// - declarationFragments: The abbreviated fragments for this symbol's declaration, or `nil` if the summarized element isn't a symbol.
311+
/// - declarationFragments: The abbreviated fragments for this symbol's declaration, to display in links, or `nil` if the summarized element isn't a symbol.
312+
/// - navigatorTitle: The abbreviated fragments for this symbol's declaration, to display in navigation, or `nil` if the summarized element isn't a symbol.
299313
/// - redirects: Any previous URLs for this element, or `nil` if this element has no previous URLs.
300314
/// - topicImages: Images that are used to represent the summarized element, or `nil` if this element has no topic images.
301315
/// - references: References used in the content of the summarized element, or `nil` if this element has no references to other content.
@@ -312,6 +326,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
312326
usr: String? = nil,
313327
fullName: String? = nil,
314328
declarationFragments: LinkDestinationSummary.DeclarationFragments? = nil,
329+
navigatorTitle: LinkDestinationSummary.DeclarationFragments? = nil,
315330
redirects: [URL]? = nil,
316331
topicImages: [TopicImage]? = nil,
317332
references: [any RenderReference]? = nil,
@@ -329,6 +344,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
329344
self.usr = usr
330345
self.fullName = fullName
331346
self.declarationFragments = declarationFragments
347+
self.navigatorTitle = navigatorTitle
332348
self.redirects = redirects
333349
self.topicImages = topicImages
334350
self.references = references
@@ -492,6 +508,7 @@ extension LinkDestinationSummary {
492508
// However if no abbreviated declaration fragments are available, use the full declaration fragments instead.
493509
// In this case, they are assumed to be the same.
494510
let declaration = renderNode.metadata.fragmentsVariants.value(for: language) ?? (symbol.declarationVariants[summaryTrait] ?? symbol.declaration).renderDeclarationTokens()
511+
let navigatorTitle = renderNode.metadata.navigatorTitleVariants.value(for: language)
495512

496513
let variants: [Variant] = documentationNode.availableVariantTraits.compactMap { trait in
497514
// Skip the variant for the summarized elements source language.
@@ -516,6 +533,7 @@ extension LinkDestinationSummary {
516533
// However if no abbreviated declaration fragments are available, use the full declaration fragments instead.
517534
// In this case, they are assumed to be the same.
518535
let declarationVariant = renderNode.metadata.fragmentsVariants.value(for: variantTraits) ?? symbol.declarationVariants[trait]?.renderDeclarationTokens()
536+
let navigatorTitleVariant = renderNode.metadata.navigatorTitleVariants.value(for: variantTraits)
519537
return Variant(
520538
traits: variantTraits,
521539
kind: nilIfEqual(main: kind, variant: symbol.kindVariants[trait].map { DocumentationNode.kind(forKind: $0.identifier) }),
@@ -526,7 +544,8 @@ extension LinkDestinationSummary {
526544
taskGroups: nilIfEqual(main: taskGroups, variant: taskGroupVariants[variantTraits]),
527545
usr: nil, // The symbol variant uses the same USR
528546
fullName: nilIfEqual(main: fullName, variant: fullNameVariant),
529-
declarationFragments: nilIfEqual(main: declaration, variant: declarationVariant)
547+
declarationFragments: nilIfEqual(main: declaration, variant: declarationVariant),
548+
navigatorTitle: nilIfEqual(main: navigatorTitle, variant: navigatorTitleVariant)
530549
)
531550
}
532551

@@ -547,6 +566,7 @@ extension LinkDestinationSummary {
547566
usr: usr,
548567
fullName: fullName,
549568
declarationFragments: declaration,
569+
navigatorTitle: navigatorTitle,
550570
redirects: redirects,
551571
topicImages: topicImages.nilIfEmpty,
552572
references: references.nilIfEmpty,
@@ -628,7 +648,7 @@ extension LinkDestinationSummary {
628648
// Add Codable methods—which include an initializer—in an extension so that it doesn't override the member-wise initializer.
629649
extension LinkDestinationSummary {
630650
enum CodingKeys: String, CodingKey {
631-
case kind, referenceURL, title, abstract, language, taskGroups, usr, availableLanguages, platforms, redirects, topicImages, references, variants, fullName
651+
case kind, referenceURL, title, abstract, language, taskGroups, usr, availableLanguages, platforms, redirects, topicImages, references, variants, fullName, navigatorTitle
632652
case relativePresentationURL = "path"
633653
case declarationFragments = "fragments"
634654
}
@@ -662,6 +682,7 @@ extension LinkDestinationSummary {
662682
try container.encodeIfPresent(usr, forKey: .usr)
663683
try container.encodeIfPresent(fullName, forKey: .fullName)
664684
try container.encodeIfPresent(declarationFragments, forKey: .declarationFragments)
685+
try container.encodeIfPresent(navigatorTitle, forKey: .navigatorTitle)
665686
try container.encodeIfPresent(redirects, forKey: .redirects)
666687
try container.encodeIfPresent(topicImages, forKey: .topicImages)
667688
try container.encodeIfPresent(references?.map { CodableRenderReference($0) }, forKey: .references)
@@ -719,6 +740,7 @@ extension LinkDestinationSummary {
719740
usr = try container.decodeIfPresent(String.self, forKey: .usr)
720741
fullName = try container.decodeIfPresent(String.self, forKey: .fullName)
721742
declarationFragments = try container.decodeIfPresent(DeclarationFragments.self, forKey: .declarationFragments)
743+
navigatorTitle = try container.decodeIfPresent(DeclarationFragments.self, forKey: .navigatorTitle)
722744
redirects = try container.decodeIfPresent([URL].self, forKey: .redirects)
723745
topicImages = try container.decodeIfPresent([TopicImage].self, forKey: .topicImages)
724746
references = try container.decodeIfPresent([CodableRenderReference].self, forKey: .references).map { decodedReferences in
@@ -731,7 +753,7 @@ extension LinkDestinationSummary {
731753

732754
extension LinkDestinationSummary.Variant {
733755
enum CodingKeys: String, CodingKey {
734-
case traits, kind, title, abstract, language, usr, taskGroups, fullName
756+
case traits, kind, title, abstract, language, usr, taskGroups, fullName, navigatorTitle
735757
case relativePresentationURL = "path"
736758
case declarationFragments = "fragments"
737759
}
@@ -759,6 +781,7 @@ extension LinkDestinationSummary.Variant {
759781
try container.encodeIfPresent(usr, forKey: .usr)
760782
try container.encodeIfPresent(fullName, forKey: .fullName)
761783
try container.encodeIfPresent(declarationFragments, forKey: .declarationFragments)
784+
try container.encodeIfPresent(navigatorTitle, forKey: .navigatorTitle)
762785
try container.encodeIfPresent(taskGroups, forKey: .taskGroups)
763786
}
764787

@@ -801,6 +824,7 @@ extension LinkDestinationSummary.Variant {
801824
usr = try container.decodeIfPresent(String?.self, forKey: .usr)
802825
fullName = try container.decodeIfPresent(String?.self, forKey: .fullName)
803826
declarationFragments = try container.decodeIfPresent(LinkDestinationSummary.DeclarationFragments?.self, forKey: .declarationFragments)
827+
navigatorTitle = try container.decodeIfPresent(LinkDestinationSummary.DeclarationFragments?.self, forKey: .navigatorTitle)
804828
taskGroups = try container.decodeIfPresent([LinkDestinationSummary.TaskGroup]?.self, forKey: .taskGroups)
805829
}
806830
}

Tests/SwiftDocCTests/Indexing/RenderIndexTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ final class RenderIndexTests: XCTestCase {
8989
},
9090
{
9191
"path": "/documentation/mixedlanguageframework/bar",
92-
"title": "Bar",
92+
"title": "Bar (objective c)",
9393
"type": "class",
9494
"children": [
9595
{

0 commit comments

Comments
 (0)