@payloadcms/richtext-lexical 4.0.0-internal.1f9ae9a → 4.0.0-internal.2fddfc0

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 (352) hide show
  1. package/dist/@types/assets.d.js +2 -0
  2. package/dist/@types/assets.d.js.map +1 -0
  3. package/dist/cell/rscEntry.d.ts.map +1 -1
  4. package/dist/cell/rscEntry.js +5 -5
  5. package/dist/cell/rscEntry.js.map +1 -1
  6. package/dist/exports/client/Field-VW7ZGT6K.js +2 -0
  7. package/dist/exports/client/Field-VW7ZGT6K.js.map +7 -0
  8. package/dist/exports/client/{RelationshipComponent-RZL743CS.js → RelationshipComponent-YCPAKOL7.js} +1 -1
  9. package/dist/exports/client/RelationshipComponent-YCPAKOL7.js.map +7 -0
  10. package/dist/exports/client/bundled.css +1 -1
  11. package/dist/exports/client/chunk-4EIYXZ6H.js +12 -0
  12. package/dist/exports/client/chunk-4EIYXZ6H.js.map +7 -0
  13. package/dist/exports/client/chunk-5VIL27GI.js +2 -0
  14. package/dist/exports/client/chunk-5VIL27GI.js.map +7 -0
  15. package/dist/exports/client/chunk-ESITTE3C.js +2 -0
  16. package/dist/exports/client/chunk-ESITTE3C.js.map +7 -0
  17. package/dist/exports/client/chunk-UD4DQ4AK.js +2 -0
  18. package/dist/exports/client/chunk-UD4DQ4AK.js.map +7 -0
  19. package/dist/exports/client/{component-CVM4OESA.js → component-PHZQBOJE.js} +2 -2
  20. package/dist/exports/client/component-PHZQBOJE.js.map +7 -0
  21. package/dist/exports/client/componentInline-H24N7GUG.js +2 -0
  22. package/dist/exports/client/index.d.ts +1 -0
  23. package/dist/exports/client/index.d.ts.map +1 -1
  24. package/dist/exports/client/index.js +25 -25
  25. package/dist/exports/client/index.js.map +4 -4
  26. package/dist/exports/server/rsc.browser.d.ts +11 -0
  27. package/dist/exports/server/rsc.browser.d.ts.map +1 -0
  28. package/dist/exports/server/rsc.browser.js +10 -0
  29. package/dist/exports/server/rsc.browser.js.map +1 -0
  30. package/dist/features/blockquote/server/index.d.ts +1 -4
  31. package/dist/features/blockquote/server/index.d.ts.map +1 -1
  32. package/dist/features/blockquote/server/index.js +2 -0
  33. package/dist/features/blockquote/server/index.js.map +1 -1
  34. package/dist/features/blockquote/server/schema.d.ts +8 -0
  35. package/dist/features/blockquote/server/schema.d.ts.map +1 -0
  36. package/dist/features/blockquote/server/schema.js +15 -0
  37. package/dist/features/blockquote/server/schema.js.map +1 -0
  38. package/dist/features/blocks/client/component/index.d.ts +2 -1
  39. package/dist/features/blocks/client/component/index.d.ts.map +1 -1
  40. package/dist/features/blocks/client/component/index.js +16 -8
  41. package/dist/features/blocks/client/component/index.js.map +1 -1
  42. package/dist/features/blocks/client/componentInline/index.d.ts +2 -1
  43. package/dist/features/blocks/client/componentInline/index.d.ts.map +1 -1
  44. package/dist/features/blocks/client/componentInline/index.js +15 -7
  45. package/dist/features/blocks/client/componentInline/index.js.map +1 -1
  46. package/dist/features/blocks/client/index.d.ts.map +1 -1
  47. package/dist/features/blocks/client/index.js +4 -2
  48. package/dist/features/blocks/client/index.js.map +1 -1
  49. package/dist/features/blocks/client/markdown/markdownTransformer.js +4 -4
  50. package/dist/features/blocks/client/markdown/markdownTransformer.js.map +1 -1
  51. package/dist/features/blocks/client/nodes/BlocksNode.d.ts +1 -1
  52. package/dist/features/blocks/client/nodes/BlocksNode.d.ts.map +1 -1
  53. package/dist/features/blocks/client/nodes/BlocksNode.js.map +1 -1
  54. package/dist/features/blocks/client/nodes/InlineBlocksNode.d.ts +1 -1
  55. package/dist/features/blocks/client/nodes/InlineBlocksNode.d.ts.map +1 -1
  56. package/dist/features/blocks/client/nodes/InlineBlocksNode.js.map +1 -1
  57. package/dist/features/blocks/client/plugin/index.d.ts +1 -1
  58. package/dist/features/blocks/client/plugin/index.d.ts.map +1 -1
  59. package/dist/features/blocks/client/plugin/index.js.map +1 -1
  60. package/dist/features/blocks/premade/CodeBlock/Component/Block.d.ts.map +1 -1
  61. package/dist/features/blocks/premade/CodeBlock/Component/Block.js +1 -0
  62. package/dist/features/blocks/premade/CodeBlock/Component/Block.js.map +1 -1
  63. package/dist/features/blocks/server/graphQLPopulationPromise.d.ts +1 -2
  64. package/dist/features/blocks/server/graphQLPopulationPromise.d.ts.map +1 -1
  65. package/dist/features/blocks/server/graphQLPopulationPromise.js.map +1 -1
  66. package/dist/features/blocks/server/index.d.ts +1 -0
  67. package/dist/features/blocks/server/index.d.ts.map +1 -1
  68. package/dist/features/blocks/server/index.js +24 -72
  69. package/dist/features/blocks/server/index.js.map +1 -1
  70. package/dist/features/blocks/server/markdown/markdownTransformer.js +4 -4
  71. package/dist/features/blocks/server/markdown/markdownTransformer.js.map +1 -1
  72. package/dist/features/blocks/server/nodes/BlocksNode.d.ts +1 -18
  73. package/dist/features/blocks/server/nodes/BlocksNode.d.ts.map +1 -1
  74. package/dist/features/blocks/server/nodes/BlocksNode.js.map +1 -1
  75. package/dist/features/blocks/server/nodes/InlineBlocksNode.d.ts +2 -10
  76. package/dist/features/blocks/server/nodes/InlineBlocksNode.d.ts.map +1 -1
  77. package/dist/features/blocks/server/nodes/InlineBlocksNode.js.map +1 -1
  78. package/dist/features/blocks/server/schema.d.ts +45 -0
  79. package/dist/features/blocks/server/schema.d.ts.map +1 -0
  80. package/dist/features/blocks/server/schema.js +139 -0
  81. package/dist/features/blocks/server/schema.js.map +1 -0
  82. package/dist/features/blocks/server/validate.d.ts +1 -2
  83. package/dist/features/blocks/server/validate.d.ts.map +1 -1
  84. package/dist/features/blocks/server/validate.js.map +1 -1
  85. package/dist/features/converters/lexicalToHtml/async/converters/upload.js.map +1 -1
  86. package/dist/features/converters/lexicalToHtml/async/types.d.ts +14 -15
  87. package/dist/features/converters/lexicalToHtml/async/types.d.ts.map +1 -1
  88. package/dist/features/converters/lexicalToHtml/async/types.js.map +1 -1
  89. package/dist/features/converters/lexicalToHtml/sync/converters/upload.js.map +1 -1
  90. package/dist/features/converters/lexicalToHtml/sync/types.d.ts +14 -15
  91. package/dist/features/converters/lexicalToHtml/sync/types.d.ts.map +1 -1
  92. package/dist/features/converters/lexicalToHtml/sync/types.js.map +1 -1
  93. package/dist/features/converters/lexicalToJSX/Component/index.d.ts +4 -2
  94. package/dist/features/converters/lexicalToJSX/Component/index.d.ts.map +1 -1
  95. package/dist/features/converters/lexicalToJSX/Component/index.js +5 -4
  96. package/dist/features/converters/lexicalToJSX/Component/index.js.map +1 -1
  97. package/dist/features/converters/lexicalToJSX/converter/converters/upload.js.map +1 -1
  98. package/dist/features/converters/lexicalToJSX/converter/types.d.ts +12 -14
  99. package/dist/features/converters/lexicalToJSX/converter/types.d.ts.map +1 -1
  100. package/dist/features/converters/lexicalToJSX/converter/types.js.map +1 -1
  101. package/dist/features/converters/lexicalToPlaintext/sync/types.d.ts +12 -14
  102. package/dist/features/converters/lexicalToPlaintext/sync/types.d.ts.map +1 -1
  103. package/dist/features/converters/lexicalToPlaintext/sync/types.js.map +1 -1
  104. package/dist/features/experimental_table/server/index.d.ts +1 -6
  105. package/dist/features/experimental_table/server/index.d.ts.map +1 -1
  106. package/dist/features/experimental_table/server/index.js +4 -0
  107. package/dist/features/experimental_table/server/index.js.map +1 -1
  108. package/dist/features/experimental_table/server/schema.d.ts +27 -0
  109. package/dist/features/experimental_table/server/schema.d.ts.map +1 -0
  110. package/dist/features/experimental_table/server/schema.js +107 -0
  111. package/dist/features/experimental_table/server/schema.js.map +1 -0
  112. package/dist/features/heading/server/index.d.ts +2 -4
  113. package/dist/features/heading/server/index.d.ts.map +1 -1
  114. package/dist/features/heading/server/index.js +2 -0
  115. package/dist/features/heading/server/index.js.map +1 -1
  116. package/dist/features/heading/server/schema.d.ts +10 -0
  117. package/dist/features/heading/server/schema.d.ts.map +1 -0
  118. package/dist/features/heading/server/schema.js +37 -0
  119. package/dist/features/heading/server/schema.js.map +1 -0
  120. package/dist/features/horizontalRule/client/nodes/HorizontalRuleNode.d.ts +1 -1
  121. package/dist/features/horizontalRule/client/nodes/HorizontalRuleNode.d.ts.map +1 -1
  122. package/dist/features/horizontalRule/client/nodes/HorizontalRuleNode.js.map +1 -1
  123. package/dist/features/horizontalRule/server/index.d.ts +1 -0
  124. package/dist/features/horizontalRule/server/index.d.ts.map +1 -1
  125. package/dist/features/horizontalRule/server/index.js +2 -0
  126. package/dist/features/horizontalRule/server/index.js.map +1 -1
  127. package/dist/features/horizontalRule/server/nodes/HorizontalRuleNode.d.ts +1 -5
  128. package/dist/features/horizontalRule/server/nodes/HorizontalRuleNode.d.ts.map +1 -1
  129. package/dist/features/horizontalRule/server/nodes/HorizontalRuleNode.js.map +1 -1
  130. package/dist/features/horizontalRule/server/schema.d.ts +7 -0
  131. package/dist/features/horizontalRule/server/schema.d.ts.map +1 -0
  132. package/dist/features/horizontalRule/server/schema.js +25 -0
  133. package/dist/features/horizontalRule/server/schema.js.map +1 -0
  134. package/dist/features/link/client/index.d.ts.map +1 -1
  135. package/dist/features/link/client/index.js.map +1 -1
  136. package/dist/features/link/client/plugins/autoLink/index.d.ts +1 -1
  137. package/dist/features/link/client/plugins/autoLink/index.d.ts.map +1 -1
  138. package/dist/features/link/client/plugins/autoLink/index.js.map +1 -1
  139. package/dist/features/link/client/plugins/floatingLinkEditor/LinkEditor/index.js.map +1 -1
  140. package/dist/features/link/client/plugins/floatingLinkEditor/types.d.ts +1 -1
  141. package/dist/features/link/client/plugins/floatingLinkEditor/types.d.ts.map +1 -1
  142. package/dist/features/link/client/plugins/floatingLinkEditor/types.js.map +1 -1
  143. package/dist/features/link/client/plugins/link/index.js.map +1 -1
  144. package/dist/features/link/markdownTransformer.d.ts +1 -1
  145. package/dist/features/link/markdownTransformer.d.ts.map +1 -1
  146. package/dist/features/link/markdownTransformer.js.map +1 -1
  147. package/dist/features/link/markdownTransformer.spec.js.map +1 -1
  148. package/dist/features/link/nodes/AutoLinkNode.d.ts +3 -3
  149. package/dist/features/link/nodes/AutoLinkNode.d.ts.map +1 -1
  150. package/dist/features/link/nodes/AutoLinkNode.js +2 -1
  151. package/dist/features/link/nodes/AutoLinkNode.js.map +1 -1
  152. package/dist/features/link/nodes/LinkNode.d.ts +3 -3
  153. package/dist/features/link/nodes/LinkNode.d.ts.map +1 -1
  154. package/dist/features/link/nodes/LinkNode.js +2 -1
  155. package/dist/features/link/nodes/LinkNode.js.map +1 -1
  156. package/dist/features/link/server/baseFields.js.map +1 -1
  157. package/dist/features/link/server/graphQLPopulationPromise.d.ts +1 -1
  158. package/dist/features/link/server/graphQLPopulationPromise.d.ts.map +1 -1
  159. package/dist/features/link/server/graphQLPopulationPromise.js.map +1 -1
  160. package/dist/features/link/server/index.d.ts +2 -1
  161. package/dist/features/link/server/index.d.ts.map +1 -1
  162. package/dist/features/link/server/index.js +3 -0
  163. package/dist/features/link/server/index.js.map +1 -1
  164. package/dist/features/link/server/schema.d.ts +32 -0
  165. package/dist/features/link/server/schema.d.ts.map +1 -0
  166. package/dist/features/link/server/schema.js +169 -0
  167. package/dist/features/link/server/schema.js.map +1 -0
  168. package/dist/features/link/server/validate.d.ts +1 -1
  169. package/dist/features/link/server/validate.d.ts.map +1 -1
  170. package/dist/features/link/server/validate.js.map +1 -1
  171. package/dist/features/lists/checklist/server/index.d.ts.map +1 -1
  172. package/dist/features/lists/checklist/server/index.js +3 -0
  173. package/dist/features/lists/checklist/server/index.js.map +1 -1
  174. package/dist/features/lists/orderedList/server/index.d.ts.map +1 -1
  175. package/dist/features/lists/orderedList/server/index.js +3 -0
  176. package/dist/features/lists/orderedList/server/index.js.map +1 -1
  177. package/dist/features/lists/plugin/index.d.ts +0 -9
  178. package/dist/features/lists/plugin/index.d.ts.map +1 -1
  179. package/dist/features/lists/plugin/index.js.map +1 -1
  180. package/dist/features/lists/shared/schema.d.ts +18 -0
  181. package/dist/features/lists/shared/schema.d.ts.map +1 -0
  182. package/dist/features/lists/shared/schema.js +62 -0
  183. package/dist/features/lists/shared/schema.js.map +1 -0
  184. package/dist/features/lists/unorderedList/server/index.d.ts.map +1 -1
  185. package/dist/features/lists/unorderedList/server/index.js +3 -0
  186. package/dist/features/lists/unorderedList/server/index.js.map +1 -1
  187. package/dist/features/relationship/client/components/RelationshipComponent.d.ts +1 -1
  188. package/dist/features/relationship/client/components/RelationshipComponent.d.ts.map +1 -1
  189. package/dist/features/relationship/client/components/RelationshipComponent.js.map +1 -1
  190. package/dist/features/relationship/client/nodes/RelationshipNode.d.ts +1 -1
  191. package/dist/features/relationship/client/nodes/RelationshipNode.d.ts.map +1 -1
  192. package/dist/features/relationship/client/nodes/RelationshipNode.js.map +1 -1
  193. package/dist/features/relationship/client/plugins/index.d.ts +1 -1
  194. package/dist/features/relationship/client/plugins/index.d.ts.map +1 -1
  195. package/dist/features/relationship/client/plugins/index.js.map +1 -1
  196. package/dist/features/relationship/client/utils/useEnabledRelationships.d.ts.map +1 -1
  197. package/dist/features/relationship/client/utils/useEnabledRelationships.js +9 -40
  198. package/dist/features/relationship/client/utils/useEnabledRelationships.js.map +1 -1
  199. package/dist/features/relationship/server/graphQLPopulationPromise.d.ts +1 -1
  200. package/dist/features/relationship/server/graphQLPopulationPromise.d.ts.map +1 -1
  201. package/dist/features/relationship/server/graphQLPopulationPromise.js.map +1 -1
  202. package/dist/features/relationship/server/index.d.ts +1 -0
  203. package/dist/features/relationship/server/index.d.ts.map +1 -1
  204. package/dist/features/relationship/server/index.js +2 -0
  205. package/dist/features/relationship/server/index.js.map +1 -1
  206. package/dist/features/relationship/server/nodes/RelationshipNode.d.ts +1 -10
  207. package/dist/features/relationship/server/nodes/RelationshipNode.d.ts.map +1 -1
  208. package/dist/features/relationship/server/nodes/RelationshipNode.js.map +1 -1
  209. package/dist/features/relationship/server/schema.d.ts +28 -0
  210. package/dist/features/relationship/server/schema.d.ts.map +1 -0
  211. package/dist/features/relationship/server/schema.js +80 -0
  212. package/dist/features/relationship/server/schema.js.map +1 -0
  213. package/dist/features/relationship/shared/filterEnabledRelationshipCollections.d.ts +23 -0
  214. package/dist/features/relationship/shared/filterEnabledRelationshipCollections.d.ts.map +1 -0
  215. package/dist/features/relationship/shared/filterEnabledRelationshipCollections.js +34 -0
  216. package/dist/features/relationship/shared/filterEnabledRelationshipCollections.js.map +1 -0
  217. package/dist/features/typesServer.d.ts +17 -40
  218. package/dist/features/typesServer.d.ts.map +1 -1
  219. package/dist/features/typesServer.js.map +1 -1
  220. package/dist/features/upload/client/component/index.css +2 -2
  221. package/dist/features/upload/client/component/index.d.ts +1 -1
  222. package/dist/features/upload/client/component/index.d.ts.map +1 -1
  223. package/dist/features/upload/client/component/index.js.map +1 -1
  224. package/dist/features/upload/client/nodes/UploadNode.d.ts +1 -1
  225. package/dist/features/upload/client/nodes/UploadNode.d.ts.map +1 -1
  226. package/dist/features/upload/client/nodes/UploadNode.js.map +1 -1
  227. package/dist/features/upload/client/plugin/index.d.ts +1 -1
  228. package/dist/features/upload/client/plugin/index.d.ts.map +1 -1
  229. package/dist/features/upload/client/plugin/index.js.map +1 -1
  230. package/dist/features/upload/server/graphQLPopulationPromise.d.ts +1 -1
  231. package/dist/features/upload/server/graphQLPopulationPromise.d.ts.map +1 -1
  232. package/dist/features/upload/server/graphQLPopulationPromise.js.map +1 -1
  233. package/dist/features/upload/server/index.d.ts +1 -0
  234. package/dist/features/upload/server/index.d.ts.map +1 -1
  235. package/dist/features/upload/server/index.js +3 -2
  236. package/dist/features/upload/server/index.js.map +1 -1
  237. package/dist/features/upload/server/nodes/UploadNode.d.ts +1 -55
  238. package/dist/features/upload/server/nodes/UploadNode.d.ts.map +1 -1
  239. package/dist/features/upload/server/nodes/UploadNode.js.map +1 -1
  240. package/dist/features/upload/server/nodes/conversions.d.ts.map +1 -1
  241. package/dist/features/upload/server/nodes/conversions.js.map +1 -1
  242. package/dist/features/upload/server/schema.d.ts +52 -0
  243. package/dist/features/upload/server/schema.d.ts.map +1 -0
  244. package/dist/features/upload/server/schema.js +129 -0
  245. package/dist/features/upload/server/schema.js.map +1 -0
  246. package/dist/features/upload/server/validate.d.ts +1 -1
  247. package/dist/features/upload/server/validate.d.ts.map +1 -1
  248. package/dist/features/upload/server/validate.js.map +1 -1
  249. package/dist/field/Diff/converters/upload/index.js.map +1 -1
  250. package/dist/field/bundled.css +1 -1
  251. package/dist/field/clientEntry.d.ts +29 -0
  252. package/dist/field/clientEntry.d.ts.map +1 -0
  253. package/dist/field/clientEntry.js +86 -0
  254. package/dist/field/clientEntry.js.map +1 -0
  255. package/dist/field/index.css +12 -12
  256. package/dist/field/index.js +1 -1
  257. package/dist/field/index.js.map +1 -1
  258. package/dist/field/rscEntry.d.ts.map +1 -1
  259. package/dist/field/rscEntry.js +2 -0
  260. package/dist/field/rscEntry.js.map +1 -1
  261. package/dist/index.d.ts +8 -5
  262. package/dist/index.d.ts.map +1 -1
  263. package/dist/index.js +47 -4
  264. package/dist/index.js.map +1 -1
  265. package/dist/lexical/LexicalEditor.d.ts.map +1 -1
  266. package/dist/lexical/LexicalEditor.js +36 -2
  267. package/dist/lexical/LexicalEditor.js.map +1 -1
  268. package/dist/lexical/LexicalProvider.d.ts.map +1 -1
  269. package/dist/lexical/LexicalProvider.js +22 -7
  270. package/dist/lexical/LexicalProvider.js.map +1 -1
  271. package/dist/lexical/config/client/loader.d.ts.map +1 -1
  272. package/dist/lexical/config/client/loader.js +5 -1
  273. package/dist/lexical/config/client/loader.js.map +1 -1
  274. package/dist/lexical/config/server/sanitize.d.ts.map +1 -1
  275. package/dist/lexical/config/server/sanitize.js +9 -11
  276. package/dist/lexical/config/server/sanitize.js.map +1 -1
  277. package/dist/packages/@lexical/markdown/LexicalMarkdownHardLineBreak.spec.js +160 -0
  278. package/dist/packages/@lexical/markdown/LexicalMarkdownHardLineBreak.spec.js.map +1 -0
  279. package/dist/packages/@lexical/markdown/MarkdownExport.d.ts.map +1 -1
  280. package/dist/packages/@lexical/markdown/MarkdownExport.js +9 -2
  281. package/dist/packages/@lexical/markdown/MarkdownExport.js.map +1 -1
  282. package/dist/packages/@lexical/markdown/MarkdownImport.d.ts.map +1 -1
  283. package/dist/packages/@lexical/markdown/MarkdownImport.js +3 -2
  284. package/dist/packages/@lexical/markdown/MarkdownImport.js.map +1 -1
  285. package/dist/packages/@lexical/markdown/MarkdownTransformers.d.ts +27 -1
  286. package/dist/packages/@lexical/markdown/MarkdownTransformers.d.ts.map +1 -1
  287. package/dist/packages/@lexical/markdown/MarkdownTransformers.js +88 -4
  288. package/dist/packages/@lexical/markdown/MarkdownTransformers.js.map +1 -1
  289. package/dist/types/builtInNodes.d.ts +14 -0
  290. package/dist/types/builtInNodes.d.ts.map +1 -0
  291. package/dist/types/builtInNodes.js +203 -0
  292. package/dist/types/builtInNodes.js.map +1 -0
  293. package/dist/types/index.d.ts +16 -17
  294. package/dist/types/index.d.ts.map +1 -1
  295. package/dist/types/index.js.map +1 -1
  296. package/dist/types/jsonSchemaHelpers.d.ts +30 -0
  297. package/dist/types/jsonSchemaHelpers.d.ts.map +1 -0
  298. package/dist/types/jsonSchemaHelpers.js +58 -0
  299. package/dist/types/jsonSchemaHelpers.js.map +1 -0
  300. package/dist/types/nodeTypes.d.ts +115 -61
  301. package/dist/types/nodeTypes.d.ts.map +1 -1
  302. package/dist/types/nodeTypes.js +3 -2
  303. package/dist/types/nodeTypes.js.map +1 -1
  304. package/dist/types/schema.d.ts.map +1 -1
  305. package/dist/types/schema.js +67 -65
  306. package/dist/types/schema.js.map +1 -1
  307. package/dist/utilities/applyBaseFilterToFields.d.ts.map +1 -1
  308. package/dist/utilities/applyBaseFilterToFields.js +1 -2
  309. package/dist/utilities/applyBaseFilterToFields.js.map +1 -1
  310. package/dist/utilities/buildEditorState.d.ts +17 -3
  311. package/dist/utilities/buildEditorState.d.ts.map +1 -1
  312. package/dist/utilities/buildEditorState.js +8 -0
  313. package/dist/utilities/buildEditorState.js.map +1 -1
  314. package/dist/utilities/buildInitialState.d.ts +2 -1
  315. package/dist/utilities/buildInitialState.d.ts.map +1 -1
  316. package/dist/utilities/buildInitialState.js.map +1 -1
  317. package/dist/utilities/fieldsDrawer/Drawer.d.ts.map +1 -1
  318. package/dist/utilities/fieldsDrawer/Drawer.js +19 -10
  319. package/dist/utilities/fieldsDrawer/Drawer.js.map +1 -1
  320. package/dist/utilities/fieldsDrawer/DrawerContent.d.ts +4 -1
  321. package/dist/utilities/fieldsDrawer/DrawerContent.d.ts.map +1 -1
  322. package/dist/utilities/fieldsDrawer/DrawerContent.js +8 -7
  323. package/dist/utilities/fieldsDrawer/DrawerContent.js.map +1 -1
  324. package/dist/utilities/fieldsDrawer/index.css +12 -0
  325. package/dist/utilities/fieldsDrawer/useDrawerSubmit.d.ts +29 -0
  326. package/dist/utilities/fieldsDrawer/useDrawerSubmit.d.ts.map +1 -0
  327. package/dist/utilities/fieldsDrawer/useDrawerSubmit.js +97 -0
  328. package/dist/utilities/fieldsDrawer/useDrawerSubmit.js.map +1 -0
  329. package/dist/utilities/generateImportMap.d.ts.map +1 -1
  330. package/dist/utilities/generateImportMap.js +7 -3
  331. package/dist/utilities/generateImportMap.js.map +1 -1
  332. package/dist/utilities/upgradeLexicalData/upgradeDocumentFieldsRecursively.js +1 -1
  333. package/dist/utilities/upgradeLexicalData/upgradeDocumentFieldsRecursively.js.map +1 -1
  334. package/package.json +8 -7
  335. package/dist/exports/client/Field-G5Z2HM5Y.js +0 -2
  336. package/dist/exports/client/Field-G5Z2HM5Y.js.map +0 -7
  337. package/dist/exports/client/RelationshipComponent-RZL743CS.js.map +0 -7
  338. package/dist/exports/client/chunk-6QWQ7JV4.js +0 -2
  339. package/dist/exports/client/chunk-6QWQ7JV4.js.map +0 -7
  340. package/dist/exports/client/chunk-FEJXFRL7.js +0 -2
  341. package/dist/exports/client/chunk-FEJXFRL7.js.map +0 -7
  342. package/dist/exports/client/chunk-INBEEENE.js +0 -2
  343. package/dist/exports/client/chunk-INBEEENE.js.map +0 -7
  344. package/dist/exports/client/chunk-LH634DPU.js +0 -12
  345. package/dist/exports/client/chunk-LH634DPU.js.map +0 -7
  346. package/dist/exports/client/component-CVM4OESA.js.map +0 -7
  347. package/dist/exports/client/componentInline-JJZ2NKW2.js +0 -2
  348. package/dist/features/link/nodes/types.d.ts +0 -27
  349. package/dist/features/link/nodes/types.d.ts.map +0 -1
  350. package/dist/features/link/nodes/types.js +0 -2
  351. package/dist/features/link/nodes/types.js.map +0 -1
  352. /package/dist/exports/client/{componentInline-JJZ2NKW2.js.map → componentInline-H24N7GUG.js.map} +0 -0
@@ -4,7 +4,8 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- */import { $getRoot, $isDecoratorNode, $isElementNode, $isLineBreakNode, $isTextNode } from 'lexical';
7
+ */import { $getRoot, $getState, $isDecoratorNode, $isElementNode, $isLineBreakNode, $isTextNode } from 'lexical';
8
+ import { hardLineBreakState } from './MarkdownTransformers.js';
8
9
  import { isEmptyParagraph, transformersByType } from './utils.js';
9
10
  /**
10
11
  * Renders string from markdown. The selection is moved to the start after the operation.
@@ -89,7 +90,7 @@ function exportChildren(node, textTransformersIndex, textMatchTransformers, uncl
89
90
  }
90
91
  }
91
92
  if ($isLineBreakNode(child)) {
92
- output.push('\n');
93
+ output.push($exportLineBreak(child));
93
94
  } else if ($isTextNode(child)) {
94
95
  output.push(exportTextFormat(child, child.getTextContent(), textTransformersIndex, unclosedTags, unclosableTags));
95
96
  } else if ($isElementNode(child)) {
@@ -101,6 +102,12 @@ function exportChildren(node, textTransformersIndex, textMatchTransformers, uncl
101
102
  }
102
103
  return output.join('');
103
104
  }
105
+ // Prefixes the newline with the original CommonMark hard line break marker
106
+ // (`\` or trailing spaces) when one was preserved on import, otherwise exports a
107
+ // plain soft line break.
108
+ function $exportLineBreak(node) {
109
+ return $getState(node, hardLineBreakState) + '\n';
110
+ }
104
111
  function exportTextFormat(node, textContent, textTransformers,
105
112
  // unclosed tags include the markdown tags that haven't been closed yet, and their associated formats
106
113
  unclosedTags, unclosableTags) {
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownExport.js","names":["$getRoot","$isDecoratorNode","$isElementNode","$isLineBreakNode","$isTextNode","isEmptyParagraph","transformersByType","createMarkdownExport","transformers","shouldPreserveNewLines","byType","elementTransformers","multilineElement","element","isNewlineDelimited","textFormatTransformers","textFormat","filter","transformer","format","length","sort","a","b","includes","node","output","children","getChildren","forEach","child","i","result","exportTopLevelElements","textMatch","push","concat","join","textTransformersIndex","textMatchTransformers","export","_node","exportChildren","getTextContent","unclosedTags","unclosableTags","mainLoop","parentNode","textNode","textContent","exportTextFormat","textTransformers","frozenString","trim","hasFormat","replace","openingTags","closingTagsBefore","closingTagsAfter","prevNode","getTextSibling","nextNode","applied","Set","tag","has","add","find","unclosedTag","nodeHasFormat","nextNodeHasFormat","unhandledUnclosedTags","pop","backward","sibling","getPreviousSibling","getNextSibling","parent","getParentOrThrow","isInline","descendant","getLastDescendant","getFirstDescendant"],"sources":["../../../../src/packages/@lexical/markdown/MarkdownExport.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { ElementNode, LexicalNode, TextFormatType, TextNode } from 'lexical'\n\nimport { $getRoot, $isDecoratorNode, $isElementNode, $isLineBreakNode, $isTextNode } from 'lexical'\n\nimport type {\n ElementTransformer,\n MultilineElementTransformer,\n TextFormatTransformer,\n TextMatchTransformer,\n Transformer,\n} from './MarkdownTransformers.js'\n\nimport { isEmptyParagraph, transformersByType } from './utils.js'\n\n/**\n * Renders string from markdown. The selection is moved to the start after the operation.\n */\nexport function createMarkdownExport(\n transformers: Array<Transformer>,\n shouldPreserveNewLines: boolean = false,\n): (node?: ElementNode) => string {\n const byType = transformersByType(transformers)\n const elementTransformers = [...byType.multilineElement, ...byType.element]\n const isNewlineDelimited = !shouldPreserveNewLines\n\n // Export only uses text formats that are responsible for single format\n // e.g. it will filter out *** (bold, italic) and instead use separate ** and *\n const textFormatTransformers = byType.textFormat\n .filter((transformer) => transformer.format.length === 1)\n // Make sure all text transformers that contain 'code' in their format are at the end of the array. Otherwise, formatted code like\n // <strong><code>code</code></strong> will be exported as `**Bold Code**`, as the code format will be applied first, and the bold format\n // will be applied second and thus skipped entirely, as the code format will prevent any further formatting.\n .sort((a, b) => {\n if (a.format.includes('code') && !b.format.includes('code')) {\n return 1\n } else if (!a.format.includes('code') && b.format.includes('code')) {\n return -1\n } else {\n return 0\n }\n })\n\n return (node) => {\n const output: string[] = []\n const children = (node || $getRoot()).getChildren()\n\n children.forEach((child, i) => {\n const result = exportTopLevelElements(\n child,\n elementTransformers,\n textFormatTransformers,\n byType.textMatch,\n )\n\n if (result != null) {\n output.push(\n // separate consecutive group of texts with a line break: eg. [\"hello\", \"world\"] -> [\"hello\", \"/nworld\"]\n isNewlineDelimited &&\n i > 0 &&\n !isEmptyParagraph(child) &&\n !isEmptyParagraph(children[i - 1]!)\n ? '\\n'.concat(result)\n : result,\n )\n }\n })\n // Ensure consecutive groups of texts are at least \\n\\n apart while each empty paragraph render as a newline.\n // Eg. [\"hello\", \"\", \"\", \"hi\", \"\\nworld\"] -> \"hello\\n\\n\\nhi\\n\\nworld\"\n return output.join('\\n')\n }\n}\n\nfunction exportTopLevelElements(\n node: LexicalNode,\n elementTransformers: Array<ElementTransformer | MultilineElementTransformer>,\n textTransformersIndex: Array<TextFormatTransformer>,\n textMatchTransformers: Array<TextMatchTransformer>,\n): null | string {\n for (const transformer of elementTransformers) {\n if (!transformer.export) {\n continue\n }\n const result = transformer.export(node, (_node) =>\n exportChildren(_node, textTransformersIndex, textMatchTransformers),\n )\n\n if (result != null) {\n return result\n }\n }\n\n if ($isElementNode(node)) {\n return exportChildren(node, textTransformersIndex, textMatchTransformers)\n } else if ($isDecoratorNode(node)) {\n return node.getTextContent()\n } else {\n return null\n }\n}\n\nfunction exportChildren(\n node: ElementNode,\n textTransformersIndex: Array<TextFormatTransformer>,\n textMatchTransformers: Array<TextMatchTransformer>,\n unclosedTags?: Array<{ format: TextFormatType; tag: string }>,\n unclosableTags?: Array<{ format: TextFormatType; tag: string }>,\n): string {\n const output = []\n const children = node.getChildren()\n // keep track of unclosed tags from the very beginning\n if (!unclosedTags) {\n unclosedTags = []\n }\n if (!unclosableTags) {\n unclosableTags = []\n }\n\n mainLoop: for (const child of children) {\n for (const transformer of textMatchTransformers) {\n if (!transformer.export) {\n continue\n }\n\n const result = transformer.export(\n child,\n (parentNode) =>\n exportChildren(\n parentNode,\n textTransformersIndex,\n textMatchTransformers,\n unclosedTags,\n // Add current unclosed tags to the list of unclosable tags - we don't want nested tags from\n // textmatch transformers to close the outer ones, as that may result in invalid markdown.\n // E.g. **text [text**](https://lexical.io)\n // is invalid markdown, as the closing ** is inside the link.\n //\n [...unclosableTags, ...unclosedTags],\n ),\n (textNode, textContent) =>\n exportTextFormat(\n textNode,\n textContent,\n textTransformersIndex,\n unclosedTags,\n unclosableTags,\n ),\n )\n\n if (result != null) {\n output.push(result)\n continue mainLoop\n }\n }\n\n if ($isLineBreakNode(child)) {\n output.push('\\n')\n } else if ($isTextNode(child)) {\n output.push(\n exportTextFormat(\n child,\n child.getTextContent(),\n textTransformersIndex,\n unclosedTags,\n unclosableTags,\n ),\n )\n } else if ($isElementNode(child)) {\n // empty paragraph returns \"\"\n output.push(\n exportChildren(\n child,\n textTransformersIndex,\n textMatchTransformers,\n unclosedTags,\n unclosableTags,\n ),\n )\n } else if ($isDecoratorNode(child)) {\n output.push(child.getTextContent())\n }\n }\n\n return output.join('')\n}\n\nfunction exportTextFormat(\n node: TextNode,\n textContent: string,\n textTransformers: Array<TextFormatTransformer>,\n // unclosed tags include the markdown tags that haven't been closed yet, and their associated formats\n unclosedTags: Array<{ format: TextFormatType; tag: string }>,\n unclosableTags?: Array<{ format: TextFormatType; tag: string }>,\n): string {\n // This function handles the case of a string looking like this: \" foo \"\n // Where it would be invalid markdown to generate: \"** foo **\"\n // We instead want to trim the whitespace out, apply formatting, and then\n // bring the whitespace back. So our returned string looks like this: \" **foo** \"\n const frozenString = textContent.trim()\n let output = frozenString\n\n if (!node.hasFormat('code')) {\n // Escape any markdown characters in the text content\n output = output.replace(/([*_`~\\\\])/g, '\\\\$1')\n }\n\n // the opening tags to be added to the result\n let openingTags = ''\n // the closing tags to be added to the result\n let closingTagsBefore = ''\n let closingTagsAfter = ''\n\n const prevNode = getTextSibling(node, true)\n const nextNode = getTextSibling(node, false)\n\n const applied = new Set()\n\n for (const transformer of textTransformers) {\n const format = transformer.format[0]!\n const tag = transformer.tag\n\n // dedup applied formats\n if (hasFormat(node, format) && !applied.has(format)) {\n // Multiple tags might be used for the same format (*, _)\n applied.add(format)\n\n // append the tag to openningTags, if it's not applied to the previous nodes,\n // or the nodes before that (which would result in an unclosed tag)\n if (!hasFormat(prevNode, format) || !unclosedTags.find((element) => element.tag === tag)) {\n unclosedTags.push({ format, tag })\n openingTags += tag\n }\n }\n }\n\n // close any tags in the same order they were applied, if necessary\n for (let i = 0; i < unclosedTags.length; i++) {\n const unclosedTag = unclosedTags[i]!\n const nodeHasFormat = hasFormat(node, unclosedTag.format)\n const nextNodeHasFormat = hasFormat(nextNode, unclosedTag.format)\n\n // prevent adding closing tag if next sibling will do it\n if (nodeHasFormat && nextNodeHasFormat) {\n continue\n }\n\n const unhandledUnclosedTags = [...unclosedTags] // Shallow copy to avoid modifying the original array\n\n while (unhandledUnclosedTags.length > i) {\n const unclosedTag = unhandledUnclosedTags.pop()\n\n // If tag is unclosable, don't close it and leave it in the original array,\n // So that it can be closed when it's no longer unclosable\n if (\n unclosableTags &&\n unclosedTag &&\n unclosableTags.find((element) => element.tag === unclosedTag.tag)\n ) {\n continue\n }\n\n if (unclosedTag && typeof unclosedTag.tag === 'string') {\n if (!nodeHasFormat) {\n // Handles cases where the tag has not been closed before, e.g. if the previous node\n // was a text match transformer that did not account for closing tags of the next node (e.g. a link)\n closingTagsBefore += unclosedTag.tag\n } else if (!nextNodeHasFormat) {\n closingTagsAfter += unclosedTag.tag\n }\n }\n // Mutate the original array to remove the closed tag\n unclosedTags.pop()\n }\n break\n }\n\n output = openingTags + output + closingTagsAfter\n // Replace trimmed version of textContent ensuring surrounding whitespace is not modified\n return closingTagsBefore + textContent.replace(frozenString, () => output)\n}\n\n// Get next or previous text sibling a text node, including cases\n// when it's a child of inline element (e.g. link)\nfunction getTextSibling(node: TextNode, backward: boolean): null | TextNode {\n let sibling = backward ? node.getPreviousSibling() : node.getNextSibling()\n\n if (!sibling) {\n const parent = node.getParentOrThrow()\n\n if (parent.isInline()) {\n sibling = backward ? parent.getPreviousSibling() : parent.getNextSibling()\n }\n }\n\n while (sibling) {\n if ($isElementNode(sibling)) {\n if (!sibling.isInline()) {\n break\n }\n\n const descendant = backward ? sibling.getLastDescendant() : sibling.getFirstDescendant()\n\n if ($isTextNode(descendant)) {\n return descendant\n } else {\n sibling = backward ? sibling.getPreviousSibling() : sibling.getNextSibling()\n }\n }\n\n if ($isTextNode(sibling)) {\n return sibling\n }\n\n if (!$isElementNode(sibling)) {\n return null\n }\n }\n\n return null\n}\n\nfunction hasFormat(node: LexicalNode | null | undefined, format: TextFormatType): boolean {\n return $isTextNode(node) && node.hasFormat(format)\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MarkdownExport.js","names":["$getRoot","$getState","$isDecoratorNode","$isElementNode","$isLineBreakNode","$isTextNode","hardLineBreakState","isEmptyParagraph","transformersByType","createMarkdownExport","transformers","shouldPreserveNewLines","byType","elementTransformers","multilineElement","element","isNewlineDelimited","textFormatTransformers","textFormat","filter","transformer","format","length","sort","a","b","includes","node","output","children","getChildren","forEach","child","i","result","exportTopLevelElements","textMatch","push","concat","join","textTransformersIndex","textMatchTransformers","export","_node","exportChildren","getTextContent","unclosedTags","unclosableTags","mainLoop","parentNode","textNode","textContent","exportTextFormat","$exportLineBreak","textTransformers","frozenString","trim","hasFormat","replace","openingTags","closingTagsBefore","closingTagsAfter","prevNode","getTextSibling","nextNode","applied","Set","tag","has","add","find","unclosedTag","nodeHasFormat","nextNodeHasFormat","unhandledUnclosedTags","pop","backward","sibling","getPreviousSibling","getNextSibling","parent","getParentOrThrow","isInline","descendant","getLastDescendant","getFirstDescendant"],"sources":["../../../../src/packages/@lexical/markdown/MarkdownExport.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { ElementNode, LexicalNode, LineBreakNode, TextFormatType, TextNode } from 'lexical'\n\nimport {\n $getRoot,\n $getState,\n $isDecoratorNode,\n $isElementNode,\n $isLineBreakNode,\n $isTextNode,\n} from 'lexical'\n\nimport type {\n ElementTransformer,\n MultilineElementTransformer,\n TextFormatTransformer,\n TextMatchTransformer,\n Transformer,\n} from './MarkdownTransformers.js'\n\nimport { hardLineBreakState } from './MarkdownTransformers.js'\nimport { isEmptyParagraph, transformersByType } from './utils.js'\n\n/**\n * Renders string from markdown. The selection is moved to the start after the operation.\n */\nexport function createMarkdownExport(\n transformers: Array<Transformer>,\n shouldPreserveNewLines: boolean = false,\n): (node?: ElementNode) => string {\n const byType = transformersByType(transformers)\n const elementTransformers = [...byType.multilineElement, ...byType.element]\n const isNewlineDelimited = !shouldPreserveNewLines\n\n // Export only uses text formats that are responsible for single format\n // e.g. it will filter out *** (bold, italic) and instead use separate ** and *\n const textFormatTransformers = byType.textFormat\n .filter((transformer) => transformer.format.length === 1)\n // Make sure all text transformers that contain 'code' in their format are at the end of the array. Otherwise, formatted code like\n // <strong><code>code</code></strong> will be exported as `**Bold Code**`, as the code format will be applied first, and the bold format\n // will be applied second and thus skipped entirely, as the code format will prevent any further formatting.\n .sort((a, b) => {\n if (a.format.includes('code') && !b.format.includes('code')) {\n return 1\n } else if (!a.format.includes('code') && b.format.includes('code')) {\n return -1\n } else {\n return 0\n }\n })\n\n return (node) => {\n const output: string[] = []\n const children = (node || $getRoot()).getChildren()\n\n children.forEach((child, i) => {\n const result = exportTopLevelElements(\n child,\n elementTransformers,\n textFormatTransformers,\n byType.textMatch,\n )\n\n if (result != null) {\n output.push(\n // separate consecutive group of texts with a line break: eg. [\"hello\", \"world\"] -> [\"hello\", \"/nworld\"]\n isNewlineDelimited &&\n i > 0 &&\n !isEmptyParagraph(child) &&\n !isEmptyParagraph(children[i - 1]!)\n ? '\\n'.concat(result)\n : result,\n )\n }\n })\n // Ensure consecutive groups of texts are at least \\n\\n apart while each empty paragraph render as a newline.\n // Eg. [\"hello\", \"\", \"\", \"hi\", \"\\nworld\"] -> \"hello\\n\\n\\nhi\\n\\nworld\"\n return output.join('\\n')\n }\n}\n\nfunction exportTopLevelElements(\n node: LexicalNode,\n elementTransformers: Array<ElementTransformer | MultilineElementTransformer>,\n textTransformersIndex: Array<TextFormatTransformer>,\n textMatchTransformers: Array<TextMatchTransformer>,\n): null | string {\n for (const transformer of elementTransformers) {\n if (!transformer.export) {\n continue\n }\n const result = transformer.export(node, (_node) =>\n exportChildren(_node, textTransformersIndex, textMatchTransformers),\n )\n\n if (result != null) {\n return result\n }\n }\n\n if ($isElementNode(node)) {\n return exportChildren(node, textTransformersIndex, textMatchTransformers)\n } else if ($isDecoratorNode(node)) {\n return node.getTextContent()\n } else {\n return null\n }\n}\n\nfunction exportChildren(\n node: ElementNode,\n textTransformersIndex: Array<TextFormatTransformer>,\n textMatchTransformers: Array<TextMatchTransformer>,\n unclosedTags?: Array<{ format: TextFormatType; tag: string }>,\n unclosableTags?: Array<{ format: TextFormatType; tag: string }>,\n): string {\n const output = []\n const children = node.getChildren()\n // keep track of unclosed tags from the very beginning\n if (!unclosedTags) {\n unclosedTags = []\n }\n if (!unclosableTags) {\n unclosableTags = []\n }\n\n mainLoop: for (const child of children) {\n for (const transformer of textMatchTransformers) {\n if (!transformer.export) {\n continue\n }\n\n const result = transformer.export(\n child,\n (parentNode) =>\n exportChildren(\n parentNode,\n textTransformersIndex,\n textMatchTransformers,\n unclosedTags,\n // Add current unclosed tags to the list of unclosable tags - we don't want nested tags from\n // textmatch transformers to close the outer ones, as that may result in invalid markdown.\n // E.g. **text [text**](https://lexical.io)\n // is invalid markdown, as the closing ** is inside the link.\n //\n [...unclosableTags, ...unclosedTags],\n ),\n (textNode, textContent) =>\n exportTextFormat(\n textNode,\n textContent,\n textTransformersIndex,\n unclosedTags,\n unclosableTags,\n ),\n )\n\n if (result != null) {\n output.push(result)\n continue mainLoop\n }\n }\n\n if ($isLineBreakNode(child)) {\n output.push($exportLineBreak(child))\n } else if ($isTextNode(child)) {\n output.push(\n exportTextFormat(\n child,\n child.getTextContent(),\n textTransformersIndex,\n unclosedTags,\n unclosableTags,\n ),\n )\n } else if ($isElementNode(child)) {\n // empty paragraph returns \"\"\n output.push(\n exportChildren(\n child,\n textTransformersIndex,\n textMatchTransformers,\n unclosedTags,\n unclosableTags,\n ),\n )\n } else if ($isDecoratorNode(child)) {\n output.push(child.getTextContent())\n }\n }\n\n return output.join('')\n}\n\n// Prefixes the newline with the original CommonMark hard line break marker\n// (`\\` or trailing spaces) when one was preserved on import, otherwise exports a\n// plain soft line break.\nfunction $exportLineBreak(node: LineBreakNode): string {\n return $getState(node, hardLineBreakState) + '\\n'\n}\n\nfunction exportTextFormat(\n node: TextNode,\n textContent: string,\n textTransformers: Array<TextFormatTransformer>,\n // unclosed tags include the markdown tags that haven't been closed yet, and their associated formats\n unclosedTags: Array<{ format: TextFormatType; tag: string }>,\n unclosableTags?: Array<{ format: TextFormatType; tag: string }>,\n): string {\n // This function handles the case of a string looking like this: \" foo \"\n // Where it would be invalid markdown to generate: \"** foo **\"\n // We instead want to trim the whitespace out, apply formatting, and then\n // bring the whitespace back. So our returned string looks like this: \" **foo** \"\n const frozenString = textContent.trim()\n let output = frozenString\n\n if (!node.hasFormat('code')) {\n // Escape any markdown characters in the text content\n output = output.replace(/([*_`~\\\\])/g, '\\\\$1')\n }\n\n // the opening tags to be added to the result\n let openingTags = ''\n // the closing tags to be added to the result\n let closingTagsBefore = ''\n let closingTagsAfter = ''\n\n const prevNode = getTextSibling(node, true)\n const nextNode = getTextSibling(node, false)\n\n const applied = new Set()\n\n for (const transformer of textTransformers) {\n const format = transformer.format[0]!\n const tag = transformer.tag\n\n // dedup applied formats\n if (hasFormat(node, format) && !applied.has(format)) {\n // Multiple tags might be used for the same format (*, _)\n applied.add(format)\n\n // append the tag to openningTags, if it's not applied to the previous nodes,\n // or the nodes before that (which would result in an unclosed tag)\n if (!hasFormat(prevNode, format) || !unclosedTags.find((element) => element.tag === tag)) {\n unclosedTags.push({ format, tag })\n openingTags += tag\n }\n }\n }\n\n // close any tags in the same order they were applied, if necessary\n for (let i = 0; i < unclosedTags.length; i++) {\n const unclosedTag = unclosedTags[i]!\n const nodeHasFormat = hasFormat(node, unclosedTag.format)\n const nextNodeHasFormat = hasFormat(nextNode, unclosedTag.format)\n\n // prevent adding closing tag if next sibling will do it\n if (nodeHasFormat && nextNodeHasFormat) {\n continue\n }\n\n const unhandledUnclosedTags = [...unclosedTags] // Shallow copy to avoid modifying the original array\n\n while (unhandledUnclosedTags.length > i) {\n const unclosedTag = unhandledUnclosedTags.pop()\n\n // If tag is unclosable, don't close it and leave it in the original array,\n // So that it can be closed when it's no longer unclosable\n if (\n unclosableTags &&\n unclosedTag &&\n unclosableTags.find((element) => element.tag === unclosedTag.tag)\n ) {\n continue\n }\n\n if (unclosedTag && typeof unclosedTag.tag === 'string') {\n if (!nodeHasFormat) {\n // Handles cases where the tag has not been closed before, e.g. if the previous node\n // was a text match transformer that did not account for closing tags of the next node (e.g. a link)\n closingTagsBefore += unclosedTag.tag\n } else if (!nextNodeHasFormat) {\n closingTagsAfter += unclosedTag.tag\n }\n }\n // Mutate the original array to remove the closed tag\n unclosedTags.pop()\n }\n break\n }\n\n output = openingTags + output + closingTagsAfter\n // Replace trimmed version of textContent ensuring surrounding whitespace is not modified\n return closingTagsBefore + textContent.replace(frozenString, () => output)\n}\n\n// Get next or previous text sibling a text node, including cases\n// when it's a child of inline element (e.g. link)\nfunction getTextSibling(node: TextNode, backward: boolean): null | TextNode {\n let sibling = backward ? node.getPreviousSibling() : node.getNextSibling()\n\n if (!sibling) {\n const parent = node.getParentOrThrow()\n\n if (parent.isInline()) {\n sibling = backward ? parent.getPreviousSibling() : parent.getNextSibling()\n }\n }\n\n while (sibling) {\n if ($isElementNode(sibling)) {\n if (!sibling.isInline()) {\n break\n }\n\n const descendant = backward ? sibling.getLastDescendant() : sibling.getFirstDescendant()\n\n if ($isTextNode(descendant)) {\n return descendant\n } else {\n sibling = backward ? sibling.getPreviousSibling() : sibling.getNextSibling()\n }\n }\n\n if ($isTextNode(sibling)) {\n return sibling\n }\n\n if (!$isElementNode(sibling)) {\n return null\n }\n }\n\n return null\n}\n\nfunction hasFormat(node: LexicalNode | null | undefined, format: TextFormatType): boolean {\n return $isTextNode(node) && node.hasFormat(format)\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownImport.d.ts","sourceRoot":"","sources":["../../../../src/packages/@lexical/markdown/MarkdownImport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAc1C,OAAO,KAAK,EAGV,qBAAqB,EAErB,WAAW,EACZ,MAAM,2BAA2B,CAAA;AAKlC,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACtD,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAA;CACnE,CAAC,CAAA;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAChC,sBAAsB,UAAQ,GAC7B,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,IAAI,CAyCtD"}
1
+ {"version":3,"file":"MarkdownImport.d.ts","sourceRoot":"","sources":["../../../../src/packages/@lexical/markdown/MarkdownImport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAa1C,OAAO,KAAK,EAGV,qBAAqB,EAErB,WAAW,EACZ,MAAM,2BAA2B,CAAA;AAMlC,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACtD,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAA;CACnE,CAAC,CAAA;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAChC,sBAAsB,UAAQ,GAC7B,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,IAAI,CAyCtD"}
@@ -7,8 +7,9 @@
7
7
  */import { $isListItemNode, $isListNode } from '@lexical/list';
8
8
  import { $isQuoteNode } from '@lexical/rich-text';
9
9
  import { $findMatchingParent } from '@lexical/utils';
10
- import { $createLineBreakNode, $createParagraphNode, $createTextNode, $getRoot, $getSelection, $isParagraphNode } from 'lexical';
10
+ import { $createParagraphNode, $createTextNode, $getRoot, $getSelection, $isParagraphNode } from 'lexical';
11
11
  import { importTextTransformers } from './importTextTransformers.js';
12
+ import { $createMarkdownLineBreakNode } from './MarkdownTransformers.js';
12
13
  import { isEmptyParagraph, transformersByType } from './utils.js';
13
14
  /**
14
15
  * Renders markdown from a string. The selection is moved to the start after the operation.
@@ -161,7 +162,7 @@ function $importBlocks(lineText, rootNode, elementTransformers, textFormatTransf
161
162
  }
162
163
  }
163
164
  if (targetNode != null && targetNode.getTextContentSize() > 0) {
164
- targetNode.splice(targetNode.getChildrenSize(), 0, [$createLineBreakNode(), ...elementNode.getChildren()]);
165
+ targetNode.splice(targetNode.getChildrenSize(), 0, [$createMarkdownLineBreakNode(targetNode), ...elementNode.getChildren()]);
165
166
  elementNode.remove();
166
167
  }
167
168
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownImport.js","names":["$isListItemNode","$isListNode","$isQuoteNode","$findMatchingParent","$createLineBreakNode","$createParagraphNode","$createTextNode","$getRoot","$getSelection","$isParagraphNode","importTextTransformers","isEmptyParagraph","transformersByType","createMarkdownImport","transformers","shouldPreserveNewLines","byType","textFormatTransformersIndex","createTextFormatTransformersIndex","textFormat","markdownString","node","lines","split","linesLength","length","root","clear","i","lineText","imported","shiftedIndex","$importMultiline","multilineElement","$importBlocks","element","textMatch","children","getChildren","child","getChildrenSize","remove","selectStart","startLineIndex","multilineElementTransformers","rootNode","transformer","handleImportAfterStartMatch","regExpEnd","regExpStart","replace","startMatch","match","result","regexpEndRegex","regExp","isEndOptional","optional","endLineIndex","endMatch","index","linesInBetween","push","slice","line","text","elementTransformers","textMatchTransformers","textNode","elementNode","append","setTextContent","isAttached","previousNode","getPreviousSibling","targetNode","lastDescendant","getLastDescendant","getTextContentSize","splice","textTransformers","transformersByTag","fullMatchRegExpByTag","openTagsRegExp","escapeRegExp","tag","tagRegExp","RegExp","join"],"sources":["../../../../src/packages/@lexical/markdown/MarkdownImport.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { ListItemNode } from '@lexical/list'\nimport type { ElementNode } from 'lexical'\n\nimport { $isListItemNode, $isListNode } from '@lexical/list'\nimport { $isQuoteNode } from '@lexical/rich-text'\nimport { $findMatchingParent } from '@lexical/utils'\nimport {\n $createLineBreakNode,\n $createParagraphNode,\n $createTextNode,\n $getRoot,\n $getSelection,\n $isParagraphNode,\n} from 'lexical'\n\nimport type {\n ElementTransformer,\n MultilineElementTransformer,\n TextFormatTransformer,\n TextMatchTransformer,\n Transformer,\n} from './MarkdownTransformers.js'\n\nimport { importTextTransformers } from './importTextTransformers.js'\nimport { isEmptyParagraph, transformersByType } from './utils.js'\n\nexport type TextFormatTransformersIndex = Readonly<{\n fullMatchRegExpByTag: Readonly<Record<string, RegExp>>\n openTagsRegExp: RegExp\n transformersByTag: Readonly<Record<string, TextFormatTransformer>>\n}>\n\n/**\n * Renders markdown from a string. The selection is moved to the start after the operation.\n */\nexport function createMarkdownImport(\n transformers: Array<Transformer>,\n shouldPreserveNewLines = false,\n): (markdownString: string, node?: ElementNode) => void {\n const byType = transformersByType(transformers)\n const textFormatTransformersIndex = createTextFormatTransformersIndex(byType.textFormat)\n\n return (markdownString, node) => {\n const lines = markdownString.split('\\n')\n const linesLength = lines.length\n const root = node || $getRoot()\n root.clear()\n\n for (let i = 0; i < linesLength; i++) {\n const lineText = lines[i]!\n\n const [imported, shiftedIndex] = $importMultiline(lines, i, byType.multilineElement, root)\n\n if (imported) {\n // If a multiline markdown element was imported, we don't want to process the lines that were part of it anymore.\n // There could be other sub-markdown elements (both multiline and normal ones) matching within this matched multiline element's children.\n // However, it would be the responsibility of the matched multiline transformer to decide how it wants to handle them.\n // We cannot handle those, as there is no way for us to know how to maintain the correct order of generated lexical nodes for possible children.\n i = shiftedIndex // Next loop will start from the line after the last line of the multiline element\n continue\n }\n\n $importBlocks(lineText, root, byType.element, textFormatTransformersIndex, byType.textMatch)\n }\n\n // By default, removing empty paragraphs as md does not really\n // allow empty lines and uses them as delimiter.\n // If you need empty lines set shouldPreserveNewLines = true.\n const children = root.getChildren()\n for (const child of children) {\n if (!shouldPreserveNewLines && isEmptyParagraph(child) && root.getChildrenSize() > 1) {\n child.remove()\n }\n }\n\n if ($getSelection() !== null) {\n root.selectStart()\n }\n }\n}\n\n/**\n *\n * @returns first element of the returned tuple is a boolean indicating if a multiline element was imported. The second element is the index of the last line that was processed.\n */\nfunction $importMultiline(\n lines: Array<string>,\n startLineIndex: number,\n multilineElementTransformers: Array<MultilineElementTransformer>,\n rootNode: ElementNode,\n): [boolean, number] {\n for (const transformer of multilineElementTransformers) {\n const { handleImportAfterStartMatch, regExpEnd, regExpStart, replace } = transformer\n\n const startMatch = lines[startLineIndex]?.match(regExpStart)\n if (!startMatch) {\n continue // Try next transformer\n }\n\n if (handleImportAfterStartMatch) {\n const result = handleImportAfterStartMatch({\n lines,\n rootNode,\n startLineIndex,\n startMatch,\n transformer,\n })\n if (result === null) {\n continue\n } else if (result) {\n return result\n }\n }\n\n const regexpEndRegex: RegExp | undefined =\n typeof regExpEnd === 'object' && 'regExp' in regExpEnd ? regExpEnd.regExp : regExpEnd\n\n const isEndOptional =\n regExpEnd && typeof regExpEnd === 'object' && 'optional' in regExpEnd\n ? regExpEnd.optional\n : !regExpEnd\n\n let endLineIndex = startLineIndex\n const linesLength = lines.length\n\n // check every single line for the closing match. It could also be on the same line as the opening match.\n while (endLineIndex < linesLength) {\n const endMatch = regexpEndRegex ? lines[endLineIndex]?.match(regexpEndRegex) : null\n if (!endMatch) {\n if (\n !isEndOptional ||\n (isEndOptional && endLineIndex < linesLength - 1) // Optional end, but didn't reach the end of the document yet => continue searching for potential closing match\n ) {\n endLineIndex++\n continue // Search next line for closing match\n }\n }\n\n // Now, check if the closing match matched is the same as the opening match.\n // If it is, we need to continue searching for the actual closing match.\n if (endMatch && startLineIndex === endLineIndex && endMatch.index === startMatch.index) {\n endLineIndex++\n continue // Search next line for closing match\n }\n\n // At this point, we have found the closing match. Next: calculate the lines in between open and closing match\n // This should not include the matches themselves, and be split up by lines\n const linesInBetween: string[] = []\n\n if (endMatch && startLineIndex === endLineIndex) {\n linesInBetween.push(lines[startLineIndex]!.slice(startMatch[0].length, -endMatch[0].length))\n } else {\n for (let i = startLineIndex; i <= endLineIndex; i++) {\n const line = lines[i]!\n if (i === startLineIndex) {\n const text = line.slice(startMatch[0].length)\n linesInBetween.push(text) // Also include empty text\n } else if (i === endLineIndex && endMatch) {\n const text = line.slice(0, -endMatch[0].length)\n linesInBetween.push(text) // Also include empty text\n } else {\n linesInBetween.push(line)\n }\n }\n }\n\n if (replace(rootNode, null, startMatch, endMatch!, linesInBetween, true) !== false) {\n // Return here. This $importMultiline function is run line by line and should only process a single multiline element at a time.\n return [true, endLineIndex]\n }\n\n // The replace function returned false, despite finding the matching open and close tags => this transformer does not want to handle it.\n // Thus, we continue letting the remaining transformers handle the passed lines of text from the beginning\n break\n }\n }\n\n // No multiline transformer handled this line successfully\n return [false, startLineIndex]\n}\n\nfunction $importBlocks(\n lineText: string,\n rootNode: ElementNode,\n elementTransformers: Array<ElementTransformer>,\n textFormatTransformersIndex: TextFormatTransformersIndex,\n textMatchTransformers: Array<TextMatchTransformer>,\n) {\n const textNode = $createTextNode(lineText)\n const elementNode = $createParagraphNode()\n elementNode.append(textNode)\n rootNode.append(elementNode)\n\n for (const { regExp, replace } of elementTransformers) {\n const match = lineText.match(regExp)\n\n if (match) {\n textNode.setTextContent(lineText.slice(match[0].length))\n if (replace(elementNode, [textNode], match, true) !== false) {\n break\n }\n }\n }\n\n importTextTransformers(textNode, textFormatTransformersIndex, textMatchTransformers)\n\n // If no transformer found and we left with original paragraph node\n // can check if its content can be appended to the previous node\n // if it's a paragraph, quote or list\n if (elementNode.isAttached() && lineText.length > 0) {\n const previousNode = elementNode.getPreviousSibling()\n if ($isParagraphNode(previousNode) || $isQuoteNode(previousNode) || $isListNode(previousNode)) {\n let targetNode: ListItemNode | null | typeof previousNode = previousNode\n\n if ($isListNode(previousNode)) {\n const lastDescendant = previousNode.getLastDescendant()\n if (lastDescendant == null) {\n targetNode = null\n } else {\n targetNode = $findMatchingParent(lastDescendant, $isListItemNode)\n }\n }\n\n if (targetNode != null && targetNode.getTextContentSize() > 0) {\n targetNode.splice(targetNode.getChildrenSize(), 0, [\n $createLineBreakNode(),\n ...elementNode.getChildren(),\n ])\n elementNode.remove()\n }\n }\n }\n}\n\nfunction createTextFormatTransformersIndex(\n textTransformers: Array<TextFormatTransformer>,\n): TextFormatTransformersIndex {\n const transformersByTag: Record<string, TextFormatTransformer> = {}\n const fullMatchRegExpByTag: Record<string, RegExp> = {}\n const openTagsRegExp: string[] = []\n const escapeRegExp = `(?<![\\\\\\\\])`\n\n for (const transformer of textTransformers) {\n const { tag } = transformer\n transformersByTag[tag] = transformer\n const tagRegExp = tag.replace(/([*^+])/g, '\\\\$1')\n openTagsRegExp.push(tagRegExp)\n\n // Single-char tag (e.g. \"*\"),\n if (tag.length === 1) {\n fullMatchRegExpByTag[tag] = new RegExp(\n `(?<![\\\\\\\\${tagRegExp}])(${tagRegExp})((\\\\\\\\${tagRegExp})?.*?[^${tagRegExp}\\\\s](\\\\\\\\${tagRegExp})?)((?<!\\\\\\\\)|(?<=\\\\\\\\\\\\\\\\))(${tagRegExp})(?![\\\\\\\\${tagRegExp}])`,\n )\n } else {\n // Multi‐char tags (e.g. \"**\")\n fullMatchRegExpByTag[tag] = new RegExp(\n `(?<!\\\\\\\\)(${tagRegExp})((\\\\\\\\${tagRegExp})?.*?[^\\\\s](\\\\\\\\${tagRegExp})?)((?<!\\\\\\\\)|(?<=\\\\\\\\\\\\\\\\))(${tagRegExp})(?!\\\\\\\\)`,\n )\n }\n }\n\n return {\n // Reg exp to find open tag + content + close tag\n fullMatchRegExpByTag,\n\n // Regexp to locate *any* potential opening tag (longest first).\n openTagsRegExp: new RegExp(`${escapeRegExp}(${openTagsRegExp.join('|')})`, 'g'),\n transformersByTag,\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MarkdownImport.js","names":["$isListItemNode","$isListNode","$isQuoteNode","$findMatchingParent","$createParagraphNode","$createTextNode","$getRoot","$getSelection","$isParagraphNode","importTextTransformers","$createMarkdownLineBreakNode","isEmptyParagraph","transformersByType","createMarkdownImport","transformers","shouldPreserveNewLines","byType","textFormatTransformersIndex","createTextFormatTransformersIndex","textFormat","markdownString","node","lines","split","linesLength","length","root","clear","i","lineText","imported","shiftedIndex","$importMultiline","multilineElement","$importBlocks","element","textMatch","children","getChildren","child","getChildrenSize","remove","selectStart","startLineIndex","multilineElementTransformers","rootNode","transformer","handleImportAfterStartMatch","regExpEnd","regExpStart","replace","startMatch","match","result","regexpEndRegex","regExp","isEndOptional","optional","endLineIndex","endMatch","index","linesInBetween","push","slice","line","text","elementTransformers","textMatchTransformers","textNode","elementNode","append","setTextContent","isAttached","previousNode","getPreviousSibling","targetNode","lastDescendant","getLastDescendant","getTextContentSize","splice","textTransformers","transformersByTag","fullMatchRegExpByTag","openTagsRegExp","escapeRegExp","tag","tagRegExp","RegExp","join"],"sources":["../../../../src/packages/@lexical/markdown/MarkdownImport.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { ListItemNode } from '@lexical/list'\nimport type { ElementNode } from 'lexical'\n\nimport { $isListItemNode, $isListNode } from '@lexical/list'\nimport { $isQuoteNode } from '@lexical/rich-text'\nimport { $findMatchingParent } from '@lexical/utils'\nimport {\n $createParagraphNode,\n $createTextNode,\n $getRoot,\n $getSelection,\n $isParagraphNode,\n} from 'lexical'\n\nimport type {\n ElementTransformer,\n MultilineElementTransformer,\n TextFormatTransformer,\n TextMatchTransformer,\n Transformer,\n} from './MarkdownTransformers.js'\n\nimport { importTextTransformers } from './importTextTransformers.js'\nimport { $createMarkdownLineBreakNode } from './MarkdownTransformers.js'\nimport { isEmptyParagraph, transformersByType } from './utils.js'\n\nexport type TextFormatTransformersIndex = Readonly<{\n fullMatchRegExpByTag: Readonly<Record<string, RegExp>>\n openTagsRegExp: RegExp\n transformersByTag: Readonly<Record<string, TextFormatTransformer>>\n}>\n\n/**\n * Renders markdown from a string. The selection is moved to the start after the operation.\n */\nexport function createMarkdownImport(\n transformers: Array<Transformer>,\n shouldPreserveNewLines = false,\n): (markdownString: string, node?: ElementNode) => void {\n const byType = transformersByType(transformers)\n const textFormatTransformersIndex = createTextFormatTransformersIndex(byType.textFormat)\n\n return (markdownString, node) => {\n const lines = markdownString.split('\\n')\n const linesLength = lines.length\n const root = node || $getRoot()\n root.clear()\n\n for (let i = 0; i < linesLength; i++) {\n const lineText = lines[i]!\n\n const [imported, shiftedIndex] = $importMultiline(lines, i, byType.multilineElement, root)\n\n if (imported) {\n // If a multiline markdown element was imported, we don't want to process the lines that were part of it anymore.\n // There could be other sub-markdown elements (both multiline and normal ones) matching within this matched multiline element's children.\n // However, it would be the responsibility of the matched multiline transformer to decide how it wants to handle them.\n // We cannot handle those, as there is no way for us to know how to maintain the correct order of generated lexical nodes for possible children.\n i = shiftedIndex // Next loop will start from the line after the last line of the multiline element\n continue\n }\n\n $importBlocks(lineText, root, byType.element, textFormatTransformersIndex, byType.textMatch)\n }\n\n // By default, removing empty paragraphs as md does not really\n // allow empty lines and uses them as delimiter.\n // If you need empty lines set shouldPreserveNewLines = true.\n const children = root.getChildren()\n for (const child of children) {\n if (!shouldPreserveNewLines && isEmptyParagraph(child) && root.getChildrenSize() > 1) {\n child.remove()\n }\n }\n\n if ($getSelection() !== null) {\n root.selectStart()\n }\n }\n}\n\n/**\n *\n * @returns first element of the returned tuple is a boolean indicating if a multiline element was imported. The second element is the index of the last line that was processed.\n */\nfunction $importMultiline(\n lines: Array<string>,\n startLineIndex: number,\n multilineElementTransformers: Array<MultilineElementTransformer>,\n rootNode: ElementNode,\n): [boolean, number] {\n for (const transformer of multilineElementTransformers) {\n const { handleImportAfterStartMatch, regExpEnd, regExpStart, replace } = transformer\n\n const startMatch = lines[startLineIndex]?.match(regExpStart)\n if (!startMatch) {\n continue // Try next transformer\n }\n\n if (handleImportAfterStartMatch) {\n const result = handleImportAfterStartMatch({\n lines,\n rootNode,\n startLineIndex,\n startMatch,\n transformer,\n })\n if (result === null) {\n continue\n } else if (result) {\n return result\n }\n }\n\n const regexpEndRegex: RegExp | undefined =\n typeof regExpEnd === 'object' && 'regExp' in regExpEnd ? regExpEnd.regExp : regExpEnd\n\n const isEndOptional =\n regExpEnd && typeof regExpEnd === 'object' && 'optional' in regExpEnd\n ? regExpEnd.optional\n : !regExpEnd\n\n let endLineIndex = startLineIndex\n const linesLength = lines.length\n\n // check every single line for the closing match. It could also be on the same line as the opening match.\n while (endLineIndex < linesLength) {\n const endMatch = regexpEndRegex ? lines[endLineIndex]?.match(regexpEndRegex) : null\n if (!endMatch) {\n if (\n !isEndOptional ||\n (isEndOptional && endLineIndex < linesLength - 1) // Optional end, but didn't reach the end of the document yet => continue searching for potential closing match\n ) {\n endLineIndex++\n continue // Search next line for closing match\n }\n }\n\n // Now, check if the closing match matched is the same as the opening match.\n // If it is, we need to continue searching for the actual closing match.\n if (endMatch && startLineIndex === endLineIndex && endMatch.index === startMatch.index) {\n endLineIndex++\n continue // Search next line for closing match\n }\n\n // At this point, we have found the closing match. Next: calculate the lines in between open and closing match\n // This should not include the matches themselves, and be split up by lines\n const linesInBetween: string[] = []\n\n if (endMatch && startLineIndex === endLineIndex) {\n linesInBetween.push(lines[startLineIndex]!.slice(startMatch[0].length, -endMatch[0].length))\n } else {\n for (let i = startLineIndex; i <= endLineIndex; i++) {\n const line = lines[i]!\n if (i === startLineIndex) {\n const text = line.slice(startMatch[0].length)\n linesInBetween.push(text) // Also include empty text\n } else if (i === endLineIndex && endMatch) {\n const text = line.slice(0, -endMatch[0].length)\n linesInBetween.push(text) // Also include empty text\n } else {\n linesInBetween.push(line)\n }\n }\n }\n\n if (replace(rootNode, null, startMatch, endMatch!, linesInBetween, true) !== false) {\n // Return here. This $importMultiline function is run line by line and should only process a single multiline element at a time.\n return [true, endLineIndex]\n }\n\n // The replace function returned false, despite finding the matching open and close tags => this transformer does not want to handle it.\n // Thus, we continue letting the remaining transformers handle the passed lines of text from the beginning\n break\n }\n }\n\n // No multiline transformer handled this line successfully\n return [false, startLineIndex]\n}\n\nfunction $importBlocks(\n lineText: string,\n rootNode: ElementNode,\n elementTransformers: Array<ElementTransformer>,\n textFormatTransformersIndex: TextFormatTransformersIndex,\n textMatchTransformers: Array<TextMatchTransformer>,\n) {\n const textNode = $createTextNode(lineText)\n const elementNode = $createParagraphNode()\n elementNode.append(textNode)\n rootNode.append(elementNode)\n\n for (const { regExp, replace } of elementTransformers) {\n const match = lineText.match(regExp)\n\n if (match) {\n textNode.setTextContent(lineText.slice(match[0].length))\n if (replace(elementNode, [textNode], match, true) !== false) {\n break\n }\n }\n }\n\n importTextTransformers(textNode, textFormatTransformersIndex, textMatchTransformers)\n\n // If no transformer found and we left with original paragraph node\n // can check if its content can be appended to the previous node\n // if it's a paragraph, quote or list\n if (elementNode.isAttached() && lineText.length > 0) {\n const previousNode = elementNode.getPreviousSibling()\n if ($isParagraphNode(previousNode) || $isQuoteNode(previousNode) || $isListNode(previousNode)) {\n let targetNode: ListItemNode | null | typeof previousNode = previousNode\n\n if ($isListNode(previousNode)) {\n const lastDescendant = previousNode.getLastDescendant()\n if (lastDescendant == null) {\n targetNode = null\n } else {\n targetNode = $findMatchingParent(lastDescendant, $isListItemNode)\n }\n }\n\n if (targetNode != null && targetNode.getTextContentSize() > 0) {\n targetNode.splice(targetNode.getChildrenSize(), 0, [\n $createMarkdownLineBreakNode(targetNode),\n ...elementNode.getChildren(),\n ])\n elementNode.remove()\n }\n }\n }\n}\n\nfunction createTextFormatTransformersIndex(\n textTransformers: Array<TextFormatTransformer>,\n): TextFormatTransformersIndex {\n const transformersByTag: Record<string, TextFormatTransformer> = {}\n const fullMatchRegExpByTag: Record<string, RegExp> = {}\n const openTagsRegExp: string[] = []\n const escapeRegExp = `(?<![\\\\\\\\])`\n\n for (const transformer of textTransformers) {\n const { tag } = transformer\n transformersByTag[tag] = transformer\n const tagRegExp = tag.replace(/([*^+])/g, '\\\\$1')\n openTagsRegExp.push(tagRegExp)\n\n // Single-char tag (e.g. \"*\"),\n if (tag.length === 1) {\n fullMatchRegExpByTag[tag] = new RegExp(\n `(?<![\\\\\\\\${tagRegExp}])(${tagRegExp})((\\\\\\\\${tagRegExp})?.*?[^${tagRegExp}\\\\s](\\\\\\\\${tagRegExp})?)((?<!\\\\\\\\)|(?<=\\\\\\\\\\\\\\\\))(${tagRegExp})(?![\\\\\\\\${tagRegExp}])`,\n )\n } else {\n // Multi‐char tags (e.g. \"**\")\n fullMatchRegExpByTag[tag] = new RegExp(\n `(?<!\\\\\\\\)(${tagRegExp})((\\\\\\\\${tagRegExp})?.*?[^\\\\s](\\\\\\\\${tagRegExp})?)((?<!\\\\\\\\)|(?<=\\\\\\\\\\\\\\\\))(${tagRegExp})(?!\\\\\\\\)`,\n )\n }\n }\n\n return {\n // Reg exp to find open tag + content + close tag\n fullMatchRegExpByTag,\n\n // Regexp to locate *any* potential opening tag (longest first).\n openTagsRegExp: new RegExp(`${escapeRegExp}(${openTagsRegExp.join('|')})`, 'g'),\n transformersByTag,\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  */
8
- import type { ElementNode, Klass, LexicalNode, TextFormatType, TextNode } from 'lexical';
8
+ import type { ElementNode, Klass, LexicalNode, LineBreakNode, TextFormatType, TextNode } from 'lexical';
9
9
  export type Transformer = ElementTransformer | MultilineElementTransformer | TextFormatTransformer | TextMatchTransformer;
10
10
  export type ElementTransformer = {
11
11
  dependencies: Array<Klass<LexicalNode>>;
@@ -129,6 +129,32 @@ export type TextMatchTransformer = Readonly<{
129
129
  trigger?: string;
130
130
  type: 'text-match';
131
131
  }>;
132
+ /**
133
+ * A CommonMark hard line break marker: either a single backslash (`\`) or two or
134
+ * more trailing spaces, both placed at the end of a line before the newline.
135
+ * See https://spec.commonmark.org/0.31.2/#hard-line-breaks
136
+ */
137
+ export type MarkdownHardLineBreak = string;
138
+ /**
139
+ * Stores the original hard line break marker on a `LineBreakNode` so it can be
140
+ * preserved across a markdown import/export round trip instead of being
141
+ * collapsed into a soft line break.
142
+ *
143
+ * Note: unlike upstream Lexical (which sets `resetOnCopyNode: true`), that option
144
+ * does not exist in the `lexical` version pinned here (0.41.0), so it is omitted.
145
+ */
146
+ export declare const hardLineBreakState: import("lexical").StateConfig<"mdHardLineBreak", string>;
147
+ /**
148
+ * Detects a CommonMark hard line break marker at the end of a raw line.
149
+ *
150
+ * @returns a tuple of `[textWithoutMarker, marker]` when a marker is found, otherwise null.
151
+ */
152
+ export declare function parseMarkdownHardLineBreak(line: string): [string, MarkdownHardLineBreak] | null;
153
+ /**
154
+ * Creates a `LineBreakNode` for a markdown line join, preserving any CommonMark
155
+ * hard line break marker found at the end of `previousNode` via node state.
156
+ */
157
+ export declare function $createMarkdownLineBreakNode(previousNode: ElementNode): LineBreakNode;
132
158
  export declare const HEADING: ElementTransformer;
133
159
  export declare const QUOTE: ElementTransformer;
134
160
  export declare const UNORDERED_LIST: ElementTransformer;
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownTransformers.d.ts","sourceRoot":"","sources":["../../../../src/packages/@lexical/markdown/MarkdownTransformers.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAoBxF,MAAM,MAAM,WAAW,GACnB,kBAAkB,GAClB,2BAA2B,GAC3B,qBAAqB,GACrB,oBAAoB,CAAA;AAExB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;IACvC;;;;OAIG;IACH,MAAM,EAAE,CACN,IAAI,EAAE,WAAW,EAEjB,gBAAgB,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,MAAM,KAC5C,IAAI,GAAG,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,OAAO,EAAE,CACP,UAAU,EAAE,WAAW,EACvB,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,EAC5B,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;IACpB;;OAEG;IACH,QAAQ,EAAE,OAAO,KACd,OAAO,GAAG,IAAI,CAAA;IACnB,IAAI,EAAE,SAAS,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;IACvC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CACP,IAAI,EAAE,WAAW,EAEjB,gBAAgB,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,MAAM,KAC5C,IAAI,GAAG,MAAM,CAAA;IAClB;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,CAAC,IAAI,EAAE;QACnC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;QACpB,QAAQ,EAAE,WAAW,CAAA;QACrB,cAAc,EAAE,MAAM,CAAA;QACtB,UAAU,EAAE,gBAAgB,CAAA;QAC5B,WAAW,EAAE,2BAA2B,CAAA;KACzC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,CAAA;IAC1C;;OAEG;IACH,SAAS,CAAC,EACN;QACE;;;WAGG;QACH,QAAQ,CAAC,EAAE,IAAI,CAAA;QACf,MAAM,EAAE,MAAM,CAAA;KACf,GACD,MAAM,CAAA;IACV;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,OAAO,EAAE,CACP,QAAQ,EAAE,WAAW;IACrB;;;OAGG;IACH,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,EACnC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,EACzB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI;IAC9B;;;OAGG;IACH,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI;IACpC;;OAEG;IACH,QAAQ,EAAE,OAAO,KACd,OAAO,GAAG,IAAI,CAAA;IACnB,IAAI,EAAE,mBAAmB,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACrC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,aAAa,CAAA;CACpB,CAAC,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;IACvC;;OAEG;IACH,MAAM,CAAC,EAAE,CACP,IAAI,EAAE,WAAW,EAEjB,cAAc,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,MAAM,EAE7C,YAAY,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,KAAK,MAAM,KAC1D,IAAI,GAAG,MAAM,CAAA;IAClB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,gBAAgB,KAAK,KAAK,GAAG,MAAM,CAAA;IACzE;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,gBAAgB,KAAK,QAAQ,GAAG,IAAI,CAAA;IACtE;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,YAAY,CAAA;CACnB,CAAC,CAAA;AAgHF,eAAO,MAAM,OAAO,EAAE,kBAerB,CAAA;AAED,eAAO,MAAM,KAAK,EAAE,kBAmCnB,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,kBAQ5B,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,kBAQxB,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,kBAQ1B,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,qBAIzB,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,qBAIvB,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,qBAI9B,CAAA;AAED,eAAO,MAAM,sBAAsB,EAAE,qBAKpC,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,qBAIvB,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,qBAK7B,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,qBAI3B,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,qBAIzB,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,qBAK/B,CAAA;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,OAAO,GAAG,MAAM,CAwE1F"}
1
+ {"version":3,"file":"MarkdownTransformers.d.ts","sourceRoot":"","sources":["../../../../src/packages/@lexical/markdown/MarkdownTransformers.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@
6
6
  *
7
7
  */import { $createListItemNode, $createListNode, $isListItemNode, $isListNode, ListItemNode, ListNode } from '@lexical/list';
8
8
  import { $createHeadingNode, $createQuoteNode, $isHeadingNode, $isQuoteNode, HeadingNode, QuoteNode } from '@lexical/rich-text';
9
- import { $createLineBreakNode } from 'lexical';
9
+ import { $createLineBreakNode, $isLineBreakNode, $isTextNode, $setState, createState } from 'lexical';
10
10
  const EMPTY_OR_WHITESPACE_ONLY = /^[\t ]*$/;
11
11
  const ORDERED_LIST_REGEX = /^(\s*)(\d+)\.\s/;
12
12
  const UNORDERED_LIST_REGEX = /^(\s*)[-*+]\s/;
@@ -20,6 +20,84 @@ const TABLE_ROW_REG_EXP = /^\|(.+)\|\s?$/;
20
20
  const TABLE_ROW_DIVIDER_REG_EXP = /^(\| ?:?-*:? ?)+\|\s?$/;
21
21
  const TAG_START_REGEX = /^[ \t]*<[a-z_][\w-]*(?:\s[^<>]*)?\/?>/i;
22
22
  const TAG_END_REGEX = /^[ \t]*<\/[a-z_][\w-]*\s*>/i;
23
+ /**
24
+ * Stores the original hard line break marker on a `LineBreakNode` so it can be
25
+ * preserved across a markdown import/export round trip instead of being
26
+ * collapsed into a soft line break.
27
+ *
28
+ * Note: unlike upstream Lexical (which sets `resetOnCopyNode: true`), that option
29
+ * does not exist in the `lexical` version pinned here (0.41.0), so it is omitted.
30
+ */
31
+ export const hardLineBreakState = createState('mdHardLineBreak', {
32
+ parse: val => {
33
+ if (typeof val === 'string' && /^(\\| {2,})$/.test(val)) {
34
+ return val;
35
+ }
36
+ return '';
37
+ }
38
+ });
39
+ /**
40
+ * Detects a CommonMark hard line break marker at the end of a raw line.
41
+ *
42
+ * @returns a tuple of `[textWithoutMarker, marker]` when a marker is found, otherwise null.
43
+ */
44
+ export function parseMarkdownHardLineBreak(line) {
45
+ if (line.endsWith('\\')) {
46
+ return [line.slice(0, -1), '\\'];
47
+ }
48
+ const spaces = line.match(/^(.*?\S)( {2,})$/);
49
+ return spaces ? [spaces[1], spaces[2]] : null;
50
+ }
51
+ function hasNonWhitespaceContentOnLine(children, endIndex) {
52
+ for (let i = endIndex - 1; i >= 0; i--) {
53
+ if ($isLineBreakNode(children[i])) {
54
+ return false;
55
+ }
56
+ if (/\S/.test(children[i].getTextContent())) {
57
+ return true;
58
+ }
59
+ }
60
+ return false;
61
+ }
62
+ /**
63
+ * Removes a trailing hard line break marker from the last text node of `previousNode`
64
+ * (if present) and returns the marker, so it can be carried onto a `LineBreakNode`.
65
+ */
66
+ function $extractMarkdownHardLineBreakMarker(previousNode) {
67
+ const children = previousNode.getChildren();
68
+ const lastChildIndex = children.length - 1;
69
+ const lastChild = children[lastChildIndex];
70
+ if (!$isTextNode(lastChild)) {
71
+ return null;
72
+ }
73
+ const lastText = lastChild.getTextContent();
74
+ const hardLineBreak = parseMarkdownHardLineBreak(lastText);
75
+ if (hardLineBreak !== null) {
76
+ const [text, marker] = hardLineBreak;
77
+ lastChild.setTextContent(text);
78
+ return marker;
79
+ }
80
+ // Trailing whitespace may have been split into its own text node by inline
81
+ // transformers (e.g. after formatted or linked content). Only treat it as a
82
+ // hard break when there is preceding non-whitespace content on the same line.
83
+ if (/^ {2,}$/.test(lastText) && hasNonWhitespaceContentOnLine(children, lastChildIndex)) {
84
+ lastChild.setTextContent('');
85
+ return lastText;
86
+ }
87
+ return null;
88
+ }
89
+ /**
90
+ * Creates a `LineBreakNode` for a markdown line join, preserving any CommonMark
91
+ * hard line break marker found at the end of `previousNode` via node state.
92
+ */
93
+ export function $createMarkdownLineBreakNode(previousNode) {
94
+ const lineBreakNode = $createLineBreakNode();
95
+ const hardLineBreak = $extractMarkdownHardLineBreakMarker(previousNode);
96
+ if (hardLineBreak !== null) {
97
+ $setState(lineBreakNode, hardLineBreakState, hardLineBreak);
98
+ }
99
+ return lineBreakNode;
100
+ }
23
101
  const createBlockNode = createNode => {
24
102
  return (parentNode, children, match) => {
25
103
  const node = createNode(match);
@@ -130,7 +208,7 @@ export const QUOTE = {
130
208
  if (isImport) {
131
209
  const previousNode = parentNode.getPreviousSibling();
132
210
  if ($isQuoteNode(previousNode)) {
133
- previousNode.splice(previousNode.getChildrenSize(), 0, [$createLineBreakNode(), ...children]);
211
+ previousNode.splice(previousNode.getChildrenSize(), 0, [$createMarkdownLineBreakNode(previousNode), ...children]);
134
212
  previousNode.select(0, 0);
135
213
  parentNode.remove();
136
214
  return;
@@ -225,6 +303,9 @@ export function normalizeMarkdown(input, shouldMergeAdjacentLines) {
225
303
  for (let i = 0; i < lines.length; i++) {
226
304
  const line = lines[i];
227
305
  const lastLine = sanitizedLines[sanitizedLines.length - 1];
306
+ // A hard line break marker on the current line only matters if another line follows it.
307
+ const hardLineBreak = i < lines.length - 1 ? parseMarkdownHardLineBreak(line) : null;
308
+ const lastLineHasHardLineBreak = lastLine !== undefined && parseMarkdownHardLineBreak(lastLine) !== null;
228
309
  // Code blocks of ```single line``` don't toggle the inCodeBlock flag
229
310
  if (CODE_SINGLE_LINE_REGEX.test(line)) {
230
311
  sanitizedLines.push(line);
@@ -257,10 +338,13 @@ export function normalizeMarkdown(input, shouldMergeAdjacentLines) {
257
338
  }
258
339
  // In markdown the concept of "empty paragraphs" does not exist.
259
340
  // Blocks must be separated by an empty line. Non-empty adjacent lines must be merged.
260
- if (EMPTY_OR_WHITESPACE_ONLY.test(line) || EMPTY_OR_WHITESPACE_ONLY.test(lastLine) || !lastLine || HEADING_REGEX.test(lastLine) || HEADING_REGEX.test(line) || QUOTE_REGEX.test(line) || ORDERED_LIST_REGEX.test(line) || UNORDERED_LIST_REGEX.test(line) || CHECK_LIST_REGEX.test(line) || TABLE_ROW_REG_EXP.test(line) || TABLE_ROW_DIVIDER_REG_EXP.test(line) || !shouldMergeAdjacentLines || TAG_START_REGEX.test(line) || TAG_END_REGEX.test(line) || TAG_START_REGEX.test(lastLine) || TAG_END_REGEX.test(lastLine) || CODE_END_REGEX.test(lastLine)) {
341
+ if (EMPTY_OR_WHITESPACE_ONLY.test(line) || EMPTY_OR_WHITESPACE_ONLY.test(lastLine) || !lastLine || HEADING_REGEX.test(lastLine) || HEADING_REGEX.test(line) || QUOTE_REGEX.test(line) || ORDERED_LIST_REGEX.test(line) || UNORDERED_LIST_REGEX.test(line) || CHECK_LIST_REGEX.test(line) || TABLE_ROW_REG_EXP.test(line) || TABLE_ROW_DIVIDER_REG_EXP.test(line) ||
342
+ // Don't merge the next line into a line that ends with a hard line break marker.
343
+ lastLineHasHardLineBreak || !shouldMergeAdjacentLines || TAG_START_REGEX.test(line) || TAG_END_REGEX.test(line) || TAG_START_REGEX.test(lastLine) || TAG_END_REGEX.test(lastLine) || CODE_END_REGEX.test(lastLine)) {
261
344
  sanitizedLines.push(line);
262
345
  } else {
263
- sanitizedLines[sanitizedLines.length - 1] = lastLine + ' ' + line.trim();
346
+ // Preserve a trailing hard line break marker on the merged line so it survives import.
347
+ sanitizedLines[sanitizedLines.length - 1] = lastLine + ' ' + (hardLineBreak === null ? line.trim() : line.trimStart());
264
348
  }
265
349
  }
266
350
  return sanitizedLines.join('\n');
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownTransformers.js","names":["$createListItemNode","$createListNode","$isListItemNode","$isListNode","ListItemNode","ListNode","$createHeadingNode","$createQuoteNode","$isHeadingNode","$isQuoteNode","HeadingNode","QuoteNode","$createLineBreakNode","EMPTY_OR_WHITESPACE_ONLY","ORDERED_LIST_REGEX","UNORDERED_LIST_REGEX","CHECK_LIST_REGEX","HEADING_REGEX","QUOTE_REGEX","CODE_START_REGEX","CODE_END_REGEX","CODE_SINGLE_LINE_REGEX","TABLE_ROW_REG_EXP","TABLE_ROW_DIVIDER_REG_EXP","TAG_START_REGEX","TAG_END_REGEX","createBlockNode","createNode","parentNode","children","match","node","append","replace","select","LIST_INDENT_SIZE","getIndent","whitespaces","tabs","spaces","indent","length","Math","floor","listReplace","listType","previousNode","getPreviousSibling","nextNode","getNextSibling","listItem","undefined","getListType","firstChild","getFirstChild","insertBefore","remove","list","Number","setIndent","listExport","listNode","exportChildren","depth","output","getChildren","index","listItemNode","getChildrenSize","push","repeat","prefix","getStart","getChecked","join","HEADING","type","dependencies","export","level","getTag","slice","regExp","tag","QUOTE","lines","split","line","_match","isImport","splice","UNORDERED_LIST","CHECK_LIST","ORDERED_LIST","INLINE_CODE","format","HIGHLIGHT","BOLD_ITALIC_STAR","BOLD_ITALIC_UNDERSCORE","intraword","BOLD_STAR","BOLD_UNDERSCORE","STRIKETHROUGH","ITALIC_STAR","ITALIC_UNDERSCORE","normalizeMarkdown","input","shouldMergeAdjacentLines","inCodeBlock","sanitizedLines","nestedDeepCodeBlock","i","lastLine","test","trim"],"sources":["../../../../src/packages/@lexical/markdown/MarkdownTransformers.ts"],"sourcesContent":["/* eslint-disable regexp/no-unused-capturing-group */\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { ListType } from '@lexical/list'\nimport type { HeadingTagType } from '@lexical/rich-text'\nimport type { ElementNode, Klass, LexicalNode, TextFormatType, TextNode } from 'lexical'\n\nimport {\n $createListItemNode,\n $createListNode,\n $isListItemNode,\n $isListNode,\n ListItemNode,\n ListNode,\n} from '@lexical/list'\nimport {\n $createHeadingNode,\n $createQuoteNode,\n $isHeadingNode,\n $isQuoteNode,\n HeadingNode,\n QuoteNode,\n} from '@lexical/rich-text'\nimport { $createLineBreakNode } from 'lexical'\n\nexport type Transformer =\n | ElementTransformer\n | MultilineElementTransformer\n | TextFormatTransformer\n | TextMatchTransformer\n\nexport type ElementTransformer = {\n dependencies: Array<Klass<LexicalNode>>\n /**\n * `export` is called when the `$convertToMarkdownString` is called to convert the editor state into markdown.\n *\n * @return return null to cancel the export, even though the regex matched. Lexical will then search for the next transformer.\n */\n export: (\n node: LexicalNode,\n\n traverseChildren: (node: ElementNode) => string,\n ) => null | string\n regExp: RegExp\n /**\n * `replace` is called when markdown is imported or typed in the editor\n *\n * @return return false to cancel the transform, even though the regex matched. Lexical will then search for the next transformer.\n */\n replace: (\n parentNode: ElementNode,\n children: Array<LexicalNode>,\n match: Array<string>,\n /**\n * Whether the match is from an import operation (e.g. through `$convertFromMarkdownString`) or not (e.g. through typing in the editor).\n */\n isImport: boolean,\n ) => boolean | void\n type: 'element'\n}\n\nexport type MultilineElementTransformer = {\n dependencies: Array<Klass<LexicalNode>>\n /**\n * `export` is called when the `$convertToMarkdownString` is called to convert the editor state into markdown.\n *\n * @return return null to cancel the export, even though the regex matched. Lexical will then search for the next transformer.\n */\n export?: (\n node: LexicalNode,\n\n traverseChildren: (node: ElementNode) => string,\n ) => null | string\n /**\n * Use this function to manually handle the import process, once the `regExpStart` has matched successfully.\n * Without providing this function, the default behavior is to match until `regExpEnd` is found, or until the end of the document if `regExpEnd.optional` is true.\n *\n * @returns a tuple or null. The first element of the returned tuple is a boolean indicating if a multiline element was imported. The second element is the index of the last line that was processed. If null is returned, the next multilineElementTransformer will be tried. If undefined is returned, the default behavior will be used.\n */\n handleImportAfterStartMatch?: (args: {\n lines: Array<string>\n rootNode: ElementNode\n startLineIndex: number\n startMatch: RegExpMatchArray\n transformer: MultilineElementTransformer\n }) => [boolean, number] | null | undefined\n /**\n * This regex determines when to stop matching. Anything in between regExpStart and regExpEnd will be matched\n */\n regExpEnd?:\n | {\n /**\n * Whether the end match is optional. If true, the end match is not required to match for the transformer to be triggered.\n * The entire text from regexpStart to the end of the document will then be matched.\n */\n optional?: true\n regExp: RegExp\n }\n | RegExp\n /**\n * This regex determines when to start matching\n */\n regExpStart: RegExp\n /**\n * `replace` is called only when markdown is imported in the editor, not when it's typed\n *\n * @return return false to cancel the transform, even though the regex matched. Lexical will then search for the next transformer.\n */\n replace: (\n rootNode: ElementNode,\n /**\n * During markdown shortcut transforms, children nodes may be provided to the transformer. If this is the case, no `linesInBetween` will be provided and\n * the children nodes should be used instead of the `linesInBetween` to create the new node.\n */\n children: Array<LexicalNode> | null,\n startMatch: Array<string>,\n endMatch: Array<string> | null,\n /**\n * linesInBetween includes the text between the start & end matches, split up by lines, not including the matches themselves.\n * This is null when the transformer is triggered through markdown shortcuts (by typing in the editor)\n */\n linesInBetween: Array<string> | null,\n /**\n * Whether the match is from an import operation (e.g. through `$convertFromMarkdownString`) or not (e.g. through typing in the editor).\n */\n isImport: boolean,\n ) => boolean | void\n type: 'multiline-element'\n}\n\nexport type TextFormatTransformer = Readonly<{\n format: ReadonlyArray<TextFormatType>\n intraword?: boolean\n tag: string\n type: 'text-format'\n}>\n\nexport type TextMatchTransformer = Readonly<{\n dependencies: Array<Klass<LexicalNode>>\n /**\n * Determines how a node should be exported to markdown\n */\n export?: (\n node: LexicalNode,\n\n exportChildren: (node: ElementNode) => string,\n\n exportFormat: (node: TextNode, textContent: string) => string,\n ) => null | string\n /**\n * For import operations, this function can be used to determine the end index of the match, after `importRegExp` has matched.\n * Without this function, the end index will be determined by the length of the match from `importRegExp`. Manually determining the end index can be useful if\n * the match from `importRegExp` is not the entire text content of the node. That way, `importRegExp` can be used to match only the start of the node, and `getEndIndex`\n * can be used to match the end of the node.\n *\n * @returns The end index of the match, or false if the match was unsuccessful and a different transformer should be tried.\n */\n getEndIndex?: (node: TextNode, match: RegExpMatchArray) => false | number\n /**\n * This regex determines what text is matched during markdown imports\n */\n importRegExp?: RegExp\n /**\n * This regex determines what text is matched for markdown shortcuts while typing in the editor\n */\n regExp: RegExp\n /**\n * Determines how the matched markdown text should be transformed into a node during the markdown import process\n *\n * @returns nothing, or a TextNode that may be a child of the new node that is created.\n * If a TextNode is returned, text format matching will be applied to it (e.g. bold, italic, etc.)\n */\n replace?: (node: TextNode, match: RegExpMatchArray) => TextNode | void\n /**\n * Single character that allows the transformer to trigger when typed in the editor. This does not affect markdown imports outside of the markdown shortcut plugin.\n * If the trigger is matched, the `regExp` will be used to match the text in the second step.\n */\n trigger?: string\n type: 'text-match'\n}>\n\nconst EMPTY_OR_WHITESPACE_ONLY = /^[\\t ]*$/\nconst ORDERED_LIST_REGEX = /^(\\s*)(\\d+)\\.\\s/\nconst UNORDERED_LIST_REGEX = /^(\\s*)[-*+]\\s/\nconst CHECK_LIST_REGEX = /^(\\s*)(?:-\\s)?\\s?(\\[(\\s|x)?\\])\\s/i\nconst HEADING_REGEX = /^(#{1,6})\\s/\nconst QUOTE_REGEX = /^>\\s/\nconst CODE_START_REGEX = /^[ \\t]*(\\\\`\\\\`\\\\`|```)(\\w+)?/\nconst CODE_END_REGEX = /[ \\t]*(\\\\`\\\\`\\\\`|```)$/\nconst CODE_SINGLE_LINE_REGEX = /^[ \\t]*```[^`]+(?:(?:`{1,2}|`{4,})[^`]+)*```(?:[^`]|$)/\nconst TABLE_ROW_REG_EXP = /^\\|(.+)\\|\\s?$/\nconst TABLE_ROW_DIVIDER_REG_EXP = /^(\\| ?:?-*:? ?)+\\|\\s?$/\nconst TAG_START_REGEX = /^[ \\t]*<[a-z_][\\w-]*(?:\\s[^<>]*)?\\/?>/i\nconst TAG_END_REGEX = /^[ \\t]*<\\/[a-z_][\\w-]*\\s*>/i\n\nconst createBlockNode = (\n createNode: (match: Array<string>) => ElementNode,\n): ElementTransformer['replace'] => {\n return (parentNode, children, match) => {\n const node = createNode(match)\n node.append(...children)\n parentNode.replace(node)\n node.select(0, 0)\n }\n}\n\n// Amount of spaces that define indentation level\n// TODO: should be an option\nconst LIST_INDENT_SIZE = 4\n\nfunction getIndent(whitespaces: string): number {\n const tabs = whitespaces.match(/\\t/g)\n const spaces = whitespaces.match(/ /g)\n\n let indent = 0\n\n if (tabs) {\n indent += tabs.length\n }\n\n if (spaces) {\n indent += Math.floor(spaces.length / LIST_INDENT_SIZE)\n }\n\n return indent\n}\n\nconst listReplace = (listType: ListType): ElementTransformer['replace'] => {\n return (parentNode, children, match) => {\n const previousNode = parentNode.getPreviousSibling()\n const nextNode = parentNode.getNextSibling()\n const listItem = $createListItemNode(listType === 'check' ? match[3] === 'x' : undefined)\n if ($isListNode(nextNode) && nextNode.getListType() === listType) {\n const firstChild = nextNode.getFirstChild()\n if (firstChild !== null) {\n firstChild.insertBefore(listItem)\n } else {\n // should never happen, but let's handle gracefully, just in case.\n nextNode.append(listItem)\n }\n parentNode.remove()\n } else if ($isListNode(previousNode) && previousNode.getListType() === listType) {\n previousNode.append(listItem)\n parentNode.remove()\n } else {\n const list = $createListNode(listType, listType === 'number' ? Number(match[2]) : undefined)\n list.append(listItem)\n parentNode.replace(list)\n }\n listItem.append(...children)\n listItem.select(0, 0)\n const indent = getIndent(match[1]!)\n if (indent) {\n listItem.setIndent(indent)\n }\n }\n}\n\nconst listExport = (\n listNode: ListNode,\n exportChildren: (node: ElementNode) => string,\n depth: number,\n): string => {\n const output: string[] = []\n const children = listNode.getChildren()\n let index = 0\n for (const listItemNode of children) {\n if ($isListItemNode(listItemNode)) {\n if (listItemNode.getChildrenSize() === 1) {\n const firstChild = listItemNode.getFirstChild()\n if ($isListNode(firstChild)) {\n output.push(listExport(firstChild, exportChildren, depth + 1))\n continue\n }\n }\n const indent = ' '.repeat(depth * LIST_INDENT_SIZE)\n const listType = listNode.getListType()\n const prefix =\n listType === 'number'\n ? `${listNode.getStart() + index}. `\n : listType === 'check'\n ? `- [${listItemNode.getChecked() ? 'x' : ' '}] `\n : '- '\n output.push(indent + prefix + exportChildren(listItemNode))\n index++\n }\n }\n\n return output.join('\\n')\n}\n\nexport const HEADING: ElementTransformer = {\n type: 'element',\n dependencies: [HeadingNode],\n export: (node, exportChildren) => {\n if (!$isHeadingNode(node)) {\n return null\n }\n const level = Number(node.getTag().slice(1))\n return '#'.repeat(level) + ' ' + exportChildren(node)\n },\n regExp: HEADING_REGEX,\n replace: createBlockNode((match) => {\n const tag = ('h' + match[1]!.length) as HeadingTagType\n return $createHeadingNode(tag)\n }),\n}\n\nexport const QUOTE: ElementTransformer = {\n type: 'element',\n dependencies: [QuoteNode],\n export: (node, exportChildren) => {\n if (!$isQuoteNode(node)) {\n return null\n }\n\n const lines = exportChildren(node).split('\\n')\n const output: string[] = []\n for (const line of lines) {\n output.push('> ' + line)\n }\n return output.join('\\n')\n },\n regExp: QUOTE_REGEX,\n replace: (parentNode, children, _match, isImport) => {\n if (isImport) {\n const previousNode = parentNode.getPreviousSibling()\n if ($isQuoteNode(previousNode)) {\n previousNode.splice(previousNode.getChildrenSize(), 0, [\n $createLineBreakNode(),\n ...children,\n ])\n previousNode.select(0, 0)\n parentNode.remove()\n return\n }\n }\n\n const node = $createQuoteNode()\n node.append(...children)\n parentNode.replace(node)\n node.select(0, 0)\n },\n}\n\nexport const UNORDERED_LIST: ElementTransformer = {\n type: 'element',\n dependencies: [ListNode, ListItemNode],\n export: (node, exportChildren) => {\n return $isListNode(node) ? listExport(node, exportChildren, 0) : null\n },\n regExp: UNORDERED_LIST_REGEX,\n replace: listReplace('bullet'),\n}\n\nexport const CHECK_LIST: ElementTransformer = {\n type: 'element',\n dependencies: [ListNode, ListItemNode],\n export: (node, exportChildren) => {\n return $isListNode(node) ? listExport(node, exportChildren, 0) : null\n },\n regExp: CHECK_LIST_REGEX,\n replace: listReplace('check'),\n}\n\nexport const ORDERED_LIST: ElementTransformer = {\n type: 'element',\n dependencies: [ListNode, ListItemNode],\n export: (node, exportChildren) => {\n return $isListNode(node) ? listExport(node, exportChildren, 0) : null\n },\n regExp: ORDERED_LIST_REGEX,\n replace: listReplace('number'),\n}\n\nexport const INLINE_CODE: TextFormatTransformer = {\n type: 'text-format',\n format: ['code'],\n tag: '`',\n}\n\nexport const HIGHLIGHT: TextFormatTransformer = {\n type: 'text-format',\n format: ['highlight'],\n tag: '==',\n}\n\nexport const BOLD_ITALIC_STAR: TextFormatTransformer = {\n type: 'text-format',\n format: ['bold', 'italic'],\n tag: '***',\n}\n\nexport const BOLD_ITALIC_UNDERSCORE: TextFormatTransformer = {\n type: 'text-format',\n format: ['bold', 'italic'],\n intraword: false,\n tag: '___',\n}\n\nexport const BOLD_STAR: TextFormatTransformer = {\n type: 'text-format',\n format: ['bold'],\n tag: '**',\n}\n\nexport const BOLD_UNDERSCORE: TextFormatTransformer = {\n type: 'text-format',\n format: ['bold'],\n intraword: false,\n tag: '__',\n}\n\nexport const STRIKETHROUGH: TextFormatTransformer = {\n type: 'text-format',\n format: ['strikethrough'],\n tag: '~~',\n}\n\nexport const ITALIC_STAR: TextFormatTransformer = {\n type: 'text-format',\n format: ['italic'],\n tag: '*',\n}\n\nexport const ITALIC_UNDERSCORE: TextFormatTransformer = {\n type: 'text-format',\n format: ['italic'],\n intraword: false,\n tag: '_',\n}\n\nexport function normalizeMarkdown(input: string, shouldMergeAdjacentLines: boolean): string {\n const lines = input.split('\\n')\n let inCodeBlock = false\n const sanitizedLines: string[] = []\n let nestedDeepCodeBlock = 0\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!\n const lastLine = sanitizedLines[sanitizedLines.length - 1]\n\n // Code blocks of ```single line``` don't toggle the inCodeBlock flag\n if (CODE_SINGLE_LINE_REGEX.test(line)) {\n sanitizedLines.push(line)\n continue\n }\n\n if (CODE_END_REGEX.test(line)) {\n if (nestedDeepCodeBlock === 0) {\n inCodeBlock = true\n }\n if (nestedDeepCodeBlock === 1) {\n inCodeBlock = false\n }\n if (nestedDeepCodeBlock > 0) {\n nestedDeepCodeBlock--\n }\n sanitizedLines.push(line)\n continue\n }\n\n // Toggle inCodeBlock state when encountering start or end of a code block\n if (CODE_START_REGEX.test(line)) {\n inCodeBlock = true\n nestedDeepCodeBlock++\n sanitizedLines.push(line)\n continue\n }\n\n // If we are inside a code block, keep the line unchanged\n if (inCodeBlock) {\n sanitizedLines.push(line)\n continue\n }\n\n // In markdown the concept of \"empty paragraphs\" does not exist.\n // Blocks must be separated by an empty line. Non-empty adjacent lines must be merged.\n if (\n EMPTY_OR_WHITESPACE_ONLY.test(line) ||\n EMPTY_OR_WHITESPACE_ONLY.test(lastLine!) ||\n !lastLine ||\n HEADING_REGEX.test(lastLine) ||\n HEADING_REGEX.test(line) ||\n QUOTE_REGEX.test(line) ||\n ORDERED_LIST_REGEX.test(line) ||\n UNORDERED_LIST_REGEX.test(line) ||\n CHECK_LIST_REGEX.test(line) ||\n TABLE_ROW_REG_EXP.test(line) ||\n TABLE_ROW_DIVIDER_REG_EXP.test(line) ||\n !shouldMergeAdjacentLines ||\n TAG_START_REGEX.test(line) ||\n TAG_END_REGEX.test(line) ||\n TAG_START_REGEX.test(lastLine) ||\n TAG_END_REGEX.test(lastLine) ||\n CODE_END_REGEX.test(lastLine)\n ) {\n sanitizedLines.push(line)\n } else {\n sanitizedLines[sanitizedLines.length - 1] = lastLine + ' ' + line.trim()\n }\n }\n\n return sanitizedLines.join('\\n')\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MarkdownTransformers.js","names":["$createListItemNode","$createListNode","$isListItemNode","$isListNode","ListItemNode","ListNode","$createHeadingNode","$createQuoteNode","$isHeadingNode","$isQuoteNode","HeadingNode","QuoteNode","$createLineBreakNode","$isLineBreakNode","$isTextNode","$setState","createState","EMPTY_OR_WHITESPACE_ONLY","ORDERED_LIST_REGEX","UNORDERED_LIST_REGEX","CHECK_LIST_REGEX","HEADING_REGEX","QUOTE_REGEX","CODE_START_REGEX","CODE_END_REGEX","CODE_SINGLE_LINE_REGEX","TABLE_ROW_REG_EXP","TABLE_ROW_DIVIDER_REG_EXP","TAG_START_REGEX","TAG_END_REGEX","hardLineBreakState","parse","val","test","parseMarkdownHardLineBreak","line","endsWith","slice","spaces","match","hasNonWhitespaceContentOnLine","children","endIndex","i","getTextContent","$extractMarkdownHardLineBreakMarker","previousNode","getChildren","lastChildIndex","length","lastChild","lastText","hardLineBreak","text","marker","setTextContent","$createMarkdownLineBreakNode","lineBreakNode","createBlockNode","createNode","parentNode","node","append","replace","select","LIST_INDENT_SIZE","getIndent","whitespaces","tabs","indent","Math","floor","listReplace","listType","getPreviousSibling","nextNode","getNextSibling","listItem","undefined","getListType","firstChild","getFirstChild","insertBefore","remove","list","Number","setIndent","listExport","listNode","exportChildren","depth","output","index","listItemNode","getChildrenSize","push","repeat","prefix","getStart","getChecked","join","HEADING","type","dependencies","export","level","getTag","regExp","tag","QUOTE","lines","split","_match","isImport","splice","UNORDERED_LIST","CHECK_LIST","ORDERED_LIST","INLINE_CODE","format","HIGHLIGHT","BOLD_ITALIC_STAR","BOLD_ITALIC_UNDERSCORE","intraword","BOLD_STAR","BOLD_UNDERSCORE","STRIKETHROUGH","ITALIC_STAR","ITALIC_UNDERSCORE","normalizeMarkdown","input","shouldMergeAdjacentLines","inCodeBlock","sanitizedLines","nestedDeepCodeBlock","lastLine","lastLineHasHardLineBreak","trim","trimStart"],"sources":["../../../../src/packages/@lexical/markdown/MarkdownTransformers.ts"],"sourcesContent":["/* eslint-disable regexp/no-unused-capturing-group */\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { ListType } from '@lexical/list'\nimport type { HeadingTagType } from '@lexical/rich-text'\nimport type {\n ElementNode,\n Klass,\n LexicalNode,\n LineBreakNode,\n TextFormatType,\n TextNode,\n} from 'lexical'\n\nimport {\n $createListItemNode,\n $createListNode,\n $isListItemNode,\n $isListNode,\n ListItemNode,\n ListNode,\n} from '@lexical/list'\nimport {\n $createHeadingNode,\n $createQuoteNode,\n $isHeadingNode,\n $isQuoteNode,\n HeadingNode,\n QuoteNode,\n} from '@lexical/rich-text'\nimport {\n $createLineBreakNode,\n $isLineBreakNode,\n $isTextNode,\n $setState,\n createState,\n} from 'lexical'\n\nexport type Transformer =\n | ElementTransformer\n | MultilineElementTransformer\n | TextFormatTransformer\n | TextMatchTransformer\n\nexport type ElementTransformer = {\n dependencies: Array<Klass<LexicalNode>>\n /**\n * `export` is called when the `$convertToMarkdownString` is called to convert the editor state into markdown.\n *\n * @return return null to cancel the export, even though the regex matched. Lexical will then search for the next transformer.\n */\n export: (\n node: LexicalNode,\n\n traverseChildren: (node: ElementNode) => string,\n ) => null | string\n regExp: RegExp\n /**\n * `replace` is called when markdown is imported or typed in the editor\n *\n * @return return false to cancel the transform, even though the regex matched. Lexical will then search for the next transformer.\n */\n replace: (\n parentNode: ElementNode,\n children: Array<LexicalNode>,\n match: Array<string>,\n /**\n * Whether the match is from an import operation (e.g. through `$convertFromMarkdownString`) or not (e.g. through typing in the editor).\n */\n isImport: boolean,\n ) => boolean | void\n type: 'element'\n}\n\nexport type MultilineElementTransformer = {\n dependencies: Array<Klass<LexicalNode>>\n /**\n * `export` is called when the `$convertToMarkdownString` is called to convert the editor state into markdown.\n *\n * @return return null to cancel the export, even though the regex matched. Lexical will then search for the next transformer.\n */\n export?: (\n node: LexicalNode,\n\n traverseChildren: (node: ElementNode) => string,\n ) => null | string\n /**\n * Use this function to manually handle the import process, once the `regExpStart` has matched successfully.\n * Without providing this function, the default behavior is to match until `regExpEnd` is found, or until the end of the document if `regExpEnd.optional` is true.\n *\n * @returns a tuple or null. The first element of the returned tuple is a boolean indicating if a multiline element was imported. The second element is the index of the last line that was processed. If null is returned, the next multilineElementTransformer will be tried. If undefined is returned, the default behavior will be used.\n */\n handleImportAfterStartMatch?: (args: {\n lines: Array<string>\n rootNode: ElementNode\n startLineIndex: number\n startMatch: RegExpMatchArray\n transformer: MultilineElementTransformer\n }) => [boolean, number] | null | undefined\n /**\n * This regex determines when to stop matching. Anything in between regExpStart and regExpEnd will be matched\n */\n regExpEnd?:\n | {\n /**\n * Whether the end match is optional. If true, the end match is not required to match for the transformer to be triggered.\n * The entire text from regexpStart to the end of the document will then be matched.\n */\n optional?: true\n regExp: RegExp\n }\n | RegExp\n /**\n * This regex determines when to start matching\n */\n regExpStart: RegExp\n /**\n * `replace` is called only when markdown is imported in the editor, not when it's typed\n *\n * @return return false to cancel the transform, even though the regex matched. Lexical will then search for the next transformer.\n */\n replace: (\n rootNode: ElementNode,\n /**\n * During markdown shortcut transforms, children nodes may be provided to the transformer. If this is the case, no `linesInBetween` will be provided and\n * the children nodes should be used instead of the `linesInBetween` to create the new node.\n */\n children: Array<LexicalNode> | null,\n startMatch: Array<string>,\n endMatch: Array<string> | null,\n /**\n * linesInBetween includes the text between the start & end matches, split up by lines, not including the matches themselves.\n * This is null when the transformer is triggered through markdown shortcuts (by typing in the editor)\n */\n linesInBetween: Array<string> | null,\n /**\n * Whether the match is from an import operation (e.g. through `$convertFromMarkdownString`) or not (e.g. through typing in the editor).\n */\n isImport: boolean,\n ) => boolean | void\n type: 'multiline-element'\n}\n\nexport type TextFormatTransformer = Readonly<{\n format: ReadonlyArray<TextFormatType>\n intraword?: boolean\n tag: string\n type: 'text-format'\n}>\n\nexport type TextMatchTransformer = Readonly<{\n dependencies: Array<Klass<LexicalNode>>\n /**\n * Determines how a node should be exported to markdown\n */\n export?: (\n node: LexicalNode,\n\n exportChildren: (node: ElementNode) => string,\n\n exportFormat: (node: TextNode, textContent: string) => string,\n ) => null | string\n /**\n * For import operations, this function can be used to determine the end index of the match, after `importRegExp` has matched.\n * Without this function, the end index will be determined by the length of the match from `importRegExp`. Manually determining the end index can be useful if\n * the match from `importRegExp` is not the entire text content of the node. That way, `importRegExp` can be used to match only the start of the node, and `getEndIndex`\n * can be used to match the end of the node.\n *\n * @returns The end index of the match, or false if the match was unsuccessful and a different transformer should be tried.\n */\n getEndIndex?: (node: TextNode, match: RegExpMatchArray) => false | number\n /**\n * This regex determines what text is matched during markdown imports\n */\n importRegExp?: RegExp\n /**\n * This regex determines what text is matched for markdown shortcuts while typing in the editor\n */\n regExp: RegExp\n /**\n * Determines how the matched markdown text should be transformed into a node during the markdown import process\n *\n * @returns nothing, or a TextNode that may be a child of the new node that is created.\n * If a TextNode is returned, text format matching will be applied to it (e.g. bold, italic, etc.)\n */\n replace?: (node: TextNode, match: RegExpMatchArray) => TextNode | void\n /**\n * Single character that allows the transformer to trigger when typed in the editor. This does not affect markdown imports outside of the markdown shortcut plugin.\n * If the trigger is matched, the `regExp` will be used to match the text in the second step.\n */\n trigger?: string\n type: 'text-match'\n}>\n\nconst EMPTY_OR_WHITESPACE_ONLY = /^[\\t ]*$/\nconst ORDERED_LIST_REGEX = /^(\\s*)(\\d+)\\.\\s/\nconst UNORDERED_LIST_REGEX = /^(\\s*)[-*+]\\s/\nconst CHECK_LIST_REGEX = /^(\\s*)(?:-\\s)?\\s?(\\[(\\s|x)?\\])\\s/i\nconst HEADING_REGEX = /^(#{1,6})\\s/\nconst QUOTE_REGEX = /^>\\s/\nconst CODE_START_REGEX = /^[ \\t]*(\\\\`\\\\`\\\\`|```)(\\w+)?/\nconst CODE_END_REGEX = /[ \\t]*(\\\\`\\\\`\\\\`|```)$/\nconst CODE_SINGLE_LINE_REGEX = /^[ \\t]*```[^`]+(?:(?:`{1,2}|`{4,})[^`]+)*```(?:[^`]|$)/\nconst TABLE_ROW_REG_EXP = /^\\|(.+)\\|\\s?$/\nconst TABLE_ROW_DIVIDER_REG_EXP = /^(\\| ?:?-*:? ?)+\\|\\s?$/\nconst TAG_START_REGEX = /^[ \\t]*<[a-z_][\\w-]*(?:\\s[^<>]*)?\\/?>/i\nconst TAG_END_REGEX = /^[ \\t]*<\\/[a-z_][\\w-]*\\s*>/i\n\n/**\n * A CommonMark hard line break marker: either a single backslash (`\\`) or two or\n * more trailing spaces, both placed at the end of a line before the newline.\n * See https://spec.commonmark.org/0.31.2/#hard-line-breaks\n */\nexport type MarkdownHardLineBreak = string\n\n/**\n * Stores the original hard line break marker on a `LineBreakNode` so it can be\n * preserved across a markdown import/export round trip instead of being\n * collapsed into a soft line break.\n *\n * Note: unlike upstream Lexical (which sets `resetOnCopyNode: true`), that option\n * does not exist in the `lexical` version pinned here (0.41.0), so it is omitted.\n */\nexport const hardLineBreakState = createState('mdHardLineBreak', {\n parse: (val): MarkdownHardLineBreak => {\n if (typeof val === 'string' && /^(\\\\| {2,})$/.test(val)) {\n return val\n }\n return ''\n },\n})\n\n/**\n * Detects a CommonMark hard line break marker at the end of a raw line.\n *\n * @returns a tuple of `[textWithoutMarker, marker]` when a marker is found, otherwise null.\n */\nexport function parseMarkdownHardLineBreak(line: string): [string, MarkdownHardLineBreak] | null {\n if (line.endsWith('\\\\')) {\n return [line.slice(0, -1), '\\\\']\n }\n\n const spaces = line.match(/^(.*?\\S)( {2,})$/)\n return spaces ? [spaces[1]!, spaces[2]!] : null\n}\n\nfunction hasNonWhitespaceContentOnLine(children: Array<LexicalNode>, endIndex: number): boolean {\n for (let i = endIndex - 1; i >= 0; i--) {\n if ($isLineBreakNode(children[i])) {\n return false\n }\n if (/\\S/.test(children[i]!.getTextContent())) {\n return true\n }\n }\n return false\n}\n\n/**\n * Removes a trailing hard line break marker from the last text node of `previousNode`\n * (if present) and returns the marker, so it can be carried onto a `LineBreakNode`.\n */\nfunction $extractMarkdownHardLineBreakMarker(\n previousNode: ElementNode,\n): MarkdownHardLineBreak | null {\n const children = previousNode.getChildren()\n const lastChildIndex = children.length - 1\n const lastChild = children[lastChildIndex]\n\n if (!$isTextNode(lastChild)) {\n return null\n }\n\n const lastText = lastChild.getTextContent()\n const hardLineBreak = parseMarkdownHardLineBreak(lastText)\n\n if (hardLineBreak !== null) {\n const [text, marker] = hardLineBreak\n lastChild.setTextContent(text)\n return marker\n }\n\n // Trailing whitespace may have been split into its own text node by inline\n // transformers (e.g. after formatted or linked content). Only treat it as a\n // hard break when there is preceding non-whitespace content on the same line.\n if (/^ {2,}$/.test(lastText) && hasNonWhitespaceContentOnLine(children, lastChildIndex)) {\n lastChild.setTextContent('')\n return lastText\n }\n\n return null\n}\n\n/**\n * Creates a `LineBreakNode` for a markdown line join, preserving any CommonMark\n * hard line break marker found at the end of `previousNode` via node state.\n */\nexport function $createMarkdownLineBreakNode(previousNode: ElementNode): LineBreakNode {\n const lineBreakNode = $createLineBreakNode()\n const hardLineBreak = $extractMarkdownHardLineBreakMarker(previousNode)\n\n if (hardLineBreak !== null) {\n $setState(lineBreakNode, hardLineBreakState, hardLineBreak)\n }\n\n return lineBreakNode\n}\n\nconst createBlockNode = (\n createNode: (match: Array<string>) => ElementNode,\n): ElementTransformer['replace'] => {\n return (parentNode, children, match) => {\n const node = createNode(match)\n node.append(...children)\n parentNode.replace(node)\n node.select(0, 0)\n }\n}\n\n// Amount of spaces that define indentation level\n// TODO: should be an option\nconst LIST_INDENT_SIZE = 4\n\nfunction getIndent(whitespaces: string): number {\n const tabs = whitespaces.match(/\\t/g)\n const spaces = whitespaces.match(/ /g)\n\n let indent = 0\n\n if (tabs) {\n indent += tabs.length\n }\n\n if (spaces) {\n indent += Math.floor(spaces.length / LIST_INDENT_SIZE)\n }\n\n return indent\n}\n\nconst listReplace = (listType: ListType): ElementTransformer['replace'] => {\n return (parentNode, children, match) => {\n const previousNode = parentNode.getPreviousSibling()\n const nextNode = parentNode.getNextSibling()\n const listItem = $createListItemNode(listType === 'check' ? match[3] === 'x' : undefined)\n if ($isListNode(nextNode) && nextNode.getListType() === listType) {\n const firstChild = nextNode.getFirstChild()\n if (firstChild !== null) {\n firstChild.insertBefore(listItem)\n } else {\n // should never happen, but let's handle gracefully, just in case.\n nextNode.append(listItem)\n }\n parentNode.remove()\n } else if ($isListNode(previousNode) && previousNode.getListType() === listType) {\n previousNode.append(listItem)\n parentNode.remove()\n } else {\n const list = $createListNode(listType, listType === 'number' ? Number(match[2]) : undefined)\n list.append(listItem)\n parentNode.replace(list)\n }\n listItem.append(...children)\n listItem.select(0, 0)\n const indent = getIndent(match[1]!)\n if (indent) {\n listItem.setIndent(indent)\n }\n }\n}\n\nconst listExport = (\n listNode: ListNode,\n exportChildren: (node: ElementNode) => string,\n depth: number,\n): string => {\n const output: string[] = []\n const children = listNode.getChildren()\n let index = 0\n for (const listItemNode of children) {\n if ($isListItemNode(listItemNode)) {\n if (listItemNode.getChildrenSize() === 1) {\n const firstChild = listItemNode.getFirstChild()\n if ($isListNode(firstChild)) {\n output.push(listExport(firstChild, exportChildren, depth + 1))\n continue\n }\n }\n const indent = ' '.repeat(depth * LIST_INDENT_SIZE)\n const listType = listNode.getListType()\n const prefix =\n listType === 'number'\n ? `${listNode.getStart() + index}. `\n : listType === 'check'\n ? `- [${listItemNode.getChecked() ? 'x' : ' '}] `\n : '- '\n output.push(indent + prefix + exportChildren(listItemNode))\n index++\n }\n }\n\n return output.join('\\n')\n}\n\nexport const HEADING: ElementTransformer = {\n type: 'element',\n dependencies: [HeadingNode],\n export: (node, exportChildren) => {\n if (!$isHeadingNode(node)) {\n return null\n }\n const level = Number(node.getTag().slice(1))\n return '#'.repeat(level) + ' ' + exportChildren(node)\n },\n regExp: HEADING_REGEX,\n replace: createBlockNode((match) => {\n const tag = ('h' + match[1]!.length) as HeadingTagType\n return $createHeadingNode(tag)\n }),\n}\n\nexport const QUOTE: ElementTransformer = {\n type: 'element',\n dependencies: [QuoteNode],\n export: (node, exportChildren) => {\n if (!$isQuoteNode(node)) {\n return null\n }\n\n const lines = exportChildren(node).split('\\n')\n const output: string[] = []\n for (const line of lines) {\n output.push('> ' + line)\n }\n return output.join('\\n')\n },\n regExp: QUOTE_REGEX,\n replace: (parentNode, children, _match, isImport) => {\n if (isImport) {\n const previousNode = parentNode.getPreviousSibling()\n if ($isQuoteNode(previousNode)) {\n previousNode.splice(previousNode.getChildrenSize(), 0, [\n $createMarkdownLineBreakNode(previousNode),\n ...children,\n ])\n previousNode.select(0, 0)\n parentNode.remove()\n return\n }\n }\n\n const node = $createQuoteNode()\n node.append(...children)\n parentNode.replace(node)\n node.select(0, 0)\n },\n}\n\nexport const UNORDERED_LIST: ElementTransformer = {\n type: 'element',\n dependencies: [ListNode, ListItemNode],\n export: (node, exportChildren) => {\n return $isListNode(node) ? listExport(node, exportChildren, 0) : null\n },\n regExp: UNORDERED_LIST_REGEX,\n replace: listReplace('bullet'),\n}\n\nexport const CHECK_LIST: ElementTransformer = {\n type: 'element',\n dependencies: [ListNode, ListItemNode],\n export: (node, exportChildren) => {\n return $isListNode(node) ? listExport(node, exportChildren, 0) : null\n },\n regExp: CHECK_LIST_REGEX,\n replace: listReplace('check'),\n}\n\nexport const ORDERED_LIST: ElementTransformer = {\n type: 'element',\n dependencies: [ListNode, ListItemNode],\n export: (node, exportChildren) => {\n return $isListNode(node) ? listExport(node, exportChildren, 0) : null\n },\n regExp: ORDERED_LIST_REGEX,\n replace: listReplace('number'),\n}\n\nexport const INLINE_CODE: TextFormatTransformer = {\n type: 'text-format',\n format: ['code'],\n tag: '`',\n}\n\nexport const HIGHLIGHT: TextFormatTransformer = {\n type: 'text-format',\n format: ['highlight'],\n tag: '==',\n}\n\nexport const BOLD_ITALIC_STAR: TextFormatTransformer = {\n type: 'text-format',\n format: ['bold', 'italic'],\n tag: '***',\n}\n\nexport const BOLD_ITALIC_UNDERSCORE: TextFormatTransformer = {\n type: 'text-format',\n format: ['bold', 'italic'],\n intraword: false,\n tag: '___',\n}\n\nexport const BOLD_STAR: TextFormatTransformer = {\n type: 'text-format',\n format: ['bold'],\n tag: '**',\n}\n\nexport const BOLD_UNDERSCORE: TextFormatTransformer = {\n type: 'text-format',\n format: ['bold'],\n intraword: false,\n tag: '__',\n}\n\nexport const STRIKETHROUGH: TextFormatTransformer = {\n type: 'text-format',\n format: ['strikethrough'],\n tag: '~~',\n}\n\nexport const ITALIC_STAR: TextFormatTransformer = {\n type: 'text-format',\n format: ['italic'],\n tag: '*',\n}\n\nexport const ITALIC_UNDERSCORE: TextFormatTransformer = {\n type: 'text-format',\n format: ['italic'],\n intraword: false,\n tag: '_',\n}\n\nexport function normalizeMarkdown(input: string, shouldMergeAdjacentLines: boolean): string {\n const lines = input.split('\\n')\n let inCodeBlock = false\n const sanitizedLines: string[] = []\n let nestedDeepCodeBlock = 0\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!\n const lastLine = sanitizedLines[sanitizedLines.length - 1]\n // A hard line break marker on the current line only matters if another line follows it.\n const hardLineBreak = i < lines.length - 1 ? parseMarkdownHardLineBreak(line) : null\n const lastLineHasHardLineBreak =\n lastLine !== undefined && parseMarkdownHardLineBreak(lastLine) !== null\n\n // Code blocks of ```single line``` don't toggle the inCodeBlock flag\n if (CODE_SINGLE_LINE_REGEX.test(line)) {\n sanitizedLines.push(line)\n continue\n }\n\n if (CODE_END_REGEX.test(line)) {\n if (nestedDeepCodeBlock === 0) {\n inCodeBlock = true\n }\n if (nestedDeepCodeBlock === 1) {\n inCodeBlock = false\n }\n if (nestedDeepCodeBlock > 0) {\n nestedDeepCodeBlock--\n }\n sanitizedLines.push(line)\n continue\n }\n\n // Toggle inCodeBlock state when encountering start or end of a code block\n if (CODE_START_REGEX.test(line)) {\n inCodeBlock = true\n nestedDeepCodeBlock++\n sanitizedLines.push(line)\n continue\n }\n\n // If we are inside a code block, keep the line unchanged\n if (inCodeBlock) {\n sanitizedLines.push(line)\n continue\n }\n\n // In markdown the concept of \"empty paragraphs\" does not exist.\n // Blocks must be separated by an empty line. Non-empty adjacent lines must be merged.\n if (\n EMPTY_OR_WHITESPACE_ONLY.test(line) ||\n EMPTY_OR_WHITESPACE_ONLY.test(lastLine!) ||\n !lastLine ||\n HEADING_REGEX.test(lastLine) ||\n HEADING_REGEX.test(line) ||\n QUOTE_REGEX.test(line) ||\n ORDERED_LIST_REGEX.test(line) ||\n UNORDERED_LIST_REGEX.test(line) ||\n CHECK_LIST_REGEX.test(line) ||\n TABLE_ROW_REG_EXP.test(line) ||\n TABLE_ROW_DIVIDER_REG_EXP.test(line) ||\n // Don't merge the next line into a line that ends with a hard line break marker.\n lastLineHasHardLineBreak ||\n !shouldMergeAdjacentLines ||\n TAG_START_REGEX.test(line) ||\n TAG_END_REGEX.test(line) ||\n TAG_START_REGEX.test(lastLine) ||\n TAG_END_REGEX.test(lastLine) ||\n CODE_END_REGEX.test(lastLine)\n ) {\n sanitizedLines.push(line)\n } else {\n // Preserve a trailing hard line break marker on the merged line so it survives import.\n sanitizedLines[sanitizedLines.length - 1] =\n lastLine + ' ' + (hardLineBreak === null ? line.trim() : line.trimStart())\n }\n }\n\n return sanitizedLines.join('\\n')\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,14 @@
1
+ import type { JSONSchemaFn } from '../features/typesServer.js';
2
+ /**
3
+ * Cross-cutting Lexical types shared by every element node. Inlined into
4
+ * `payload-types.ts`. Must stay byte-for-byte in sync with the runtime twins
5
+ * in `types/nodeTypes.ts` (`LexicalElementFormat`, `LexicalElementDirection`,
6
+ * `SerializedLexicalElementBase`) — cross-module assignability depends on it.
7
+ */
8
+ export declare const CORE_LEXICAL_TYPE_STRING = "/** @internal Core Lexical types \u2014 see @payloadcms/richtext-lexical. */\nexport type LexicalElementFormat = 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';\nexport type LexicalElementDirection = ('ltr' | 'rtl') | null;\n\nexport interface SerializedLexicalElementBase<TChildren> {\n children: TChildren[];\n direction: LexicalElementDirection;\n format: LexicalElementFormat;\n indent: number;\n textFormat?: number;\n textStyle?: string;\n version: number;\n}";
9
+ export declare const textNodeJSONSchema: JSONSchemaFn;
10
+ export declare const tabNodeJSONSchema: JSONSchemaFn;
11
+ export declare const lineBreakNodeJSONSchema: JSONSchemaFn;
12
+ export declare const paragraphNodeJSONSchema: JSONSchemaFn;
13
+ export declare const rootNodeJSONSchema: JSONSchemaFn;
14
+ //# sourceMappingURL=builtInNodes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtInNodes.d.ts","sourceRoot":"","sources":["../../src/types/builtInNodes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAI9D;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,6eAYnC,CAAA;AA4DF,eAAO,MAAM,kBAAkB,EAAE,YAkBhC,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,YAoB/B,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,YAYrC,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,YAerC,CAAA;AAeD,eAAO,MAAM,kBAAkB,EAAE,YAoBhC,CAAA"}