react-native-marcus 0.1.1 → 0.2.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 (294) hide show
  1. package/README.md +220 -63
  2. package/RNMarcus.podspec +6 -0
  3. package/android/src/main/java/app/getbullet/marcus/MarcusPackage.kt +2 -1
  4. package/android/src/main/java/app/getbullet/marcus/MarcusTextDecoratorView.kt +168 -0
  5. package/android/src/main/java/app/getbullet/marcus/MarcusTextDecoratorViewManager.kt +38 -0
  6. package/android/src/main/java/app/getbullet/marcus/MarcusTextDecoratorViewManagerSpec.kt +19 -0
  7. package/android/src/main/java/app/getbullet/marcus/MarcusTextInputDecoratorView.kt +23 -1
  8. package/android/src/main/java/app/getbullet/marcus/MarkdownBackgroundPainter.kt +147 -0
  9. package/android/src/main/java/app/getbullet/marcus/MarkdownBackgroundPass.kt +19 -0
  10. package/android/src/main/java/app/getbullet/marcus/MarkdownCopy.kt +87 -0
  11. package/android/src/main/java/app/getbullet/marcus/MarkdownFormatter.kt +652 -113
  12. package/android/src/main/java/app/getbullet/marcus/MarkdownRanges.kt +47 -0
  13. package/android/src/main/java/app/getbullet/marcus/MarkdownStyle.kt +140 -61
  14. package/android/src/main/java/app/getbullet/marcus/MarkdownUtils.kt +37 -7
  15. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownAbsoluteLineHeightSpan.kt +48 -0
  16. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBackgroundSpan.kt +102 -48
  17. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBlockIndentSpan.kt +22 -4
  18. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBulletSpan.kt +78 -0
  19. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownCodeBlockSpan.kt +177 -0
  20. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownFontStyleSpan.kt +32 -0
  21. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownFontWeightSpan.kt +34 -0
  22. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownGapSpan.kt +24 -11
  23. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownLetterSpacingSpan.kt +32 -0
  24. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownTextShadowSpan.kt +32 -0
  25. package/android/src/main/new_arch/CMakeLists.txt +17 -0
  26. package/android/src/main/new_arch/RNMarcusSpec.h +1 -0
  27. package/android/src/main/new_arch/react/renderer/components/RNMarcusSpec/MarcusTextDecoratorShadowNode.cpp +235 -0
  28. package/android/src/main/new_arch/react/renderer/components/RNMarcusSpec/MarcusTextDecoratorShadowNode.h +62 -0
  29. package/android/src/reactNativeVersionPatch/CustomMountingManager/81/app/getbullet/marcus/CustomFabricUIManager.java +22 -3
  30. package/android/src/reactNativeVersionPatch/CustomMountingManager/latest/app/getbullet/marcus/CustomFabricUIManager.java +22 -3
  31. package/android/src/test/java/app/getbullet/marcus/MarkdownCopyTest.kt +69 -0
  32. package/android/src/test/java/app/getbullet/marcus/MarkdownFormatterTest.kt +170 -25
  33. package/android/src/test/java/app/getbullet/marcus/RenderModel.kt +22 -5
  34. package/android/src/test/java/app/getbullet/marcus/spans/MarkdownCodeBlockSpanTest.kt +91 -0
  35. package/android/src/test/resources/render-model.txt +221 -16
  36. package/apple/MarcusSwizzle.h +25 -0
  37. package/apple/MarcusTextDecoratorComponentView.h +22 -0
  38. package/apple/MarcusTextDecoratorComponentView.mm +72 -0
  39. package/apple/MarcusTextDecoratorShadowNode.h +62 -0
  40. package/apple/MarcusTextDecoratorShadowNode.mm +192 -0
  41. package/apple/MarcusTextDecoratorViewManager.h +4 -0
  42. package/apple/MarcusTextDecoratorViewManager.mm +11 -0
  43. package/apple/MarcusTextInputDecoratorComponentView.mm +1 -1
  44. package/apple/MarcusTextInputDecoratorShadowNode.mm +1 -1
  45. package/apple/MarcusTextLayoutManager.h +40 -0
  46. package/apple/MarcusTextLayoutManager.mm +173 -0
  47. package/apple/MarkdownAttributes.h +23 -2
  48. package/apple/MarkdownAttributes.m +6 -0
  49. package/apple/MarkdownCopy.swift +63 -0
  50. package/apple/MarkdownDecorator.swift +2 -2
  51. package/apple/MarkdownFormatter+React.swift +23 -0
  52. package/apple/MarkdownFormatter.swift +869 -148
  53. package/apple/MarkdownParagraphLayoutManager.swift +455 -0
  54. package/apple/MarkdownSwiftInterop.h +0 -1
  55. package/apple/MarkdownTextBackground.swift +59 -1
  56. package/apple/MarkdownTextFieldObserver.swift +2 -2
  57. package/apple/MarkdownTextLayoutFragment.swift +159 -33
  58. package/apple/MarkdownTextLayoutManagerDelegate.swift +67 -3
  59. package/apple/MarkdownTextStorageDelegate.swift +2 -2
  60. package/apple/MarkdownTextViewObserver.swift +2 -2
  61. package/apple/MarkdownUtils.swift +38 -0
  62. package/apple/MarkdownWritingDirection.swift +132 -0
  63. package/apple/RCTMarcusStyle+Codegen.h +115 -9
  64. package/apple/RCTMarcusStyle.h +128 -31
  65. package/apple/RCTMarcusStyle.m +48 -0
  66. package/apple/RCTParagraphComponentView+Marcus.h +17 -0
  67. package/apple/RCTParagraphComponentView+Marcus.mm +38 -0
  68. package/apple/RCTTextInputComponentView+Marcus.mm +1 -25
  69. package/cpp/react/renderer/components/RNMarcusSpec/MarcusTextDecoratorState.h +37 -0
  70. package/cpp/react/renderer/components/RNMarcusSpec/MarcusTextDecoratorViewComponentDescriptor.h +17 -0
  71. package/lib/commonjs/MarcusTextDecoratorViewNativeComponent.ts +199 -0
  72. package/lib/commonjs/MarcusTextInputDecoratorViewNativeComponent.ts +145 -58
  73. package/lib/commonjs/MarkdownText.js +330 -0
  74. package/lib/commonjs/MarkdownText.js.map +1 -0
  75. package/lib/commonjs/MarkdownText.web.js +529 -0
  76. package/lib/commonjs/MarkdownText.web.js.map +1 -0
  77. package/lib/commonjs/MarkdownTextInput.js +22 -27
  78. package/lib/commonjs/MarkdownTextInput.js.map +1 -1
  79. package/lib/commonjs/MarkdownTextInput.web.js +12 -7
  80. package/lib/commonjs/MarkdownTextInput.web.js.map +1 -1
  81. package/lib/commonjs/atomUtils.js +112 -0
  82. package/lib/commonjs/atomUtils.js.map +1 -0
  83. package/lib/commonjs/childrenUtils.js +36 -0
  84. package/lib/commonjs/childrenUtils.js.map +1 -0
  85. package/lib/commonjs/index.js +8 -7
  86. package/lib/commonjs/index.js.map +1 -1
  87. package/lib/commonjs/math/environment.js +69 -0
  88. package/lib/commonjs/math/environment.js.map +1 -0
  89. package/lib/commonjs/math/index.js +61 -0
  90. package/lib/commonjs/math/index.js.map +1 -0
  91. package/lib/commonjs/math/mathjax.js +548 -0
  92. package/lib/commonjs/math/mathjax.js.map +1 -0
  93. package/lib/commonjs/metro.js +172 -0
  94. package/lib/commonjs/metro.js.map +1 -0
  95. package/lib/commonjs/parser/index.d.ts +3 -0
  96. package/lib/commonjs/parser/index.js +450 -42
  97. package/lib/commonjs/parser/index.js.map +4 -4
  98. package/lib/commonjs/stripUtils.js +743 -0
  99. package/lib/commonjs/stripUtils.js.map +1 -0
  100. package/lib/commonjs/styleUtils.js +194 -23
  101. package/lib/commonjs/styleUtils.js.map +1 -1
  102. package/lib/commonjs/web/MarkdownElements.css +67 -0
  103. package/lib/commonjs/web/MarkdownTextInput.css +9 -7
  104. package/lib/commonjs/web/utils/blockLayout.js +95 -7
  105. package/lib/commonjs/web/utils/blockLayout.js.map +1 -1
  106. package/lib/commonjs/web/utils/blockUtils.js +327 -54
  107. package/lib/commonjs/web/utils/blockUtils.js.map +1 -1
  108. package/lib/commonjs/web/utils/elementUtils.js +80 -0
  109. package/lib/commonjs/web/utils/elementUtils.js.map +1 -0
  110. package/lib/commonjs/web/utils/parserUtils.js +84 -28
  111. package/lib/commonjs/web/utils/parserUtils.js.map +1 -1
  112. package/lib/commonjs/web/utils/treeUtils.js +6 -0
  113. package/lib/commonjs/web/utils/treeUtils.js.map +1 -1
  114. package/lib/commonjs/web/utils/webStyleUtils.js +25 -5
  115. package/lib/commonjs/web/utils/webStyleUtils.js.map +1 -1
  116. package/lib/module/MarcusTextDecoratorViewNativeComponent.ts +199 -0
  117. package/lib/module/MarcusTextInputDecoratorViewNativeComponent.ts +145 -58
  118. package/lib/module/MarkdownText.js +325 -0
  119. package/lib/module/MarkdownText.js.map +1 -0
  120. package/lib/module/MarkdownText.web.js +524 -0
  121. package/lib/module/MarkdownText.web.js.map +1 -0
  122. package/lib/module/MarkdownTextInput.js +24 -29
  123. package/lib/module/MarkdownTextInput.js.map +1 -1
  124. package/lib/module/MarkdownTextInput.web.js +12 -7
  125. package/lib/module/MarkdownTextInput.web.js.map +1 -1
  126. package/lib/module/atomUtils.js +106 -0
  127. package/lib/module/atomUtils.js.map +1 -0
  128. package/lib/module/childrenUtils.js +33 -0
  129. package/lib/module/childrenUtils.js.map +1 -0
  130. package/lib/module/index.js +1 -1
  131. package/lib/module/index.js.map +1 -1
  132. package/lib/module/math/environment.js +67 -0
  133. package/lib/module/math/environment.js.map +1 -0
  134. package/lib/module/math/index.js +56 -0
  135. package/lib/module/math/index.js.map +1 -0
  136. package/lib/module/math/mathjax.js +541 -0
  137. package/lib/module/math/mathjax.js.map +1 -0
  138. package/lib/module/metro.js +169 -0
  139. package/lib/module/metro.js.map +1 -0
  140. package/lib/module/parser/index.d.ts +3 -0
  141. package/lib/module/parser/index.js +450 -42
  142. package/lib/module/parser/index.js.map +4 -4
  143. package/lib/module/stripUtils.js +739 -0
  144. package/lib/module/stripUtils.js.map +1 -0
  145. package/lib/module/styleUtils.js +196 -25
  146. package/lib/module/styleUtils.js.map +1 -1
  147. package/lib/module/web/MarkdownElements.css +67 -0
  148. package/lib/module/web/MarkdownTextInput.css +9 -7
  149. package/lib/module/web/utils/blockLayout.js +94 -8
  150. package/lib/module/web/utils/blockLayout.js.map +1 -1
  151. package/lib/module/web/utils/blockUtils.js +328 -56
  152. package/lib/module/web/utils/blockUtils.js.map +1 -1
  153. package/lib/module/web/utils/elementUtils.js +75 -0
  154. package/lib/module/web/utils/elementUtils.js.map +1 -0
  155. package/lib/module/web/utils/parserUtils.js +86 -30
  156. package/lib/module/web/utils/parserUtils.js.map +1 -1
  157. package/lib/module/web/utils/treeUtils.js +6 -0
  158. package/lib/module/web/utils/treeUtils.js.map +1 -1
  159. package/lib/module/web/utils/webStyleUtils.js +25 -5
  160. package/lib/module/web/utils/webStyleUtils.js.map +1 -1
  161. package/lib/typescript/commonjs/e2e/links.test.d.ts +2 -0
  162. package/lib/typescript/commonjs/e2e/links.test.d.ts.map +1 -0
  163. package/lib/typescript/commonjs/src/MarcusTextDecoratorViewNativeComponent.d.ts +93 -0
  164. package/lib/typescript/commonjs/src/MarcusTextDecoratorViewNativeComponent.d.ts.map +1 -0
  165. package/lib/typescript/commonjs/src/MarcusTextInputDecoratorViewNativeComponent.d.ts +64 -51
  166. package/lib/typescript/commonjs/src/MarcusTextInputDecoratorViewNativeComponent.d.ts.map +1 -1
  167. package/lib/typescript/commonjs/src/MarkdownText.d.ts +127 -0
  168. package/lib/typescript/commonjs/src/MarkdownText.d.ts.map +1 -0
  169. package/lib/typescript/commonjs/src/MarkdownText.web.d.ts +126 -0
  170. package/lib/typescript/commonjs/src/MarkdownText.web.d.ts.map +1 -0
  171. package/lib/typescript/commonjs/src/MarkdownTextInput.d.ts +23 -1
  172. package/lib/typescript/commonjs/src/MarkdownTextInput.d.ts.map +1 -1
  173. package/lib/typescript/commonjs/src/MarkdownTextInput.web.d.ts +26 -4
  174. package/lib/typescript/commonjs/src/MarkdownTextInput.web.d.ts.map +1 -1
  175. package/lib/typescript/commonjs/src/atomUtils.d.ts +58 -0
  176. package/lib/typescript/commonjs/src/atomUtils.d.ts.map +1 -0
  177. package/lib/typescript/commonjs/src/childrenUtils.d.ts +12 -0
  178. package/lib/typescript/commonjs/src/childrenUtils.d.ts.map +1 -0
  179. package/lib/typescript/commonjs/src/commonTypes.d.ts +39 -3
  180. package/lib/typescript/commonjs/src/commonTypes.d.ts.map +1 -1
  181. package/lib/typescript/commonjs/src/index.d.ts +2 -1
  182. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  183. package/lib/typescript/commonjs/src/math/environment.d.ts +7 -0
  184. package/lib/typescript/commonjs/src/math/environment.d.ts.map +1 -0
  185. package/lib/typescript/commonjs/src/math/index.d.ts +64 -0
  186. package/lib/typescript/commonjs/src/math/index.d.ts.map +1 -0
  187. package/lib/typescript/commonjs/src/math/mathjax.d.ts +63 -0
  188. package/lib/typescript/commonjs/src/math/mathjax.d.ts.map +1 -0
  189. package/lib/typescript/commonjs/src/metro.d.ts +59 -0
  190. package/lib/typescript/commonjs/src/metro.d.ts.map +1 -0
  191. package/lib/typescript/commonjs/src/parser/index.d.ts +3 -3
  192. package/lib/typescript/commonjs/src/parser/index.d.ts.map +1 -1
  193. package/lib/typescript/commonjs/src/parser/micromark-extension-mentions.d.ts.map +1 -1
  194. package/lib/typescript/commonjs/src/rangeUtils.d.ts +1 -1
  195. package/lib/typescript/commonjs/src/stripUtils.d.ts +108 -0
  196. package/lib/typescript/commonjs/src/stripUtils.d.ts.map +1 -0
  197. package/lib/typescript/commonjs/src/styleUtils.d.ts +62 -4
  198. package/lib/typescript/commonjs/src/styleUtils.d.ts.map +1 -1
  199. package/lib/typescript/commonjs/src/web/utils/blockLayout.d.ts +32 -4
  200. package/lib/typescript/commonjs/src/web/utils/blockLayout.d.ts.map +1 -1
  201. package/lib/typescript/commonjs/src/web/utils/blockUtils.d.ts +20 -8
  202. package/lib/typescript/commonjs/src/web/utils/blockUtils.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/src/web/utils/elementUtils.d.ts +37 -0
  204. package/lib/typescript/commonjs/src/web/utils/elementUtils.d.ts.map +1 -0
  205. package/lib/typescript/commonjs/src/web/utils/parserUtils.d.ts +5 -5
  206. package/lib/typescript/commonjs/src/web/utils/parserUtils.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/src/web/utils/treeUtils.d.ts +6 -1
  208. package/lib/typescript/commonjs/src/web/utils/treeUtils.d.ts.map +1 -1
  209. package/lib/typescript/commonjs/src/web/utils/webStyleUtils.d.ts +2 -2
  210. package/lib/typescript/commonjs/src/web/utils/webStyleUtils.d.ts.map +1 -1
  211. package/lib/typescript/module/e2e/links.test.d.ts +2 -0
  212. package/lib/typescript/module/e2e/links.test.d.ts.map +1 -0
  213. package/lib/typescript/module/src/MarcusTextDecoratorViewNativeComponent.d.ts +93 -0
  214. package/lib/typescript/module/src/MarcusTextDecoratorViewNativeComponent.d.ts.map +1 -0
  215. package/lib/typescript/module/src/MarcusTextInputDecoratorViewNativeComponent.d.ts +64 -51
  216. package/lib/typescript/module/src/MarcusTextInputDecoratorViewNativeComponent.d.ts.map +1 -1
  217. package/lib/typescript/module/src/MarkdownText.d.ts +127 -0
  218. package/lib/typescript/module/src/MarkdownText.d.ts.map +1 -0
  219. package/lib/typescript/module/src/MarkdownText.web.d.ts +126 -0
  220. package/lib/typescript/module/src/MarkdownText.web.d.ts.map +1 -0
  221. package/lib/typescript/module/src/MarkdownTextInput.d.ts +23 -1
  222. package/lib/typescript/module/src/MarkdownTextInput.d.ts.map +1 -1
  223. package/lib/typescript/module/src/MarkdownTextInput.web.d.ts +26 -4
  224. package/lib/typescript/module/src/MarkdownTextInput.web.d.ts.map +1 -1
  225. package/lib/typescript/module/src/atomUtils.d.ts +58 -0
  226. package/lib/typescript/module/src/atomUtils.d.ts.map +1 -0
  227. package/lib/typescript/module/src/childrenUtils.d.ts +12 -0
  228. package/lib/typescript/module/src/childrenUtils.d.ts.map +1 -0
  229. package/lib/typescript/module/src/commonTypes.d.ts +39 -3
  230. package/lib/typescript/module/src/commonTypes.d.ts.map +1 -1
  231. package/lib/typescript/module/src/index.d.ts +2 -1
  232. package/lib/typescript/module/src/index.d.ts.map +1 -1
  233. package/lib/typescript/module/src/math/environment.d.ts +7 -0
  234. package/lib/typescript/module/src/math/environment.d.ts.map +1 -0
  235. package/lib/typescript/module/src/math/index.d.ts +64 -0
  236. package/lib/typescript/module/src/math/index.d.ts.map +1 -0
  237. package/lib/typescript/module/src/math/mathjax.d.ts +63 -0
  238. package/lib/typescript/module/src/math/mathjax.d.ts.map +1 -0
  239. package/lib/typescript/module/src/metro.d.ts +59 -0
  240. package/lib/typescript/module/src/metro.d.ts.map +1 -0
  241. package/lib/typescript/module/src/parser/index.d.ts +3 -3
  242. package/lib/typescript/module/src/parser/index.d.ts.map +1 -1
  243. package/lib/typescript/module/src/parser/micromark-extension-mentions.d.ts.map +1 -1
  244. package/lib/typescript/module/src/rangeUtils.d.ts +1 -1
  245. package/lib/typescript/module/src/stripUtils.d.ts +108 -0
  246. package/lib/typescript/module/src/stripUtils.d.ts.map +1 -0
  247. package/lib/typescript/module/src/styleUtils.d.ts +62 -4
  248. package/lib/typescript/module/src/styleUtils.d.ts.map +1 -1
  249. package/lib/typescript/module/src/web/utils/blockLayout.d.ts +32 -4
  250. package/lib/typescript/module/src/web/utils/blockLayout.d.ts.map +1 -1
  251. package/lib/typescript/module/src/web/utils/blockUtils.d.ts +20 -8
  252. package/lib/typescript/module/src/web/utils/blockUtils.d.ts.map +1 -1
  253. package/lib/typescript/module/src/web/utils/elementUtils.d.ts +37 -0
  254. package/lib/typescript/module/src/web/utils/elementUtils.d.ts.map +1 -0
  255. package/lib/typescript/module/src/web/utils/parserUtils.d.ts +5 -5
  256. package/lib/typescript/module/src/web/utils/parserUtils.d.ts.map +1 -1
  257. package/lib/typescript/module/src/web/utils/treeUtils.d.ts +6 -1
  258. package/lib/typescript/module/src/web/utils/treeUtils.d.ts.map +1 -1
  259. package/lib/typescript/module/src/web/utils/webStyleUtils.d.ts +2 -2
  260. package/lib/typescript/module/src/web/utils/webStyleUtils.d.ts.map +1 -1
  261. package/package.json +29 -2
  262. package/react-native.config.js +8 -1
  263. package/src/MarcusTextDecoratorViewNativeComponent.ts +199 -0
  264. package/src/MarcusTextInputDecoratorViewNativeComponent.ts +145 -58
  265. package/src/MarkdownText.tsx +472 -0
  266. package/src/MarkdownText.web.tsx +668 -0
  267. package/src/MarkdownTextInput.tsx +42 -38
  268. package/src/MarkdownTextInput.web.tsx +36 -13
  269. package/src/atomUtils.ts +112 -0
  270. package/src/childrenUtils.ts +39 -0
  271. package/src/commonTypes.ts +69 -9
  272. package/src/index.tsx +2 -1
  273. package/src/math/environment.ts +68 -0
  274. package/src/math/index.ts +78 -0
  275. package/src/math/mathjax.ts +604 -0
  276. package/src/metro.ts +238 -0
  277. package/src/parser/index.ts +175 -10
  278. package/src/parser/micromark-extension-mentions.ts +104 -11
  279. package/src/stripUtils.ts +919 -0
  280. package/src/styleUtils.ts +290 -26
  281. package/src/web/MarkdownElements.css +67 -0
  282. package/src/web/MarkdownTextInput.css +9 -7
  283. package/src/web/utils/blockLayout.ts +124 -14
  284. package/src/web/utils/blockUtils.ts +365 -59
  285. package/src/web/utils/elementUtils.ts +87 -0
  286. package/src/web/utils/parserUtils.ts +119 -31
  287. package/src/web/utils/treeUtils.ts +6 -1
  288. package/src/web/utils/webStyleUtils.ts +32 -8
  289. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBackgroundColorSpan.kt +0 -6
  290. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownBoldSpan.kt +0 -6
  291. package/android/src/main/java/app/getbullet/marcus/spans/MarkdownItalicSpan.kt +0 -6
  292. package/apple/RCTMarcusStyle+Codegen.mm +0 -64
  293. package/apple/RCTMarcusUtils.h +0 -26
  294. package/apple/RCTMarcusUtils.mm +0 -26
@@ -0,0 +1,739 @@
1
+ "use strict";
2
+
3
+ // Removing the markdown syntax from the string before it reaches the platform
4
+ // is what separates the display component from the input one: the input shows
5
+ // what you typed, the display shows what it meant. Everything downstream --
6
+ // measurement, drawing, selection, VoiceOver -- then sees only the text that is
7
+ // meant to be read, without any of the hiding tricks that a formatter would
8
+ // otherwise have to play on characters that are still there.
9
+ //
10
+ // The parser's offsets are into the original string, so cutting characters out
11
+ // invalidates every range it emitted. Both halves happen here, in one pass, so
12
+ // there is never a moment where a range and the string it indexes disagree.
13
+
14
+ /** What an image stood for, for a caller that has something to show instead. */
15
+
16
+ /** A maths span, for a caller that has something to draw it with. */
17
+
18
+ /** A link the display can hand to whatever is going to act on a press. */
19
+
20
+ /**
21
+ * The character standing in for an embed, matching what the platforms use for
22
+ * an attachment so that the stripped text and the string that reaches the
23
+ * formatters are the same length.
24
+ */
25
+ const OBJECT_REPLACEMENT = "\uFFFC";
26
+
27
+ /** Shared so that the common case of a document with no embeds allocates nothing. */
28
+ const NO_EMBEDS = [];
29
+
30
+ /** Shared for the same reason. */
31
+ const NO_MATHS = [];
32
+
33
+ /** Shared for the same reason. */
34
+ const NO_LINKS = [];
35
+ const TAB = 9;
36
+ const LINE_FEED = 10;
37
+ const CARRIAGE_RETURN = 13;
38
+ const SPACE = 32;
39
+ const GREATER_THAN = 62;
40
+ const LEFT_PAREN = 40;
41
+ const RIGHT_PAREN = 41;
42
+ function isBlank(code) {
43
+ return code === SPACE || code === TAB;
44
+ }
45
+ function isLineBreak(code) {
46
+ return code === LINE_FEED || code === CARRIAGE_RETURN;
47
+ }
48
+
49
+ /**
50
+ * Spans of the block markers that survive stripping, in original offsets.
51
+ *
52
+ * A list's marker is the only syntax that carries meaning of its own -- `1.`
53
+ * numbers the item and `-` stands in for a bullet -- so it stays in the string
54
+ * and is laid out the way the input lays it out. A blockquote's `>` says
55
+ * nothing the ribbon beside it does not already say, so it goes.
56
+ *
57
+ * `flushLine` emits a `block-prefix` immediately before the container that owns
58
+ * it, which is the same pairing the native formatters read, so the container is
59
+ * simply the range that follows.
60
+ */
61
+ function listMarkers(ranges) {
62
+ const markers = [];
63
+ for (let i = 0; i < ranges.length; i++) {
64
+ const range = ranges[i];
65
+ if (range.type !== "block-prefix") {
66
+ continue;
67
+ }
68
+ const container = ranges[i + 1];
69
+ if (container && (container.type === "list-ordered" || container.type === "list-unordered")) {
70
+ markers.push({
71
+ start: range.start,
72
+ end: range.start + range.length
73
+ });
74
+ }
75
+ }
76
+ return markers;
77
+ }
78
+
79
+ /**
80
+ * Whether a syntax range is a quote marker sitting inside a list's prefix.
81
+ *
82
+ * A prefix is measured from wherever the previous container's marker ended, so
83
+ * the ordered list in `- > 1. ` is handed the whole run `> 1. ` -- quote marker
84
+ * included. Containment alone would therefore keep a `>` that belongs to
85
+ * something else, and `>` is the only block marker that can appear there.
86
+ */
87
+ function isQuoteMarker(text, start, end) {
88
+ for (let i = start; i < end; i++) {
89
+ if (text.charCodeAt(i) !== GREATER_THAN) {
90
+ return false;
91
+ }
92
+ }
93
+ return true;
94
+ }
95
+
96
+ /** The `( ... )` an inline link or image carries, and what it carries in it. */
97
+
98
+ /**
99
+ * The resources in `text`, in the order they are written.
100
+ *
101
+ * The parser reports the brackets and parentheses as syntax but the destination
102
+ * itself as a `link`, which is right for an input -- the URL is text you can
103
+ * edit -- and wrong for a display, where cutting only the punctuation out of
104
+ * `[text](url)` leaves `texturl`. So the whole run between the markers goes,
105
+ * and reading it on the way past is what leaves something to hand a press
106
+ * handler afterwards.
107
+ *
108
+ * `(` is emitted as syntax only by `resourceMarker`, so there is nothing else
109
+ * this can match, and one resource cannot hold another: the inner parentheses
110
+ * of `[a](b(c))` are part of the destination rather than markers of their own.
111
+ * Reference links and their definitions are not covered: their label is
112
+ * punctuation around prose the way emphasis is, and telling `[text]` a
113
+ * reference from `[text]` a label needs more than the ranges carry.
114
+ */
115
+ function resourceSpans(text, ranges) {
116
+ const spans = [];
117
+ let current = null;
118
+ for (const range of ranges) {
119
+ if (range.type === "syntax" && range.length === 1) {
120
+ const code = text.charCodeAt(range.start);
121
+ if (code === LEFT_PAREN) {
122
+ current = {
123
+ open: range.start,
124
+ close: -1,
125
+ uri: "",
126
+ title: ""
127
+ };
128
+ } else if (code === RIGHT_PAREN && current !== null) {
129
+ current.close = range.start;
130
+ spans.push(current);
131
+ current = null;
132
+ }
133
+ continue;
134
+ }
135
+
136
+ // A destination and a title are emitted between the two markers, so
137
+ // whichever resource is open is the one they belong to. Anything else that
138
+ // arrives in between -- a container flushed at a line break inside a title
139
+ // -- is neither and is passed over.
140
+ if (current === null) {
141
+ continue;
142
+ }
143
+ if (range.type === "link") {
144
+ current.uri = text.slice(range.start, range.start + range.length);
145
+ } else if (range.type === "title") {
146
+ current.title = text.slice(range.start, range.start + range.length);
147
+ }
148
+ }
149
+ return spans;
150
+ }
151
+
152
+ /** Marks every resource for removal, markers and all. */
153
+ function cutResources(resources, cut) {
154
+ let cutSomething = false;
155
+ for (const resource of resources) {
156
+ for (let i = resource.open; i <= resource.close; i++) {
157
+ cut[i] = 1;
158
+ cutSomething = true;
159
+ }
160
+ }
161
+ return cutSomething;
162
+ }
163
+
164
+ /**
165
+ * Whether anything but block markers shares a line with the character at
166
+ * `index`.
167
+ *
168
+ * Read off the stripped text, which is the text that will be laid out: by this
169
+ * point a quote's marker is gone entirely and a list's is a `block-prefix`
170
+ * range over characters that were kept to be laid out rather than read.
171
+ */
172
+ function sharesItsLine(text, prefixes, index) {
173
+ let start = index;
174
+ while (start > 0 && !isLineBreak(text.charCodeAt(start - 1))) {
175
+ start--;
176
+ }
177
+ let end = index;
178
+ while (end < text.length && !isLineBreak(text.charCodeAt(end))) {
179
+ end++;
180
+ }
181
+ for (let i = start; i < end; i++) {
182
+ if (i === index || isBlank(text.charCodeAt(i))) {
183
+ continue;
184
+ }
185
+ if (prefixes.some(prefix => i >= prefix.start && i < prefix.start + prefix.length)) {
186
+ continue;
187
+ }
188
+ return true;
189
+ }
190
+ return false;
191
+ }
192
+
193
+ /** The characters of a span that survive the cut, which is CommonMark's `alt`. */
194
+ function flatten(text, cut, start, end) {
195
+ let flattened = "";
196
+ let segmentStart = start;
197
+ for (let i = start; i < end; i++) {
198
+ if (cut[i] === 1) {
199
+ if (segmentStart < i) {
200
+ flattened += text.slice(segmentStart, i);
201
+ }
202
+ segmentStart = i + 1;
203
+ }
204
+ }
205
+ return segmentStart < end ? flattened + text.slice(segmentStart, end) : flattened;
206
+ }
207
+ /** Shared for the same reason `NO_EMBEDS` is. */
208
+ const NO_IMAGES = [];
209
+
210
+ /**
211
+ * The images in `text`, with the three things a renderer needs to show one.
212
+ *
213
+ * Read straight off the ranges, because the parser has already made an image
214
+ * flat: inside a label it emits nothing but the `syntax` the markup is spelled
215
+ * with and one `alt` range over the lot. So there is exactly one `link`
216
+ * range in a span -- the destination -- and no image nested in another, and
217
+ * neither case needs guarding here.
218
+ *
219
+ * `alt` still has to be flattened, since a single range cannot skip the `**` in
220
+ * `![**a**](b)`. `cut` is what does it: it already marks every character the
221
+ * strip is removing, so reading the label through it gives exactly the string
222
+ * CommonMark would have put in the attribute.
223
+ */
224
+ function imageSpans(text, ranges, cut) {
225
+ const spans = [];
226
+ for (let i = 0; i < ranges.length; i++) {
227
+ const image = ranges[i];
228
+ if (image.type !== "image") {
229
+ continue;
230
+ }
231
+ const start = image.start;
232
+ const end = Math.min(start + image.length, text.length);
233
+ const span = {
234
+ start,
235
+ end,
236
+ uri: "",
237
+ alt: "",
238
+ title: ""
239
+ };
240
+ for (let j = i + 1; j < ranges.length; j++) {
241
+ const inner = ranges[j];
242
+ const innerEnd = inner.start + inner.length;
243
+
244
+ // Ranges are not sorted -- a container is emitted after the content of
245
+ // the line it encloses -- so anything reaching past the image is one of
246
+ // those and is skipped rather than ending the walk.
247
+ if (inner.start >= end) {
248
+ break;
249
+ }
250
+ if (innerEnd > end) {
251
+ continue;
252
+ }
253
+ if (inner.type === "alt") {
254
+ span.alt = flatten(text, cut, inner.start, innerEnd);
255
+ } else if (inner.type === "link") {
256
+ span.uri = text.slice(inner.start, innerEnd);
257
+ } else if (inner.type === "title") {
258
+ span.title = text.slice(inner.start, innerEnd);
259
+ }
260
+ }
261
+ spans.push(span);
262
+ }
263
+ return spans;
264
+ }
265
+
266
+ /**
267
+ * The bounds of every maths span, whether or not the caller means to render one.
268
+ *
269
+ * A display with nothing to draw maths with keeps `$x^2$` exactly as it was
270
+ * written: cutting only the dollars would leave `x^2`, which is neither the
271
+ * markdown nor the maths, and TeX read as prose is worse than TeX read as TeX.
272
+ * So the delimiters inside these bounds are spared the syntax cut.
273
+ */
274
+ function mathBounds(ranges) {
275
+ const bounds = [];
276
+ for (const range of ranges) {
277
+ if (range.type === "math" || range.type === "math-block") {
278
+ bounds.push({
279
+ start: range.start,
280
+ end: range.start + range.length
281
+ });
282
+ }
283
+ }
284
+ return bounds;
285
+ }
286
+
287
+ /** A maths span as the strip sees it, before the offsets move. */
288
+
289
+ /** Shared for the same reason `NO_EMBEDS` is. */
290
+ const NO_MATH_SPANS = [];
291
+
292
+ /**
293
+ * The maths spans in `text`, with the TeX each one carries.
294
+ *
295
+ * Nothing has to be walked for the content: the parser makes a maths span
296
+ * opaque -- one range over the lot and `syntax` over the delimiters, and
297
+ * nothing at all for what is between them -- so the TeX is simply the
298
+ * characters the strip is not already removing. `cut` is what says which those
299
+ * are, which is why this runs at the same moment `imageSpans` does: after the
300
+ * syntax has been marked and before the spans themselves are.
301
+ *
302
+ * A `$$` block is trimmed because its delimiters sit on lines of their own, so
303
+ * what survives between them opens and closes with a line break.
304
+ */
305
+ function mathSpans(text, ranges, cut) {
306
+ const spans = [];
307
+ for (const range of ranges) {
308
+ if (range.type !== "math" && range.type !== "math-block") {
309
+ continue;
310
+ }
311
+ const start = range.start;
312
+ const end = Math.min(start + range.length, text.length);
313
+ const tex = flatten(text, cut, start, end).trim();
314
+
315
+ // `$$` with nothing in it is punctuation, not maths. Left as it was
316
+ // written rather than turned into a placeholder standing for nothing.
317
+ if (tex === "") {
318
+ continue;
319
+ }
320
+ spans.push({
321
+ start,
322
+ end,
323
+ tex,
324
+ display: range.type === "math-block"
325
+ });
326
+ }
327
+ return spans;
328
+ }
329
+ /** Shared for the same reason `NO_EMBEDS` is. */
330
+ const NO_LINK_SPANS = [];
331
+
332
+ /**
333
+ * The links in `text`, as the text that will be left of each and where it
334
+ * points.
335
+ *
336
+ * A written link is a label followed immediately by a resource, so the label is
337
+ * the one that opens at `](`. A label with no resource after it is a reference
338
+ * or a shortcut, and nothing here can resolve one: it is still styled as a link
339
+ * -- that much the ranges say -- but there is no destination to press it to.
340
+ *
341
+ * An autolink has no label at all and is its own text, so any `link` left over
342
+ * is one. Left over means outside every resource: the destinations are `link`
343
+ * ranges too, and each has already been taken by the label in front of it or
344
+ * belongs to an image, which has no label to press. The exception is a
345
+ * definition's destination -- `[ref]: https://example.com` -- which is written
346
+ * plainly, is shown as written, and is treated as what it looks like.
347
+ */
348
+ function linkSpans(text, ranges, resources) {
349
+ const spans = [];
350
+ for (const range of ranges) {
351
+ const end = range.start + range.length;
352
+ let span = null;
353
+ if (range.type === "label") {
354
+ const resource = resources.find(candidate => candidate.open === end + 1);
355
+ if (resource !== undefined) {
356
+ span = {
357
+ start: range.start,
358
+ end,
359
+ uri: resource.uri,
360
+ title: resource.title
361
+ };
362
+ }
363
+ } else if (range.type === "link" && !resources.some(resource => range.start > resource.open && range.start < resource.close)) {
364
+ span = {
365
+ start: range.start,
366
+ end,
367
+ uri: text.slice(range.start, end),
368
+ title: ""
369
+ };
370
+ }
371
+ if (span === null) {
372
+ continue;
373
+ }
374
+
375
+ // A link cannot hold another one, but micromark still reports the construct
376
+ // it finds inside a label: `[see <https://x.com>](y)` arrives as a label
377
+ // with an autolink in it. A label is emitted before its own content, so the
378
+ // one that encloses the other is the one already here -- and it is the one
379
+ // to keep, being the whole of what the reader is shown. Two of them would
380
+ // be worse than a wrong choice: the caller splices the text at these, and
381
+ // spans that overlap would splice the run they share in twice.
382
+ if (spans.length > 0 && span.start < spans[spans.length - 1].end) {
383
+ continue;
384
+ }
385
+ spans.push(span);
386
+ }
387
+ return spans;
388
+ }
389
+
390
+ /**
391
+ * The spans as offsets into the stripped text, carrying the label they now
392
+ * cover. `offsets` is null when nothing was cut and the two texts are the same.
393
+ */
394
+ function toLinks(text, spans, offsets) {
395
+ if (spans.length === 0) {
396
+ return NO_LINKS;
397
+ }
398
+ const links = [];
399
+ for (const span of spans) {
400
+ const start = offsets === null ? span.start : offsets[span.start];
401
+ const end = offsets === null ? span.end : offsets[span.end];
402
+
403
+ // A label that was nothing but markup -- `[**](x)` -- has nothing left to
404
+ // press.
405
+ if (end <= start) {
406
+ continue;
407
+ }
408
+ links.push({
409
+ start,
410
+ length: end - start,
411
+ uri: span.uri,
412
+ label: text.slice(start, end),
413
+ title: span.title
414
+ });
415
+ }
416
+ return links;
417
+ }
418
+
419
+ /**
420
+ * A span that collapses to a single placeholder character, of either kind.
421
+ *
422
+ * Images and maths are the same problem -- a run of markdown that the display
423
+ * does not read but draws, and that costs the platform exactly one character --
424
+ * so they go through one set of machinery. Sorting by offset is enough to put
425
+ * them back in emission order: both are emitted from the parser as they are
426
+ * met, and neither can contain the other.
427
+ */
428
+
429
+ /** Shared for the same reason `NO_EMBEDS` is. */
430
+ const NO_ATOMS = [];
431
+ function atomsOf(images, maths) {
432
+ if (images.length === 0) {
433
+ return maths.length === 0 ? NO_ATOMS : maths;
434
+ }
435
+ if (maths.length === 0) {
436
+ return images;
437
+ }
438
+ return [...images, ...maths].sort((a, b) => a.start - b.start);
439
+ }
440
+
441
+ /** Whether a range is one that stands for an atom rather than describing text. */
442
+ function isAtomType(type) {
443
+ return type === "image" || type === "math" || type === "math-block";
444
+ }
445
+
446
+ /**
447
+ * Widens the cuts already marked on a line to cover the whitespace that only
448
+ * existed to separate a marker from what it marked.
449
+ *
450
+ * A line opens with a run of block markers and the blanks between them. Walking
451
+ * that run, a blank goes only if the marker in front of it went: `# Title` and
452
+ * `> - item` lose their spacing, `- item` keeps the one its bullet needs.
453
+ *
454
+ * A line that turns out to be nothing but removed markers takes its own line
455
+ * break with it, so a setext underline or a thematic break does not leave a
456
+ * blank line behind.
457
+ */
458
+ function absorbMarkerSpacing(text, cut, marker) {
459
+ let lineStart = 0;
460
+ while (lineStart <= text.length) {
461
+ let lineEnd = lineStart;
462
+ while (lineEnd < text.length) {
463
+ const code = text.charCodeAt(lineEnd);
464
+ if (code === LINE_FEED || code === CARRIAGE_RETURN) {
465
+ break;
466
+ }
467
+ lineEnd++;
468
+ }
469
+ let cursor = lineStart;
470
+ let cutSomething = false;
471
+ let keptMarker = false;
472
+ let afterCut = false;
473
+ while (cursor < lineEnd) {
474
+ const blank = isBlank(text.charCodeAt(cursor));
475
+ if (cut[cursor] === 1) {
476
+ cutSomething = true;
477
+ afterCut = true;
478
+ } else if (blank) {
479
+ if (afterCut) {
480
+ cut[cursor] = 1;
481
+ }
482
+ } else if (marker[cursor] === 1) {
483
+ keptMarker = true;
484
+ afterCut = false;
485
+ } else {
486
+ break;
487
+ }
488
+ cursor++;
489
+ }
490
+
491
+ // Nothing readable left on the line, and no marker worth keeping either.
492
+ if (cursor >= lineEnd && cutSomething && !keptMarker) {
493
+ for (let i = lineStart; i < lineEnd; i++) {
494
+ cut[i] = 1;
495
+ }
496
+
497
+ // The break in front, for any line but the first, which has none and
498
+ // takes the one behind instead.
499
+ if (lineStart > 0) {
500
+ let index = lineStart - 1;
501
+ if (text.charCodeAt(index) === LINE_FEED) {
502
+ cut[index] = 1;
503
+ index--;
504
+ }
505
+ if (index >= 0 && text.charCodeAt(index) === CARRIAGE_RETURN) {
506
+ cut[index] = 1;
507
+ }
508
+ } else {
509
+ let index = lineEnd;
510
+ if (text.charCodeAt(index) === CARRIAGE_RETURN) {
511
+ cut[index] = 1;
512
+ index++;
513
+ }
514
+ if (text.charCodeAt(index) === LINE_FEED) {
515
+ cut[index] = 1;
516
+ }
517
+ }
518
+ }
519
+ if (lineEnd >= text.length) {
520
+ break;
521
+ }
522
+ lineStart = lineEnd;
523
+ if (text.charCodeAt(lineStart) === CARRIAGE_RETURN) {
524
+ lineStart++;
525
+ }
526
+ if (text.charCodeAt(lineStart) === LINE_FEED) {
527
+ lineStart++;
528
+ }
529
+ }
530
+ }
531
+
532
+ /**
533
+ * What a type means once the markup around it is gone.
534
+ *
535
+ * A link's label is the one type that changes. While it is being edited it is
536
+ * text between two brackets and is left alone; once the brackets have been
537
+ * removed it is the only thing left standing for the link, so it takes the
538
+ * link's styling -- the destination it was pointing at having been removed too.
539
+ */
540
+ function displayType(type) {
541
+ return type === "label" ? "link" : type;
542
+ }
543
+
544
+ /**
545
+ * Removes the markdown syntax from `text` and rewrites `ranges` to index what
546
+ * is left.
547
+ *
548
+ * Ranges are only ever dropped or shortened, never reordered, so the emission
549
+ * order the native formatters depend on survives -- a `block-prefix` still
550
+ * arrives immediately before its container, and a container that lost its
551
+ * marker entirely arrives with none, which is exactly the gutter-without-marker
552
+ * case the block layout already handles.
553
+ */
554
+ function stripSyntax(text, ranges, options = {}) {
555
+ if (text.length === 0 || ranges.length === 0) {
556
+ return {
557
+ text,
558
+ ranges,
559
+ embeds: NO_EMBEDS,
560
+ maths: NO_MATHS,
561
+ links: NO_LINKS
562
+ };
563
+ }
564
+ const markers = listMarkers(ranges);
565
+ // Only when there is nothing to draw maths with: otherwise the spans are cut
566
+ // whole a few lines down and sparing their dollars would be pointless work.
567
+ const spared = options.math ? [] : mathBounds(ranges);
568
+ const cut = new Uint8Array(text.length);
569
+ const kept = new Uint8Array(text.length);
570
+ let cutSomething = false;
571
+ for (const range of ranges) {
572
+ // A fenced block's language is metadata about the block, not part of it, so
573
+ // it goes the same way the fence itself does.
574
+ if (range.type !== "syntax" && range.type !== "language") {
575
+ continue;
576
+ }
577
+ const start = range.start;
578
+ const end = Math.min(start + range.length, text.length);
579
+ if (spared.some(span => start >= span.start && end <= span.end)) {
580
+ continue;
581
+ }
582
+ const inListMarker = range.type === "syntax" && markers.some(marker => start >= marker.start && end <= marker.end) && !isQuoteMarker(text, start, end);
583
+ for (let i = start; i < end; i++) {
584
+ if (inListMarker) {
585
+ kept[i] = 1;
586
+ } else {
587
+ cut[i] = 1;
588
+ cutSomething = true;
589
+ }
590
+ }
591
+ }
592
+ const resources = resourceSpans(text, ranges);
593
+ const links = options.links ? linkSpans(text, ranges, resources) : NO_LINK_SPANS;
594
+ cutSomething = cutResources(resources, cut) || cutSomething;
595
+
596
+ // An image goes whole -- markup, alt text and destination alike -- and leaves
597
+ // one character behind. Keeping one of its own characters rather than
598
+ // splicing a new one in is what lets the offsets below stay as they are: a
599
+ // range is still only ever shortened, never moved.
600
+ // After the cuts above and before the images are cut themselves, which is the
601
+ // one moment `cut` describes the markup inside a label without describing the
602
+ // label's own removal -- exactly what flattening the alt text needs.
603
+ const images = options.embeds ? imageSpans(text, ranges, cut) : NO_IMAGES;
604
+ const maths = options.math ? mathSpans(text, ranges, cut) : NO_MATH_SPANS;
605
+ const atoms = atomsOf(images, maths);
606
+ const placeholder = atoms.length > 0 ? new Uint8Array(text.length) : null;
607
+ for (const atom of atoms) {
608
+ for (let i = atom.start; i < atom.end; i++) {
609
+ cut[i] = 1;
610
+ // 1 for a character the atom swallowed, 2 for the one it left behind.
611
+ placeholder[i] = 1;
612
+ }
613
+ cut[atom.start] = 0;
614
+ placeholder[atom.start] = 2;
615
+ cutSomething = true;
616
+ }
617
+ if (!cutSomething) {
618
+ // Nothing moved, so the spans already index the text as it stands. A bare
619
+ // URL gets here: it is a link written with no syntax at all.
620
+ return {
621
+ text,
622
+ ranges,
623
+ embeds: NO_EMBEDS,
624
+ maths: NO_MATHS,
625
+ links: toLinks(text, links, null)
626
+ };
627
+ }
628
+ absorbMarkerSpacing(text, cut, kept);
629
+
630
+ // Kept characters before each offset, which is where that offset lands once
631
+ // the cuts are gone. One extra entry so a range's end can be mapped the same
632
+ // way as its start.
633
+ const offsets = new Int32Array(text.length + 1);
634
+ let stripped = "";
635
+ let segmentStart = 0;
636
+ let survivors = 0;
637
+ for (let i = 0; i < text.length; i++) {
638
+ offsets[i] = survivors;
639
+ if (placeholder !== null && placeholder[i] === 2) {
640
+ if (segmentStart < i) {
641
+ stripped += text.slice(segmentStart, i);
642
+ }
643
+ stripped += OBJECT_REPLACEMENT;
644
+ segmentStart = i + 1;
645
+ survivors++;
646
+ } else if (cut[i] === 1) {
647
+ if (segmentStart < i) {
648
+ stripped += text.slice(segmentStart, i);
649
+ }
650
+ segmentStart = i + 1;
651
+ } else {
652
+ survivors++;
653
+ }
654
+ }
655
+ offsets[text.length] = survivors;
656
+ if (segmentStart < text.length) {
657
+ stripped += text.slice(segmentStart);
658
+ }
659
+ const remapped = [];
660
+ // The atom being walked past, if any: everything it swallowed goes with it,
661
+ // save its own range, which shrinks onto the character left behind. Without
662
+ // this the `syntax` over the `!` of an image or the opening `$` of a maths
663
+ // span -- the very character kept as the placeholder -- would survive to
664
+ // style what stands there as markup.
665
+ //
666
+ // Swallowed means emitted after the atom opened and ending inside it, which
667
+ // is what tells the alt text apart from the two kinds of range that reach
668
+ // over an atom and have to survive: the label of a link written around an
669
+ // image, which is emitted before it, and the container of the line it sits
670
+ // on, which is emitted after and runs past its end.
671
+ let atom = 0;
672
+ let insideStart = -1;
673
+ let insideEnd = -1;
674
+ for (const range of ranges) {
675
+ // One span per atom range, in the order they were emitted, so the two walks
676
+ // stay in step. Matched on the offset as well as the type, because a kind
677
+ // of atom the caller did not ask for is not one: an `image` range with no
678
+ // `renderEmbed` behind it is still just a range.
679
+ if (atom < atoms.length && isAtomType(range.type) && range.start === atoms[atom].start) {
680
+ insideStart = atoms[atom].start;
681
+ insideEnd = atoms[atom].end;
682
+ atom++;
683
+ } else if (range.start >= insideStart && range.start + range.length <= insideEnd) {
684
+ continue;
685
+ }
686
+ let start = offsets[Math.min(range.start, text.length)];
687
+ const end = offsets[Math.min(range.start + range.length, text.length)];
688
+
689
+ // A fenced block opens with a line of its own, and cutting that line leaves
690
+ // the break that ended it at the front of the block. What is left then
691
+ // starts on the line above the code, which is a blank first line in
692
+ // whatever draws the block as a box.
693
+ if (range.type === "codeblock") {
694
+ while (start < end && isLineBreak(stripped.charCodeAt(start))) {
695
+ start++;
696
+ }
697
+ }
698
+ if (end <= start) {
699
+ continue;
700
+ }
701
+ const next = {
702
+ type: displayType(range.type),
703
+ start,
704
+ length: end - start
705
+ };
706
+ if (range.depth !== undefined) {
707
+ next.depth = range.depth;
708
+ }
709
+ remapped.push(next);
710
+ }
711
+ const prefixes = atoms.length > 0 ? remapped.filter(range => range.type === "block-prefix") : [];
712
+ const embeds = images.length > 0 ? images.map(image => {
713
+ const index = offsets[image.start];
714
+ return {
715
+ index,
716
+ uri: image.uri,
717
+ alt: image.alt,
718
+ title: image.title,
719
+ inline: sharesItsLine(stripped, prefixes, index)
720
+ };
721
+ }) : NO_EMBEDS;
722
+ const mathsOut = maths.length > 0 ? maths.map(span => {
723
+ const index = offsets[span.start];
724
+ return {
725
+ index,
726
+ tex: span.tex,
727
+ display: span.display
728
+ };
729
+ }) : NO_MATHS;
730
+ return {
731
+ text: stripped,
732
+ ranges: remapped,
733
+ embeds,
734
+ maths: mathsOut,
735
+ links: toLinks(stripped, links, offsets)
736
+ };
737
+ }
738
+ export { OBJECT_REPLACEMENT, stripSyntax };
739
+ //# sourceMappingURL=stripUtils.js.map