Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit 682f95d

Browse files
mattpolzinkaremanmattt
authored
Bugfix/relative links (#127)
* Fix relative link generation. * Expose base-url argument for GitHub action. * fix #134: crash for operator functions when no baseURL. Fixes crashes like this one: ```bash $ swift doc generate my-repo/Sources --module-name MyRepo 2020-06-30T17:00:13-0400 critical: Unable to construct path for /(lhs:rhs:) with baseURL / Fatal error: file /private/tmp/swift-doc-20200630-24417-jrxtfw/Sources/swift-doc/Supporting Types/Page.swift, line 55 zsh: illegal hardware instruction swift doc generate my-repo/Sources --module-name MyRepo ``` * swap out path for absoluteString to ensure that both relative and absolute URLs are supported as documentation paths. * Move path helper functions to SwiftDoc module * Add PathTests * Add assertions for function identifiers See #134 * Add changelog entry for #127 Co-authored-by: Kare Morstol <[email protected]> Co-authored-by: Mattt <[email protected]>
1 parent b815728 commit 682f95d

File tree

6 files changed

+78
-34
lines changed

6 files changed

+78
-34
lines changed

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
#140 by @JaapWijnen.
1414
- Fixed whitespace of code listings.
1515
#144 by @mbrandonw.
16+
- Fixed crash when attempting to generate paths with no base URL specified.
17+
#127 by @mattpolzin, @kareman, and @mattt.
1618

1719
## [1.0.0-beta.3] - 2020-05-19
1820

Sources/SwiftDoc/Helpers.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import Foundation
2+
3+
public func route(for symbol: Symbol) -> String {
4+
return route(for: symbol.id)
5+
}
6+
7+
public func route(for name: CustomStringConvertible) -> String {
8+
return name.description.replacingOccurrences(of: ".", with: "_")
9+
}
10+
11+
public func path(for symbol: Symbol, with baseURL: String) -> String {
12+
return path(for: route(for: symbol), with: baseURL)
13+
}
14+
15+
public func path(for identifier: CustomStringConvertible, with baseURL: String) -> String {
16+
let url = URL(string: baseURL)?.appendingPathComponent("\(identifier)") ?? URL(string: "\(identifier)")
17+
guard let string = url?.absoluteString else {
18+
fatalError("Unable to construct path for \(identifier) with baseURL \(baseURL)")
19+
}
20+
21+
return string
22+
}

Sources/swift-doc/Supporting Types/Layout.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import SwiftDoc
12
import HypertextLiteral
23
import Foundation
34

Sources/swift-doc/Supporting Types/Page.swift

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,7 @@ extension Page {
3535
}
3636
}
3737

38-
func route(for symbol: Symbol) -> String {
39-
return route(for: symbol.id)
40-
}
41-
42-
func route(for name: CustomStringConvertible) -> String {
43-
return name.description.replacingOccurrences(of: ".", with: "_")
44-
}
4538

46-
func path(for symbol: Symbol, with baseURL: String) -> String {
47-
return path(for: route(for: symbol), with: baseURL)
48-
}
49-
50-
func path(for identifier: CustomStringConvertible, with baseURL: String) -> String {
51-
var urlComponents = URLComponents(string: baseURL)
52-
urlComponents = urlComponents?.appendingPathComponent("\(identifier)")
53-
guard let string = urlComponents?.string else {
54-
logger.critical("Unable to construct path for \(identifier) with baseURL \(baseURL)")
55-
fatalError()
56-
}
57-
58-
return string
59-
}
6039

6140
func writeFile(_ data: Data, to url: URL) throws {
6241
let fileManager = FileManager.default
@@ -65,16 +44,3 @@ func writeFile(_ data: Data, to url: URL) throws {
6544
try data.write(to: url)
6645
try fileManager.setAttributes([.posixPermissions: 0o744], ofItemAtPath: url.path)
6746
}
68-
69-
// MARK: -
70-
71-
fileprivate extension URLComponents {
72-
func appendingPathComponent(_ component: String) -> URLComponents? {
73-
var urlComponents = self
74-
var pathComponents = urlComponents.path.split(separator: "/").map { "\($0)" }
75-
pathComponents.append(component)
76-
urlComponents.path = "/" + pathComponents.joined(separator: "/")
77-
78-
return urlComponents
79-
}
80-
}

Tests/SwiftDocTests/PathTests.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import XCTest
2+
3+
import SwiftDoc
4+
5+
final class PathTests: XCTestCase {
6+
func testEmptyBaseURL() {
7+
XCTAssertEqual(path(for: "Class", with: ""), "Class")
8+
9+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: ""), "(lhs:rhs:)")
10+
}
11+
12+
func testRootDirectoryBaseURL() {
13+
XCTAssertEqual(path(for: "Class", with: "/"), "/Class")
14+
15+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: "/"), "/(lhs:rhs:)")
16+
}
17+
18+
func testCurrentDirectoryBaseURL() {
19+
XCTAssertEqual(path(for: "Class", with: "./"), "./Class")
20+
21+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: "./"), "./(lhs:rhs:)")
22+
}
23+
24+
func testNestedSubdirectoryBaseURL() {
25+
XCTAssertEqual(path(for: "Class", with: "/path/to/directory"), "/path/to/directory/Class")
26+
XCTAssertEqual(path(for: "Class", with: "/path/to/directory/"), "/path/to/directory/Class")
27+
28+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: "/path/to/directory"), "/path/to/directory/(lhs:rhs:)")
29+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: "/path/to/directory/"), "/path/to/directory/(lhs:rhs:)")
30+
}
31+
32+
func testDomainBaseURL() {
33+
XCTAssertEqual(path(for: "Class", with: "https://example.com"), "https://example.com/Class")
34+
XCTAssertEqual(path(for: "Class", with: "https://example.com/"), "https://example.com/Class")
35+
36+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: "https://example.com"), "https://example.com/(lhs:rhs:)")
37+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: "https://example.com/"), "https://example.com/(lhs:rhs:)")
38+
}
39+
40+
func testDomainSubdirectoryBaseURL() {
41+
XCTAssertEqual(path(for: "Class", with: "https://example.com/docs"), "https://example.com/docs/Class")
42+
XCTAssertEqual(path(for: "Class", with: "https://example.com/docs/"), "https://example.com/docs/Class")
43+
44+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: "https://example.com/docs"), "https://example.com/docs/(lhs:rhs:)")
45+
XCTAssertEqual(path(for: "(lhs:rhs:)", with: "https://example.com/docs/"), "https://example.com/docs/(lhs:rhs:)")
46+
}
47+
}

action.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ inputs:
1212
format:
1313
description: "The output format (commonmark or html)"
1414
default: "commonmark"
15+
base-url:
16+
description: "The base URL for all relative URLs generated in documents"
17+
required: false
18+
default: "./"
1519
output:
1620
description: "The path for generated output"
1721
required: true
@@ -26,6 +30,8 @@ runs:
2630
"${{ inputs.inputs }}",
2731
--format,
2832
"${{ inputs.format }}",
33+
--base-url,
34+
"${{ inputs.base-url }}",
2935
--module-name,
3036
"${{ inputs.module-name }}",
3137
--output,

0 commit comments

Comments
 (0)