react-native-marcus 0.1.0

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 (304) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +227 -0
  3. package/RNMarcus.podspec +78 -0
  4. package/android/build.gradle +220 -0
  5. package/android/proguard-rules.pro +1 -0
  6. package/android/src/main/AndroidManifest.xml +3 -0
  7. package/android/src/main/AndroidManifestNew.xml +2 -0
  8. package/android/src/main/cpp/CMakeLists.txt +41 -0
  9. package/android/src/main/cpp/MarkdownParser.cpp +49 -0
  10. package/android/src/main/cpp/MarkdownParser.h +56 -0
  11. package/android/src/main/cpp/OnLoad.cpp +17 -0
  12. package/android/src/main/java/app/getbullet/marcus/MarcusModule.kt +28 -0
  13. package/android/src/main/java/app/getbullet/marcus/MarcusPackage.kt +31 -0
  14. package/android/src/main/java/app/getbullet/marcus/MarcusTextInputDecoratorView.kt +63 -0
  15. package/android/src/main/java/app/getbullet/marcus/MarcusTextInputDecoratorViewManager.kt +32 -0
  16. package/android/src/main/java/app/getbullet/marcus/MarcusTextInputDecoratorViewManagerSpec.kt +21 -0
  17. package/android/src/main/java/app/getbullet/marcus/MarkdownFormatter.kt +333 -0
  18. package/android/src/main/java/app/getbullet/marcus/MarkdownParseResult.kt +12 -0
  19. package/android/src/main/java/app/getbullet/marcus/MarkdownParser.kt +89 -0
  20. package/android/src/main/java/app/getbullet/marcus/MarkdownRange.kt +11 -0
  21. package/android/src/main/java/app/getbullet/marcus/MarkdownStyle.kt +81 -0
  22. package/android/src/main/java/app/getbullet/marcus/MarkdownTextWatcher.kt +17 -0
  23. package/android/src/main/java/app/getbullet/marcus/MarkdownUtils.kt +84 -0
  24. package/android/src/main/java/app/getbullet/marcus/ReactLineHeight.java +29 -0
  25. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBackgroundColorSpan.kt +6 -0
  26. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBackgroundSpan.kt +105 -0
  27. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBlockIndentSpan.kt +67 -0
  28. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBoldSpan.kt +6 -0
  29. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownFontFamilySpan.kt +28 -0
  30. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownFontSizeSpan.kt +7 -0
  31. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownForegroundColorSpan.kt +6 -0
  32. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownGapSpan.kt +57 -0
  33. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownItalicSpan.kt +6 -0
  34. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownLineHeightSpan.kt +21 -0
  35. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownSpan.kt +7 -0
  36. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownStrikethroughSpan.kt +5 -0
  37. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownUnderlineSpan.kt +5 -0
  38. package/android/src/main/new_arch/CMakeLists.txt +70 -0
  39. package/android/src/main/new_arch/RNMarcusSpec.cpp +43 -0
  40. package/android/src/main/new_arch/RNMarcusSpec.h +36 -0
  41. package/android/src/main/new_arch/react/renderer/components/RNMarcusSpec/MarcusTextInputDecoratorShadowNode.cpp +218 -0
  42. package/android/src/main/new_arch/react/renderer/components/RNMarcusSpec/MarcusTextInputDecoratorShadowNode.h +54 -0
  43. package/android/src/reactNativeVersionPatch/CustomMountingManager/81/app/getbullet/marcus/CustomFabricUIManager.java +156 -0
  44. package/android/src/reactNativeVersionPatch/CustomMountingManager/latest/app/getbullet/marcus/CustomFabricUIManager.java +130 -0
  45. package/android/src/test/java/app/getbullet/marcus/MarkdownFormatterTest.kt +205 -0
  46. package/android/src/test/java/app/getbullet/marcus/RenderModel.kt +78 -0
  47. package/android/src/test/resources/render-model.txt +583 -0
  48. package/apple/MarcusModule.h +8 -0
  49. package/apple/MarcusModule.mm +26 -0
  50. package/apple/MarcusRange.h +15 -0
  51. package/apple/MarcusRange.mm +15 -0
  52. package/apple/MarcusTextInputDecoratorComponentView.h +12 -0
  53. package/apple/MarcusTextInputDecoratorComponentView.mm +121 -0
  54. package/apple/MarcusTextInputDecoratorShadowNode.cpp +251 -0
  55. package/apple/MarcusTextInputDecoratorShadowNode.h +65 -0
  56. package/apple/MarcusTextInputDecoratorShadowNode.mm +204 -0
  57. package/apple/MarcusTextInputDecoratorViewManager.h +8 -0
  58. package/apple/MarcusTextInputDecoratorViewManager.mm +11 -0
  59. package/apple/MarkdownAdaptiveImageGlyph.swift +44 -0
  60. package/apple/MarkdownAttributes.h +31 -0
  61. package/apple/MarkdownAttributes.m +9 -0
  62. package/apple/MarkdownBackedTextInputDelegate.swift +117 -0
  63. package/apple/MarkdownDecorator.swift +316 -0
  64. package/apple/MarkdownFonts.swift +21 -0
  65. package/apple/MarkdownFormatter+React.swift +51 -0
  66. package/apple/MarkdownFormatter.swift +509 -0
  67. package/apple/MarkdownLog.h +10 -0
  68. package/apple/MarkdownLog.mm +6 -0
  69. package/apple/MarkdownParser.swift +200 -0
  70. package/apple/MarkdownSwiftInterop.h +23 -0
  71. package/apple/MarkdownTextBackground.swift +17 -0
  72. package/apple/MarkdownTextFieldObserver.swift +90 -0
  73. package/apple/MarkdownTextLayoutFragment.swift +205 -0
  74. package/apple/MarkdownTextLayoutManagerDelegate.swift +84 -0
  75. package/apple/MarkdownTextStorageDelegate.swift +32 -0
  76. package/apple/MarkdownTextViewObserver.swift +30 -0
  77. package/apple/RCTMarcusStyle+Codegen.h +18 -0
  78. package/apple/RCTMarcusStyle+Codegen.mm +64 -0
  79. package/apple/RCTMarcusStyle.h +41 -0
  80. package/apple/RCTMarcusStyle.m +5 -0
  81. package/apple/RCTMarcusUtils.h +26 -0
  82. package/apple/RCTMarcusUtils.mm +26 -0
  83. package/apple/RCTTextInput+AdaptiveImageGlyph.h +16 -0
  84. package/apple/RCTTextInput+AdaptiveImageGlyph.mm +79 -0
  85. package/apple/RCTTextInputComponentView+Marcus.h +11 -0
  86. package/apple/RCTTextInputComponentView+Marcus.mm +79 -0
  87. package/cpp/MarkdownCxx.modulemap +8 -0
  88. package/cpp/MarkdownGlobal.cpp +48 -0
  89. package/cpp/MarkdownGlobal.h +33 -0
  90. package/cpp/MarkdownWorkletParser.cpp +93 -0
  91. package/cpp/MarkdownWorkletParser.h +45 -0
  92. package/cpp/RuntimeDecorator.cpp +39 -0
  93. package/cpp/RuntimeDecorator.h +14 -0
  94. package/cpp/react/renderer/components/RNMarcusSpec/MarcusTextInputDecoratorState.h +33 -0
  95. package/cpp/react/renderer/components/RNMarcusSpec/MarcusTextInputDecoratorViewComponentDescriptor.h +17 -0
  96. package/lib/commonjs/MarcusTextInputDecoratorViewNativeComponent.ts +77 -0
  97. package/lib/commonjs/MarkdownTextInput.js +99 -0
  98. package/lib/commonjs/MarkdownTextInput.js.map +1 -0
  99. package/lib/commonjs/MarkdownTextInput.web.js +618 -0
  100. package/lib/commonjs/MarkdownTextInput.web.js.map +1 -0
  101. package/lib/commonjs/NativeMarcusModule.js +9 -0
  102. package/lib/commonjs/NativeMarcusModule.js.map +1 -0
  103. package/lib/commonjs/commonTypes.js +2 -0
  104. package/lib/commonjs/commonTypes.js.map +1 -0
  105. package/lib/commonjs/global.d.js +2 -0
  106. package/lib/commonjs/global.d.js.map +1 -0
  107. package/lib/commonjs/index.js +27 -0
  108. package/lib/commonjs/index.js.map +1 -0
  109. package/lib/commonjs/package.json +1 -0
  110. package/lib/commonjs/parser/index.js +7030 -0
  111. package/lib/commonjs/parser/index.js.map +7 -0
  112. package/lib/commonjs/rangeUtils.js +71 -0
  113. package/lib/commonjs/rangeUtils.js.map +1 -0
  114. package/lib/commonjs/react-native-web.d.js +2 -0
  115. package/lib/commonjs/react-native-web.d.js.map +1 -0
  116. package/lib/commonjs/styleUtils.js +91 -0
  117. package/lib/commonjs/styleUtils.js.map +1 -0
  118. package/lib/commonjs/web/InputHistory.js +111 -0
  119. package/lib/commonjs/web/InputHistory.js.map +1 -0
  120. package/lib/commonjs/web/MarkdownTextInput.css +72 -0
  121. package/lib/commonjs/web/utils/blockLayout.js +132 -0
  122. package/lib/commonjs/web/utils/blockLayout.js.map +1 -0
  123. package/lib/commonjs/web/utils/blockUtils.js +219 -0
  124. package/lib/commonjs/web/utils/blockUtils.js.map +1 -0
  125. package/lib/commonjs/web/utils/browserUtils.js +40 -0
  126. package/lib/commonjs/web/utils/browserUtils.js.map +1 -0
  127. package/lib/commonjs/web/utils/cursorUtils.js +157 -0
  128. package/lib/commonjs/web/utils/cursorUtils.js.map +1 -0
  129. package/lib/commonjs/web/utils/inputUtils.js +152 -0
  130. package/lib/commonjs/web/utils/inputUtils.js.map +1 -0
  131. package/lib/commonjs/web/utils/measureUtils.js +0 -0
  132. package/lib/commonjs/web/utils/measureUtils.js.map +1 -0
  133. package/lib/commonjs/web/utils/parserUtils.js +552 -0
  134. package/lib/commonjs/web/utils/parserUtils.js.map +1 -0
  135. package/lib/commonjs/web/utils/treeUtils.js +109 -0
  136. package/lib/commonjs/web/utils/treeUtils.js.map +1 -0
  137. package/lib/commonjs/web/utils/webStyleUtils.js +59 -0
  138. package/lib/commonjs/web/utils/webStyleUtils.js.map +1 -0
  139. package/lib/module/MarcusTextInputDecoratorViewNativeComponent.ts +77 -0
  140. package/lib/module/MarkdownTextInput.js +94 -0
  141. package/lib/module/MarkdownTextInput.js.map +1 -0
  142. package/lib/module/MarkdownTextInput.web.js +612 -0
  143. package/lib/module/MarkdownTextInput.web.js.map +1 -0
  144. package/lib/module/NativeMarcusModule.js +5 -0
  145. package/lib/module/NativeMarcusModule.js.map +1 -0
  146. package/lib/module/commonTypes.js +2 -0
  147. package/lib/module/commonTypes.js.map +1 -0
  148. package/lib/module/global.d.js +2 -0
  149. package/lib/module/global.d.js.map +1 -0
  150. package/lib/module/index.js +5 -0
  151. package/lib/module/index.js.map +1 -0
  152. package/lib/module/package.json +1 -0
  153. package/lib/module/parser/index.js +7029 -0
  154. package/lib/module/parser/index.js.map +7 -0
  155. package/lib/module/rangeUtils.js +66 -0
  156. package/lib/module/rangeUtils.js.map +1 -0
  157. package/lib/module/react-native-web.d.js +2 -0
  158. package/lib/module/react-native-web.d.js.map +1 -0
  159. package/lib/module/styleUtils.js +88 -0
  160. package/lib/module/styleUtils.js.map +1 -0
  161. package/lib/module/web/InputHistory.js +106 -0
  162. package/lib/module/web/InputHistory.js.map +1 -0
  163. package/lib/module/web/MarkdownTextInput.css +72 -0
  164. package/lib/module/web/utils/blockLayout.js +128 -0
  165. package/lib/module/web/utils/blockLayout.js.map +1 -0
  166. package/lib/module/web/utils/blockUtils.js +210 -0
  167. package/lib/module/web/utils/blockUtils.js.map +1 -0
  168. package/lib/module/web/utils/browserUtils.js +36 -0
  169. package/lib/module/web/utils/browserUtils.js.map +1 -0
  170. package/lib/module/web/utils/cursorUtils.js +150 -0
  171. package/lib/module/web/utils/cursorUtils.js.map +1 -0
  172. package/lib/module/web/utils/inputUtils.js +144 -0
  173. package/lib/module/web/utils/inputUtils.js.map +1 -0
  174. package/lib/module/web/utils/measureUtils.js +0 -0
  175. package/lib/module/web/utils/measureUtils.js.map +1 -0
  176. package/lib/module/web/utils/parserUtils.js +547 -0
  177. package/lib/module/web/utils/parserUtils.js.map +1 -0
  178. package/lib/module/web/utils/treeUtils.js +103 -0
  179. package/lib/module/web/utils/treeUtils.js.map +1 -0
  180. package/lib/module/web/utils/webStyleUtils.js +54 -0
  181. package/lib/module/web/utils/webStyleUtils.js.map +1 -0
  182. package/lib/typescript/commonjs/e2e/checks.test.d.ts +2 -0
  183. package/lib/typescript/commonjs/e2e/checks.test.d.ts.map +1 -0
  184. package/lib/typescript/commonjs/e2e/editing.test.d.ts +2 -0
  185. package/lib/typescript/commonjs/e2e/editing.test.d.ts.map +1 -0
  186. package/lib/typescript/commonjs/e2e/helpers.d.ts +23 -0
  187. package/lib/typescript/commonjs/e2e/helpers.d.ts.map +1 -0
  188. package/lib/typescript/commonjs/e2e/smoke.test.d.ts +2 -0
  189. package/lib/typescript/commonjs/e2e/smoke.test.d.ts.map +1 -0
  190. package/lib/typescript/commonjs/package.json +1 -0
  191. package/lib/typescript/commonjs/src/MarcusTextInputDecoratorViewNativeComponent.d.ts +63 -0
  192. package/lib/typescript/commonjs/src/MarcusTextInputDecoratorViewNativeComponent.d.ts.map +1 -0
  193. package/lib/typescript/commonjs/src/MarkdownTextInput.d.ts +22 -0
  194. package/lib/typescript/commonjs/src/MarkdownTextInput.d.ts.map +1 -0
  195. package/lib/typescript/commonjs/src/MarkdownTextInput.web.d.ts +41 -0
  196. package/lib/typescript/commonjs/src/MarkdownTextInput.web.d.ts.map +1 -0
  197. package/lib/typescript/commonjs/src/NativeMarcusModule.d.ts +7 -0
  198. package/lib/typescript/commonjs/src/NativeMarcusModule.d.ts.map +1 -0
  199. package/lib/typescript/commonjs/src/commonTypes.d.ts +10 -0
  200. package/lib/typescript/commonjs/src/commonTypes.d.ts.map +1 -0
  201. package/lib/typescript/commonjs/src/index.d.ts +5 -0
  202. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  203. package/lib/typescript/commonjs/src/parser/index.d.ts +8 -0
  204. package/lib/typescript/commonjs/src/parser/index.d.ts.map +1 -0
  205. package/lib/typescript/commonjs/src/parser/micromark-extension-mentions.d.ts +8 -0
  206. package/lib/typescript/commonjs/src/parser/micromark-extension-mentions.d.ts.map +1 -0
  207. package/lib/typescript/commonjs/src/rangeUtils.d.ts +6 -0
  208. package/lib/typescript/commonjs/src/rangeUtils.d.ts.map +1 -0
  209. package/lib/typescript/commonjs/src/styleUtils.d.ts +8 -0
  210. package/lib/typescript/commonjs/src/styleUtils.d.ts.map +1 -0
  211. package/lib/typescript/commonjs/src/web/InputHistory.d.ts +24 -0
  212. package/lib/typescript/commonjs/src/web/InputHistory.d.ts.map +1 -0
  213. package/lib/typescript/commonjs/src/web/utils/blockLayout.d.ts +41 -0
  214. package/lib/typescript/commonjs/src/web/utils/blockLayout.d.ts.map +1 -0
  215. package/lib/typescript/commonjs/src/web/utils/blockUtils.d.ts +33 -0
  216. package/lib/typescript/commonjs/src/web/utils/blockUtils.d.ts.map +1 -0
  217. package/lib/typescript/commonjs/src/web/utils/browserUtils.d.ts +7 -0
  218. package/lib/typescript/commonjs/src/web/utils/browserUtils.d.ts.map +1 -0
  219. package/lib/typescript/commonjs/src/web/utils/cursorUtils.d.ts +12 -0
  220. package/lib/typescript/commonjs/src/web/utils/cursorUtils.d.ts.map +1 -0
  221. package/lib/typescript/commonjs/src/web/utils/inputUtils.d.ts +12 -0
  222. package/lib/typescript/commonjs/src/web/utils/inputUtils.d.ts.map +1 -0
  223. package/lib/typescript/commonjs/src/web/utils/measureUtils.d.ts +22 -0
  224. package/lib/typescript/commonjs/src/web/utils/measureUtils.d.ts.map +1 -0
  225. package/lib/typescript/commonjs/src/web/utils/parserUtils.d.ts +44 -0
  226. package/lib/typescript/commonjs/src/web/utils/parserUtils.d.ts.map +1 -0
  227. package/lib/typescript/commonjs/src/web/utils/treeUtils.d.ts +25 -0
  228. package/lib/typescript/commonjs/src/web/utils/treeUtils.d.ts.map +1 -0
  229. package/lib/typescript/commonjs/src/web/utils/webStyleUtils.d.ts +7 -0
  230. package/lib/typescript/commonjs/src/web/utils/webStyleUtils.d.ts.map +1 -0
  231. package/lib/typescript/module/e2e/checks.test.d.ts +2 -0
  232. package/lib/typescript/module/e2e/checks.test.d.ts.map +1 -0
  233. package/lib/typescript/module/e2e/editing.test.d.ts +2 -0
  234. package/lib/typescript/module/e2e/editing.test.d.ts.map +1 -0
  235. package/lib/typescript/module/e2e/helpers.d.ts +23 -0
  236. package/lib/typescript/module/e2e/helpers.d.ts.map +1 -0
  237. package/lib/typescript/module/e2e/smoke.test.d.ts +2 -0
  238. package/lib/typescript/module/e2e/smoke.test.d.ts.map +1 -0
  239. package/lib/typescript/module/package.json +1 -0
  240. package/lib/typescript/module/src/MarcusTextInputDecoratorViewNativeComponent.d.ts +63 -0
  241. package/lib/typescript/module/src/MarcusTextInputDecoratorViewNativeComponent.d.ts.map +1 -0
  242. package/lib/typescript/module/src/MarkdownTextInput.d.ts +22 -0
  243. package/lib/typescript/module/src/MarkdownTextInput.d.ts.map +1 -0
  244. package/lib/typescript/module/src/MarkdownTextInput.web.d.ts +41 -0
  245. package/lib/typescript/module/src/MarkdownTextInput.web.d.ts.map +1 -0
  246. package/lib/typescript/module/src/NativeMarcusModule.d.ts +7 -0
  247. package/lib/typescript/module/src/NativeMarcusModule.d.ts.map +1 -0
  248. package/lib/typescript/module/src/commonTypes.d.ts +10 -0
  249. package/lib/typescript/module/src/commonTypes.d.ts.map +1 -0
  250. package/lib/typescript/module/src/index.d.ts +5 -0
  251. package/lib/typescript/module/src/index.d.ts.map +1 -0
  252. package/lib/typescript/module/src/parser/index.d.ts +8 -0
  253. package/lib/typescript/module/src/parser/index.d.ts.map +1 -0
  254. package/lib/typescript/module/src/parser/micromark-extension-mentions.d.ts +8 -0
  255. package/lib/typescript/module/src/parser/micromark-extension-mentions.d.ts.map +1 -0
  256. package/lib/typescript/module/src/rangeUtils.d.ts +6 -0
  257. package/lib/typescript/module/src/rangeUtils.d.ts.map +1 -0
  258. package/lib/typescript/module/src/styleUtils.d.ts +8 -0
  259. package/lib/typescript/module/src/styleUtils.d.ts.map +1 -0
  260. package/lib/typescript/module/src/web/InputHistory.d.ts +24 -0
  261. package/lib/typescript/module/src/web/InputHistory.d.ts.map +1 -0
  262. package/lib/typescript/module/src/web/utils/blockLayout.d.ts +41 -0
  263. package/lib/typescript/module/src/web/utils/blockLayout.d.ts.map +1 -0
  264. package/lib/typescript/module/src/web/utils/blockUtils.d.ts +33 -0
  265. package/lib/typescript/module/src/web/utils/blockUtils.d.ts.map +1 -0
  266. package/lib/typescript/module/src/web/utils/browserUtils.d.ts +7 -0
  267. package/lib/typescript/module/src/web/utils/browserUtils.d.ts.map +1 -0
  268. package/lib/typescript/module/src/web/utils/cursorUtils.d.ts +12 -0
  269. package/lib/typescript/module/src/web/utils/cursorUtils.d.ts.map +1 -0
  270. package/lib/typescript/module/src/web/utils/inputUtils.d.ts +12 -0
  271. package/lib/typescript/module/src/web/utils/inputUtils.d.ts.map +1 -0
  272. package/lib/typescript/module/src/web/utils/measureUtils.d.ts +22 -0
  273. package/lib/typescript/module/src/web/utils/measureUtils.d.ts.map +1 -0
  274. package/lib/typescript/module/src/web/utils/parserUtils.d.ts +44 -0
  275. package/lib/typescript/module/src/web/utils/parserUtils.d.ts.map +1 -0
  276. package/lib/typescript/module/src/web/utils/treeUtils.d.ts +25 -0
  277. package/lib/typescript/module/src/web/utils/treeUtils.d.ts.map +1 -0
  278. package/lib/typescript/module/src/web/utils/webStyleUtils.d.ts +7 -0
  279. package/lib/typescript/module/src/web/utils/webStyleUtils.d.ts.map +1 -0
  280. package/package.json +167 -0
  281. package/react-native.config.js +10 -0
  282. package/src/MarcusTextInputDecoratorViewNativeComponent.ts +77 -0
  283. package/src/MarkdownTextInput.tsx +139 -0
  284. package/src/MarkdownTextInput.web.tsx +958 -0
  285. package/src/NativeMarcusModule.ts +8 -0
  286. package/src/commonTypes.ts +30 -0
  287. package/src/global.d.ts +1 -0
  288. package/src/index.tsx +4 -0
  289. package/src/parser/index.ts +556 -0
  290. package/src/parser/micromark-extension-mentions.ts +82 -0
  291. package/src/rangeUtils.ts +68 -0
  292. package/src/react-native-web.d.ts +1 -0
  293. package/src/styleUtils.ts +100 -0
  294. package/src/web/InputHistory.ts +137 -0
  295. package/src/web/MarkdownTextInput.css +72 -0
  296. package/src/web/utils/blockLayout.ts +163 -0
  297. package/src/web/utils/blockUtils.ts +245 -0
  298. package/src/web/utils/browserUtils.ts +41 -0
  299. package/src/web/utils/cursorUtils.ts +204 -0
  300. package/src/web/utils/inputUtils.ts +206 -0
  301. package/src/web/utils/measureUtils.ts +0 -0
  302. package/src/web/utils/parserUtils.ts +813 -0
  303. package/src/web/utils/treeUtils.ts +149 -0
  304. package/src/web/utils/webStyleUtils.ts +69 -0
@@ -0,0 +1,68 @@
1
+ "worklet"
2
+
3
+ import type { MarkdownRange } from "./commonTypes"
4
+
5
+ // A range is emitted when the construct it belongs to opens, so the parser's order is already
6
+ // containment order: whatever encloses something opened before it. `sortRanges` keeps that order
7
+ // for ranges it cannot separate, which is just as well, because for two containers of the same size
8
+ // the answer is not a property of their types at all -- `> - a` and `- > a` are the same pair over
9
+ // the same line, nested opposite ways.
10
+ //
11
+ // One pairing breaks the rule, deliberately. `flushLine` emits a container's `block-prefix` before
12
+ // the container itself, because the native formatters lay a line out in one left-to-right walk and
13
+ // hand each marker to the container that follows it; the `syntax` inside that marker is emitted
14
+ // earlier still, when the marker's own token opens. Typing a bare `>` therefore produces three
15
+ // ranges over one character, in exactly the wrong order for a tree.
16
+ //
17
+ // This table exists to invert that one pairing, and nothing else: a block container outranks the
18
+ // `block-prefix` holding its marker, which outranks the `syntax` of the marker itself. `heading`
19
+ // sits above the default so it encloses what a heading line contains, and `emoji` below everything
20
+ // because it is always innermost. A container type left out of the table sorts level with the
21
+ // marker it should contain, and the marker then renders once per range -- see
22
+ // `reportAmbiguousNesting`, which is the check for exactly that.
23
+ function getTagPriority(tag: string) {
24
+ switch (tag) {
25
+ case "blockquote":
26
+ case "list-ordered":
27
+ case "list-unordered":
28
+ return 3
29
+ case "block-prefix":
30
+ return 2
31
+ case "heading":
32
+ return 1
33
+ case "emoji":
34
+ return -1
35
+ default:
36
+ return 0
37
+ }
38
+ }
39
+
40
+ // Sorts into the containment order the web builder nests by: outermost first, and for anything the
41
+ // three keys below cannot separate, the order the parser emitted them in. That last step is load
42
+ // bearing rather than incidental -- `Array.prototype.sort` is required to be stable, and emission
43
+ // order is what decides which of two equally sized containers encloses the other.
44
+ function sortRanges(ranges: MarkdownRange[]) {
45
+ // sort ranges by start position, then by length, then by tag hierarchy
46
+ return ranges.sort(
47
+ (a, b) =>
48
+ a.start - b.start ||
49
+ b.length - a.length ||
50
+ getTagPriority(b.type) - getTagPriority(a.type) ||
51
+ 0,
52
+ )
53
+ }
54
+
55
+ function ungroupRanges(ranges: MarkdownRange[]): MarkdownRange[] {
56
+ const ungroupedRanges: MarkdownRange[] = []
57
+ ranges.forEach((range) => {
58
+ if (!range.depth) {
59
+ ungroupedRanges.push(range)
60
+ }
61
+ const { depth, ...rangeWithoutDepth } = range
62
+ Array.from({ length: depth! }).forEach(() => {
63
+ ungroupedRanges.push(rangeWithoutDepth)
64
+ })
65
+ })
66
+ return ungroupedRanges
67
+ }
68
+ export { getTagPriority, sortRanges, ungroupRanges }
@@ -0,0 +1 @@
1
+ declare module "react-native-web/dist/exports/StyleSheet/compiler/createReactDOMStyle"
@@ -0,0 +1,100 @@
1
+ import { Platform } from "react-native"
2
+ import type { MarkdownStyle } from "./MarcusTextInputDecoratorViewNativeComponent"
3
+
4
+ type PartialMarkdownStyle = Partial<{
5
+ [K in keyof MarkdownStyle]: Partial<MarkdownStyle[K]>
6
+ }>
7
+
8
+ const FONT_FAMILY_MONOSPACE = Platform.select({
9
+ ios: "Courier",
10
+ default: "monospace",
11
+ })
12
+
13
+ const FONT_FAMILY_EMOJI = Platform.select({
14
+ ios: "System",
15
+ android: "Noto Color Emoji",
16
+ default: "System, Apple Color Emoji, Segoe UI Emoji, Noto Color Emoji",
17
+ })
18
+
19
+ function makeDefaultMarkdownStyle(): MarkdownStyle {
20
+ return {
21
+ syntax: {
22
+ color: "gray",
23
+ },
24
+ link: {
25
+ color: "blue",
26
+ },
27
+ heading: {
28
+ fontSize: 38,
29
+ scale: 0.85,
30
+ },
31
+ emoji: {
32
+ fontSize: 16,
33
+ fontFamily: FONT_FAMILY_EMOJI,
34
+ },
35
+ blockquote: {
36
+ borderColor: "gray",
37
+ borderWidth: 6,
38
+ marginLeft: 6,
39
+ paddingLeft: 6,
40
+ },
41
+ orderedList: {
42
+ marginLeft: 6,
43
+ paddingLeft: 18,
44
+ },
45
+ unorderedList: {
46
+ marginLeft: 6,
47
+ paddingLeft: 18,
48
+ },
49
+ code: {
50
+ fontFamily: FONT_FAMILY_MONOSPACE,
51
+ fontSize: 16,
52
+ color: "black",
53
+ backgroundColor: "lightgray",
54
+ },
55
+ pre: {
56
+ fontFamily: FONT_FAMILY_MONOSPACE,
57
+ fontSize: 16,
58
+ color: "black",
59
+ backgroundColor: "lightgray",
60
+ },
61
+ mentionHere: {
62
+ color: "green",
63
+ backgroundColor: "lime",
64
+ borderRadius: 5,
65
+ },
66
+ mentionUser: {
67
+ color: "blue",
68
+ backgroundColor: "cyan",
69
+ borderRadius: 5,
70
+ },
71
+ mentionReport: {
72
+ color: "red",
73
+ backgroundColor: "pink",
74
+ borderRadius: 5,
75
+ },
76
+ }
77
+ }
78
+
79
+ function mergeMarkdownStyleWithDefault(input: PartialMarkdownStyle | undefined): MarkdownStyle {
80
+ const output = makeDefaultMarkdownStyle()
81
+
82
+ if (input !== undefined) {
83
+ Object.keys(input).forEach((key) => {
84
+ if (!(key in output)) {
85
+ return
86
+ }
87
+
88
+ const outputValue = output[key as keyof MarkdownStyle]
89
+ if (outputValue) {
90
+ Object.assign(outputValue, input[key as keyof MarkdownStyle])
91
+ }
92
+ })
93
+ }
94
+
95
+ return output
96
+ }
97
+
98
+ export type { PartialMarkdownStyle }
99
+
100
+ export { mergeMarkdownStyleWithDefault }
@@ -0,0 +1,137 @@
1
+ type HistoryItem = {
2
+ text: string
3
+ cursorPosition: number | null
4
+ }
5
+
6
+ export default class InputHistory {
7
+ depth: number
8
+
9
+ items: HistoryItem[]
10
+
11
+ historyIndex: number
12
+
13
+ currentText: string | null = null
14
+
15
+ timeout: NodeJS.Timeout | null = null
16
+
17
+ debounceTime: number
18
+
19
+ constructor(depth: number, debounceTime = 150, startingText = "") {
20
+ this.depth = depth
21
+ this.items = [{ text: startingText, cursorPosition: startingText.length }]
22
+ this.historyIndex = 0
23
+ this.debounceTime = debounceTime
24
+ }
25
+
26
+ getCurrentItem(): HistoryItem | null {
27
+ return this.items[this.historyIndex] || null
28
+ }
29
+
30
+ setHistory(newHistory: HistoryItem[]): void {
31
+ this.items = newHistory.slice(newHistory.length - this.depth)
32
+ this.historyIndex = newHistory.length - 1
33
+ }
34
+
35
+ setHistoryIndex(index: number): void {
36
+ this.historyIndex = index
37
+ }
38
+
39
+ clear(): void {
40
+ this.items = []
41
+ this.historyIndex = 0
42
+ }
43
+
44
+ throttledAdd(text: string, cursorPosition: number): void {
45
+ if (this.timeout) {
46
+ clearTimeout(this.timeout)
47
+ }
48
+
49
+ if (this.currentText === null) {
50
+ this.timeout = null
51
+ this.add(text, cursorPosition)
52
+ } else {
53
+ this.items[this.historyIndex] = { text, cursorPosition }
54
+ }
55
+ this.currentText = text
56
+
57
+ this.timeout = setTimeout(() => {
58
+ this.currentText = null
59
+ }, this.debounceTime)
60
+ }
61
+
62
+ stopTimeout(): void {
63
+ if (this.timeout) {
64
+ clearTimeout(this.timeout)
65
+ this.timeout = null
66
+ }
67
+ this.currentText = null
68
+ }
69
+
70
+ add(text: string, cursorPosition: number): void {
71
+ if (this.items.length > 0) {
72
+ const currentItem = this.items[this.historyIndex]
73
+ if (currentItem && text === currentItem.text) {
74
+ return
75
+ }
76
+ }
77
+
78
+ if (this.historyIndex < this.items.length - 1) {
79
+ this.items.splice(this.historyIndex + 1)
80
+ this.historyIndex = this.items.length - 1
81
+ }
82
+
83
+ this.items.push({ text, cursorPosition })
84
+ if (this.items.length > this.depth) {
85
+ this.items.shift()
86
+ } else {
87
+ this.historyIndex += 1
88
+ }
89
+ }
90
+
91
+ undo(): HistoryItem | null {
92
+ this.stopTimeout()
93
+
94
+ if (this.items.length === 0 || this.historyIndex - 1 < 0) {
95
+ return null
96
+ }
97
+
98
+ const currentHistoryItem = this.items[this.historyIndex]
99
+ const previousHistoryItem = this.items[this.historyIndex - 1]
100
+
101
+ const undoItem = previousHistoryItem
102
+ ? {
103
+ text: previousHistoryItem.text,
104
+ cursorPosition: Math.min(
105
+ (currentHistoryItem?.cursorPosition ?? 0) -
106
+ ((currentHistoryItem?.text ?? "").length -
107
+ (previousHistoryItem?.text ?? "").length),
108
+ (previousHistoryItem?.text ?? "").length,
109
+ ),
110
+ }
111
+ : null
112
+
113
+ if (this.historyIndex > 0) {
114
+ this.historyIndex -= 1
115
+ }
116
+
117
+ return undoItem
118
+ }
119
+
120
+ redo(): HistoryItem | null {
121
+ if (this.currentText !== null && this.timeout) {
122
+ this.stopTimeout()
123
+ }
124
+
125
+ if (this.items.length === 0 || this.historyIndex + 1 > this.items.length) {
126
+ return null
127
+ }
128
+
129
+ if (this.historyIndex < this.items.length - 1) {
130
+ this.historyIndex += 1
131
+ } else {
132
+ return null
133
+ }
134
+
135
+ return this.items[this.historyIndex] || null
136
+ }
137
+ }
@@ -0,0 +1,72 @@
1
+ .react-native-marcus-input-multiline {
2
+ white-space: pre-wrap;
3
+ }
4
+
5
+ .react-native-marcus-input-singleline p {
6
+ display: inline-block;
7
+ }
8
+
9
+ .react-native-marcus-input-multiline p {
10
+ display: block;
11
+ }
12
+
13
+ .react-native-marcus-input-singleline::-webkit-scrollbar {
14
+ display: none;
15
+ }
16
+
17
+ .react-native-marcus-input-singleline br {
18
+ display: none;
19
+ }
20
+
21
+ .react-native-marcus-input-singleline span[data-type='text'] {
22
+ vertical-align: middle;
23
+ }
24
+
25
+ .react-native-marcus-input-singleline span[data-type='link'] span[data-type='text'] {
26
+ vertical-align: top;
27
+ }
28
+
29
+ .react-native-marcus-input-singleline > p:last-child {
30
+ padding-right: 1px !important;
31
+ }
32
+
33
+ .react-native-marcus-input-singleline:empty::before,
34
+ .react-native-marcus-input-multiline:empty::before {
35
+ pointer-events: none;
36
+ display: block; /* For Firefox */
37
+ content: attr(placeholder);
38
+ }
39
+
40
+ .react-native-marcus-input-multiline *[data-type='pre'] {
41
+ line-height: 1.3;
42
+ display: block;
43
+ width: fit-content;
44
+ max-width: 100%;
45
+ box-sizing: border-box;
46
+ }
47
+
48
+ .react-native-marcus-input-multiline *[data-type='codeblock'] {
49
+ position: relative;
50
+ width: fit-content;
51
+ max-width: 100%;
52
+ box-sizing: border-box;
53
+ z-index: 2;
54
+ display: block;
55
+ }
56
+
57
+ .react-native-marcus-input-singleline *[data-type='code'] > *[data-type='emoji'],
58
+ .react-native-marcus-input-multiline *[data-type='code'] > *[data-type='emoji'] {
59
+ font-size: inherit !important;
60
+ line-height: inherit !important;
61
+ vertical-align: unset !important;
62
+ }
63
+
64
+ .react-native-marcus-input-multiline *[data-type='line'] *[data-type='syntax']:has(+ *[data-type='pre']),
65
+ .react-native-marcus-input-multiline *[data-type='line'] *[data-type='pre'] + *[data-type='syntax'] {
66
+ display: block;
67
+ line-height: 1.3;
68
+ }
69
+
70
+ [class^='react-native-marcus-input'] [data-type='strikethrough'] * {
71
+ text-decoration: inherit;
72
+ }
@@ -0,0 +1,163 @@
1
+ import type { MarkdownRange, MarkdownType } from "../../commonTypes"
2
+ import type { PartialMarkdownStyle } from "../../styleUtils"
3
+ import type { TextMeasurer } from "./measureUtils"
4
+
5
+ const BLOCK_PREFIX = "block-prefix"
6
+
7
+ /**
8
+ * Where one line's text sits, and what has to be drawn in the space to its left.
9
+ *
10
+ * The same three numbers the native formatters produce: `firstLineIndent` is `firstLineHeadIndent`
11
+ * on iOS and `getLeadingMargin(true)` on Android, `indent` is the head indent the line resumes at
12
+ * when it wraps, and `ribbons` are the offsets `MarkdownTextLayoutFragment` and
13
+ * `MarkdownBlockIndentSpan` fill a blockquote's bars at.
14
+ */
15
+ type LineLayout = {
16
+ firstLineIndent: number
17
+ indent: number
18
+ ribbons: number[]
19
+ /** Space to open after a marker, so the next container's gutter lands between the two. */
20
+ gaps: Map<number, number>
21
+ }
22
+
23
+ function toNumber(value: string | number | undefined | null): number {
24
+ if (typeof value === "number") {
25
+ return value
26
+ }
27
+ if (!value) {
28
+ return 0
29
+ }
30
+ const parsed = parseFloat(value)
31
+ return Number.isFinite(parsed) ? parsed : 0
32
+ }
33
+
34
+ /** The gutter one level of a container reserves, or null if the type is not one. */
35
+ function stepOf(type: MarkdownType, markdownStyle: PartialMarkdownStyle): number | null {
36
+ switch (type) {
37
+ case "blockquote":
38
+ return (
39
+ toNumber(markdownStyle.blockquote?.marginLeft) +
40
+ toNumber(markdownStyle.blockquote?.borderWidth) +
41
+ toNumber(markdownStyle.blockquote?.paddingLeft)
42
+ )
43
+ case "list-ordered":
44
+ return (
45
+ toNumber(markdownStyle.orderedList?.marginLeft) +
46
+ toNumber(markdownStyle.orderedList?.paddingLeft)
47
+ )
48
+ case "list-unordered":
49
+ return (
50
+ toNumber(markdownStyle.unorderedList?.marginLeft) +
51
+ toNumber(markdownStyle.unorderedList?.paddingLeft)
52
+ )
53
+ default:
54
+ return null
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Places the containers of every line, left to right -- the web half of `BlockLayout` in
60
+ * `apple/MarkdownFormatter.swift` and `android/.../MarkdownFormatter.kt`, and deliberately the same
61
+ * walk.
62
+ *
63
+ * Each container reserves a gutter and is then followed by its own marker, which is text and so has
64
+ * to be stepped over rather than reserved: the container nested inside it starts after the marker,
65
+ * not in front of it. That is what puts a quote's ribbons after a list bullet, and a list's indent
66
+ * after a quote's `>`.
67
+ *
68
+ * A line continuing a block carries no marker of its own and reuses the one that opened it, which
69
+ * is why this runs across the whole document rather than per line: without it a continuation line
70
+ * would sit a marker's width to the left of the line above and break the block in two.
71
+ *
72
+ * It reads the ranges in the order the parser emits them -- marker, then the container it belongs
73
+ * to -- so it has to run before `sortRanges` rearranges them into the containment order the DOM
74
+ * builder needs.
75
+ */
76
+ function layoutBlocks(
77
+ text: string,
78
+ ranges: MarkdownRange[],
79
+ markdownStyle: PartialMarkdownStyle,
80
+ measure: TextMeasurer,
81
+ ): Map<number, LineLayout> {
82
+ const layouts = new Map<number, LineLayout>()
83
+ /** Last marker seen for each container type, for the lines that continue it. */
84
+ const markers = new Map<MarkdownType, MarkdownRange>()
85
+ const ribbonMargin = toNumber(markdownStyle.blockquote?.marginLeft)
86
+
87
+ let pendingPrefix: MarkdownRange | null = null
88
+ let line: LineLayout | null = null
89
+ let lineStart = -1
90
+ /** Offset reached so far, from the line's own left edge. */
91
+ let offset = 0
92
+ /**
93
+ * Where the line's first marker begins, if it has one. The text starts there; everything past it
94
+ * is held open with padding instead.
95
+ */
96
+ let textStart = -1
97
+ /** Marker of the container placed most recently, if it is on this line and so has something to
98
+ * pad. */
99
+ let padded: MarkdownRange | null = null
100
+
101
+ for (let i = 0; i < ranges.length; i++) {
102
+ const range = ranges[i] as MarkdownRange
103
+
104
+ if (range.type === BLOCK_PREFIX) {
105
+ pendingPrefix = range
106
+ continue
107
+ }
108
+
109
+ const step = stepOf(range.type, markdownStyle)
110
+ if (step === null) {
111
+ continue
112
+ }
113
+
114
+ const depth = range.depth && range.depth > 0 ? range.depth : 1
115
+ const gutter = step * depth
116
+
117
+ if (range.start !== lineStart) {
118
+ lineStart = range.start
119
+ offset = 0
120
+ textStart = -1
121
+ padded = null
122
+ line = { firstLineIndent: 0, indent: 0, ribbons: [], gaps: new Map() }
123
+ layouts.set(lineStart, line)
124
+ }
125
+
126
+ const current = line as LineLayout
127
+
128
+ if (padded) {
129
+ current.gaps.set(padded.start, (current.gaps.get(padded.start) ?? 0) + gutter)
130
+ }
131
+
132
+ if (range.type === "blockquote") {
133
+ for (let level = 0; level < depth; level++) {
134
+ current.ribbons.push(offset + ribbonMargin + step * level)
135
+ }
136
+ }
137
+
138
+ offset += gutter
139
+
140
+ if (pendingPrefix) {
141
+ markers.set(range.type, pendingPrefix)
142
+ if (textStart < 0) {
143
+ textStart = offset
144
+ }
145
+ }
146
+
147
+ const marker = pendingPrefix ?? markers.get(range.type)
148
+ if (marker) {
149
+ offset += measure(text.substring(marker.start, marker.start + marker.length))
150
+ }
151
+
152
+ padded = pendingPrefix
153
+ pendingPrefix = null
154
+
155
+ current.firstLineIndent = textStart >= 0 ? textStart : offset
156
+ current.indent = offset
157
+ }
158
+
159
+ return layouts
160
+ }
161
+
162
+ export { layoutBlocks, toNumber }
163
+ export type { LineLayout }