@contentful/field-editor-rich-text 3.14.3 → 3.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (323) hide show
  1. package/dist/cjs/ContentfulEditorProvider.js +8 -8
  2. package/dist/cjs/RichTextEditor.js +22 -20
  3. package/dist/cjs/RichTextEditor.styles.js +2 -1
  4. package/dist/cjs/SdkProvider.js +7 -5
  5. package/dist/cjs/SyncEditorChanges.js +15 -6
  6. package/dist/cjs/Toolbar/_tests_/toolbar.test.js +17 -15
  7. package/dist/cjs/Toolbar/components/EmbedEntityWidget.js +14 -10
  8. package/dist/cjs/Toolbar/components/EmbeddedEntityDropdownButton.js +10 -8
  9. package/dist/cjs/Toolbar/components/StickyToolbarWrapper.js +2 -2
  10. package/dist/cjs/Toolbar/index.js +33 -30
  11. package/dist/cjs/__fixtures__/FakeSdk.js +3 -3
  12. package/dist/cjs/__fixtures__/asset/index.js +10 -10
  13. package/dist/cjs/__fixtures__/content-type/index.js +1 -1
  14. package/dist/cjs/__fixtures__/entry/index.js +7 -7
  15. package/dist/cjs/__fixtures__/fixtures.js +8 -6
  16. package/dist/cjs/__fixtures__/locale/index.js +2 -2
  17. package/dist/cjs/__fixtures__/space/index.js +1 -1
  18. package/dist/cjs/constants/Schema.js +1 -0
  19. package/dist/cjs/dialogs/HypelinkDialog/HyperlinkDialog.js +43 -38
  20. package/dist/cjs/dialogs/openRichTextDialog.js +6 -4
  21. package/dist/cjs/dialogs/renderRichTextDialog.js +6 -4
  22. package/dist/cjs/helpers/__tests__/removeInternalMarks.test.js +10 -10
  23. package/dist/cjs/helpers/callbacks.js +3 -3
  24. package/dist/cjs/helpers/config.js +2 -2
  25. package/dist/cjs/helpers/editor.js +53 -44
  26. package/dist/cjs/helpers/environment.js +3 -3
  27. package/dist/cjs/helpers/formatDateAndTime.js +5 -4
  28. package/dist/cjs/helpers/getAllowedResourcesForNodeType.js +22 -5
  29. package/dist/cjs/helpers/getLinkedContentTypeIdsForNodeType.js +29 -5
  30. package/dist/cjs/helpers/nodeFactory.js +6 -6
  31. package/dist/cjs/helpers/sdkNavigatorSlideIn.js +14 -6
  32. package/dist/cjs/helpers/sdkNavigatorSlideIn.spec.js +3 -2
  33. package/dist/cjs/helpers/toSlateValue.js +14 -3
  34. package/dist/cjs/helpers/transformers.js +5 -5
  35. package/dist/cjs/helpers/validations.js +12 -9
  36. package/dist/cjs/index.js +7 -5
  37. package/dist/cjs/internal/constants.js +4 -2
  38. package/dist/cjs/internal/hooks.js +8 -6
  39. package/dist/cjs/internal/misc.js +15 -12
  40. package/dist/cjs/internal/queries.js +115 -108
  41. package/dist/cjs/internal/transforms.js +51 -48
  42. package/dist/cjs/internal/types/editor.js +3 -1
  43. package/dist/cjs/plugins/Break/createExitBreakPlugin.test.js +4 -3
  44. package/dist/cjs/plugins/Break/createResetNodePlugin.js +1 -0
  45. package/dist/cjs/plugins/Break/createSoftBreakPlugin.test.js +3 -3
  46. package/dist/cjs/plugins/CommandPalette/components/CommandList.js +35 -33
  47. package/dist/cjs/plugins/CommandPalette/components/CommandList.styles.js +1 -1
  48. package/dist/cjs/plugins/CommandPalette/components/CommandPrompt.js +7 -5
  49. package/dist/cjs/plugins/CommandPalette/hooks/useCommandList.js +7 -3
  50. package/dist/cjs/plugins/CommandPalette/onKeyDown.js +6 -1
  51. package/dist/cjs/plugins/CommandPalette/onKeyDown.spec.js +6 -4
  52. package/dist/cjs/plugins/CommandPalette/useCommands.js +3 -3
  53. package/dist/cjs/plugins/CommandPalette/utils/fetchEntries.js +2 -0
  54. package/dist/cjs/plugins/CommandPalette/utils/trimLeadingSlash.js +6 -1
  55. package/dist/cjs/plugins/DragAndDrop/index.js +9 -1
  56. package/dist/cjs/plugins/EmbeddedEntityBlock/LinkedEntityBlock.js +10 -8
  57. package/dist/cjs/plugins/EmbeddedEntityBlock/index.js +3 -3
  58. package/dist/cjs/plugins/EmbeddedEntityInline/FetchingWrappedInlineEntryCard.js +19 -17
  59. package/dist/cjs/plugins/EmbeddedEntityInline/LinkedEntityInline.js +9 -7
  60. package/dist/cjs/plugins/EmbeddedResourceBlock/LinkedResourceBlock.js +5 -5
  61. package/dist/cjs/plugins/EmbeddedResourceInline/FetchingWrappedResourceInlineCard.js +17 -13
  62. package/dist/cjs/plugins/EmbeddedResourceInline/LinkedResourceInline.js +5 -5
  63. package/dist/cjs/plugins/Heading/__tests__/createHeadingPlugin.test.js +32 -32
  64. package/dist/cjs/plugins/Heading/components/Heading.js +13 -10
  65. package/dist/cjs/plugins/Heading/components/ToolbarHeadingButton.js +19 -11
  66. package/dist/cjs/plugins/Heading/createHeadingPlugin.js +7 -2
  67. package/dist/cjs/plugins/Hr/index.js +19 -14
  68. package/dist/cjs/plugins/Hyperlink/HyperlinkModal.js +32 -28
  69. package/dist/cjs/plugins/Hyperlink/__tests__/createHyperlinkPlugin.test.js +8 -8
  70. package/dist/cjs/plugins/Hyperlink/components/EntityHyperlink.js +8 -6
  71. package/dist/cjs/plugins/Hyperlink/components/ResourceHyperlink.js +8 -6
  72. package/dist/cjs/plugins/Hyperlink/components/ToolbarHyperlinkButton.js +6 -4
  73. package/dist/cjs/plugins/Hyperlink/components/UrlHyperlink.js +7 -5
  74. package/dist/cjs/plugins/Hyperlink/components/styles.js +1 -1
  75. package/dist/cjs/plugins/Hyperlink/createHyperlinkPlugin.js +10 -4
  76. package/dist/cjs/plugins/Hyperlink/useEntityInfo.js +6 -3
  77. package/dist/cjs/plugins/Hyperlink/useResourceEntityInfo.js +7 -5
  78. package/dist/cjs/plugins/Hyperlink/utils.js +6 -14
  79. package/dist/cjs/plugins/List/__tests__/createListPlugin.test.js +13 -13
  80. package/dist/cjs/plugins/List/__tests__/insertListBreak.test.js +29 -25
  81. package/dist/cjs/plugins/List/__tests__/insertListFragment.test.js +22 -22
  82. package/dist/cjs/plugins/List/components/List.js +9 -7
  83. package/dist/cjs/plugins/List/components/ListItem.js +6 -4
  84. package/dist/cjs/plugins/List/components/ToolbarListButton.js +7 -5
  85. package/dist/cjs/plugins/List/createListPlugin.js +4 -0
  86. package/dist/cjs/plugins/List/insertListBreak.js +13 -4
  87. package/dist/cjs/plugins/List/insertListFragment.js +18 -5
  88. package/dist/cjs/plugins/List/onKeyDownList.js +7 -4
  89. package/dist/cjs/plugins/List/transforms/insertListItem.js +17 -2
  90. package/dist/cjs/plugins/List/transforms/moveListItemDown.js +8 -2
  91. package/dist/cjs/plugins/List/transforms/moveListItems.js +7 -2
  92. package/dist/cjs/plugins/List/transforms/moveListItems.test.js +15 -14
  93. package/dist/cjs/plugins/List/transforms/toggleList.js +8 -3
  94. package/dist/cjs/plugins/List/transforms/toggleList.spec.js +28 -28
  95. package/dist/cjs/plugins/List/transforms/unwrapList.js +7 -2
  96. package/dist/cjs/plugins/List/utils.js +12 -11
  97. package/dist/cjs/plugins/List/withList.js +6 -2
  98. package/dist/cjs/plugins/Marks/Bold.js +9 -7
  99. package/dist/cjs/plugins/Marks/Code.js +15 -7
  100. package/dist/cjs/plugins/Marks/Italic.js +9 -7
  101. package/dist/cjs/plugins/Marks/Subscript.js +10 -8
  102. package/dist/cjs/plugins/Marks/Superscript.js +10 -8
  103. package/dist/cjs/plugins/Marks/Underline.js +6 -4
  104. package/dist/cjs/plugins/Marks/components/MarkToolbarButton.js +9 -7
  105. package/dist/cjs/plugins/Marks/helpers.js +5 -5
  106. package/dist/cjs/plugins/Normalizer/baseRules.js +2 -0
  107. package/dist/cjs/plugins/Normalizer/createNormalizerPlugin.test.js +12 -12
  108. package/dist/cjs/plugins/Normalizer/utils.js +4 -3
  109. package/dist/cjs/plugins/Normalizer/withNormalizer.js +23 -3
  110. package/dist/cjs/plugins/Paragraph/Paragraph.js +6 -4
  111. package/dist/cjs/plugins/Paragraph/__tests__/createParagraphPlugin.test.js +32 -32
  112. package/dist/cjs/plugins/Paragraph/createParagraphPlugin.js +3 -2
  113. package/dist/cjs/plugins/PasteHTML/createPasteHTMLPlugin.js +9 -6
  114. package/dist/cjs/plugins/PasteHTML/utils/__tests__/sanitizeHTML.test.js +2 -0
  115. package/dist/cjs/plugins/PasteHTML/utils/sanitizeAnchors.js +9 -0
  116. package/dist/cjs/plugins/PasteHTML/utils/sanitizeHTML.js +17 -2
  117. package/dist/cjs/plugins/PasteHTML/utils/sanitizeSheets.js +13 -1
  118. package/dist/cjs/plugins/Quote/__test__/createQuotePlugin.test.js +21 -21
  119. package/dist/cjs/plugins/Quote/components/Quote.js +6 -4
  120. package/dist/cjs/plugins/Quote/components/ToolbarQuoteButton.js +6 -4
  121. package/dist/cjs/plugins/Quote/createQuotePlugin.js +1 -0
  122. package/dist/cjs/plugins/Quote/toggleQuote.js +5 -5
  123. package/dist/cjs/plugins/Quote/withQuote.js +4 -2
  124. package/dist/cjs/plugins/SelectOnBackspace/createSelectOnBackspacePlugin.js +1 -0
  125. package/dist/cjs/plugins/Table/__tests__/createTablePlugin.test.js +22 -22
  126. package/dist/cjs/plugins/Table/__tests__/helpers.test.js +4 -4
  127. package/dist/cjs/plugins/Table/actions/addColumn.js +5 -4
  128. package/dist/cjs/plugins/Table/actions/addRow.js +6 -3
  129. package/dist/cjs/plugins/Table/components/Cell.js +7 -5
  130. package/dist/cjs/plugins/Table/components/HeaderCell.js +7 -5
  131. package/dist/cjs/plugins/Table/components/Row.js +6 -4
  132. package/dist/cjs/plugins/Table/components/Table.js +8 -6
  133. package/dist/cjs/plugins/Table/components/TableActions.js +19 -16
  134. package/dist/cjs/plugins/Table/components/ToolbarButton.js +7 -4
  135. package/dist/cjs/plugins/Table/createTablePlugin.js +11 -1
  136. package/dist/cjs/plugins/Table/helpers.js +16 -12
  137. package/dist/cjs/plugins/Table/insertTableFragment.js +15 -2
  138. package/dist/cjs/plugins/Table/onKeyDownTable.js +10 -2
  139. package/dist/cjs/plugins/Table/tableTracking.js +6 -6
  140. package/dist/cjs/plugins/Text/__tests__/createTextPlugin.test.js +19 -17
  141. package/dist/cjs/plugins/Text/createTextPlugin.js +22 -5
  142. package/dist/cjs/plugins/Tracking/createTrackingPlugin.js +5 -4
  143. package/dist/cjs/plugins/Tracking/utils.js +6 -3
  144. package/dist/cjs/plugins/Voids/createVoidsPlugin.js +5 -0
  145. package/dist/cjs/plugins/Voids/transformVoid.js +1 -0
  146. package/dist/cjs/plugins/index.js +15 -3
  147. package/dist/cjs/plugins/shared/EmbeddedBlockToolbarIcon.js +12 -10
  148. package/dist/cjs/plugins/shared/EmbeddedBlockUtil.js +16 -6
  149. package/dist/cjs/plugins/shared/EmbeddedInlineToolbarIcon.js +10 -8
  150. package/dist/cjs/plugins/shared/EmbeddedInlineUtil.js +9 -5
  151. package/dist/cjs/plugins/shared/FetchingWrappedAssetCard.js +13 -11
  152. package/dist/cjs/plugins/shared/FetchingWrappedEntryCard.js +14 -12
  153. package/dist/cjs/plugins/shared/FetchingWrappedResourceCard.js +14 -11
  154. package/dist/cjs/plugins/shared/LinkedBlockWrapper.js +8 -4
  155. package/dist/cjs/plugins/shared/LinkedInlineWrapper.js +10 -6
  156. package/dist/cjs/plugins/shared/ResourceNewBadge.js +5 -3
  157. package/dist/cjs/plugins/shared/ToolbarButton.js +8 -6
  158. package/dist/cjs/plugins/shared/__tests__/FetchingWrappedAssetCard.test.js +10 -5
  159. package/dist/cjs/plugins/shared/__tests__/FetchingWrappedEntryCard.test.js +11 -6
  160. package/dist/cjs/plugins/shared/__tests__/FetchingWrappedResourceCard.test.js +15 -13
  161. package/dist/cjs/plugins/shared/utils.js +20 -3
  162. package/dist/cjs/test-utils/assertOutput.js +1 -0
  163. package/dist/cjs/test-utils/hyperscript.d.js +1 -0
  164. package/dist/cjs/test-utils/randomId.js +3 -1
  165. package/dist/cjs/test-utils/validation.js +8 -5
  166. package/dist/esm/ContentfulEditorProvider.js +4 -1
  167. package/dist/esm/RichTextEditor.js +13 -13
  168. package/dist/esm/RichTextEditor.styles.js +1 -0
  169. package/dist/esm/SdkProvider.js +2 -2
  170. package/dist/esm/SyncEditorChanges.js +18 -3
  171. package/dist/esm/Toolbar/_tests_/toolbar.test.js +12 -12
  172. package/dist/esm/Toolbar/components/EmbedEntityWidget.js +10 -8
  173. package/dist/esm/Toolbar/components/EmbeddedEntityDropdownButton.js +6 -6
  174. package/dist/esm/Toolbar/components/StickyToolbarWrapper.js +1 -1
  175. package/dist/esm/Toolbar/index.js +28 -27
  176. package/dist/esm/__fixtures__/FakeSdk.js +3 -3
  177. package/dist/esm/constants/Schema.js +1 -0
  178. package/dist/esm/dialogs/HypelinkDialog/HyperlinkDialog.js +34 -31
  179. package/dist/esm/dialogs/openRichTextDialog.js +2 -2
  180. package/dist/esm/dialogs/renderRichTextDialog.js +2 -2
  181. package/dist/esm/helpers/__tests__/removeInternalMarks.test.js +10 -10
  182. package/dist/esm/helpers/callbacks.js +1 -1
  183. package/dist/esm/helpers/config.js +9 -1
  184. package/dist/esm/helpers/editor.js +22 -6
  185. package/dist/esm/helpers/extractNodes.js +3 -1
  186. package/dist/esm/helpers/formatDateAndTime.js +11 -2
  187. package/dist/esm/helpers/getAllowedResourcesForNodeType.js +19 -2
  188. package/dist/esm/helpers/getLinkedContentTypeIdsForNodeType.js +26 -2
  189. package/dist/esm/helpers/sdkNavigatorSlideIn.js +20 -6
  190. package/dist/esm/helpers/sdkNavigatorSlideIn.spec.js +1 -0
  191. package/dist/esm/helpers/toSlateValue.js +17 -3
  192. package/dist/esm/helpers/validations.js +5 -1
  193. package/dist/esm/internal/misc.js +23 -2
  194. package/dist/esm/internal/queries.js +11 -2
  195. package/dist/esm/internal/transforms.js +14 -3
  196. package/dist/esm/internal/types/editor.js +3 -1
  197. package/dist/esm/plugins/Break/createExitBreakPlugin.test.js +4 -3
  198. package/dist/esm/plugins/Break/createResetNodePlugin.js +1 -0
  199. package/dist/esm/plugins/Break/createSoftBreakPlugin.test.js +3 -3
  200. package/dist/esm/plugins/CommandPalette/components/CommandList.js +30 -30
  201. package/dist/esm/plugins/CommandPalette/components/CommandPrompt.js +2 -2
  202. package/dist/esm/plugins/CommandPalette/createCommandPalettePlugin.js +11 -1
  203. package/dist/esm/plugins/CommandPalette/hooks/useCommandList.js +2 -0
  204. package/dist/esm/plugins/CommandPalette/onKeyDown.js +5 -0
  205. package/dist/esm/plugins/CommandPalette/onKeyDown.spec.js +2 -2
  206. package/dist/esm/plugins/CommandPalette/useCommands.js +3 -3
  207. package/dist/esm/plugins/CommandPalette/utils/fetchEntries.js +2 -0
  208. package/dist/esm/plugins/CommandPalette/utils/trimLeadingSlash.js +6 -1
  209. package/dist/esm/plugins/DragAndDrop/index.js +9 -1
  210. package/dist/esm/plugins/EmbeddedEntityBlock/LinkedEntityBlock.js +6 -6
  211. package/dist/esm/plugins/EmbeddedEntityInline/FetchingWrappedInlineEntryCard.js +14 -14
  212. package/dist/esm/plugins/EmbeddedEntityInline/LinkedEntityInline.js +5 -5
  213. package/dist/esm/plugins/EmbeddedResourceBlock/LinkedResourceBlock.js +4 -4
  214. package/dist/esm/plugins/EmbeddedResourceInline/FetchingWrappedResourceInlineCard.js +13 -11
  215. package/dist/esm/plugins/EmbeddedResourceInline/LinkedResourceInline.js +4 -4
  216. package/dist/esm/plugins/Heading/__tests__/createHeadingPlugin.test.js +32 -32
  217. package/dist/esm/plugins/Heading/components/Heading.js +8 -7
  218. package/dist/esm/plugins/Heading/components/ToolbarHeadingButton.js +14 -8
  219. package/dist/esm/plugins/Heading/createHeadingPlugin.js +6 -1
  220. package/dist/esm/plugins/Hr/index.js +8 -5
  221. package/dist/esm/plugins/Hyperlink/HyperlinkModal.js +25 -23
  222. package/dist/esm/plugins/Hyperlink/__tests__/createHyperlinkPlugin.test.js +8 -8
  223. package/dist/esm/plugins/Hyperlink/components/EntityHyperlink.js +4 -4
  224. package/dist/esm/plugins/Hyperlink/components/ResourceHyperlink.js +4 -4
  225. package/dist/esm/plugins/Hyperlink/components/ToolbarHyperlinkButton.js +2 -2
  226. package/dist/esm/plugins/Hyperlink/components/UrlHyperlink.js +3 -3
  227. package/dist/esm/plugins/Hyperlink/createHyperlinkPlugin.js +5 -1
  228. package/dist/esm/plugins/Hyperlink/useEntityInfo.js +6 -3
  229. package/dist/esm/plugins/Hyperlink/useResourceEntityInfo.js +3 -3
  230. package/dist/esm/plugins/Hyperlink/utils.js +2 -7
  231. package/dist/esm/plugins/List/__tests__/createListPlugin.test.js +13 -13
  232. package/dist/esm/plugins/List/__tests__/insertListBreak.test.js +29 -25
  233. package/dist/esm/plugins/List/__tests__/insertListFragment.test.js +22 -22
  234. package/dist/esm/plugins/List/components/List.js +1 -1
  235. package/dist/esm/plugins/List/components/ListItem.js +1 -1
  236. package/dist/esm/plugins/List/components/ToolbarListButton.js +3 -3
  237. package/dist/esm/plugins/List/createListPlugin.js +4 -0
  238. package/dist/esm/plugins/List/insertListBreak.js +13 -4
  239. package/dist/esm/plugins/List/insertListFragment.js +18 -5
  240. package/dist/esm/plugins/List/onKeyDownList.js +5 -2
  241. package/dist/esm/plugins/List/transforms/insertListItem.js +20 -3
  242. package/dist/esm/plugins/List/transforms/moveListItemDown.js +8 -2
  243. package/dist/esm/plugins/List/transforms/moveListItems.js +7 -2
  244. package/dist/esm/plugins/List/transforms/moveListItems.test.js +15 -14
  245. package/dist/esm/plugins/List/transforms/toggleList.js +8 -3
  246. package/dist/esm/plugins/List/transforms/toggleList.spec.js +28 -28
  247. package/dist/esm/plugins/List/transforms/unwrapList.js +7 -2
  248. package/dist/esm/plugins/List/utils.js +7 -2
  249. package/dist/esm/plugins/List/withList.js +6 -2
  250. package/dist/esm/plugins/Marks/Bold.js +2 -2
  251. package/dist/esm/plugins/Marks/Code.js +8 -2
  252. package/dist/esm/plugins/Marks/Italic.js +2 -2
  253. package/dist/esm/plugins/Marks/Subscript.js +2 -2
  254. package/dist/esm/plugins/Marks/Superscript.js +2 -2
  255. package/dist/esm/plugins/Marks/Underline.js +2 -2
  256. package/dist/esm/plugins/Marks/components/MarkToolbarButton.js +4 -4
  257. package/dist/esm/plugins/Marks/helpers.js +1 -1
  258. package/dist/esm/plugins/Normalizer/baseRules.js +4 -0
  259. package/dist/esm/plugins/Normalizer/createNormalizerPlugin.test.js +12 -12
  260. package/dist/esm/plugins/Normalizer/utils.js +1 -0
  261. package/dist/esm/plugins/Normalizer/withNormalizer.js +22 -2
  262. package/dist/esm/plugins/Paragraph/Paragraph.js +1 -1
  263. package/dist/esm/plugins/Paragraph/__tests__/createParagraphPlugin.test.js +32 -32
  264. package/dist/esm/plugins/Paragraph/createParagraphPlugin.js +2 -1
  265. package/dist/esm/plugins/PasteHTML/createPasteHTMLPlugin.js +9 -3
  266. package/dist/esm/plugins/PasteHTML/utils/__tests__/sanitizeHTML.test.js +2 -0
  267. package/dist/esm/plugins/PasteHTML/utils/sanitizeAnchors.js +27 -1
  268. package/dist/esm/plugins/PasteHTML/utils/sanitizeHTML.js +17 -2
  269. package/dist/esm/plugins/PasteHTML/utils/sanitizeSheets.js +13 -1
  270. package/dist/esm/plugins/Quote/__test__/createQuotePlugin.test.js +21 -21
  271. package/dist/esm/plugins/Quote/components/Quote.js +1 -1
  272. package/dist/esm/plugins/Quote/components/ToolbarQuoteButton.js +2 -2
  273. package/dist/esm/plugins/Quote/createQuotePlugin.js +1 -0
  274. package/dist/esm/plugins/Quote/shouldResetQuote.js +6 -1
  275. package/dist/esm/plugins/Quote/toggleQuote.js +1 -1
  276. package/dist/esm/plugins/Quote/withQuote.js +4 -2
  277. package/dist/esm/plugins/SelectOnBackspace/createSelectOnBackspacePlugin.js +1 -0
  278. package/dist/esm/plugins/Table/__tests__/createTablePlugin.test.js +22 -22
  279. package/dist/esm/plugins/Table/__tests__/helpers.test.js +4 -4
  280. package/dist/esm/plugins/Table/actions/addColumn.js +2 -1
  281. package/dist/esm/plugins/Table/actions/addRow.js +3 -0
  282. package/dist/esm/plugins/Table/components/Cell.js +2 -2
  283. package/dist/esm/plugins/Table/components/HeaderCell.js +2 -2
  284. package/dist/esm/plugins/Table/components/Row.js +1 -1
  285. package/dist/esm/plugins/Table/components/Table.js +3 -3
  286. package/dist/esm/plugins/Table/components/TableActions.js +12 -11
  287. package/dist/esm/plugins/Table/components/ToolbarButton.js +3 -2
  288. package/dist/esm/plugins/Table/createTablePlugin.js +11 -1
  289. package/dist/esm/plugins/Table/helpers.js +10 -1
  290. package/dist/esm/plugins/Table/insertTableFragment.js +15 -2
  291. package/dist/esm/plugins/Table/onKeyDownTable.js +10 -2
  292. package/dist/esm/plugins/Table/tableTracking.js +6 -6
  293. package/dist/esm/plugins/Text/__tests__/createTextPlugin.test.js +19 -17
  294. package/dist/esm/plugins/Text/createTextPlugin.js +22 -5
  295. package/dist/esm/plugins/Tracking/createTrackingPlugin.js +2 -1
  296. package/dist/esm/plugins/Tracking/utils.js +1 -0
  297. package/dist/esm/plugins/Voids/createVoidsPlugin.js +5 -0
  298. package/dist/esm/plugins/Voids/transformVoid.js +4 -1
  299. package/dist/esm/plugins/index.js +12 -0
  300. package/dist/esm/plugins/shared/EmbeddedBlockToolbarIcon.js +5 -5
  301. package/dist/esm/plugins/shared/EmbeddedBlockUtil.js +15 -5
  302. package/dist/esm/plugins/shared/EmbeddedInlineToolbarIcon.js +5 -5
  303. package/dist/esm/plugins/shared/EmbeddedInlineUtil.js +8 -4
  304. package/dist/esm/plugins/shared/FetchingWrappedAssetCard.js +8 -8
  305. package/dist/esm/plugins/shared/FetchingWrappedEntryCard.js +9 -9
  306. package/dist/esm/plugins/shared/FetchingWrappedResourceCard.js +9 -8
  307. package/dist/esm/plugins/shared/LinkedBlockWrapper.js +7 -3
  308. package/dist/esm/plugins/shared/LinkedInlineWrapper.js +5 -3
  309. package/dist/esm/plugins/shared/ResourceNewBadge.js +1 -1
  310. package/dist/esm/plugins/shared/ToolbarButton.js +3 -3
  311. package/dist/esm/plugins/shared/__tests__/FetchingWrappedAssetCard.test.js +5 -2
  312. package/dist/esm/plugins/shared/__tests__/FetchingWrappedEntryCard.test.js +5 -2
  313. package/dist/esm/plugins/shared/__tests__/FetchingWrappedResourceCard.test.js +8 -8
  314. package/dist/esm/plugins/shared/utils.js +9 -0
  315. package/dist/esm/test-utils/assertOutput.js +1 -0
  316. package/dist/esm/test-utils/hyperscript.d.js +1 -0
  317. package/dist/esm/test-utils/jsx.js +5 -1
  318. package/dist/esm/test-utils/randomId.js +3 -1
  319. package/dist/esm/test-utils/setEmptyDataAttribute.js +4 -1
  320. package/dist/esm/test-utils/validation.js +7 -4
  321. package/dist/types/plugins/Hyperlink/utils.d.ts +0 -1
  322. package/dist/types/plugins/shared/utils.d.ts +1 -0
  323. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { BLOCKS, INLINES } from '@contentful/rich-text-types';
1
+ /** @jsx jsx */ import { BLOCKS, INLINES } from '@contentful/rich-text-types';
2
2
  import { transformWrapIn } from '../../helpers/transformers';
3
3
  import { jsx, createTestEditor, mockPlugin, assertOutput } from '../../test-utils';
4
4
  import { createNormalizerPlugin } from './createNormalizerPlugin';
@@ -12,15 +12,15 @@ describe('Normalizer', ()=>{
12
12
  ];
13
13
  let input;
14
14
  beforeEach(()=>{
15
- input = jsx("editor", null, jsx("hul", null, jsx("hli", null, jsx("hembed", {
15
+ input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hul", null, /*#__PURE__*/ jsx("hli", null, /*#__PURE__*/ jsx("hembed", {
16
16
  type: "Entry",
17
17
  id: "embedded-entry"
18
- }), jsx("hp", null, "List item"))));
18
+ }), /*#__PURE__*/ jsx("hp", null, "List item"))));
19
19
  });
20
- const expected = jsx("editor", null, jsx("hul", null, jsx("hli", null, jsx("hp", null, "List item"))));
20
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hul", null, /*#__PURE__*/ jsx("hli", null, /*#__PURE__*/ jsx("hp", null, "List item"))));
21
21
  describe('rule.match', ()=>{
22
22
  it('matches elements of type "plugin.type" by default', ()=>{
23
- const { editor } = createTestEditor({
23
+ const { editor } = createTestEditor({
24
24
  input,
25
25
  plugins: [
26
26
  mockPlugin({
@@ -50,14 +50,14 @@ describe('Normalizer', ()=>{
50
50
  });
51
51
  describe('rule.transform', ()=>{
52
52
  it('works with conditional transformation', ()=>{
53
- const { editor } = createTestEditor({
54
- input: jsx("editor", null, jsx("hul", null, jsx("hli", null, jsx("hembed", {
53
+ const { editor } = createTestEditor({
54
+ input: /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hul", null, /*#__PURE__*/ jsx("hli", null, /*#__PURE__*/ jsx("hembed", {
55
55
  type: "Entry",
56
56
  id: "embedded-entry"
57
- }), jsx("hinline", {
57
+ }), /*#__PURE__*/ jsx("hinline", {
58
58
  type: "Entry",
59
59
  id: "inline-entry"
60
- }), jsx("hp", null, "List item")))),
60
+ }), /*#__PURE__*/ jsx("hp", null, "List item")))),
61
61
  plugins: [
62
62
  mockPlugin({
63
63
  isElement: true,
@@ -78,16 +78,16 @@ describe('Normalizer', ()=>{
78
78
  });
79
79
  assertOutput({
80
80
  editor,
81
- expected: jsx("editor", null, jsx("hul", null, jsx("hli", null, jsx("hp", null, jsx("hinline", {
81
+ expected: /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hul", null, /*#__PURE__*/ jsx("hli", null, /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("hinline", {
82
82
  type: "Entry",
83
83
  id: "inline-entry"
84
- })), jsx("hp", null, "List item"))))
84
+ })), /*#__PURE__*/ jsx("hp", null, "List item"))))
85
85
  });
86
86
  });
87
87
  });
88
88
  describe('rule.validChildren', ()=>{
89
89
  it('supports custom functions', ()=>{
90
- const { editor } = createTestEditor({
90
+ const { editor } = createTestEditor({
91
91
  input,
92
92
  plugins: [
93
93
  mockPlugin({
@@ -5,6 +5,7 @@ export const createValidatorFromTypes = (types)=>(_, [node])=>{
5
5
  return isElement(node) && types.includes(node.type);
6
6
  };
7
7
  export const createTransformerFromObject = (transforms)=>{
8
+ // A default transformer must always be provided
8
9
  const fallback = transforms['default'];
9
10
  if (!fallback) {
10
11
  throw new NormalizerError('A default transformer MUST be provided');
@@ -6,25 +6,35 @@ import { baseRules } from './baseRules';
6
6
  import { NormalizerError, createValidatorFromTypes, createTransformerFromObject } from './utils';
7
7
  export const withNormalizer = (editor)=>{
8
8
  const rules = baseRules;
9
+ // Derive normalization rules from other plugin's configurations
9
10
  for (const p of editor.plugins){
10
- const { normalizer: _rules } = p;
11
+ const { normalizer: _rules } = p;
11
12
  if (!_rules) {
12
13
  continue;
13
14
  }
14
15
  for (const _rule of _rules){
16
+ // Clone to avoid mutation bugs
15
17
  const rule = {
16
18
  ..._rule
17
19
  };
18
20
  if (!rule.match && !p.isElement) {
19
21
  throw new NormalizerError('rule.match MUST be defined in a non-element plugin');
20
22
  }
23
+ // By default we filter elements with given plugin type
21
24
  if (!rule.match) {
22
25
  rule.match = {
23
26
  type: getPluginType(editor, p.key)
24
27
  };
25
28
  }
29
+ // Conditional transformation e.g.
30
+ // {
31
+ // [BLOCKS.EMBEDDED_ASSET]: transformLift,
32
+ // default?: transformRemove
33
+ // }
34
+ //
26
35
  if (isPlainObject(rule.transform)) {
27
36
  if ('validNode' in rule) {
37
+ // I can't think of a use case. Disabled to prevent misuse
28
38
  throw new NormalizerError('conditional transformations are not supported in validNode rules');
29
39
  }
30
40
  rule.transform = createTransformerFromObject({
@@ -32,33 +42,43 @@ export const withNormalizer = (editor)=>{
32
42
  ...rule.transform
33
43
  });
34
44
  }
45
+ // By default all invalid nodes are removed.
35
46
  if (!rule.transform) {
36
47
  rule.transform = transformRemove;
37
48
  }
49
+ // Convert Types array syntax to a validator function
38
50
  if ('validChildren' in rule && Array.isArray(rule.validChildren)) {
39
51
  rule.validChildren = createValidatorFromTypes(rule.validChildren);
40
52
  }
41
53
  rules.push(rule);
42
54
  }
43
55
  }
56
+ // Wrap transformer in a withoutNormalizing() call to avoid unnecessary
57
+ // normalization cycles.
44
58
  const _transform = (tr, entry)=>{
45
59
  withoutNormalizing(editor, ()=>{
46
60
  tr(editor, entry);
47
61
  });
48
62
  };
49
- const { normalizeNode } = editor;
63
+ const { normalizeNode } = editor;
64
+ // @ts-expect-error
50
65
  editor.normalizeNode = (entry)=>{
51
66
  const [node, path] = entry;
52
67
  const children = getChildren(entry);
68
+ // The order of validNode rules Vs validChildren doesn't matter. Slate
69
+ // will always perform normalization in a depth-first fashion.
53
70
  for (const rule of rules){
54
71
  if (!matchNode(node, path, rule.match)) {
55
72
  continue;
56
73
  }
74
+ // Normalize node
57
75
  if ('validNode' in rule && !rule.validNode(editor, entry)) {
58
76
  _transform(rule.transform, entry);
59
77
  return;
60
78
  }
79
+ // Normalize node.children
61
80
  if ('validChildren' in rule) {
81
+ // It can not be an array since we enforced it earlier
62
82
  const isValidChild = rule.validChildren;
63
83
  const invalidChildEntry = children.find((entry)=>!isValidChild(editor, entry));
64
84
  if (invalidChildEntry) {
@@ -9,7 +9,7 @@ const styles = {
9
9
  `
10
10
  };
11
11
  export function Paragraph(props) {
12
- return React.createElement("div", {
12
+ return /*#__PURE__*/ React.createElement("div", {
13
13
  ...props.attributes,
14
14
  className: styles[BLOCKS.PARAGRAPH]
15
15
  }, props.children);
@@ -1,16 +1,16 @@
1
- import { assertOutput, jsx } from '../../../test-utils';
1
+ /* eslint-disable react/no-unknown-property */ /** @jsx jsx */ import { assertOutput, jsx } from '../../../test-utils';
2
2
  describe('normalization', ()=>{
3
3
  it('can contain inline entries & hyperlinks', ()=>{
4
- const input = jsx("editor", null, jsx("hp", null, "some text before", jsx("hinline", {
4
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some text before", /*#__PURE__*/ jsx("hinline", {
5
5
  type: "Entry",
6
6
  id: "inline-entry"
7
- }), jsx("hlink", {
7
+ }), /*#__PURE__*/ jsx("hlink", {
8
8
  uri: "https://contentful.com"
9
- }), jsx("hlink", {
9
+ }), /*#__PURE__*/ jsx("hlink", {
10
10
  entry: "entry-id"
11
- }), jsx("hlink", {
11
+ }), /*#__PURE__*/ jsx("hlink", {
12
12
  resource: "resource-urn"
13
- }), jsx("hlink", {
13
+ }), /*#__PURE__*/ jsx("hlink", {
14
14
  asset: "asset-id"
15
15
  }), "some text after"));
16
16
  assertOutput({
@@ -19,20 +19,20 @@ describe('normalization', ()=>{
19
19
  });
20
20
  });
21
21
  it('wraps orphaned text nodes in a paragraph', ()=>{
22
- const input = jsx("editor", null, jsx("hp", null, "valid text"), jsx("hh1", null, "valid text"), jsx("htable", null, jsx("htr", null, jsx("htd", null, "invalid text"))));
23
- const expected = jsx("editor", null, jsx("hp", null, "valid text"), jsx("hh1", null, "valid text"), jsx("htable", null, jsx("htr", null, jsx("htd", null, jsx("hp", null, "invalid text")))), jsx("hp", null, jsx("htext", null)));
22
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "valid text"), /*#__PURE__*/ jsx("hh1", null, "valid text"), /*#__PURE__*/ jsx("htable", null, /*#__PURE__*/ jsx("htr", null, /*#__PURE__*/ jsx("htd", null, "invalid text"))));
23
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "valid text"), /*#__PURE__*/ jsx("hh1", null, "valid text"), /*#__PURE__*/ jsx("htable", null, /*#__PURE__*/ jsx("htr", null, /*#__PURE__*/ jsx("htd", null, /*#__PURE__*/ jsx("hp", null, "invalid text")))), /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("htext", null)));
24
24
  assertOutput({
25
25
  input,
26
26
  expected
27
27
  });
28
28
  });
29
29
  it('unwraps nested paragraphs', ()=>{
30
- const input = jsx("editor", null, jsx("hp", null, "some", jsx("hp", null, jsx("htext", {
30
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some", /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("htext", {
31
31
  bold: true,
32
32
  italic: true,
33
33
  underline: true
34
34
  }, "paragraph")), "text"));
35
- const expected = jsx("editor", null, jsx("hp", null, "some", jsx("htext", {
35
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some", /*#__PURE__*/ jsx("htext", {
36
36
  bold: true,
37
37
  italic: true,
38
38
  underline: true
@@ -44,76 +44,76 @@ describe('normalization', ()=>{
44
44
  });
45
45
  describe('lifts other invalid children', ()=>{
46
46
  it('block void elements', ()=>{
47
- const input = jsx("editor", null, jsx("hp", null, jsx("hembed", {
47
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("hembed", {
48
48
  type: "Asset",
49
49
  id: "1"
50
- }), " start"), jsx("hp", null, "end ", jsx("hembed", {
50
+ }), " start"), /*#__PURE__*/ jsx("hp", null, "end ", /*#__PURE__*/ jsx("hembed", {
51
51
  type: "Asset",
52
52
  id: "2"
53
- })), jsx("hp", null, "in ", jsx("hembed", {
53
+ })), /*#__PURE__*/ jsx("hp", null, "in ", /*#__PURE__*/ jsx("hembed", {
54
54
  type: "Asset",
55
55
  id: "3"
56
- }), " between"), jsx("hp", null, jsx("hembed", {
56
+ }), " between"), /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("hembed", {
57
57
  type: "Entry",
58
58
  id: "1"
59
- }), " start"), jsx("hp", null, "end ", jsx("hembed", {
59
+ }), " start"), /*#__PURE__*/ jsx("hp", null, "end ", /*#__PURE__*/ jsx("hembed", {
60
60
  type: "Entry",
61
61
  id: "2"
62
- })), jsx("hp", null, "in ", jsx("hembed", {
62
+ })), /*#__PURE__*/ jsx("hp", null, "in ", /*#__PURE__*/ jsx("hembed", {
63
63
  type: "Entry",
64
64
  id: "3"
65
- }), " between"), jsx("hp", null, jsx("hhr", null), " start"), jsx("hp", null, "end ", jsx("hhr", null)), jsx("hp", null, "in ", jsx("hhr", null), " between"));
66
- const expected = jsx("editor", null, jsx("hembed", {
65
+ }), " between"), /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("hhr", null), " start"), /*#__PURE__*/ jsx("hp", null, "end ", /*#__PURE__*/ jsx("hhr", null)), /*#__PURE__*/ jsx("hp", null, "in ", /*#__PURE__*/ jsx("hhr", null), " between"));
66
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hembed", {
67
67
  type: "Asset",
68
68
  id: "1"
69
- }), jsx("hp", null, " start"), jsx("hp", null, "end "), jsx("hembed", {
69
+ }), /*#__PURE__*/ jsx("hp", null, " start"), /*#__PURE__*/ jsx("hp", null, "end "), /*#__PURE__*/ jsx("hembed", {
70
70
  type: "Asset",
71
71
  id: "2"
72
- }), jsx("hp", null, "in "), jsx("hembed", {
72
+ }), /*#__PURE__*/ jsx("hp", null, "in "), /*#__PURE__*/ jsx("hembed", {
73
73
  type: "Asset",
74
74
  id: "3"
75
- }), jsx("hp", null, " between"), jsx("hembed", {
75
+ }), /*#__PURE__*/ jsx("hp", null, " between"), /*#__PURE__*/ jsx("hembed", {
76
76
  type: "Entry",
77
77
  id: "1"
78
- }), jsx("hp", null, " start"), jsx("hp", null, "end "), jsx("hembed", {
78
+ }), /*#__PURE__*/ jsx("hp", null, " start"), /*#__PURE__*/ jsx("hp", null, "end "), /*#__PURE__*/ jsx("hembed", {
79
79
  type: "Entry",
80
80
  id: "2"
81
- }), jsx("hp", null, "in "), jsx("hembed", {
81
+ }), /*#__PURE__*/ jsx("hp", null, "in "), /*#__PURE__*/ jsx("hembed", {
82
82
  type: "Entry",
83
83
  id: "3"
84
- }), jsx("hp", null, " between"), jsx("hhr", null), jsx("hp", null, " start"), jsx("hp", null, "end "), jsx("hhr", null), jsx("hp", null, "in "), jsx("hhr", null), jsx("hp", null, " between"));
84
+ }), /*#__PURE__*/ jsx("hp", null, " between"), /*#__PURE__*/ jsx("hhr", null), /*#__PURE__*/ jsx("hp", null, " start"), /*#__PURE__*/ jsx("hp", null, "end "), /*#__PURE__*/ jsx("hhr", null), /*#__PURE__*/ jsx("hp", null, "in "), /*#__PURE__*/ jsx("hhr", null), /*#__PURE__*/ jsx("hp", null, " between"));
85
85
  assertOutput({
86
86
  input,
87
87
  expected
88
88
  });
89
89
  });
90
90
  it('handles heading', ()=>{
91
- const input = jsx("editor", null, jsx("hp", null, "some", jsx("hh1", null, "heading"), "text"));
92
- const expected = jsx("editor", null, jsx("hp", null, "some"), jsx("hh1", null, "heading"), jsx("hp", null, "text"));
91
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some", /*#__PURE__*/ jsx("hh1", null, "heading"), "text"));
92
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some"), /*#__PURE__*/ jsx("hh1", null, "heading"), /*#__PURE__*/ jsx("hp", null, "text"));
93
93
  assertOutput({
94
94
  input,
95
95
  expected
96
96
  });
97
97
  });
98
98
  it('handles quotes', ()=>{
99
- const input = jsx("editor", null, jsx("hp", null, "some", jsx("hquote", null, jsx("hp", null, "quote")), "text"));
100
- const expected = jsx("editor", null, jsx("hp", null, "some"), jsx("hquote", null, jsx("hp", null, "quote")), jsx("hp", null, "text"));
99
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some", /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "quote")), "text"));
100
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some"), /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "quote")), /*#__PURE__*/ jsx("hp", null, "text"));
101
101
  assertOutput({
102
102
  input,
103
103
  expected
104
104
  });
105
105
  });
106
106
  it('handles lists', ()=>{
107
- const input = jsx("editor", null, jsx("hp", null, "some", jsx("hul", null, jsx("hli", null, jsx("hp", null, "list item"))), "text"));
108
- const expected = jsx("editor", null, jsx("hp", null, "some"), jsx("hul", null, jsx("hli", null, jsx("hp", null, "list item"))), jsx("hp", null, "text"));
107
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some", /*#__PURE__*/ jsx("hul", null, /*#__PURE__*/ jsx("hli", null, /*#__PURE__*/ jsx("hp", null, "list item"))), "text"));
108
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some"), /*#__PURE__*/ jsx("hul", null, /*#__PURE__*/ jsx("hli", null, /*#__PURE__*/ jsx("hp", null, "list item"))), /*#__PURE__*/ jsx("hp", null, "text"));
109
109
  assertOutput({
110
110
  input,
111
111
  expected
112
112
  });
113
113
  });
114
114
  it('handles tables', ()=>{
115
- const input = jsx("editor", null, jsx("hp", null, "some", jsx("htable", null, jsx("htr", null, jsx("htd", null, jsx("hp", null, "cell 1")), jsx("htd", null, jsx("hp", null, "cell 2")))), "text"));
116
- const expected = jsx("editor", null, jsx("hp", null, "some"), jsx("htable", null, jsx("htr", null, jsx("htd", null, jsx("hp", null, "cell 1")), jsx("htd", null, jsx("hp", null, "cell 2")))), jsx("hp", null, "text"));
115
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some", /*#__PURE__*/ jsx("htable", null, /*#__PURE__*/ jsx("htr", null, /*#__PURE__*/ jsx("htd", null, /*#__PURE__*/ jsx("hp", null, "cell 1")), /*#__PURE__*/ jsx("htd", null, /*#__PURE__*/ jsx("hp", null, "cell 2")))), "text"));
116
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hp", null, "some"), /*#__PURE__*/ jsx("htable", null, /*#__PURE__*/ jsx("htr", null, /*#__PURE__*/ jsx("htd", null, /*#__PURE__*/ jsx("hp", null, "cell 1")), /*#__PURE__*/ jsx("htd", null, /*#__PURE__*/ jsx("hp", null, "cell 2")))), /*#__PURE__*/ jsx("hp", null, "text"));
117
117
  assertOutput({
118
118
  input,
119
119
  expected
@@ -5,7 +5,7 @@ import { isInlineOrText, toggleElement } from '../../helpers/editor';
5
5
  import { transformUnwrap, transformLift } from '../../helpers/transformers';
6
6
  import { Paragraph } from './Paragraph';
7
7
  import { isEmbedElement, isEmptyElement } from './utils';
8
- const buildParagraphKeyDownHandler = (editor, { options: { hotkey } })=>(event)=>{
8
+ const buildParagraphKeyDownHandler = (editor, { options: { hotkey } })=>(event)=>{
9
9
  if (editor.selection && hotkey && isHotkey(hotkey, event)) {
10
10
  toggleElement(editor, {
11
11
  activeType: BLOCKS.PARAGRAPH,
@@ -26,6 +26,7 @@ export const createParagraphPlugin = ()=>{
26
26
  onKeyDown: buildParagraphKeyDownHandler
27
27
  },
28
28
  softBreak: [
29
+ // create a new line with SHIFT+Enter inside a paragraph
29
30
  {
30
31
  hotkey: 'shift+enter',
31
32
  query: {
@@ -1,12 +1,17 @@
1
1
  import { KEY_DESERIALIZE_HTML } from '@udecode/plate-common';
2
2
  import { sanitizeHTML } from './utils/sanitizeHTML';
3
- const catchSlateFragment = /data-slate-fragment="(.+?)"/m;
3
+ /**
4
+ * Get x-slate-fragment attribute from data-slate-fragment
5
+ */ const catchSlateFragment = /data-slate-fragment="(.+?)"/m;
4
6
  export const getSlateFragmentAttribute = (dataTransfer)=>{
5
7
  const htmlData = dataTransfer.getData('text/html');
6
8
  const [, fragment] = htmlData.match(catchSlateFragment) || [];
7
9
  return fragment;
8
10
  };
9
- export const ensureXSlateFragment = (dataTransfer)=>{
11
+ /**
12
+ * Get the x-slate-fragment attribute that exist in text/html data
13
+ * and append it to the DataTransfer object
14
+ */ export const ensureXSlateFragment = (dataTransfer)=>{
10
15
  if (!dataTransfer.getData('application/x-slate-fragment')) {
11
16
  const fragment = getSlateFragmentAttribute(dataTransfer);
12
17
  if (fragment) {
@@ -23,7 +28,7 @@ export const ensureXSlateFragment = (dataTransfer)=>{
23
28
  export const createPasteHTMLPlugin = ()=>({
24
29
  key: 'PasteHTMLPlugin',
25
30
  withOverrides: (editor)=>{
26
- const { insertData } = editor;
31
+ const { insertData } = editor;
27
32
  editor.insertData = (data)=>insertData(ensureXSlateFragment(data));
28
33
  return editor;
29
34
  },
@@ -33,6 +38,7 @@ export const createPasteHTMLPlugin = ()=>({
33
38
  editor: {
34
39
  insertData: {
35
40
  format: 'text/html',
41
+ // Perform custom content transformation *before* pasting
36
42
  transformData: sanitizeHTML
37
43
  }
38
44
  }
@@ -2,6 +2,7 @@ import { sanitizeHTML } from '../sanitizeHTML';
2
2
  describe('HTML Sanitization', ()=>{
3
3
  it('removes unsupported elements from <a>', ()=>{
4
4
  const cases = [
5
+ // Supported
5
6
  {
6
7
  input: '<h1><a href="#">Link in h1</a></h1>',
7
8
  output: 'unchanged'
@@ -30,6 +31,7 @@ describe('HTML Sanitization', ()=>{
30
31
  input: '<a href="#"><u>u in Link</u></a>',
31
32
  output: 'unchanged'
32
33
  },
34
+ // Unsupported. Should be unwrapped
33
35
  {
34
36
  input: '<a href="#"><h1>h1 in Link</h1><h2>this is h2</h2></a>',
35
37
  output: '<a href="#">h1 in Link this is h2</a>'
@@ -12,20 +12,46 @@ const wrapSpaceAround = (el)=>{
12
12
  }
13
13
  };
14
14
  const unwrap = (el)=>{
15
+ // add a spacer to avoid the content being cramped together with
16
+ // the element siblings after it's unwrapped. It may not always
17
+ // be desired but it should be easy to adjust by the end user.
15
18
  wrapSpaceAround(el);
16
19
  el.replaceWith(...Array.from(el.childNodes));
17
20
  };
18
- export const sanitizeAnchors = (doc)=>{
21
+ /**
22
+ * In HTML it's a valid structure to have a block element inside a link
23
+ *
24
+ * e.g: <a href="..."><h1> My link </h1><h2>is fancy</h2></a>
25
+ *
26
+ * However, that's not supported in Slate. There are generally two ways to
27
+ * handle this:
28
+ *
29
+ * a) Unwrap inner blocks while preserving the content.
30
+ * e.g. <a href="...">My link is fancy</a>
31
+ *
32
+ * b) Break the link into multiple elements with having each block
33
+ * element as a wrapper for an anchor with the same URL
34
+ * e.g. <h1><a href="...">My link</a></h1>
35
+ * and <h2><a href="...">is fancy</a></h2>
36
+ *
37
+ * We take approach (a) in here.
38
+ */ export const sanitizeAnchors = (doc)=>{
19
39
  const unsupportedTagSelector = `a :not(${[
40
+ // Bold
20
41
  'b',
21
42
  'strong',
43
+ // Code
22
44
  'code',
23
45
  'pre',
46
+ // Italic
24
47
  'em',
25
48
  'i',
49
+ // Super/subscript
26
50
  'sub',
27
51
  'sup',
52
+ // Underline
28
53
  'u',
54
+ // Other
29
55
  'span'
30
56
  ].join(',')})`;
31
57
  doc.querySelectorAll(unsupportedTagSelector).forEach(unwrap);
@@ -1,15 +1,20 @@
1
1
  import { sanitizeAnchors } from './sanitizeAnchors';
2
2
  import { sanitizeSheets } from './sanitizeSheets';
3
- const stripStyleTags = (doc)=>{
3
+ /**
4
+ * Remove all <style> tags
5
+ */ const stripStyleTags = (doc)=>{
4
6
  doc.querySelectorAll('style').forEach((e)=>{
5
7
  e.remove();
6
8
  });
7
9
  return doc;
8
10
  };
9
- const stripMetaTags = (doc)=>{
11
+ /**
12
+ * Remove all <meta /> tags
13
+ */ const stripMetaTags = (doc)=>{
10
14
  doc.querySelectorAll('meta').forEach((el)=>el.remove());
11
15
  return doc;
12
16
  };
17
+ // Attention: Order is important
13
18
  const transformers = [
14
19
  stripStyleTags,
15
20
  sanitizeSheets,
@@ -24,17 +29,27 @@ function removeTableWrappers(table) {
24
29
  }
25
30
  }
26
31
  export const sanitizeHTML = (html)=>{
32
+ // Parse the HTML string and pipe it through our transformers
27
33
  const doc = transformers.reduce((value, cb)=>cb(value), new DOMParser().parseFromString(html, 'text/html'));
28
34
  const replacers = [
35
+ // remove whitespaces between some tags, as this can lead to unwanted behaviour:
36
+ // - table -> empty table cells
37
+ // - list -> leading whitespaces
29
38
  (innerHtml)=>innerHtml.replace(/<(\/)?(table|thead|tbody|tr|td|th|caption|col|colgroup|ol|ul|li)(.*)>\s+<(\/)?(table|thead|tbody|tr|td|th|caption|col|colgroup|ol|ul|li)/g, '<$1$2$3><$4$5'),
39
+ // remove empty elements before the ending block element tag
30
40
  (innerHtml)=>innerHtml.replace(/(?:<[^>^/]*>)\s*(?:<\/[^>]*>)<\/(div|p|table|thead|tbody|tr|td|th|caption|col|colgroup|ol|ul|li)/g, '</$1'),
41
+ // remove whitespaces before the ending block element tag
31
42
  (innerHTML)=>innerHTML.replace(/\s*<\/(div|p|table|thead|tbody|tr|td|th|caption|col|colgroup|ol|ul|li)/g, '</$1')
32
43
  ];
33
44
  let previous;
34
45
  do {
46
+ // save previous first before doing modifications
35
47
  previous = doc.body.innerHTML;
36
48
  doc.body.innerHTML = replacers.reduce((innerHTML, replacer)=>replacer(innerHTML), doc.body.innerHTML);
37
49
  }while (doc.body.innerHTML !== previous)
50
+ // Removing the div container wrappers from tables
51
+ // The div container including attributes and possible linebreaks inside wil be removed
52
+ // TODO: can be removed with plate >= 20
38
53
  doc.querySelectorAll('table').forEach(removeTableWrappers);
39
54
  return doc.body.innerHTML;
40
55
  };
@@ -1,6 +1,12 @@
1
- export const sanitizeSheets = (doc)=>{
1
+ /**
2
+ * Remove empty spreadsheets columns/rows for performance reasons.
3
+ */ export const sanitizeSheets = (doc)=>{
4
+ // Ensure we are inside a spreadsheet i.e. not pasting
5
+ // a table from within the editor
2
6
  const supported = [
7
+ // Google Sheets
3
8
  'google-sheets-html-origin',
9
+ // MS Excel
4
10
  'meta[content="Excel.Sheet"]',
5
11
  'meta[content*="Microsoft Excel"]'
6
12
  ];
@@ -12,17 +18,23 @@ export const sanitizeSheets = (doc)=>{
12
18
  };
13
19
  const tables = Array.from(doc.querySelectorAll('table'));
14
20
  for (const table of tables){
21
+ // Remove empty columns first!
15
22
  table.querySelectorAll('tr').forEach((row)=>{
16
23
  isEmptyElement(row) && row.remove();
17
24
  });
18
25
  const rows = Array.from(table.querySelectorAll('tr'));
26
+ // CSS :nth-of-type index starts from 1
19
27
  let colIndex = 1;
28
+ // eslint-disable-next-line -- TODO: explain this disable
20
29
  while(true){
21
30
  const cells = rows.map((row)=>row.querySelector(`th:nth-of-type(${colIndex}), td:nth-of-type(${colIndex})`)).filter((cell)=>!!cell);
31
+ // No more columns
22
32
  if (cells.length === 0) {
23
33
  break;
24
34
  }
25
35
  const isEmpty = cells.every((cell)=>isEmptyElement(cell));
36
+ // Don't increment on deletion because columns will be shifted
37
+ // left anyway. Incrementing may result in skipping
26
38
  if (!isEmpty) {
27
39
  colIndex += 1;
28
40
  continue;
@@ -1,16 +1,16 @@
1
- import { assertOutput, jsx } from '../../../test-utils';
1
+ /* eslint-disable react/no-unknown-property */ /** @jsx jsx */ import { assertOutput, jsx } from '../../../test-utils';
2
2
  describe('normalization', ()=>{
3
3
  it('can contain inline entries & hyperlinks', ()=>{
4
- const input = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "some text before", jsx("hinline", {
4
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "some text before", /*#__PURE__*/ jsx("hinline", {
5
5
  type: "Entry",
6
6
  id: "inline-entry"
7
- }), jsx("hlink", {
7
+ }), /*#__PURE__*/ jsx("hlink", {
8
8
  uri: "https://contentful.com"
9
- }), jsx("hlink", {
9
+ }), /*#__PURE__*/ jsx("hlink", {
10
10
  entry: "entry-id"
11
- }), jsx("hlink", {
11
+ }), /*#__PURE__*/ jsx("hlink", {
12
12
  resource: "resource-urn"
13
- }), jsx("hlink", {
13
+ }), /*#__PURE__*/ jsx("hlink", {
14
14
  asset: "asset-id"
15
15
  }), "some text after")));
16
16
  assertOutput({
@@ -19,16 +19,16 @@ describe('normalization', ()=>{
19
19
  });
20
20
  });
21
21
  it('unwraps nested quotes', ()=>{
22
- const input = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "some"), jsx("hquote", null, jsx("hp", null, jsx("htext", {
22
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "some"), /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("htext", {
23
23
  bold: true,
24
24
  italic: true,
25
25
  underline: true
26
- }, "paragraph"))), jsx("hp", null, "text")));
27
- const expected = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "some"), jsx("hp", null, jsx("htext", {
26
+ }, "paragraph"))), /*#__PURE__*/ jsx("hp", null, "text")));
27
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "some"), /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("htext", {
28
28
  bold: true,
29
29
  italic: true,
30
30
  underline: true
31
- }, "paragraph")), jsx("hp", null, "text")), jsx("hp", null, jsx("htext", null)));
31
+ }, "paragraph")), /*#__PURE__*/ jsx("hp", null, "text")), /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("htext", null)));
32
32
  assertOutput({
33
33
  input,
34
34
  expected
@@ -36,37 +36,37 @@ describe('normalization', ()=>{
36
36
  });
37
37
  describe('lifts other invalid children', ()=>{
38
38
  it('block void elements', ()=>{
39
- const input = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "this"), jsx("hembed", {
39
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "this"), /*#__PURE__*/ jsx("hembed", {
40
40
  type: "Asset",
41
41
  id: "1"
42
- }), jsx("hp", null, "is"), jsx("hembed", {
42
+ }), /*#__PURE__*/ jsx("hp", null, "is"), /*#__PURE__*/ jsx("hembed", {
43
43
  type: "Entry",
44
44
  id: "1"
45
- }), jsx("hp", null, "a blockquote"), jsx("hhr", null), jsx("hh1", null, "Heading 1")));
46
- const expected = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "this")), jsx("hembed", {
45
+ }), /*#__PURE__*/ jsx("hp", null, "a blockquote"), /*#__PURE__*/ jsx("hhr", null), /*#__PURE__*/ jsx("hh1", null, "Heading 1")));
46
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "this")), /*#__PURE__*/ jsx("hembed", {
47
47
  type: "Asset",
48
48
  id: "1"
49
- }), jsx("hquote", null, jsx("hp", null, "is")), jsx("hembed", {
49
+ }), /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "is")), /*#__PURE__*/ jsx("hembed", {
50
50
  type: "Entry",
51
51
  id: "1"
52
- }), jsx("hquote", null, jsx("hp", null, "a blockquote")), jsx("hhr", null), jsx("hh1", null, "Heading 1"), jsx("hp", null, jsx("text", null)));
52
+ }), /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "a blockquote")), /*#__PURE__*/ jsx("hhr", null), /*#__PURE__*/ jsx("hh1", null, "Heading 1"), /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("text", null)));
53
53
  assertOutput({
54
54
  input,
55
55
  expected
56
56
  });
57
57
  });
58
58
  it('handles lists', ()=>{
59
- const input = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "some", jsx("hul", null, jsx("hli", null, jsx("hp", null, "list item"))), "text")));
60
- const expected = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "some")), jsx("hul", null, jsx("hli", null, jsx("hp", null, "list item"))), jsx("hquote", null, jsx("hp", null, "text")), jsx("hp", null, jsx("text", null)));
59
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "some", /*#__PURE__*/ jsx("hul", null, /*#__PURE__*/ jsx("hli", null, /*#__PURE__*/ jsx("hp", null, "list item"))), "text")));
60
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "some")), /*#__PURE__*/ jsx("hul", null, /*#__PURE__*/ jsx("hli", null, /*#__PURE__*/ jsx("hp", null, "list item"))), /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "text")), /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("text", null)));
61
61
  assertOutput({
62
62
  input,
63
63
  expected
64
64
  });
65
65
  });
66
66
  it('handles tables', ()=>{
67
- const table = jsx("htable", null, jsx("htr", null, jsx("htd", null, jsx("hp", null, "cell 1")), jsx("htd", null, jsx("hp", null, "cell 2"))));
68
- const input = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "some", table, "text")));
69
- const expected = jsx("editor", null, jsx("hquote", null, jsx("hp", null, "some")), table, jsx("hquote", null, jsx("hp", null, "text")), jsx("hp", null, jsx("text", null)));
67
+ const table = /*#__PURE__*/ jsx("htable", null, /*#__PURE__*/ jsx("htr", null, /*#__PURE__*/ jsx("htd", null, /*#__PURE__*/ jsx("hp", null, "cell 1")), /*#__PURE__*/ jsx("htd", null, /*#__PURE__*/ jsx("hp", null, "cell 2"))));
68
+ const input = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "some", table, "text")));
69
+ const expected = /*#__PURE__*/ jsx("editor", null, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "some")), table, /*#__PURE__*/ jsx("hquote", null, /*#__PURE__*/ jsx("hp", null, "text")), /*#__PURE__*/ jsx("hp", null, /*#__PURE__*/ jsx("text", null)));
70
70
  assertOutput({
71
71
  input,
72
72
  expected