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.
Files changed (211) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +479 -0
  3. package/ReactNativeEnrichedMarkdown.podspec +27 -0
  4. package/android/build.gradle +101 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +39 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +21 -0
  7. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +22 -0
  8. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.h +24 -0
  9. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +24 -0
  10. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +25 -0
  11. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +57 -0
  12. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +1164 -0
  13. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.cpp +17 -0
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.h +32 -0
  15. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.cpp +16 -0
  16. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.h +20 -0
  17. package/android/gradle.properties +5 -0
  18. package/android/src/main/AndroidManifest.xml +2 -0
  19. package/android/src/main/baseline-prof.txt +65 -0
  20. package/android/src/main/cpp/jni-adapter.cpp +203 -0
  21. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +153 -0
  22. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +30 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +119 -0
  24. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextPackage.kt +17 -0
  25. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +165 -0
  26. package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkPressEvent.kt +23 -0
  27. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +29 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +48 -0
  29. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +166 -0
  30. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +89 -0
  31. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +105 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeRenderer.kt +35 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/DocumentRenderer.kt +15 -0
  34. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/EmphasisRenderer.kt +26 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +54 -0
  36. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ImageRenderer.kt +52 -0
  37. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LineBreakRenderer.kt +15 -0
  38. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +28 -0
  39. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +105 -0
  40. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +58 -0
  41. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +69 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +99 -0
  43. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ParagraphRenderer.kt +66 -0
  44. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/Renderer.kt +95 -0
  45. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +85 -0
  46. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/StrongRenderer.kt +26 -0
  47. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/TextRenderer.kt +29 -0
  48. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ThematicBreakRenderer.kt +44 -0
  49. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +136 -0
  50. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +135 -0
  51. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +180 -0
  52. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +196 -0
  53. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +27 -0
  54. package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +34 -0
  55. package/android/src/main/java/com/swmansion/enriched/markdown/spans/HeadingSpan.kt +38 -0
  56. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +320 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LineHeightSpan.kt +36 -0
  58. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +37 -0
  59. package/android/src/main/java/com/swmansion/enriched/markdown/spans/MarginBottomSpan.kt +76 -0
  60. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +87 -0
  61. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +37 -0
  62. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TextSpan.kt +26 -0
  63. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ThematicBreakSpan.kt +69 -0
  64. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +69 -0
  65. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BaseBlockStyle.kt +10 -0
  66. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +48 -0
  67. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +51 -0
  68. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeStyle.kt +21 -0
  69. package/android/src/main/java/com/swmansion/enriched/markdown/styles/EmphasisStyle.kt +17 -0
  70. package/android/src/main/java/com/swmansion/enriched/markdown/styles/HeadingStyle.kt +29 -0
  71. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +21 -0
  72. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineImageStyle.kt +17 -0
  73. package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +19 -0
  74. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +54 -0
  75. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ParagraphStyle.kt +29 -0
  76. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StrongStyle.kt +17 -0
  77. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +180 -0
  78. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleParser.kt +75 -0
  79. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ThematicBreakStyle.kt +23 -0
  80. package/android/src/main/java/com/swmansion/enriched/markdown/utils/AsyncDrawable.kt +91 -0
  81. package/android/src/main/java/com/swmansion/enriched/markdown/utils/HTMLGenerator.kt +809 -0
  82. package/android/src/main/java/com/swmansion/enriched/markdown/utils/MarkdownExtractor.kt +365 -0
  83. package/android/src/main/java/com/swmansion/enriched/markdown/utils/SelectionActionMode.kt +139 -0
  84. package/android/src/main/java/com/swmansion/enriched/markdown/utils/Utils.kt +181 -0
  85. package/android/src/main/jni/CMakeLists.txt +82 -0
  86. package/android/src/main/jni/EnrichedMarkdownTextSpec.cpp +21 -0
  87. package/android/src/main/jni/EnrichedMarkdownTextSpec.h +25 -0
  88. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextComponentDescriptor.h +29 -0
  89. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextMeasurementManager.cpp +45 -0
  90. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextMeasurementManager.h +21 -0
  91. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +33 -0
  92. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +49 -0
  93. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
  94. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +25 -0
  95. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +19 -0
  96. package/cpp/md4c/md4c.c +6492 -0
  97. package/cpp/md4c/md4c.h +402 -0
  98. package/cpp/parser/MD4CParser.cpp +314 -0
  99. package/cpp/parser/MD4CParser.hpp +23 -0
  100. package/cpp/parser/MarkdownASTNode.hpp +49 -0
  101. package/ios/EnrichedMarkdownText.h +18 -0
  102. package/ios/EnrichedMarkdownText.mm +1074 -0
  103. package/ios/attachments/ImageAttachment.h +23 -0
  104. package/ios/attachments/ImageAttachment.m +185 -0
  105. package/ios/attachments/ThematicBreakAttachment.h +15 -0
  106. package/ios/attachments/ThematicBreakAttachment.m +33 -0
  107. package/ios/generated/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +22 -0
  108. package/ios/generated/EnrichedMarkdownTextSpec/ComponentDescriptors.h +24 -0
  109. package/ios/generated/EnrichedMarkdownTextSpec/EventEmitters.cpp +24 -0
  110. package/ios/generated/EnrichedMarkdownTextSpec/EventEmitters.h +25 -0
  111. package/ios/generated/EnrichedMarkdownTextSpec/Props.cpp +57 -0
  112. package/ios/generated/EnrichedMarkdownTextSpec/Props.h +1164 -0
  113. package/ios/generated/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +20 -0
  114. package/ios/generated/EnrichedMarkdownTextSpec/ShadowNodes.cpp +17 -0
  115. package/ios/generated/EnrichedMarkdownTextSpec/ShadowNodes.h +32 -0
  116. package/ios/generated/EnrichedMarkdownTextSpec/States.cpp +16 -0
  117. package/ios/generated/EnrichedMarkdownTextSpec/States.h +20 -0
  118. package/ios/internals/EnrichedMarkdownTextComponentDescriptor.h +19 -0
  119. package/ios/internals/EnrichedMarkdownTextShadowNode.h +43 -0
  120. package/ios/internals/EnrichedMarkdownTextShadowNode.mm +85 -0
  121. package/ios/internals/EnrichedMarkdownTextState.h +24 -0
  122. package/ios/parser/MarkdownASTNode.h +33 -0
  123. package/ios/parser/MarkdownASTNode.m +32 -0
  124. package/ios/parser/MarkdownParser.h +8 -0
  125. package/ios/parser/MarkdownParser.mm +13 -0
  126. package/ios/parser/MarkdownParserBridge.mm +110 -0
  127. package/ios/renderer/AttributedRenderer.h +9 -0
  128. package/ios/renderer/AttributedRenderer.m +119 -0
  129. package/ios/renderer/BlockquoteRenderer.h +7 -0
  130. package/ios/renderer/BlockquoteRenderer.m +159 -0
  131. package/ios/renderer/CodeBlockRenderer.h +10 -0
  132. package/ios/renderer/CodeBlockRenderer.m +89 -0
  133. package/ios/renderer/CodeRenderer.h +10 -0
  134. package/ios/renderer/CodeRenderer.m +60 -0
  135. package/ios/renderer/EmphasisRenderer.h +6 -0
  136. package/ios/renderer/EmphasisRenderer.m +96 -0
  137. package/ios/renderer/HeadingRenderer.h +7 -0
  138. package/ios/renderer/HeadingRenderer.m +98 -0
  139. package/ios/renderer/ImageRenderer.h +12 -0
  140. package/ios/renderer/ImageRenderer.m +62 -0
  141. package/ios/renderer/LinkRenderer.h +7 -0
  142. package/ios/renderer/LinkRenderer.m +69 -0
  143. package/ios/renderer/ListItemRenderer.h +16 -0
  144. package/ios/renderer/ListItemRenderer.m +91 -0
  145. package/ios/renderer/ListRenderer.h +13 -0
  146. package/ios/renderer/ListRenderer.m +67 -0
  147. package/ios/renderer/NodeRenderer.h +8 -0
  148. package/ios/renderer/ParagraphRenderer.h +7 -0
  149. package/ios/renderer/ParagraphRenderer.m +69 -0
  150. package/ios/renderer/RenderContext.h +88 -0
  151. package/ios/renderer/RenderContext.m +248 -0
  152. package/ios/renderer/RendererFactory.h +12 -0
  153. package/ios/renderer/RendererFactory.m +110 -0
  154. package/ios/renderer/StrongRenderer.h +6 -0
  155. package/ios/renderer/StrongRenderer.m +83 -0
  156. package/ios/renderer/TextRenderer.h +6 -0
  157. package/ios/renderer/TextRenderer.m +16 -0
  158. package/ios/renderer/ThematicBreakRenderer.h +5 -0
  159. package/ios/renderer/ThematicBreakRenderer.m +53 -0
  160. package/ios/styles/StyleConfig.h +228 -0
  161. package/ios/styles/StyleConfig.mm +1467 -0
  162. package/ios/utils/BlockquoteBorder.h +20 -0
  163. package/ios/utils/BlockquoteBorder.m +92 -0
  164. package/ios/utils/CodeBackground.h +19 -0
  165. package/ios/utils/CodeBackground.m +191 -0
  166. package/ios/utils/CodeBlockBackground.h +17 -0
  167. package/ios/utils/CodeBlockBackground.m +87 -0
  168. package/ios/utils/EditMenuUtils.h +22 -0
  169. package/ios/utils/EditMenuUtils.m +118 -0
  170. package/ios/utils/FontUtils.h +20 -0
  171. package/ios/utils/FontUtils.m +13 -0
  172. package/ios/utils/HTMLGenerator.h +20 -0
  173. package/ios/utils/HTMLGenerator.m +779 -0
  174. package/ios/utils/LastElementUtils.h +53 -0
  175. package/ios/utils/ListMarkerDrawer.h +15 -0
  176. package/ios/utils/ListMarkerDrawer.m +127 -0
  177. package/ios/utils/MarkdownExtractor.h +17 -0
  178. package/ios/utils/MarkdownExtractor.m +295 -0
  179. package/ios/utils/ParagraphStyleUtils.h +13 -0
  180. package/ios/utils/ParagraphStyleUtils.m +56 -0
  181. package/ios/utils/PasteboardUtils.h +36 -0
  182. package/ios/utils/PasteboardUtils.m +134 -0
  183. package/ios/utils/RTFExportUtils.h +24 -0
  184. package/ios/utils/RTFExportUtils.m +297 -0
  185. package/ios/utils/RuntimeKeys.h +38 -0
  186. package/ios/utils/RuntimeKeys.m +11 -0
  187. package/ios/utils/TextViewLayoutManager.h +14 -0
  188. package/ios/utils/TextViewLayoutManager.mm +113 -0
  189. package/lib/module/EnrichedMarkdownText.js +34 -0
  190. package/lib/module/EnrichedMarkdownText.js.map +1 -0
  191. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +130 -0
  192. package/lib/module/index.js +5 -0
  193. package/lib/module/index.js.map +1 -0
  194. package/lib/module/normalizeMarkdownStyle.js +340 -0
  195. package/lib/module/normalizeMarkdownStyle.js.map +1 -0
  196. package/lib/module/package.json +1 -0
  197. package/lib/typescript/package.json +1 -0
  198. package/lib/typescript/src/EnrichedMarkdownText.d.ts +101 -0
  199. package/lib/typescript/src/EnrichedMarkdownText.d.ts.map +1 -0
  200. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +111 -0
  201. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -0
  202. package/lib/typescript/src/index.d.ts +5 -0
  203. package/lib/typescript/src/index.d.ts.map +1 -0
  204. package/lib/typescript/src/normalizeMarkdownStyle.d.ts +6 -0
  205. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -0
  206. package/package.json +186 -1
  207. package/react-native.config.js +13 -0
  208. package/src/EnrichedMarkdownText.tsx +152 -0
  209. package/src/EnrichedMarkdownTextNativeComponent.ts +130 -0
  210. package/src/index.tsx +7 -0
  211. package/src/normalizeMarkdownStyle.ts +377 -0
@@ -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: GenerateComponentHObjCpp.js
8
+ */
9
+
10
+ #import <Foundation/Foundation.h>
11
+ #import <React/RCTDefines.h>
12
+ #import <React/RCTLog.h>
13
+
14
+ NS_ASSUME_NONNULL_BEGIN
15
+
16
+ @protocol RCTEnrichedMarkdownTextViewProtocol <NSObject>
17
+
18
+ @end
19
+
20
+ NS_ASSUME_NONNULL_END
@@ -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
@@ -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,19 @@
1
+ #pragma once
2
+ #include "EnrichedMarkdownTextShadowNode.h"
3
+ #include <react/debug/react_native_assert.h>
4
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
5
+
6
+ namespace facebook::react {
7
+
8
+ class EnrichedMarkdownTextComponentDescriptor final
9
+ : public ConcreteComponentDescriptor<EnrichedMarkdownTextShadowNode> {
10
+ public:
11
+ using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
12
+
13
+ void adopt(ShadowNode &shadowNode) const override {
14
+ react_native_assert(dynamic_cast<EnrichedMarkdownTextShadowNode *>(&shadowNode));
15
+ ConcreteComponentDescriptor::adopt(shadowNode);
16
+ }
17
+ };
18
+
19
+ } // namespace facebook::react
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+ #include <ReactNativeEnrichedMarkdown/EnrichedMarkdownTextState.h>
3
+ #include <ReactNativeEnrichedMarkdown/EventEmitters.h>
4
+ #include <ReactNativeEnrichedMarkdown/Props.h>
5
+ #include <react/renderer/components/view/ConcreteViewShadowNode.h>
6
+ #include <react/renderer/core/LayoutConstraints.h>
7
+
8
+ namespace facebook::react {
9
+
10
+ JSI_EXPORT extern const char EnrichedMarkdownTextComponentName[];
11
+
12
+ /// ShadowNode implementing measureContent for automatic height calculation.
13
+ class EnrichedMarkdownTextShadowNode
14
+ : public ConcreteViewShadowNode<EnrichedMarkdownTextComponentName, EnrichedMarkdownTextProps,
15
+ EnrichedMarkdownTextEventEmitter, EnrichedMarkdownTextState> {
16
+ public:
17
+ using ConcreteViewShadowNode::ConcreteViewShadowNode;
18
+
19
+ EnrichedMarkdownTextShadowNode(const ShadowNodeFragment &fragment, const ShadowNodeFamily::Shared &family,
20
+ ShadowNodeTraits traits);
21
+
22
+ EnrichedMarkdownTextShadowNode(const ShadowNode &sourceShadowNode, const ShadowNodeFragment &fragment);
23
+
24
+ void dirtyLayoutIfNeeded();
25
+
26
+ Size measureContent(const LayoutContext &layoutContext, const LayoutConstraints &layoutConstraints) const override;
27
+
28
+ static ShadowNodeTraits BaseTraits()
29
+ {
30
+ auto traits = ConcreteViewShadowNode::BaseTraits();
31
+ traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
32
+ traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode);
33
+ return traits;
34
+ }
35
+
36
+ private:
37
+ int localHeightRecalculationCounter_{0};
38
+
39
+ // Creates mock view off-screen for initial measurement when real view doesn't exist
40
+ id setupMockEnrichedMarkdownText_(CGFloat width) const;
41
+ };
42
+
43
+ } // namespace facebook::react
@@ -0,0 +1,85 @@
1
+ #import "EnrichedMarkdownTextShadowNode.h"
2
+ #import "EnrichedMarkdownText.h"
3
+ #import <react/utils/ManagedObjectWrapper.h>
4
+ #import <yoga/Yoga.h>
5
+
6
+ namespace facebook::react {
7
+
8
+ extern const char EnrichedMarkdownTextComponentName[] = "EnrichedMarkdownText";
9
+
10
+ EnrichedMarkdownTextShadowNode::EnrichedMarkdownTextShadowNode(const ShadowNodeFragment &fragment,
11
+ const ShadowNodeFamily::Shared &family,
12
+ ShadowNodeTraits traits)
13
+ : ConcreteViewShadowNode(fragment, family, traits)
14
+ {
15
+ }
16
+
17
+ EnrichedMarkdownTextShadowNode::EnrichedMarkdownTextShadowNode(const ShadowNode &sourceShadowNode,
18
+ const ShadowNodeFragment &fragment)
19
+ : ConcreteViewShadowNode(sourceShadowNode, fragment)
20
+ {
21
+ dirtyLayoutIfNeeded();
22
+ }
23
+
24
+ void EnrichedMarkdownTextShadowNode::dirtyLayoutIfNeeded()
25
+ {
26
+ const auto state = this->getStateData();
27
+ const int receivedCounter = state.getHeightRecalculationCounter();
28
+
29
+ if (receivedCounter > localHeightRecalculationCounter_) {
30
+ localHeightRecalculationCounter_ = receivedCounter;
31
+ YGNodeMarkDirty(&yogaNode_);
32
+ }
33
+ }
34
+
35
+ /// Creates a mock view off-screen to measure content when real view isn't ready yet.
36
+ id EnrichedMarkdownTextShadowNode::setupMockEnrichedMarkdownText_(CGFloat width) const
37
+ {
38
+ EnrichedMarkdownText *mockView = [[EnrichedMarkdownText alloc] initWithFrame:CGRectMake(20000, 20000, width, 1000)];
39
+
40
+ const auto props = this->getProps();
41
+ [mockView updateProps:props oldProps:nullptr];
42
+
43
+ // Render markdown synchronously for accurate measurement
44
+ const auto &typedProps = *std::static_pointer_cast<const EnrichedMarkdownTextProps>(props);
45
+ if (!typedProps.markdown.empty()) {
46
+ NSString *markdown = [NSString stringWithUTF8String:typedProps.markdown.c_str()];
47
+ [mockView renderMarkdownSynchronously:markdown];
48
+ }
49
+
50
+ return mockView;
51
+ }
52
+
53
+ Size EnrichedMarkdownTextShadowNode::measureContent(const LayoutContext &layoutContext,
54
+ const LayoutConstraints &layoutConstraints) const
55
+ {
56
+ CGFloat maxWidth = layoutConstraints.maximumSize.width;
57
+ CGFloat maxHeight = layoutConstraints.maximumSize.height;
58
+
59
+ RCTInternalGenericWeakWrapper *weakWrapper =
60
+ (RCTInternalGenericWeakWrapper *)unwrapManagedObject(getStateData().getComponentViewRef());
61
+ EnrichedMarkdownText *view = weakWrapper ? (EnrichedMarkdownText *)weakWrapper.object : nil;
62
+
63
+ __block CGSize size;
64
+
65
+ // Measure on main thread (required for UIKit)
66
+ void (^measureBlock)(void) = ^{
67
+ if (view) {
68
+ size = [view measureSize:maxWidth];
69
+ } else {
70
+ // No view yet - create mock view for accurate initial measurement
71
+ EnrichedMarkdownText *mockView = setupMockEnrichedMarkdownText_(maxWidth);
72
+ size = [mockView measureSize:maxWidth];
73
+ }
74
+ };
75
+
76
+ if ([NSThread isMainThread]) {
77
+ measureBlock();
78
+ } else {
79
+ dispatch_sync(dispatch_get_main_queue(), measureBlock);
80
+ }
81
+
82
+ return {size.width, MIN(size.height, maxHeight)};
83
+ }
84
+
85
+ } // namespace facebook::react
@@ -0,0 +1,24 @@
1
+ #pragma once
2
+ #include <memory>
3
+
4
+ namespace facebook::react {
5
+
6
+ /// Counter triggers layout recalculation, viewRef allows shadow node to access view for measurement.
7
+ class EnrichedMarkdownTextState {
8
+ public:
9
+ EnrichedMarkdownTextState() = default;
10
+ EnrichedMarkdownTextState(int counter, std::shared_ptr<void> ref) : counter_(counter), viewRef_(ref) {}
11
+
12
+ int getHeightRecalculationCounter() const {
13
+ return counter_;
14
+ }
15
+ std::shared_ptr<void> getComponentViewRef() const {
16
+ return viewRef_;
17
+ }
18
+
19
+ private:
20
+ int counter_{0};
21
+ std::shared_ptr<void> viewRef_{nullptr};
22
+ };
23
+
24
+ } // namespace facebook::react
@@ -0,0 +1,33 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ typedef NS_ENUM(NSInteger, MarkdownNodeType) {
4
+ MarkdownNodeTypeDocument,
5
+ MarkdownNodeTypeParagraph,
6
+ MarkdownNodeTypeText,
7
+ MarkdownNodeTypeLink,
8
+ MarkdownNodeTypeHeading,
9
+ MarkdownNodeTypeLineBreak,
10
+ MarkdownNodeTypeStrong,
11
+ MarkdownNodeTypeEmphasis,
12
+ MarkdownNodeTypeCode,
13
+ MarkdownNodeTypeImage,
14
+ MarkdownNodeTypeBlockquote,
15
+ MarkdownNodeTypeUnorderedList,
16
+ MarkdownNodeTypeOrderedList,
17
+ MarkdownNodeTypeListItem,
18
+ MarkdownNodeTypeCodeBlock,
19
+ MarkdownNodeTypeThematicBreak
20
+ };
21
+
22
+ @interface MarkdownASTNode : NSObject
23
+
24
+ @property (nonatomic, assign) MarkdownNodeType type;
25
+ @property (nonatomic, strong) NSString *content;
26
+ @property (nonatomic, strong) NSMutableDictionary *attributes;
27
+ @property (nonatomic, strong) NSMutableArray<MarkdownASTNode *> *children;
28
+
29
+ - (instancetype)initWithType:(MarkdownNodeType)type;
30
+ - (void)addChild:(MarkdownASTNode *)child;
31
+ - (void)setAttribute:(NSString *)key value:(NSString *)value;
32
+
33
+ @end
@@ -0,0 +1,32 @@
1
+ #import "MarkdownASTNode.h"
2
+
3
+ @implementation MarkdownASTNode
4
+
5
+ - (instancetype)initWithType:(MarkdownNodeType)type
6
+ {
7
+ if (self = [super init]) {
8
+ _type = type;
9
+ _content = nil;
10
+ _attributes = [[NSMutableDictionary alloc] init];
11
+ _children = [[NSMutableArray alloc] init];
12
+ }
13
+ return self;
14
+ }
15
+
16
+ - (void)addChild:(MarkdownASTNode *)child
17
+ {
18
+ [_children addObject:child];
19
+ }
20
+
21
+ - (void)setAttribute:(NSString *)key value:(NSString *)value
22
+ {
23
+ _attributes[key] = value;
24
+ }
25
+
26
+ - (NSString *)description
27
+ {
28
+ return [NSString stringWithFormat:@"MarkdownASTNode(type=%ld, content=%@, children=%lu)", (long)_type, _content,
29
+ (unsigned long)_children.count];
30
+ }
31
+
32
+ @end
@@ -0,0 +1,8 @@
1
+ #import "MarkdownASTNode.h"
2
+ #import <Foundation/Foundation.h>
3
+
4
+ @interface MarkdownParser : NSObject
5
+
6
+ - (MarkdownASTNode *)parseMarkdown:(NSString *)markdown;
7
+
8
+ @end
@@ -0,0 +1,13 @@
1
+ #import "MarkdownParser.h"
2
+ #import "MarkdownASTNode.h"
3
+
4
+ extern MarkdownASTNode *parseMarkdownWithCppParser(NSString *markdown);
5
+
6
+ @implementation MarkdownParser
7
+
8
+ - (MarkdownASTNode *)parseMarkdown:(NSString *)markdown
9
+ {
10
+ return parseMarkdownWithCppParser(markdown);
11
+ }
12
+
13
+ @end
@@ -0,0 +1,110 @@
1
+ #include "MD4CParser.hpp"
2
+ #import "MarkdownASTNode.h"
3
+ #include "MarkdownASTNode.hpp"
4
+
5
+ // Convert C++ AST node to Objective-C AST node
6
+ static MarkdownASTNode *convertCppASTToObjC(std::shared_ptr<Markdown::MarkdownASTNode> cppNode)
7
+ {
8
+ if (!cppNode) {
9
+ return [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeDocument];
10
+ }
11
+
12
+ // Convert C++ NodeType enum to Objective-C MarkdownNodeType
13
+ MarkdownNodeType objcType;
14
+ switch (cppNode->type) {
15
+ case Markdown::NodeType::Document:
16
+ objcType = MarkdownNodeTypeDocument;
17
+ break;
18
+ case Markdown::NodeType::Paragraph:
19
+ objcType = MarkdownNodeTypeParagraph;
20
+ break;
21
+ case Markdown::NodeType::Text:
22
+ objcType = MarkdownNodeTypeText;
23
+ break;
24
+ case Markdown::NodeType::Link:
25
+ objcType = MarkdownNodeTypeLink;
26
+ break;
27
+ case Markdown::NodeType::Heading:
28
+ objcType = MarkdownNodeTypeHeading;
29
+ break;
30
+ case Markdown::NodeType::LineBreak:
31
+ objcType = MarkdownNodeTypeLineBreak;
32
+ break;
33
+ case Markdown::NodeType::Strong:
34
+ objcType = MarkdownNodeTypeStrong;
35
+ break;
36
+ case Markdown::NodeType::Emphasis:
37
+ objcType = MarkdownNodeTypeEmphasis;
38
+ break;
39
+ case Markdown::NodeType::Code:
40
+ objcType = MarkdownNodeTypeCode;
41
+ break;
42
+ case Markdown::NodeType::Image:
43
+ objcType = MarkdownNodeTypeImage;
44
+ break;
45
+ case Markdown::NodeType::Blockquote:
46
+ objcType = MarkdownNodeTypeBlockquote;
47
+ break;
48
+ case Markdown::NodeType::UnorderedList:
49
+ objcType = MarkdownNodeTypeUnorderedList;
50
+ break;
51
+ case Markdown::NodeType::OrderedList:
52
+ objcType = MarkdownNodeTypeOrderedList;
53
+ break;
54
+ case Markdown::NodeType::ListItem:
55
+ objcType = MarkdownNodeTypeListItem;
56
+ break;
57
+ case Markdown::NodeType::CodeBlock:
58
+ objcType = MarkdownNodeTypeCodeBlock;
59
+ break;
60
+ case Markdown::NodeType::ThematicBreak:
61
+ objcType = MarkdownNodeTypeThematicBreak;
62
+ break;
63
+ }
64
+
65
+ MarkdownASTNode *objcNode = [[MarkdownASTNode alloc] initWithType:objcType];
66
+
67
+ // Convert content
68
+ if (!cppNode->content.empty()) {
69
+ objcNode.content = [NSString stringWithUTF8String:cppNode->content.c_str()];
70
+ }
71
+
72
+ // Convert attributes
73
+ for (const auto &[key, value] : cppNode->attributes) {
74
+ NSString *objcKey = [NSString stringWithUTF8String:key.c_str()];
75
+ NSString *objcValue = [NSString stringWithUTF8String:value.c_str()];
76
+ [objcNode setAttribute:objcKey value:objcValue];
77
+ }
78
+
79
+ // Convert children recursively
80
+ for (const auto &child : cppNode->children) {
81
+ MarkdownASTNode *objcChild = convertCppASTToObjC(child);
82
+ [objcNode addChild:objcChild];
83
+ }
84
+
85
+ return objcNode;
86
+ }
87
+
88
+ // Public function to parse markdown using C++ parser and convert to Objective-C AST
89
+ MarkdownASTNode *parseMarkdownWithCppParser(NSString *markdown)
90
+ {
91
+ if (markdown.length == 0) {
92
+ return [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeDocument];
93
+ }
94
+
95
+ // Convert NSString to std::string
96
+ const char *utf8String = [markdown UTF8String];
97
+ if (!utf8String) {
98
+ NSLog(@"MarkdownParserBridge: Failed to convert markdown to UTF-8");
99
+ return [[MarkdownASTNode alloc] initWithType:MarkdownNodeTypeDocument];
100
+ }
101
+
102
+ std::string cppMarkdown(utf8String);
103
+
104
+ // Parse using C++ parser
105
+ Markdown::MD4CParser parser;
106
+ auto cppAST = parser.parse(cppMarkdown);
107
+
108
+ // Convert C++ AST to Objective-C AST
109
+ return convertCppASTToObjC(cppAST);
110
+ }
@@ -0,0 +1,9 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ @class MarkdownASTNode;
4
+ @class RenderContext;
5
+
6
+ @interface AttributedRenderer : NSObject
7
+ - (instancetype)initWithConfig:(id)config;
8
+ - (NSMutableAttributedString *)renderRoot:(MarkdownASTNode *)root context:(RenderContext *)context;
9
+ @end
@@ -0,0 +1,119 @@
1
+ #import "AttributedRenderer.h"
2
+ #import "CodeBlockBackground.h"
3
+ #import "LastElementUtils.h"
4
+ #import "MarkdownASTNode.h"
5
+ #import "NodeRenderer.h"
6
+ #import "RenderContext.h"
7
+ #import "RendererFactory.h"
8
+ #import "StyleConfig.h"
9
+
10
+ @implementation AttributedRenderer {
11
+ StyleConfig *_config;
12
+ RendererFactory *_rendererFactory;
13
+ }
14
+
15
+ - (instancetype)initWithConfig:(StyleConfig *)config
16
+ {
17
+ self = [super init];
18
+ if (self) {
19
+ _config = config;
20
+ _rendererFactory = [[RendererFactory alloc] initWithConfig:config];
21
+ }
22
+ return self;
23
+ }
24
+
25
+ /**
26
+ * Entry point for rendering a Markdown AST.
27
+ * Sets the baseline global style and initiates the recursive traversal.
28
+ */
29
+ - (NSMutableAttributedString *)renderRoot:(MarkdownASTNode *)root context:(RenderContext *)context
30
+ {
31
+ if (!root)
32
+ return [[NSMutableAttributedString alloc] init];
33
+
34
+ // 1. Establish the global baseline style.
35
+ // This ensures that leaf nodes (like Text) have valid attributes if they appear at the root.
36
+ [context setBlockStyle:BlockTypeParagraph font:_config.paragraphFont color:_config.paragraphColor headingLevel:0];
37
+
38
+ NSMutableAttributedString *output = [[NSMutableAttributedString alloc] init];
39
+
40
+ // 2. Iterate through root children.
41
+ // We skip the 'Root' node itself as it is a container, not a renderable element.
42
+ for (MarkdownASTNode *node in root.children) {
43
+ [self renderNodeRecursive:node into:output context:context];
44
+ }
45
+
46
+ // 3. Remove trailing paragraph spacing from last block element
47
+ [self removeTrailingSpacing:output];
48
+
49
+ // 4. Cleanup global state to prevent side effects in subsequent renders.
50
+ [context clearBlockStyle];
51
+
52
+ return output;
53
+ }
54
+
55
+ /// Removes trailing margin spacing while preserving code block padding
56
+ - (void)removeTrailingSpacing:(NSMutableAttributedString *)output
57
+ {
58
+ if (output.length == 0)
59
+ return;
60
+
61
+ NSRange lastContent = [output.string rangeOfCharacterFromSet:[[NSCharacterSet newlineCharacterSet] invertedSet]
62
+ options:NSBackwardsSearch];
63
+ if (lastContent.location == NSNotFound)
64
+ return;
65
+
66
+ if (isLastElementCodeBlock(output)) {
67
+ // Code block: preserve bottom padding, only trim external margin
68
+ NSRange codeBlockRange;
69
+ [output attribute:CodeBlockAttributeName atIndex:lastContent.location effectiveRange:&codeBlockRange];
70
+ NSUInteger codeBlockEnd = NSMaxRange(codeBlockRange);
71
+ if (codeBlockEnd < output.length) {
72
+ [output deleteCharactersInRange:NSMakeRange(codeBlockEnd, output.length - codeBlockEnd)];
73
+ }
74
+ } else {
75
+ // Other elements: trim trailing newlines and zero all spacing
76
+ [output deleteCharactersInRange:NSMakeRange(NSMaxRange(lastContent), output.length - NSMaxRange(lastContent))];
77
+
78
+ NSRange range;
79
+ NSParagraphStyle *style = [output attribute:NSParagraphStyleAttributeName
80
+ atIndex:lastContent.location
81
+ effectiveRange:&range];
82
+ if (style) {
83
+ NSMutableParagraphStyle *fixed = [style mutableCopy];
84
+ fixed.paragraphSpacing = 0;
85
+ fixed.paragraphSpacingBefore = 0;
86
+ // For images: zero line spacing to eliminate baseline gaps
87
+ if (isLastElementImage(output)) {
88
+ fixed.lineSpacing = 0;
89
+ }
90
+ [output addAttribute:NSParagraphStyleAttributeName value:fixed range:range];
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Orchestrates the recursive traversal of the AST.
97
+ * If a specialized renderer exists for a node type, it takes full control.
98
+ */
99
+ - (void)renderNodeRecursive:(MarkdownASTNode *)node
100
+ into:(NSMutableAttributedString *)out
101
+ context:(RenderContext *)context
102
+ {
103
+ if (!node)
104
+ return;
105
+
106
+ id<NodeRenderer> renderer = [_rendererFactory rendererForNodeType:node.type];
107
+
108
+ if (renderer) {
109
+ // Specialized renderers (e.g., Strong, Link, Heading) handle their own sub-trees.
110
+ [renderer renderNode:node into:out context:context];
111
+ } else {
112
+ // Fallback: Default to deep-first traversal for unhandled container nodes.
113
+ for (MarkdownASTNode *child in node.children) {
114
+ [self renderNodeRecursive:child into:out context:context];
115
+ }
116
+ }
117
+ }
118
+
119
+ @end
@@ -0,0 +1,7 @@
1
+ #import "MarkdownASTNode.h"
2
+ #import "NodeRenderer.h"
3
+ #import "RenderContext.h"
4
+
5
+ @interface BlockquoteRenderer : NSObject <NodeRenderer>
6
+ - (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config;
7
+ @end