-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLinkRenderer.m
More file actions
87 lines (72 loc) · 3.67 KB
/
LinkRenderer.m
File metadata and controls
87 lines (72 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#import "LinkRenderer.h"
#import "FontUtils.h"
#import "RenderContext.h"
#import "RendererFactory.h"
#import "StyleConfig.h"
#import <React/RCTFont.h>
@implementation LinkRenderer {
__weak RendererFactory *_rendererFactory;
StyleConfig *_config;
}
- (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config
{
self = [super init];
if (self) {
_rendererFactory = rendererFactory;
_config = (StyleConfig *)config;
}
return self;
}
#pragma mark - Rendering
- (void)renderNode:(MarkdownASTNode *)node into:(NSMutableAttributedString *)output context:(RenderContext *)context
{
NSUInteger start = output.length;
// 1. Render children first to establish base attributes
[_rendererFactory renderChildrenOfNode:node into:output context:context];
NSRange range = NSMakeRange(start, output.length - start);
if (range.length == 0)
return;
// 2. Extract configuration
NSString *url = node.attributes[@"url"] ?: @"";
RCTUIColor *linkColor = [_config linkColor];
NSNumber *underlineStyle = @([_config linkUnderline] ? NSUnderlineStyleSingle : NSUnderlineStyleNone);
NSString *linkFontFamily = [_config linkFontFamily];
// 3. Apply core link functionality (non-destructive)
[output addAttribute:NSLinkAttributeName value:url range:range];
// 4. Optimize visual attributes via enumeration to avoid redundant updates
[output enumerateAttributesInRange:range
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
usingBlock:^(NSDictionary<NSAttributedStringKey, id> *attrs, NSRange subrange, BOOL *stop) {
NSMutableDictionary *newAttributes = [NSMutableDictionary dictionary];
// Only apply link color if the subrange isn't already colored by the link style
if (linkColor && ![attrs[NSForegroundColorAttributeName] isEqual:linkColor]) {
newAttributes[NSForegroundColorAttributeName] = linkColor;
newAttributes[NSUnderlineColorAttributeName] = linkColor;
}
// Only update underline style if it differs from the config
if (![attrs[NSUnderlineStyleAttributeName] isEqual:underlineStyle]) {
newAttributes[NSUnderlineStyleAttributeName] = underlineStyle;
}
if (linkFontFamily.length > 0) {
UIFont *currentFont = attrs[NSFontAttributeName];
if (currentFont) {
UIFont *linkFont = [RCTFont updateFont:currentFont
withFamily:linkFontFamily
size:nil
weight:nil
style:nil
variant:nil
scaleMultiplier:1.0];
if (linkFont && ![currentFont isEqual:linkFont]) {
newAttributes[NSFontAttributeName] = linkFont;
}
}
}
if (newAttributes.count > 0) {
[output addAttributes:newAttributes range:subrange];
}
}];
// 5. Register for touch handling
[context registerLinkRange:range url:url];
}
@end