react-native-enriched-markdown-scaffold 0.6.0-scaffold.8 → 0.7.4-scaffold.2

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 (150) hide show
  1. package/ReactNativeEnrichedMarkdown.podspec +62 -11
  2. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +3 -0
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +1 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +9 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +3 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +3 -0
  7. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +1 -0
  8. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +20 -0
  9. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +744 -0
  10. package/android/src/main/baseline-prof.txt +75 -2
  11. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +62 -0
  12. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +10 -2
  13. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +10 -0
  14. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +9 -2
  15. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +10 -0
  16. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibilityLabels.kt +15 -0
  17. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/MarkdownAccessibilityHelper.kt +44 -7
  18. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +52 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +89 -11
  20. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +19 -0
  21. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +22 -3
  22. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputRemend.kt +1 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +7 -1
  24. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +54 -13
  25. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +17 -0
  26. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +4 -4
  27. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +30 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkEvents.kt +22 -0
  29. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +36 -7
  30. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +73 -3
  31. package/android/src/main/jni/CMakeLists.txt +15 -1
  32. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +24 -2
  33. package/app.plugin.js +2 -1
  34. package/cpp/parser/MD4CParser.cpp +1 -1
  35. package/cpp/wasm/build.sh +9 -9
  36. package/docs/ACCESSIBILITY.md +172 -0
  37. package/docs/API_REFERENCE.md +948 -0
  38. package/docs/COPY_OPTIONS.md +127 -0
  39. package/docs/ELEMENTS_STRUCTURE.md +112 -0
  40. package/docs/IMAGE_CACHING.md +25 -0
  41. package/docs/INPUT.md +233 -0
  42. package/docs/LATEX_MATH.md +136 -0
  43. package/docs/MACOS.md +19 -0
  44. package/docs/MARKDOWN_STREAMING.md +36 -0
  45. package/docs/MENTIONS.md +97 -0
  46. package/docs/RTL.md +82 -0
  47. package/docs/STYLES.md +519 -0
  48. package/docs/TEXT.md +110 -0
  49. package/docs/WEB.md +49 -0
  50. package/ios/EnrichedMarkdown.mm +82 -25
  51. package/ios/EnrichedMarkdownText.mm +37 -5
  52. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +20 -0
  53. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +744 -0
  54. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +15 -0
  55. package/ios/input/ENRMFormattingStore.h +5 -0
  56. package/ios/input/ENRMFormattingStore.mm +34 -0
  57. package/ios/input/ENRMInputTextView.h +2 -0
  58. package/ios/input/ENRMInputTextView.mm +8 -17
  59. package/ios/input/ENRMMarkdownSerializer.mm +1 -1
  60. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +71 -53
  61. package/ios/input/EnrichedMarkdownTextInput+Internal.h +26 -0
  62. package/ios/input/EnrichedMarkdownTextInput.h +1 -0
  63. package/ios/input/EnrichedMarkdownTextInput.mm +230 -29
  64. package/ios/input/styles/ENRMBoldStyleHandler.mm +3 -2
  65. package/ios/input/styles/ENRMItalicStyleHandler.mm +3 -2
  66. package/ios/renderer/AttributedRenderer.m +51 -6
  67. package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
  68. package/ios/styles/ENRMFontSlot.h +1 -1
  69. package/ios/utils/ENRMAccessibilityLabels.h +36 -0
  70. package/ios/utils/ENRMAccessibilityLabels.m +5 -0
  71. package/ios/utils/EditMenuUtils+macOS.m +4 -5
  72. package/ios/utils/EditMenuUtils.h +70 -0
  73. package/ios/utils/EditMenuUtils.m +14 -11
  74. package/ios/utils/LastElementUtils.h +39 -2
  75. package/ios/utils/MarkdownAccessibilityElementBuilder.h +18 -16
  76. package/ios/utils/MarkdownAccessibilityElementBuilder.m +64 -32
  77. package/ios/utils/ParagraphStyleUtils.m +21 -2
  78. package/ios/views/ENRMMathContainerView.h +8 -0
  79. package/ios/views/ENRMMathContainerView.m +7 -5
  80. package/ios/views/ENRMTableIOSGridView.h +40 -0
  81. package/ios/views/ENRMTableIOSGridView.m +216 -0
  82. package/ios/views/EnrichedMarkdownInternalText.h +2 -0
  83. package/ios/views/EnrichedMarkdownInternalText.m +2 -0
  84. package/ios/views/TableContainerView.h +8 -0
  85. package/ios/views/TableContainerView.m +72 -128
  86. package/lib/module/EnrichedMarkdownNativeComponent.ts +37 -0
  87. package/lib/module/EnrichedMarkdownTextInput.js +48 -1
  88. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  89. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +35 -0
  90. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +37 -0
  91. package/lib/module/accessibilityLabelDefaults.js +64 -0
  92. package/lib/module/accessibilityLabelDefaults.js.map +1 -0
  93. package/lib/module/index.js +1 -0
  94. package/lib/module/index.js.map +1 -1
  95. package/lib/module/native/EnrichedMarkdownText.js +72 -4
  96. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  97. package/lib/module/normalizeMenuItem.js +38 -0
  98. package/lib/module/normalizeMenuItem.js.map +1 -0
  99. package/lib/module/types/AccessibilityLabels.js +2 -0
  100. package/lib/module/types/AccessibilityLabels.js.map +1 -0
  101. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +34 -0
  102. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  103. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +55 -1
  104. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  105. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +30 -0
  106. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  107. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +34 -0
  108. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  109. package/lib/typescript/src/accessibilityLabelDefaults.d.ts +16 -0
  110. package/lib/typescript/src/accessibilityLabelDefaults.d.ts.map +1 -0
  111. package/lib/typescript/src/index.d.ts +4 -2
  112. package/lib/typescript/src/index.d.ts.map +1 -1
  113. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
  114. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  115. package/lib/typescript/src/normalizeMenuItem.d.ts +7 -0
  116. package/lib/typescript/src/normalizeMenuItem.d.ts.map +1 -0
  117. package/lib/typescript/src/types/AccessibilityLabels.d.ts +114 -0
  118. package/lib/typescript/src/types/AccessibilityLabels.d.ts.map +1 -0
  119. package/lib/typescript/src/types/MarkdownTextProps.d.ts +78 -9
  120. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  121. package/package.json +4 -2
  122. package/plugin/build/withAndroidMath.js +19 -0
  123. package/plugin/build/withIosMath.js +28 -0
  124. package/plugin/build/withReactNativeEnrichedMarkdown.js +11 -0
  125. package/plugin/tsconfig.build.json +16 -0
  126. package/src/EnrichedMarkdownNativeComponent.ts +37 -0
  127. package/src/EnrichedMarkdownTextInput.tsx +117 -1
  128. package/src/EnrichedMarkdownTextInputNativeComponent.ts +35 -0
  129. package/src/EnrichedMarkdownTextNativeComponent.ts +37 -0
  130. package/src/accessibilityLabelDefaults.ts +83 -0
  131. package/src/index.tsx +11 -0
  132. package/src/native/EnrichedMarkdownText.tsx +120 -6
  133. package/src/normalizeMenuItem.ts +52 -0
  134. package/src/types/AccessibilityLabels.ts +118 -0
  135. package/src/types/MarkdownTextProps.ts +74 -9
  136. package/lib/module/plugin/withAndroidMath.js +0 -20
  137. package/lib/module/plugin/withAndroidMath.js.map +0 -1
  138. package/lib/module/plugin/withIosMath.js +0 -23
  139. package/lib/module/plugin/withIosMath.js.map +0 -1
  140. package/lib/module/plugin/withReactNativeEnrichedMarkdown.js +0 -16
  141. package/lib/module/plugin/withReactNativeEnrichedMarkdown.js.map +0 -1
  142. package/lib/typescript/src/plugin/withAndroidMath.d.ts +0 -5
  143. package/lib/typescript/src/plugin/withAndroidMath.d.ts.map +0 -1
  144. package/lib/typescript/src/plugin/withIosMath.d.ts +0 -5
  145. package/lib/typescript/src/plugin/withIosMath.d.ts.map +0 -1
  146. package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts +0 -6
  147. package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts.map +0 -1
  148. /package/{src/plugin → plugin/src}/withAndroidMath.ts +0 -0
  149. /package/{src/plugin → plugin/src}/withIosMath.ts +0 -0
  150. /package/{src/plugin → plugin/src}/withReactNativeEnrichedMarkdown.ts +0 -0
@@ -35,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
35
35
  - (void)insertMath:(NSString *)latex displayMode:(BOOL)displayMode;
36
36
  - (void)updateMath:(NSInteger)start latex:(NSString *)latex displayMode:(BOOL)displayMode;
37
37
  - (void)removeMath:(NSInteger)start;
38
+ - (void)copyToClipboard;
38
39
  - (void)requestMarkdown:(NSInteger)requestId;
39
40
  - (void)requestCaretRect:(NSInteger)requestId;
40
41
  @end
@@ -384,6 +385,20 @@ if ([commandName isEqualToString:@"removeMath"]) {
384
385
  return;
385
386
  }
386
387
 
388
+ if ([commandName isEqualToString:@"copyToClipboard"]) {
389
+ #if RCT_DEBUG
390
+ if ([args count] != 0) {
391
+ RCTLogError(@"%@ command %@ received %d arguments, expected %d.", @"EnrichedMarkdownTextInput", commandName, (int)[args count], 0);
392
+ return;
393
+ }
394
+ #endif
395
+
396
+
397
+
398
+ [componentView copyToClipboard];
399
+ return;
400
+ }
401
+
387
402
  if ([commandName isEqualToString:@"requestMarkdown"]) {
388
403
  #if RCT_DEBUG
389
404
  if ([args count] != 1) {
@@ -14,8 +14,13 @@ NS_ASSUME_NONNULL_BEGIN
14
14
  - (nullable ENRMFormattingRange *)rangeOfType:(ENRMInputStyleType)type containingPosition:(NSUInteger)position;
15
15
  - (BOOL)isStyleActive:(ENRMInputStyleType)type atPosition:(NSUInteger)position;
16
16
  - (BOOL)isStyleActive:(ENRMInputStyleType)type inRange:(NSRange)range;
17
+ - (BOOL)isStyleAdjacentBefore:(ENRMInputStyleType)type position:(NSUInteger)position;
17
18
  - (NSArray<ENRMFormattingRange *> *)rangesOfType:(ENRMInputStyleType)type;
18
19
 
20
+ /// Snaps a selection so it never partially overlaps an atomic link: a partial selection expands to
21
+ /// the whole link, a caret inside a link moves to its end (unchanged when no adjustment is needed).
22
+ - (NSRange)selectionAdjustedForAtomicLinks:(NSRange)selection;
23
+
19
24
  - (void)addRange:(ENRMFormattingRange *)range;
20
25
  - (void)removeType:(ENRMInputStyleType)type inRange:(NSRange)range;
21
26
  - (void)removeRange:(ENRMFormattingRange *)range;
@@ -99,6 +99,31 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
99
99
  return nil;
100
100
  }
101
101
 
102
+ - (NSRange)selectionAdjustedForAtomicLinks:(NSRange)selection
103
+ {
104
+ if (selection.length > 0) {
105
+ NSUInteger start = selection.location;
106
+ NSUInteger end = NSMaxRange(selection);
107
+ ENRMFormattingRange *startLink = [self rangeOfType:ENRMInputStyleTypeLink containingPosition:start];
108
+ if (startLink != nil) {
109
+ start = MIN(start, startLink.range.location);
110
+ }
111
+ if (end > 0) {
112
+ ENRMFormattingRange *endLink = [self rangeOfType:ENRMInputStyleTypeLink containingPosition:(end - 1)];
113
+ if (endLink != nil) {
114
+ end = MAX(end, NSMaxRange(endLink.range));
115
+ }
116
+ }
117
+ return NSMakeRange(start, end - start);
118
+ }
119
+ ENRMFormattingRange *caretLink = [self rangeOfType:ENRMInputStyleTypeLink containingPosition:selection.location];
120
+ if (caretLink != nil && selection.location > caretLink.range.location &&
121
+ selection.location < NSMaxRange(caretLink.range)) {
122
+ return NSMakeRange(NSMaxRange(caretLink.range), 0);
123
+ }
124
+ return selection;
125
+ }
126
+
102
127
  - (BOOL)isStyleActive:(ENRMInputStyleType)type atPosition:(NSUInteger)position
103
128
  {
104
129
  return [self rangeOfType:type containingPosition:position] != nil;
@@ -114,6 +139,15 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
114
139
  return NO;
115
140
  }
116
141
 
142
+ - (BOOL)isStyleAdjacentBefore:(ENRMInputStyleType)type position:(NSUInteger)position
143
+ {
144
+ if (position == 0) {
145
+ return NO;
146
+ }
147
+ return [self rangeOfType:type containingPosition:position] != nil || [self rangeOfType:type
148
+ containingPosition:position - 1] != nil;
149
+ }
150
+
117
151
  - (void)addRange:(ENRMFormattingRange *)newRange
118
152
  {
119
153
  NSMutableIndexSet *mergeIndexes = [NSMutableIndexSet indexSet];
@@ -6,6 +6,8 @@
6
6
 
7
7
  NS_ASSUME_NONNULL_BEGIN
8
8
 
9
+ extern NSString *const kENRMMarkdownPasteboardType;
10
+
9
11
  @interface ENRMInputTextView : ENRMPlatformTextView
10
12
  @property (nonatomic, weak, nullable) EnrichedMarkdownTextInput *markdownTextInput;
11
13
  @end
@@ -1,15 +1,14 @@
1
1
  #import "ENRMInputTextView.h"
2
2
  #import "EnrichedMarkdownTextInput.h"
3
+ #import "PasteboardUtils.h"
3
4
  #if TARGET_OS_OSX
4
5
  #import "EnrichedMarkdownTextInput+Internal.h"
5
6
  #endif
6
7
 
7
- static NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-markdown.markdown";
8
+ NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-markdown.markdown";
8
9
 
9
10
  #if !TARGET_OS_OSX
10
11
 
11
- #import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
12
-
13
12
  @implementation ENRMInputTextView
14
13
 
15
14
  - (void)copy:(id)sender
@@ -21,14 +20,12 @@ static NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-ma
21
20
 
22
21
  NSString *plainText = [self.text substringWithRange:selection];
23
22
  NSString *markdown = [self.markdownTextInput markdownForSelectedRange];
24
-
25
- UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
26
23
  NSMutableDictionary *items = [NSMutableDictionary dictionary];
27
- items[UTTypePlainText.identifier] = plainText;
24
+ items[kUTIPlainText] = plainText;
28
25
  if (markdown.length > 0) {
29
26
  items[kENRMMarkdownPasteboardType] = markdown;
30
27
  }
31
- pasteboard.items = @[ items ];
28
+ copyItemsToPasteboard(items);
32
29
  }
33
30
 
34
31
  - (void)cut:(id)sender
@@ -94,18 +91,12 @@ static NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-ma
94
91
 
95
92
  NSString *plainText = [self.string substringWithRange:selection];
96
93
  NSString *markdown = [self.markdownTextInput markdownForSelectedRange];
97
-
98
- NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
99
- [pasteboard clearContents];
100
- NSMutableArray *types = [NSMutableArray arrayWithObject:NSPasteboardTypeString];
101
- if (markdown.length > 0) {
102
- [types addObject:kENRMMarkdownPasteboardType];
103
- }
104
- [pasteboard declareTypes:types owner:nil];
105
- [pasteboard setString:plainText forType:NSPasteboardTypeString];
94
+ NSMutableDictionary *items = [NSMutableDictionary dictionary];
95
+ items[kUTIPlainText] = plainText;
106
96
  if (markdown.length > 0) {
107
- [pasteboard setString:markdown forType:kENRMMarkdownPasteboardType];
97
+ items[kENRMMarkdownPasteboardType] = markdown;
108
98
  }
99
+ copyItemsToPasteboard(items);
109
100
  }
110
101
 
111
102
  - (void)cut:(id)sender
@@ -100,7 +100,7 @@ static NSCharacterSet *whitespaceSet(void)
100
100
  {
101
101
  static NSCharacterSet *set;
102
102
  static dispatch_once_t onceToken;
103
- dispatch_once(&onceToken, ^{ set = [NSCharacterSet whitespaceCharacterSet]; });
103
+ dispatch_once(&onceToken, ^{ set = [NSCharacterSet whitespaceAndNewlineCharacterSet]; });
104
104
  return set;
105
105
  }
106
106
 
@@ -3,8 +3,6 @@
3
3
  #import "EnrichedMarkdownTextInput+Internal.h"
4
4
  #import "PasteboardUtils.h"
5
5
 
6
- // TODO: Wrap all user-facing strings with NSLocalizedString for localization support.
7
-
8
6
  @implementation EnrichedMarkdownTextInput (ContextMenu)
9
7
 
10
8
  - (void)copySelectedRangeAsMarkdown
@@ -25,28 +23,33 @@
25
23
  return nil;
26
24
  }
27
25
 
26
+ ENRMInputSelectionMenuConfig menuConfig = [self inputSelectionMenuConfig];
27
+ ENRMFormatMenuConfig fmtConfig = [self formatMenuConfig];
28
28
  __weak EnrichedMarkdownTextInput *weakSelf = self;
29
29
 
30
- static const struct {
30
+ const struct {
31
31
  NSString *title;
32
32
  NSString *icon;
33
33
  ENRMInputStyleType styleType;
34
- } kFormatItems[] = {
35
- // TODO: Localize titles with NSLocalizedString.
36
- {@"Bold", @"bold", ENRMInputStyleTypeStrong},
37
- {@"Italic", @"italic", ENRMInputStyleTypeEmphasis},
38
- {@"Underline", @"underline", ENRMInputStyleTypeUnderline},
39
- {@"Strikethrough", @"strikethrough", ENRMInputStyleTypeStrikethrough},
40
- {@"Spoiler", @"eye.slash", ENRMInputStyleTypeSpoiler},
41
- {@"Link", @"link", ENRMInputStyleTypeLink},
34
+ BOOL visible;
35
+ } formatItems[] = {
36
+ {fmtConfig.boldLabel, @"bold", ENRMInputStyleTypeStrong, fmtConfig.bold},
37
+ {fmtConfig.italicLabel, @"italic", ENRMInputStyleTypeEmphasis, fmtConfig.italic},
38
+ {fmtConfig.underlineLabel, @"underline", ENRMInputStyleTypeUnderline, fmtConfig.underline},
39
+ {fmtConfig.strikethroughLabel, @"strikethrough", ENRMInputStyleTypeStrikethrough, fmtConfig.strikethrough},
40
+ {fmtConfig.spoilerLabel, @"eye.slash", ENRMInputStyleTypeSpoiler, fmtConfig.spoiler},
41
+ {fmtConfig.linkLabel, @"link", ENRMInputStyleTypeLink, fmtConfig.link},
42
42
  };
43
- static const NSUInteger kFormatItemCount = sizeof(kFormatItems) / sizeof(kFormatItems[0]);
43
+ const NSUInteger formatItemCount = sizeof(formatItems) / sizeof(formatItems[0]);
44
44
 
45
- NSMutableArray<UIAction *> *formatActions = [NSMutableArray arrayWithCapacity:kFormatItemCount];
46
- for (NSUInteger i = 0; i < kFormatItemCount; i++) {
47
- ENRMInputStyleType styleType = kFormatItems[i].styleType;
48
- UIAction *action = [UIAction actionWithTitle:kFormatItems[i].title
49
- image:[UIImage systemImageNamed:kFormatItems[i].icon]
45
+ NSMutableArray<UIAction *> *formatActions = [NSMutableArray arrayWithCapacity:formatItemCount];
46
+ for (NSUInteger i = 0; i < formatItemCount; i++) {
47
+ if (!formatItems[i].visible) {
48
+ continue;
49
+ }
50
+ ENRMInputStyleType styleType = formatItems[i].styleType;
51
+ UIAction *action = [UIAction actionWithTitle:formatItems[i].title
52
+ image:[UIImage systemImageNamed:formatItems[i].icon]
50
53
  identifier:nil
51
54
  handler:^(__kindof UIAction *_) {
52
55
  if (styleType == ENRMInputStyleTypeLink) {
@@ -57,14 +60,14 @@
57
60
  }];
58
61
  [formatActions addObject:action];
59
62
  }
60
- UIMenu *formatMenu = [UIMenu menuWithTitle:@"Format"
63
+ UIMenu *formatMenu = [UIMenu menuWithTitle:menuConfig.formatLabel
61
64
  image:[UIImage systemImageNamed:@"textformat"]
62
65
  identifier:@"com.enrichedmarkdown.format"
63
66
  options:0
64
67
  children:formatActions];
65
68
 
66
69
  UIAction *copyMarkdownAction =
67
- [UIAction actionWithTitle:@"Copy as Markdown"
70
+ [UIAction actionWithTitle:menuConfig.copyAsMarkdownLabel
68
71
  image:[UIImage systemImageNamed:@"doc.text"]
69
72
  identifier:@"com.enrichedmarkdown.copyMarkdown"
70
73
  handler:^(__kindof UIAction *action) { [self copySelectedRangeAsMarkdown]; }];
@@ -91,8 +94,13 @@
91
94
  break;
92
95
  }
93
96
  }
94
- [systemActions insertObject:formatMenu atIndex:insertIndex];
95
- [systemActions insertObject:copyMarkdownAction atIndex:insertIndex + 1];
97
+ if (menuConfig.format) {
98
+ [systemActions insertObject:formatMenu atIndex:insertIndex];
99
+ insertIndex++;
100
+ }
101
+ if (menuConfig.copyAsMarkdown) {
102
+ [systemActions insertObject:copyMarkdownAction atIndex:insertIndex];
103
+ }
96
104
  [allActions addObjectsFromArray:systemActions];
97
105
 
98
106
  return [UIMenu menuWithChildren:allActions];
@@ -104,6 +112,8 @@
104
112
  return menu;
105
113
  }
106
114
 
115
+ ENRMInputSelectionMenuConfig menuConfig = [self inputSelectionMenuConfig];
116
+ ENRMFormatMenuConfig fmtConfig = [self formatMenuConfig];
107
117
  __weak EnrichedMarkdownTextInput *weakSelf = self;
108
118
  NSArray<NSMenuItem *> *customItems =
109
119
  ENRMBuildContextMenuItems([self contextMenuItemTexts], [self contextMenuItemIcons], textView,
@@ -114,41 +124,49 @@
114
124
 
115
125
  [menu addItem:[NSMenuItem separatorItem]];
116
126
 
117
- NSMenuItem *copyMarkdownItem = [[NSMenuItem alloc] initWithTitle:@"Copy as Markdown"
118
- action:@selector(copySelectedRangeAsMarkdown)
119
- keyEquivalent:@""];
120
- copyMarkdownItem.target = self;
121
- [menu addItem:copyMarkdownItem];
122
-
123
- NSMenu *formatSubmenu = [[NSMenu alloc] initWithTitle:@"Format"];
124
- struct {
125
- NSString *title;
126
- SEL action;
127
- NSString *key;
128
- NSEventModifierFlags modifiers;
129
- } const items[] = {
130
- {@"Bold", @selector(toggleBold), @"b", NSEventModifierFlagCommand},
131
- {@"Italic", @selector(toggleItalic), @"i", NSEventModifierFlagCommand},
132
- {@"Underline", @selector(toggleUnderline), @"u", NSEventModifierFlagCommand},
133
- {@"Strikethrough", @selector(toggleStrikethrough), @"", 0},
134
- {@"Spoiler", @selector(toggleSpoiler), @"", 0},
135
- {@"Link", @selector(showLinkPrompt), @"", 0},
136
- };
127
+ if (menuConfig.copyAsMarkdown) {
128
+ NSMenuItem *copyMarkdownItem = [[NSMenuItem alloc] initWithTitle:menuConfig.copyAsMarkdownLabel
129
+ action:@selector(copySelectedRangeAsMarkdown)
130
+ keyEquivalent:@""];
131
+ copyMarkdownItem.target = self;
132
+ [menu addItem:copyMarkdownItem];
133
+ }
137
134
 
138
- for (NSUInteger i = 0; i < sizeof(items) / sizeof(items[0]); i++) {
139
- NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:items[i].title
140
- action:items[i].action
141
- keyEquivalent:items[i].key];
142
- if (items[i].modifiers) {
143
- item.keyEquivalentModifierMask = items[i].modifiers;
135
+ if (menuConfig.format) {
136
+ NSMenu *formatSubmenu = [[NSMenu alloc] initWithTitle:menuConfig.formatLabel];
137
+ const struct {
138
+ NSString *title;
139
+ SEL action;
140
+ NSString *key;
141
+ NSEventModifierFlags modifiers;
142
+ BOOL visible;
143
+ } items[] = {
144
+ {fmtConfig.boldLabel, @selector(toggleBold), @"b", NSEventModifierFlagCommand, fmtConfig.bold},
145
+ {fmtConfig.italicLabel, @selector(toggleItalic), @"i", NSEventModifierFlagCommand, fmtConfig.italic},
146
+ {fmtConfig.underlineLabel, @selector(toggleUnderline), @"u", NSEventModifierFlagCommand, fmtConfig.underline},
147
+ {fmtConfig.strikethroughLabel, @selector(toggleStrikethrough), @"", 0, fmtConfig.strikethrough},
148
+ {fmtConfig.spoilerLabel, @selector(toggleSpoiler), @"", 0, fmtConfig.spoiler},
149
+ {fmtConfig.linkLabel, @selector(showLinkPrompt), @"", 0, fmtConfig.link},
150
+ };
151
+
152
+ for (NSUInteger i = 0; i < sizeof(items) / sizeof(items[0]); i++) {
153
+ if (!items[i].visible) {
154
+ continue;
155
+ }
156
+ NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:items[i].title
157
+ action:items[i].action
158
+ keyEquivalent:items[i].key];
159
+ if (items[i].modifiers) {
160
+ item.keyEquivalentModifierMask = items[i].modifiers;
161
+ }
162
+ item.target = self;
163
+ [formatSubmenu addItem:item];
144
164
  }
145
- item.target = self;
146
- [formatSubmenu addItem:item];
147
- }
148
165
 
149
- NSMenuItem *formatItem = [[NSMenuItem alloc] initWithTitle:@"Format" action:nil keyEquivalent:@""];
150
- formatItem.submenu = formatSubmenu;
151
- [menu addItem:formatItem];
166
+ NSMenuItem *formatItem = [[NSMenuItem alloc] initWithTitle:menuConfig.formatLabel action:nil keyEquivalent:@""];
167
+ formatItem.submenu = formatSubmenu;
168
+ [menu addItem:formatItem];
169
+ }
152
170
 
153
171
  return menu;
154
172
  }
@@ -5,6 +5,30 @@
5
5
 
6
6
  NS_ASSUME_NONNULL_BEGIN
7
7
 
8
+ // The owner must keep these strings alive for the duration of the call (the
9
+ // view holds them in strong ivars).
10
+ typedef struct {
11
+ BOOL format;
12
+ __unsafe_unretained NSString *_Nullable formatLabel;
13
+ BOOL copyAsMarkdown;
14
+ __unsafe_unretained NSString *_Nullable copyAsMarkdownLabel;
15
+ } ENRMInputSelectionMenuConfig;
16
+
17
+ typedef struct {
18
+ BOOL bold;
19
+ __unsafe_unretained NSString *_Nullable boldLabel;
20
+ BOOL italic;
21
+ __unsafe_unretained NSString *_Nullable italicLabel;
22
+ BOOL underline;
23
+ __unsafe_unretained NSString *_Nullable underlineLabel;
24
+ BOOL strikethrough;
25
+ __unsafe_unretained NSString *_Nullable strikethroughLabel;
26
+ BOOL spoiler;
27
+ __unsafe_unretained NSString *_Nullable spoilerLabel;
28
+ BOOL link;
29
+ __unsafe_unretained NSString *_Nullable linkLabel;
30
+ } ENRMFormatMenuConfig;
31
+
8
32
  @interface EnrichedMarkdownTextInput (Internal)
9
33
 
10
34
  - (void)toggleBold;
@@ -20,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN
20
44
  - (void)emitContextMenuItemPress:(NSString *)itemText;
21
45
  - (NSArray<NSString *> *)contextMenuItemTexts;
22
46
  - (NSArray<NSString *> *)contextMenuItemIcons;
47
+ - (ENRMInputSelectionMenuConfig)inputSelectionMenuConfig;
48
+ - (ENRMFormatMenuConfig)formatMenuConfig;
23
49
 
24
50
  #if TARGET_OS_OSX
25
51
  - (NSMenu *)enrichedMenuForEvent:(NSEvent *)event defaultMenu:(NSMenu *)menu textView:(NSTextView *)textView;
@@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN
10
10
  @property (nonatomic, assign) BOOL blockEmitting;
11
11
  - (CGSize)measureSize:(CGFloat)maxWidth;
12
12
  - (nullable NSString *)markdownForSelectedRange;
13
+ - (void)copyToClipboard;
13
14
  - (void)pasteMarkdown:(NSString *)markdown;
14
15
  - (void)replaceSelectedTextWith:(NSString *)text formattingRanges:(NSArray *)ranges;
15
16
  - (void)scheduleRelayoutIfNeeded;