Skip to content
Closed
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 @@ -45,7 +45,7 @@ extension API.PackageController.GetRoute {
var isArchived: Bool
var hasBinaryTargets: Bool
var homepageUrl: String?
var documentationTarget: DocumentationTarget? = nil
var currentDocumentationTarget: DocumentationTarget? = nil
var weightedKeywords: [WeightedKeyword]
var releaseReferences: [App.Version.Kind: App.Reference]
var fundingLinks: [FundingLink]
Expand Down Expand Up @@ -75,7 +75,7 @@ extension API.PackageController.GetRoute {
isArchived: Bool,
hasBinaryTargets: Bool = false,
homepageUrl: String? = nil,
documentationTarget: DocumentationTarget? = nil,
currentDocumentationTarget: DocumentationTarget? = nil,
weightedKeywords: [WeightedKeyword] = [],
defaultBranchReference: App.Reference,
releaseReference: App.Reference?,
Expand Down Expand Up @@ -109,7 +109,7 @@ extension API.PackageController.GetRoute {
self.isArchived = isArchived
self.hasBinaryTargets = hasBinaryTargets
self.homepageUrl = homepageUrl
self.documentationTarget = documentationTarget
self.currentDocumentationTarget = currentDocumentationTarget
self.weightedKeywords = weightedKeywords
self.releaseReferences = {
var refs = [App.Version.Kind.defaultBranch: defaultBranchReference]
Expand Down Expand Up @@ -171,7 +171,7 @@ extension API.PackageController.GetRoute {
isArchived: repository.isArchived,
hasBinaryTargets: result.defaultBranchVersion.hasBinaryTargets,
homepageUrl: repository.homepageUrl,
documentationTarget: result.canonicalDocumentationTarget(),
currentDocumentationTarget: result.currentDocumentationTarget(),
weightedKeywords: weightedKeywords,
defaultBranchReference: result.defaultBranchVersion.reference,
releaseReference: result.releaseVersion?.reference,
Expand Down
12 changes: 12 additions & 0 deletions Sources/App/Controllers/PackageController+PackageResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,16 @@ extension PackageController.PackageResult {
preReleaseVersion?.model
].canonicalDocumentationTarget()
}

func currentDocumentationTarget() -> DocumentationTarget? {
guard let target = canonicalDocumentationTarget()
else { return nil }

switch target {
case .external:
return target
case .internal(_, let archive):
return .internal(docVersion: .current(referencing: nil), archive: archive)
}
}
}
26 changes: 10 additions & 16 deletions Sources/App/Controllers/PackageController+routes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,11 @@ enum PackageController {
.init(archive: $0, isCurrent: $0.name == route.archive)
}

let canonicalUrl: String? = {
guard let canonicalOwner = documentationMetadata.owner,
let canonicalRepository = documentationMetadata.repository,
let canonicalTarget = documentationMetadata.canonicalTarget
else { return nil }

return Self.canonicalDocumentationUrl(from: "\(req.url)",
owner: canonicalOwner,
repository: canonicalRepository,
docVersion: route.docVersion,
toTarget: canonicalTarget)
}()

let canonicalUrl = Self.canonicalDocumentationUrl(from: "\(req.url)",
owner: documentationMetadata.owner,
repository: documentationMetadata.repository,
docVersion: route.docVersion,
toTarget: documentationMetadata.canonicalTarget)

// Try and parse the page and add our header, but fall back to the unprocessed page if it fails.
guard let body = awsResponse.body,
Expand Down Expand Up @@ -466,10 +458,12 @@ extension PackageController {

extension PackageController {
static func canonicalDocumentationUrl(from url: String,
owner: String,
repository: String,
owner: String?,
repository: String?,
docVersion: DocVersion,
toTarget target: DocumentationTarget) -> String? {
toTarget target: DocumentationTarget?) -> String? {
guard let owner, let repository, let target else { return nil }

// It's important to use `docVersion.reference` here to make sure we match with true reference urls and not ~
let urlPrefix = "/\(owner)/\(repository)/\(docVersion.reference.pathEncoded)/"
if case let .internal(canonicalReference, _) = target,
Expand Down
6 changes: 3 additions & 3 deletions Sources/App/Views/DocumentationPageProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ struct DocumentationPageProcessor {
try document.head()?.append(self.javascriptLinks)
if let canonicalUrl = self.canonicalUrl {
try document.head()?.append(
// We should not use `url` here as some of the DocC JavaScript lowercases
// both the `og:url` and `twitter:url` properties, if present. It is better
// to have no `og:url` and `twitter:url` properties than incorrect ones.
// We should not use Plot's `url` helper here as some of the DocC JavaScript
// lowercases both the `og:url` and `twitter:url` properties, if present. It's
// better to have no `og:url` and `twitter:url` properties than incorrect ones.
Plot.Node.link(
.rel(.canonical),
.href(canonicalUrl)
Expand Down
2 changes: 1 addition & 1 deletion Sources/App/Views/PackageController/PackageShow+View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ extension PackageShow {
)
)
},
.unwrap(model.documentationTarget) { target in
.unwrap(model.currentDocumentationTarget) { target in
.li(
.a(
.href(SiteURL.relativeURL(owner: model.repositoryOwner,
Expand Down
10 changes: 3 additions & 7 deletions Tests/AppTests/API+PackageController+GetRoute+ModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,14 @@ class API_PackageController_GetRoute_ModelTests: SnapshotTestCase {
swift6Readiness: nil))

// validate
XCTAssertEqual(model.documentationTarget, .internal(docVersion: .reference("main"), archive: "archive1"))
XCTAssertEqual(model.currentDocumentationTarget, .internal(docVersion: .current(referencing: nil), archive: "archive1"))
}

func test_init_external_documentation() async throws {
let pkg = try await savePackage(on: app.db, "1".url)
try await Repository(package: pkg, name: "bar", owner: "foo").save(on: app.db)
let version = try App.Version(package: pkg, latest: .defaultBranch, packageName: nil, reference: .branch("main"))
version.spiManifest = try .init(yml: """
version: 1
external_links:
documentation: "https://example.com/package/documentation"
""")
version.spiManifest = .init(externalLinks: .init(documentation: "https://example.com/package/documentation"))
try await version.save(on: app.db)
let packageResult = try await PackageResult.query(on: app.db, owner: "foo", repository: "bar")

Expand All @@ -115,7 +111,7 @@ class API_PackageController_GetRoute_ModelTests: SnapshotTestCase {
swift6Readiness: nil))

// validate
XCTAssertEqual(model.documentationTarget, .external(url: "https://example.com/package/documentation"))
XCTAssertEqual(model.currentDocumentationTarget, .external(url: "https://example.com/package/documentation"))
}

func test_gitHubOwnerUrl() throws {
Expand Down
84 changes: 84 additions & 0 deletions Tests/AppTests/PackageResultTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -285,4 +285,88 @@
XCTAssertEqual(res.canonicalDocumentationTarget(), nil)
}
}

func test_currentDocumentationTarget() async throws {
do {
// Test package with branch docs and stable version docs
let pkg = try savePackage(on: app.db, "1".url)

Check failure on line 292 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 292 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 292 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 292 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 292 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 292 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 292 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 292 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'
try await Repository(package: pkg,
defaultBranch: "main",
forks: 42,
license: .mit,
name: "bar1",
owner: "foo",
stars: 17,
summary: "summary").save(on: app.db)
try await App.Version(package: pkg,
docArchives: [.init(name: "archive1", title: "Archive 1")],
latest: .defaultBranch,
reference: .branch("main")).save(on: app.db)
try await App.Version(package: pkg,
// Note the name change on the default branch. The current should point to this archive.
docArchives: [.init(name: "archive2", title: "Archive 2")],
latest: .release,
reference: .tag(1, 2, 3)).save(on: app.db)
}

do {
// Test package with only branch docs hosted externally.
let pkg = try savePackage(on: app.db, "2".url)

Check failure on line 314 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 314 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 314 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 314 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 314 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 314 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'
try await Repository(package: pkg,
defaultBranch: "main",
forks: 42,
license: .mit,
name: "bar2",
owner: "foo",
stars: 17,
summary: "summary").save(on: app.db)
try await App.Version(package: pkg,
latest: .defaultBranch,
reference: .branch("main"),
spiManifest: .init(externalLinks: .init(documentation: "https://example.com"))).save(on: app.db)
}

do {
// Test package with no documentation
let pkg = try savePackage(on: app.db, "3".url)

Check failure on line 331 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 331 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 331 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 331 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 331 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'

Check failure on line 331 in Tests/AppTests/PackageResultTests.swift

View workflow job for this annotation

GitHub Actions / Test

expression is 'async' but is not marked with 'await'
try await Repository(package: pkg,
defaultBranch: "main",
forks: 42,
license: .mit,
name: "bar3",
owner: "foo",
stars: 17,
summary: "summary").save(on: app.db)
try await App.Version(package: pkg,
latest: .defaultBranch,
reference: .branch("main")).save(on: app.db)
}

do {
// Testing for internally hosted documentation pointing at the "current".
let res = try await PackageController.PackageResult.query(on: app.db, owner: "foo", repository: "bar1")
let currentTarget = try XCTUnwrap(res.currentDocumentationTarget())

// Validaton
XCTAssertEqual(currentTarget, .internal(docVersion: .current(referencing: nil), archive: "archive2"))
}

do {
// Testing for `.external` case pass-through.
let res = try await PackageController.PackageResult.query(on: app.db, owner: "foo", repository: "bar2")
let currentTarget = try XCTUnwrap(res.currentDocumentationTarget())

// Validaton
XCTAssertEqual(currentTarget, .external(url: "https://example.com"))
}

do {
// Testing for "no documentation" pass-through.
let res = try await PackageController.PackageResult.query(on: app.db, owner: "foo", repository: "bar3")

// Validaton
XCTAssertNil(res.currentDocumentationTarget())
}
}

}
2 changes: 1 addition & 1 deletion Tests/AppTests/WebpageSnapshotTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class WebpageSnapshotTests: SnapshotTestCase {

func test_PackageShowView_with_documentation_link() throws {
var model = API.PackageController.GetRoute.Model.mock
model.documentationTarget = .internal(docVersion: .reference("main"), archive: "archive")
model.currentDocumentationTarget = .internal(docVersion: .reference("main"), archive: "archive")
let page = { PackageShow.View(path: "", model: model, packageSchema: .mock).document() }

assertSnapshot(of: page, as: .html)
Expand Down
Loading