Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ extension OutOfProcessReferenceResolver {
/// Information about the platforms and their versions where the resolved node is available, if any.
public let platforms: [PlatformAvailability]?
/// Information about the resolved declaration fragments, if any.
///
/// This is expected to be an abbreviated declaration for the symbol.
public let declarationFragments: DeclarationFragments?

// We use the real types here because they're Codable and don't have public member-wise initializers.
Expand Down Expand Up @@ -205,7 +207,7 @@ extension OutOfProcessReferenceResolver {
/// - language: The resolved language.
/// - availableLanguages: The languages where the resolved node is available.
/// - platforms: The platforms and their versions where the resolved node is available, if any.
/// - declarationFragments: The resolved declaration fragments, if any.
/// - declarationFragments: The resolved declaration fragments, if any. This is expected to be an abbreviated declaration for the symbol.
/// - topicImages: Images that are used to represent the summarized element.
/// - references: References used in the content of the summarized element.
/// - variants: The variants of content for this resolver information.
Expand Down Expand Up @@ -259,6 +261,8 @@ extension OutOfProcessReferenceResolver {
public let language: VariantValue<SourceLanguage>
/// The declaration fragments of the variant or `nil` if the declaration is the same as the resolved information.
///
/// This is expected to be an abbreviated declaration for the symbol.
///
/// If the resolver information has a declaration but the variant doesn't, this property will be `Optional.some(nil)`.
public let declarationFragments: VariantValue<DeclarationFragments?>

Expand All @@ -271,7 +275,7 @@ extension OutOfProcessReferenceResolver {
/// - title: The resolved title
/// - abstract: The resolved (plain text) abstract.
/// - language: The resolved language.
/// - declarationFragments: The resolved declaration fragments, if any.
/// - declarationFragments: The resolved declaration fragments, if any. This is expected to be an abbreviated declaration for the symbol.
public init(
traits: [RenderNode.Variant.Trait],
kind: VariantValue<DocumentationNode.Kind> = nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ final class ExternalPathHierarchyResolver {
return collidingNode.name
}
if let symbolID = collidingNode.symbol?.identifier {
if symbolID.interfaceLanguage == summary.language.id, let fragments = summary.declarationFragments {
return fragments.plainTextDeclaration()
if symbolID.interfaceLanguage == summary.language.id, let plainTextDeclaration = summary.plainTextDeclaration {
return plainTextDeclaration
}
if let variant = summary.variants.first(where: { $0.traits.contains(.interfaceLanguage(symbolID.interfaceLanguage)) }),
let fragments = variant.declarationFragments ?? summary.declarationFragments
let plainTextDeclaration = variant.plainTextDeclaration ?? summary.plainTextDeclaration
{
return fragments.plainTextDeclaration()
return plainTextDeclaration
}
}
return summary.title
Expand Down Expand Up @@ -153,12 +153,6 @@ final class ExternalPathHierarchyResolver {
}
}

private extension Sequence<DeclarationRenderSection.Token> {
func plainTextDeclaration() -> String {
return self.map(\.text).joined().split(whereSeparator: { $0.isWhitespace || $0.isNewline }).joined(separator: " ")
}
}

// MARK: ExternalEntity

extension LinkDestinationSummary {
Expand All @@ -177,7 +171,8 @@ extension LinkDestinationSummary {

var titleVariants = VariantCollection(defaultValue: title)
var abstractVariants = VariantCollection(defaultValue: abstract ?? [])
var fragmentVariants = VariantCollection(defaultValue: declarationFragments)
var fragmentVariants = VariantCollection(defaultValue: subheadingDeclarationFragments)
var navigatorTitleVariants = VariantCollection(defaultValue: navigatorDeclarationFragments)

for variant in variants {
let traits = variant.traits
Expand All @@ -187,9 +182,12 @@ extension LinkDestinationSummary {
if let abstract = variant.abstract {
abstractVariants.variants.append(.init(traits: traits, patch: [.replace(value: abstract ?? [])]))
}
if let fragment = variant.declarationFragments {
if let fragment = variant.subheadingDeclarationFragments {
fragmentVariants.variants.append(.init(traits: traits, patch: [.replace(value: fragment)]))
}
if let navigatorTitle = variant.navigatorDeclarationFragments {
navigatorTitleVariants.variants.append(.init(traits: traits, patch: [.replace(value: navigatorTitle)]))
}
}

return TopicRenderReference(
Expand All @@ -201,7 +199,7 @@ extension LinkDestinationSummary {
required: false,
role: role,
fragmentsVariants: fragmentVariants,
navigatorTitleVariants: .init(defaultValue: nil),
navigatorTitleVariants: navigatorTitleVariants,
estimatedTime: nil,
conformance: nil,
isBeta: isBeta,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ package struct ExternalRenderNode {
topicRenderReference.navigatorTitleVariants
}

/// The variants of the abbreviated declaration of the symbol to display in links and fall-back to in navigation.
///
/// This value is `nil` if the referenced page is not a symbol.
var fragmentsVariants: VariantCollection<[DeclarationRenderSection.Token]?> {
topicRenderReference.fragmentsVariants
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: since this is for the navigator, should it return the navigator title?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's meant to return the subheading declaration fragments AFAICT -- for internal links in the navigator, we store this information:

var navigatorTitle: [DeclarationRenderSection.Token]? {
wrapped.navigatorTitleVariants.value(for: traits)
}
var fragments: [DeclarationRenderSection.Token]? {
wrapped.fragmentsVariants.value(for: traits)
}

Where this type is wrapping RenderMetadata and these fragments are derived from the symbol subheading fragments:

/// Abbreviated declaration to display in links.
public var fragments: [DeclarationRenderSection.Token]? {
get { getVariantDefaultValue(keyPath: \.fragmentsVariants) }
set { setVariantDefaultValue(newValue, keyPath: \.fragmentsVariants) }
}
/// The variants for the fragments of a page.
public var fragmentsVariants: VariantCollection<[DeclarationRenderSection.Token]?> = .init(defaultValue: nil)

node.metadata.fragmentsVariants = contentRenderer.subHeadingFragments(for: documentationNode)

And then finally there's some logic when deriving the final navigator title, to choose to use either the subheading fragments or the navigator fragments:

/// Returns a navigator title preferring the fragments inside the metadata, if applicable.
func navigatorTitle() -> String? {
let tokens: [DeclarationRenderSection.Token]?
// FIXME: Use `metadata.navigatorTitle` for all Swift symbols (github.com/swiftlang/swift-docc/issues/176).
if identifier.sourceLanguage == .swift || (metadata.navigatorTitle ?? []).isEmpty {
let pageType = navigatorPageType()
guard !typesThatShouldNotUseNavigatorTitle.contains(pageType) else {
return metadata.title
}
tokens = metadata.fragments
} else {
tokens = metadata.navigatorTitle
}
return tokens?.map(\.text).joined() ?? metadata.title
}

}

/// Author provided images that represent this page.
var images: [TopicImage] {
entity.topicImages ?? []
Expand Down Expand Up @@ -129,7 +136,8 @@ struct NavigatorExternalRenderNode: NavigatorIndexableRenderNodeRepresentation {
role: renderNode.role,
symbolKind: renderNode.symbolKind?.renderingIdentifier,
images: renderNode.images,
isBeta: renderNode.isBeta
isBeta: renderNode.isBeta,
fragments: renderNode.fragmentsVariants.value(for: traits)
)
}
}
Expand All @@ -143,19 +151,16 @@ struct ExternalRenderNodeMetadataRepresentation: NavigatorIndexableRenderMetadat
var symbolKind: String?
var images: [TopicImage]
var isBeta: Bool
var fragments: [DeclarationRenderSection.Token]?

// Values that we have insufficient information to derive.
// These are needed to conform to the navigator indexable metadata protocol.
//
// The fragments that we get as part of the external link are the full declaration fragments.
// These are too verbose for the navigator, so instead of using them, we rely on the title, navigator title and symbol kind instead.
//
// The role heading is used to identify Property Lists.
// The value being missing is used for computing the final navigator title.
//
// The platforms are used for generating the availability index,
// but doesn't affect how the node is rendered in the sidebar.
var fragments: [DeclarationRenderSection.Token]? = nil
var roleHeading: String? = nil
var platforms: [AvailabilityRenderItem]? = nil
}
Loading