react-native-enriched-markdown-scaffold 1.0.2-scaffold.3 → 1.0.2-scaffold.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +1 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +1 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +48 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +32 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +10 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +122 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +8 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +8 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLayoutEvent.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +37 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +5 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +13 -99
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/InlineChipPainter.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkChipSpans.kt +177 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +1 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +36 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +7 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLayoutCollector.kt +100 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +4 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +14 -0
- package/docs/API_REFERENCE.md +53 -0
- package/docs/MENTIONS.md +8 -1
- package/docs/STYLES.md +27 -0
- package/docs/TEXT.md +2 -0
- package/ios/EnrichedMarkdown.mm +48 -0
- package/ios/EnrichedMarkdownText.mm +39 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +48 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +32 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +10 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +122 -0
- package/ios/internals/MeasurementCache.h +5 -0
- package/ios/renderer/LinkRenderer.m +47 -15
- package/ios/styles/StyleConfig.h +16 -0
- package/ios/styles/StyleConfig.mm +60 -0
- package/ios/utils/CodeBackground.m +3 -65
- package/ios/utils/ENRMChipDrawing.h +24 -0
- package/ios/utils/ENRMChipDrawing.m +83 -0
- package/ios/utils/ENRMLinkChip.h +70 -0
- package/ios/utils/ENRMLinkChip.m +194 -0
- package/ios/utils/ENRMLinkLayout.h +50 -0
- package/ios/utils/ENRMLinkLayout.m +45 -0
- package/ios/utils/EditMenuUtils+macOS.m +4 -1
- package/ios/utils/EditMenuUtils.m +4 -1
- package/ios/utils/HTMLGenerator.m +2 -1
- package/ios/utils/MarkdownAccessibilityElementBuilder.m +4 -1
- package/ios/utils/MarkdownExtractor.m +2 -1
- package/ios/utils/RTFExportUtils.m +2 -0
- package/ios/utils/StylePropsUtils.h +37 -1
- package/ios/utils/TextViewLayoutManager.mm +3 -0
- package/ios/views/TableContainerView.h +3 -0
- package/ios/views/TableContainerView.m +21 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +41 -0
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +41 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/EnrichedMarkdownText.js +96 -7
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +13 -2
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +13 -2
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/web/EnrichedMarkdownText.js +6 -3
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +96 -3
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/styles.js +18 -0
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +13 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +40 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +40 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +1 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +28 -5
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +10 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +41 -0
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +41 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +4 -0
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts +4 -0
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/EnrichedMarkdownNativeComponent.ts +41 -0
- package/src/EnrichedMarkdownTextNativeComponent.ts +41 -0
- package/src/index.tsx +2 -0
- package/src/index.web.tsx +5 -1
- package/src/native/EnrichedMarkdownText.tsx +103 -6
- package/src/normalizeMarkdownStyle.ts +13 -0
- package/src/normalizeMarkdownStyle.web.ts +11 -0
- package/src/types/MarkdownStyle.ts +29 -5
- package/src/types/MarkdownStyleInternal.ts +10 -0
- package/src/types/MarkdownTextProps.ts +43 -0
- package/src/types/MarkdownTextProps.web.ts +43 -1
- package/src/web/EnrichedMarkdownText.tsx +10 -3
- package/src/web/renderers/InlineRenderers.tsx +111 -3
- package/src/web/styles.ts +25 -0
- package/src/web/types.ts +4 -0
- package/src/web/utils.ts +8 -0
package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java
CHANGED
|
@@ -32,6 +32,9 @@ public class EnrichedMarkdownManagerDelegate<T extends View, U extends BaseViewM
|
|
|
32
32
|
case "markdownStyle":
|
|
33
33
|
mViewManager.setMarkdownStyle(view, (ReadableMap) value);
|
|
34
34
|
break;
|
|
35
|
+
case "emitLinkLayout":
|
|
36
|
+
mViewManager.setEmitLinkLayout(view, value == null ? false : (boolean) value);
|
|
37
|
+
break;
|
|
35
38
|
case "enableTaskListItemToggle":
|
|
36
39
|
mViewManager.setEnableTaskListItemToggle(view, value == null ? true : (boolean) value);
|
|
37
40
|
break;
|
package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java
CHANGED
|
@@ -18,6 +18,7 @@ import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;
|
|
|
18
18
|
public interface EnrichedMarkdownManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {
|
|
19
19
|
void setMarkdown(T view, @Nullable String value);
|
|
20
20
|
void setMarkdownStyle(T view, @Nullable ReadableMap value);
|
|
21
|
+
void setEmitLinkLayout(T view, boolean value);
|
|
21
22
|
void setEnableTaskListItemToggle(T view, boolean value);
|
|
22
23
|
void setEnableLinkPreview(T view, boolean value);
|
|
23
24
|
void setSelectable(T view, boolean value);
|
|
@@ -32,6 +32,9 @@ public class EnrichedMarkdownTextManagerDelegate<T extends View, U extends BaseV
|
|
|
32
32
|
case "markdownStyle":
|
|
33
33
|
mViewManager.setMarkdownStyle(view, (ReadableMap) value);
|
|
34
34
|
break;
|
|
35
|
+
case "emitLinkLayout":
|
|
36
|
+
mViewManager.setEmitLinkLayout(view, value == null ? false : (boolean) value);
|
|
37
|
+
break;
|
|
35
38
|
case "enableTaskListItemToggle":
|
|
36
39
|
mViewManager.setEnableTaskListItemToggle(view, value == null ? true : (boolean) value);
|
|
37
40
|
break;
|
|
@@ -18,6 +18,7 @@ import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;
|
|
|
18
18
|
public interface EnrichedMarkdownTextManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {
|
|
19
19
|
void setMarkdown(T view, @Nullable String value);
|
|
20
20
|
void setMarkdownStyle(T view, @Nullable ReadableMap value);
|
|
21
|
+
void setEmitLinkLayout(T view, boolean value);
|
|
21
22
|
void setEnableTaskListItemToggle(T view, boolean value);
|
|
22
23
|
void setEnableLinkPreview(T view, boolean value);
|
|
23
24
|
void setSelectable(T view, boolean value);
|
package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp
CHANGED
|
@@ -31,6 +31,30 @@ void EnrichedMarkdownEventEmitter::onLinkLongPress(OnLinkLongPress event) const
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
void EnrichedMarkdownEventEmitter::onLinkLayout(OnLinkLayout event) const {
|
|
35
|
+
dispatchEvent("linkLayout", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
36
|
+
auto payload = jsi::Object(runtime);
|
|
37
|
+
|
|
38
|
+
auto fragments = jsi::Array(runtime, event.fragments.size());
|
|
39
|
+
size_t fragmentsIndex = 0;
|
|
40
|
+
for (auto fragmentsValue : event.fragments) {
|
|
41
|
+
auto fragmentsObject = jsi::Object(runtime);
|
|
42
|
+
fragmentsObject.setProperty(runtime, "linkIndex", fragmentsValue.linkIndex);
|
|
43
|
+
fragmentsObject.setProperty(runtime, "url", fragmentsValue.url);
|
|
44
|
+
fragmentsObject.setProperty(runtime, "text", fragmentsValue.text);
|
|
45
|
+
fragmentsObject.setProperty(runtime, "x", fragmentsValue.x);
|
|
46
|
+
fragmentsObject.setProperty(runtime, "y", fragmentsValue.y);
|
|
47
|
+
fragmentsObject.setProperty(runtime, "width", fragmentsValue.width);
|
|
48
|
+
fragmentsObject.setProperty(runtime, "height", fragmentsValue.height);
|
|
49
|
+
fragments.setValueAtIndex(runtime, fragmentsIndex++, fragmentsObject);
|
|
50
|
+
}
|
|
51
|
+
payload.setProperty(runtime, "fragments", fragments);
|
|
52
|
+
|
|
53
|
+
return payload;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
34
58
|
void EnrichedMarkdownEventEmitter::onTaskListItemPress(OnTaskListItemPress event) const {
|
|
35
59
|
dispatchEvent("taskListItemPress", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
36
60
|
auto payload = jsi::Object(runtime);
|
|
@@ -370,6 +394,30 @@ void EnrichedMarkdownTextEventEmitter::onLinkLongPress(OnLinkLongPress event) co
|
|
|
370
394
|
}
|
|
371
395
|
|
|
372
396
|
|
|
397
|
+
void EnrichedMarkdownTextEventEmitter::onLinkLayout(OnLinkLayout event) const {
|
|
398
|
+
dispatchEvent("linkLayout", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
399
|
+
auto payload = jsi::Object(runtime);
|
|
400
|
+
|
|
401
|
+
auto fragments = jsi::Array(runtime, event.fragments.size());
|
|
402
|
+
size_t fragmentsIndex = 0;
|
|
403
|
+
for (auto fragmentsValue : event.fragments) {
|
|
404
|
+
auto fragmentsObject = jsi::Object(runtime);
|
|
405
|
+
fragmentsObject.setProperty(runtime, "linkIndex", fragmentsValue.linkIndex);
|
|
406
|
+
fragmentsObject.setProperty(runtime, "url", fragmentsValue.url);
|
|
407
|
+
fragmentsObject.setProperty(runtime, "text", fragmentsValue.text);
|
|
408
|
+
fragmentsObject.setProperty(runtime, "x", fragmentsValue.x);
|
|
409
|
+
fragmentsObject.setProperty(runtime, "y", fragmentsValue.y);
|
|
410
|
+
fragmentsObject.setProperty(runtime, "width", fragmentsValue.width);
|
|
411
|
+
fragmentsObject.setProperty(runtime, "height", fragmentsValue.height);
|
|
412
|
+
fragments.setValueAtIndex(runtime, fragmentsIndex++, fragmentsObject);
|
|
413
|
+
}
|
|
414
|
+
payload.setProperty(runtime, "fragments", fragments);
|
|
415
|
+
|
|
416
|
+
return payload;
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
|
|
373
421
|
void EnrichedMarkdownTextEventEmitter::onTaskListItemPress(OnTaskListItemPress event) const {
|
|
374
422
|
dispatchEvent("taskListItemPress", [event=std::move(event)](jsi::Runtime &runtime) {
|
|
375
423
|
auto payload = jsi::Object(runtime);
|
package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h
CHANGED
|
@@ -25,6 +25,20 @@ class EnrichedMarkdownEventEmitter : public ViewEventEmitter {
|
|
|
25
25
|
std::string url;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
struct OnLinkLayoutFragments {
|
|
29
|
+
int linkIndex;
|
|
30
|
+
std::string url;
|
|
31
|
+
std::string text;
|
|
32
|
+
double x;
|
|
33
|
+
double y;
|
|
34
|
+
double width;
|
|
35
|
+
double height;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
struct OnLinkLayout {
|
|
39
|
+
std::vector<OnLinkLayoutFragments> fragments;
|
|
40
|
+
};
|
|
41
|
+
|
|
28
42
|
struct OnTaskListItemPress {
|
|
29
43
|
int index;
|
|
30
44
|
bool checked;
|
|
@@ -53,6 +67,8 @@ class EnrichedMarkdownEventEmitter : public ViewEventEmitter {
|
|
|
53
67
|
|
|
54
68
|
void onLinkLongPress(OnLinkLongPress value) const;
|
|
55
69
|
|
|
70
|
+
void onLinkLayout(OnLinkLayout value) const;
|
|
71
|
+
|
|
56
72
|
void onTaskListItemPress(OnTaskListItemPress value) const;
|
|
57
73
|
|
|
58
74
|
void onCopyPress(OnCopyPress value) const;
|
|
@@ -301,6 +317,20 @@ class EnrichedMarkdownTextEventEmitter : public ViewEventEmitter {
|
|
|
301
317
|
std::string url;
|
|
302
318
|
};
|
|
303
319
|
|
|
320
|
+
struct OnLinkLayoutFragments {
|
|
321
|
+
int linkIndex;
|
|
322
|
+
std::string url;
|
|
323
|
+
std::string text;
|
|
324
|
+
double x;
|
|
325
|
+
double y;
|
|
326
|
+
double width;
|
|
327
|
+
double height;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
struct OnLinkLayout {
|
|
331
|
+
std::vector<OnLinkLayoutFragments> fragments;
|
|
332
|
+
};
|
|
333
|
+
|
|
304
334
|
struct OnTaskListItemPress {
|
|
305
335
|
int index;
|
|
306
336
|
bool checked;
|
|
@@ -329,6 +359,8 @@ class EnrichedMarkdownTextEventEmitter : public ViewEventEmitter {
|
|
|
329
359
|
|
|
330
360
|
void onLinkLongPress(OnLinkLongPress value) const;
|
|
331
361
|
|
|
362
|
+
void onLinkLayout(OnLinkLayout value) const;
|
|
363
|
+
|
|
332
364
|
void onTaskListItemPress(OnTaskListItemPress value) const;
|
|
333
365
|
|
|
334
366
|
void onCopyPress(OnCopyPress value) const;
|
|
@@ -21,6 +21,7 @@ EnrichedMarkdownProps::EnrichedMarkdownProps(
|
|
|
21
21
|
|
|
22
22
|
markdown(convertRawProp(context, rawProps, "markdown", sourceProps.markdown, {})),
|
|
23
23
|
markdownStyle(convertRawProp(context, rawProps, "markdownStyle", sourceProps.markdownStyle, {})),
|
|
24
|
+
emitLinkLayout(convertRawProp(context, rawProps, "emitLinkLayout", sourceProps.emitLinkLayout, {false})),
|
|
24
25
|
enableTaskListItemToggle(convertRawProp(context, rawProps, "enableTaskListItemToggle", sourceProps.enableTaskListItemToggle, {true})),
|
|
25
26
|
enableLinkPreview(convertRawProp(context, rawProps, "enableLinkPreview", sourceProps.enableLinkPreview, {true})),
|
|
26
27
|
selectable(convertRawProp(context, rawProps, "selectable", sourceProps.selectable, {false})),
|
|
@@ -66,6 +67,10 @@ folly::dynamic EnrichedMarkdownProps::getDiffProps(
|
|
|
66
67
|
result["markdownStyle"] = toDynamic(markdownStyle);
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
if (emitLinkLayout != oldProps->emitLinkLayout) {
|
|
71
|
+
result["emitLinkLayout"] = emitLinkLayout;
|
|
72
|
+
}
|
|
73
|
+
|
|
69
74
|
if (enableTaskListItemToggle != oldProps->enableTaskListItemToggle) {
|
|
70
75
|
result["enableTaskListItemToggle"] = enableTaskListItemToggle;
|
|
71
76
|
}
|
|
@@ -304,6 +309,7 @@ EnrichedMarkdownTextProps::EnrichedMarkdownTextProps(
|
|
|
304
309
|
|
|
305
310
|
markdown(convertRawProp(context, rawProps, "markdown", sourceProps.markdown, {})),
|
|
306
311
|
markdownStyle(convertRawProp(context, rawProps, "markdownStyle", sourceProps.markdownStyle, {})),
|
|
312
|
+
emitLinkLayout(convertRawProp(context, rawProps, "emitLinkLayout", sourceProps.emitLinkLayout, {false})),
|
|
307
313
|
enableTaskListItemToggle(convertRawProp(context, rawProps, "enableTaskListItemToggle", sourceProps.enableTaskListItemToggle, {true})),
|
|
308
314
|
enableLinkPreview(convertRawProp(context, rawProps, "enableLinkPreview", sourceProps.enableLinkPreview, {true})),
|
|
309
315
|
selectable(convertRawProp(context, rawProps, "selectable", sourceProps.selectable, {false})),
|
|
@@ -349,6 +355,10 @@ folly::dynamic EnrichedMarkdownTextProps::getDiffProps(
|
|
|
349
355
|
result["markdownStyle"] = toDynamic(markdownStyle);
|
|
350
356
|
}
|
|
351
357
|
|
|
358
|
+
if (emitLinkLayout != oldProps->emitLinkLayout) {
|
|
359
|
+
result["emitLinkLayout"] = emitLinkLayout;
|
|
360
|
+
}
|
|
361
|
+
|
|
352
362
|
if (enableTaskListItemToggle != oldProps->enableTaskListItemToggle) {
|
|
353
363
|
result["enableTaskListItemToggle"] = enableTaskListItemToggle;
|
|
354
364
|
}
|
|
@@ -997,6 +997,11 @@ struct EnrichedMarkdownMarkdownStyleLinkStruct {
|
|
|
997
997
|
SharedColor color{};
|
|
998
998
|
bool underline{false};
|
|
999
999
|
SharedColor backgroundColor{};
|
|
1000
|
+
Float borderRadius{0.0};
|
|
1001
|
+
Float paddingHorizontal{0.0};
|
|
1002
|
+
Float paddingVertical{0.0};
|
|
1003
|
+
SharedColor borderColor{};
|
|
1004
|
+
Float borderWidth{0.0};
|
|
1000
1005
|
|
|
1001
1006
|
|
|
1002
1007
|
#ifdef RN_SERIALIZABLE_STATE
|
|
@@ -1008,6 +1013,11 @@ struct EnrichedMarkdownMarkdownStyleLinkStruct {
|
|
|
1008
1013
|
result["color"] = ::facebook::react::toDynamic(color);
|
|
1009
1014
|
result["underline"] = underline;
|
|
1010
1015
|
result["backgroundColor"] = ::facebook::react::toDynamic(backgroundColor);
|
|
1016
|
+
result["borderRadius"] = borderRadius;
|
|
1017
|
+
result["paddingHorizontal"] = paddingHorizontal;
|
|
1018
|
+
result["paddingVertical"] = paddingVertical;
|
|
1019
|
+
result["borderColor"] = ::facebook::react::toDynamic(borderColor);
|
|
1020
|
+
result["borderWidth"] = borderWidth;
|
|
1011
1021
|
return result;
|
|
1012
1022
|
}
|
|
1013
1023
|
#endif
|
|
@@ -1032,6 +1042,26 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
|
|
|
1032
1042
|
if (tmp_backgroundColor != map.end()) {
|
|
1033
1043
|
fromRawValue(context, tmp_backgroundColor->second, result.backgroundColor);
|
|
1034
1044
|
}
|
|
1045
|
+
auto tmp_borderRadius = map.find("borderRadius");
|
|
1046
|
+
if (tmp_borderRadius != map.end()) {
|
|
1047
|
+
fromRawValue(context, tmp_borderRadius->second, result.borderRadius);
|
|
1048
|
+
}
|
|
1049
|
+
auto tmp_paddingHorizontal = map.find("paddingHorizontal");
|
|
1050
|
+
if (tmp_paddingHorizontal != map.end()) {
|
|
1051
|
+
fromRawValue(context, tmp_paddingHorizontal->second, result.paddingHorizontal);
|
|
1052
|
+
}
|
|
1053
|
+
auto tmp_paddingVertical = map.find("paddingVertical");
|
|
1054
|
+
if (tmp_paddingVertical != map.end()) {
|
|
1055
|
+
fromRawValue(context, tmp_paddingVertical->second, result.paddingVertical);
|
|
1056
|
+
}
|
|
1057
|
+
auto tmp_borderColor = map.find("borderColor");
|
|
1058
|
+
if (tmp_borderColor != map.end()) {
|
|
1059
|
+
fromRawValue(context, tmp_borderColor->second, result.borderColor);
|
|
1060
|
+
}
|
|
1061
|
+
auto tmp_borderWidth = map.find("borderWidth");
|
|
1062
|
+
if (tmp_borderWidth != map.end()) {
|
|
1063
|
+
fromRawValue(context, tmp_borderWidth->second, result.borderWidth);
|
|
1064
|
+
}
|
|
1035
1065
|
}
|
|
1036
1066
|
|
|
1037
1067
|
static inline std::string toString(const EnrichedMarkdownMarkdownStyleLinkStruct &value) {
|
|
@@ -1049,6 +1079,11 @@ struct EnrichedMarkdownMarkdownStyleLinkVariantsStruct {
|
|
|
1049
1079
|
SharedColor color{};
|
|
1050
1080
|
bool underline{false};
|
|
1051
1081
|
SharedColor backgroundColor{};
|
|
1082
|
+
Float borderRadius{0.0};
|
|
1083
|
+
Float paddingHorizontal{0.0};
|
|
1084
|
+
Float paddingVertical{0.0};
|
|
1085
|
+
SharedColor borderColor{};
|
|
1086
|
+
Float borderWidth{0.0};
|
|
1052
1087
|
|
|
1053
1088
|
|
|
1054
1089
|
#ifdef RN_SERIALIZABLE_STATE
|
|
@@ -1060,6 +1095,11 @@ struct EnrichedMarkdownMarkdownStyleLinkVariantsStruct {
|
|
|
1060
1095
|
result["color"] = ::facebook::react::toDynamic(color);
|
|
1061
1096
|
result["underline"] = underline;
|
|
1062
1097
|
result["backgroundColor"] = ::facebook::react::toDynamic(backgroundColor);
|
|
1098
|
+
result["borderRadius"] = borderRadius;
|
|
1099
|
+
result["paddingHorizontal"] = paddingHorizontal;
|
|
1100
|
+
result["paddingVertical"] = paddingVertical;
|
|
1101
|
+
result["borderColor"] = ::facebook::react::toDynamic(borderColor);
|
|
1102
|
+
result["borderWidth"] = borderWidth;
|
|
1063
1103
|
return result;
|
|
1064
1104
|
}
|
|
1065
1105
|
#endif
|
|
@@ -1084,6 +1124,26 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
|
|
|
1084
1124
|
if (tmp_backgroundColor != map.end()) {
|
|
1085
1125
|
fromRawValue(context, tmp_backgroundColor->second, result.backgroundColor);
|
|
1086
1126
|
}
|
|
1127
|
+
auto tmp_borderRadius = map.find("borderRadius");
|
|
1128
|
+
if (tmp_borderRadius != map.end()) {
|
|
1129
|
+
fromRawValue(context, tmp_borderRadius->second, result.borderRadius);
|
|
1130
|
+
}
|
|
1131
|
+
auto tmp_paddingHorizontal = map.find("paddingHorizontal");
|
|
1132
|
+
if (tmp_paddingHorizontal != map.end()) {
|
|
1133
|
+
fromRawValue(context, tmp_paddingHorizontal->second, result.paddingHorizontal);
|
|
1134
|
+
}
|
|
1135
|
+
auto tmp_paddingVertical = map.find("paddingVertical");
|
|
1136
|
+
if (tmp_paddingVertical != map.end()) {
|
|
1137
|
+
fromRawValue(context, tmp_paddingVertical->second, result.paddingVertical);
|
|
1138
|
+
}
|
|
1139
|
+
auto tmp_borderColor = map.find("borderColor");
|
|
1140
|
+
if (tmp_borderColor != map.end()) {
|
|
1141
|
+
fromRawValue(context, tmp_borderColor->second, result.borderColor);
|
|
1142
|
+
}
|
|
1143
|
+
auto tmp_borderWidth = map.find("borderWidth");
|
|
1144
|
+
if (tmp_borderWidth != map.end()) {
|
|
1145
|
+
fromRawValue(context, tmp_borderWidth->second, result.borderWidth);
|
|
1146
|
+
}
|
|
1087
1147
|
}
|
|
1088
1148
|
|
|
1089
1149
|
static inline std::string toString(const EnrichedMarkdownMarkdownStyleLinkVariantsStruct &value) {
|
|
@@ -2826,6 +2886,7 @@ class EnrichedMarkdownProps final : public ViewProps {
|
|
|
2826
2886
|
|
|
2827
2887
|
std::string markdown{};
|
|
2828
2888
|
EnrichedMarkdownMarkdownStyleStruct markdownStyle{};
|
|
2889
|
+
bool emitLinkLayout{false};
|
|
2829
2890
|
bool enableTaskListItemToggle{true};
|
|
2830
2891
|
bool enableLinkPreview{true};
|
|
2831
2892
|
bool selectable{false};
|
|
@@ -4980,6 +5041,11 @@ struct EnrichedMarkdownTextMarkdownStyleLinkStruct {
|
|
|
4980
5041
|
SharedColor color{};
|
|
4981
5042
|
bool underline{false};
|
|
4982
5043
|
SharedColor backgroundColor{};
|
|
5044
|
+
Float borderRadius{0.0};
|
|
5045
|
+
Float paddingHorizontal{0.0};
|
|
5046
|
+
Float paddingVertical{0.0};
|
|
5047
|
+
SharedColor borderColor{};
|
|
5048
|
+
Float borderWidth{0.0};
|
|
4983
5049
|
|
|
4984
5050
|
|
|
4985
5051
|
#ifdef RN_SERIALIZABLE_STATE
|
|
@@ -4991,6 +5057,11 @@ struct EnrichedMarkdownTextMarkdownStyleLinkStruct {
|
|
|
4991
5057
|
result["color"] = ::facebook::react::toDynamic(color);
|
|
4992
5058
|
result["underline"] = underline;
|
|
4993
5059
|
result["backgroundColor"] = ::facebook::react::toDynamic(backgroundColor);
|
|
5060
|
+
result["borderRadius"] = borderRadius;
|
|
5061
|
+
result["paddingHorizontal"] = paddingHorizontal;
|
|
5062
|
+
result["paddingVertical"] = paddingVertical;
|
|
5063
|
+
result["borderColor"] = ::facebook::react::toDynamic(borderColor);
|
|
5064
|
+
result["borderWidth"] = borderWidth;
|
|
4994
5065
|
return result;
|
|
4995
5066
|
}
|
|
4996
5067
|
#endif
|
|
@@ -5015,6 +5086,26 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
|
|
|
5015
5086
|
if (tmp_backgroundColor != map.end()) {
|
|
5016
5087
|
fromRawValue(context, tmp_backgroundColor->second, result.backgroundColor);
|
|
5017
5088
|
}
|
|
5089
|
+
auto tmp_borderRadius = map.find("borderRadius");
|
|
5090
|
+
if (tmp_borderRadius != map.end()) {
|
|
5091
|
+
fromRawValue(context, tmp_borderRadius->second, result.borderRadius);
|
|
5092
|
+
}
|
|
5093
|
+
auto tmp_paddingHorizontal = map.find("paddingHorizontal");
|
|
5094
|
+
if (tmp_paddingHorizontal != map.end()) {
|
|
5095
|
+
fromRawValue(context, tmp_paddingHorizontal->second, result.paddingHorizontal);
|
|
5096
|
+
}
|
|
5097
|
+
auto tmp_paddingVertical = map.find("paddingVertical");
|
|
5098
|
+
if (tmp_paddingVertical != map.end()) {
|
|
5099
|
+
fromRawValue(context, tmp_paddingVertical->second, result.paddingVertical);
|
|
5100
|
+
}
|
|
5101
|
+
auto tmp_borderColor = map.find("borderColor");
|
|
5102
|
+
if (tmp_borderColor != map.end()) {
|
|
5103
|
+
fromRawValue(context, tmp_borderColor->second, result.borderColor);
|
|
5104
|
+
}
|
|
5105
|
+
auto tmp_borderWidth = map.find("borderWidth");
|
|
5106
|
+
if (tmp_borderWidth != map.end()) {
|
|
5107
|
+
fromRawValue(context, tmp_borderWidth->second, result.borderWidth);
|
|
5108
|
+
}
|
|
5018
5109
|
}
|
|
5019
5110
|
|
|
5020
5111
|
static inline std::string toString(const EnrichedMarkdownTextMarkdownStyleLinkStruct &value) {
|
|
@@ -5032,6 +5123,11 @@ struct EnrichedMarkdownTextMarkdownStyleLinkVariantsStruct {
|
|
|
5032
5123
|
SharedColor color{};
|
|
5033
5124
|
bool underline{false};
|
|
5034
5125
|
SharedColor backgroundColor{};
|
|
5126
|
+
Float borderRadius{0.0};
|
|
5127
|
+
Float paddingHorizontal{0.0};
|
|
5128
|
+
Float paddingVertical{0.0};
|
|
5129
|
+
SharedColor borderColor{};
|
|
5130
|
+
Float borderWidth{0.0};
|
|
5035
5131
|
|
|
5036
5132
|
|
|
5037
5133
|
#ifdef RN_SERIALIZABLE_STATE
|
|
@@ -5043,6 +5139,11 @@ struct EnrichedMarkdownTextMarkdownStyleLinkVariantsStruct {
|
|
|
5043
5139
|
result["color"] = ::facebook::react::toDynamic(color);
|
|
5044
5140
|
result["underline"] = underline;
|
|
5045
5141
|
result["backgroundColor"] = ::facebook::react::toDynamic(backgroundColor);
|
|
5142
|
+
result["borderRadius"] = borderRadius;
|
|
5143
|
+
result["paddingHorizontal"] = paddingHorizontal;
|
|
5144
|
+
result["paddingVertical"] = paddingVertical;
|
|
5145
|
+
result["borderColor"] = ::facebook::react::toDynamic(borderColor);
|
|
5146
|
+
result["borderWidth"] = borderWidth;
|
|
5046
5147
|
return result;
|
|
5047
5148
|
}
|
|
5048
5149
|
#endif
|
|
@@ -5067,6 +5168,26 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
|
|
|
5067
5168
|
if (tmp_backgroundColor != map.end()) {
|
|
5068
5169
|
fromRawValue(context, tmp_backgroundColor->second, result.backgroundColor);
|
|
5069
5170
|
}
|
|
5171
|
+
auto tmp_borderRadius = map.find("borderRadius");
|
|
5172
|
+
if (tmp_borderRadius != map.end()) {
|
|
5173
|
+
fromRawValue(context, tmp_borderRadius->second, result.borderRadius);
|
|
5174
|
+
}
|
|
5175
|
+
auto tmp_paddingHorizontal = map.find("paddingHorizontal");
|
|
5176
|
+
if (tmp_paddingHorizontal != map.end()) {
|
|
5177
|
+
fromRawValue(context, tmp_paddingHorizontal->second, result.paddingHorizontal);
|
|
5178
|
+
}
|
|
5179
|
+
auto tmp_paddingVertical = map.find("paddingVertical");
|
|
5180
|
+
if (tmp_paddingVertical != map.end()) {
|
|
5181
|
+
fromRawValue(context, tmp_paddingVertical->second, result.paddingVertical);
|
|
5182
|
+
}
|
|
5183
|
+
auto tmp_borderColor = map.find("borderColor");
|
|
5184
|
+
if (tmp_borderColor != map.end()) {
|
|
5185
|
+
fromRawValue(context, tmp_borderColor->second, result.borderColor);
|
|
5186
|
+
}
|
|
5187
|
+
auto tmp_borderWidth = map.find("borderWidth");
|
|
5188
|
+
if (tmp_borderWidth != map.end()) {
|
|
5189
|
+
fromRawValue(context, tmp_borderWidth->second, result.borderWidth);
|
|
5190
|
+
}
|
|
5070
5191
|
}
|
|
5071
5192
|
|
|
5072
5193
|
static inline std::string toString(const EnrichedMarkdownTextMarkdownStyleLinkVariantsStruct &value) {
|
|
@@ -6809,6 +6930,7 @@ class EnrichedMarkdownTextProps final : public ViewProps {
|
|
|
6809
6930
|
|
|
6810
6931
|
std::string markdown{};
|
|
6811
6932
|
EnrichedMarkdownTextMarkdownStyleStruct markdownStyle{};
|
|
6933
|
+
bool emitLinkLayout{false};
|
|
6812
6934
|
bool enableTaskListItemToggle{true};
|
|
6813
6935
|
bool enableLinkPreview{true};
|
|
6814
6936
|
bool selectable{false};
|
|
@@ -25,9 +25,12 @@ import com.swmansion.enriched.markdown.utils.common.RenderedSegment
|
|
|
25
25
|
import com.swmansion.enriched.markdown.utils.common.SegmentReconciler
|
|
26
26
|
import com.swmansion.enriched.markdown.utils.common.StreamingMarkdownFilter
|
|
27
27
|
import com.swmansion.enriched.markdown.utils.common.TableStreamingMode
|
|
28
|
+
import com.swmansion.enriched.markdown.utils.common.emitLinkLayout
|
|
28
29
|
import com.swmansion.enriched.markdown.utils.common.isReducedMotionEnabled
|
|
29
30
|
import com.swmansion.enriched.markdown.utils.common.splitASTIntoSegments
|
|
30
31
|
import com.swmansion.enriched.markdown.utils.text.TailFadeInAnimator
|
|
32
|
+
import com.swmansion.enriched.markdown.utils.text.view.LinkLayoutCollector
|
|
33
|
+
import com.swmansion.enriched.markdown.utils.text.view.LinkLayoutFragment
|
|
31
34
|
import com.swmansion.enriched.markdown.utils.text.view.SelectionMenuConfig
|
|
32
35
|
import com.swmansion.enriched.markdown.utils.text.view.applySelectionColors
|
|
33
36
|
import com.swmansion.enriched.markdown.views.BlockMenuOptions
|
|
@@ -99,6 +102,8 @@ class EnrichedMarkdown
|
|
|
99
102
|
private var selectionMenuConfig = SelectionMenuConfig()
|
|
100
103
|
private var accessibilityLabels = AccessibilityLabels()
|
|
101
104
|
private var textBreakStrategy: String = BreakStrategyUtils.DEFAULT_STRATEGY
|
|
105
|
+
private var linkLayoutEnabled = false
|
|
106
|
+
private var lastLinkLayout: List<LinkLayoutFragment>? = null
|
|
102
107
|
|
|
103
108
|
private var onLinkPressCallback: ((String) -> Unit)? = null
|
|
104
109
|
private var onLinkLongPressCallback: ((String) -> Unit)? = null
|
|
@@ -782,6 +787,39 @@ class EnrichedMarkdown
|
|
|
782
787
|
currentY += segment?.segmentMarginBottom ?: 0
|
|
783
788
|
}
|
|
784
789
|
}
|
|
790
|
+
|
|
791
|
+
emitLinkLayoutIfNeeded()
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
fun setEmitLinkLayout(enabled: Boolean) {
|
|
795
|
+
if (linkLayoutEnabled == enabled) return
|
|
796
|
+
linkLayoutEnabled = enabled
|
|
797
|
+
lastLinkLayout = null
|
|
798
|
+
emitLinkLayoutIfNeeded()
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Reports link rects of every text segment (offset by the segment's position) to JS for
|
|
803
|
+
* `renderLinkDecoration`. Tables are skipped: their cells scroll horizontally, so rects would
|
|
804
|
+
* go stale. Runs after each segment layout pass; deduplicated so an unchanged layout sends nothing.
|
|
805
|
+
*/
|
|
806
|
+
private fun emitLinkLayoutIfNeeded() {
|
|
807
|
+
if (!linkLayoutEnabled || width <= 0) return
|
|
808
|
+
val fragments = mutableListOf<LinkLayoutFragment>()
|
|
809
|
+
var linkCount = 0
|
|
810
|
+
segmentViews.forEach { view ->
|
|
811
|
+
if (view is TableContainerView) {
|
|
812
|
+
linkCount += view.linkCount
|
|
813
|
+
return@forEach
|
|
814
|
+
}
|
|
815
|
+
if (view !is EnrichedMarkdownInternalText) return@forEach
|
|
816
|
+
val (segmentFragments, segmentLinks) = LinkLayoutCollector.collect(view, view.left, view.top, linkCount)
|
|
817
|
+
fragments += segmentFragments
|
|
818
|
+
linkCount += segmentLinks
|
|
819
|
+
}
|
|
820
|
+
if (fragments == lastLinkLayout) return
|
|
821
|
+
lastLinkLayout = fragments
|
|
822
|
+
emitLinkLayout(this, fragments)
|
|
785
823
|
}
|
|
786
824
|
|
|
787
825
|
private fun computeSegmentsTotalHeight(): Int {
|
|
@@ -177,6 +177,14 @@ class EnrichedMarkdownManager :
|
|
|
177
177
|
view?.setContextMenuHidden(contextMenuHidden)
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
@ReactProp(name = "emitLinkLayout", defaultBoolean = false)
|
|
181
|
+
override fun setEmitLinkLayout(
|
|
182
|
+
view: EnrichedMarkdown?,
|
|
183
|
+
emitLinkLayout: Boolean,
|
|
184
|
+
) {
|
|
185
|
+
view?.setEmitLinkLayout(emitLinkLayout)
|
|
186
|
+
}
|
|
187
|
+
|
|
180
188
|
@ReactProp(name = "enableLinkPreview", defaultBoolean = true)
|
|
181
189
|
override fun setEnableLinkPreview(
|
|
182
190
|
view: EnrichedMarkdown?,
|
|
@@ -24,8 +24,11 @@ import com.swmansion.enriched.markdown.spoiler.SpoilerOverlay
|
|
|
24
24
|
import com.swmansion.enriched.markdown.spoiler.SpoilerOverlayDrawer
|
|
25
25
|
import com.swmansion.enriched.markdown.styles.StyleConfig
|
|
26
26
|
import com.swmansion.enriched.markdown.utils.common.BreakStrategyUtils
|
|
27
|
+
import com.swmansion.enriched.markdown.utils.common.emitLinkLayout
|
|
27
28
|
import com.swmansion.enriched.markdown.utils.text.TailFadeInAnimator
|
|
28
29
|
import com.swmansion.enriched.markdown.utils.text.interaction.CheckboxTouchHelper
|
|
30
|
+
import com.swmansion.enriched.markdown.utils.text.view.LinkLayoutCollector
|
|
31
|
+
import com.swmansion.enriched.markdown.utils.text.view.LinkLayoutFragment
|
|
29
32
|
import com.swmansion.enriched.markdown.utils.text.view.LinkLongPressMovementMethod
|
|
30
33
|
import com.swmansion.enriched.markdown.utils.text.view.SelectionMenuConfig
|
|
31
34
|
import com.swmansion.enriched.markdown.utils.text.view.applySelectableState
|
|
@@ -102,6 +105,9 @@ class EnrichedMarkdownText
|
|
|
102
105
|
private var contextMenuHidden = false
|
|
103
106
|
private var activeActionMode: ActionMode? = null
|
|
104
107
|
|
|
108
|
+
private var linkLayoutEnabled = false
|
|
109
|
+
private var lastLinkLayout: List<LinkLayoutFragment>? = null
|
|
110
|
+
|
|
105
111
|
init {
|
|
106
112
|
setupAsMarkdownTextView()
|
|
107
113
|
customSelectionActionModeCallback =
|
|
@@ -310,6 +316,37 @@ class EnrichedMarkdownText
|
|
|
310
316
|
}
|
|
311
317
|
|
|
312
318
|
applySelectionColors(selectionColor, selectionHandleColor)
|
|
319
|
+
emitLinkLayoutIfNeeded()
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
fun setEmitLinkLayout(enabled: Boolean) {
|
|
323
|
+
if (linkLayoutEnabled == enabled) return
|
|
324
|
+
linkLayoutEnabled = enabled
|
|
325
|
+
lastLinkLayout = null
|
|
326
|
+
emitLinkLayoutIfNeeded()
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Reports link rects to JS (for `renderLinkDecoration`) after every render and layout;
|
|
331
|
+
* deduplicated so an unchanged layout — the common case while streaming — sends nothing.
|
|
332
|
+
*/
|
|
333
|
+
private fun emitLinkLayoutIfNeeded() {
|
|
334
|
+
if (!linkLayoutEnabled || layout == null || width <= 0) return
|
|
335
|
+
val (fragments, _) = LinkLayoutCollector.collect(this)
|
|
336
|
+
if (fragments == lastLinkLayout) return
|
|
337
|
+
lastLinkLayout = fragments
|
|
338
|
+
emitLinkLayout(this, fragments)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
override fun onLayout(
|
|
342
|
+
changed: Boolean,
|
|
343
|
+
left: Int,
|
|
344
|
+
top: Int,
|
|
345
|
+
right: Int,
|
|
346
|
+
bottom: Int,
|
|
347
|
+
) {
|
|
348
|
+
super.onLayout(changed, left, top, right, bottom)
|
|
349
|
+
emitLinkLayoutIfNeeded()
|
|
313
350
|
}
|
|
314
351
|
|
|
315
352
|
// Trailing bottom margin included in the shadow-node measurement — must be
|
package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt
CHANGED
|
@@ -177,6 +177,14 @@ class EnrichedMarkdownTextManager :
|
|
|
177
177
|
view?.setContextMenuHidden(contextMenuHidden)
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
@ReactProp(name = "emitLinkLayout", defaultBoolean = false)
|
|
181
|
+
override fun setEmitLinkLayout(
|
|
182
|
+
view: EnrichedMarkdownText?,
|
|
183
|
+
emitLinkLayout: Boolean,
|
|
184
|
+
) {
|
|
185
|
+
view?.setEmitLinkLayout(emitLinkLayout)
|
|
186
|
+
}
|
|
187
|
+
|
|
180
188
|
@ReactProp(name = "enableLinkPreview", defaultBoolean = true)
|
|
181
189
|
override fun setEnableLinkPreview(
|
|
182
190
|
view: EnrichedMarkdownText?,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
import com.facebook.react.uimanager.events.Event
|
|
6
|
+
import com.swmansion.enriched.markdown.utils.text.view.LinkLayoutFragment
|
|
7
|
+
|
|
8
|
+
class LinkLayoutEvent(
|
|
9
|
+
surfaceId: Int,
|
|
10
|
+
viewId: Int,
|
|
11
|
+
private val fragments: List<LinkLayoutFragment>,
|
|
12
|
+
) : Event<LinkLayoutEvent>(surfaceId, viewId) {
|
|
13
|
+
override fun getEventName(): String = EVENT_NAME
|
|
14
|
+
|
|
15
|
+
override fun getEventData(): WritableMap {
|
|
16
|
+
val array = Arguments.createArray()
|
|
17
|
+
fragments.forEach { fragment ->
|
|
18
|
+
array.pushMap(
|
|
19
|
+
Arguments.createMap().apply {
|
|
20
|
+
putInt("linkIndex", fragment.linkIndex)
|
|
21
|
+
putString("url", fragment.url)
|
|
22
|
+
putString("text", fragment.text)
|
|
23
|
+
putDouble("x", fragment.x.toDouble())
|
|
24
|
+
putDouble("y", fragment.y.toDouble())
|
|
25
|
+
putDouble("width", fragment.width.toDouble())
|
|
26
|
+
putDouble("height", fragment.height.toDouble())
|
|
27
|
+
},
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
return Arguments.createMap().apply { putArray("fragments", array) }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
companion object {
|
|
34
|
+
const val EVENT_NAME: String = "onLinkLayout"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -2,6 +2,9 @@ package com.swmansion.enriched.markdown.renderer
|
|
|
2
2
|
|
|
3
3
|
import android.text.SpannableStringBuilder
|
|
4
4
|
import com.swmansion.enriched.markdown.parser.MarkdownASTNode
|
|
5
|
+
import com.swmansion.enriched.markdown.spans.LinkChipBackgroundSpan
|
|
6
|
+
import com.swmansion.enriched.markdown.spans.LinkSpacerSpan
|
|
7
|
+
import com.swmansion.enriched.markdown.spans.LinkSpacers
|
|
5
8
|
import com.swmansion.enriched.markdown.spans.LinkSpan
|
|
6
9
|
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE
|
|
7
10
|
|
|
@@ -16,14 +19,41 @@ class LinkRenderer(
|
|
|
16
19
|
factory: RendererFactory,
|
|
17
20
|
) {
|
|
18
21
|
val url = node.getAttribute("url") ?: return
|
|
22
|
+
// Chip ("box") properties never fall back to the base link style.
|
|
23
|
+
val chip = factory.styleCache.linkChipForUrl(url)
|
|
24
|
+
val padding = chip.paddingHorizontal
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
val start = builder.length
|
|
27
|
+
// The leading spacer goes in before the children so ranges they register stay valid.
|
|
28
|
+
if (padding > 0f) appendSpacer(builder, padding)
|
|
29
|
+
val contentStart = builder.length
|
|
30
|
+
|
|
31
|
+
factory.renderChildren(node, builder, onLinkPress, onLinkLongPress)
|
|
32
|
+
|
|
33
|
+
if (builder.length == contentStart) {
|
|
34
|
+
if (contentStart > start) builder.delete(start, contentStart)
|
|
35
|
+
return
|
|
27
36
|
}
|
|
37
|
+
if (padding > 0f) appendSpacer(builder, padding)
|
|
38
|
+
val end = builder.length
|
|
39
|
+
|
|
40
|
+
val blockStyle = factory.blockStyleContext.requireBlockStyle()
|
|
41
|
+
builder.setSpan(
|
|
42
|
+
LinkSpan(url, onLinkPress, onLinkLongPress, factory.styleCache, blockStyle, factory.context),
|
|
43
|
+
start,
|
|
44
|
+
end,
|
|
45
|
+
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
46
|
+
)
|
|
47
|
+
// One instance per link: also identifies the link for link-layout reporting.
|
|
48
|
+
builder.setSpan(LinkChipBackgroundSpan(chip), start, end, SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private fun appendSpacer(
|
|
52
|
+
builder: SpannableStringBuilder,
|
|
53
|
+
width: Float,
|
|
54
|
+
) {
|
|
55
|
+
val position = builder.length
|
|
56
|
+
builder.append(LinkSpacers.CHAR)
|
|
57
|
+
builder.setSpan(LinkSpacerSpan(width), position, position + 1, SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE)
|
|
28
58
|
}
|
|
29
59
|
}
|