diff --git a/Sources/MarkdownView/Configuration/Markdown.ListConfiguration.swift b/Sources/MarkdownView/Configuration/Markdown.ListConfiguration.swift index 055850d1..5cb80938 100644 --- a/Sources/MarkdownView/Configuration/Markdown.ListConfiguration.swift +++ b/Sources/MarkdownView/Configuration/Markdown.ListConfiguration.swift @@ -18,26 +18,38 @@ struct MarkdownListConfiguration: Hashable, @unchecked Sendable { public protocol OrderedListMarkerProtocol: Hashable { /// Returns a marker for a specific index of ordered list item. Index starting from 0. - func marker(at index: Int) -> String + func marker(at index: Int, listDepth: Int) -> String + + var monospaced: Bool { get } +} + +extension OrderedListMarkerProtocol { + public var monospaced: Bool { + true + } } struct AnyOrderedListMarkerProtocol: OrderedListMarkerProtocol { private var _marker: AnyHashable + var monospaced: Bool { + (_marker as! (any OrderedListMarkerProtocol)).monospaced + } - init(_ marker: some OrderedListMarkerProtocol) { + init(_ marker: T) { self._marker = AnyHashable(marker) } - public func marker(at index: Int) -> String { - (_marker as! (any OrderedListMarkerProtocol)).marker(at: index) + public func marker(at index: Int, listDepth: Int) -> String { + (_marker as! (any OrderedListMarkerProtocol)).marker(at: index, listDepth: listDepth) } } - public struct OrderedListIncreasingDigitsMarker: OrderedListMarkerProtocol { - public func marker(at index: Int) -> String { - String(index + 1) + public func marker(at index: Int, listDepth: Int) -> String { + String(index + 1) + "." } + + public var monospaced: Bool { false } } extension OrderedListMarkerProtocol where Self == OrderedListIncreasingDigitsMarker { @@ -45,7 +57,7 @@ extension OrderedListMarkerProtocol where Self == OrderedListIncreasingDigitsMar } public struct OrderedListIncreasingLettersMarker: OrderedListMarkerProtocol { - public func marker(at index: Int) -> String { + public func marker(at index: Int, listDepth: Int) -> String { let base = 26 var index = index var result = "" @@ -63,8 +75,10 @@ public struct OrderedListIncreasingLettersMarker: OrderedListMarkerProtocol { result.append(Character(secondLetter)) } - return result + return result + "." } + + public var monospaced: Bool { false } } extension OrderedListMarkerProtocol where Self == OrderedListIncreasingLettersMarker { @@ -75,23 +89,34 @@ extension OrderedListMarkerProtocol where Self == OrderedListIncreasingLettersMa public protocol UnorderedListMarkerProtocol: Hashable { /// Returns a marker for a specific indentation level of unordered list item. indentationLevel starting from 0. - func marker(at indentationLevel: Int) -> String + func marker(listDepth: Int) -> String + + var monospaced: Bool { get } +} + +extension UnorderedListMarkerProtocol { + public var monospaced: Bool { + true + } } struct AnyUnorderedListMarkerProtocol: UnorderedListMarkerProtocol { private var _marker: AnyHashable + var monospaced: Bool { + (_marker as! (any UnorderedListMarkerProtocol)).monospaced + } - init(_ marker: some UnorderedListMarkerProtocol) { + init(_ marker: T) { self._marker = AnyHashable(marker) } - public func marker(at indentationLevel: Int) -> String { - (_marker as! (any UnorderedListMarkerProtocol)).marker(at: indentationLevel) + public func marker(listDepth: Int) -> String { + (_marker as! (any UnorderedListMarkerProtocol)).marker(listDepth: listDepth) } } public struct UnorderedListDashMarker: UnorderedListMarkerProtocol { - public func marker(at indentationLevel: Int) -> String { + public func marker(listDepth: Int) -> String { "-" } } @@ -101,7 +126,7 @@ extension UnorderedListMarkerProtocol where Self == UnorderedListDashMarker { } public struct UnorderedListBulletMarker: UnorderedListMarkerProtocol { - public func marker(at indentationLevel: Int) -> String { + public func marker(listDepth: Int) -> String { "•" } } diff --git a/Sources/MarkdownView/Renderer/Component Renderers/Renderer.List.swift b/Sources/MarkdownView/Renderer/Component Renderers/Renderer.List.swift index fe2cf400..6a69e522 100644 --- a/Sources/MarkdownView/Renderer/Component Renderers/Renderer.List.swift +++ b/Sources/MarkdownView/Renderer/Component Renderers/Renderer.List.swift @@ -52,7 +52,7 @@ extension MarkdownViewRenderer { if listItem.checkbox != nil { CheckboxView(listItem: listItem) } else { - SwiftUI.Text(configuration.listConfiguration.unorderedListMarker.marker(at: unorderedList.listDepth)) + SwiftUI.Text(configuration.listConfiguration.unorderedListMarker.marker(listDepth: unorderedList.listDepth)) .font(.title2) .padding(.leading, depth == 0 ? configuration.listConfiguration.leadingIndent : 0) } diff --git a/Sources/MarkdownView/WIP/MarkdownText/MarkdownTextNode.swift b/Sources/MarkdownView/WIP/MarkdownText/MarkdownTextNode.swift index be02b548..9de302aa 100644 --- a/Sources/MarkdownView/WIP/MarkdownText/MarkdownTextNode.swift +++ b/Sources/MarkdownView/WIP/MarkdownText/MarkdownTextNode.swift @@ -103,20 +103,6 @@ enum MarkdownTextKind: Sendable, Equatable { case placeholder(UUID) // A placeholder to enable async resources loading, e.g. image loading case image(Image) -} - - -fileprivate extension Font { - static func heading(level: Int) -> Font { - @Environment(\.markdownRendererConfiguration.fontGroup) var fontGroup - return switch level { - case 1: fontGroup.h1 - case 2: fontGroup.h2 - case 3: fontGroup.h3 - case 4: fontGroup.h4 - case 5: fontGroup.h5 - case 6: fontGroup.h6 - default: fontGroup.body - } - } + + case unknown } diff --git a/Sources/MarkdownView/WIP/MarkdownText/MarkdownTextRenderer.swift b/Sources/MarkdownView/WIP/MarkdownText/MarkdownTextRenderer.swift index 9c5b3885..b2084412 100644 --- a/Sources/MarkdownView/WIP/MarkdownText/MarkdownTextRenderer.swift +++ b/Sources/MarkdownView/WIP/MarkdownText/MarkdownTextRenderer.swift @@ -15,7 +15,13 @@ struct MarkdownTextRenderer: MarkupVisitor { } mutating func defaultVisit(_ markup: any Markdown.Markup) -> MarkdownTextNode { - MarkdownTextNode(kind: .placeholder(UUID()), children: []) + MarkdownTextNode( + kind: .unknown, + children: markup.children.enumerated().map { + visit($0.element) + .with(\.index, $0.offset) + } + ) } mutating func visitDocument(_ document: Document) -> MarkdownTextNode { diff --git a/Sources/MarkdownView/WIP/MarkdownText/Renderers/CodeBlockTextRenderer.swift b/Sources/MarkdownView/WIP/MarkdownText/Renderers/CodeBlockTextRenderer.swift index 1d986cfb..6cf63262 100644 --- a/Sources/MarkdownView/WIP/MarkdownText/Renderers/CodeBlockTextRenderer.swift +++ b/Sources/MarkdownView/WIP/MarkdownText/Renderers/CodeBlockTextRenderer.swift @@ -12,10 +12,10 @@ import Highlightr struct CodeBlockTextRenderer: MarkdownNode2TextRenderer { func body(context: Context) -> Text { - BreakTextRenderer(breakType: .hard) - .body(context: context) - BreakTextRenderer(breakType: .hard) - .body(context: context) + if context.node.index != 0 { + BreakTextRenderer(breakType: .hard) + .body(context: context) + } let language = if case let .codeLanguage(language) = context.node.content! { language @@ -47,9 +47,6 @@ struct CodeBlockTextRenderer: MarkdownNode2TextRenderer { Text(processedCode) .font(.callout.monospaced()) } - - BreakTextRenderer(breakType: .hard) - .body(context: context) } } diff --git a/Sources/MarkdownView/WIP/MarkdownText/Renderers/HeadingTextRenderer.swift b/Sources/MarkdownView/WIP/MarkdownText/Renderers/HeadingTextRenderer.swift index 713c0491..1f6c0a38 100644 --- a/Sources/MarkdownView/WIP/MarkdownText/Renderers/HeadingTextRenderer.swift +++ b/Sources/MarkdownView/WIP/MarkdownText/Renderers/HeadingTextRenderer.swift @@ -9,9 +9,6 @@ import SwiftUI struct HeadingTextRenderer: MarkdownNode2TextRenderer { func body(context: Context) -> Text { - BreakTextRenderer(breakType: .hard) - .body(context: context) - let level = if case let .heading(level) = context.node.content { level } else { @@ -50,5 +47,8 @@ struct HeadingTextRenderer: MarkdownNode2TextRenderer { .reduce(Text(""), +) .font(font) } + + BreakTextRenderer(breakType: .hard) + .body(context: context) } } diff --git a/Sources/MarkdownView/WIP/MarkdownText/Renderers/InlineCodeTextRenderer.swift b/Sources/MarkdownView/WIP/MarkdownText/Renderers/InlineCodeTextRenderer.swift index 660d3a98..a7c198b5 100644 --- a/Sources/MarkdownView/WIP/MarkdownText/Renderers/InlineCodeTextRenderer.swift +++ b/Sources/MarkdownView/WIP/MarkdownText/Renderers/InlineCodeTextRenderer.swift @@ -10,7 +10,11 @@ import SwiftUI struct InlineCodeTextRenderer: MarkdownNode2TextRenderer { func body(context: Context) -> Text { if case let .text(text) = context.node.content! { - Text(text).font(.body.monospaced()) + if #available(iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) { + Text(text).monospaced() + } else { + Text(text).font(.body.monospaced()) + } } } } diff --git a/Sources/MarkdownView/WIP/MarkdownText/Renderers/OrderedListTextRenderer.swift b/Sources/MarkdownView/WIP/MarkdownText/Renderers/OrderedListTextRenderer.swift index 6f2986c7..8688e2cc 100644 --- a/Sources/MarkdownView/WIP/MarkdownText/Renderers/OrderedListTextRenderer.swift +++ b/Sources/MarkdownView/WIP/MarkdownText/Renderers/OrderedListTextRenderer.swift @@ -9,17 +9,36 @@ import SwiftUI struct OrderedListTextRenderer: MarkdownNode2TextRenderer { func body(context: Context) -> Text { - BreakTextRenderer(breakType: .hard) - .body(context: context) - - let listConfiguration = context.renderConfiguration.listConfiguration - let marker = Text("\(listConfiguration.orderedListMarker.marker(at: context.node.depth ?? 0)) ") - .font(.body.monospaced()) + let indents = context.node.depth ?? 0 + let indentation = (0.. Text { + let marker = context.renderConfiguration.listConfiguration + .orderedListMarker + .marker(at: index, listDepth: context.node.depth ?? 0) + if context.renderConfiguration.listConfiguration.orderedListMarker.monospaced { + if #available(iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) { + Text("\(marker) ") + .monospaced() + } else { + Text("\(marker) ") + .font(.body.monospaced()) } + } else { + Text("\(marker) ") + } } } diff --git a/Sources/MarkdownView/WIP/MarkdownText/Renderers/ParagraphTextRenderer.swift b/Sources/MarkdownView/WIP/MarkdownText/Renderers/ParagraphTextRenderer.swift index f95acad9..51ae0945 100644 --- a/Sources/MarkdownView/WIP/MarkdownText/Renderers/ParagraphTextRenderer.swift +++ b/Sources/MarkdownView/WIP/MarkdownText/Renderers/ParagraphTextRenderer.swift @@ -9,12 +9,10 @@ import SwiftUI struct ParagraphTextRenderer: MarkdownNode2TextRenderer { func body(context: Context) -> Text { - if context.node.index != 0 { - BreakTextRenderer(breakType: .hard) - .body(context: context) - } context.node.children .map { $0.render(configuration: context.renderConfiguration) } .reduce(Text(""), +) + BreakTextRenderer(breakType: .hard) + .body(context: context) } } diff --git a/Sources/MarkdownView/WIP/MarkdownText/Renderers/UnorderedListTextRenderer.swift b/Sources/MarkdownView/WIP/MarkdownText/Renderers/UnorderedListTextRenderer.swift index b48f4fe2..baccf950 100644 --- a/Sources/MarkdownView/WIP/MarkdownText/Renderers/UnorderedListTextRenderer.swift +++ b/Sources/MarkdownView/WIP/MarkdownText/Renderers/UnorderedListTextRenderer.swift @@ -9,12 +9,6 @@ import SwiftUI struct UnorderedListTextRenderer: MarkdownNode2TextRenderer { func body(context: Context) -> Text { - let listConfiguration = context.renderConfiguration.listConfiguration - let marker = Text("\(listConfiguration.unorderedListMarker.marker(at: context.node.depth ?? 0)) ") - .font(.body.monospaced()) - - let lineBreak = BreakTextRenderer(breakType: .hard) - .body(context: context) let indents = context.node.depth ?? 0 let indentation = (0.. Text { + let marker = context.renderConfiguration.listConfiguration + .unorderedListMarker + .marker(listDepth: context.node.depth ?? 0) + if context.renderConfiguration.listConfiguration.unorderedListMarker.monospaced { + if #available(iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) { + Text("\(marker) ") + .monospaced() + } else { + Text("\(marker) ") + .font(.body.monospaced()) } + } else { + Text("\(marker) ") + } } }