diff --git a/ios/EnrichedMarkdown.mm b/ios/EnrichedMarkdown.mm index 5d6b6345..6c12aefc 100644 --- a/ios/EnrichedMarkdown.mm +++ b/ios/EnrichedMarkdown.mm @@ -1,9 +1,8 @@ #import "EnrichedMarkdown.h" -#import "AccessibilityInfo.h" -#import "AttributedRenderer.h" #import "ContextMenuUtils.h" #import "ENRMImageAttachment.h" #import "ENRMMarkdownParser.h" +#import "ENRMTextRenderer.h" #import "ENRMUIKit.h" #import "EditMenuUtils.h" @@ -25,7 +24,6 @@ #import "MarkdownAccessibilityElementBuilder.h" #import "MarkdownExtractor.h" #import "ParagraphStyleUtils.h" -#import "RenderContext.h" #import "RuntimeKeys.h" #import "StyleConfig.h" #import "StylePropsUtils.h" @@ -91,32 +89,6 @@ + (instancetype)segmentWithLatex:(NSString *)latex @end #endif -@interface EMRenderedTextSegment : NSObject -@property (nonatomic, strong) NSMutableAttributedString *attributedText; -@property (nonatomic, strong) RenderContext *context; -@property (nonatomic, strong) AccessibilityInfo *accessibilityInfo; -@property (nonatomic, assign) CGFloat lastElementMarginBottom; -+ (instancetype)withAttributedText:(NSMutableAttributedString *)text - context:(RenderContext *)context - accessibilityInfo:(AccessibilityInfo *)info - lastElementMarginBottom:(CGFloat)marginBottom; -@end - -@implementation EMRenderedTextSegment -+ (instancetype)withAttributedText:(NSMutableAttributedString *)text - context:(RenderContext *)context - accessibilityInfo:(AccessibilityInfo *)info - lastElementMarginBottom:(CGFloat)marginBottom -{ - EMRenderedTextSegment *segment = [[EMRenderedTextSegment alloc] init]; - segment.attributedText = text; - segment.context = context; - segment.accessibilityInfo = info; - segment.lastElementMarginBottom = marginBottom; - return segment; -} -@end - @interface EnrichedMarkdown () @end @@ -363,11 +335,11 @@ - (void)renderMarkdownContent:(NSString *)markdownString for (id segment in segments) { if ([segment isKindOfClass:[EMTextSegment class]]) { - EMRenderedTextSegment *rendered = [self renderTextSegment:(EMTextSegment *)segment - config:config - allowTrailingMargin:allowTrailingMargin - allowFontScaling:allowFontScaling - maxFontSizeMultiplier:maxFontSizeMultiplier]; + ENRMRenderResult *rendered = [self renderTextSegment:(EMTextSegment *)segment + config:config + allowTrailingMargin:allowTrailingMargin + allowFontScaling:allowFontScaling + maxFontSizeMultiplier:maxFontSizeMultiplier]; [renderedSegments addObject:rendered]; } else if ([segment isKindOfClass:[EMTableSegment class]]) { [renderedSegments addObject:segment]; @@ -401,11 +373,11 @@ - (NSArray *)parseAndRenderSegments:(NSString *)markdownString for (id segment in segments) { if ([segment isKindOfClass:[EMTextSegment class]]) { - EMRenderedTextSegment *rendered = [self renderTextSegment:(EMTextSegment *)segment - config:_config - allowTrailingMargin:_allowTrailingMargin - allowFontScaling:_fontScaleObserver.allowFontScaling - maxFontSizeMultiplier:_maxFontSizeMultiplier]; + ENRMRenderResult *rendered = [self renderTextSegment:(EMTextSegment *)segment + config:_config + allowTrailingMargin:_allowTrailingMargin + allowFontScaling:_fontScaleObserver.allowFontScaling + maxFontSizeMultiplier:_maxFontSizeMultiplier]; [renderedSegments addObject:rendered]; } else if ([segment isKindOfClass:[EMTableSegment class]]) { [renderedSegments addObject:segment]; @@ -442,8 +414,8 @@ - (void)renderMarkdownSynchronously:(NSString *)markdownString } for (id segment in renderedSegments) { - if ([segment isKindOfClass:[EMRenderedTextSegment class]]) { - EnrichedMarkdownInternalText *view = [self createTextViewForRenderedSegment:(EMRenderedTextSegment *)segment]; + if ([segment isKindOfClass:[ENRMRenderResult class]]) { + EnrichedMarkdownInternalText *view = [self createTextViewForRenderedSegment:(ENRMRenderResult *)segment]; [_segmentViews addObject:view]; [self addSubview:view]; } else if ([segment isKindOfClass:[EMTableSegment class]]) { @@ -471,8 +443,8 @@ - (void)applyRenderedSegments:(NSArray *)renderedSegments [_segmentViews removeAllObjects]; for (id segment in renderedSegments) { - if ([segment isKindOfClass:[EMRenderedTextSegment class]]) { - EnrichedMarkdownInternalText *view = [self createTextViewForRenderedSegment:(EMRenderedTextSegment *)segment]; + if ([segment isKindOfClass:[ENRMRenderResult class]]) { + EnrichedMarkdownInternalText *view = [self createTextViewForRenderedSegment:(ENRMRenderResult *)segment]; [_segmentViews addObject:view]; [self addSubview:view]; } else if ([segment isKindOfClass:[EMTableSegment class]]) { @@ -501,34 +473,17 @@ - (void)applyRenderedSegments:(NSArray *)renderedSegments } } -- (EMRenderedTextSegment *)renderTextSegment:(EMTextSegment *)textSegment - config:(StyleConfig *)config - allowTrailingMargin:(BOOL)allowTrailingMargin - allowFontScaling:(BOOL)allowFontScaling - maxFontSizeMultiplier:(CGFloat)maxFontSizeMultiplier +- (ENRMRenderResult *)renderTextSegment:(EMTextSegment *)textSegment + config:(StyleConfig *)config + allowTrailingMargin:(BOOL)allowTrailingMargin + allowFontScaling:(BOOL)allowFontScaling + maxFontSizeMultiplier:(CGFloat)maxFontSizeMultiplier { - MarkdownASTNode *temporaryRoot = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeDocument]; - for (MarkdownASTNode *node in textSegment.nodes) { - [temporaryRoot addChild:node]; - } - - AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:config]; - [renderer setAllowTrailingMargin:allowTrailingMargin]; - RenderContext *context = [RenderContext new]; - context.allowFontScaling = allowFontScaling; - context.maxFontSizeMultiplier = maxFontSizeMultiplier; - NSMutableAttributedString *attributedText = [renderer renderRoot:temporaryRoot context:context]; - - CGFloat lastMarginBottom = [renderer getLastElementMarginBottom]; - AccessibilityInfo *accessibilityInfo = [AccessibilityInfo infoFromContext:context]; - - return [EMRenderedTextSegment withAttributedText:attributedText - context:context - accessibilityInfo:accessibilityInfo - lastElementMarginBottom:lastMarginBottom]; + return ENRMRenderASTNodes(textSegment.nodes, config, allowTrailingMargin, allowFontScaling, maxFontSizeMultiplier, + currentWritingDirection()); } -- (EnrichedMarkdownInternalText *)createTextViewForRenderedSegment:(EMRenderedTextSegment *)segment +- (EnrichedMarkdownInternalText *)createTextViewForRenderedSegment:(ENRMRenderResult *)segment { EnrichedMarkdownInternalText *view = [[EnrichedMarkdownInternalText alloc] initWithConfig:_config]; view.spoilerMode = _spoilerMode; diff --git a/ios/EnrichedMarkdownText.mm b/ios/EnrichedMarkdownText.mm index bc68a52a..06e3f3cb 100644 --- a/ios/EnrichedMarkdownText.mm +++ b/ios/EnrichedMarkdownText.mm @@ -1,6 +1,4 @@ #import "EnrichedMarkdownText.h" -#import "AccessibilityInfo.h" -#import "AttributedRenderer.h" #import "CodeBlockBackground.h" #import "ContextMenuUtils.h" #import "ENRMContextMenuTextView+macOS.h" @@ -9,6 +7,7 @@ #import "ENRMSpoilerOverlayManager.h" #import "ENRMSpoilerTapUtils.h" #import "ENRMTailFadeInAnimator.h" +#import "ENRMTextRenderer.h" #import "ENRMTextViewSetup.h" #import "EditMenuUtils.h" #import "FontScaleObserver.h" @@ -19,7 +18,6 @@ #import "MarkdownAccessibilityElementBuilder.h" #import "MarkdownExtractor.h" #import "ParagraphStyleUtils.h" -#import "RenderContext.h" #import "RuntimeKeys.h" #import "StylePropsUtils.h" #import "TaskListTapUtils.h" @@ -259,29 +257,18 @@ - (void)renderMarkdownContent:(NSString *)markdownString return; } - AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:config]; - [renderer setAllowTrailingMargin:allowTrailingMargin]; - RenderContext *context = [RenderContext new]; - context.allowFontScaling = allowFontScaling; - context.maxFontSizeMultiplier = maxFontSizeMultiplier; - context.writingDirection = writingDirection; - NSMutableAttributedString *attributedText = [renderer renderRoot:ast context:context]; - - CGFloat lastElementMarginBottom = [renderer getLastElementMarginBottom]; - - [context applyLinkAttributesToString:attributedText]; - - AccessibilityInfo *accessibilityInfo = [AccessibilityInfo infoFromContext:context]; + ENRMRenderResult *result = ENRMRenderASTNodes(ast.children, config, allowTrailingMargin, allowFontScaling, + maxFontSizeMultiplier, writingDirection); dispatch_async(dispatch_get_main_queue(), ^{ if (renderId != self->_currentRenderId) { return; } - self->_lastElementMarginBottom = lastElementMarginBottom; - self->_accessibilityInfo = accessibilityInfo; + self->_lastElementMarginBottom = result.lastElementMarginBottom; + self->_accessibilityInfo = result.accessibilityInfo; - [self applyRenderedText:attributedText]; + [self applyRenderedText:result.attributedText]; }); }); } @@ -293,21 +280,14 @@ - (NSMutableAttributedString *)parseAndRenderMarkdown:(NSString *)markdownString return nil; } - AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:_config]; - [renderer setAllowTrailingMargin:_allowTrailingMargin]; - RenderContext *context = [RenderContext new]; - context.allowFontScaling = _fontScaleObserver.allowFontScaling; - context.maxFontSizeMultiplier = _maxFontSizeMultiplier; - context.writingDirection = currentWritingDirection(); - NSMutableAttributedString *attributedText = [renderer renderRoot:ast context:context]; - - _lastElementMarginBottom = [renderer getLastElementMarginBottom]; - - [context applyLinkAttributesToString:attributedText]; + ENRMRenderResult *result = + ENRMRenderASTNodes(ast.children, _config, _allowTrailingMargin, _fontScaleObserver.allowFontScaling, + _maxFontSizeMultiplier, currentWritingDirection()); - _accessibilityInfo = [AccessibilityInfo infoFromContext:context]; + _lastElementMarginBottom = result.lastElementMarginBottom; + _accessibilityInfo = result.accessibilityInfo; - return attributedText; + return result.attributedText; } /// Synchronous rendering for mock view measurement (no UI updates needed). diff --git a/ios/utils/ENRMTextRenderer.h b/ios/utils/ENRMTextRenderer.h new file mode 100644 index 00000000..d6345f7a --- /dev/null +++ b/ios/utils/ENRMTextRenderer.h @@ -0,0 +1,30 @@ +#pragma once +#import + +@class AccessibilityInfo; +@class MarkdownASTNode; +@class RenderContext; +@class StyleConfig; + +NS_ASSUME_NONNULL_BEGIN + +@interface ENRMRenderResult : NSObject +@property (nonatomic, strong) NSMutableAttributedString *attributedText; +@property (nonatomic, strong) RenderContext *context; +@property (nonatomic, strong) AccessibilityInfo *accessibilityInfo; +@property (nonatomic, assign) CGFloat lastElementMarginBottom; +@end + +#ifdef __cplusplus +extern "C" { +#endif + +ENRMRenderResult *ENRMRenderASTNodes(NSArray *nodes, StyleConfig *config, BOOL allowTrailingMargin, + BOOL allowFontScaling, CGFloat maxFontSizeMultiplier, + NSWritingDirection writingDirection); + +#ifdef __cplusplus +} +#endif + +NS_ASSUME_NONNULL_END diff --git a/ios/utils/ENRMTextRenderer.m b/ios/utils/ENRMTextRenderer.m new file mode 100644 index 00000000..f9783b44 --- /dev/null +++ b/ios/utils/ENRMTextRenderer.m @@ -0,0 +1,37 @@ +#import "ENRMTextRenderer.h" +#import "AccessibilityInfo.h" +#import "AttributedRenderer.h" +#import "MarkdownASTNode.h" +#import "RenderContext.h" +#import "StyleConfig.h" + +@implementation ENRMRenderResult +@end + +ENRMRenderResult *ENRMRenderASTNodes(NSArray *nodes, StyleConfig *config, BOOL allowTrailingMargin, + BOOL allowFontScaling, CGFloat maxFontSizeMultiplier, + NSWritingDirection writingDirection) +{ + MarkdownASTNode *root = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeDocument]; + for (MarkdownASTNode *node in nodes) { + [root addChild:node]; + } + + AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:config]; + [renderer setAllowTrailingMargin:allowTrailingMargin]; + + RenderContext *context = [RenderContext new]; + context.allowFontScaling = allowFontScaling; + context.maxFontSizeMultiplier = maxFontSizeMultiplier; + context.writingDirection = writingDirection; + + NSMutableAttributedString *attributedText = [renderer renderRoot:root context:context]; + [context applyLinkAttributesToString:attributedText]; + + ENRMRenderResult *result = [[ENRMRenderResult alloc] init]; + result.attributedText = attributedText; + result.context = context; + result.accessibilityInfo = [AccessibilityInfo infoFromContext:context]; + result.lastElementMarginBottom = [renderer getLastElementMarginBottom]; + return result; +} diff --git a/ios/views/EnrichedMarkdownInternalText.m b/ios/views/EnrichedMarkdownInternalText.m index 34d3eb91..67c93c30 100644 --- a/ios/views/EnrichedMarkdownInternalText.m +++ b/ios/views/EnrichedMarkdownInternalText.m @@ -1,10 +1,8 @@ #import "EnrichedMarkdownInternalText.h" -#import "AccessibilityInfo.h" #import "ENRMContextMenuTextView+macOS.h" #import "ENRMSpoilerOverlayManager.h" #import "ENRMTextViewSetup.h" #import "MarkdownAccessibilityElementBuilder.h" -#import "RenderContext.h" #import "RuntimeKeys.h" #include @@ -65,8 +63,6 @@ - (void)setSpoilerMode:(ENRMSpoilerMode)spoilerMode - (void)applyAttributedText:(NSMutableAttributedString *)text context:(RenderContext *)context { - [context applyLinkAttributesToString:text]; - NSLayoutManager *layoutManager = _textView.layoutManager; if ([layoutManager isKindOfClass:[TextViewLayoutManager class]]) { [layoutManager setValue:_config forKey:@"config"];