diff options
| -rw-r--r-- | Hutch.xcodeproj/project.pbxproj | 8 | ||||
| -rw-r--r-- | Hutch/Views/Repositories/MarkdownHTMLRenderer.swift | 42 | ||||
| -rw-r--r-- | HutchTests/ReadmeViewTests.swift | 10 |
3 files changed, 50 insertions, 10 deletions
diff --git a/Hutch.xcodeproj/project.pbxproj b/Hutch.xcodeproj/project.pbxproj index e72dfd4..f4dffa0 100644 --- a/Hutch.xcodeproj/project.pbxproj +++ b/Hutch.xcodeproj/project.pbxproj @@ -11,7 +11,6 @@ 8B2F89672F69DEB900FC0253 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 8B2F89642F69DEB900FC0253 /* README.md */; }; 8B2F89682F69DEB900FC0253 /* SECURITY.md in Resources */ = {isa = PBXBuildFile; fileRef = 8B2F89652F69DEB900FC0253 /* SECURITY.md */; }; 8BE082012F80000100000001 /* HutchWidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 8BE081F62F80000100000001 /* HutchWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 8BE09E792F7B20CB00F88693 /* TEST_README.md in Resources */ = {isa = PBXBuildFile; fileRef = 8BE09E782F7B20CB00F88693 /* TEST_README.md */; }; 8BF100032F9A000100000001 /* Markdown in Frameworks */ = {isa = PBXBuildFile; productRef = 8BF100022F9A000100000001 /* Markdown */; }; /* End PBXBuildFile section */ @@ -55,7 +54,6 @@ 8B8182C22F6B742B000AE049 /* HutchTests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = HutchTests; sourceTree = "<group>"; }; 8BDCA5272F6B76B20066AA29 /* HutchTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = HutchTests.xctestplan; sourceTree = "<group>"; }; 8BE081F62F80000100000001 /* HutchWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = HutchWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; - 8BE09E782F7B20CB00F88693 /* TEST_README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = TEST_README.md; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ @@ -143,7 +141,6 @@ 8BE081F52F80000100000001 /* HutchWidgetExtension */, 8B8182B82F6B73F3000AE049 /* HutchTests */, 8B4B28D22F6704280045FA19 /* Products */, - 8BE09E782F7B20CB00F88693 /* TEST_README.md */, ); sourceTree = "<group>"; }; @@ -281,7 +278,6 @@ buildActionMask = 2147483647; files = ( 8B2F89662F69DEB900FC0253 /* LICENSE in Resources */, - 8BE09E792F7B20CB00F88693 /* TEST_README.md in Resources */, 8B2F89672F69DEB900FC0253 /* README.md in Resources */, 8B2F89682F69DEB900FC0253 /* SECURITY.md in Resources */, ); @@ -486,7 +482,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.4.2; + MARKETING_VERSION = 2.5.0; PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; @@ -523,7 +519,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.4.2; + MARKETING_VERSION = 2.5.0; PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; diff --git a/Hutch/Views/Repositories/MarkdownHTMLRenderer.swift b/Hutch/Views/Repositories/MarkdownHTMLRenderer.swift index 67966f1..5c69659 100644 --- a/Hutch/Views/Repositories/MarkdownHTMLRenderer.swift +++ b/Hutch/Views/Repositories/MarkdownHTMLRenderer.swift @@ -10,7 +10,9 @@ private struct MarkdownHTMLRenderer: MarkupVisitor { typealias Result = String nonisolated(unsafe) let imageURLResolver: ((String) -> String?)? - private var isRenderingTableHead = false + nonisolated(unsafe) private var isRenderingTableHead = false + nonisolated(unsafe) private var currentTableAlignments: [Markdown.Table.ColumnAlignment?] = [] + nonisolated(unsafe) private var currentTableColumnIndex = 0 nonisolated init(imageURLResolver: ((String) -> String?)?) { self.imageURLResolver = imageURLResolver @@ -140,7 +142,14 @@ private struct MarkdownHTMLRenderer: MarkupVisitor { } nonisolated mutating func visitTable(_ table: Markdown.Table) -> String { - "<table>\n\(visitChildren(of: table))</table>\n" + let previousAlignments = currentTableAlignments + let previousColumnIndex = currentTableColumnIndex + currentTableAlignments = table.columnAlignments + currentTableColumnIndex = 0 + let content = visitChildren(of: table) + currentTableAlignments = previousAlignments + currentTableColumnIndex = previousColumnIndex + return "<table>\n\(content)</table>\n" } nonisolated mutating func visitTableHead(_ tableHead: Markdown.Table.Head) -> String { @@ -160,12 +169,18 @@ private struct MarkdownHTMLRenderer: MarkupVisitor { } nonisolated mutating func visitTableRow(_ tableRow: Markdown.Table.Row) -> String { - "<tr>\(visitChildren(of: tableRow))</tr>\n" + let previousColumnIndex = currentTableColumnIndex + currentTableColumnIndex = 0 + let content = visitChildren(of: tableRow) + currentTableColumnIndex = previousColumnIndex + return "<tr>\(content)</tr>\n" } nonisolated mutating func visitTableCell(_ tableCell: Markdown.Table.Cell) -> String { let tagName = isRenderingTableHead ? "th" : "td" - return "<\(tagName)>\(visitChildren(of: tableCell))</\(tagName)>" + let styleAttribute = alignmentStyleAttribute(forColumn: currentTableColumnIndex) + currentTableColumnIndex += 1 + return "<\(tagName)\(styleAttribute)>\(visitChildren(of: tableCell))</\(tagName)>" } nonisolated private mutating func visitChildren(of markup: Markup) -> String { @@ -195,6 +210,25 @@ private struct MarkdownHTMLRenderer: MarkupVisitor { } } + nonisolated private func alignmentStyleAttribute(forColumn column: Int) -> String { + guard column < currentTableAlignments.count, + let alignment = currentTableAlignments[column] else { + return "" + } + + let textAlignment: String + switch alignment { + case .left: + textAlignment = "left" + case .center: + textAlignment = "center" + case .right: + textAlignment = "right" + } + + return " style=\"text-align: \(textAlignment);\"" + } + nonisolated private func checkboxHTML(for checkbox: Checkbox) -> String { switch checkbox { case .checked: diff --git a/HutchTests/ReadmeViewTests.swift b/HutchTests/ReadmeViewTests.swift index e9bab0b..8cced03 100644 --- a/HutchTests/ReadmeViewTests.swift +++ b/HutchTests/ReadmeViewTests.swift @@ -55,6 +55,16 @@ struct MarkdownRenderingTests { } @Test + func markdownTableAlignment() { + let input = "| Left | Center | Right |\n|:-----|:------:|------:|\n| a | b | c |" + let html = markdownToHTML(input) + + #expect(html.contains("text-align: left;")) + #expect(html.contains("text-align: center;")) + #expect(html.contains("text-align: right;")) + } + + @Test func markdownStrikethrough() { let html = markdownToHTML("~~deleted~~") |
