gitbay/Views/Repos/ReadmeView.swift

v1.0.1
gitbay-ios/gitbay/Views/Repos/ReadmeView.swift history · blame · raw

54 lines · 1997 bytes

 1import Foundation
 2import OrgSwift
 3import OrgSwiftUI
 4import SwiftUI
 5
 6/// README rendering follows the file's format. Org is rendered natively by the shared
 7/// `OrgSwiftUI` package; everything else keeps the established Markdown renderer.
 8struct ReadmeView: View {
 9    let name: String
10    let content: String
11    /// Instance host and `owner/repo`, used to resolve repository-relative links and images.
12    /// Empty leaves relative references unresolved.
13    var host: String = ""
14    var repoPath: String = ""
15
16    @Environment(\.colorScheme) private var colorScheme
17
18    /// Format follows the file name, never a guess at the content.
19    var isOrg: Bool { name.lowercased().hasSuffix(".org") }
20
21    var body: some View {
22        if isOrg {
23            // Qualified: `OrgView` here is org-mode, not the organization view.
24            OrgSwiftUI.OrgView(
25                content,
26                options: orgOptions,
27                styler: OrgSyntaxStyler(colorScheme: colorScheme),
28                // org's TODO/DONE are the same open/done distinction the forge already
29                // colors, so they reuse those tokens rather than a third treatment.
30                keywords: OrgKeywordStyle(todo: .gbOK, done: .gbDone)
31            )
32        } else {
33            MarkdownView(markdown: content)
34        }
35    }
36
37    /// gitbay serves raw bytes at `/{owner}/{repo}/raw/{ref}/…` and the file page at
38    /// `/blob/…`, so relative images resolve against `raw` and links against `blob`.
39    private var orgOptions: OrgRenderOptions {
40        let parts = repoPath.split(separator: "/", maxSplits: 1).map(String.init)
41        guard parts.count == 2, !host.isEmpty else {
42            return OrgRenderOptions()
43        }
44        return OrgRenderOptions(
45            host: host,
46            owner: parts[0],
47            repositoryName: parts[1],
48            ref: "HEAD",
49            readmePath: name,
50            imagePathSegment: "raw",
51            linkPathSegment: "blob"
52        )
53    }
54}