Skip to content

Commit 10aaa0a

Browse files
authored
Implemented alphabetic sorting by titles when automatically curating … (#1195) (#1207)
* Implemented alphabetic sorting by titles when automatically curating documentation + added testing and inline comments on such implementation * Transitioned to implict parameters within sorting closure, as well as additional test on case-insensitive sorting with its respective comments Co-authored-by: Ricardo Mendez Cavalieri <[email protected]> rdar://148534834
1 parent 68bb59d commit 10aaa0a

File tree

2 files changed

+114
-2
lines changed

2 files changed

+114
-2
lines changed

Sources/SwiftDocC/Infrastructure/DocumentationContext.swift

+8-2
Original file line numberDiff line numberDiff line change
@@ -2126,7 +2126,7 @@ public class DocumentationContext {
21262126
/// - otherArticles: Non-root articles to curate.
21272127
/// - rootNode: The node that will serve as the source of any topic graph edges created by this method.
21282128
/// - Throws: If looking up a `DocumentationNode` for the root module reference fails.
2129-
/// - Returns: An array of resolved references to the articles that were automatically curated.
2129+
/// - Returns: An array of resolved references to the articles that were automatically curated, sorted by their titles.
21302130
private func autoCurateArticles(_ otherArticles: DocumentationContext.Articles, startingFrom rootNode: TopicGraph.Node) throws -> [ResolvedTopicReference] {
21312131
let articlesToAutoCurate = otherArticles.filter { article in
21322132
let reference = article.topicGraphNode.reference
@@ -2140,8 +2140,14 @@ public class DocumentationContext {
21402140
topicGraph.addEdge(from: rootNode, to: article.topicGraphNode)
21412141
uncuratedArticles.removeValue(forKey: article.topicGraphNode.reference)
21422142
}
2143+
2144+
// Sort the articles by their titles to ensure a deterministic order
2145+
let sortedArticles = articlesToAutoCurate.sorted {
2146+
$0.topicGraphNode.title.lowercased() < $1.topicGraphNode.title.lowercased()
2147+
}
2148+
2149+
let articleReferences = sortedArticles.map(\.topicGraphNode.reference)
21432150

2144-
let articleReferences = articlesToAutoCurate.map(\.topicGraphNode.reference)
21452151
let automaticTaskGroup = AutomaticTaskGroupSection(
21462152
title: "Articles",
21472153
references: articleReferences,

Tests/SwiftDocCTests/Infrastructure/AutomaticCurationTests.swift

+106
Original file line numberDiff line numberDiff line change
@@ -1265,4 +1265,110 @@ class AutomaticCurationTests: XCTestCase {
12651265
XCTAssertFalse(renderNode.topicSections.first?.generated ?? false)
12661266
}
12671267
}
1268+
1269+
func testAutomaticallyCuratedArticlesAreSortedByTitle() throws {
1270+
// Test bundle with articles where file names and titles are in different orders
1271+
let catalog = Folder(name: "TestBundle.docc", content: [
1272+
JSONFile(name: "TestModule.symbols.json", content: makeSymbolGraph(moduleName: "TestModule")),
1273+
1274+
TextFile(name: "C-Article.md", utf8Content: """
1275+
# A Article
1276+
"""),
1277+
1278+
TextFile(name: "B-Article.md", utf8Content: """
1279+
# B Article
1280+
"""),
1281+
1282+
TextFile(name: "A-Article.md", utf8Content: """
1283+
# C Article
1284+
"""),
1285+
])
1286+
1287+
// Load the bundle
1288+
let (_, context) = try loadBundle(catalog: catalog)
1289+
XCTAssert(context.problems.isEmpty, "Unexpected problems: \(context.problems.map(\.diagnostic.summary))")
1290+
1291+
// Get the module and its automatic curation groups
1292+
let moduleReference = try XCTUnwrap(context.soleRootModuleReference)
1293+
let moduleNode = try XCTUnwrap(context.entity(with: moduleReference))
1294+
let symbol = try XCTUnwrap(moduleNode.semantic as? Symbol)
1295+
let articlesGroup = try XCTUnwrap(
1296+
symbol.automaticTaskGroups.first(where: { $0.title == "Articles" }),
1297+
"Expected 'Articles' automatic task group"
1298+
)
1299+
1300+
// Get the titles of the articles in the order they appear in the automatic curation
1301+
let titles = articlesGroup.references.compactMap {
1302+
context.topicGraph.nodes[$0]?.title
1303+
}
1304+
1305+
// Verify we have 3 articles in title order (A, B, C)—file order does not matter
1306+
XCTAssertEqual(titles, ["A Article", "B Article", "C Article"],
1307+
"Articles should be sorted by title, not by file name")
1308+
}
1309+
1310+
// autoCuratedArticles are sorted by title in a case-insensitive manner
1311+
// this test verifies that the sorting is correct even when the file names have different cases
1312+
func testAutomaticallyCuratedArticlesAreSortedByTitleDifferentCases() throws {
1313+
1314+
// In the catalog, the articles are named with the same letter, different cases,
1315+
// and other articles are added as well
1316+
let catalog = Folder(name: "TestBundle.docc", content: [
1317+
JSONFile(name: "TestModule.symbols.json", content: makeSymbolGraph(moduleName: "TestModule")),
1318+
1319+
TextFile(name: "C-article.md", utf8Content: """
1320+
# C Article
1321+
"""),
1322+
1323+
TextFile(name: "c-article.md", utf8Content: """
1324+
# c Article2
1325+
"""),
1326+
1327+
TextFile(name: "A-article.md", utf8Content: """
1328+
# A Article
1329+
"""),
1330+
1331+
TextFile(name: "a-article.md", utf8Content: """
1332+
# a Article2
1333+
"""),
1334+
1335+
TextFile(name: "B-article.md", utf8Content: """
1336+
# B Article
1337+
"""),
1338+
1339+
TextFile(name: "b-article.md", utf8Content: """
1340+
# b Article2
1341+
"""),
1342+
1343+
TextFile(name: "k-article.md", utf8Content: """
1344+
# k Article
1345+
"""),
1346+
1347+
1348+
TextFile(name: "random-article.md", utf8Content: """
1349+
# Z Article
1350+
"""),
1351+
])
1352+
1353+
// Load the bundle
1354+
let (_, context) = try loadBundle(catalog: catalog)
1355+
XCTAssert(context.problems.isEmpty, "Unexpected problems: \(context.problems.map(\.diagnostic.summary))")
1356+
1357+
// Get the module and its automatic curation groups
1358+
let moduleReference = try XCTUnwrap(context.soleRootModuleReference)
1359+
let moduleNode = try XCTUnwrap(context.entity(with: moduleReference))
1360+
let symbol = try XCTUnwrap(moduleNode.semantic as? Symbol)
1361+
let articlesGroup = try XCTUnwrap(
1362+
symbol.automaticTaskGroups.first(where: { $0.title == "Articles" }),
1363+
"Expected 'Articles' automatic task group"
1364+
)
1365+
1366+
let titles = articlesGroup.references.compactMap {
1367+
context.topicGraph.nodes[$0]?.title
1368+
}
1369+
1370+
// Verify that the articles are sorted by title, not by file name
1371+
XCTAssertEqual(titles, ["A Article", "a Article2", "B Article", "b Article2", "C Article", "c Article2", "k Article", "Z Article"],
1372+
"Articles should be sorted by title, not by file name")
1373+
}
12681374
}

0 commit comments

Comments
 (0)