@saiansh2525/react-native-nitro-markdown 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +468 -0
  3. package/android/CMakeLists.txt +40 -0
  4. package/android/build.gradle +92 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +4 -0
  7. package/android/src/main/cpp/cpp-adapter.cpp +7 -0
  8. package/android/src/main/java/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSession.kt +61 -0
  9. package/android/src/main/java/com/nitromarkdown/NitroMarkdownPackage.kt +27 -0
  10. package/cpp/CMakeLists.txt +46 -0
  11. package/cpp/bindings/HybridMarkdownParser.cpp +114 -0
  12. package/cpp/bindings/HybridMarkdownParser.hpp +28 -0
  13. package/cpp/bindings/HybridMarkdownSession.cpp +0 -0
  14. package/cpp/core/MD4CParser.cpp +440 -0
  15. package/cpp/core/MD4CParser.hpp +21 -0
  16. package/cpp/core/MarkdownSessionCore.cpp +0 -0
  17. package/cpp/core/MarkdownTypes.hpp +124 -0
  18. package/cpp/md4c/md4c.c +6610 -0
  19. package/cpp/md4c/md4c.h +410 -0
  20. package/ios/HybridMarkdownSession.swift +64 -0
  21. package/lib/commonjs/Markdown.nitro.js +6 -0
  22. package/lib/commonjs/Markdown.nitro.js.map +1 -0
  23. package/lib/commonjs/MarkdownContext.js +17 -0
  24. package/lib/commonjs/MarkdownContext.js.map +1 -0
  25. package/lib/commonjs/MarkdownSession.js +11 -0
  26. package/lib/commonjs/MarkdownSession.js.map +1 -0
  27. package/lib/commonjs/default-markdown-renderer.js +217 -0
  28. package/lib/commonjs/default-markdown-renderer.js.map +1 -0
  29. package/lib/commonjs/headless.js +98 -0
  30. package/lib/commonjs/headless.js.map +1 -0
  31. package/lib/commonjs/index.js +226 -0
  32. package/lib/commonjs/index.js.map +1 -0
  33. package/lib/commonjs/markdown-stream.js +32 -0
  34. package/lib/commonjs/markdown-stream.js.map +1 -0
  35. package/lib/commonjs/markdown.js +385 -0
  36. package/lib/commonjs/markdown.js.map +1 -0
  37. package/lib/commonjs/package.json +1 -0
  38. package/lib/commonjs/renderers/blockquote.js +36 -0
  39. package/lib/commonjs/renderers/blockquote.js.map +1 -0
  40. package/lib/commonjs/renderers/code.js +99 -0
  41. package/lib/commonjs/renderers/code.js.map +1 -0
  42. package/lib/commonjs/renderers/heading.js +63 -0
  43. package/lib/commonjs/renderers/heading.js.map +1 -0
  44. package/lib/commonjs/renderers/horizontal-rule.js +29 -0
  45. package/lib/commonjs/renderers/horizontal-rule.js.map +1 -0
  46. package/lib/commonjs/renderers/image.js +184 -0
  47. package/lib/commonjs/renderers/image.js.map +1 -0
  48. package/lib/commonjs/renderers/link.js +35 -0
  49. package/lib/commonjs/renderers/link.js.map +1 -0
  50. package/lib/commonjs/renderers/list.js +114 -0
  51. package/lib/commonjs/renderers/list.js.map +1 -0
  52. package/lib/commonjs/renderers/math.js +137 -0
  53. package/lib/commonjs/renderers/math.js.map +1 -0
  54. package/lib/commonjs/renderers/paragraph.js +37 -0
  55. package/lib/commonjs/renderers/paragraph.js.map +1 -0
  56. package/lib/commonjs/renderers/table.js +290 -0
  57. package/lib/commonjs/renderers/table.js.map +1 -0
  58. package/lib/commonjs/specs/MarkdownSession.nitro.js +6 -0
  59. package/lib/commonjs/specs/MarkdownSession.nitro.js.map +1 -0
  60. package/lib/commonjs/theme.js +191 -0
  61. package/lib/commonjs/theme.js.map +1 -0
  62. package/lib/commonjs/use-markdown-stream.js +71 -0
  63. package/lib/commonjs/use-markdown-stream.js.map +1 -0
  64. package/lib/module/Markdown.nitro.js +4 -0
  65. package/lib/module/Markdown.nitro.js.map +1 -0
  66. package/lib/module/MarkdownContext.js +12 -0
  67. package/lib/module/MarkdownContext.js.map +1 -0
  68. package/lib/module/MarkdownSession.js +7 -0
  69. package/lib/module/MarkdownSession.js.map +1 -0
  70. package/lib/module/default-markdown-renderer.js +212 -0
  71. package/lib/module/default-markdown-renderer.js.map +1 -0
  72. package/lib/module/headless.js +90 -0
  73. package/lib/module/headless.js.map +1 -0
  74. package/lib/module/index.js +21 -0
  75. package/lib/module/index.js.map +1 -0
  76. package/lib/module/markdown-stream.js +27 -0
  77. package/lib/module/markdown-stream.js.map +1 -0
  78. package/lib/module/markdown.js +380 -0
  79. package/lib/module/markdown.js.map +1 -0
  80. package/lib/module/package.json +1 -0
  81. package/lib/module/renderers/blockquote.js +31 -0
  82. package/lib/module/renderers/blockquote.js.map +1 -0
  83. package/lib/module/renderers/code.js +93 -0
  84. package/lib/module/renderers/code.js.map +1 -0
  85. package/lib/module/renderers/heading.js +58 -0
  86. package/lib/module/renderers/heading.js.map +1 -0
  87. package/lib/module/renderers/horizontal-rule.js +24 -0
  88. package/lib/module/renderers/horizontal-rule.js.map +1 -0
  89. package/lib/module/renderers/image.js +179 -0
  90. package/lib/module/renderers/image.js.map +1 -0
  91. package/lib/module/renderers/link.js +30 -0
  92. package/lib/module/renderers/link.js.map +1 -0
  93. package/lib/module/renderers/list.js +107 -0
  94. package/lib/module/renderers/list.js.map +1 -0
  95. package/lib/module/renderers/math.js +131 -0
  96. package/lib/module/renderers/math.js.map +1 -0
  97. package/lib/module/renderers/paragraph.js +32 -0
  98. package/lib/module/renderers/paragraph.js.map +1 -0
  99. package/lib/module/renderers/table.js +285 -0
  100. package/lib/module/renderers/table.js.map +1 -0
  101. package/lib/module/specs/MarkdownSession.nitro.js +4 -0
  102. package/lib/module/specs/MarkdownSession.nitro.js.map +1 -0
  103. package/lib/module/theme.js +186 -0
  104. package/lib/module/theme.js.map +1 -0
  105. package/lib/module/use-markdown-stream.js +66 -0
  106. package/lib/module/use-markdown-stream.js.map +1 -0
  107. package/lib/typescript/commonjs/Markdown.nitro.d.ts +13 -0
  108. package/lib/typescript/commonjs/Markdown.nitro.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/MarkdownContext.d.ts +65 -0
  110. package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/MarkdownSession.d.ts +4 -0
  112. package/lib/typescript/commonjs/MarkdownSession.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/default-markdown-renderer.d.ts +10 -0
  114. package/lib/typescript/commonjs/default-markdown-renderer.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/headless.d.ts +61 -0
  116. package/lib/typescript/commonjs/headless.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/index.d.ts +22 -0
  118. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/markdown-stream.d.ts +15 -0
  120. package/lib/typescript/commonjs/markdown-stream.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/markdown.d.ts +60 -0
  122. package/lib/typescript/commonjs/markdown.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/package.json +1 -0
  124. package/lib/typescript/commonjs/renderers/blockquote.d.ts +9 -0
  125. package/lib/typescript/commonjs/renderers/blockquote.d.ts.map +1 -0
  126. package/lib/typescript/commonjs/renderers/code.d.ts +19 -0
  127. package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -0
  128. package/lib/typescript/commonjs/renderers/heading.d.ts +10 -0
  129. package/lib/typescript/commonjs/renderers/heading.d.ts.map +1 -0
  130. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts +8 -0
  131. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -0
  132. package/lib/typescript/commonjs/renderers/image.d.ts +13 -0
  133. package/lib/typescript/commonjs/renderers/image.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/renderers/link.d.ts +10 -0
  135. package/lib/typescript/commonjs/renderers/link.d.ts.map +1 -0
  136. package/lib/typescript/commonjs/renderers/list.d.ts +26 -0
  137. package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -0
  138. package/lib/typescript/commonjs/renderers/math.d.ts +14 -0
  139. package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -0
  140. package/lib/typescript/commonjs/renderers/paragraph.d.ts +10 -0
  141. package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -0
  142. package/lib/typescript/commonjs/renderers/table.d.ts +12 -0
  143. package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -0
  144. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts +12 -0
  145. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -0
  146. package/lib/typescript/commonjs/theme.d.ts +65 -0
  147. package/lib/typescript/commonjs/theme.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/use-markdown-stream.d.ts +22 -0
  149. package/lib/typescript/commonjs/use-markdown-stream.d.ts.map +1 -0
  150. package/lib/typescript/module/Markdown.nitro.d.ts +13 -0
  151. package/lib/typescript/module/Markdown.nitro.d.ts.map +1 -0
  152. package/lib/typescript/module/MarkdownContext.d.ts +65 -0
  153. package/lib/typescript/module/MarkdownContext.d.ts.map +1 -0
  154. package/lib/typescript/module/MarkdownSession.d.ts +4 -0
  155. package/lib/typescript/module/MarkdownSession.d.ts.map +1 -0
  156. package/lib/typescript/module/default-markdown-renderer.d.ts +10 -0
  157. package/lib/typescript/module/default-markdown-renderer.d.ts.map +1 -0
  158. package/lib/typescript/module/headless.d.ts +61 -0
  159. package/lib/typescript/module/headless.d.ts.map +1 -0
  160. package/lib/typescript/module/index.d.ts +22 -0
  161. package/lib/typescript/module/index.d.ts.map +1 -0
  162. package/lib/typescript/module/markdown-stream.d.ts +15 -0
  163. package/lib/typescript/module/markdown-stream.d.ts.map +1 -0
  164. package/lib/typescript/module/markdown.d.ts +60 -0
  165. package/lib/typescript/module/markdown.d.ts.map +1 -0
  166. package/lib/typescript/module/package.json +1 -0
  167. package/lib/typescript/module/renderers/blockquote.d.ts +9 -0
  168. package/lib/typescript/module/renderers/blockquote.d.ts.map +1 -0
  169. package/lib/typescript/module/renderers/code.d.ts +19 -0
  170. package/lib/typescript/module/renderers/code.d.ts.map +1 -0
  171. package/lib/typescript/module/renderers/heading.d.ts +10 -0
  172. package/lib/typescript/module/renderers/heading.d.ts.map +1 -0
  173. package/lib/typescript/module/renderers/horizontal-rule.d.ts +8 -0
  174. package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -0
  175. package/lib/typescript/module/renderers/image.d.ts +13 -0
  176. package/lib/typescript/module/renderers/image.d.ts.map +1 -0
  177. package/lib/typescript/module/renderers/link.d.ts +10 -0
  178. package/lib/typescript/module/renderers/link.d.ts.map +1 -0
  179. package/lib/typescript/module/renderers/list.d.ts +26 -0
  180. package/lib/typescript/module/renderers/list.d.ts.map +1 -0
  181. package/lib/typescript/module/renderers/math.d.ts +14 -0
  182. package/lib/typescript/module/renderers/math.d.ts.map +1 -0
  183. package/lib/typescript/module/renderers/paragraph.d.ts +10 -0
  184. package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -0
  185. package/lib/typescript/module/renderers/table.d.ts +12 -0
  186. package/lib/typescript/module/renderers/table.d.ts.map +1 -0
  187. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts +12 -0
  188. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -0
  189. package/lib/typescript/module/theme.d.ts +65 -0
  190. package/lib/typescript/module/theme.d.ts.map +1 -0
  191. package/lib/typescript/module/use-markdown-stream.d.ts +22 -0
  192. package/lib/typescript/module/use-markdown-stream.d.ts.map +1 -0
  193. package/nitro.json +19 -0
  194. package/nitrogen/generated/.gitattributes +1 -0
  195. package/nitrogen/generated/android/NitroMarkdown+autolinking.cmake +82 -0
  196. package/nitrogen/generated/android/NitroMarkdown+autolinking.gradle +27 -0
  197. package/nitrogen/generated/android/NitroMarkdownOnLoad.cpp +56 -0
  198. package/nitrogen/generated/android/NitroMarkdownOnLoad.hpp +25 -0
  199. package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
  200. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.cpp +91 -0
  201. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.hpp +70 -0
  202. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/Func_void.kt +80 -0
  203. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSessionSpec.kt +78 -0
  204. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/NitroMarkdownOnLoad.kt +35 -0
  205. package/nitrogen/generated/ios/NitroMarkdown+autolinking.rb +60 -0
  206. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.cpp +41 -0
  207. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.hpp +93 -0
  208. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Umbrella.hpp +45 -0
  209. package/nitrogen/generated/ios/NitroMarkdownAutolinking.mm +43 -0
  210. package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +26 -0
  211. package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.cpp +11 -0
  212. package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.hpp +108 -0
  213. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  214. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +59 -0
  215. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec_cxx.swift +190 -0
  216. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.cpp +22 -0
  217. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.hpp +65 -0
  218. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.cpp +26 -0
  219. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.hpp +67 -0
  220. package/nitrogen/generated/shared/c++/ParserOptions.hpp +87 -0
  221. package/package.json +134 -0
  222. package/react-native-nitro-markdown.podspec +42 -0
  223. package/src/Markdown.nitro.ts +12 -0
  224. package/src/MarkdownContext.ts +98 -0
  225. package/src/MarkdownSession.ts +8 -0
  226. package/src/default-markdown-renderer.tsx +261 -0
  227. package/src/headless.ts +171 -0
  228. package/src/index.ts +52 -0
  229. package/src/markdown-stream.tsx +32 -0
  230. package/src/markdown.tsx +521 -0
  231. package/src/renderers/blockquote.tsx +30 -0
  232. package/src/renderers/code.tsx +112 -0
  233. package/src/renderers/heading.tsx +66 -0
  234. package/src/renderers/horizontal-rule.tsx +23 -0
  235. package/src/renderers/image.tsx +204 -0
  236. package/src/renderers/link.tsx +33 -0
  237. package/src/renderers/list.tsx +123 -0
  238. package/src/renderers/math.tsx +147 -0
  239. package/src/renderers/paragraph.tsx +45 -0
  240. package/src/renderers/table.tsx +370 -0
  241. package/src/specs/MarkdownSession.nitro.ts +14 -0
  242. package/src/theme.ts +243 -0
  243. package/src/use-markdown-stream.ts +83 -0
@@ -0,0 +1,27 @@
1
+ package com.nitromarkdown
2
+
3
+ import com.facebook.react.TurboReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfoProvider
7
+ import com.facebook.react.uimanager.ViewManager
8
+
9
+ class NitroMarkdownPackage : TurboReactPackage() {
10
+ companion object {
11
+ init {
12
+ System.loadLibrary("NitroMarkdown")
13
+ }
14
+ }
15
+
16
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
17
+ return null
18
+ }
19
+
20
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
21
+ return ReactModuleInfoProvider { emptyMap() }
22
+ }
23
+
24
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
25
+ return emptyList()
26
+ }
27
+ }
@@ -0,0 +1,46 @@
1
+ cmake_minimum_required(VERSION 3.22.1)
2
+ project(MD4CParserTest)
3
+
4
+ set(CMAKE_CXX_STANDARD 20)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+ set(CMAKE_C_STANDARD 11)
7
+ set(CMAKE_C_STANDARD_REQUIRED ON)
8
+
9
+ # Define the path to our C++ sources
10
+ set(CPP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")
11
+
12
+ # Collect source files
13
+ file(GLOB MD4C_SOURCES "${CPP_ROOT}/md4c/*.c")
14
+ file(GLOB CORE_SOURCES "${CPP_ROOT}/core/*.cpp")
15
+ # Exclude the test file from the library sources
16
+ list(FILTER CORE_SOURCES EXCLUDE REGEX ".*Test\.cpp$")
17
+
18
+ # Create the core library
19
+ add_library(MD4CCore STATIC
20
+ ${MD4C_SOURCES}
21
+ ${CORE_SOURCES}
22
+ )
23
+
24
+ # Include directories for the library
25
+ target_include_directories(MD4CCore PUBLIC
26
+ "${CPP_ROOT}/md4c"
27
+ "${CPP_ROOT}/core"
28
+ )
29
+
30
+ # Preprocessor definitions
31
+ target_compile_definitions(MD4CCore PRIVATE
32
+ MD4C_USE_UTF8=1
33
+ )
34
+
35
+ # Create the test executable
36
+ add_executable(MD4CParserTest
37
+ core/MD4CParserTest.cpp
38
+ )
39
+
40
+ # Link the test executable to the core library
41
+ target_link_libraries(MD4CParserTest PRIVATE MD4CCore)
42
+
43
+ # Include directories for the test
44
+ target_include_directories(MD4CParserTest PRIVATE
45
+ "${CPP_ROOT}/core"
46
+ )
@@ -0,0 +1,114 @@
1
+ #include "HybridMarkdownParser.hpp"
2
+ #include <sstream>
3
+ #include <iomanip>
4
+
5
+ namespace margelo::nitro::Markdown {
6
+
7
+ std::string HybridMarkdownParser::parse(const std::string& text) {
8
+ InternalParserOptions opts;
9
+ opts.gfm = true;
10
+ opts.math = true;
11
+
12
+ auto ast = parser_->parse(text, opts);
13
+ return nodeToJson(ast);
14
+ }
15
+
16
+ std::string HybridMarkdownParser::parseWithOptions(const std::string& text, const ParserOptions& options) {
17
+ InternalParserOptions internalOpts;
18
+ internalOpts.gfm = options.gfm.value_or(true);
19
+ internalOpts.math = options.math.value_or(true);
20
+
21
+ auto ast = parser_->parse(text, internalOpts);
22
+ return nodeToJson(ast);
23
+ }
24
+
25
+ static std::string escapeJson(const std::string& s) {
26
+ std::ostringstream o;
27
+ for (char c : s) {
28
+ switch (c) {
29
+ case '"': o << "\\\""; break;
30
+ case '\\': o << "\\\\"; break;
31
+ case '\b': o << "\\b"; break;
32
+ case '\f': o << "\\f"; break;
33
+ case '\n': o << "\\n"; break;
34
+ case '\r': o << "\\r"; break;
35
+ case '\t': o << "\\t"; break;
36
+ default:
37
+ if ('\x00' <= c && c <= '\x1f') {
38
+ o << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (int)(unsigned char)c;
39
+ } else {
40
+ o << c;
41
+ }
42
+ }
43
+ }
44
+ return o.str();
45
+ }
46
+
47
+ std::string HybridMarkdownParser::nodeToJson(const std::shared_ptr<InternalMarkdownNode>& node) {
48
+ std::ostringstream json;
49
+ json << "{";
50
+ json << "\"type\":\"" << ::NitroMarkdown::nodeTypeToString(node->type) << "\"";
51
+ json << ",\"beg\":" << node->beg;
52
+ json << ",\"end\":" << node->end;
53
+
54
+ if (node->content.has_value()) {
55
+ json << ",\"content\":\"" << escapeJson(node->content.value()) << "\"";
56
+ }
57
+
58
+ if (node->level.has_value()) {
59
+ json << ",\"level\":" << node->level.value();
60
+ }
61
+
62
+ if (node->href.has_value()) {
63
+ json << ",\"href\":\"" << escapeJson(node->href.value()) << "\"";
64
+ }
65
+
66
+ if (node->title.has_value()) {
67
+ json << ",\"title\":\"" << escapeJson(node->title.value()) << "\"";
68
+ }
69
+
70
+ if (node->alt.has_value()) {
71
+ json << ",\"alt\":\"" << escapeJson(node->alt.value()) << "\"";
72
+ }
73
+
74
+ if (node->language.has_value()) {
75
+ json << ",\"language\":\"" << escapeJson(node->language.value()) << "\"";
76
+ }
77
+
78
+ if (node->ordered.has_value()) {
79
+ json << ",\"ordered\":" << (node->ordered.value() ? "true" : "false");
80
+ }
81
+
82
+ if (node->start.has_value()) {
83
+ json << ",\"start\":" << node->start.value();
84
+ }
85
+
86
+ if (node->checked.has_value()) {
87
+ json << ",\"checked\":" << (node->checked.value() ? "true" : "false");
88
+ }
89
+
90
+ if (node->isHeader.has_value()) {
91
+ json << ",\"isHeader\":" << (node->isHeader.value() ? "true" : "false");
92
+ }
93
+
94
+ if (node->align.has_value()) {
95
+ std::string alignStr = ::NitroMarkdown::textAlignToString(node->align.value());
96
+ if (!alignStr.empty()) {
97
+ json << ",\"align\":\"" << alignStr << "\"";
98
+ }
99
+ }
100
+
101
+ if (!node->children.empty()) {
102
+ json << ",\"children\":[";
103
+ for (size_t i = 0; i < node->children.size(); ++i) {
104
+ if (i > 0) json << ",";
105
+ json << nodeToJson(node->children[i]);
106
+ }
107
+ json << "]";
108
+ }
109
+
110
+ json << "}";
111
+ return json.str();
112
+ }
113
+
114
+ } // namespace margelo::nitro::Markdown
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include "HybridMarkdownParserSpec.hpp"
4
+ #include "../core/MD4CParser.hpp"
5
+ #include <memory>
6
+
7
+ namespace margelo::nitro::Markdown {
8
+
9
+ using InternalMarkdownNode = ::NitroMarkdown::MarkdownNode;
10
+ using InternalParserOptions = ::NitroMarkdown::ParserOptions;
11
+
12
+ class HybridMarkdownParser : public HybridMarkdownParserSpec {
13
+ public:
14
+ HybridMarkdownParser() : HybridObject(TAG), HybridMarkdownParserSpec() {
15
+ parser_ = std::make_unique<::NitroMarkdown::MD4CParser>();
16
+ }
17
+
18
+ ~HybridMarkdownParser() override = default;
19
+
20
+ std::string parse(const std::string& text) override;
21
+ std::string parseWithOptions(const std::string& text, const ParserOptions& options) override;
22
+
23
+ private:
24
+ std::unique_ptr<::NitroMarkdown::MD4CParser> parser_;
25
+ std::string nodeToJson(const std::shared_ptr<InternalMarkdownNode>& node);
26
+ };
27
+
28
+ } // namespace margelo::nitro::Markdown
File without changes
@@ -0,0 +1,440 @@
1
+ #include "MD4CParser.hpp"
2
+ #include "../md4c/md4c.h"
3
+
4
+ #include <stack>
5
+ #include <cstring>
6
+
7
+ namespace NitroMarkdown {
8
+
9
+ class MD4CParser::Impl {
10
+ public:
11
+ std::shared_ptr<MarkdownNode> root;
12
+ std::stack<std::shared_ptr<MarkdownNode>> nodeStack;
13
+ std::string currentText;
14
+ const char* inputText = nullptr;
15
+ size_t inputTextSize = 0;
16
+ OFF currentTextBeg = 0;
17
+ OFF lastTextEnd = 0;
18
+
19
+ void reset() {
20
+ root = std::make_shared<MarkdownNode>(NodeType::Document);
21
+ while (!nodeStack.empty()) nodeStack.pop();
22
+ nodeStack.push(root);
23
+ currentText.clear();
24
+ currentText.reserve(256);
25
+ currentTextBeg = 0;
26
+ lastTextEnd = 0;
27
+ }
28
+
29
+ void flushText() {
30
+ if (!currentText.empty() && !nodeStack.empty()) {
31
+ auto textNode = std::make_shared<MarkdownNode>(NodeType::Text);
32
+ textNode->content = std::move(currentText);
33
+ textNode->beg = currentTextBeg;
34
+ textNode->end = lastTextEnd;
35
+ nodeStack.top()->addChild(std::move(textNode));
36
+ currentText.clear();
37
+ }
38
+ }
39
+
40
+ void pushNode(std::shared_ptr<MarkdownNode> node, OFF beg = 0) {
41
+ flushText();
42
+ if (node && !nodeStack.empty()) {
43
+ node->beg = beg;
44
+ nodeStack.top()->addChild(node);
45
+ nodeStack.push(std::move(node));
46
+ }
47
+ }
48
+
49
+ void popNode(OFF end = 0) {
50
+ flushText();
51
+ if (nodeStack.size() > 1) {
52
+ nodeStack.top()->end = end;
53
+ nodeStack.pop();
54
+ }
55
+ }
56
+
57
+ std::string getAttributeText(const MD_ATTRIBUTE* attr) {
58
+ if (!attr || attr->size == 0) return "";
59
+
60
+ std::string result;
61
+ result.reserve(attr->size);
62
+
63
+ for (unsigned i = 0; i < attr->size; i++) {
64
+ if (attr->substr_types[i] == MD_TEXT_NORMAL ||
65
+ attr->substr_types[i] == MD_TEXT_ENTITY ||
66
+ attr->substr_types[i] == MD_TEXT_NULLCHAR) {
67
+ result.append(attr->substr_offsets[i],
68
+ i + 1 < attr->size ? attr->substr_offsets[i + 1] - attr->substr_offsets[i]
69
+ : attr->size - attr->substr_offsets[i]);
70
+ }
71
+ }
72
+
73
+ if (result.empty() && attr->text && attr->size > 0) {
74
+ result.assign(attr->text, attr->size);
75
+ }
76
+
77
+ return result;
78
+ }
79
+
80
+ static int enterBlock(MD_BLOCKTYPE type, void* detail, MD_OFFSET off, void* userdata) {
81
+ auto* impl = static_cast<Impl*>(userdata);
82
+
83
+ switch (type) {
84
+ case MD_BLOCK_DOC:
85
+ break;
86
+
87
+ case MD_BLOCK_QUOTE: {
88
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::Blockquote), off);
89
+ break;
90
+ }
91
+
92
+ case MD_BLOCK_UL: {
93
+ auto node = std::make_shared<MarkdownNode>(NodeType::List);
94
+ node->ordered = false;
95
+ impl->pushNode(node, off);
96
+ break;
97
+ }
98
+
99
+ case MD_BLOCK_OL: {
100
+ auto* d = static_cast<MD_BLOCK_OL_DETAIL*>(detail);
101
+ auto node = std::make_shared<MarkdownNode>(NodeType::List);
102
+ node->ordered = true;
103
+ node->start = d->start;
104
+ impl->pushNode(node, off);
105
+ break;
106
+ }
107
+
108
+ case MD_BLOCK_LI: {
109
+ auto* d = static_cast<MD_BLOCK_LI_DETAIL*>(detail);
110
+ if (d->is_task) {
111
+ auto node = std::make_shared<MarkdownNode>(NodeType::TaskListItem);
112
+ node->checked = (d->task_mark == 'x' || d->task_mark == 'X');
113
+ impl->pushNode(node, off);
114
+ } else {
115
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::ListItem), off);
116
+ }
117
+ break;
118
+ }
119
+
120
+ case MD_BLOCK_HR: {
121
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::HorizontalRule), off);
122
+ break;
123
+ }
124
+
125
+ case MD_BLOCK_H: {
126
+ auto* d = static_cast<MD_BLOCK_H_DETAIL*>(detail);
127
+ auto node = std::make_shared<MarkdownNode>(NodeType::Heading);
128
+ node->level = d->level;
129
+ impl->pushNode(node, off);
130
+ break;
131
+ }
132
+
133
+ case MD_BLOCK_CODE: {
134
+ auto* d = static_cast<MD_BLOCK_CODE_DETAIL*>(detail);
135
+ auto node = std::make_shared<MarkdownNode>(NodeType::CodeBlock);
136
+ if (d->lang.text && d->lang.size > 0) {
137
+ node->language = std::string(d->lang.text, d->lang.size);
138
+ }
139
+ impl->pushNode(node, off);
140
+ break;
141
+ }
142
+
143
+ case MD_BLOCK_HTML: {
144
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::HtmlBlock), off);
145
+ break;
146
+ }
147
+
148
+ case MD_BLOCK_P: {
149
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::Paragraph), off);
150
+ break;
151
+ }
152
+
153
+ case MD_BLOCK_TABLE: {
154
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::Table), off);
155
+ break;
156
+ }
157
+
158
+ case MD_BLOCK_THEAD: {
159
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::TableHead), off);
160
+ break;
161
+ }
162
+
163
+ case MD_BLOCK_TBODY: {
164
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::TableBody), off);
165
+ break;
166
+ }
167
+
168
+ case MD_BLOCK_TR: {
169
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::TableRow), off);
170
+ break;
171
+ }
172
+
173
+ case MD_BLOCK_TH: {
174
+ auto* d = static_cast<MD_BLOCK_TD_DETAIL*>(detail);
175
+ auto node = std::make_shared<MarkdownNode>(NodeType::TableCell);
176
+ node->isHeader = true;
177
+ switch (d->align) {
178
+ case MD_ALIGN_LEFT: node->align = TextAlign::Left; break;
179
+ case MD_ALIGN_CENTER: node->align = TextAlign::Center; break;
180
+ case MD_ALIGN_RIGHT: node->align = TextAlign::Right; break;
181
+ default: node->align = TextAlign::Default; break;
182
+ }
183
+ impl->pushNode(node, off);
184
+ break;
185
+ }
186
+
187
+ case MD_BLOCK_TD: {
188
+ auto* d = static_cast<MD_BLOCK_TD_DETAIL*>(detail);
189
+ auto node = std::make_shared<MarkdownNode>(NodeType::TableCell);
190
+ node->isHeader = false;
191
+ switch (d->align) {
192
+ case MD_ALIGN_LEFT: node->align = TextAlign::Left; break;
193
+ case MD_ALIGN_CENTER: node->align = TextAlign::Center; break;
194
+ case MD_ALIGN_RIGHT: node->align = TextAlign::Right; break;
195
+ default: node->align = TextAlign::Default; break;
196
+ }
197
+ impl->pushNode(node, off);
198
+ break;
199
+ }
200
+ }
201
+
202
+ return 0;
203
+ }
204
+
205
+ static int leaveBlock(MD_BLOCKTYPE type, void* detail, MD_OFFSET off, void* userdata) {
206
+ (void)detail;
207
+ auto* impl = static_cast<Impl*>(userdata);
208
+
209
+ switch (type) {
210
+ case MD_BLOCK_DOC:
211
+ impl->root->end = off;
212
+ break;
213
+ case MD_BLOCK_HR:
214
+ impl->popNode(off);
215
+ break;
216
+ default:
217
+ impl->popNode(off);
218
+ break;
219
+ }
220
+
221
+ return 0;
222
+ }
223
+
224
+ static int enterSpan(MD_SPANTYPE type, void* detail, MD_OFFSET off, void* userdata) {
225
+ auto* impl = static_cast<Impl*>(userdata);
226
+
227
+ switch (type) {
228
+ case MD_SPAN_EM: {
229
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::Italic), off);
230
+ break;
231
+ }
232
+
233
+ case MD_SPAN_STRONG: {
234
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::Bold), off);
235
+ break;
236
+ }
237
+
238
+ case MD_SPAN_DEL: {
239
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::Strikethrough), off);
240
+ break;
241
+ }
242
+
243
+ case MD_SPAN_A: {
244
+ auto* d = static_cast<MD_SPAN_A_DETAIL*>(detail);
245
+ auto node = std::make_shared<MarkdownNode>(NodeType::Link);
246
+ if (d->href.text && d->href.size > 0) {
247
+ node->href = std::string(d->href.text, d->href.size);
248
+ }
249
+ if (d->title.text && d->title.size > 0) {
250
+ node->title = std::string(d->title.text, d->title.size);
251
+ }
252
+ impl->pushNode(node, off);
253
+ break;
254
+ }
255
+
256
+ case MD_SPAN_IMG: {
257
+ auto* d = static_cast<MD_SPAN_IMG_DETAIL*>(detail);
258
+ auto node = std::make_shared<MarkdownNode>(NodeType::Image);
259
+ if (d->src.text && d->src.size > 0) {
260
+ node->href = std::string(d->src.text, d->src.size);
261
+ }
262
+ if (d->title.text && d->title.size > 0) {
263
+ node->title = std::string(d->title.text, d->title.size);
264
+ }
265
+ impl->pushNode(node, off);
266
+ break;
267
+ }
268
+
269
+ case MD_SPAN_CODE: {
270
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::CodeInline), off);
271
+ break;
272
+ }
273
+
274
+ case MD_SPAN_LATEXMATH: {
275
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::MathInline), off);
276
+ break;
277
+ }
278
+
279
+ case MD_SPAN_LATEXMATH_DISPLAY: {
280
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::MathBlock), off);
281
+ break;
282
+ }
283
+
284
+ case MD_SPAN_U: {
285
+ impl->pushNode(std::make_shared<MarkdownNode>(NodeType::Italic), off);
286
+ break;
287
+ }
288
+
289
+ case MD_SPAN_WIKILINK: {
290
+ auto node = std::make_shared<MarkdownNode>(NodeType::Link);
291
+ impl->pushNode(node, off);
292
+ break;
293
+ }
294
+ }
295
+
296
+ return 0;
297
+ }
298
+
299
+ static int leaveSpan(MD_SPANTYPE type, void* detail, MD_OFFSET off, void* userdata) {
300
+ (void)detail;
301
+ auto* impl = static_cast<Impl*>(userdata);
302
+
303
+ if (!impl->nodeStack.empty()) {
304
+ auto currentNode = impl->nodeStack.top();
305
+
306
+ switch (type) {
307
+ case MD_SPAN_CODE:
308
+ currentNode->content = impl->currentText;
309
+ impl->currentText.clear();
310
+ break;
311
+
312
+ case MD_SPAN_IMG:
313
+ currentNode->alt = impl->currentText;
314
+ impl->currentText.clear();
315
+ break;
316
+
317
+ default:
318
+ break;
319
+ }
320
+ }
321
+
322
+ impl->popNode(off);
323
+ return 0;
324
+ }
325
+
326
+ static int text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata) {
327
+ auto* impl = static_cast<Impl*>(userdata);
328
+
329
+ if (!text || size == 0) return 0;
330
+
331
+ switch (type) {
332
+ case MD_TEXT_NULLCHAR:
333
+ if (impl->currentText.empty()) impl->currentTextBeg = impl->lastTextEnd;
334
+ impl->currentText += '\0';
335
+ break;
336
+
337
+ case MD_TEXT_BR:
338
+ impl->flushText();
339
+ impl->nodeStack.top()->addChild(
340
+ std::make_shared<MarkdownNode>(NodeType::LineBreak));
341
+ break;
342
+
343
+ case MD_TEXT_SOFTBR:
344
+ impl->flushText();
345
+ impl->nodeStack.top()->addChild(
346
+ std::make_shared<MarkdownNode>(NodeType::SoftBreak));
347
+ break;
348
+
349
+ case MD_TEXT_HTML:
350
+ impl->flushText();
351
+ {
352
+ auto node = std::make_shared<MarkdownNode>(NodeType::HtmlInline);
353
+ node->content = std::string(text, size);
354
+ impl->nodeStack.top()->addChild(node);
355
+ }
356
+ break;
357
+
358
+ case MD_TEXT_ENTITY:
359
+ if (text && size > 0) {
360
+ MD_OFFSET off = impl->lastTextEnd;
361
+ ptrdiff_t diff = text - impl->inputText;
362
+ if (diff >= 0 && static_cast<size_t>(diff) <= impl->inputTextSize) {
363
+ off = static_cast<MD_OFFSET>(diff);
364
+ }
365
+ if (impl->currentText.empty()) impl->currentTextBeg = off;
366
+ impl->currentText.append(text, size);
367
+ impl->lastTextEnd = off + size;
368
+ }
369
+ break;
370
+
371
+ case MD_TEXT_NORMAL:
372
+ case MD_TEXT_CODE:
373
+ case MD_TEXT_LATEXMATH:
374
+ default: {
375
+ if (text && size > 0) {
376
+ MD_OFFSET off = impl->lastTextEnd;
377
+ ptrdiff_t diff = text - impl->inputText;
378
+ if (diff >= 0 && static_cast<size_t>(diff) <= impl->inputTextSize) {
379
+ off = static_cast<MD_OFFSET>(diff);
380
+ }
381
+
382
+ if (impl->currentText.empty()) {
383
+ impl->currentTextBeg = off;
384
+ }
385
+ impl->currentText.append(text, size);
386
+ impl->lastTextEnd = off + size;
387
+ }
388
+ break;
389
+ }
390
+ }
391
+
392
+ return 0;
393
+ }
394
+ };
395
+
396
+ MD4CParser::MD4CParser() : impl_(std::make_unique<Impl>()) {}
397
+
398
+ MD4CParser::~MD4CParser() = default;
399
+
400
+ std::shared_ptr<MarkdownNode> MD4CParser::parse(const std::string& markdown, const ParserOptions& options) {
401
+ impl_->reset();
402
+ impl_->inputText = markdown.c_str();
403
+ impl_->inputTextSize = markdown.size();
404
+
405
+ unsigned int flags = MD_FLAG_NOHTML | MD_FLAG_HARD_SOFT_BREAKS;
406
+
407
+ if (options.gfm) {
408
+ flags |= MD_FLAG_TABLES;
409
+ flags |= MD_FLAG_STRIKETHROUGH;
410
+ flags |= MD_FLAG_TASKLISTS;
411
+ flags |= MD_FLAG_PERMISSIVEAUTOLINKS;
412
+ }
413
+
414
+ if (options.math) {
415
+ flags |= MD_FLAG_LATEXMATHSPANS;
416
+ }
417
+
418
+ MD_PARSER parser = {
419
+ 0,
420
+ flags,
421
+ &Impl::enterBlock,
422
+ &Impl::leaveBlock,
423
+ &Impl::enterSpan,
424
+ &Impl::leaveSpan,
425
+ &Impl::text,
426
+ nullptr,
427
+ nullptr
428
+ };
429
+
430
+ md_parse(markdown.c_str(),
431
+ static_cast<MD_SIZE>(markdown.size()),
432
+ &parser,
433
+ impl_.get());
434
+
435
+ impl_->flushText();
436
+ return impl_->root;
437
+ }
438
+
439
+ } // namespace NitroMarkdown
440
+
@@ -0,0 +1,21 @@
1
+ #pragma once
2
+
3
+ #include "MarkdownTypes.hpp"
4
+ #include <string>
5
+ #include <memory>
6
+
7
+ namespace NitroMarkdown {
8
+
9
+ class MD4CParser {
10
+ public:
11
+ MD4CParser();
12
+ ~MD4CParser();
13
+ std::shared_ptr<MarkdownNode> parse(const std::string& markdown, const ParserOptions& options);
14
+
15
+ private:
16
+ class Impl;
17
+ std::unique_ptr<Impl> impl_;
18
+ };
19
+
20
+ } // namespace NitroMarkdown
21
+
File without changes