react-native-enriched-markdown-scaffold 1.0.2-scaffold.1 → 1.0.2-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/android/build.gradle +2 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +18 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +4 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +18 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +4 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +148 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +120 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +30 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +210 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +176 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +45 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +112 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +34 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +46 -8
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyRequestEvent.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLayoutEvent.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/SelectionChangeEvent.kt +43 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +25 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +37 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +5 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +13 -99
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/InlineChipPainter.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkChipSpans.kt +177 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +1 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +16 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +36 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +7 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +51 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +34 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/HeadlessActionMode.kt +88 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLayoutCollector.kt +100 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +53 -14
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionChangeReporter.kt +232 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +64 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +29 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +30 -7
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +1 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +13 -6
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +2 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +25 -9
- package/docs/API_REFERENCE.md +183 -4
- package/docs/COPY_OPTIONS.md +40 -0
- package/docs/INPUT.md +3 -1
- package/docs/MENTIONS.md +8 -1
- package/docs/STYLES.md +27 -0
- package/docs/TEXT.md +2 -0
- package/docs/WEB.md +1 -0
- package/ios/EnrichedMarkdown.mm +321 -9
- package/ios/EnrichedMarkdownText.mm +203 -6
- package/ios/attachments/ENRMMathInlineAttachment+macOS.m +2 -1
- package/ios/attachments/ENRMMathInlineAttachment.h +3 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +2 -1
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +148 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +120 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +30 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +210 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +50 -2
- package/ios/internals/MeasurementCache.h +8 -2
- package/ios/math/ENRMRaTeXBridge.swift +23 -5
- package/ios/renderer/ENRMMathInlineRenderer.m +1 -0
- package/ios/renderer/LinkRenderer.m +47 -15
- package/ios/styles/StyleConfig.h +20 -0
- package/ios/styles/StyleConfig.mm +84 -0
- package/ios/utils/CodeBackground.m +3 -65
- package/ios/utils/ENRMBlockMenu.h +66 -0
- package/ios/utils/ENRMChipDrawing.h +24 -0
- package/ios/utils/ENRMChipDrawing.m +83 -0
- package/ios/utils/ENRMLinkChip.h +70 -0
- package/ios/utils/ENRMLinkChip.m +213 -0
- package/ios/utils/ENRMLinkLayout.h +50 -0
- package/ios/utils/ENRMLinkLayout.m +45 -0
- package/ios/utils/ENRMSelectionChange.h +120 -0
- package/ios/utils/ENRMSelectionChange.m +282 -0
- package/ios/utils/EditMenuUtils+macOS.m +4 -1
- package/ios/utils/EditMenuUtils.h +35 -6
- package/ios/utils/EditMenuUtils.m +171 -15
- package/ios/utils/HTMLGenerator.m +2 -1
- package/ios/utils/MarkdownAccessibilityElementBuilder.m +3 -1
- package/ios/utils/MarkdownExtractor.m +2 -1
- package/ios/utils/RTFExportUtils.m +2 -0
- package/ios/utils/StylePropsUtils.h +47 -1
- package/ios/utils/TextViewLayoutManager.mm +3 -0
- package/ios/views/ENRMCodeBlockContainerView.h +16 -2
- package/ios/views/ENRMCodeBlockContainerView.m +22 -19
- package/ios/views/ENRMMathContainerView.h +11 -0
- package/ios/views/ENRMMathContainerView.m +17 -20
- package/ios/views/TableContainerView.h +14 -0
- package/ios/views/TableContainerView.m +34 -18
- package/lib/module/EnrichedMarkdownNativeComponent.ts +138 -1
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +138 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest/index.js +14 -0
- package/lib/module/jest/index.js.map +1 -1
- package/lib/module/native/EnrichedMarkdownText.js +169 -11
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +17 -4
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +17 -4
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/web/EnrichedMarkdownText.js +6 -3
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +96 -3
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/styles.js +18 -0
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +13 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +123 -2
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +123 -2
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +1 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/jest/index.d.ts +1 -1
- package/lib/typescript/src/jest/index.d.ts.map +1 -1
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +5 -5
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +50 -5
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +12 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +144 -11
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +41 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +66 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +4 -0
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts +4 -0
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/EnrichedMarkdownNativeComponent.ts +138 -1
- package/src/EnrichedMarkdownTextNativeComponent.ts +138 -1
- package/src/index.tsx +6 -0
- package/src/index.web.tsx +5 -1
- package/src/jest/index.tsx +22 -1
- package/src/native/EnrichedMarkdownText.tsx +220 -9
- package/src/normalizeMarkdownStyle.ts +15 -0
- package/src/normalizeMarkdownStyle.web.ts +13 -0
- package/src/types/MarkdownStyle.ts +51 -5
- package/src/types/MarkdownStyleInternal.ts +12 -0
- package/src/types/MarkdownTextProps.ts +151 -11
- package/src/types/MarkdownTextProps.web.ts +43 -1
- package/src/types/events.ts +69 -0
- package/src/web/EnrichedMarkdownText.tsx +10 -3
- package/src/web/renderers/InlineRenderers.tsx +111 -3
- package/src/web/styles.ts +25 -0
- package/src/web/types.ts +4 -0
- package/src/web/utils.ts +8 -0
|
@@ -14,9 +14,33 @@
|
|
|
14
14
|
NS_ASSUME_NONNULL_BEGIN
|
|
15
15
|
|
|
16
16
|
@protocol RCTEnrichedMarkdownViewProtocol <NSObject>
|
|
17
|
-
|
|
17
|
+
- (void)clearSelection;
|
|
18
18
|
@end
|
|
19
19
|
|
|
20
|
+
RCT_EXTERN inline void RCTEnrichedMarkdownHandleCommand(
|
|
21
|
+
id<RCTEnrichedMarkdownViewProtocol> componentView,
|
|
22
|
+
NSString const *commandName,
|
|
23
|
+
NSArray const *args)
|
|
24
|
+
{
|
|
25
|
+
if ([commandName isEqualToString:@"clearSelection"]) {
|
|
26
|
+
#if RCT_DEBUG
|
|
27
|
+
if ([args count] != 0) {
|
|
28
|
+
RCTLogError(@"%@ command %@ received %d arguments, expected %d.", @"EnrichedMarkdown", commandName, (int)[args count], 0);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
[componentView clearSelection];
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#if RCT_DEBUG
|
|
40
|
+
RCTLogError(@"%@ received command %@, which is not a supported command.", @"EnrichedMarkdown", commandName);
|
|
41
|
+
#endif
|
|
42
|
+
}
|
|
43
|
+
|
|
20
44
|
@protocol RCTEnrichedMarkdownTextInputViewProtocol <NSObject>
|
|
21
45
|
- (void)focus;
|
|
22
46
|
- (void)blur;
|
|
@@ -576,7 +600,31 @@ if ([commandName isEqualToString:@"requestCaretRect"]) {
|
|
|
576
600
|
}
|
|
577
601
|
|
|
578
602
|
@protocol RCTEnrichedMarkdownTextViewProtocol <NSObject>
|
|
579
|
-
|
|
603
|
+
- (void)clearSelection;
|
|
580
604
|
@end
|
|
581
605
|
|
|
606
|
+
RCT_EXTERN inline void RCTEnrichedMarkdownTextHandleCommand(
|
|
607
|
+
id<RCTEnrichedMarkdownTextViewProtocol> componentView,
|
|
608
|
+
NSString const *commandName,
|
|
609
|
+
NSArray const *args)
|
|
610
|
+
{
|
|
611
|
+
if ([commandName isEqualToString:@"clearSelection"]) {
|
|
612
|
+
#if RCT_DEBUG
|
|
613
|
+
if ([args count] != 0) {
|
|
614
|
+
RCTLogError(@"%@ command %@ received %d arguments, expected %d.", @"EnrichedMarkdownText", commandName, (int)[args count], 0);
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
#endif
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
[componentView clearSelection];
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
#if RCT_DEBUG
|
|
626
|
+
RCTLogError(@"%@ received command %@, which is not a supported command.", @"EnrichedMarkdownText", commandName);
|
|
627
|
+
#endif
|
|
628
|
+
}
|
|
629
|
+
|
|
582
630
|
NS_ASSUME_NONNULL_END
|
|
@@ -128,6 +128,11 @@ template <typename StyleStruct> inline size_t computeStyleFingerprint(const Styl
|
|
|
128
128
|
s.codeBlock.borderWidth);
|
|
129
129
|
hashFields(s.code.fontFamily, s.code.fontSize);
|
|
130
130
|
hashFields(s.link.fontFamily, s.strong.fontFamily, s.strong.fontWeight, s.em.fontFamily, s.em.fontStyle);
|
|
131
|
+
// Link chip horizontal padding reserves space in the line; variants can set their own.
|
|
132
|
+
hashFields(s.link.paddingHorizontal);
|
|
133
|
+
for (const auto &variant : s.linkVariants) {
|
|
134
|
+
hashFields(variant.pattern, variant.paddingHorizontal);
|
|
135
|
+
}
|
|
131
136
|
hashFields(s.highlight.backgroundColor, s.highlight.color);
|
|
132
137
|
|
|
133
138
|
// Visual/Spacing Elements
|
|
@@ -139,8 +144,9 @@ template <typename StyleStruct> inline size_t computeStyleFingerprint(const Styl
|
|
|
139
144
|
hashTextLayout(s.table);
|
|
140
145
|
hashFields(s.table.headerFontFamily, s.table.cellPaddingHorizontal, s.table.cellPaddingVertical, s.table.borderWidth,
|
|
141
146
|
s.table.borderRadius, s.table.horizontalOverflow);
|
|
142
|
-
hashFields(s.math.fontSize, s.math.padding, s.math.marginTop, s.math.marginBottom, s.math.textAlign
|
|
143
|
-
|
|
147
|
+
hashFields(s.math.fontSize, s.math.padding, s.math.marginTop, s.math.marginBottom, s.math.textAlign,
|
|
148
|
+
s.math.glyphOverflow);
|
|
149
|
+
hashFields(s.inlineMath.paddingVertical, s.inlineMath.glyphOverflow);
|
|
144
150
|
hashFields(s.taskList.checkboxSize, s.taskList.checkboxBorderRadius);
|
|
145
151
|
|
|
146
152
|
return h;
|
|
@@ -42,23 +42,39 @@ public final class ENRMRaTeXRenderResult: NSObject {
|
|
|
42
42
|
/// Non-zero only in bold mode: half of it grows the glyph ink on each side.
|
|
43
43
|
private let boldStrokeWidth: CGFloat
|
|
44
44
|
private let boldStrokeColor: CGColor?
|
|
45
|
+
/// Headroom added above and below RaTeX's box. RaTeX sizes a formula by its TeX
|
|
46
|
+
/// metric box, which digit and capital outlines (and the bold stroke) overshoot;
|
|
47
|
+
/// every view and attachment clips to `totalHeight`, so that ink needs room inside it.
|
|
48
|
+
private let glyphOverflow: CGFloat
|
|
45
49
|
|
|
46
50
|
@objc public let width: CGFloat
|
|
47
51
|
@objc public let ascent: CGFloat
|
|
48
52
|
@objc public let descent: CGFloat
|
|
49
53
|
@objc public var totalHeight: CGFloat { ascent + descent }
|
|
50
54
|
|
|
51
|
-
init(renderer: RaTeXRenderer, boldStrokeWidth: CGFloat, boldStrokeColor: CGColor
|
|
55
|
+
init(renderer: RaTeXRenderer, boldStrokeWidth: CGFloat, boldStrokeColor: CGColor?, glyphOverflow: CGFloat) {
|
|
52
56
|
self.renderer = renderer
|
|
53
57
|
self.boldStrokeWidth = boldStrokeWidth
|
|
54
58
|
self.boldStrokeColor = boldStrokeColor
|
|
59
|
+
self.glyphOverflow = max(glyphOverflow, 0)
|
|
55
60
|
self.width = renderer.width
|
|
56
|
-
self.ascent = renderer.height
|
|
57
|
-
self.descent = renderer.depth
|
|
61
|
+
self.ascent = renderer.height + self.glyphOverflow
|
|
62
|
+
self.descent = renderer.depth + self.glyphOverflow
|
|
58
63
|
super.init()
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
@objc public func draw(in context: CGContext) {
|
|
67
|
+
guard glyphOverflow > 0 else {
|
|
68
|
+
drawFormula(in: context)
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
context.saveGState()
|
|
72
|
+
context.translateBy(x: 0, y: glyphOverflow)
|
|
73
|
+
drawFormula(in: context)
|
|
74
|
+
context.restoreGState()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private func drawFormula(in context: CGContext) {
|
|
62
78
|
guard boldStrokeWidth > 0, let boldStrokeColor else {
|
|
63
79
|
renderer.draw(in: context)
|
|
64
80
|
return
|
|
@@ -90,7 +106,8 @@ public final class ENRMRaTeXBridge: NSObject {
|
|
|
90
106
|
displayMode: Bool,
|
|
91
107
|
fontSize: CGFloat,
|
|
92
108
|
color: UIColor,
|
|
93
|
-
bold: Bool
|
|
109
|
+
bold: Bool,
|
|
110
|
+
glyphOverflow: CGFloat
|
|
94
111
|
) -> ENRMRaTeXRenderResult? {
|
|
95
112
|
RaTeXFontLoader.ensureLoaded()
|
|
96
113
|
do {
|
|
@@ -100,7 +117,8 @@ public final class ENRMRaTeXBridge: NSObject {
|
|
|
100
117
|
return ENRMRaTeXRenderResult(
|
|
101
118
|
renderer: renderer,
|
|
102
119
|
boldStrokeWidth: strokeWidth,
|
|
103
|
-
boldStrokeColor: strokeWidth > 0 ? color.cgColor : nil
|
|
120
|
+
boldStrokeColor: strokeWidth > 0 ? color.cgColor : nil,
|
|
121
|
+
glyphOverflow: glyphOverflow
|
|
104
122
|
)
|
|
105
123
|
} catch {
|
|
106
124
|
NSLog("[RaTeX] Failed to parse LaTeX: %@", error.localizedDescription)
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
attachment.mathTextColor = [_config inlineMathColor];
|
|
31
31
|
attachment.containerPaddingVertical = [_config inlineMathPaddingVertical];
|
|
32
32
|
attachment.bold = ENRMMathFontWeightIsBold([_config inlineMathFontWeight]);
|
|
33
|
+
attachment.glyphOverflow = [_config inlineMathGlyphOverflow];
|
|
33
34
|
|
|
34
35
|
#if TARGET_OS_OSX
|
|
35
36
|
// On macOS, NSLayoutManager uses self.image/self.bounds rather than calling
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "LinkRenderer.h"
|
|
2
|
+
#import "ENRMLinkChip.h"
|
|
2
3
|
#import "FontUtils.h"
|
|
3
4
|
#import "RenderContext.h"
|
|
4
5
|
#import "RendererFactory.h"
|
|
@@ -13,31 +14,49 @@
|
|
|
13
14
|
into:(NSMutableAttributedString *)output
|
|
14
15
|
context:(RenderContext *)context
|
|
15
16
|
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
// 1. Render children first to establish base attributes
|
|
19
|
-
[_rendererFactory renderChildrenOfNode:node into:output context:context];
|
|
20
|
-
|
|
21
|
-
NSRange range = NSMakeRange(start, output.length - start);
|
|
22
|
-
if (range.length == 0)
|
|
23
|
-
return;
|
|
24
|
-
|
|
25
|
-
// 2. Extract configuration
|
|
17
|
+
// 1. Extract configuration
|
|
26
18
|
NSString *url = node.attributes[@"url"] ?: @"";
|
|
27
19
|
LinkVariantConfig *variant = [_config effectiveLinkVariantForURL:url];
|
|
28
20
|
|
|
29
21
|
RCTUIColor *linkColor = variant.color ?: [_config linkColor];
|
|
30
22
|
BOOL linkUnderline = variant ? variant.underline : [_config linkUnderline];
|
|
31
23
|
NSString *linkFontFamily = [_config linkFontFamily];
|
|
32
|
-
|
|
24
|
+
// Chip ("box") properties never fall back to the base link style.
|
|
25
|
+
ENRMLinkChip *chip = [[ENRMLinkChip alloc] init];
|
|
26
|
+
chip.backgroundColor = variant ? variant.backgroundColor : [_config linkBackgroundColor];
|
|
27
|
+
chip.borderColor = variant ? variant.borderColor : [_config linkBorderColor];
|
|
28
|
+
chip.borderWidth = variant ? variant.borderWidth : [_config linkBorderWidth];
|
|
29
|
+
chip.borderRadius = variant ? variant.borderRadius : [_config linkBorderRadius];
|
|
30
|
+
chip.paddingHorizontal = variant ? variant.paddingHorizontal : [_config linkPaddingHorizontal];
|
|
31
|
+
chip.paddingVertical = variant ? variant.paddingVertical : [_config linkPaddingVertical];
|
|
32
|
+
BOOL hasSpacers = chip.paddingHorizontal > 0;
|
|
33
33
|
|
|
34
34
|
NSNumber *underlineStyle = @(linkUnderline ? NSUnderlineStyleSingle : NSUnderlineStyleNone);
|
|
35
35
|
|
|
36
|
+
// 2. Render children to establish base attributes. With horizontal padding, a
|
|
37
|
+
// leading spacer goes in first so ranges the children register stay valid;
|
|
38
|
+
// its attributes are fixed up once the first child glyph exists.
|
|
39
|
+
NSUInteger start = output.length;
|
|
40
|
+
if (hasSpacers) {
|
|
41
|
+
[output appendAttributedString:ENRMLinkSpacerString([context getTextAttributes], chip.paddingHorizontal)];
|
|
42
|
+
}
|
|
43
|
+
NSUInteger contentStart = output.length;
|
|
44
|
+
|
|
45
|
+
[_rendererFactory renderChildrenOfNode:node into:output context:context];
|
|
46
|
+
|
|
47
|
+
NSRange contentRange = NSMakeRange(contentStart, output.length - contentStart);
|
|
48
|
+
if (contentRange.length == 0) {
|
|
49
|
+
if (hasSpacers) {
|
|
50
|
+
[output deleteCharactersInRange:NSMakeRange(start, contentStart - start)];
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
36
55
|
// 3. Apply core link functionality (non-destructive)
|
|
37
|
-
[output addAttribute:NSLinkAttributeName value:url range:
|
|
56
|
+
[output addAttribute:NSLinkAttributeName value:url range:contentRange];
|
|
38
57
|
|
|
39
58
|
// 4. Optimize visual attributes via enumeration to avoid redundant updates
|
|
40
|
-
[output enumerateAttributesInRange:
|
|
59
|
+
[output enumerateAttributesInRange:contentRange
|
|
41
60
|
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
|
|
42
61
|
usingBlock:^(NSDictionary<NSAttributedStringKey, id> *attrs, NSRange subrange, BOOL *stop) {
|
|
43
62
|
NSMutableDictionary *newAttributes = [NSMutableDictionary dictionary];
|
|
@@ -74,10 +93,23 @@
|
|
|
74
93
|
}
|
|
75
94
|
}];
|
|
76
95
|
|
|
77
|
-
|
|
78
|
-
|
|
96
|
+
// 5. Reserve horizontal padding with a spacer at each outer edge (see
|
|
97
|
+
// ENRMLinkSpacerString). Spacers sit inside the link range, so tapping the
|
|
98
|
+
// padding hits the link.
|
|
99
|
+
NSRange range = contentRange;
|
|
100
|
+
if (hasSpacers) {
|
|
101
|
+
NSDictionary *firstAttrs = [output attributesAtIndex:contentRange.location effectiveRange:NULL];
|
|
102
|
+
NSDictionary *lastAttrs = [output attributesAtIndex:NSMaxRange(contentRange) - 1 effectiveRange:NULL];
|
|
103
|
+
NSAttributedString *leading = ENRMLinkSpacerString(firstAttrs, chip.paddingHorizontal);
|
|
104
|
+
[output setAttributes:[leading attributesAtIndex:0 effectiveRange:NULL] range:NSMakeRange(start, 1)];
|
|
105
|
+
[output appendAttributedString:ENRMLinkSpacerString(lastAttrs, chip.paddingHorizontal)];
|
|
106
|
+
range = NSMakeRange(start, output.length - start);
|
|
79
107
|
}
|
|
80
108
|
|
|
109
|
+
// 6. Chip background/border is drawn by the layout manager (see ENRMLinkChip).
|
|
110
|
+
// Attached even when invisible so the chip's padding is known to link-layout reporting.
|
|
111
|
+
[output addAttribute:ENRMLinkChipAttributeName value:chip range:range];
|
|
112
|
+
|
|
81
113
|
[context registerLinkRange:range url:url];
|
|
82
114
|
}
|
|
83
115
|
|
package/ios/styles/StyleConfig.h
CHANGED
|
@@ -13,6 +13,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
13
13
|
@property (nonatomic, strong) RCTUIColor *color;
|
|
14
14
|
@property (nonatomic, assign) BOOL underline;
|
|
15
15
|
@property (nonatomic, strong, nullable) RCTUIColor *backgroundColor;
|
|
16
|
+
// Chip ("box") properties — never inherited from the base link style.
|
|
17
|
+
@property (nonatomic, assign) CGFloat borderRadius;
|
|
18
|
+
@property (nonatomic, assign) CGFloat paddingHorizontal;
|
|
19
|
+
@property (nonatomic, assign) CGFloat paddingVertical;
|
|
20
|
+
@property (nonatomic, strong, nullable) RCTUIColor *borderColor;
|
|
21
|
+
@property (nonatomic, assign) CGFloat borderWidth;
|
|
16
22
|
@end
|
|
17
23
|
|
|
18
24
|
@interface StyleConfig : NSObject <NSCopying>
|
|
@@ -166,6 +172,16 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
166
172
|
- (void)setLinkUnderline:(BOOL)newValue;
|
|
167
173
|
- (nullable RCTUIColor *)linkBackgroundColor;
|
|
168
174
|
- (void)setLinkBackgroundColor:(nullable RCTUIColor *)newValue;
|
|
175
|
+
- (CGFloat)linkBorderRadius;
|
|
176
|
+
- (void)setLinkBorderRadius:(CGFloat)newValue;
|
|
177
|
+
- (CGFloat)linkPaddingHorizontal;
|
|
178
|
+
- (void)setLinkPaddingHorizontal:(CGFloat)newValue;
|
|
179
|
+
- (CGFloat)linkPaddingVertical;
|
|
180
|
+
- (void)setLinkPaddingVertical:(CGFloat)newValue;
|
|
181
|
+
- (nullable RCTUIColor *)linkBorderColor;
|
|
182
|
+
- (void)setLinkBorderColor:(nullable RCTUIColor *)newValue;
|
|
183
|
+
- (CGFloat)linkBorderWidth;
|
|
184
|
+
- (void)setLinkBorderWidth:(CGFloat)newValue;
|
|
169
185
|
- (NSArray<LinkVariantConfig *> *)linkVariants;
|
|
170
186
|
- (void)setLinkVariants:(NSArray<LinkVariantConfig *> *)newValue;
|
|
171
187
|
- (nullable LinkVariantConfig *)effectiveLinkVariantForURL:(NSString *)url;
|
|
@@ -402,6 +418,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
402
418
|
- (void)setMathTextAlign:(NSString *)newValue;
|
|
403
419
|
- (NSString *)mathFontWeight;
|
|
404
420
|
- (void)setMathFontWeight:(NSString *)newValue;
|
|
421
|
+
- (CGFloat)mathGlyphOverflow;
|
|
422
|
+
- (void)setMathGlyphOverflow:(CGFloat)newValue;
|
|
405
423
|
|
|
406
424
|
// Inline Math properties
|
|
407
425
|
- (RCTUIColor *)inlineMathColor;
|
|
@@ -410,6 +428,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
410
428
|
- (void)setInlineMathPaddingVertical:(CGFloat)newValue;
|
|
411
429
|
- (NSString *)inlineMathFontWeight;
|
|
412
430
|
- (void)setInlineMathFontWeight:(NSString *)newValue;
|
|
431
|
+
- (CGFloat)inlineMathGlyphOverflow;
|
|
432
|
+
- (void)setInlineMathGlyphOverflow:(CGFloat)newValue;
|
|
413
433
|
// Spoiler properties
|
|
414
434
|
- (RCTUIColor *)spoilerColor;
|
|
415
435
|
- (void)setSpoilerColor:(RCTUIColor *)newValue;
|
|
@@ -113,6 +113,11 @@ static inline NSString *normalizedFontWeight(NSString *fontWeight)
|
|
|
113
113
|
RCTUIColor *_linkColor;
|
|
114
114
|
BOOL _linkUnderline;
|
|
115
115
|
RCTUIColor *_linkBackgroundColor;
|
|
116
|
+
CGFloat _linkBorderRadius;
|
|
117
|
+
CGFloat _linkPaddingHorizontal;
|
|
118
|
+
CGFloat _linkPaddingVertical;
|
|
119
|
+
RCTUIColor *_linkBorderColor;
|
|
120
|
+
CGFloat _linkBorderWidth;
|
|
116
121
|
NSArray<LinkVariantConfig *> *_linkVariants;
|
|
117
122
|
NSArray<LinkVariantRegexEntry *> *_compiledVariantRegexes;
|
|
118
123
|
// Strong properties
|
|
@@ -239,10 +244,12 @@ static inline NSString *normalizedFontWeight(NSString *fontWeight)
|
|
|
239
244
|
CGFloat _mathMarginBottom;
|
|
240
245
|
NSString *_mathTextAlign;
|
|
241
246
|
NSString *_mathFontWeight;
|
|
247
|
+
CGFloat _mathGlyphOverflow;
|
|
242
248
|
// Inline Math properties
|
|
243
249
|
RCTUIColor *_inlineMathColor;
|
|
244
250
|
CGFloat _inlineMathPaddingVertical;
|
|
245
251
|
NSString *_inlineMathFontWeight;
|
|
252
|
+
CGFloat _inlineMathGlyphOverflow;
|
|
246
253
|
// Spoiler properties
|
|
247
254
|
RCTUIColor *_spoilerColor;
|
|
248
255
|
CGFloat _spoilerParticleDensity;
|
|
@@ -405,6 +412,11 @@ static inline NSString *normalizedFontWeight(NSString *fontWeight)
|
|
|
405
412
|
copy->_linkColor = [_linkColor copy];
|
|
406
413
|
copy->_linkUnderline = _linkUnderline;
|
|
407
414
|
copy->_linkBackgroundColor = [_linkBackgroundColor copy];
|
|
415
|
+
copy->_linkBorderRadius = _linkBorderRadius;
|
|
416
|
+
copy->_linkPaddingHorizontal = _linkPaddingHorizontal;
|
|
417
|
+
copy->_linkPaddingVertical = _linkPaddingVertical;
|
|
418
|
+
copy->_linkBorderColor = [_linkBorderColor copy];
|
|
419
|
+
copy->_linkBorderWidth = _linkBorderWidth;
|
|
408
420
|
copy->_linkVariants = [_linkVariants copy];
|
|
409
421
|
copy->_compiledVariantRegexes = [_compiledVariantRegexes copy];
|
|
410
422
|
copy->_strongFontFamily = [_strongFontFamily copy];
|
|
@@ -512,9 +524,11 @@ static inline NSString *normalizedFontWeight(NSString *fontWeight)
|
|
|
512
524
|
copy->_mathMarginBottom = _mathMarginBottom;
|
|
513
525
|
copy->_mathTextAlign = [_mathTextAlign copy];
|
|
514
526
|
copy->_mathFontWeight = [_mathFontWeight copy];
|
|
527
|
+
copy->_mathGlyphOverflow = _mathGlyphOverflow;
|
|
515
528
|
copy->_inlineMathColor = [_inlineMathColor copy];
|
|
516
529
|
copy->_inlineMathPaddingVertical = _inlineMathPaddingVertical;
|
|
517
530
|
copy->_inlineMathFontWeight = [_inlineMathFontWeight copy];
|
|
531
|
+
copy->_inlineMathGlyphOverflow = _inlineMathGlyphOverflow;
|
|
518
532
|
copy->_spoilerColor = [_spoilerColor copy];
|
|
519
533
|
copy->_spoilerParticleDensity = _spoilerParticleDensity;
|
|
520
534
|
copy->_spoilerParticleSpeed = _spoilerParticleSpeed;
|
|
@@ -1334,6 +1348,56 @@ static inline NSString *normalizedFontWeight(NSString *fontWeight)
|
|
|
1334
1348
|
_linkBackgroundColor = newValue;
|
|
1335
1349
|
}
|
|
1336
1350
|
|
|
1351
|
+
- (CGFloat)linkBorderRadius
|
|
1352
|
+
{
|
|
1353
|
+
return _linkBorderRadius;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
- (void)setLinkBorderRadius:(CGFloat)newValue
|
|
1357
|
+
{
|
|
1358
|
+
_linkBorderRadius = newValue;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
- (CGFloat)linkPaddingHorizontal
|
|
1362
|
+
{
|
|
1363
|
+
return _linkPaddingHorizontal;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
- (void)setLinkPaddingHorizontal:(CGFloat)newValue
|
|
1367
|
+
{
|
|
1368
|
+
_linkPaddingHorizontal = newValue;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
- (CGFloat)linkPaddingVertical
|
|
1372
|
+
{
|
|
1373
|
+
return _linkPaddingVertical;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
- (void)setLinkPaddingVertical:(CGFloat)newValue
|
|
1377
|
+
{
|
|
1378
|
+
_linkPaddingVertical = newValue;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
- (RCTUIColor *)linkBorderColor
|
|
1382
|
+
{
|
|
1383
|
+
return _linkBorderColor;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
- (void)setLinkBorderColor:(RCTUIColor *)newValue
|
|
1387
|
+
{
|
|
1388
|
+
_linkBorderColor = newValue;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
- (CGFloat)linkBorderWidth
|
|
1392
|
+
{
|
|
1393
|
+
return _linkBorderWidth;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
- (void)setLinkBorderWidth:(CGFloat)newValue
|
|
1397
|
+
{
|
|
1398
|
+
_linkBorderWidth = newValue;
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1337
1401
|
- (NSArray<LinkVariantConfig *> *)linkVariants
|
|
1338
1402
|
{
|
|
1339
1403
|
return _linkVariants;
|
|
@@ -2598,6 +2662,26 @@ static const CGFloat kDefaultMinGap = 4.0;
|
|
|
2598
2662
|
_inlineMathPaddingVertical = newValue;
|
|
2599
2663
|
}
|
|
2600
2664
|
|
|
2665
|
+
- (CGFloat)mathGlyphOverflow
|
|
2666
|
+
{
|
|
2667
|
+
return _mathGlyphOverflow;
|
|
2668
|
+
}
|
|
2669
|
+
|
|
2670
|
+
- (void)setMathGlyphOverflow:(CGFloat)newValue
|
|
2671
|
+
{
|
|
2672
|
+
_mathGlyphOverflow = newValue;
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2675
|
+
- (CGFloat)inlineMathGlyphOverflow
|
|
2676
|
+
{
|
|
2677
|
+
return _inlineMathGlyphOverflow;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
- (void)setInlineMathGlyphOverflow:(CGFloat)newValue
|
|
2681
|
+
{
|
|
2682
|
+
_inlineMathGlyphOverflow = newValue;
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2601
2685
|
// ── Spoiler ─────────────────────────────────────────────────────────────
|
|
2602
2686
|
|
|
2603
2687
|
- (RCTUIColor *)spoilerColor
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "CodeBackground.h"
|
|
2
|
+
#import "ENRMChipDrawing.h"
|
|
2
3
|
#import "ENRMUIKit.h"
|
|
3
4
|
#import "RenderContext.h"
|
|
4
5
|
|
|
@@ -116,71 +117,8 @@ static const CGFloat kCodeBackgroundBorderWidth = 0.5;
|
|
|
116
117
|
isFirst:(BOOL)isFirst
|
|
117
118
|
isLast:(BOOL)isLast
|
|
118
119
|
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
[path fill];
|
|
122
|
-
|
|
123
|
-
if (borderColor) {
|
|
124
|
-
[borderColor setStroke];
|
|
125
|
-
UIBezierPath *strokePath =
|
|
126
|
-
(isFirst && isLast) ? path : [self openBorderPathForRect:rect isFirst:isFirst isLast:isLast];
|
|
127
|
-
strokePath.lineWidth = kCodeBackgroundBorderWidth;
|
|
128
|
-
BezierPathSetRoundStyle(strokePath);
|
|
129
|
-
[strokePath stroke];
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
- (UIBezierPath *)pathForRect:(CGRect)rect isFirst:(BOOL)isFirst isLast:(BOOL)isLast
|
|
134
|
-
{
|
|
135
|
-
#if !TARGET_OS_OSX
|
|
136
|
-
UIRectCorner corners = 0;
|
|
137
|
-
if (isFirst)
|
|
138
|
-
corners |= (UIRectCornerTopLeft | UIRectCornerBottomLeft);
|
|
139
|
-
if (isLast)
|
|
140
|
-
corners |= (UIRectCornerTopRight | UIRectCornerBottomRight);
|
|
141
|
-
|
|
142
|
-
return [UIBezierPath bezierPathWithRoundedRect:rect
|
|
143
|
-
byRoundingCorners:corners
|
|
144
|
-
cornerRadii:CGSizeMake(kCodeBackgroundCornerRadius, kCodeBackgroundCornerRadius)];
|
|
145
|
-
#else
|
|
146
|
-
// NSBezierPath doesn't support per-corner rounding — use uniform corner radius
|
|
147
|
-
CGFloat cornerRadius = (isFirst || isLast) ? kCodeBackgroundCornerRadius : 0;
|
|
148
|
-
return UIBezierPathWithRoundedRect(rect, cornerRadius);
|
|
149
|
-
#endif
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
- (UIBezierPath *)openBorderPathForRect:(CGRect)rect isFirst:(BOOL)isFirst isLast:(BOOL)isLast
|
|
153
|
-
{
|
|
154
|
-
UIBezierPath *path = [UIBezierPath bezierPath];
|
|
155
|
-
CGFloat r = kCodeBackgroundCornerRadius;
|
|
156
|
-
CGFloat inset = kCodeBackgroundBorderWidth / 2.0;
|
|
157
|
-
CGRect insetRect = CGRectInset(rect, inset, inset);
|
|
158
|
-
|
|
159
|
-
if (isFirst) {
|
|
160
|
-
[path moveToPoint:CGPointMake(CGRectGetMaxX(rect), insetRect.origin.y)];
|
|
161
|
-
BezierPathAddLine(path, CGPointMake(insetRect.origin.x + r, insetRect.origin.y));
|
|
162
|
-
BezierPathAddQuadCurve(path, CGPointMake(insetRect.origin.x, insetRect.origin.y + r),
|
|
163
|
-
CGPointMake(insetRect.origin.x, insetRect.origin.y));
|
|
164
|
-
BezierPathAddLine(path, CGPointMake(insetRect.origin.x, CGRectGetMaxY(insetRect) - r));
|
|
165
|
-
BezierPathAddQuadCurve(path, CGPointMake(insetRect.origin.x + r, CGRectGetMaxY(insetRect)),
|
|
166
|
-
CGPointMake(insetRect.origin.x, CGRectGetMaxY(insetRect)));
|
|
167
|
-
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(insetRect)));
|
|
168
|
-
} else if (isLast) {
|
|
169
|
-
[path moveToPoint:CGPointMake(rect.origin.x, insetRect.origin.y)];
|
|
170
|
-
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(insetRect) - r, insetRect.origin.y));
|
|
171
|
-
BezierPathAddQuadCurve(path, CGPointMake(CGRectGetMaxX(insetRect), insetRect.origin.y + r),
|
|
172
|
-
CGPointMake(CGRectGetMaxX(insetRect), insetRect.origin.y));
|
|
173
|
-
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(insetRect), CGRectGetMaxY(insetRect) - r));
|
|
174
|
-
BezierPathAddQuadCurve(path, CGPointMake(CGRectGetMaxX(insetRect) - r, CGRectGetMaxY(insetRect)),
|
|
175
|
-
CGPointMake(CGRectGetMaxX(insetRect), CGRectGetMaxY(insetRect)));
|
|
176
|
-
BezierPathAddLine(path, CGPointMake(rect.origin.x, CGRectGetMaxY(insetRect)));
|
|
177
|
-
} else {
|
|
178
|
-
[path moveToPoint:CGPointMake(rect.origin.x, insetRect.origin.y)];
|
|
179
|
-
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), insetRect.origin.y));
|
|
180
|
-
[path moveToPoint:CGPointMake(rect.origin.x, CGRectGetMaxY(insetRect))];
|
|
181
|
-
BezierPathAddLine(path, CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(insetRect)));
|
|
182
|
-
}
|
|
183
|
-
return path;
|
|
120
|
+
ENRMDrawChipFragment(rect, backgroundColor, borderColor, kCodeBackgroundBorderWidth, kCodeBackgroundCornerRadius,
|
|
121
|
+
isFirst, isLast, NO);
|
|
184
122
|
}
|
|
185
123
|
|
|
186
124
|
#pragma mark - Helpers
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
#include <TargetConditionals.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
/// Selection-menu options that table, math and code block views need for their
|
|
8
|
+
/// own long-press menus. Every field is phrased so that the zero value keeps the
|
|
9
|
+
/// legacy behavior, so a block view that has not received options yet behaves
|
|
10
|
+
/// exactly as before.
|
|
11
|
+
typedef struct {
|
|
12
|
+
// `selectionMenuConfig.copy.enabled == false`.
|
|
13
|
+
BOOL copyHidden;
|
|
14
|
+
// `selectionMenuConfig.copy.format == 'markdown'`: the Copy item writes the
|
|
15
|
+
// block's Markdown instead of its raw content.
|
|
16
|
+
BOOL copyWritesMarkdown;
|
|
17
|
+
// `selectionMenuConfig.copyAsMarkdown.enabled == false`.
|
|
18
|
+
BOOL copyAsMarkdownHidden;
|
|
19
|
+
// `selectionMenuConfig.codeBlockCopyButton.enabled == false`.
|
|
20
|
+
BOOL copyButtonHidden;
|
|
21
|
+
// JS `onCopy` is set: the Copy item hands the block's content to the view's
|
|
22
|
+
// `onCopyRequest` instead of writing the pasteboard.
|
|
23
|
+
BOOL interceptCopy;
|
|
24
|
+
} ENRMBlockMenuOptions;
|
|
25
|
+
|
|
26
|
+
/// Receives an intercepted block Copy: the block's Markdown and its raw content.
|
|
27
|
+
typedef void (^ENRMBlockCopyRequestBlock)(NSString *markdown, NSString *text);
|
|
28
|
+
|
|
29
|
+
#if !TARGET_OS_OSX
|
|
30
|
+
/// Builds the long-press menu shared by the table, math and code block views.
|
|
31
|
+
/// Returns nil when no item is left — nil is how UIKit suppresses a context
|
|
32
|
+
/// menu, whereas an empty menu would still lift the view. `requestCopy` replaces
|
|
33
|
+
/// the Copy item's handler when `options.interceptCopy` is set.
|
|
34
|
+
static inline UIContextMenuConfiguration *_Nullable ENRMBlockContextMenuConfiguration(
|
|
35
|
+
ENRMBlockMenuOptions options, NSString *_Nullable copyLabel, NSString *_Nullable copyAsMarkdownLabel,
|
|
36
|
+
void (^copyRaw)(void), void (^copyMarkdown)(void), void (^_Nullable requestCopy)(void))
|
|
37
|
+
{
|
|
38
|
+
if (options.copyHidden && options.copyAsMarkdownHidden) {
|
|
39
|
+
return nil;
|
|
40
|
+
}
|
|
41
|
+
void (^copyHandler)(void) = (options.interceptCopy && requestCopy) ? requestCopy
|
|
42
|
+
: options.copyWritesMarkdown ? copyMarkdown
|
|
43
|
+
: copyRaw;
|
|
44
|
+
return [UIContextMenuConfiguration
|
|
45
|
+
configurationWithIdentifier:nil
|
|
46
|
+
previewProvider:nil
|
|
47
|
+
actionProvider:^UIMenu *(NSArray<UIMenuElement *> *suggestedActions) {
|
|
48
|
+
NSMutableArray<UIMenuElement *> *children = [NSMutableArray arrayWithCapacity:2];
|
|
49
|
+
if (!options.copyHidden) {
|
|
50
|
+
[children addObject:[UIAction actionWithTitle:copyLabel ?: @""
|
|
51
|
+
image:[RCTUIImage systemImageNamed:@"doc.on.doc"]
|
|
52
|
+
identifier:nil
|
|
53
|
+
handler:^(__kindof UIAction *action) { copyHandler(); }]];
|
|
54
|
+
}
|
|
55
|
+
if (!options.copyAsMarkdownHidden) {
|
|
56
|
+
[children addObject:[UIAction actionWithTitle:copyAsMarkdownLabel ?: @""
|
|
57
|
+
image:[RCTUIImage systemImageNamed:@"doc.text"]
|
|
58
|
+
identifier:nil
|
|
59
|
+
handler:^(__kindof UIAction *action) { copyMarkdown(); }]];
|
|
60
|
+
}
|
|
61
|
+
return [UIMenu menuWithTitle:@"" children:children];
|
|
62
|
+
}];
|
|
63
|
+
}
|
|
64
|
+
#endif
|
|
65
|
+
|
|
66
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
#ifdef __cplusplus
|
|
7
|
+
extern "C" {
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
/// Fills (and optionally strokes) one line fragment of an inline "chip" — the
|
|
11
|
+
/// rounded background shared by inline code and link chips. For a chip that
|
|
12
|
+
/// wraps, only the outer ends are rounded (`isFirst` / `isLast`) and the border
|
|
13
|
+
/// stays open where the fragment is cut.
|
|
14
|
+
///
|
|
15
|
+
/// `strokeInset` keeps a closed border inside `rect` (link chips); otherwise it
|
|
16
|
+
/// is centered on the edge (inline code, kept for pixel parity).
|
|
17
|
+
void ENRMDrawChipFragment(CGRect rect, RCTUIColor *_Nullable backgroundColor, RCTUIColor *_Nullable borderColor,
|
|
18
|
+
CGFloat borderWidth, CGFloat cornerRadius, BOOL isFirst, BOOL isLast, BOOL strokeInset);
|
|
19
|
+
|
|
20
|
+
#ifdef __cplusplus
|
|
21
|
+
}
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
NS_ASSUME_NONNULL_END
|