react-native-enriched-markdown-scaffold 0.6.0-scaffold.8 → 0.7.4-scaffold.10
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/ReactNativeEnrichedMarkdown.podspec +62 -11
- package/android/build.gradle +5 -0
- 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/EnrichedMarkdownTextInputManagerDelegate.java +12 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +4 -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/Props.cpp +25 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +793 -0
- package/android/src/main/baseline-prof.txt +75 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +62 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +10 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +9 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +6 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/MarkdownAccessibilityHelper.kt +44 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +72 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +110 -12
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockSyntaxSentinel.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +84 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputRemend.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputLayoutManager.kt +30 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +13 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +54 -13
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +4 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/HeadingSpan.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LineHeightSpan.kt +27 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +5 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathFontWeight.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +12 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +37 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/SpannableExtensions.kt +12 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkEvents.kt +22 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +36 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +74 -4
- package/android/src/main/jni/CMakeLists.txt +15 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +2 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlinePlaceholderSpan.kt +7 -3
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +8 -5
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathTypeface.kt +30 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +27 -3
- package/app.plugin.js +2 -1
- package/cpp/parser/MD4CParser.cpp +1 -1
- package/cpp/wasm/build.sh +9 -9
- package/docs/ACCESSIBILITY.md +172 -0
- package/docs/API_REFERENCE.md +957 -0
- package/docs/COPY_OPTIONS.md +127 -0
- package/docs/ELEMENTS_STRUCTURE.md +112 -0
- package/docs/IMAGE_CACHING.md +25 -0
- package/docs/INPUT.md +281 -0
- package/docs/LATEX_MATH.md +198 -0
- package/docs/MACOS.md +19 -0
- package/docs/MARKDOWN_STREAMING.md +36 -0
- package/docs/MENTIONS.md +97 -0
- package/docs/RTL.md +82 -0
- package/docs/STYLES.md +522 -0
- package/docs/TEXT.md +110 -0
- package/docs/WEB.md +49 -0
- package/ios/EnrichedMarkdown.mm +126 -37
- package/ios/EnrichedMarkdownText.mm +84 -16
- package/ios/attachments/ENRMMathInlineAttachment+macOS.m +5 -1
- package/ios/attachments/ENRMMathInlineAttachment.h +3 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +2 -1
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +25 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +793 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +15 -0
- package/ios/input/ENRMBlockSyntaxSentinel.h +25 -0
- package/ios/input/ENRMBlockSyntaxSentinel.mm +80 -0
- package/ios/input/ENRMFormattingStore.h +5 -0
- package/ios/input/ENRMFormattingStore.mm +34 -0
- package/ios/input/ENRMInputFormatter.h +4 -0
- package/ios/input/ENRMInputFormatter.mm +2 -0
- package/ios/input/ENRMInputParser.h +5 -0
- package/ios/input/ENRMInputParser.mm +79 -6
- package/ios/input/ENRMInputTextView.h +2 -0
- package/ios/input/ENRMInputTextView.mm +8 -17
- package/ios/input/ENRMMarkdownSerializer.mm +1 -1
- package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +71 -53
- package/ios/input/EnrichedMarkdownTextInput+Internal.h +26 -0
- package/ios/input/EnrichedMarkdownTextInput.h +1 -0
- package/ios/input/EnrichedMarkdownTextInput.mm +249 -31
- package/ios/input/InputStylePropsUtils.h +13 -0
- package/ios/input/styles/ENRMBoldStyleHandler.mm +3 -2
- package/ios/input/styles/ENRMItalicStyleHandler.mm +3 -2
- package/ios/internals/MeasurementCache.h +1 -0
- package/ios/math/ENRMRaTeXBridge.swift +52 -3
- package/ios/parser/ENRMMarkdownParser.h +8 -0
- package/ios/parser/ENRMMarkdownParser.mm +11 -0
- package/ios/renderer/AttributedRenderer.m +51 -6
- package/ios/renderer/ENRMMathInlineRenderer.m +8 -1
- package/ios/renderer/ListItemRenderer.m +8 -5
- package/ios/styles/ENRMFontSlot.h +1 -1
- package/ios/styles/StyleConfig.h +6 -0
- package/ios/styles/StyleConfig.mm +36 -0
- package/ios/utils/ENRMAccessibilityLabels.h +36 -0
- package/ios/utils/ENRMAccessibilityLabels.m +5 -0
- package/ios/utils/ENRMMathFontWeight.h +18 -0
- package/ios/utils/EditMenuUtils+macOS.m +4 -5
- package/ios/utils/EditMenuUtils.h +70 -0
- package/ios/utils/EditMenuUtils.m +14 -11
- package/ios/utils/LastElementUtils.h +39 -2
- package/ios/utils/MarkdownAccessibilityElementBuilder.h +18 -16
- package/ios/utils/MarkdownAccessibilityElementBuilder.m +64 -32
- package/ios/utils/ParagraphStyleUtils.m +21 -2
- package/ios/utils/StylePropsUtils.h +21 -0
- package/ios/views/ENRMMathContainerView.h +8 -0
- package/ios/views/ENRMMathContainerView.m +10 -6
- package/ios/views/ENRMTableIOSGridView.h +40 -0
- package/ios/views/ENRMTableIOSGridView.m +216 -0
- package/ios/views/EnrichedMarkdownInternalText.h +2 -0
- package/ios/views/EnrichedMarkdownInternalText.m +2 -0
- package/ios/views/TableContainerView.h +8 -0
- package/ios/views/TableContainerView.m +72 -128
- package/lib/module/EnrichedMarkdownNativeComponent.ts +40 -0
- package/lib/module/EnrichedMarkdownTextInput.js +50 -1
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +47 -0
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +40 -0
- package/lib/module/accessibilityLabelDefaults.js +64 -0
- package/lib/module/accessibilityLabelDefaults.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/EnrichedMarkdownText.js +72 -4
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +5 -2
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +5 -2
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/normalizeMarkdownTextInputStyle.js +7 -3
- package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
- package/lib/module/normalizeMenuItem.js +38 -0
- package/lib/module/normalizeMenuItem.js.map +1 -0
- package/lib/module/types/AccessibilityLabels.js +2 -0
- package/lib/module/types/AccessibilityLabels.js.map +1 -0
- package/lib/module/web/globalStyles.js +8 -1
- package/lib/module/web/globalStyles.js.map +1 -1
- package/lib/module/web/styles.js +3 -1
- package/lib/module/web/styles.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +37 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +57 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +42 -0
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +37 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/accessibilityLabelDefaults.d.ts +16 -0
- package/lib/typescript/src/accessibilityLabelDefaults.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -2
- package/lib/typescript/src/index.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/normalizeMarkdownTextInputStyle.d.ts +1 -0
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMenuItem.d.ts +7 -0
- package/lib/typescript/src/normalizeMenuItem.d.ts.map +1 -0
- package/lib/typescript/src/types/AccessibilityLabels.d.ts +114 -0
- package/lib/typescript/src/types/AccessibilityLabels.d.ts.map +1 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts +32 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +3 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +78 -9
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/package.json +4 -2
- package/plugin/build/withAndroidMath.js +19 -0
- package/plugin/build/withIosMath.js +28 -0
- package/plugin/build/withReactNativeEnrichedMarkdown.js +11 -0
- package/plugin/tsconfig.build.json +16 -0
- package/src/EnrichedMarkdownNativeComponent.ts +40 -0
- package/src/EnrichedMarkdownTextInput.tsx +121 -1
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +47 -0
- package/src/EnrichedMarkdownTextNativeComponent.ts +40 -0
- package/src/accessibilityLabelDefaults.ts +83 -0
- package/src/index.tsx +11 -0
- package/src/native/EnrichedMarkdownText.tsx +120 -6
- package/src/normalizeMarkdownStyle.ts +6 -1
- package/src/normalizeMarkdownStyle.web.ts +6 -1
- package/src/normalizeMarkdownTextInputStyle.ts +5 -0
- package/src/normalizeMenuItem.ts +52 -0
- package/src/types/AccessibilityLabels.ts +118 -0
- package/src/types/MarkdownStyle.ts +32 -0
- package/src/types/MarkdownStyleInternal.ts +3 -0
- package/src/types/MarkdownTextProps.ts +74 -9
- package/src/web/globalStyles.ts +7 -0
- package/src/web/styles.ts +5 -1
- package/lib/module/plugin/withAndroidMath.js +0 -20
- package/lib/module/plugin/withAndroidMath.js.map +0 -1
- package/lib/module/plugin/withIosMath.js +0 -23
- package/lib/module/plugin/withIosMath.js.map +0 -1
- package/lib/module/plugin/withReactNativeEnrichedMarkdown.js +0 -16
- package/lib/module/plugin/withReactNativeEnrichedMarkdown.js.map +0 -1
- package/lib/typescript/src/plugin/withAndroidMath.d.ts +0 -5
- package/lib/typescript/src/plugin/withAndroidMath.d.ts.map +0 -1
- package/lib/typescript/src/plugin/withIosMath.d.ts +0 -5
- package/lib/typescript/src/plugin/withIosMath.d.ts.map +0 -1
- package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts +0 -6
- package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts.map +0 -1
- /package/{src/plugin → plugin/src}/withAndroidMath.ts +0 -0
- /package/{src/plugin → plugin/src}/withIosMath.ts +0 -0
- /package/{src/plugin → plugin/src}/withReactNativeEnrichedMarkdown.ts +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#import "MarkdownAccessibilityElementBuilder.h"
|
|
2
2
|
#import "AccessibilityInfo.h"
|
|
3
|
+
#import "BlockquoteBorder.h"
|
|
4
|
+
#import "ENRMAccessibilityLabels.h"
|
|
3
5
|
#include <TargetConditionals.h>
|
|
4
6
|
|
|
5
7
|
typedef NS_ENUM(NSInteger, ElementType) { ElementTypeText, ElementTypeLink, ElementTypeImage };
|
|
@@ -14,6 +16,7 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
14
16
|
|
|
15
17
|
+ (NSMutableArray<UIAccessibilityElement *> *)buildElementsForTextView:(UITextView *)textView
|
|
16
18
|
info:(AccessibilityInfo *)info
|
|
19
|
+
labels:(ENRMAccessibilityLabels *)labels
|
|
17
20
|
container:(id)container
|
|
18
21
|
{
|
|
19
22
|
NSString *fullString = textView.attributedText.string;
|
|
@@ -45,6 +48,7 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
45
48
|
isLinked:NO
|
|
46
49
|
heading:level
|
|
47
50
|
listInfo:list
|
|
51
|
+
labels:labels
|
|
48
52
|
view:textView
|
|
49
53
|
container:container]];
|
|
50
54
|
} else {
|
|
@@ -53,6 +57,7 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
53
57
|
headingLevel:level
|
|
54
58
|
listInfo:list
|
|
55
59
|
specials:specials
|
|
60
|
+
labels:labels
|
|
56
61
|
inTextView:textView
|
|
57
62
|
container:container]];
|
|
58
63
|
}
|
|
@@ -77,6 +82,7 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
77
82
|
headingLevel:(NSInteger)headingLevel
|
|
78
83
|
listInfo:(NSDictionary *)listInfo
|
|
79
84
|
specials:(NSArray *)specials
|
|
85
|
+
labels:(ENRMAccessibilityLabels *)labels
|
|
80
86
|
inTextView:(UITextView *)textView
|
|
81
87
|
container:(id)container
|
|
82
88
|
{
|
|
@@ -100,6 +106,7 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
100
106
|
isLinked:NO
|
|
101
107
|
heading:headingLevel
|
|
102
108
|
listInfo:listInfo
|
|
109
|
+
labels:labels
|
|
103
110
|
view:textView
|
|
104
111
|
container:container]];
|
|
105
112
|
}
|
|
@@ -113,6 +120,7 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
113
120
|
isLinked:isImg ? [item[@"isLinked"] boolValue] : YES
|
|
114
121
|
heading:0
|
|
115
122
|
listInfo:listInfo
|
|
123
|
+
labels:labels
|
|
116
124
|
view:textView
|
|
117
125
|
container:container]];
|
|
118
126
|
segmentStart = NSMaxRange(itemRange);
|
|
@@ -129,6 +137,7 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
129
137
|
isLinked:NO
|
|
130
138
|
heading:headingLevel
|
|
131
139
|
listInfo:listInfo
|
|
140
|
+
labels:labels
|
|
132
141
|
view:textView
|
|
133
142
|
container:container]];
|
|
134
143
|
}
|
|
@@ -144,11 +153,13 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
144
153
|
isLinked:(BOOL)linked
|
|
145
154
|
heading:(NSInteger)level
|
|
146
155
|
listInfo:(NSDictionary *)listInfo
|
|
156
|
+
labels:(ENRMAccessibilityLabels *)labels
|
|
147
157
|
view:(UITextView *)textView
|
|
148
158
|
container:(id)container
|
|
149
159
|
{
|
|
150
160
|
UIAccessibilityElement *element = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:container];
|
|
151
|
-
|
|
161
|
+
if (text.length > 0)
|
|
162
|
+
element.accessibilityLabel = text;
|
|
152
163
|
|
|
153
164
|
UIBezierPath *path = [self accessibilityPathForRange:range inTextView:textView];
|
|
154
165
|
if (path) {
|
|
@@ -157,41 +168,58 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
157
168
|
element.accessibilityFrameInContainerSpace = [self frameForRange:range inTextView:textView container:container];
|
|
158
169
|
}
|
|
159
170
|
|
|
160
|
-
NSMutableArray *values = [NSMutableArray array];
|
|
161
|
-
|
|
162
171
|
if (type == ElementTypeImage) {
|
|
163
172
|
element.accessibilityTraits =
|
|
164
173
|
linked ? (UIAccessibilityTraitImage | UIAccessibilityTraitLink) : UIAccessibilityTraitImage;
|
|
174
|
+
|
|
165
175
|
} else if (type == ElementTypeLink) {
|
|
166
176
|
element.accessibilityTraits = UIAccessibilityTraitLink;
|
|
167
177
|
} else if (level > 0) {
|
|
168
178
|
element.accessibilityTraits = UIAccessibilityTraitHeader;
|
|
169
|
-
[values addObject:[NSString stringWithFormat:NSLocalizedString(@"heading level %ld", @""), (long)level]];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (element.accessibilityTraits & UIAccessibilityTraitLink) {
|
|
173
|
-
element.accessibilityHint = NSLocalizedString(@"Tap to open link", @"");
|
|
174
179
|
}
|
|
175
180
|
|
|
181
|
+
NSMutableArray<NSString *> *valueParts = [NSMutableArray array];
|
|
176
182
|
if (listInfo && type != ElementTypeImage) {
|
|
177
|
-
[
|
|
183
|
+
[valueParts addObject:[self formatListAnnouncement:listInfo labels:labels]];
|
|
178
184
|
}
|
|
179
|
-
|
|
180
|
-
if (
|
|
181
|
-
|
|
185
|
+
NSString *blockquoteAnnouncement = [self blockquoteAnnouncementForRange:range textView:textView labels:labels];
|
|
186
|
+
if (blockquoteAnnouncement) {
|
|
187
|
+
[valueParts addObject:blockquoteAnnouncement];
|
|
188
|
+
}
|
|
189
|
+
if (valueParts.count > 0) {
|
|
190
|
+
element.accessibilityValue = [valueParts componentsJoinedByString:@", "];
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
return element;
|
|
185
194
|
}
|
|
186
195
|
|
|
196
|
+
+ (NSString *)blockquoteAnnouncementForRange:(NSRange)range
|
|
197
|
+
textView:(UITextView *)textView
|
|
198
|
+
labels:(ENRMAccessibilityLabels *)labels
|
|
199
|
+
{
|
|
200
|
+
if (textView.attributedText.length == 0 || range.location >= textView.attributedText.length)
|
|
201
|
+
return nil;
|
|
202
|
+
NSRange effective;
|
|
203
|
+
NSNumber *depth = [textView.attributedText attribute:BlockquoteDepthAttributeName
|
|
204
|
+
atIndex:range.location
|
|
205
|
+
effectiveRange:&effective];
|
|
206
|
+
if (depth == nil)
|
|
207
|
+
return nil;
|
|
208
|
+
return depth.integerValue >= 1 ? labels.nestedBlockquote : labels.blockquote;
|
|
209
|
+
}
|
|
210
|
+
|
|
187
211
|
#pragma mark - Helpers
|
|
188
212
|
|
|
189
|
-
+ (NSString *)formatListAnnouncement:(NSDictionary *)info
|
|
213
|
+
+ (NSString *)formatListAnnouncement:(NSDictionary *)info labels:(ENRMAccessibilityLabels *)labels
|
|
190
214
|
{
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
215
|
+
BOOL nested = [info[@"depth"] integerValue] > 1;
|
|
216
|
+
if ([info[@"isOrdered"] boolValue]) {
|
|
217
|
+
long position = (long)[info[@"position"] integerValue];
|
|
218
|
+
NSString *template = nested ? labels.nestedOrderedItem : labels.orderedItem;
|
|
219
|
+
return [template stringByReplacingOccurrencesOfString:@"{n}"
|
|
220
|
+
withString:[NSString stringWithFormat:@"%ld", position]];
|
|
221
|
+
}
|
|
222
|
+
return nested ? labels.nestedBulletPoint : labels.bulletPoint;
|
|
195
223
|
}
|
|
196
224
|
|
|
197
225
|
+ (NSRange)clampedRange:(NSRange)range forText:(NSString *)text
|
|
@@ -370,36 +398,37 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
370
398
|
{
|
|
371
399
|
return [self filterElements:elements withTrait:UIAccessibilityTraitImage];
|
|
372
400
|
}
|
|
373
|
-
+ (UIAccessibilityCustomRotor *)createHeadingRotorWithElements:(NSArray *)elements
|
|
401
|
+
+ (UIAccessibilityCustomRotor *)createHeadingRotorWithElements:(NSArray *)elements name:(NSString *)name
|
|
374
402
|
{
|
|
375
|
-
return [self createRotorWithName:
|
|
403
|
+
return [self createRotorWithName:name elements:elements];
|
|
376
404
|
}
|
|
377
|
-
+ (UIAccessibilityCustomRotor *)createLinkRotorWithElements:(NSArray *)elements
|
|
405
|
+
+ (UIAccessibilityCustomRotor *)createLinkRotorWithElements:(NSArray *)elements name:(NSString *)name
|
|
378
406
|
{
|
|
379
|
-
return [self createRotorWithName:
|
|
407
|
+
return [self createRotorWithName:name elements:elements];
|
|
380
408
|
}
|
|
381
|
-
+ (UIAccessibilityCustomRotor *)createImageRotorWithElements:(NSArray *)elements
|
|
409
|
+
+ (UIAccessibilityCustomRotor *)createImageRotorWithElements:(NSArray *)elements name:(NSString *)name
|
|
382
410
|
{
|
|
383
|
-
return [self createRotorWithName:
|
|
411
|
+
return [self createRotorWithName:name elements:elements];
|
|
384
412
|
}
|
|
385
413
|
|
|
386
414
|
+ (NSArray<UIAccessibilityCustomRotor *> *)buildRotorsFromElements:(NSArray<UIAccessibilityElement *> *)elements
|
|
415
|
+
labels:(ENRMAccessibilityLabels *)labels
|
|
387
416
|
{
|
|
388
417
|
NSMutableArray<UIAccessibilityCustomRotor *> *rotors = [NSMutableArray array];
|
|
389
418
|
|
|
390
419
|
NSArray<UIAccessibilityElement *> *headingElements = [self filterHeadingElements:elements];
|
|
391
420
|
if (headingElements.count > 0) {
|
|
392
|
-
[rotors addObject:[self createHeadingRotorWithElements:headingElements]];
|
|
421
|
+
[rotors addObject:[self createHeadingRotorWithElements:headingElements name:labels.rotorHeadings]];
|
|
393
422
|
}
|
|
394
423
|
|
|
395
424
|
NSArray<UIAccessibilityElement *> *linkElements = [self filterLinkElements:elements];
|
|
396
425
|
if (linkElements.count > 0) {
|
|
397
|
-
[rotors addObject:[self createLinkRotorWithElements:linkElements]];
|
|
426
|
+
[rotors addObject:[self createLinkRotorWithElements:linkElements name:labels.rotorLinks]];
|
|
398
427
|
}
|
|
399
428
|
|
|
400
429
|
NSArray<UIAccessibilityElement *> *imageElements = [self filterImageElements:elements];
|
|
401
430
|
if (imageElements.count > 0) {
|
|
402
|
-
[rotors addObject:[self createImageRotorWithElements:imageElements]];
|
|
431
|
+
[rotors addObject:[self createImageRotorWithElements:imageElements name:labels.rotorImages]];
|
|
403
432
|
}
|
|
404
433
|
|
|
405
434
|
return rotors;
|
|
@@ -412,7 +441,10 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
412
441
|
// attributes, and exposing them via NSAccessibilityElement so VoiceOver can navigate the
|
|
413
442
|
// rendered markdown content. The iOS implementation above can serve as a reference.
|
|
414
443
|
|
|
415
|
-
+ (NSMutableArray *)buildElementsForTextView:(id)textView
|
|
444
|
+
+ (NSMutableArray *)buildElementsForTextView:(id)textView
|
|
445
|
+
info:(AccessibilityInfo *)info
|
|
446
|
+
labels:(ENRMAccessibilityLabels *)labels
|
|
447
|
+
container:(id)container
|
|
416
448
|
{
|
|
417
449
|
return [NSMutableArray array];
|
|
418
450
|
}
|
|
@@ -428,23 +460,23 @@ static const CGFloat kFocusRectPadding = 2.0;
|
|
|
428
460
|
{
|
|
429
461
|
return @[];
|
|
430
462
|
}
|
|
431
|
-
+ (id)createHeadingRotorWithElements:(NSArray *)elements
|
|
463
|
+
+ (id)createHeadingRotorWithElements:(NSArray *)elements name:(NSString *)name
|
|
432
464
|
{
|
|
433
465
|
return nil;
|
|
434
466
|
}
|
|
435
|
-
+ (id)createLinkRotorWithElements:(NSArray *)elements
|
|
467
|
+
+ (id)createLinkRotorWithElements:(NSArray *)elements name:(NSString *)name
|
|
436
468
|
{
|
|
437
469
|
return nil;
|
|
438
470
|
}
|
|
439
|
-
+ (id)createImageRotorWithElements:(NSArray *)elements
|
|
471
|
+
+ (id)createImageRotorWithElements:(NSArray *)elements name:(NSString *)name
|
|
440
472
|
{
|
|
441
473
|
return nil;
|
|
442
474
|
}
|
|
443
|
-
+ (NSArray *)buildRotorsFromElements:(NSArray *)elements
|
|
475
|
+
+ (NSArray *)buildRotorsFromElements:(NSArray *)elements labels:(ENRMAccessibilityLabels *)labels
|
|
444
476
|
{
|
|
445
477
|
return @[];
|
|
446
478
|
}
|
|
447
479
|
|
|
448
480
|
#endif
|
|
449
481
|
|
|
450
|
-
@end
|
|
482
|
+
@end
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
#import "ParagraphStyleUtils.h"
|
|
2
|
+
#import "ENRMFeatureFlags.h"
|
|
2
3
|
#import "LastElementUtils.h"
|
|
3
4
|
#import <React/RCTI18nUtil.h>
|
|
4
5
|
|
|
6
|
+
#if ENRICHED_MARKDOWN_MATH
|
|
7
|
+
#import "ENRMMathInlineAttachment.h"
|
|
8
|
+
#endif
|
|
9
|
+
|
|
5
10
|
NSAttributedString *kNewlineAttributedString;
|
|
6
11
|
static NSParagraphStyle *kBlockSpacerTemplate;
|
|
7
12
|
|
|
@@ -247,10 +252,24 @@ void applyLineHeight(NSMutableAttributedString *output, NSRange range, CGFloat l
|
|
|
247
252
|
return;
|
|
248
253
|
}
|
|
249
254
|
|
|
255
|
+
__block BOOL hasMath = NO;
|
|
256
|
+
|
|
257
|
+
#if ENRICHED_MARKDOWN_MATH
|
|
258
|
+
[output enumerateAttribute:NSAttachmentAttributeName
|
|
259
|
+
inRange:range
|
|
260
|
+
options:0
|
|
261
|
+
usingBlock:^(id value, __unused NSRange attrRange, BOOL *stop) {
|
|
262
|
+
if ([value isKindOfClass:[ENRMMathInlineAttachment class]]) {
|
|
263
|
+
hasMath = YES;
|
|
264
|
+
*stop = YES;
|
|
265
|
+
}
|
|
266
|
+
}];
|
|
267
|
+
#endif
|
|
268
|
+
|
|
250
269
|
NSMutableParagraphStyle *style = getOrCreateParagraphStyle(output, range.location);
|
|
251
270
|
|
|
252
271
|
style.minimumLineHeight = lineHeight;
|
|
253
|
-
style.maximumLineHeight = lineHeight;
|
|
272
|
+
style.maximumLineHeight = hasMath ? 0 : lineHeight;
|
|
254
273
|
|
|
255
274
|
[output addAttribute:NSParagraphStyleAttributeName value:style range:range];
|
|
256
275
|
}
|
|
@@ -288,7 +307,7 @@ void applyBaselineOffset(NSMutableAttributedString *output, NSRange range)
|
|
|
288
307
|
if (!font) {
|
|
289
308
|
return;
|
|
290
309
|
}
|
|
291
|
-
maximumFontLineHeight = MAX(font
|
|
310
|
+
maximumFontLineHeight = MAX(UIFontLineHeight(font), maximumFontLineHeight);
|
|
292
311
|
}];
|
|
293
312
|
|
|
294
313
|
if (maximumFontLineHeight <= 0 || maximumLineHeight < maximumFontLineHeight) {
|
|
@@ -1078,6 +1078,14 @@ BOOL applyMarkdownStyleToConfig(StyleConfig *config, const MarkdownStyle &newSty
|
|
|
1078
1078
|
changed = YES;
|
|
1079
1079
|
}
|
|
1080
1080
|
|
|
1081
|
+
if (newStyle.math.fontWeight != oldStyle.math.fontWeight) {
|
|
1082
|
+
if (!newStyle.math.fontWeight.empty()) {
|
|
1083
|
+
NSString *fontWeight = [[NSString alloc] initWithUTF8String:newStyle.math.fontWeight.c_str()];
|
|
1084
|
+
[config setMathFontWeight:fontWeight];
|
|
1085
|
+
changed = YES;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1081
1089
|
if (newStyle.math.textAlign != oldStyle.math.textAlign) {
|
|
1082
1090
|
[config setMathTextAlign:@(newStyle.math.textAlign.c_str())];
|
|
1083
1091
|
changed = YES;
|
|
@@ -1095,6 +1103,19 @@ BOOL applyMarkdownStyleToConfig(StyleConfig *config, const MarkdownStyle &newSty
|
|
|
1095
1103
|
changed = YES;
|
|
1096
1104
|
}
|
|
1097
1105
|
|
|
1106
|
+
if (newStyle.inlineMath.fontWeight != oldStyle.inlineMath.fontWeight) {
|
|
1107
|
+
if (!newStyle.inlineMath.fontWeight.empty()) {
|
|
1108
|
+
NSString *fontWeight = [[NSString alloc] initWithUTF8String:newStyle.inlineMath.fontWeight.c_str()];
|
|
1109
|
+
[config setInlineMathFontWeight:fontWeight];
|
|
1110
|
+
changed = YES;
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
if (newStyle.inlineMath.paddingVertical != oldStyle.inlineMath.paddingVertical) {
|
|
1115
|
+
[config setInlineMathPaddingVertical:newStyle.inlineMath.paddingVertical];
|
|
1116
|
+
changed = YES;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1098
1119
|
// ── Spoiler ─────────────────────────────────────────────────────────────
|
|
1099
1120
|
|
|
1100
1121
|
if (newStyle.spoiler.color != oldStyle.spoiler.color) {
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
#import "ENRMUIKit.h"
|
|
3
3
|
#import "StyleConfig.h"
|
|
4
4
|
|
|
5
|
+
@class ENRMAccessibilityLabels;
|
|
6
|
+
|
|
5
7
|
NS_ASSUME_NONNULL_BEGIN
|
|
6
8
|
|
|
7
9
|
@interface ENRMMathContainerView : RCTUIView
|
|
@@ -14,6 +16,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
14
16
|
|
|
15
17
|
@property (nonatomic, strong) StyleConfig *config;
|
|
16
18
|
@property (nonatomic, copy, readonly) NSString *cachedLatex;
|
|
19
|
+
@property (nonatomic, strong, nullable) ENRMAccessibilityLabels *accessibilityLabels;
|
|
20
|
+
|
|
21
|
+
// Renamed getters avoid the Cocoa `copy` method family (which signals +1
|
|
22
|
+
// retained returns). Property names are unchanged so call sites stay the same.
|
|
23
|
+
@property (nonatomic, copy, nullable, getter=menuCopyLabel) NSString *copyLabel;
|
|
24
|
+
@property (nonatomic, copy, nullable, getter=menuCopyAsMarkdownLabel) NSString *copyAsMarkdownLabel;
|
|
17
25
|
|
|
18
26
|
@end
|
|
19
27
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#import "ENRMMathContainerView.h"
|
|
2
|
+
#import "ENRMAccessibilityLabels.h"
|
|
2
3
|
#import "ENRMFeatureFlags.h"
|
|
4
|
+
#import "ENRMMathFontWeight.h"
|
|
3
5
|
#include <TargetConditionals.h>
|
|
4
6
|
|
|
5
7
|
#if ENRICHED_MARKDOWN_MATH
|
|
@@ -93,7 +95,8 @@
|
|
|
93
95
|
ENRMRaTeXRenderResult *result = [ENRMRaTeXBridge parse:latex
|
|
94
96
|
displayMode:YES
|
|
95
97
|
fontSize:config.mathFontSize
|
|
96
|
-
color:config.mathColor
|
|
98
|
+
color:config.mathColor
|
|
99
|
+
bold:ENRMMathFontWeightIsBold(config.mathFontWeight)];
|
|
97
100
|
_mathView.renderResult = result;
|
|
98
101
|
|
|
99
102
|
CGFloat padding = config.mathPadding;
|
|
@@ -119,13 +122,13 @@
|
|
|
119
122
|
previewProvider:nil
|
|
120
123
|
actionProvider:^UIMenu *(NSArray<UIMenuElement *> *suggestedActions) {
|
|
121
124
|
UIAction *copyPlainText =
|
|
122
|
-
[UIAction actionWithTitle
|
|
125
|
+
[UIAction actionWithTitle:self.copyLabel
|
|
123
126
|
image:[RCTUIImage systemImageNamed:@"doc.on.doc"]
|
|
124
127
|
identifier:nil
|
|
125
128
|
handler:^(__kindof UIAction *action) { [self copyLatexToPasteboard]; }];
|
|
126
129
|
|
|
127
130
|
UIAction *copyMarkdown =
|
|
128
|
-
[UIAction actionWithTitle
|
|
131
|
+
[UIAction actionWithTitle:self.copyAsMarkdownLabel
|
|
129
132
|
image:[RCTUIImage systemImageNamed:@"doc.text"]
|
|
130
133
|
identifier:nil
|
|
131
134
|
handler:^(__kindof UIAction *action) { [self copyMarkdownToPasteboard]; }];
|
|
@@ -139,8 +142,8 @@
|
|
|
139
142
|
- (NSMenu *)menuForEvent:(NSEvent *)event
|
|
140
143
|
{
|
|
141
144
|
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
|
|
142
|
-
[menu addItem:ENRMCreateMenuItem(
|
|
143
|
-
[menu addItem:ENRMCreateMenuItem(
|
|
145
|
+
[menu addItem:ENRMCreateMenuItem(self.copyLabel, ^{ [self copyLatexToPasteboard]; })];
|
|
146
|
+
[menu addItem:ENRMCreateMenuItem(self.copyAsMarkdownLabel, ^{ [self copyMarkdownToPasteboard]; })];
|
|
144
147
|
return menu;
|
|
145
148
|
}
|
|
146
149
|
#endif
|
|
@@ -212,7 +215,8 @@
|
|
|
212
215
|
|
|
213
216
|
- (NSString *)accessibilityLabel
|
|
214
217
|
{
|
|
215
|
-
return [
|
|
218
|
+
return [_accessibilityLabels.mathEquation stringByReplacingOccurrencesOfString:@"{latex}"
|
|
219
|
+
withString:_cachedLatex ?: @""];
|
|
216
220
|
}
|
|
217
221
|
|
|
218
222
|
#if !TARGET_OS_OSX
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <TargetConditionals.h>
|
|
4
|
+
#if !TARGET_OS_OSX
|
|
5
|
+
|
|
6
|
+
#import <UIKit/UIKit.h>
|
|
7
|
+
|
|
8
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
9
|
+
|
|
10
|
+
typedef void (^ENRMTableIOSLinkBlock)(NSString *url);
|
|
11
|
+
|
|
12
|
+
@interface ENRMTableIOSRowData : NSObject
|
|
13
|
+
@property (nonatomic, strong) NSArray<NSAttributedString *> *cellTexts;
|
|
14
|
+
@property (nonatomic, strong) UIColor *backgroundColor;
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
/// Draws the entire table grid in a single drawRect: pass, avoiding
|
|
18
|
+
/// per-cell UITextView allocation and the TextKit layout storms that
|
|
19
|
+
/// cause multi-second main-thread hangs on large tables.
|
|
20
|
+
@interface ENRMTableIOSGridView : UIView
|
|
21
|
+
|
|
22
|
+
@property (nonatomic, copy, nullable) ENRMTableIOSLinkBlock onLinkTap;
|
|
23
|
+
@property (nonatomic, copy, nullable) ENRMTableIOSLinkBlock onLinkLongTap;
|
|
24
|
+
|
|
25
|
+
- (void)updateWithRows:(NSArray<ENRMTableIOSRowData *> *)rows
|
|
26
|
+
columnWidths:(NSArray<NSNumber *> *)columnWidths
|
|
27
|
+
rowHeights:(NSArray<NSNumber *> *)rowHeights
|
|
28
|
+
borderColor:(UIColor *)borderColor
|
|
29
|
+
borderWidth:(CGFloat)borderWidth
|
|
30
|
+
horizontalCellPadding:(CGFloat)horizontalCellPadding
|
|
31
|
+
verticalCellPadding:(CGFloat)verticalCellPadding
|
|
32
|
+
cornerRadius:(CGFloat)cornerRadius;
|
|
33
|
+
|
|
34
|
+
- (void)fadeInRowsFrom:(NSUInteger)startRow duration:(NSTimeInterval)duration;
|
|
35
|
+
|
|
36
|
+
@end
|
|
37
|
+
|
|
38
|
+
NS_ASSUME_NONNULL_END
|
|
39
|
+
|
|
40
|
+
#endif // !TARGET_OS_OSX
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#import "ENRMTableIOSGridView.h"
|
|
2
|
+
|
|
3
|
+
#if !TARGET_OS_OSX
|
|
4
|
+
|
|
5
|
+
@implementation ENRMTableIOSRowData
|
|
6
|
+
@end
|
|
7
|
+
|
|
8
|
+
@implementation ENRMTableIOSGridView {
|
|
9
|
+
NSArray<ENRMTableIOSRowData *> *_tableRows;
|
|
10
|
+
NSArray<NSNumber *> *_columnWidths;
|
|
11
|
+
NSArray<NSNumber *> *_rowHeights;
|
|
12
|
+
UIColor *_borderColor;
|
|
13
|
+
CGFloat _borderWidth;
|
|
14
|
+
CGFloat _horizontalCellPadding;
|
|
15
|
+
CGFloat _verticalCellPadding;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
19
|
+
{
|
|
20
|
+
self = [super initWithFrame:frame];
|
|
21
|
+
if (self) {
|
|
22
|
+
self.backgroundColor = [UIColor clearColor];
|
|
23
|
+
self.contentMode = UIViewContentModeRedraw;
|
|
24
|
+
self.opaque = NO;
|
|
25
|
+
self.accessibilityElementsHidden = YES;
|
|
26
|
+
|
|
27
|
+
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
|
|
28
|
+
[self addGestureRecognizer:tap];
|
|
29
|
+
|
|
30
|
+
UILongPressGestureRecognizer *longPress =
|
|
31
|
+
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
|
|
32
|
+
[self addGestureRecognizer:longPress];
|
|
33
|
+
}
|
|
34
|
+
return self;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#pragma mark - Data
|
|
38
|
+
|
|
39
|
+
- (void)updateWithRows:(NSArray<ENRMTableIOSRowData *> *)rows
|
|
40
|
+
columnWidths:(NSArray<NSNumber *> *)columnWidths
|
|
41
|
+
rowHeights:(NSArray<NSNumber *> *)rowHeights
|
|
42
|
+
borderColor:(UIColor *)borderColor
|
|
43
|
+
borderWidth:(CGFloat)borderWidth
|
|
44
|
+
horizontalCellPadding:(CGFloat)horizontalCellPadding
|
|
45
|
+
verticalCellPadding:(CGFloat)verticalCellPadding
|
|
46
|
+
cornerRadius:(CGFloat)cornerRadius
|
|
47
|
+
{
|
|
48
|
+
_tableRows = [rows copy];
|
|
49
|
+
_columnWidths = [columnWidths copy];
|
|
50
|
+
_rowHeights = [rowHeights copy];
|
|
51
|
+
_borderColor = borderColor;
|
|
52
|
+
_borderWidth = borderWidth;
|
|
53
|
+
_horizontalCellPadding = horizontalCellPadding;
|
|
54
|
+
_verticalCellPadding = verticalCellPadding;
|
|
55
|
+
[self setNeedsDisplay];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
- (void)fadeInRowsFrom:(NSUInteger)startRow duration:(NSTimeInterval)duration
|
|
59
|
+
{
|
|
60
|
+
if (startRow >= _tableRows.count)
|
|
61
|
+
return;
|
|
62
|
+
|
|
63
|
+
[UIView transitionWithView:self
|
|
64
|
+
duration:duration
|
|
65
|
+
options:UIViewAnimationOptionTransitionCrossDissolve
|
|
66
|
+
animations:^{}
|
|
67
|
+
completion:nil];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#pragma mark - Drawing
|
|
71
|
+
|
|
72
|
+
- (void)drawRect:(CGRect)dirtyRect
|
|
73
|
+
{
|
|
74
|
+
if (!_tableRows.count || !_columnWidths.count || !_rowHeights.count)
|
|
75
|
+
return;
|
|
76
|
+
|
|
77
|
+
CGFloat yOffset = 0;
|
|
78
|
+
for (NSUInteger r = 0; r < _tableRows.count; r++) {
|
|
79
|
+
ENRMTableIOSRowData *rowData = _tableRows[r];
|
|
80
|
+
CGFloat rowHeight = [_rowHeights[r] doubleValue];
|
|
81
|
+
CGFloat xOffset = 0;
|
|
82
|
+
|
|
83
|
+
NSUInteger colCount = MIN(rowData.cellTexts.count, _columnWidths.count);
|
|
84
|
+
for (NSUInteger c = 0; c < colCount; c++) {
|
|
85
|
+
CGFloat columnWidth = [_columnWidths[c] doubleValue];
|
|
86
|
+
CGRect cellRect = CGRectMake(xOffset, yOffset, columnWidth + _borderWidth, rowHeight + _borderWidth);
|
|
87
|
+
|
|
88
|
+
[rowData.backgroundColor setFill];
|
|
89
|
+
UIRectFill(cellRect);
|
|
90
|
+
|
|
91
|
+
[_borderColor setStroke];
|
|
92
|
+
UIBezierPath *border = [UIBezierPath bezierPathWithRect:cellRect];
|
|
93
|
+
border.lineWidth = _borderWidth;
|
|
94
|
+
[border stroke];
|
|
95
|
+
|
|
96
|
+
NSAttributedString *text = rowData.cellTexts[c];
|
|
97
|
+
if (text.length > 0) {
|
|
98
|
+
CGRect textRect = CGRectMake(xOffset + _horizontalCellPadding, yOffset + _verticalCellPadding,
|
|
99
|
+
columnWidth - _horizontalCellPadding * 2, rowHeight - _verticalCellPadding * 2);
|
|
100
|
+
[text drawWithRect:textRect
|
|
101
|
+
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
|
|
102
|
+
context:nil];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
xOffset += columnWidth;
|
|
106
|
+
}
|
|
107
|
+
yOffset += rowHeight;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#pragma mark - Link hit-testing
|
|
112
|
+
|
|
113
|
+
- (BOOL)cellAtPoint:(CGPoint)point
|
|
114
|
+
rowOrigin:(out CGFloat *)outRowY
|
|
115
|
+
rowHeight:(out CGFloat *)outRowH
|
|
116
|
+
colOrigin:(out CGFloat *)outColX
|
|
117
|
+
colWidth:(out CGFloat *)outColW
|
|
118
|
+
cellText:(out NSAttributedString *__autoreleasing *)outText
|
|
119
|
+
{
|
|
120
|
+
CGFloat rowY = 0;
|
|
121
|
+
for (NSUInteger r = 0; r < _tableRows.count; r++) {
|
|
122
|
+
CGFloat rh = [_rowHeights[r] doubleValue];
|
|
123
|
+
if (point.y >= rowY && point.y < rowY + rh) {
|
|
124
|
+
CGFloat colX = 0;
|
|
125
|
+
for (NSUInteger c = 0; c < _columnWidths.count; c++) {
|
|
126
|
+
CGFloat cw = [_columnWidths[c] doubleValue];
|
|
127
|
+
if (point.x >= colX && point.x < colX + cw) {
|
|
128
|
+
ENRMTableIOSRowData *rowData = _tableRows[r];
|
|
129
|
+
if (c >= rowData.cellTexts.count)
|
|
130
|
+
return NO;
|
|
131
|
+
*outRowY = rowY;
|
|
132
|
+
*outRowH = rh;
|
|
133
|
+
*outColX = colX;
|
|
134
|
+
*outColW = cw;
|
|
135
|
+
*outText = rowData.cellTexts[c];
|
|
136
|
+
return YES;
|
|
137
|
+
}
|
|
138
|
+
colX += cw;
|
|
139
|
+
}
|
|
140
|
+
return NO;
|
|
141
|
+
}
|
|
142
|
+
rowY += rh;
|
|
143
|
+
}
|
|
144
|
+
return NO;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
static NSString *linkInAttributedString(NSAttributedString *text, CGRect textRect, CGPoint point)
|
|
148
|
+
{
|
|
149
|
+
if (text.length == 0)
|
|
150
|
+
return nil;
|
|
151
|
+
|
|
152
|
+
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:text];
|
|
153
|
+
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
|
|
154
|
+
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:textRect.size];
|
|
155
|
+
textContainer.lineFragmentPadding = 0;
|
|
156
|
+
[layoutManager addTextContainer:textContainer];
|
|
157
|
+
[textStorage addLayoutManager:layoutManager];
|
|
158
|
+
[layoutManager ensureLayoutForTextContainer:textContainer];
|
|
159
|
+
|
|
160
|
+
CGPoint local = CGPointMake(point.x - textRect.origin.x, point.y - textRect.origin.y);
|
|
161
|
+
CGFloat fraction = 0;
|
|
162
|
+
NSUInteger glyphIndex = [layoutManager glyphIndexForPoint:local
|
|
163
|
+
inTextContainer:textContainer
|
|
164
|
+
fractionOfDistanceThroughGlyph:&fraction];
|
|
165
|
+
if (glyphIndex >= layoutManager.numberOfGlyphs)
|
|
166
|
+
return nil;
|
|
167
|
+
NSUInteger charIndex = [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
|
|
168
|
+
if (charIndex >= text.length)
|
|
169
|
+
return nil;
|
|
170
|
+
|
|
171
|
+
return [text attribute:@"linkURL" atIndex:charIndex effectiveRange:NULL];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
- (NSString *)linkURLAtPoint:(CGPoint)point
|
|
175
|
+
{
|
|
176
|
+
CGFloat rowY, rowH, colX, colW;
|
|
177
|
+
NSAttributedString *text;
|
|
178
|
+
if (![self cellAtPoint:point rowOrigin:&rowY rowHeight:&rowH colOrigin:&colX colWidth:&colW cellText:&text])
|
|
179
|
+
return nil;
|
|
180
|
+
|
|
181
|
+
CGRect textRect = CGRectMake(colX + _horizontalCellPadding, rowY + _verticalCellPadding,
|
|
182
|
+
colW - _horizontalCellPadding * 2, rowH - _verticalCellPadding * 2);
|
|
183
|
+
if (!CGRectContainsPoint(textRect, point))
|
|
184
|
+
return nil;
|
|
185
|
+
|
|
186
|
+
return linkInAttributedString(text, textRect, point);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
#pragma mark - Gesture handlers
|
|
190
|
+
|
|
191
|
+
- (void)handleLinkGesture:(UIGestureRecognizer *)recognizer block:(ENRMTableIOSLinkBlock)block
|
|
192
|
+
{
|
|
193
|
+
CGPoint point = [recognizer locationInView:self];
|
|
194
|
+
NSString *url = [self linkURLAtPoint:point];
|
|
195
|
+
if (url && block) {
|
|
196
|
+
block(url);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
- (void)handleTap:(UITapGestureRecognizer *)recognizer
|
|
201
|
+
{
|
|
202
|
+
if (recognizer.state == UIGestureRecognizerStateEnded) {
|
|
203
|
+
[self handleLinkGesture:recognizer block:self.onLinkTap];
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
- (void)handleLongPress:(UILongPressGestureRecognizer *)recognizer
|
|
208
|
+
{
|
|
209
|
+
if (recognizer.state == UIGestureRecognizerStateBegan) {
|
|
210
|
+
[self handleLinkGesture:recognizer block:self.onLinkLongTap];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@end
|
|
215
|
+
|
|
216
|
+
#endif // !TARGET_OS_OSX
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
@class RenderContext;
|
|
10
10
|
@class AccessibilityInfo;
|
|
11
|
+
@class ENRMAccessibilityLabels;
|
|
11
12
|
@class ENRMSpoilerOverlayManager;
|
|
12
13
|
|
|
13
14
|
NS_ASSUME_NONNULL_BEGIN
|
|
@@ -26,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
26
27
|
@property (nonatomic) ENRMSpoilerOverlay spoilerOverlay;
|
|
27
28
|
|
|
28
29
|
@property (nonatomic, strong, nullable) AccessibilityInfo *accessibilityInfo;
|
|
30
|
+
@property (nonatomic, strong, nullable) ENRMAccessibilityLabels *accessibilityLabels;
|
|
29
31
|
|
|
30
32
|
@property (nonatomic, strong) StyleConfig *config;
|
|
31
33
|
|