From 06bb3224afebe2fd018712b37678b44461e80573 Mon Sep 17 00:00:00 2001 From: Jon Wall Date: Thu, 17 Jul 2025 15:00:02 -0400 Subject: [PATCH] add a synchronous placeholder() function to InlineImageProvider --- .../Extensibility/InlineImageProvider.swift | 6 ++++++ .../MarkdownUI/Renderer/TextInlineRenderer.swift | 13 ++++++++++--- Sources/MarkdownUI/Views/Inlines/InlineText.swift | 3 ++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Sources/MarkdownUI/Extensibility/InlineImageProvider.swift b/Sources/MarkdownUI/Extensibility/InlineImageProvider.swift index 06bd9e1c..ae2b20dd 100644 --- a/Sources/MarkdownUI/Extensibility/InlineImageProvider.swift +++ b/Sources/MarkdownUI/Extensibility/InlineImageProvider.swift @@ -13,4 +13,10 @@ public protocol InlineImageProvider { /// - url: The URL of the image to display. /// - label: The accessibility label associated with the image. func image(with url: URL, label: String) async throws -> Image + + func placeholder() -> Text? +} + +extension InlineImageProvider { + public func placeholder() -> Text? { nil } } diff --git a/Sources/MarkdownUI/Renderer/TextInlineRenderer.swift b/Sources/MarkdownUI/Renderer/TextInlineRenderer.swift index e3f86673..791390ff 100644 --- a/Sources/MarkdownUI/Renderer/TextInlineRenderer.swift +++ b/Sources/MarkdownUI/Renderer/TextInlineRenderer.swift @@ -6,14 +6,16 @@ extension Sequence where Element == InlineNode { textStyles: InlineTextStyles, images: [String: Image], softBreakMode: SoftBreak.Mode, - attributes: AttributeContainer + attributes: AttributeContainer, + placeholderImage: Text? ) -> Text { var renderer = TextInlineRenderer( baseURL: baseURL, textStyles: textStyles, images: images, softBreakMode: softBreakMode, - attributes: attributes + attributes: attributes, + placeholderImage: placeholderImage ) renderer.render(self) return renderer.result @@ -28,6 +30,7 @@ private struct TextInlineRenderer { private let images: [String: Image] private let softBreakMode: SoftBreak.Mode private let attributes: AttributeContainer + private let placeholderImage: Text? private var shouldSkipNextWhitespace = false init( @@ -35,13 +38,15 @@ private struct TextInlineRenderer { textStyles: InlineTextStyles, images: [String: Image], softBreakMode: SoftBreak.Mode, - attributes: AttributeContainer + attributes: AttributeContainer, + placeholderImage: Text? ) { self.baseURL = baseURL self.textStyles = textStyles self.images = images self.softBreakMode = softBreakMode self.attributes = attributes + self.placeholderImage = placeholderImage } mutating func render(_ inlines: S) where S.Element == InlineNode { @@ -103,6 +108,8 @@ private struct TextInlineRenderer { private mutating func renderImage(_ source: String) { if let image = self.images[source] { self.result = self.result + Text(image) + } else if let placeholderImage { + self.result = self.result + placeholderImage } } diff --git a/Sources/MarkdownUI/Views/Inlines/InlineText.swift b/Sources/MarkdownUI/Views/Inlines/InlineText.swift index 9da39404..269f4494 100644 --- a/Sources/MarkdownUI/Views/Inlines/InlineText.swift +++ b/Sources/MarkdownUI/Views/Inlines/InlineText.swift @@ -28,7 +28,8 @@ struct InlineText: View { ), images: self.inlineImages, softBreakMode: self.softBreakMode, - attributes: attributes + attributes: attributes, + placeholderImage: self.inlineImageProvider.placeholder() ) } .task(id: self.inlines) {