gitbay/Views/Repos/ReadmeView.swift
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}