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.
Files changed (213) hide show
  1. package/ReactNativeEnrichedMarkdown.podspec +62 -11
  2. package/android/build.gradle +5 -0
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +3 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +1 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +12 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +4 -0
  7. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +3 -0
  8. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +1 -0
  9. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +25 -0
  10. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +793 -0
  11. package/android/src/main/baseline-prof.txt +75 -2
  12. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +62 -0
  13. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +10 -2
  14. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +10 -0
  15. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +9 -2
  16. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +10 -0
  17. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +6 -4
  18. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt +15 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/MarkdownAccessibilityHelper.kt +44 -7
  20. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +72 -0
  21. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +110 -12
  22. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockSyntaxSentinel.kt +69 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +19 -0
  24. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +84 -6
  25. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputRemend.kt +1 -0
  26. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputLayoutManager.kt +30 -2
  27. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +13 -2
  28. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +3 -0
  29. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +54 -13
  30. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +17 -0
  31. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +1 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +4 -4
  33. package/android/src/main/java/com/swmansion/enriched/markdown/spans/HeadingSpan.kt +8 -1
  34. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LineHeightSpan.kt +27 -1
  35. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +5 -1
  36. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathFontWeight.kt +25 -0
  37. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +12 -1
  38. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +37 -7
  39. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +10 -0
  40. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/SpannableExtensions.kt +12 -4
  41. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkEvents.kt +22 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +36 -7
  43. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +74 -4
  44. package/android/src/main/jni/CMakeLists.txt +15 -1
  45. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +2 -0
  46. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
  47. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlinePlaceholderSpan.kt +7 -3
  48. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +8 -5
  49. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathTypeface.kt +30 -0
  50. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +27 -3
  51. package/app.plugin.js +2 -1
  52. package/cpp/parser/MD4CParser.cpp +1 -1
  53. package/cpp/wasm/build.sh +9 -9
  54. package/docs/ACCESSIBILITY.md +172 -0
  55. package/docs/API_REFERENCE.md +957 -0
  56. package/docs/COPY_OPTIONS.md +127 -0
  57. package/docs/ELEMENTS_STRUCTURE.md +112 -0
  58. package/docs/IMAGE_CACHING.md +25 -0
  59. package/docs/INPUT.md +281 -0
  60. package/docs/LATEX_MATH.md +198 -0
  61. package/docs/MACOS.md +19 -0
  62. package/docs/MARKDOWN_STREAMING.md +36 -0
  63. package/docs/MENTIONS.md +97 -0
  64. package/docs/RTL.md +82 -0
  65. package/docs/STYLES.md +522 -0
  66. package/docs/TEXT.md +110 -0
  67. package/docs/WEB.md +49 -0
  68. package/ios/EnrichedMarkdown.mm +126 -37
  69. package/ios/EnrichedMarkdownText.mm +84 -16
  70. package/ios/attachments/ENRMMathInlineAttachment+macOS.m +5 -1
  71. package/ios/attachments/ENRMMathInlineAttachment.h +3 -0
  72. package/ios/attachments/ENRMMathInlineAttachment.m +2 -1
  73. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +25 -0
  74. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +793 -0
  75. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +15 -0
  76. package/ios/input/ENRMBlockSyntaxSentinel.h +25 -0
  77. package/ios/input/ENRMBlockSyntaxSentinel.mm +80 -0
  78. package/ios/input/ENRMFormattingStore.h +5 -0
  79. package/ios/input/ENRMFormattingStore.mm +34 -0
  80. package/ios/input/ENRMInputFormatter.h +4 -0
  81. package/ios/input/ENRMInputFormatter.mm +2 -0
  82. package/ios/input/ENRMInputParser.h +5 -0
  83. package/ios/input/ENRMInputParser.mm +79 -6
  84. package/ios/input/ENRMInputTextView.h +2 -0
  85. package/ios/input/ENRMInputTextView.mm +8 -17
  86. package/ios/input/ENRMMarkdownSerializer.mm +1 -1
  87. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +71 -53
  88. package/ios/input/EnrichedMarkdownTextInput+Internal.h +26 -0
  89. package/ios/input/EnrichedMarkdownTextInput.h +1 -0
  90. package/ios/input/EnrichedMarkdownTextInput.mm +249 -31
  91. package/ios/input/InputStylePropsUtils.h +13 -0
  92. package/ios/input/styles/ENRMBoldStyleHandler.mm +3 -2
  93. package/ios/input/styles/ENRMItalicStyleHandler.mm +3 -2
  94. package/ios/internals/MeasurementCache.h +1 -0
  95. package/ios/math/ENRMRaTeXBridge.swift +52 -3
  96. package/ios/parser/ENRMMarkdownParser.h +8 -0
  97. package/ios/parser/ENRMMarkdownParser.mm +11 -0
  98. package/ios/renderer/AttributedRenderer.m +51 -6
  99. package/ios/renderer/ENRMMathInlineRenderer.m +8 -1
  100. package/ios/renderer/ListItemRenderer.m +8 -5
  101. package/ios/styles/ENRMFontSlot.h +1 -1
  102. package/ios/styles/StyleConfig.h +6 -0
  103. package/ios/styles/StyleConfig.mm +36 -0
  104. package/ios/utils/ENRMAccessibilityLabels.h +36 -0
  105. package/ios/utils/ENRMAccessibilityLabels.m +5 -0
  106. package/ios/utils/ENRMMathFontWeight.h +18 -0
  107. package/ios/utils/EditMenuUtils+macOS.m +4 -5
  108. package/ios/utils/EditMenuUtils.h +70 -0
  109. package/ios/utils/EditMenuUtils.m +14 -11
  110. package/ios/utils/LastElementUtils.h +39 -2
  111. package/ios/utils/MarkdownAccessibilityElementBuilder.h +18 -16
  112. package/ios/utils/MarkdownAccessibilityElementBuilder.m +64 -32
  113. package/ios/utils/ParagraphStyleUtils.m +21 -2
  114. package/ios/utils/StylePropsUtils.h +21 -0
  115. package/ios/views/ENRMMathContainerView.h +8 -0
  116. package/ios/views/ENRMMathContainerView.m +10 -6
  117. package/ios/views/ENRMTableIOSGridView.h +40 -0
  118. package/ios/views/ENRMTableIOSGridView.m +216 -0
  119. package/ios/views/EnrichedMarkdownInternalText.h +2 -0
  120. package/ios/views/EnrichedMarkdownInternalText.m +2 -0
  121. package/ios/views/TableContainerView.h +8 -0
  122. package/ios/views/TableContainerView.m +72 -128
  123. package/lib/module/EnrichedMarkdownNativeComponent.ts +40 -0
  124. package/lib/module/EnrichedMarkdownTextInput.js +50 -1
  125. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  126. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +47 -0
  127. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +40 -0
  128. package/lib/module/accessibilityLabelDefaults.js +64 -0
  129. package/lib/module/accessibilityLabelDefaults.js.map +1 -0
  130. package/lib/module/index.js +1 -0
  131. package/lib/module/index.js.map +1 -1
  132. package/lib/module/native/EnrichedMarkdownText.js +72 -4
  133. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  134. package/lib/module/normalizeMarkdownStyle.js +5 -2
  135. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  136. package/lib/module/normalizeMarkdownStyle.web.js +5 -2
  137. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  138. package/lib/module/normalizeMarkdownTextInputStyle.js +7 -3
  139. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  140. package/lib/module/normalizeMenuItem.js +38 -0
  141. package/lib/module/normalizeMenuItem.js.map +1 -0
  142. package/lib/module/types/AccessibilityLabels.js +2 -0
  143. package/lib/module/types/AccessibilityLabels.js.map +1 -0
  144. package/lib/module/web/globalStyles.js +8 -1
  145. package/lib/module/web/globalStyles.js.map +1 -1
  146. package/lib/module/web/styles.js +3 -1
  147. package/lib/module/web/styles.js.map +1 -1
  148. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +37 -0
  149. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  150. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +57 -1
  151. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  152. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +42 -0
  153. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  154. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +37 -0
  155. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  156. package/lib/typescript/src/accessibilityLabelDefaults.d.ts +16 -0
  157. package/lib/typescript/src/accessibilityLabelDefaults.d.ts.map +1 -0
  158. package/lib/typescript/src/index.d.ts +4 -2
  159. package/lib/typescript/src/index.d.ts.map +1 -1
  160. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
  161. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  162. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  163. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  164. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +1 -0
  165. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  166. package/lib/typescript/src/normalizeMenuItem.d.ts +7 -0
  167. package/lib/typescript/src/normalizeMenuItem.d.ts.map +1 -0
  168. package/lib/typescript/src/types/AccessibilityLabels.d.ts +114 -0
  169. package/lib/typescript/src/types/AccessibilityLabels.d.ts.map +1 -0
  170. package/lib/typescript/src/types/MarkdownStyle.d.ts +32 -0
  171. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  172. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +3 -0
  173. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  174. package/lib/typescript/src/types/MarkdownTextProps.d.ts +78 -9
  175. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  176. package/lib/typescript/src/web/styles.d.ts.map +1 -1
  177. package/package.json +4 -2
  178. package/plugin/build/withAndroidMath.js +19 -0
  179. package/plugin/build/withIosMath.js +28 -0
  180. package/plugin/build/withReactNativeEnrichedMarkdown.js +11 -0
  181. package/plugin/tsconfig.build.json +16 -0
  182. package/src/EnrichedMarkdownNativeComponent.ts +40 -0
  183. package/src/EnrichedMarkdownTextInput.tsx +121 -1
  184. package/src/EnrichedMarkdownTextInputNativeComponent.ts +47 -0
  185. package/src/EnrichedMarkdownTextNativeComponent.ts +40 -0
  186. package/src/accessibilityLabelDefaults.ts +83 -0
  187. package/src/index.tsx +11 -0
  188. package/src/native/EnrichedMarkdownText.tsx +120 -6
  189. package/src/normalizeMarkdownStyle.ts +6 -1
  190. package/src/normalizeMarkdownStyle.web.ts +6 -1
  191. package/src/normalizeMarkdownTextInputStyle.ts +5 -0
  192. package/src/normalizeMenuItem.ts +52 -0
  193. package/src/types/AccessibilityLabels.ts +118 -0
  194. package/src/types/MarkdownStyle.ts +32 -0
  195. package/src/types/MarkdownStyleInternal.ts +3 -0
  196. package/src/types/MarkdownTextProps.ts +74 -9
  197. package/src/web/globalStyles.ts +7 -0
  198. package/src/web/styles.ts +5 -1
  199. package/lib/module/plugin/withAndroidMath.js +0 -20
  200. package/lib/module/plugin/withAndroidMath.js.map +0 -1
  201. package/lib/module/plugin/withIosMath.js +0 -23
  202. package/lib/module/plugin/withIosMath.js.map +0 -1
  203. package/lib/module/plugin/withReactNativeEnrichedMarkdown.js +0 -16
  204. package/lib/module/plugin/withReactNativeEnrichedMarkdown.js.map +0 -1
  205. package/lib/typescript/src/plugin/withAndroidMath.d.ts +0 -5
  206. package/lib/typescript/src/plugin/withAndroidMath.d.ts.map +0 -1
  207. package/lib/typescript/src/plugin/withIosMath.d.ts +0 -5
  208. package/lib/typescript/src/plugin/withIosMath.d.ts.map +0 -1
  209. package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts +0 -6
  210. package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts.map +0 -1
  211. /package/{src/plugin → plugin/src}/withAndroidMath.ts +0 -0
  212. /package/{src/plugin → plugin/src}/withIosMath.ts +0 -0
  213. /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
- element.accessibilityLabel = (type == ElementTypeImage && text.length == 0) ? NSLocalizedString(@"Image", @"") : text;
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
- [values addObject:[self formatListAnnouncement:listInfo]];
183
+ [valueParts addObject:[self formatListAnnouncement:listInfo labels:labels]];
178
184
  }
179
-
180
- if (values.count > 0) {
181
- element.accessibilityValue = [values componentsJoinedByString:@", "];
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
- NSString *prefix = [info[@"depth"] integerValue] > 1 ? @"nested " : @"";
192
- return [info[@"isOrdered"] boolValue]
193
- ? [NSString stringWithFormat:@"%@list item %ld", prefix, (long)[info[@"position"] integerValue]]
194
- : [NSString stringWithFormat:@"%@bullet point", prefix];
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:NSLocalizedString(@"Headings", @"") elements:elements];
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:NSLocalizedString(@"Links", @"") elements:elements];
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:NSLocalizedString(@"Images", @"") elements:elements];
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 info:(AccessibilityInfo *)info container:(id)container
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.lineHeight, maximumFontLineHeight);
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:@"Copy"
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:@"Copy as Markdown"
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(NSLocalizedString(@"Copy", nil), ^{ [self copyLatexToPasteboard]; })];
143
- [menu addItem:ENRMCreateMenuItem(NSLocalizedString(@"Copy as Markdown", nil), ^{ [self copyMarkdownToPasteboard]; })];
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 [NSString stringWithFormat:@"Math equation: %@", _cachedLatex];
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