Skip to content

Commit 806c3a0

Browse files
authored
refactor(ios): extract shared text renderer (#230)
1 parent 090f937 commit 806c3a0

5 files changed

Lines changed: 102 additions & 104 deletions

File tree

ios/EnrichedMarkdown.mm

Lines changed: 23 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
#import "EnrichedMarkdown.h"
2-
#import "AccessibilityInfo.h"
3-
#import "AttributedRenderer.h"
42
#import "ContextMenuUtils.h"
53
#import "ENRMImageAttachment.h"
64
#import "ENRMMarkdownParser.h"
5+
#import "ENRMTextRenderer.h"
76
#import "ENRMUIKit.h"
87
#import "EditMenuUtils.h"
98

@@ -25,7 +24,6 @@
2524
#import "MarkdownAccessibilityElementBuilder.h"
2625
#import "MarkdownExtractor.h"
2726
#import "ParagraphStyleUtils.h"
28-
#import "RenderContext.h"
2927
#import "RuntimeKeys.h"
3028
#import "StyleConfig.h"
3129
#import "StylePropsUtils.h"
@@ -91,32 +89,6 @@ + (instancetype)segmentWithLatex:(NSString *)latex
9189
@end
9290
#endif
9391

94-
@interface EMRenderedTextSegment : NSObject
95-
@property (nonatomic, strong) NSMutableAttributedString *attributedText;
96-
@property (nonatomic, strong) RenderContext *context;
97-
@property (nonatomic, strong) AccessibilityInfo *accessibilityInfo;
98-
@property (nonatomic, assign) CGFloat lastElementMarginBottom;
99-
+ (instancetype)withAttributedText:(NSMutableAttributedString *)text
100-
context:(RenderContext *)context
101-
accessibilityInfo:(AccessibilityInfo *)info
102-
lastElementMarginBottom:(CGFloat)marginBottom;
103-
@end
104-
105-
@implementation EMRenderedTextSegment
106-
+ (instancetype)withAttributedText:(NSMutableAttributedString *)text
107-
context:(RenderContext *)context
108-
accessibilityInfo:(AccessibilityInfo *)info
109-
lastElementMarginBottom:(CGFloat)marginBottom
110-
{
111-
EMRenderedTextSegment *segment = [[EMRenderedTextSegment alloc] init];
112-
segment.attributedText = text;
113-
segment.context = context;
114-
segment.accessibilityInfo = info;
115-
segment.lastElementMarginBottom = marginBottom;
116-
return segment;
117-
}
118-
@end
119-
12092
@interface EnrichedMarkdown () <RCTEnrichedMarkdownViewProtocol, UITextViewDelegate>
12193
@end
12294

@@ -363,11 +335,11 @@ - (void)renderMarkdownContent:(NSString *)markdownString
363335

364336
for (id segment in segments) {
365337
if ([segment isKindOfClass:[EMTextSegment class]]) {
366-
EMRenderedTextSegment *rendered = [self renderTextSegment:(EMTextSegment *)segment
367-
config:config
368-
allowTrailingMargin:allowTrailingMargin
369-
allowFontScaling:allowFontScaling
370-
maxFontSizeMultiplier:maxFontSizeMultiplier];
338+
ENRMRenderResult *rendered = [self renderTextSegment:(EMTextSegment *)segment
339+
config:config
340+
allowTrailingMargin:allowTrailingMargin
341+
allowFontScaling:allowFontScaling
342+
maxFontSizeMultiplier:maxFontSizeMultiplier];
371343
[renderedSegments addObject:rendered];
372344
} else if ([segment isKindOfClass:[EMTableSegment class]]) {
373345
[renderedSegments addObject:segment];
@@ -401,11 +373,11 @@ - (NSArray *)parseAndRenderSegments:(NSString *)markdownString
401373

402374
for (id segment in segments) {
403375
if ([segment isKindOfClass:[EMTextSegment class]]) {
404-
EMRenderedTextSegment *rendered = [self renderTextSegment:(EMTextSegment *)segment
405-
config:_config
406-
allowTrailingMargin:_allowTrailingMargin
407-
allowFontScaling:_fontScaleObserver.allowFontScaling
408-
maxFontSizeMultiplier:_maxFontSizeMultiplier];
376+
ENRMRenderResult *rendered = [self renderTextSegment:(EMTextSegment *)segment
377+
config:_config
378+
allowTrailingMargin:_allowTrailingMargin
379+
allowFontScaling:_fontScaleObserver.allowFontScaling
380+
maxFontSizeMultiplier:_maxFontSizeMultiplier];
409381
[renderedSegments addObject:rendered];
410382
} else if ([segment isKindOfClass:[EMTableSegment class]]) {
411383
[renderedSegments addObject:segment];
@@ -442,8 +414,8 @@ - (void)renderMarkdownSynchronously:(NSString *)markdownString
442414
}
443415

444416
for (id segment in renderedSegments) {
445-
if ([segment isKindOfClass:[EMRenderedTextSegment class]]) {
446-
EnrichedMarkdownInternalText *view = [self createTextViewForRenderedSegment:(EMRenderedTextSegment *)segment];
417+
if ([segment isKindOfClass:[ENRMRenderResult class]]) {
418+
EnrichedMarkdownInternalText *view = [self createTextViewForRenderedSegment:(ENRMRenderResult *)segment];
447419
[_segmentViews addObject:view];
448420
[self addSubview:view];
449421
} else if ([segment isKindOfClass:[EMTableSegment class]]) {
@@ -471,8 +443,8 @@ - (void)applyRenderedSegments:(NSArray *)renderedSegments
471443
[_segmentViews removeAllObjects];
472444

473445
for (id segment in renderedSegments) {
474-
if ([segment isKindOfClass:[EMRenderedTextSegment class]]) {
475-
EnrichedMarkdownInternalText *view = [self createTextViewForRenderedSegment:(EMRenderedTextSegment *)segment];
446+
if ([segment isKindOfClass:[ENRMRenderResult class]]) {
447+
EnrichedMarkdownInternalText *view = [self createTextViewForRenderedSegment:(ENRMRenderResult *)segment];
476448
[_segmentViews addObject:view];
477449
[self addSubview:view];
478450
} else if ([segment isKindOfClass:[EMTableSegment class]]) {
@@ -501,34 +473,17 @@ - (void)applyRenderedSegments:(NSArray *)renderedSegments
501473
}
502474
}
503475

504-
- (EMRenderedTextSegment *)renderTextSegment:(EMTextSegment *)textSegment
505-
config:(StyleConfig *)config
506-
allowTrailingMargin:(BOOL)allowTrailingMargin
507-
allowFontScaling:(BOOL)allowFontScaling
508-
maxFontSizeMultiplier:(CGFloat)maxFontSizeMultiplier
476+
- (ENRMRenderResult *)renderTextSegment:(EMTextSegment *)textSegment
477+
config:(StyleConfig *)config
478+
allowTrailingMargin:(BOOL)allowTrailingMargin
479+
allowFontScaling:(BOOL)allowFontScaling
480+
maxFontSizeMultiplier:(CGFloat)maxFontSizeMultiplier
509481
{
510-
MarkdownASTNode *temporaryRoot = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeDocument];
511-
for (MarkdownASTNode *node in textSegment.nodes) {
512-
[temporaryRoot addChild:node];
513-
}
514-
515-
AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:config];
516-
[renderer setAllowTrailingMargin:allowTrailingMargin];
517-
RenderContext *context = [RenderContext new];
518-
context.allowFontScaling = allowFontScaling;
519-
context.maxFontSizeMultiplier = maxFontSizeMultiplier;
520-
NSMutableAttributedString *attributedText = [renderer renderRoot:temporaryRoot context:context];
521-
522-
CGFloat lastMarginBottom = [renderer getLastElementMarginBottom];
523-
AccessibilityInfo *accessibilityInfo = [AccessibilityInfo infoFromContext:context];
524-
525-
return [EMRenderedTextSegment withAttributedText:attributedText
526-
context:context
527-
accessibilityInfo:accessibilityInfo
528-
lastElementMarginBottom:lastMarginBottom];
482+
return ENRMRenderASTNodes(textSegment.nodes, config, allowTrailingMargin, allowFontScaling, maxFontSizeMultiplier,
483+
currentWritingDirection());
529484
}
530485

531-
- (EnrichedMarkdownInternalText *)createTextViewForRenderedSegment:(EMRenderedTextSegment *)segment
486+
- (EnrichedMarkdownInternalText *)createTextViewForRenderedSegment:(ENRMRenderResult *)segment
532487
{
533488
EnrichedMarkdownInternalText *view = [[EnrichedMarkdownInternalText alloc] initWithConfig:_config];
534489
view.spoilerMode = _spoilerMode;

ios/EnrichedMarkdownText.mm

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
#import "EnrichedMarkdownText.h"
2-
#import "AccessibilityInfo.h"
3-
#import "AttributedRenderer.h"
42
#import "CodeBlockBackground.h"
53
#import "ContextMenuUtils.h"
64
#import "ENRMContextMenuTextView+macOS.h"
@@ -9,6 +7,7 @@
97
#import "ENRMSpoilerOverlayManager.h"
108
#import "ENRMSpoilerTapUtils.h"
119
#import "ENRMTailFadeInAnimator.h"
10+
#import "ENRMTextRenderer.h"
1211
#import "ENRMTextViewSetup.h"
1312
#import "EditMenuUtils.h"
1413
#import "FontScaleObserver.h"
@@ -19,7 +18,6 @@
1918
#import "MarkdownAccessibilityElementBuilder.h"
2019
#import "MarkdownExtractor.h"
2120
#import "ParagraphStyleUtils.h"
22-
#import "RenderContext.h"
2321
#import "RuntimeKeys.h"
2422
#import "StylePropsUtils.h"
2523
#import "TaskListTapUtils.h"
@@ -259,29 +257,18 @@ - (void)renderMarkdownContent:(NSString *)markdownString
259257
return;
260258
}
261259

262-
AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:config];
263-
[renderer setAllowTrailingMargin:allowTrailingMargin];
264-
RenderContext *context = [RenderContext new];
265-
context.allowFontScaling = allowFontScaling;
266-
context.maxFontSizeMultiplier = maxFontSizeMultiplier;
267-
context.writingDirection = writingDirection;
268-
NSMutableAttributedString *attributedText = [renderer renderRoot:ast context:context];
269-
270-
CGFloat lastElementMarginBottom = [renderer getLastElementMarginBottom];
271-
272-
[context applyLinkAttributesToString:attributedText];
273-
274-
AccessibilityInfo *accessibilityInfo = [AccessibilityInfo infoFromContext:context];
260+
ENRMRenderResult *result = ENRMRenderASTNodes(ast.children, config, allowTrailingMargin, allowFontScaling,
261+
maxFontSizeMultiplier, writingDirection);
275262

276263
dispatch_async(dispatch_get_main_queue(), ^{
277264
if (renderId != self->_currentRenderId) {
278265
return;
279266
}
280267

281-
self->_lastElementMarginBottom = lastElementMarginBottom;
282-
self->_accessibilityInfo = accessibilityInfo;
268+
self->_lastElementMarginBottom = result.lastElementMarginBottom;
269+
self->_accessibilityInfo = result.accessibilityInfo;
283270

284-
[self applyRenderedText:attributedText];
271+
[self applyRenderedText:result.attributedText];
285272
});
286273
});
287274
}
@@ -293,21 +280,14 @@ - (NSMutableAttributedString *)parseAndRenderMarkdown:(NSString *)markdownString
293280
return nil;
294281
}
295282

296-
AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:_config];
297-
[renderer setAllowTrailingMargin:_allowTrailingMargin];
298-
RenderContext *context = [RenderContext new];
299-
context.allowFontScaling = _fontScaleObserver.allowFontScaling;
300-
context.maxFontSizeMultiplier = _maxFontSizeMultiplier;
301-
context.writingDirection = currentWritingDirection();
302-
NSMutableAttributedString *attributedText = [renderer renderRoot:ast context:context];
303-
304-
_lastElementMarginBottom = [renderer getLastElementMarginBottom];
305-
306-
[context applyLinkAttributesToString:attributedText];
283+
ENRMRenderResult *result =
284+
ENRMRenderASTNodes(ast.children, _config, _allowTrailingMargin, _fontScaleObserver.allowFontScaling,
285+
_maxFontSizeMultiplier, currentWritingDirection());
307286

308-
_accessibilityInfo = [AccessibilityInfo infoFromContext:context];
287+
_lastElementMarginBottom = result.lastElementMarginBottom;
288+
_accessibilityInfo = result.accessibilityInfo;
309289

310-
return attributedText;
290+
return result.attributedText;
311291
}
312292

313293
/// Synchronous rendering for mock view measurement (no UI updates needed).

ios/utils/ENRMTextRenderer.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
#import <Foundation/Foundation.h>
3+
4+
@class AccessibilityInfo;
5+
@class MarkdownASTNode;
6+
@class RenderContext;
7+
@class StyleConfig;
8+
9+
NS_ASSUME_NONNULL_BEGIN
10+
11+
@interface ENRMRenderResult : NSObject
12+
@property (nonatomic, strong) NSMutableAttributedString *attributedText;
13+
@property (nonatomic, strong) RenderContext *context;
14+
@property (nonatomic, strong) AccessibilityInfo *accessibilityInfo;
15+
@property (nonatomic, assign) CGFloat lastElementMarginBottom;
16+
@end
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
ENRMRenderResult *ENRMRenderASTNodes(NSArray<MarkdownASTNode *> *nodes, StyleConfig *config, BOOL allowTrailingMargin,
23+
BOOL allowFontScaling, CGFloat maxFontSizeMultiplier,
24+
NSWritingDirection writingDirection);
25+
26+
#ifdef __cplusplus
27+
}
28+
#endif
29+
30+
NS_ASSUME_NONNULL_END

ios/utils/ENRMTextRenderer.m

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#import "ENRMTextRenderer.h"
2+
#import "AccessibilityInfo.h"
3+
#import "AttributedRenderer.h"
4+
#import "MarkdownASTNode.h"
5+
#import "RenderContext.h"
6+
#import "StyleConfig.h"
7+
8+
@implementation ENRMRenderResult
9+
@end
10+
11+
ENRMRenderResult *ENRMRenderASTNodes(NSArray<MarkdownASTNode *> *nodes, StyleConfig *config, BOOL allowTrailingMargin,
12+
BOOL allowFontScaling, CGFloat maxFontSizeMultiplier,
13+
NSWritingDirection writingDirection)
14+
{
15+
MarkdownASTNode *root = [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeDocument];
16+
for (MarkdownASTNode *node in nodes) {
17+
[root addChild:node];
18+
}
19+
20+
AttributedRenderer *renderer = [[AttributedRenderer alloc] initWithConfig:config];
21+
[renderer setAllowTrailingMargin:allowTrailingMargin];
22+
23+
RenderContext *context = [RenderContext new];
24+
context.allowFontScaling = allowFontScaling;
25+
context.maxFontSizeMultiplier = maxFontSizeMultiplier;
26+
context.writingDirection = writingDirection;
27+
28+
NSMutableAttributedString *attributedText = [renderer renderRoot:root context:context];
29+
[context applyLinkAttributesToString:attributedText];
30+
31+
ENRMRenderResult *result = [[ENRMRenderResult alloc] init];
32+
result.attributedText = attributedText;
33+
result.context = context;
34+
result.accessibilityInfo = [AccessibilityInfo infoFromContext:context];
35+
result.lastElementMarginBottom = [renderer getLastElementMarginBottom];
36+
return result;
37+
}

ios/views/EnrichedMarkdownInternalText.m

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
#import "EnrichedMarkdownInternalText.h"
2-
#import "AccessibilityInfo.h"
32
#import "ENRMContextMenuTextView+macOS.h"
43
#import "ENRMSpoilerOverlayManager.h"
54
#import "ENRMTextViewSetup.h"
65
#import "MarkdownAccessibilityElementBuilder.h"
7-
#import "RenderContext.h"
86
#import "RuntimeKeys.h"
97
#include <TargetConditionals.h>
108

@@ -65,8 +63,6 @@ - (void)setSpoilerMode:(ENRMSpoilerMode)spoilerMode
6563

6664
- (void)applyAttributedText:(NSMutableAttributedString *)text context:(RenderContext *)context
6765
{
68-
[context applyLinkAttributesToString:text];
69-
7066
NSLayoutManager *layoutManager = _textView.layoutManager;
7167
if ([layoutManager isKindOfClass:[TextViewLayoutManager class]]) {
7268
[layoutManager setValue:_config forKey:@"config"];

0 commit comments

Comments
 (0)