Skip to content

Commit b82a4a5

Browse files
committed
add a synthetic See Also section containing other modules in the same package to module pages
1 parent 18272e2 commit b82a4a5

File tree

4 files changed

+45
-15
lines changed

4 files changed

+45
-15
lines changed

Sources/UnidocLinker/Linker/DynamicLinker.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ extension DynamicLinker
7979
diagnostics: diagnostics,
8080
extensions: extensions)
8181

82+
self.synthesizeTopics()
8283
self.link(clients: clients)
8384

8485
// Create file records.
@@ -107,9 +108,34 @@ extension DynamicLinker
107108
}
108109
extension DynamicLinker
109110
{
111+
private mutating
112+
func synthesizeTopics()
113+
{
114+
115+
}
110116
private mutating
111117
func link(clients:[DynamicClientGroup])
112118
{
119+
// Create a synthetic topic containing all the cultures. This will become a “See Also”
120+
// for their module pages, unless they belong to a custom topic group.
121+
let cultures:Record.Group.Topic = .init(id: self.topic.id(),
122+
members: self.current.graph.cultures.indices.sorted
123+
{
124+
self.current.graph.namespaces[$0] <
125+
self.current.graph.namespaces[$1]
126+
}
127+
.map
128+
{
129+
.scalar(self.current.zone + $0 * .module)
130+
})
131+
132+
self.groups.append(.topic(cultures))
133+
134+
for c:Int in self.current.graph.cultures.indices
135+
{
136+
self.topics[c * .module] = cultures.id
137+
}
138+
113139
// First pass to create the topic records, which also populates topic memberships.
114140
for ((culture, input), clients):
115141
((Int, SymbolGraph.Culture), DynamicClientGroup) in zip(zip(
@@ -191,7 +217,7 @@ extension DynamicLinker
191217

192218
for case .scalar(let master) in record.members
193219
{
194-
// TODO: diagnose overlapping topics
220+
// This may replace a synthesized topic.
195221
if let local:Int32 = master - self.current.zone
196222
{
197223
self.topics[local] = record.id

Sources/UnidocPages/WideQuery.Output (ext).swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ extension WideQuery.Output:ServerResponseFactory
1616
type: .text(.plain, charset: .utf8)))
1717
}
1818

19-
if let master:Record.Master = principal.master,
20-
let tree:Record.NounTree = principal.tree
19+
if let master:Record.Master = principal.master
2120
{
2221
let resource:ServerResource
2322
let inliner:Inliner = .init(principal: master.id, zone: principal.zone)
@@ -33,27 +32,31 @@ extension WideQuery.Output:ServerResponseFactory
3332
inliner.outlines += $0.outlines
3433
}
3534

35+
/// Tree won’t exist if the module contains no declarations. (For example,
36+
/// an `@_exported` shim.)
37+
let nouns:[Record.Noun] = principal.tree?.rows ?? []
38+
3639
switch master
3740
{
3841
case .article(let master):
3942
let page:Site.Docs.Article = .init(inliner,
4043
master: master,
4144
groups: principal.groups,
42-
nouns: tree.rows)
45+
nouns: nouns)
4346
resource = page.rendered()
4447

4548
case .culture(let master):
4649
let page:Site.Docs.Culture = .init(inliner,
4750
master: master,
4851
groups: principal.groups,
49-
nouns: tree.rows)
52+
nouns: nouns)
5053
resource = page.rendered()
5154

5255
case .decl(let master):
5356
let page:Site.Docs.Decl = .init(inliner,
5457
master: master,
5558
groups: principal.groups,
56-
nouns: tree.rows)
59+
nouns: nouns)
5760
resource = page.rendered()
5861

5962
case .file:

Sources/UnidocRecords/Groups/Record.Group.Topic.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ extension Record.Group
99
let id:Unidoc.Scalar
1010

1111
public
12-
let culture:Unidoc.Scalar
12+
let culture:Unidoc.Scalar?
1313
public
14-
let scope:Unidoc.Scalar
14+
let scope:Unidoc.Scalar?
1515

1616
/// Additional scalars to prefetch when this extension is loaded.
1717
/// This is used to obtain the masters for passage referents in the
@@ -27,8 +27,8 @@ extension Record.Group
2727

2828
@inlinable public
2929
init(id:Unidoc.Scalar,
30-
culture:Unidoc.Scalar,
31-
scope:Unidoc.Scalar,
30+
culture:Unidoc.Scalar? = nil,
31+
scope:Unidoc.Scalar? = nil,
3232
prefetch:[Unidoc.Scalar] = [],
3333
overview:Record.Passage? = nil,
3434
members:[Record.Link] = [])

Sources/UnidocRecords/Groups/Record.Group.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ extension Record.Group
2626
/// constraints, which contain scalars.
2727
case conditions = "g"
2828

29-
/// Always present, contains a scalar.
29+
/// Always present in ``Extension``, optional in ``Topic``, and contains a scalar.
3030
case culture = "c"
31-
/// Always present, contains a scalar (but usually doesn’t need a secondary lookup).
31+
/// Always present in ``Extension``, optional in ``Topic``, and contains a scalar.
32+
/// Usually doesn’t need a secondary lookup.
3233
case scope = "X"
3334

3435
/// Optional and appears in ``Extension`` only.
@@ -133,7 +134,7 @@ extension Record.Group:BSONDocumentEncodable
133134
bson[.overview] = self.overview
134135
bson[.members] = self.members.isEmpty ? nil : self.members
135136

136-
zones.update(with: self.culture.zone)
137+
zones.update(with: self.culture?.zone)
137138
zones.update(with: self.prefetch)
138139
}
139140

@@ -149,8 +150,8 @@ extension Record.Group:BSONDocumentDecodable
149150
if case .topic? = id.plane
150151
{
151152
self = .topic(.init(id: id,
152-
culture: try bson[.culture].decode(),
153-
scope: try bson[.scope].decode(),
153+
culture: try bson[.culture]?.decode(),
154+
scope: try bson[.scope]?.decode(),
154155
prefetch: try bson[.prefetch]?.decode() ?? [],
155156
overview: try bson[.overview]?.decode(),
156157
members: try bson[.members]?.decode() ?? []))

0 commit comments

Comments
 (0)