react-native-enriched-markdown-scaffold 1.0.2-scaffold.3 → 1.0.2-scaffold.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +1 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +1 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +48 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +32 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +10 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +122 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +8 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +8 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLayoutEvent.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +37 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +5 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +13 -99
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/InlineChipPainter.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkChipSpans.kt +177 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +1 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +36 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +7 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLayoutCollector.kt +100 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +4 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +14 -0
- package/docs/API_REFERENCE.md +53 -0
- package/docs/MENTIONS.md +8 -1
- package/docs/STYLES.md +27 -0
- package/docs/TEXT.md +2 -0
- package/ios/EnrichedMarkdown.mm +48 -0
- package/ios/EnrichedMarkdownText.mm +39 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +48 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +32 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +10 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +122 -0
- package/ios/internals/MeasurementCache.h +5 -0
- package/ios/renderer/LinkRenderer.m +47 -15
- package/ios/styles/StyleConfig.h +16 -0
- package/ios/styles/StyleConfig.mm +60 -0
- package/ios/utils/CodeBackground.m +3 -65
- package/ios/utils/ENRMChipDrawing.h +24 -0
- package/ios/utils/ENRMChipDrawing.m +83 -0
- package/ios/utils/ENRMLinkChip.h +70 -0
- package/ios/utils/ENRMLinkChip.m +194 -0
- package/ios/utils/ENRMLinkLayout.h +50 -0
- package/ios/utils/ENRMLinkLayout.m +45 -0
- package/ios/utils/EditMenuUtils+macOS.m +4 -1
- package/ios/utils/EditMenuUtils.m +4 -1
- package/ios/utils/HTMLGenerator.m +2 -1
- package/ios/utils/MarkdownAccessibilityElementBuilder.m +4 -1
- package/ios/utils/MarkdownExtractor.m +2 -1
- package/ios/utils/RTFExportUtils.m +2 -0
- package/ios/utils/StylePropsUtils.h +37 -1
- package/ios/utils/TextViewLayoutManager.mm +3 -0
- package/ios/views/TableContainerView.h +3 -0
- package/ios/views/TableContainerView.m +21 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +41 -0
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +41 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/EnrichedMarkdownText.js +96 -7
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +13 -2
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +13 -2
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/web/EnrichedMarkdownText.js +6 -3
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +96 -3
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/styles.js +18 -0
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +13 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +40 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +40 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +1 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +28 -5
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +10 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +41 -0
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +41 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +4 -0
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts +4 -0
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/EnrichedMarkdownNativeComponent.ts +41 -0
- package/src/EnrichedMarkdownTextNativeComponent.ts +41 -0
- package/src/index.tsx +2 -0
- package/src/index.web.tsx +5 -1
- package/src/native/EnrichedMarkdownText.tsx +103 -6
- package/src/normalizeMarkdownStyle.ts +13 -0
- package/src/normalizeMarkdownStyle.web.ts +11 -0
- package/src/types/MarkdownStyle.ts +29 -5
- package/src/types/MarkdownStyleInternal.ts +10 -0
- package/src/types/MarkdownTextProps.ts +43 -0
- package/src/types/MarkdownTextProps.web.ts +43 -1
- package/src/web/EnrichedMarkdownText.tsx +10 -3
- package/src/web/renderers/InlineRenderers.tsx +111 -3
- package/src/web/styles.ts +25 -0
- package/src/web/types.ts +4 -0
- package/src/web/utils.ts +8 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
/// Marks a link range that carries chip styling. The value is one
|
|
7
|
+
/// `ENRMLinkChip` instance per link: instances compare by identity, so two
|
|
8
|
+
/// adjacent links never coalesce into one attribute run (one chip).
|
|
9
|
+
extern NSString *const ENRMLinkChipAttributeName;
|
|
10
|
+
|
|
11
|
+
/// Marks the spacer characters `LinkRenderer` inserts at both outer edges of a
|
|
12
|
+
/// link to reserve `paddingHorizontal` in the line. Spacers are layout-only:
|
|
13
|
+
/// every text exit point (copy, markdown/HTML export, decoration text) strips
|
|
14
|
+
/// them by this attribute — never by character, since U+00A0 can be content.
|
|
15
|
+
extern NSString *const ENRMLinkSpacerAttributeName;
|
|
16
|
+
|
|
17
|
+
@interface ENRMLinkChip : NSObject
|
|
18
|
+
@property (nonatomic, strong, nullable) RCTUIColor *backgroundColor;
|
|
19
|
+
@property (nonatomic, strong, nullable) RCTUIColor *borderColor;
|
|
20
|
+
@property (nonatomic, assign) CGFloat borderWidth;
|
|
21
|
+
@property (nonatomic, assign) CGFloat borderRadius;
|
|
22
|
+
@property (nonatomic, assign) CGFloat paddingHorizontal;
|
|
23
|
+
@property (nonatomic, assign) CGFloat paddingVertical;
|
|
24
|
+
/// YES when the chip paints something (a background or a visible border).
|
|
25
|
+
@property (nonatomic, readonly) BOOL isVisible;
|
|
26
|
+
@end
|
|
27
|
+
|
|
28
|
+
#ifdef __cplusplus
|
|
29
|
+
extern "C" {
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
/// A spacer character (U+00A0) whose advance is exactly `width`.
|
|
33
|
+
///
|
|
34
|
+
/// U+00A0 is line-break class GL: a break is allowed before it after a space
|
|
35
|
+
/// but never after it, and never before it after a non-space — so a leading
|
|
36
|
+
/// spacer always travels with the link's first glyph and a trailing one with
|
|
37
|
+
/// its last glyph (no orphaned padding at a wrap). It uses a 1pt system font
|
|
38
|
+
/// so its own advance and line-height contribution are negligible whatever
|
|
39
|
+
/// the link font (a custom font may lack U+00A0), and NSKern makes up the rest.
|
|
40
|
+
NSAttributedString *ENRMLinkSpacerString(NSDictionary<NSAttributedStringKey, id> *baseAttributes, CGFloat width);
|
|
41
|
+
|
|
42
|
+
/// `string` without link spacers (returns `string` itself when it has none).
|
|
43
|
+
NSAttributedString *ENRMAttributedStringByRemovingLinkSpacers(NSAttributedString *string);
|
|
44
|
+
|
|
45
|
+
/// Plain text of `range` without link spacers.
|
|
46
|
+
NSString *ENRMPlainTextByRemovingLinkSpacers(NSAttributedString *string, NSRange range);
|
|
47
|
+
|
|
48
|
+
/// Falls back to a plain `NSBackgroundColorAttributeName` for every chip
|
|
49
|
+
/// background, for text drawn without `TextViewLayoutManager` (table cells,
|
|
50
|
+
/// RTF export). Radius, border and vertical padding are not represented.
|
|
51
|
+
void ENRMApplyLinkChipBackgroundsAsTextBackground(NSMutableAttributedString *string);
|
|
52
|
+
|
|
53
|
+
/// Enumerates the chip rect of every laid-out line fragment of the link at
|
|
54
|
+
/// `charRange`, in text-container coordinates. The rect spans the glyphs
|
|
55
|
+
/// (spacers included, so it already covers `paddingHorizontal`) horizontally
|
|
56
|
+
/// and the link font's ascender..descender ± `paddingVertical` vertically.
|
|
57
|
+
void ENRMEnumerateLinkChipFragments(NSLayoutManager *layoutManager, NSTextContainer *textContainer, NSRange charRange,
|
|
58
|
+
ENRMLinkChip *_Nullable chip,
|
|
59
|
+
void (^block)(CGRect rect, BOOL isFirst, BOOL isLast));
|
|
60
|
+
|
|
61
|
+
/// Draws the visible link chips intersecting `glyphsToShow`. Called from the
|
|
62
|
+
/// layout manager's background pass, before glyphs are drawn.
|
|
63
|
+
void ENRMDrawLinkChipsForGlyphRange(NSLayoutManager *layoutManager, NSTextContainer *textContainer,
|
|
64
|
+
NSRange glyphsToShow, CGPoint origin);
|
|
65
|
+
|
|
66
|
+
#ifdef __cplusplus
|
|
67
|
+
}
|
|
68
|
+
#endif
|
|
69
|
+
|
|
70
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#import "ENRMLinkChip.h"
|
|
2
|
+
#import "ENRMChipDrawing.h"
|
|
3
|
+
#import <CoreText/CoreText.h>
|
|
4
|
+
|
|
5
|
+
NSString *const ENRMLinkChipAttributeName = @"ENRMLinkChip";
|
|
6
|
+
NSString *const ENRMLinkSpacerAttributeName = @"ENRMLinkSpacer";
|
|
7
|
+
|
|
8
|
+
static const unichar kSpacerChar = 0x00A0;
|
|
9
|
+
static const CGFloat kSpacerFontSize = 1.0;
|
|
10
|
+
|
|
11
|
+
@implementation ENRMLinkChip
|
|
12
|
+
|
|
13
|
+
- (BOOL)isVisible
|
|
14
|
+
{
|
|
15
|
+
return self.backgroundColor != nil || (self.borderColor != nil && self.borderWidth > 0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@end
|
|
19
|
+
|
|
20
|
+
#pragma mark - Spacers
|
|
21
|
+
|
|
22
|
+
static CGFloat spacerAdvance(UIFont *font)
|
|
23
|
+
{
|
|
24
|
+
CTFontRef ctFont = (__bridge CTFontRef)font;
|
|
25
|
+
UniChar character = kSpacerChar;
|
|
26
|
+
CGGlyph glyph = 0;
|
|
27
|
+
if (!CTFontGetGlyphsForCharacters(ctFont, &character, &glyph, 1))
|
|
28
|
+
return 0;
|
|
29
|
+
CGSize advance = CGSizeZero;
|
|
30
|
+
CTFontGetAdvancesForGlyphs(ctFont, kCTFontOrientationHorizontal, &glyph, &advance, 1);
|
|
31
|
+
return advance.width;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
NSAttributedString *ENRMLinkSpacerString(NSDictionary<NSAttributedStringKey, id> *baseAttributes, CGFloat width)
|
|
35
|
+
{
|
|
36
|
+
static UIFont *spacerFont;
|
|
37
|
+
static CGFloat spacerFontAdvance;
|
|
38
|
+
static dispatch_once_t onceToken;
|
|
39
|
+
dispatch_once(&onceToken, ^{
|
|
40
|
+
spacerFont = [UIFont systemFontOfSize:kSpacerFontSize];
|
|
41
|
+
spacerFontAdvance = spacerAdvance(spacerFont);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
NSMutableDictionary *attributes = [baseAttributes mutableCopy] ?: [NSMutableDictionary dictionary];
|
|
45
|
+
attributes[NSFontAttributeName] = spacerFont;
|
|
46
|
+
attributes[NSKernAttributeName] = @(width - spacerFontAdvance);
|
|
47
|
+
attributes[ENRMLinkSpacerAttributeName] = @YES;
|
|
48
|
+
// Padding is not text: keep decorations and attachments off it.
|
|
49
|
+
[attributes removeObjectForKey:NSUnderlineStyleAttributeName];
|
|
50
|
+
[attributes removeObjectForKey:NSStrikethroughStyleAttributeName];
|
|
51
|
+
[attributes removeObjectForKey:NSAttachmentAttributeName];
|
|
52
|
+
|
|
53
|
+
NSString *spacer = [NSString stringWithCharacters:&kSpacerChar length:1];
|
|
54
|
+
return [[NSAttributedString alloc] initWithString:spacer attributes:attributes];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
NSAttributedString *ENRMAttributedStringByRemovingLinkSpacers(NSAttributedString *string)
|
|
58
|
+
{
|
|
59
|
+
__block NSMutableAttributedString *stripped = nil;
|
|
60
|
+
[string enumerateAttribute:ENRMLinkSpacerAttributeName
|
|
61
|
+
inRange:NSMakeRange(0, string.length)
|
|
62
|
+
options:NSAttributedStringEnumerationReverse
|
|
63
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
64
|
+
if (!value)
|
|
65
|
+
return;
|
|
66
|
+
if (!stripped)
|
|
67
|
+
stripped = [string mutableCopy];
|
|
68
|
+
[stripped deleteCharactersInRange:range];
|
|
69
|
+
}];
|
|
70
|
+
return stripped ?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
NSString *ENRMPlainTextByRemovingLinkSpacers(NSAttributedString *string, NSRange range)
|
|
74
|
+
{
|
|
75
|
+
if (range.location == NSNotFound || NSMaxRange(range) > string.length)
|
|
76
|
+
return @"";
|
|
77
|
+
return ENRMAttributedStringByRemovingLinkSpacers([string attributedSubstringFromRange:range]).string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
void ENRMApplyLinkChipBackgroundsAsTextBackground(NSMutableAttributedString *string)
|
|
81
|
+
{
|
|
82
|
+
[string enumerateAttribute:ENRMLinkChipAttributeName
|
|
83
|
+
inRange:NSMakeRange(0, string.length)
|
|
84
|
+
options:0
|
|
85
|
+
usingBlock:^(ENRMLinkChip *chip, NSRange range, BOOL *stop) {
|
|
86
|
+
if (chip.backgroundColor) {
|
|
87
|
+
[string addAttribute:NSBackgroundColorAttributeName value:chip.backgroundColor range:range];
|
|
88
|
+
}
|
|
89
|
+
}];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#pragma mark - Geometry
|
|
93
|
+
|
|
94
|
+
/// The font of the first non-spacer character of `charRange` — the spacer's
|
|
95
|
+
/// 1pt font must not drive the chip's height.
|
|
96
|
+
static UIFont *_Nullable chipFontInRange(NSTextStorage *storage, NSRange charRange)
|
|
97
|
+
{
|
|
98
|
+
__block UIFont *font = nil;
|
|
99
|
+
[storage enumerateAttributesInRange:charRange
|
|
100
|
+
options:0
|
|
101
|
+
usingBlock:^(NSDictionary<NSAttributedStringKey, id> *attrs, NSRange range, BOOL *stop) {
|
|
102
|
+
if (attrs[ENRMLinkSpacerAttributeName])
|
|
103
|
+
return;
|
|
104
|
+
font = attrs[NSFontAttributeName];
|
|
105
|
+
*stop = font != nil;
|
|
106
|
+
}];
|
|
107
|
+
return font;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void ENRMEnumerateLinkChipFragments(NSLayoutManager *layoutManager, NSTextContainer *textContainer, NSRange charRange,
|
|
111
|
+
ENRMLinkChip *chip, void (^block)(CGRect rect, BOOL isFirst, BOOL isLast))
|
|
112
|
+
{
|
|
113
|
+
NSTextStorage *storage = layoutManager.textStorage;
|
|
114
|
+
if (charRange.length == 0 || NSMaxRange(charRange) > storage.length)
|
|
115
|
+
return;
|
|
116
|
+
|
|
117
|
+
NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:charRange actualCharacterRange:NULL];
|
|
118
|
+
if (glyphRange.location == NSNotFound || glyphRange.length == 0)
|
|
119
|
+
return;
|
|
120
|
+
|
|
121
|
+
CGFloat paddingHorizontal = chip.paddingHorizontal;
|
|
122
|
+
CGFloat paddingVertical = chip.paddingVertical;
|
|
123
|
+
|
|
124
|
+
[layoutManager
|
|
125
|
+
enumerateLineFragmentsForGlyphRange:glyphRange
|
|
126
|
+
usingBlock:^(CGRect lineRect, CGRect usedRect, NSTextContainer *tc, NSRange lineRange,
|
|
127
|
+
BOOL *stop) {
|
|
128
|
+
NSRange intersect = NSIntersectionRange(lineRange, glyphRange);
|
|
129
|
+
if (intersect.length == 0)
|
|
130
|
+
return;
|
|
131
|
+
|
|
132
|
+
BOOL isFirst = intersect.location == glyphRange.location;
|
|
133
|
+
BOOL isLast = NSMaxRange(intersect) == NSMaxRange(glyphRange);
|
|
134
|
+
|
|
135
|
+
CGRect textRect = [layoutManager boundingRectForGlyphRange:intersect
|
|
136
|
+
inTextContainer:textContainer];
|
|
137
|
+
CGFloat left = CGRectGetMinX(textRect);
|
|
138
|
+
CGFloat right = CGRectGetMaxX(textRect);
|
|
139
|
+
|
|
140
|
+
// The trailing spacer's kern is its advance; don't rely on the
|
|
141
|
+
// glyph bounds including it.
|
|
142
|
+
if (isLast && paddingHorizontal > 0) {
|
|
143
|
+
NSUInteger lastGlyph = NSMaxRange(intersect) - 1;
|
|
144
|
+
CGFloat spacerX =
|
|
145
|
+
lineRect.origin.x + [layoutManager locationForGlyphAtIndex:lastGlyph].x;
|
|
146
|
+
right = MAX(right, spacerX + paddingHorizontal);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
NSRange fragmentChars = [layoutManager characterRangeForGlyphRange:intersect
|
|
150
|
+
actualGlyphRange:NULL];
|
|
151
|
+
UIFont *font = chipFontInRange(storage, fragmentChars);
|
|
152
|
+
CGFloat top = CGRectGetMinY(textRect);
|
|
153
|
+
CGFloat bottom = CGRectGetMaxY(textRect);
|
|
154
|
+
if (font) {
|
|
155
|
+
// locationForGlyphAtIndex: y is the baseline within the line fragment.
|
|
156
|
+
CGFloat baseline =
|
|
157
|
+
lineRect.origin.y + [layoutManager locationForGlyphAtIndex:intersect.location].y;
|
|
158
|
+
top = baseline - font.ascender;
|
|
159
|
+
bottom = baseline - font.descender;
|
|
160
|
+
}
|
|
161
|
+
top -= paddingVertical;
|
|
162
|
+
bottom += paddingVertical;
|
|
163
|
+
|
|
164
|
+
block(CGRectMake(left, top, right - left, bottom - top), isFirst, isLast);
|
|
165
|
+
}];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
#pragma mark - Drawing
|
|
169
|
+
|
|
170
|
+
void ENRMDrawLinkChipsForGlyphRange(NSLayoutManager *layoutManager, NSTextContainer *textContainer,
|
|
171
|
+
NSRange glyphsToShow, CGPoint origin)
|
|
172
|
+
{
|
|
173
|
+
NSTextStorage *storage = layoutManager.textStorage;
|
|
174
|
+
NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphsToShow actualGlyphRange:NULL];
|
|
175
|
+
if (charRange.location == NSNotFound || charRange.length == 0)
|
|
176
|
+
return;
|
|
177
|
+
|
|
178
|
+
// Enumerate the whole storage (like CodeBackground) so a chip that starts
|
|
179
|
+
// before the dirty range still gets its full rect.
|
|
180
|
+
[storage enumerateAttribute:ENRMLinkChipAttributeName
|
|
181
|
+
inRange:NSMakeRange(0, storage.length)
|
|
182
|
+
options:0
|
|
183
|
+
usingBlock:^(ENRMLinkChip *chip, NSRange range, BOOL *stop) {
|
|
184
|
+
if (!chip.isVisible || NSIntersectionRange(range, charRange).length == 0)
|
|
185
|
+
return;
|
|
186
|
+
|
|
187
|
+
ENRMEnumerateLinkChipFragments(
|
|
188
|
+
layoutManager, textContainer, range, chip, ^(CGRect rect, BOOL isFirst, BOOL isLast) {
|
|
189
|
+
ENRMDrawChipFragment(CGRectOffset(rect, origin.x, origin.y), chip.backgroundColor,
|
|
190
|
+
chip.borderColor, chip.borderWidth, chip.borderRadius, isFirst, isLast,
|
|
191
|
+
YES);
|
|
192
|
+
});
|
|
193
|
+
}];
|
|
194
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
#ifdef __cplusplus
|
|
7
|
+
extern "C" {
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
/// Collects the chip rect of every link fragment laid out in `textView`, for
|
|
11
|
+
/// the `onLinkLayout` event. Each entry is
|
|
12
|
+
/// `@{linkIndex, url, text, x, y, width, height}` (NSNumber/NSString), so a
|
|
13
|
+
/// payload compares with `-isEqualToArray:` for deduplication.
|
|
14
|
+
///
|
|
15
|
+
/// - `offset` is added to every rect (a segment's origin inside its container).
|
|
16
|
+
/// - Links are numbered in document order starting at `indexBase`; the number
|
|
17
|
+
/// of links found is written to `outLinkCount` so the next segment continues.
|
|
18
|
+
///
|
|
19
|
+
/// Rects are in points relative to the text view, which the markdown views
|
|
20
|
+
/// configure with zero insets and no line-fragment padding.
|
|
21
|
+
NSArray<NSDictionary *> *ENRMCollectLinkLayoutFragments(ENRMPlatformTextView *textView, CGPoint offset,
|
|
22
|
+
NSInteger indexBase, NSInteger *_Nullable outLinkCount);
|
|
23
|
+
|
|
24
|
+
#ifdef __cplusplus
|
|
25
|
+
}
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
#ifdef __cplusplus
|
|
29
|
+
/// Converts collected fragments into a codegen `OnLinkLayout` payload. Templated
|
|
30
|
+
/// because each component has its own (structurally identical) event struct.
|
|
31
|
+
template <typename Event> inline Event ENRMLinkLayoutEventFromFragments(NSArray<NSDictionary *> *fragments)
|
|
32
|
+
{
|
|
33
|
+
Event event;
|
|
34
|
+
event.fragments.reserve(fragments.count);
|
|
35
|
+
for (NSDictionary *fragment in fragments) {
|
|
36
|
+
typename decltype(event.fragments)::value_type item;
|
|
37
|
+
item.linkIndex = [fragment[@"linkIndex"] intValue];
|
|
38
|
+
item.url = std::string([fragment[@"url"] UTF8String] ?: "");
|
|
39
|
+
item.text = std::string([fragment[@"text"] UTF8String] ?: "");
|
|
40
|
+
item.x = [fragment[@"x"] doubleValue];
|
|
41
|
+
item.y = [fragment[@"y"] doubleValue];
|
|
42
|
+
item.width = [fragment[@"width"] doubleValue];
|
|
43
|
+
item.height = [fragment[@"height"] doubleValue];
|
|
44
|
+
event.fragments.push_back(item);
|
|
45
|
+
}
|
|
46
|
+
return event;
|
|
47
|
+
}
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#import "ENRMLinkLayout.h"
|
|
2
|
+
#import "ENRMLinkChip.h"
|
|
3
|
+
|
|
4
|
+
NSArray<NSDictionary *> *ENRMCollectLinkLayoutFragments(ENRMPlatformTextView *textView, CGPoint offset,
|
|
5
|
+
NSInteger indexBase, NSInteger *outLinkCount)
|
|
6
|
+
{
|
|
7
|
+
NSLayoutManager *layoutManager = textView.layoutManager;
|
|
8
|
+
NSTextContainer *textContainer = textView.textContainer;
|
|
9
|
+
NSTextStorage *storage = layoutManager.textStorage;
|
|
10
|
+
NSMutableArray<NSDictionary *> *fragments = [NSMutableArray array];
|
|
11
|
+
__block NSInteger linkIndex = indexBase;
|
|
12
|
+
|
|
13
|
+
if (storage.length > 0 && textContainer != nil) {
|
|
14
|
+
// LinkRenderer attaches one ENRMLinkChip instance per link, so each
|
|
15
|
+
// attribute run is exactly one link (adjacent links never coalesce).
|
|
16
|
+
[storage enumerateAttribute:ENRMLinkChipAttributeName
|
|
17
|
+
inRange:NSMakeRange(0, storage.length)
|
|
18
|
+
options:0
|
|
19
|
+
usingBlock:^(ENRMLinkChip *chip, NSRange range, BOOL *stop) {
|
|
20
|
+
if (!chip)
|
|
21
|
+
return;
|
|
22
|
+
id link = [storage attribute:NSLinkAttributeName atIndex:range.location effectiveRange:NULL];
|
|
23
|
+
NSString *url = [link isKindOfClass:[NSURL class]] ? [(NSURL *)link absoluteString] : link;
|
|
24
|
+
NSString *text = ENRMPlainTextByRemovingLinkSpacers(storage, range);
|
|
25
|
+
NSNumber *index = @(linkIndex++);
|
|
26
|
+
|
|
27
|
+
ENRMEnumerateLinkChipFragments(
|
|
28
|
+
layoutManager, textContainer, range, chip, ^(CGRect rect, BOOL isFirst, BOOL isLast) {
|
|
29
|
+
[fragments addObject:@{
|
|
30
|
+
@"linkIndex" : index,
|
|
31
|
+
@"url" : url ?: @"",
|
|
32
|
+
@"text" : text,
|
|
33
|
+
@"x" : @(rect.origin.x + offset.x),
|
|
34
|
+
@"y" : @(rect.origin.y + offset.y),
|
|
35
|
+
@"width" : @(rect.size.width),
|
|
36
|
+
@"height" : @(rect.size.height),
|
|
37
|
+
}];
|
|
38
|
+
});
|
|
39
|
+
}];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (outLinkCount)
|
|
43
|
+
*outLinkCount = linkIndex - indexBase;
|
|
44
|
+
return fragments;
|
|
45
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import "ContextMenuUtils.h"
|
|
2
2
|
#import "ENRMMenuAction.h"
|
|
3
3
|
#import "EditMenuUtils.h"
|
|
4
|
+
#import "ENRMLinkChip.h"
|
|
4
5
|
#import "PasteboardUtils.h"
|
|
5
6
|
#import "StyleConfig.h"
|
|
6
7
|
#include <TargetConditionals.h>
|
|
@@ -19,7 +20,9 @@ NSMenu *_Nullable buildEditMenuForSelection(NSAttributedString *attributedText,
|
|
|
19
20
|
return menu;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
// Link spacers only reserve layout space; keep them out of every copied flavor.
|
|
24
|
+
NSAttributedString *selectedText =
|
|
25
|
+
ENRMAttributedStringByRemovingLinkSpacers([attributedText attributedSubstringFromRange:range]);
|
|
23
26
|
NSString *markdown = markdownForRange(attributedText, range, cachedMarkdown);
|
|
24
27
|
NSArray<NSString *> *imageURLs = imageURLsInRange(attributedText, range);
|
|
25
28
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "EditMenuUtils.h"
|
|
2
|
+
#import "ENRMLinkChip.h"
|
|
2
3
|
#import "PasteboardUtils.h"
|
|
3
4
|
#import "StyleConfig.h"
|
|
4
5
|
#include <TargetConditionals.h>
|
|
@@ -121,7 +122,9 @@ UIMenu *buildEditMenuForSelection(NSAttributedString *attributedText, NSRange ra
|
|
|
121
122
|
ENRMSelectionMenuConfig selectionMenuConfig,
|
|
122
123
|
ENRMCopyRequestHandler _Nullable onCopyRequest) API_AVAILABLE(ios(16.0))
|
|
123
124
|
{
|
|
124
|
-
|
|
125
|
+
// Link spacers only reserve layout space; keep them out of every copied flavor.
|
|
126
|
+
NSAttributedString *selectedText =
|
|
127
|
+
ENRMAttributedStringByRemovingLinkSpacers([attributedText attributedSubstringFromRange:range]);
|
|
125
128
|
NSString *markdown = markdownForRange(attributedText, range, cachedMarkdown);
|
|
126
129
|
NSArray<NSString *> *imageURLs = imageURLsInRange(attributedText, range);
|
|
127
130
|
// Same threshold markdownForRange uses to return the cached markdown.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#import "CodeBackground.h"
|
|
4
4
|
#import "ENRMFeatureFlags.h"
|
|
5
5
|
#import "ENRMImageAttachment.h"
|
|
6
|
+
#import "ENRMLinkChip.h"
|
|
6
7
|
#import "HighlightRenderer.h"
|
|
7
8
|
#if ENRICHED_MARKDOWN_MATH
|
|
8
9
|
#import "ENRMMathInlineAttachment.h"
|
|
@@ -460,7 +461,7 @@ static void generateInlineHTML(NSMutableString *html, NSAttributedString *attrib
|
|
|
460
461
|
usingBlock:^(NSDictionary<NSAttributedStringKey, id> *attrs, NSRange attrRange, BOOL *stop) {
|
|
461
462
|
NSString *text = [string substringWithRange:attrRange];
|
|
462
463
|
|
|
463
|
-
if ([text isEqualToString:@"\n"])
|
|
464
|
+
if ([text isEqualToString:@"\n"] || attrs[ENRMLinkSpacerAttributeName])
|
|
464
465
|
return;
|
|
465
466
|
|
|
466
467
|
if ([text containsString:kObjectReplacementChar]) {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#import "AccessibilityInfo.h"
|
|
3
3
|
#import "BlockquoteBorder.h"
|
|
4
4
|
#import "ENRMAccessibilityLabels.h"
|
|
5
|
+
#import "ENRMLinkChip.h"
|
|
5
6
|
#include <TargetConditionals.h>
|
|
6
7
|
|
|
7
8
|
typedef NS_ENUM(NSInteger, ElementType) { ElementTypeText, ElementTypeLink, ElementTypeImage };
|
|
@@ -113,7 +114,9 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
BOOL isImg = item[@"altText"] != nil;
|
|
116
|
-
|
|
117
|
+
// Link chips pad their text with spacer characters; keep them out of the spoken label.
|
|
118
|
+
NSString *label = isImg ? item[@"altText"]
|
|
119
|
+
: ENRMPlainTextByRemovingLinkSpacers(textView.attributedText, itemRange);
|
|
117
120
|
[elements addObject:[self createElementForRange:itemRange
|
|
118
121
|
type:isImg ? ElementTypeImage : ElementTypeLink
|
|
119
122
|
text:label
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#import "BlockquoteBorder.h"
|
|
3
3
|
#import "ENRMFeatureFlags.h"
|
|
4
4
|
#import "ENRMImageAttachment.h"
|
|
5
|
+
#import "ENRMLinkChip.h"
|
|
5
6
|
#import "ENRMUIKit.h"
|
|
6
7
|
#import "HighlightRenderer.h"
|
|
7
8
|
#include <TargetConditionals.h>
|
|
@@ -152,7 +153,7 @@ NSString *_Nullable extractMarkdownFromAttributedString(NSAttributedString *attr
|
|
|
152
153
|
options:0
|
|
153
154
|
usingBlock:^(NSDictionary<NSAttributedStringKey, id> *attrs, NSRange attrRange, BOOL *stop) {
|
|
154
155
|
NSString *text = [[attributedText attributedSubstringFromRange:attrRange] string];
|
|
155
|
-
if (text.length == 0)
|
|
156
|
+
if (text.length == 0 || attrs[ENRMLinkSpacerAttributeName])
|
|
156
157
|
return;
|
|
157
158
|
|
|
158
159
|
// Images and Thematic Breaks
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import "RTFExportUtils.h"
|
|
2
2
|
#import "BlockquoteBorder.h"
|
|
3
3
|
#import "CodeBackground.h"
|
|
4
|
+
#import "ENRMLinkChip.h"
|
|
4
5
|
#import "LastElementUtils.h"
|
|
5
6
|
#import "ListItemRenderer.h"
|
|
6
7
|
#import "RenderContext.h"
|
|
@@ -288,6 +289,7 @@ NSAttributedString *prepareAttributedStringForRTFExport(NSAttributedString *attr
|
|
|
288
289
|
RCTUIColor *blockquoteBgColor = [styleConfig blockquoteBackgroundColor];
|
|
289
290
|
|
|
290
291
|
processThematicBreaks(prepared);
|
|
292
|
+
ENRMApplyLinkChipBackgroundsAsTextBackground(prepared);
|
|
291
293
|
processCodes(prepared, codeBgColor);
|
|
292
294
|
processCodeBlocks(prepared, codeBlockBgColor);
|
|
293
295
|
processBlockquotes(prepared, blockquoteBgColor);
|
|
@@ -523,6 +523,32 @@ BOOL applyMarkdownStyleToConfig(StyleConfig *config, const MarkdownStyle &newSty
|
|
|
523
523
|
changed = YES;
|
|
524
524
|
}
|
|
525
525
|
|
|
526
|
+
if (newStyle.link.borderRadius != oldStyle.link.borderRadius) {
|
|
527
|
+
[config setLinkBorderRadius:newStyle.link.borderRadius];
|
|
528
|
+
changed = YES;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (newStyle.link.paddingHorizontal != oldStyle.link.paddingHorizontal) {
|
|
532
|
+
[config setLinkPaddingHorizontal:newStyle.link.paddingHorizontal];
|
|
533
|
+
changed = YES;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (newStyle.link.paddingVertical != oldStyle.link.paddingVertical) {
|
|
537
|
+
[config setLinkPaddingVertical:newStyle.link.paddingVertical];
|
|
538
|
+
changed = YES;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (newStyle.link.borderColor != oldStyle.link.borderColor) {
|
|
542
|
+
RCTUIColor *color = RCTUIColorFromSharedColor(newStyle.link.borderColor);
|
|
543
|
+
[config setLinkBorderColor:CGColorGetAlpha(color.CGColor) > 0 ? color : nil];
|
|
544
|
+
changed = YES;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (newStyle.link.borderWidth != oldStyle.link.borderWidth) {
|
|
548
|
+
[config setLinkBorderWidth:newStyle.link.borderWidth];
|
|
549
|
+
changed = YES;
|
|
550
|
+
}
|
|
551
|
+
|
|
526
552
|
{
|
|
527
553
|
BOOL linkVariantsChanged = newStyle.linkVariants.size() != oldStyle.linkVariants.size();
|
|
528
554
|
if (!linkVariantsChanged) {
|
|
@@ -530,7 +556,11 @@ BOOL applyMarkdownStyleToConfig(StyleConfig *config, const MarkdownStyle &newSty
|
|
|
530
556
|
const auto &newVariant = newStyle.linkVariants[i];
|
|
531
557
|
const auto &oldVariant = oldStyle.linkVariants[i];
|
|
532
558
|
if (newVariant.pattern != oldVariant.pattern || newVariant.color != oldVariant.color ||
|
|
533
|
-
newVariant.underline != oldVariant.underline || newVariant.backgroundColor != oldVariant.backgroundColor
|
|
559
|
+
newVariant.underline != oldVariant.underline || newVariant.backgroundColor != oldVariant.backgroundColor ||
|
|
560
|
+
newVariant.borderRadius != oldVariant.borderRadius ||
|
|
561
|
+
newVariant.paddingHorizontal != oldVariant.paddingHorizontal ||
|
|
562
|
+
newVariant.paddingVertical != oldVariant.paddingVertical ||
|
|
563
|
+
newVariant.borderColor != oldVariant.borderColor || newVariant.borderWidth != oldVariant.borderWidth) {
|
|
534
564
|
linkVariantsChanged = YES;
|
|
535
565
|
break;
|
|
536
566
|
}
|
|
@@ -545,6 +575,12 @@ BOOL applyMarkdownStyleToConfig(StyleConfig *config, const MarkdownStyle &newSty
|
|
|
545
575
|
variant.underline = entry.underline;
|
|
546
576
|
RCTUIColor *backgroundColor = RCTUIColorFromSharedColor(entry.backgroundColor);
|
|
547
577
|
variant.backgroundColor = CGColorGetAlpha(backgroundColor.CGColor) > 0 ? backgroundColor : nil;
|
|
578
|
+
variant.borderRadius = entry.borderRadius;
|
|
579
|
+
variant.paddingHorizontal = entry.paddingHorizontal;
|
|
580
|
+
variant.paddingVertical = entry.paddingVertical;
|
|
581
|
+
RCTUIColor *borderColor = RCTUIColorFromSharedColor(entry.borderColor);
|
|
582
|
+
variant.borderColor = CGColorGetAlpha(borderColor.CGColor) > 0 ? borderColor : nil;
|
|
583
|
+
variant.borderWidth = entry.borderWidth;
|
|
548
584
|
[variants addObject:variant];
|
|
549
585
|
}
|
|
550
586
|
[config setLinkVariants:variants];
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#import "BlockquoteBorder.h"
|
|
3
3
|
#import "CodeBackground.h"
|
|
4
4
|
#import "CodeBlockBackground.h"
|
|
5
|
+
#import "ENRMLinkChip.h"
|
|
5
6
|
#import "ListMarkerDrawer.h"
|
|
6
7
|
#import "RuntimeKeys.h"
|
|
7
8
|
#import "StyleConfig.h"
|
|
@@ -31,6 +32,8 @@
|
|
|
31
32
|
// We fetch the objects into local variables FIRST to ensure they don't
|
|
32
33
|
// disappear mid-method if setConfig: is called on another thread.
|
|
33
34
|
|
|
35
|
+
ENRMDrawLinkChipsForGlyphRange(self, textContainer, glyphsToShow, origin);
|
|
36
|
+
|
|
34
37
|
CodeBackground *codeBg = [self getCodeBackgroundWithConfig:config];
|
|
35
38
|
[codeBg drawBackgroundsForGlyphRange:glyphsToShow layoutManager:self textContainer:textContainer atPoint:origin];
|
|
36
39
|
|
|
@@ -65,6 +65,9 @@ typedef void (^TableLinkPressBlock)(NSString *url);
|
|
|
65
65
|
@property (nonatomic, copy, nullable) ENRMBlockCopyRequestBlock onCopyRequest;
|
|
66
66
|
|
|
67
67
|
@property (nonatomic, readonly) NSUInteger rowCount;
|
|
68
|
+
/// Number of links across all cells. Tables are not reported by `onLinkLayout`,
|
|
69
|
+
/// but their links still count so later link indices stay in document order.
|
|
70
|
+
@property (nonatomic, readonly) NSInteger linkCount;
|
|
68
71
|
|
|
69
72
|
- (void)animateNewRowsFromPreviousCount:(NSUInteger)previousRowCount duration:(NSTimeInterval)duration;
|
|
70
73
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "TableContainerView.h"
|
|
2
|
+
#import "ENRMLinkChip.h"
|
|
2
3
|
#import "AttributedRenderer.h"
|
|
3
4
|
#import "ENRMAccessibilityLabels.h"
|
|
4
5
|
#import "HTMLGenerator.h"
|
|
@@ -90,6 +91,8 @@ static NSMutableAttributedString *ENRMTableRenderCellNode(MarkdownASTNode *cellN
|
|
|
90
91
|
NSMutableAttributedString *attributedText = [renderer renderRoot:temporaryRoot context:context];
|
|
91
92
|
|
|
92
93
|
[context applyLinkAttributesToString:attributedText];
|
|
94
|
+
// Cells draw with -drawWithRect:, which bypasses the layout manager that paints link chips.
|
|
95
|
+
ENRMApplyLinkChipBackgroundsAsTextBackground(attributedText);
|
|
93
96
|
|
|
94
97
|
ENRMApplyWritingDirectionMode(attributedText, writingDirectionMode, resolvedLayoutDirection);
|
|
95
98
|
|
|
@@ -302,6 +305,24 @@ static void ENRMTableComputeLayout(NSArray<NSArray<TableCellData *> *> *rows, NS
|
|
|
302
305
|
return _rows.count;
|
|
303
306
|
}
|
|
304
307
|
|
|
308
|
+
- (NSInteger)linkCount
|
|
309
|
+
{
|
|
310
|
+
__block NSInteger count = 0;
|
|
311
|
+
for (NSArray<TableCellData *> *row in _rows) {
|
|
312
|
+
for (TableCellData *cell in row) {
|
|
313
|
+
// LinkRenderer attaches one ENRMLinkChip instance per link.
|
|
314
|
+
[cell.attributedText enumerateAttribute:ENRMLinkChipAttributeName
|
|
315
|
+
inRange:NSMakeRange(0, cell.attributedText.length)
|
|
316
|
+
options:0
|
|
317
|
+
usingBlock:^(id chip, NSRange range, BOOL *stop) {
|
|
318
|
+
if (chip)
|
|
319
|
+
count++;
|
|
320
|
+
}];
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return count;
|
|
324
|
+
}
|
|
325
|
+
|
|
305
326
|
#if !TARGET_OS_OSX
|
|
306
327
|
- (void)animateNewRowsFromPreviousCount:(NSUInteger)previousRowCount duration:(NSTimeInterval)duration
|
|
307
328
|
{
|
|
@@ -75,6 +75,11 @@ interface LinkStyleInternal {
|
|
|
75
75
|
color: ColorValue;
|
|
76
76
|
underline: boolean;
|
|
77
77
|
backgroundColor: ColorValue;
|
|
78
|
+
borderRadius: CodegenTypes.Float;
|
|
79
|
+
paddingHorizontal: CodegenTypes.Float;
|
|
80
|
+
paddingVertical: CodegenTypes.Float;
|
|
81
|
+
borderColor: ColorValue;
|
|
82
|
+
borderWidth: CodegenTypes.Float;
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
// Mirrors EnrichedMarkdownTextNativeComponent.ts — kept in sync manually (codegen spec files must be self-contained).
|
|
@@ -83,6 +88,11 @@ interface LinkVariantEntryInternal {
|
|
|
83
88
|
color: ColorValue;
|
|
84
89
|
underline: boolean;
|
|
85
90
|
backgroundColor: ColorValue;
|
|
91
|
+
borderRadius: CodegenTypes.Float;
|
|
92
|
+
paddingHorizontal: CodegenTypes.Float;
|
|
93
|
+
paddingVertical: CodegenTypes.Float;
|
|
94
|
+
borderColor: ColorValue;
|
|
95
|
+
borderWidth: CodegenTypes.Float;
|
|
86
96
|
}
|
|
87
97
|
|
|
88
98
|
interface StrongStyleInternal {
|
|
@@ -245,6 +255,25 @@ export interface LinkLongPressEvent {
|
|
|
245
255
|
url: string;
|
|
246
256
|
}
|
|
247
257
|
|
|
258
|
+
/**
|
|
259
|
+
* `fragments` holds one entry per laid-out line of a link (a wrapping link
|
|
260
|
+
* yields several). Rects are in dp, relative to the native view's origin, and
|
|
261
|
+
* cover the drawn chip (glyphs + padding). Flattened rather than nested per
|
|
262
|
+
* link, and written inline, because codegen only accepts inline object
|
|
263
|
+
* literals as event array elements.
|
|
264
|
+
*/
|
|
265
|
+
export interface LinkLayoutEvent {
|
|
266
|
+
fragments: {
|
|
267
|
+
linkIndex: CodegenTypes.Int32;
|
|
268
|
+
url: string;
|
|
269
|
+
text: string;
|
|
270
|
+
x: CodegenTypes.Double;
|
|
271
|
+
y: CodegenTypes.Double;
|
|
272
|
+
width: CodegenTypes.Double;
|
|
273
|
+
height: CodegenTypes.Double;
|
|
274
|
+
}[];
|
|
275
|
+
}
|
|
276
|
+
|
|
248
277
|
export interface TaskListItemPressEvent {
|
|
249
278
|
index: CodegenTypes.Int32;
|
|
250
279
|
checked: boolean;
|
|
@@ -400,6 +429,18 @@ export interface NativeProps extends ViewProps {
|
|
|
400
429
|
* - Android: Handles long press gestures on links.
|
|
401
430
|
*/
|
|
402
431
|
onLinkLongPress?: CodegenTypes.BubblingEventHandler<LinkLongPressEvent>;
|
|
432
|
+
/**
|
|
433
|
+
* When true, the view reports the laid-out rects of every link through
|
|
434
|
+
* `onLinkLayout` (after each render and whenever its size changes).
|
|
435
|
+
* Set by the JS wrapper only when `renderLinkDecoration` is provided.
|
|
436
|
+
* @default false
|
|
437
|
+
*/
|
|
438
|
+
emitLinkLayout?: CodegenTypes.WithDefault<boolean, false>;
|
|
439
|
+
/**
|
|
440
|
+
* Fired with the rects of every link fragment while `emitLinkLayout` is on.
|
|
441
|
+
* Deduplicated: not re-fired when the payload is unchanged.
|
|
442
|
+
*/
|
|
443
|
+
onLinkLayout?: CodegenTypes.DirectEventHandler<LinkLayoutEvent>;
|
|
403
444
|
/**
|
|
404
445
|
* Callback fired when a task list checkbox is tapped.
|
|
405
446
|
* Receives the 0-based task index, current checked state, and the item's plain text.
|