From 14c27f5eb88a250a90079204b25ce173c2ec54ea Mon Sep 17 00:00:00 2001 From: Shai Mishali Date: Fri, 9 Aug 2024 11:55:52 +0300 Subject: [PATCH] Allow customizing soft break mode Resolved #341 --- .../MarkdownUI/DSL/Inlines/SoftBreak.swift | 10 ++++++++ .../Renderer/TextInlineRenderer.swift | 19 +++++++++++---- .../Environment+SoftBreakMode.swift | 23 +++++++++++++++++++ .../MarkdownUI/Views/Inlines/InlineText.swift | 2 ++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 Sources/MarkdownUI/Views/Environment/Environment+SoftBreakMode.swift diff --git a/Sources/MarkdownUI/DSL/Inlines/SoftBreak.swift b/Sources/MarkdownUI/DSL/Inlines/SoftBreak.swift index b3dbccea..95551353 100644 --- a/Sources/MarkdownUI/DSL/Inlines/SoftBreak.swift +++ b/Sources/MarkdownUI/DSL/Inlines/SoftBreak.swift @@ -11,3 +11,13 @@ public struct SoftBreak: InlineContentProtocol { .init(inlines: [.softBreak]) } } + +extension SoftBreak { + public enum Mode { + /// Treat a soft break as a space + case space + + /// Treat a soft break as a line break + case lineBreak + } +} diff --git a/Sources/MarkdownUI/Renderer/TextInlineRenderer.swift b/Sources/MarkdownUI/Renderer/TextInlineRenderer.swift index 50ae3657..72002423 100644 --- a/Sources/MarkdownUI/Renderer/TextInlineRenderer.swift +++ b/Sources/MarkdownUI/Renderer/TextInlineRenderer.swift @@ -5,12 +5,14 @@ extension Sequence where Element == InlineNode { baseURL: URL?, textStyles: InlineTextStyles, images: [String: Image], + softBreakMode: SoftBreak.Mode, attributes: AttributeContainer ) -> Text { var renderer = TextInlineRenderer( baseURL: baseURL, textStyles: textStyles, images: images, + softBreakMode: softBreakMode, attributes: attributes ) renderer.render(self) @@ -24,6 +26,7 @@ private struct TextInlineRenderer { private let baseURL: URL? private let textStyles: InlineTextStyles private let images: [String: Image] + private let softBreakMode: SoftBreak.Mode private let attributes: AttributeContainer private var shouldSkipNextWhitespace = false @@ -31,11 +34,13 @@ private struct TextInlineRenderer { baseURL: URL?, textStyles: InlineTextStyles, images: [String: Image], + softBreakMode: SoftBreak.Mode, attributes: AttributeContainer ) { self.baseURL = baseURL self.textStyles = textStyles self.images = images + self.softBreakMode = softBreakMode self.attributes = attributes } @@ -72,10 +77,16 @@ private struct TextInlineRenderer { } private mutating func renderSoftBreak() { - if self.shouldSkipNextWhitespace { - self.shouldSkipNextWhitespace = false - } else { - self.defaultRender(.softBreak) + switch self.softBreakMode { + case .space: + if self.shouldSkipNextWhitespace { + self.shouldSkipNextWhitespace = false + } else { + self.defaultRender(.softBreak) + } + case .lineBreak: + self.shouldSkipNextWhitespace = true + self.defaultRender(.lineBreak) } } diff --git a/Sources/MarkdownUI/Views/Environment/Environment+SoftBreakMode.swift b/Sources/MarkdownUI/Views/Environment/Environment+SoftBreakMode.swift new file mode 100644 index 00000000..52e24687 --- /dev/null +++ b/Sources/MarkdownUI/Views/Environment/Environment+SoftBreakMode.swift @@ -0,0 +1,23 @@ +import SwiftUI + +extension View { + /// Sets the soft break mode for inline texts in a view hierarchy. + /// + /// - parameter softBreakMode: If set to `space`, treats all soft breaks as spaces, keeping sentences whole. If set to `lineBreak`, treats soft breaks as full line breaks + /// + /// - Returns: A view that uses the specified soft break mode for itself and its child views. + public func markdownSoftBreakMode(_ softBreakMode: SoftBreak.Mode) -> some View { + self.environment(\.softBreakMode, softBreakMode) + } +} + +extension EnvironmentValues { + var softBreakMode: SoftBreak.Mode { + get { self[SoftBreakModeKey.self] } + set { self[SoftBreakModeKey.self] = newValue } + } +} + +private struct SoftBreakModeKey: EnvironmentKey { + static let defaultValue: SoftBreak.Mode = .space +} diff --git a/Sources/MarkdownUI/Views/Inlines/InlineText.swift b/Sources/MarkdownUI/Views/Inlines/InlineText.swift index c328a7d3..9da39404 100644 --- a/Sources/MarkdownUI/Views/Inlines/InlineText.swift +++ b/Sources/MarkdownUI/Views/Inlines/InlineText.swift @@ -4,6 +4,7 @@ struct InlineText: View { @Environment(\.inlineImageProvider) private var inlineImageProvider @Environment(\.baseURL) private var baseURL @Environment(\.imageBaseURL) private var imageBaseURL + @Environment(\.softBreakMode) private var softBreakMode @Environment(\.theme) private var theme @State private var inlineImages: [String: Image] = [:] @@ -26,6 +27,7 @@ struct InlineText: View { link: self.theme.link ), images: self.inlineImages, + softBreakMode: self.softBreakMode, attributes: attributes ) }