react-native-enriched-markdown 0.1.0 → 0.1.1
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/LICENSE +20 -0
- package/README.md +479 -0
- package/ReactNativeEnrichedMarkdown.podspec +27 -0
- package/android/build.gradle +101 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +39 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +21 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +22 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.h +24 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +24 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +25 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +57 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +1164 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.cpp +17 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.h +32 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.cpp +16 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.h +20 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/baseline-prof.txt +65 -0
- package/android/src/main/cpp/jni-adapter.cpp +203 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +153 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +30 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +119 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextPackage.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +165 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkPressEvent.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +166 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +89 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +105 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeRenderer.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/DocumentRenderer.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/EmphasisRenderer.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ImageRenderer.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LineBreakRenderer.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +105 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +58 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +99 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ParagraphRenderer.kt +66 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/Renderer.kt +95 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +85 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/StrongRenderer.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/TextRenderer.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ThematicBreakRenderer.kt +44 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +136 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +135 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +180 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +196 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +34 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/HeadingSpan.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +320 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LineHeightSpan.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/MarginBottomSpan.kt +76 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +87 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TextSpan.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ThematicBreakSpan.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BaseBlockStyle.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +51 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeStyle.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/EmphasisStyle.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/HeadingStyle.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineImageStyle.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ParagraphStyle.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StrongStyle.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +180 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleParser.kt +75 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ThematicBreakStyle.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/AsyncDrawable.kt +91 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/HTMLGenerator.kt +809 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/MarkdownExtractor.kt +365 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/SelectionActionMode.kt +139 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/Utils.kt +181 -0
- package/android/src/main/jni/CMakeLists.txt +82 -0
- package/android/src/main/jni/EnrichedMarkdownTextSpec.cpp +21 -0
- package/android/src/main/jni/EnrichedMarkdownTextSpec.h +25 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextComponentDescriptor.h +29 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextMeasurementManager.cpp +45 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextMeasurementManager.h +21 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +33 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +49 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +25 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +19 -0
- package/cpp/md4c/md4c.c +6492 -0
- package/cpp/md4c/md4c.h +402 -0
- package/cpp/parser/MD4CParser.cpp +314 -0
- package/cpp/parser/MD4CParser.hpp +23 -0
- package/cpp/parser/MarkdownASTNode.hpp +49 -0
- package/ios/EnrichedMarkdownText.h +18 -0
- package/ios/EnrichedMarkdownText.mm +1074 -0
- package/ios/attachments/ImageAttachment.h +23 -0
- package/ios/attachments/ImageAttachment.m +185 -0
- package/ios/attachments/ThematicBreakAttachment.h +15 -0
- package/ios/attachments/ThematicBreakAttachment.m +33 -0
- package/ios/generated/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +22 -0
- package/ios/generated/EnrichedMarkdownTextSpec/ComponentDescriptors.h +24 -0
- package/ios/generated/EnrichedMarkdownTextSpec/EventEmitters.cpp +24 -0
- package/ios/generated/EnrichedMarkdownTextSpec/EventEmitters.h +25 -0
- package/ios/generated/EnrichedMarkdownTextSpec/Props.cpp +57 -0
- package/ios/generated/EnrichedMarkdownTextSpec/Props.h +1164 -0
- package/ios/generated/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +20 -0
- package/ios/generated/EnrichedMarkdownTextSpec/ShadowNodes.cpp +17 -0
- package/ios/generated/EnrichedMarkdownTextSpec/ShadowNodes.h +32 -0
- package/ios/generated/EnrichedMarkdownTextSpec/States.cpp +16 -0
- package/ios/generated/EnrichedMarkdownTextSpec/States.h +20 -0
- package/ios/internals/EnrichedMarkdownTextComponentDescriptor.h +19 -0
- package/ios/internals/EnrichedMarkdownTextShadowNode.h +43 -0
- package/ios/internals/EnrichedMarkdownTextShadowNode.mm +85 -0
- package/ios/internals/EnrichedMarkdownTextState.h +24 -0
- package/ios/parser/MarkdownASTNode.h +33 -0
- package/ios/parser/MarkdownASTNode.m +32 -0
- package/ios/parser/MarkdownParser.h +8 -0
- package/ios/parser/MarkdownParser.mm +13 -0
- package/ios/parser/MarkdownParserBridge.mm +110 -0
- package/ios/renderer/AttributedRenderer.h +9 -0
- package/ios/renderer/AttributedRenderer.m +119 -0
- package/ios/renderer/BlockquoteRenderer.h +7 -0
- package/ios/renderer/BlockquoteRenderer.m +159 -0
- package/ios/renderer/CodeBlockRenderer.h +10 -0
- package/ios/renderer/CodeBlockRenderer.m +89 -0
- package/ios/renderer/CodeRenderer.h +10 -0
- package/ios/renderer/CodeRenderer.m +60 -0
- package/ios/renderer/EmphasisRenderer.h +6 -0
- package/ios/renderer/EmphasisRenderer.m +96 -0
- package/ios/renderer/HeadingRenderer.h +7 -0
- package/ios/renderer/HeadingRenderer.m +98 -0
- package/ios/renderer/ImageRenderer.h +12 -0
- package/ios/renderer/ImageRenderer.m +62 -0
- package/ios/renderer/LinkRenderer.h +7 -0
- package/ios/renderer/LinkRenderer.m +69 -0
- package/ios/renderer/ListItemRenderer.h +16 -0
- package/ios/renderer/ListItemRenderer.m +91 -0
- package/ios/renderer/ListRenderer.h +13 -0
- package/ios/renderer/ListRenderer.m +67 -0
- package/ios/renderer/NodeRenderer.h +8 -0
- package/ios/renderer/ParagraphRenderer.h +7 -0
- package/ios/renderer/ParagraphRenderer.m +69 -0
- package/ios/renderer/RenderContext.h +88 -0
- package/ios/renderer/RenderContext.m +248 -0
- package/ios/renderer/RendererFactory.h +12 -0
- package/ios/renderer/RendererFactory.m +110 -0
- package/ios/renderer/StrongRenderer.h +6 -0
- package/ios/renderer/StrongRenderer.m +83 -0
- package/ios/renderer/TextRenderer.h +6 -0
- package/ios/renderer/TextRenderer.m +16 -0
- package/ios/renderer/ThematicBreakRenderer.h +5 -0
- package/ios/renderer/ThematicBreakRenderer.m +53 -0
- package/ios/styles/StyleConfig.h +228 -0
- package/ios/styles/StyleConfig.mm +1467 -0
- package/ios/utils/BlockquoteBorder.h +20 -0
- package/ios/utils/BlockquoteBorder.m +92 -0
- package/ios/utils/CodeBackground.h +19 -0
- package/ios/utils/CodeBackground.m +191 -0
- package/ios/utils/CodeBlockBackground.h +17 -0
- package/ios/utils/CodeBlockBackground.m +87 -0
- package/ios/utils/EditMenuUtils.h +22 -0
- package/ios/utils/EditMenuUtils.m +118 -0
- package/ios/utils/FontUtils.h +20 -0
- package/ios/utils/FontUtils.m +13 -0
- package/ios/utils/HTMLGenerator.h +20 -0
- package/ios/utils/HTMLGenerator.m +779 -0
- package/ios/utils/LastElementUtils.h +53 -0
- package/ios/utils/ListMarkerDrawer.h +15 -0
- package/ios/utils/ListMarkerDrawer.m +127 -0
- package/ios/utils/MarkdownExtractor.h +17 -0
- package/ios/utils/MarkdownExtractor.m +295 -0
- package/ios/utils/ParagraphStyleUtils.h +13 -0
- package/ios/utils/ParagraphStyleUtils.m +56 -0
- package/ios/utils/PasteboardUtils.h +36 -0
- package/ios/utils/PasteboardUtils.m +134 -0
- package/ios/utils/RTFExportUtils.h +24 -0
- package/ios/utils/RTFExportUtils.m +297 -0
- package/ios/utils/RuntimeKeys.h +38 -0
- package/ios/utils/RuntimeKeys.m +11 -0
- package/ios/utils/TextViewLayoutManager.h +14 -0
- package/ios/utils/TextViewLayoutManager.mm +113 -0
- package/lib/module/EnrichedMarkdownText.js +34 -0
- package/lib/module/EnrichedMarkdownText.js.map +1 -0
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +130 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/normalizeMarkdownStyle.js +340 -0
- package/lib/module/normalizeMarkdownStyle.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/EnrichedMarkdownText.d.ts +101 -0
- package/lib/typescript/src/EnrichedMarkdownText.d.ts.map +1 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +111 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts +6 -0
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -0
- package/package.json +186 -1
- package/react-native.config.js +13 -0
- package/src/EnrichedMarkdownText.tsx +152 -0
- package/src/EnrichedMarkdownTextNativeComponent.ts +130 -0
- package/src/index.tsx +7 -0
- package/src/normalizeMarkdownStyle.ts +377 -0
package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.cpp
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
4
|
+
*
|
|
5
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
6
|
+
* once the code is regenerated.
|
|
7
|
+
*
|
|
8
|
+
* @generated by codegen project: GenerateShadowNodeCpp.js
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#include "ShadowNodes.h"
|
|
12
|
+
|
|
13
|
+
namespace facebook::react {
|
|
14
|
+
|
|
15
|
+
extern const char EnrichedMarkdownTextComponentName[] = "EnrichedMarkdownText";
|
|
16
|
+
|
|
17
|
+
} // namespace facebook::react
|
package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.h
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
4
|
+
*
|
|
5
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
6
|
+
* once the code is regenerated.
|
|
7
|
+
*
|
|
8
|
+
* @generated by codegen project: GenerateShadowNodeH.js
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#pragma once
|
|
12
|
+
|
|
13
|
+
#include "EventEmitters.h"
|
|
14
|
+
#include "Props.h"
|
|
15
|
+
#include "States.h"
|
|
16
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
17
|
+
#include <jsi/jsi.h>
|
|
18
|
+
|
|
19
|
+
namespace facebook::react {
|
|
20
|
+
|
|
21
|
+
JSI_EXPORT extern const char EnrichedMarkdownTextComponentName[];
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* `ShadowNode` for <EnrichedMarkdownText> component.
|
|
25
|
+
*/
|
|
26
|
+
using EnrichedMarkdownTextShadowNode = ConcreteViewShadowNode<
|
|
27
|
+
EnrichedMarkdownTextComponentName,
|
|
28
|
+
EnrichedMarkdownTextProps,
|
|
29
|
+
EnrichedMarkdownTextEventEmitter,
|
|
30
|
+
EnrichedMarkdownTextState>;
|
|
31
|
+
|
|
32
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
4
|
+
*
|
|
5
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
6
|
+
* once the code is regenerated.
|
|
7
|
+
*
|
|
8
|
+
* @generated by codegen project: GenerateStateCpp.js
|
|
9
|
+
*/
|
|
10
|
+
#include "States.h"
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
3
|
+
*
|
|
4
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
5
|
+
* once the code is regenerated.
|
|
6
|
+
*
|
|
7
|
+
* @generated by codegen project: GenerateStateH.js
|
|
8
|
+
*/
|
|
9
|
+
#pragma once
|
|
10
|
+
|
|
11
|
+
#include <react/renderer/core/StateData.h>
|
|
12
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
13
|
+
#include <folly/dynamic.h>
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
namespace facebook::react {
|
|
17
|
+
|
|
18
|
+
using EnrichedMarkdownTextState = StateData;
|
|
19
|
+
|
|
20
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Baseline Profile for react-native-enriched-markdown
|
|
2
|
+
# These classes will be AOT compiled during app install
|
|
3
|
+
# to improve cold start performance.
|
|
4
|
+
|
|
5
|
+
# Core View and Rendering
|
|
6
|
+
Lcom/swmansion/enriched/markdown/EnrichedMarkdownText;
|
|
7
|
+
Lcom/swmansion/enriched/markdown/EnrichedMarkdownTextManager;
|
|
8
|
+
Lcom/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager;
|
|
9
|
+
|
|
10
|
+
# Renderer Classes
|
|
11
|
+
Lcom/swmansion/enriched/markdown/renderer/Renderer;
|
|
12
|
+
Lcom/swmansion/enriched/markdown/renderer/RendererFactory;
|
|
13
|
+
Lcom/swmansion/enriched/markdown/renderer/RendererConfig;
|
|
14
|
+
Lcom/swmansion/enriched/markdown/renderer/BlockStyleContext;
|
|
15
|
+
Lcom/swmansion/enriched/markdown/renderer/BlockStyle;
|
|
16
|
+
Lcom/swmansion/enriched/markdown/renderer/SpanStyleCache;
|
|
17
|
+
Lcom/swmansion/enriched/markdown/renderer/NodeRenderer;
|
|
18
|
+
Lcom/swmansion/enriched/markdown/renderer/TextRenderer;
|
|
19
|
+
Lcom/swmansion/enriched/markdown/renderer/ParagraphRenderer;
|
|
20
|
+
Lcom/swmansion/enriched/markdown/renderer/HeadingRenderer;
|
|
21
|
+
Lcom/swmansion/enriched/markdown/renderer/StrongRenderer;
|
|
22
|
+
Lcom/swmansion/enriched/markdown/renderer/EmphasisRenderer;
|
|
23
|
+
Lcom/swmansion/enriched/markdown/renderer/LinkRenderer;
|
|
24
|
+
Lcom/swmansion/enriched/markdown/renderer/ListRenderer;
|
|
25
|
+
Lcom/swmansion/enriched/markdown/renderer/ListItemRenderer;
|
|
26
|
+
Lcom/swmansion/enriched/markdown/renderer/BlockquoteRenderer;
|
|
27
|
+
Lcom/swmansion/enriched/markdown/renderer/CodeBlockRenderer;
|
|
28
|
+
Lcom/swmansion/enriched/markdown/renderer/CodeRenderer;
|
|
29
|
+
Lcom/swmansion/enriched/markdown/renderer/ImageRenderer;
|
|
30
|
+
Lcom/swmansion/enriched/markdown/renderer/LineBreakRenderer;
|
|
31
|
+
Lcom/swmansion/enriched/markdown/renderer/DocumentRenderer;
|
|
32
|
+
|
|
33
|
+
# Spans
|
|
34
|
+
Lcom/swmansion/enriched/markdown/spans/StrongSpan;
|
|
35
|
+
Lcom/swmansion/enriched/markdown/spans/EmphasisSpan;
|
|
36
|
+
Lcom/swmansion/enriched/markdown/spans/CodeSpan;
|
|
37
|
+
Lcom/swmansion/enriched/markdown/spans/TextSpan;
|
|
38
|
+
Lcom/swmansion/enriched/markdown/spans/HeadingSpan;
|
|
39
|
+
Lcom/swmansion/enriched/markdown/spans/LinkSpan;
|
|
40
|
+
Lcom/swmansion/enriched/markdown/spans/LineHeightSpan;
|
|
41
|
+
Lcom/swmansion/enriched/markdown/spans/MarginBottomSpan;
|
|
42
|
+
Lcom/swmansion/enriched/markdown/spans/BaseListSpan;
|
|
43
|
+
Lcom/swmansion/enriched/markdown/spans/UnorderedListSpan;
|
|
44
|
+
Lcom/swmansion/enriched/markdown/spans/OrderedListSpan;
|
|
45
|
+
Lcom/swmansion/enriched/markdown/spans/BlockquoteSpan;
|
|
46
|
+
Lcom/swmansion/enriched/markdown/spans/CodeBlockSpan;
|
|
47
|
+
Lcom/swmansion/enriched/markdown/spans/CodeBackgroundSpan;
|
|
48
|
+
Lcom/swmansion/enriched/markdown/spans/ImageSpan;
|
|
49
|
+
|
|
50
|
+
# Style Configuration
|
|
51
|
+
Lcom/swmansion/enriched/markdown/styles/StyleConfig;
|
|
52
|
+
Lcom/swmansion/enriched/markdown/styles/ParagraphStyle;
|
|
53
|
+
Lcom/swmansion/enriched/markdown/styles/HeadingStyle;
|
|
54
|
+
Lcom/swmansion/enriched/markdown/styles/ListStyle;
|
|
55
|
+
Lcom/swmansion/enriched/markdown/styles/BlockquoteStyle;
|
|
56
|
+
Lcom/swmansion/enriched/markdown/styles/CodeBlockStyle;
|
|
57
|
+
Lcom/swmansion/enriched/markdown/styles/CodeStyle;
|
|
58
|
+
|
|
59
|
+
# Parser
|
|
60
|
+
Lcom/swmansion/enriched/markdown/parser/Parser;
|
|
61
|
+
Lcom/swmansion/enriched/markdown/parser/MarkdownASTNode;
|
|
62
|
+
Lcom/swmansion/enriched/markdown/parser/MarkdownASTNode$NodeType;
|
|
63
|
+
|
|
64
|
+
# Utilities
|
|
65
|
+
Lcom/swmansion/enriched/markdown/utils/UtilsKt;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#include "MD4CParser.hpp"
|
|
2
|
+
#include <android/log.h>
|
|
3
|
+
#include <jni.h>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
using namespace Markdown;
|
|
7
|
+
|
|
8
|
+
#define ENRICHEDMARKDOWN_LOG_TAG "EnrichedMarkdownJNI"
|
|
9
|
+
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, ENRICHEDMARKDOWN_LOG_TAG, __VA_ARGS__)
|
|
10
|
+
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, ENRICHEDMARKDOWN_LOG_TAG, __VA_ARGS__)
|
|
11
|
+
|
|
12
|
+
// Helper function to convert C++ NodeType to Kotlin enum ordinal
|
|
13
|
+
static jint nodeTypeToJavaOrdinal(NodeType type) {
|
|
14
|
+
switch (type) {
|
|
15
|
+
case NodeType::Document:
|
|
16
|
+
return 0;
|
|
17
|
+
case NodeType::Paragraph:
|
|
18
|
+
return 1;
|
|
19
|
+
case NodeType::Text:
|
|
20
|
+
return 2;
|
|
21
|
+
case NodeType::Link:
|
|
22
|
+
return 3;
|
|
23
|
+
case NodeType::Heading:
|
|
24
|
+
return 4;
|
|
25
|
+
case NodeType::LineBreak:
|
|
26
|
+
return 5;
|
|
27
|
+
case NodeType::Strong:
|
|
28
|
+
return 6;
|
|
29
|
+
case NodeType::Emphasis:
|
|
30
|
+
return 7;
|
|
31
|
+
case NodeType::Code:
|
|
32
|
+
return 8;
|
|
33
|
+
case NodeType::Image:
|
|
34
|
+
return 9;
|
|
35
|
+
case NodeType::Blockquote:
|
|
36
|
+
return 10;
|
|
37
|
+
case NodeType::UnorderedList:
|
|
38
|
+
return 11;
|
|
39
|
+
case NodeType::OrderedList:
|
|
40
|
+
return 12;
|
|
41
|
+
case NodeType::ListItem:
|
|
42
|
+
return 13;
|
|
43
|
+
case NodeType::CodeBlock:
|
|
44
|
+
return 14;
|
|
45
|
+
case NodeType::ThematicBreak:
|
|
46
|
+
return 15;
|
|
47
|
+
default:
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Helper function to create a Kotlin MarkdownASTNode object from C++ AST node
|
|
53
|
+
static jobject createJavaNode(JNIEnv *env, std::shared_ptr<MarkdownASTNode> node) {
|
|
54
|
+
if (!node) {
|
|
55
|
+
return nullptr;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Find the MarkdownASTNode class
|
|
59
|
+
jclass nodeClass = env->FindClass("com/swmansion/enriched/markdown/parser/MarkdownASTNode");
|
|
60
|
+
if (!nodeClass) {
|
|
61
|
+
LOGE("Failed to find MarkdownASTNode class");
|
|
62
|
+
return nullptr;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Find the NodeType enum class
|
|
66
|
+
jclass nodeTypeClass = env->FindClass("com/swmansion/enriched/markdown/parser/MarkdownASTNode$NodeType");
|
|
67
|
+
if (!nodeTypeClass) {
|
|
68
|
+
LOGE("Failed to find NodeType enum class");
|
|
69
|
+
return nullptr;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Get the enum values array
|
|
73
|
+
jmethodID valuesMethod = env->GetStaticMethodID(
|
|
74
|
+
nodeTypeClass, "values", "()[Lcom/swmansion/enriched/markdown/parser/MarkdownASTNode$NodeType;");
|
|
75
|
+
if (!valuesMethod) {
|
|
76
|
+
LOGE("Failed to find NodeType.values() method");
|
|
77
|
+
return nullptr;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
jobjectArray enumValues = (jobjectArray)env->CallStaticObjectMethod(nodeTypeClass, valuesMethod);
|
|
81
|
+
if (!enumValues) {
|
|
82
|
+
LOGE("Failed to get NodeType enum values");
|
|
83
|
+
return nullptr;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Get the enum value for this node type
|
|
87
|
+
jint ordinal = nodeTypeToJavaOrdinal(node->type);
|
|
88
|
+
jobject nodeTypeEnum = env->GetObjectArrayElement(enumValues, ordinal);
|
|
89
|
+
if (!nodeTypeEnum) {
|
|
90
|
+
LOGE("Failed to get NodeType enum value at index %d", ordinal);
|
|
91
|
+
return nullptr;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Create content string
|
|
95
|
+
jstring contentStr = env->NewStringUTF(node->content.c_str());
|
|
96
|
+
if (!contentStr && !node->content.empty()) {
|
|
97
|
+
LOGE("Failed to create content string");
|
|
98
|
+
return nullptr;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Create attributes HashMap
|
|
102
|
+
jclass mapClass = env->FindClass("java/util/HashMap");
|
|
103
|
+
jmethodID mapInit = env->GetMethodID(mapClass, "<init>", "(I)V");
|
|
104
|
+
jmethodID mapPut = env->GetMethodID(mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
|
105
|
+
|
|
106
|
+
jobject attributesMap = env->NewObject(mapClass, mapInit, static_cast<jint>(node->attributes.size()));
|
|
107
|
+
|
|
108
|
+
for (const auto &pair : node->attributes) {
|
|
109
|
+
jstring key = env->NewStringUTF(pair.first.c_str());
|
|
110
|
+
jstring value = env->NewStringUTF(pair.second.c_str());
|
|
111
|
+
env->CallObjectMethod(attributesMap, mapPut, key, value);
|
|
112
|
+
env->DeleteLocalRef(key);
|
|
113
|
+
env->DeleteLocalRef(value);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Create children ArrayList
|
|
117
|
+
jclass listClass = env->FindClass("java/util/ArrayList");
|
|
118
|
+
jmethodID listInit = env->GetMethodID(listClass, "<init>", "(I)V");
|
|
119
|
+
jmethodID listAdd = env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
|
|
120
|
+
|
|
121
|
+
jobject childrenList = env->NewObject(listClass, listInit, static_cast<jint>(node->children.size()));
|
|
122
|
+
|
|
123
|
+
for (const auto &child : node->children) {
|
|
124
|
+
jobject childObj = createJavaNode(env, child);
|
|
125
|
+
if (childObj) {
|
|
126
|
+
env->CallBooleanMethod(childrenList, listAdd, childObj);
|
|
127
|
+
env->DeleteLocalRef(childObj);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Find the MarkdownASTNode constructor
|
|
132
|
+
// Constructor signature: (Lcom/swmansion/enriched/markdown/parser/MarkdownASTNode$NodeType;Ljava/lang/String;Ljava/util/Map;Ljava/util/List;)V
|
|
133
|
+
jmethodID constructor = env->GetMethodID(nodeClass, "<init>",
|
|
134
|
+
"(Lcom/swmansion/enriched/markdown/parser/MarkdownASTNode$NodeType;Ljava/"
|
|
135
|
+
"lang/String;Ljava/util/Map;Ljava/util/List;)V");
|
|
136
|
+
if (!constructor) {
|
|
137
|
+
LOGE("Failed to find MarkdownASTNode constructor");
|
|
138
|
+
return nullptr;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Create the Kotlin MarkdownASTNode object
|
|
142
|
+
jobject javaNode = env->NewObject(nodeClass, constructor, nodeTypeEnum, contentStr, attributesMap, childrenList);
|
|
143
|
+
|
|
144
|
+
// Clean up local references
|
|
145
|
+
env->DeleteLocalRef(nodeTypeClass);
|
|
146
|
+
env->DeleteLocalRef(enumValues);
|
|
147
|
+
env->DeleteLocalRef(nodeTypeEnum);
|
|
148
|
+
if (contentStr)
|
|
149
|
+
env->DeleteLocalRef(contentStr);
|
|
150
|
+
env->DeleteLocalRef(attributesMap);
|
|
151
|
+
env->DeleteLocalRef(childrenList);
|
|
152
|
+
|
|
153
|
+
return javaNode;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
extern "C" {
|
|
157
|
+
|
|
158
|
+
JNIEXPORT jobject JNICALL Java_com_swmansion_enriched_markdown_parser_Parser_nativeParseMarkdown(JNIEnv *env,
|
|
159
|
+
jobject /* this */,
|
|
160
|
+
jstring markdown) {
|
|
161
|
+
if (!markdown) {
|
|
162
|
+
LOGE("Markdown string is null");
|
|
163
|
+
return nullptr;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const char *markdownStr = env->GetStringUTFChars(markdown, nullptr);
|
|
167
|
+
if (!markdownStr) {
|
|
168
|
+
LOGE("Failed to get UTF-8 chars from markdown string");
|
|
169
|
+
return nullptr;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
// Parse markdown using C++ MD4CParser
|
|
174
|
+
MD4CParser parser;
|
|
175
|
+
auto ast = parser.parse(std::string(markdownStr));
|
|
176
|
+
|
|
177
|
+
env->ReleaseStringUTFChars(markdown, markdownStr);
|
|
178
|
+
|
|
179
|
+
if (!ast) {
|
|
180
|
+
LOGE("Parser returned null AST");
|
|
181
|
+
return nullptr;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Convert C++ AST to Kotlin MarkdownASTNode object
|
|
185
|
+
jobject javaNode = createJavaNode(env, ast);
|
|
186
|
+
|
|
187
|
+
if (!javaNode) {
|
|
188
|
+
LOGE("Failed to create Java node from AST");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return javaNode;
|
|
192
|
+
} catch (const std::exception &e) {
|
|
193
|
+
env->ReleaseStringUTFChars(markdown, markdownStr);
|
|
194
|
+
LOGE("Exception during parsing: %s", e.what());
|
|
195
|
+
return nullptr;
|
|
196
|
+
} catch (...) {
|
|
197
|
+
env->ReleaseStringUTFChars(markdown, markdownStr);
|
|
198
|
+
LOGE("Unknown exception during parsing");
|
|
199
|
+
return nullptr;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
} // extern "C"
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Color
|
|
5
|
+
import android.os.Handler
|
|
6
|
+
import android.os.Looper
|
|
7
|
+
import android.text.method.LinkMovementMethod
|
|
8
|
+
import android.util.AttributeSet
|
|
9
|
+
import android.util.Log
|
|
10
|
+
import androidx.appcompat.widget.AppCompatTextView
|
|
11
|
+
import com.facebook.react.bridge.ReadableMap
|
|
12
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
13
|
+
import com.swmansion.enriched.markdown.events.LinkPressEvent
|
|
14
|
+
import com.swmansion.enriched.markdown.parser.Parser
|
|
15
|
+
import com.swmansion.enriched.markdown.renderer.Renderer
|
|
16
|
+
import com.swmansion.enriched.markdown.styles.StyleConfig
|
|
17
|
+
import com.swmansion.enriched.markdown.utils.createSelectionActionModeCallback
|
|
18
|
+
import java.util.concurrent.Executors
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* EnrichedMarkdownText that handles Markdown parsing and rendering on a background thread.
|
|
22
|
+
* Utilizes PrecomputedText for smoother UI updates on supported Android versions.
|
|
23
|
+
*/
|
|
24
|
+
class EnrichedMarkdownText
|
|
25
|
+
@JvmOverloads
|
|
26
|
+
constructor(
|
|
27
|
+
context: Context,
|
|
28
|
+
attrs: AttributeSet? = null,
|
|
29
|
+
defStyleAttr: Int = 0,
|
|
30
|
+
) : AppCompatTextView(context, attrs, defStyleAttr) {
|
|
31
|
+
private val parser = Parser.shared
|
|
32
|
+
private val renderer = Renderer()
|
|
33
|
+
private var onLinkPressCallback: ((String) -> Unit)? = null
|
|
34
|
+
|
|
35
|
+
// Background processing tools
|
|
36
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
37
|
+
private val executor = Executors.newSingleThreadExecutor()
|
|
38
|
+
private var currentRenderId = 0L
|
|
39
|
+
|
|
40
|
+
val layoutManager = EnrichedMarkdownTextLayoutManager(this)
|
|
41
|
+
|
|
42
|
+
var markdownStyle: StyleConfig? = null
|
|
43
|
+
private set
|
|
44
|
+
|
|
45
|
+
var currentMarkdown: String = ""
|
|
46
|
+
private set
|
|
47
|
+
|
|
48
|
+
init {
|
|
49
|
+
setBackgroundColor(Color.TRANSPARENT)
|
|
50
|
+
includeFontPadding = false // Must match setIncludePad(false) in MeasurementStore
|
|
51
|
+
movementMethod = LinkMovementMethod.getInstance()
|
|
52
|
+
setTextIsSelectable(true)
|
|
53
|
+
customSelectionActionModeCallback = createSelectionActionModeCallback(this)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fun setMarkdownContent(markdown: String) {
|
|
57
|
+
if (currentMarkdown == markdown) return
|
|
58
|
+
currentMarkdown = markdown
|
|
59
|
+
scheduleRender()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fun setMarkdownStyle(style: ReadableMap?) {
|
|
63
|
+
val newStyle = style?.let { StyleConfig(it, context) }
|
|
64
|
+
if (markdownStyle == newStyle) return
|
|
65
|
+
|
|
66
|
+
markdownStyle = newStyle
|
|
67
|
+
scheduleRender()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private fun scheduleRender() {
|
|
71
|
+
val style = markdownStyle ?: return
|
|
72
|
+
val markdown = currentMarkdown
|
|
73
|
+
val renderId = ++currentRenderId
|
|
74
|
+
val scheduleStart = System.currentTimeMillis()
|
|
75
|
+
|
|
76
|
+
executor.execute {
|
|
77
|
+
try {
|
|
78
|
+
// 1. Parse Markdown → AST (C++ md4c parser)
|
|
79
|
+
val parseStart = System.currentTimeMillis()
|
|
80
|
+
val ast =
|
|
81
|
+
parser.parseMarkdown(markdown) ?: run {
|
|
82
|
+
mainHandler.post { if (renderId == currentRenderId) text = "" }
|
|
83
|
+
return@execute
|
|
84
|
+
}
|
|
85
|
+
val parseTime = System.currentTimeMillis() - parseStart
|
|
86
|
+
|
|
87
|
+
// 2. Render AST → Spannable
|
|
88
|
+
val renderStart = System.currentTimeMillis()
|
|
89
|
+
renderer.configure(style, context)
|
|
90
|
+
val styledText = renderer.renderDocument(ast, onLinkPressCallback)
|
|
91
|
+
val renderTime = System.currentTimeMillis() - renderStart
|
|
92
|
+
|
|
93
|
+
Log.i(TAG, "┌──────────────────────────────────────────────")
|
|
94
|
+
Log.i(TAG, "│ 📝 Input: ${markdown.length} chars of Markdown")
|
|
95
|
+
Log.i(TAG, "│ ⚡ md4c (C++ native): ${parseTime}ms → ${ast.children.size} AST nodes")
|
|
96
|
+
Log.i(TAG, "│ 🎨 Spannable render: ${renderTime}ms → ${styledText.length} styled chars")
|
|
97
|
+
Log.i(TAG, "└──────────────────────────────────────────────")
|
|
98
|
+
|
|
99
|
+
mainHandler.post {
|
|
100
|
+
if (renderId == currentRenderId) {
|
|
101
|
+
applyRenderedText(styledText)
|
|
102
|
+
Log.i(TAG, "✅ Total time to display: ${System.currentTimeMillis() - scheduleStart}ms")
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} catch (e: Exception) {
|
|
106
|
+
Log.e(TAG, "❌ Render failed: ${e.message}", e)
|
|
107
|
+
mainHandler.post { if (renderId == currentRenderId) text = "" }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private fun applyRenderedText(styledText: CharSequence) {
|
|
113
|
+
// Sets the text. If it's PrecomputedText, the UI thread skips the measure pass.
|
|
114
|
+
text = styledText
|
|
115
|
+
|
|
116
|
+
// LinkMovementMethod check (setText can sometimes reset it)
|
|
117
|
+
if (movementMethod !is LinkMovementMethod) {
|
|
118
|
+
movementMethod = LinkMovementMethod.getInstance()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Register ImageSpans from the collector
|
|
122
|
+
renderer.getCollectedImageSpans().forEach { span ->
|
|
123
|
+
span.registerTextView(this)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
layoutManager.invalidateLayout()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fun setIsSelectable(selectable: Boolean) {
|
|
130
|
+
if (isTextSelectable == selectable) return
|
|
131
|
+
setTextIsSelectable(selectable)
|
|
132
|
+
movementMethod = LinkMovementMethod.getInstance()
|
|
133
|
+
if (!selectable && !isClickable) isClickable = true
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
fun emitOnLinkPress(url: String) {
|
|
137
|
+
val reactContext = context as? com.facebook.react.bridge.ReactContext ?: return
|
|
138
|
+
val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
|
|
139
|
+
val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
|
|
140
|
+
|
|
141
|
+
dispatcher?.dispatchEvent(
|
|
142
|
+
LinkPressEvent(surfaceId, id, url),
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
fun setOnLinkPressCallback(callback: (String) -> Unit) {
|
|
147
|
+
onLinkPressCallback = callback
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
companion object {
|
|
151
|
+
private const val TAG = "EnrichedMarkdownMeasure"
|
|
152
|
+
}
|
|
153
|
+
}
|
package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
5
|
+
|
|
6
|
+
class EnrichedMarkdownTextLayoutManager(
|
|
7
|
+
private val view: EnrichedMarkdownText,
|
|
8
|
+
) {
|
|
9
|
+
private var forceHeightRecalculationCounter: Int = 0
|
|
10
|
+
|
|
11
|
+
var stateWrapper: StateWrapper? = null
|
|
12
|
+
|
|
13
|
+
fun invalidateLayout() {
|
|
14
|
+
val text = view.text
|
|
15
|
+
val paint = view.paint
|
|
16
|
+
|
|
17
|
+
val needUpdate = MeasurementStore.store(view.id, text, paint)
|
|
18
|
+
if (!needUpdate) return
|
|
19
|
+
|
|
20
|
+
val counter = forceHeightRecalculationCounter
|
|
21
|
+
forceHeightRecalculationCounter++
|
|
22
|
+
val state = Arguments.createMap()
|
|
23
|
+
state.putInt("forceHeightRecalculationCounter", counter)
|
|
24
|
+
stateWrapper?.updateState(state)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
fun releaseMeasurementStore() {
|
|
28
|
+
MeasurementStore.release(view.id)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap
|
|
5
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
6
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
|
7
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
8
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
9
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
10
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
11
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
12
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
13
|
+
import com.facebook.react.viewmanagers.EnrichedMarkdownTextManagerDelegate
|
|
14
|
+
import com.facebook.react.viewmanagers.EnrichedMarkdownTextManagerInterface
|
|
15
|
+
import com.facebook.yoga.YogaMeasureMode
|
|
16
|
+
import com.swmansion.enriched.markdown.events.LinkPressEvent
|
|
17
|
+
|
|
18
|
+
@ReactModule(name = EnrichedMarkdownTextManager.NAME)
|
|
19
|
+
class EnrichedMarkdownTextManager :
|
|
20
|
+
SimpleViewManager<EnrichedMarkdownText>(),
|
|
21
|
+
EnrichedMarkdownTextManagerInterface<EnrichedMarkdownText> {
|
|
22
|
+
private val mDelegate: ViewManagerDelegate<EnrichedMarkdownText> = EnrichedMarkdownTextManagerDelegate(this)
|
|
23
|
+
|
|
24
|
+
override fun getDelegate(): ViewManagerDelegate<EnrichedMarkdownText>? = mDelegate
|
|
25
|
+
|
|
26
|
+
override fun getName(): String = NAME
|
|
27
|
+
|
|
28
|
+
override fun createViewInstance(reactContext: ThemedReactContext): EnrichedMarkdownText = EnrichedMarkdownText(reactContext)
|
|
29
|
+
|
|
30
|
+
override fun onDropViewInstance(view: EnrichedMarkdownText) {
|
|
31
|
+
super.onDropViewInstance(view)
|
|
32
|
+
view.layoutManager.releaseMeasurementStore()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override fun updateState(
|
|
36
|
+
view: EnrichedMarkdownText,
|
|
37
|
+
props: ReactStylesDiffMap?,
|
|
38
|
+
stateWrapper: StateWrapper?,
|
|
39
|
+
): Any? {
|
|
40
|
+
view.layoutManager.stateWrapper = stateWrapper
|
|
41
|
+
return super.updateState(view, props, stateWrapper)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
|
|
45
|
+
val map = mutableMapOf<String, Any>()
|
|
46
|
+
map.put(LinkPressEvent.EVENT_NAME, mapOf("registrationName" to LinkPressEvent.EVENT_NAME))
|
|
47
|
+
return map
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@ReactProp(name = "markdown")
|
|
51
|
+
override fun setMarkdown(
|
|
52
|
+
view: EnrichedMarkdownText?,
|
|
53
|
+
markdown: String?,
|
|
54
|
+
) {
|
|
55
|
+
view?.setOnLinkPressCallback { url ->
|
|
56
|
+
emitOnLinkPress(view, url)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
view?.setMarkdownContent(markdown ?: "No markdown content")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@ReactProp(name = "markdownStyle")
|
|
63
|
+
override fun setMarkdownStyle(
|
|
64
|
+
view: EnrichedMarkdownText?,
|
|
65
|
+
style: com.facebook.react.bridge.ReadableMap?,
|
|
66
|
+
) {
|
|
67
|
+
view?.setMarkdownStyle(style)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@ReactProp(name = "isSelectable", defaultBoolean = true)
|
|
71
|
+
override fun setIsSelectable(
|
|
72
|
+
view: EnrichedMarkdownText?,
|
|
73
|
+
selectable: Boolean,
|
|
74
|
+
) {
|
|
75
|
+
view?.setIsSelectable(selectable)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
override fun setPadding(
|
|
79
|
+
view: EnrichedMarkdownText,
|
|
80
|
+
left: Int,
|
|
81
|
+
top: Int,
|
|
82
|
+
right: Int,
|
|
83
|
+
bottom: Int,
|
|
84
|
+
) {
|
|
85
|
+
super.setPadding(view, left, top, right, bottom)
|
|
86
|
+
view.setPadding(left, top, right, bottom)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private fun emitOnLinkPress(
|
|
90
|
+
view: EnrichedMarkdownText,
|
|
91
|
+
url: String,
|
|
92
|
+
) {
|
|
93
|
+
val context = view.context as com.facebook.react.bridge.ReactContext
|
|
94
|
+
val surfaceId = UIManagerHelper.getSurfaceId(context)
|
|
95
|
+
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.id)
|
|
96
|
+
val event = LinkPressEvent(surfaceId, view.id, url)
|
|
97
|
+
|
|
98
|
+
eventDispatcher?.dispatchEvent(event)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
override fun measure(
|
|
102
|
+
context: Context,
|
|
103
|
+
localData: ReadableMap?,
|
|
104
|
+
props: ReadableMap?,
|
|
105
|
+
state: ReadableMap?,
|
|
106
|
+
width: Float,
|
|
107
|
+
widthMode: YogaMeasureMode?,
|
|
108
|
+
height: Float,
|
|
109
|
+
heightMode: YogaMeasureMode?,
|
|
110
|
+
attachmentsPositions: FloatArray?,
|
|
111
|
+
): Long {
|
|
112
|
+
val id = localData?.getInt("viewTag")
|
|
113
|
+
return MeasurementStore.getMeasureById(context, id, width, height, heightMode, props)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
companion object {
|
|
117
|
+
const val NAME = "EnrichedMarkdownText"
|
|
118
|
+
}
|
|
119
|
+
}
|