decap-cms-widget-markdown 2.16.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/CHANGELOG.md +820 -0
  2. package/LICENSE +22 -0
  3. package/README.md +9 -0
  4. package/dist/decap-cms-widget-markdown.js +9 -0
  5. package/dist/decap-cms-widget-markdown.js.LICENSE.txt +37 -0
  6. package/dist/decap-cms-widget-markdown.js.map +1 -0
  7. package/dist/esm/MarkdownControl/RawEditor.js +106 -0
  8. package/dist/esm/MarkdownControl/Toolbar.js +216 -0
  9. package/dist/esm/MarkdownControl/ToolbarButton.js +43 -0
  10. package/dist/esm/MarkdownControl/VisualEditor.js +268 -0
  11. package/dist/esm/MarkdownControl/components/Shortcode.js +78 -0
  12. package/dist/esm/MarkdownControl/components/VoidBlock.js +55 -0
  13. package/dist/esm/MarkdownControl/index.js +129 -0
  14. package/dist/esm/MarkdownControl/plugins/BreakToDefaultBlock.js +34 -0
  15. package/dist/esm/MarkdownControl/plugins/CloseBlock.js +36 -0
  16. package/dist/esm/MarkdownControl/plugins/CommandsAndQueries.js +188 -0
  17. package/dist/esm/MarkdownControl/plugins/ForceInsert.js +49 -0
  18. package/dist/esm/MarkdownControl/plugins/Hotkey.js +35 -0
  19. package/dist/esm/MarkdownControl/plugins/LineBreak.js +21 -0
  20. package/dist/esm/MarkdownControl/plugins/Link.js +56 -0
  21. package/dist/esm/MarkdownControl/plugins/blocks/defaultEmptyBlock.js +16 -0
  22. package/dist/esm/MarkdownControl/plugins/blocks/events/keyDown.js +47 -0
  23. package/dist/esm/MarkdownControl/plugins/blocks/events/keyDownBackspace.js +26 -0
  24. package/dist/esm/MarkdownControl/plugins/blocks/events/keyDownEnter.js +28 -0
  25. package/dist/esm/MarkdownControl/plugins/blocks/events/toggleBlock.js +46 -0
  26. package/dist/esm/MarkdownControl/plugins/blocks/locations/areCurrentAndPreviousBlocksOfType.js +20 -0
  27. package/dist/esm/MarkdownControl/plugins/blocks/locations/getListTypeAtCursor.js +16 -0
  28. package/dist/esm/MarkdownControl/plugins/blocks/locations/isCursorAtEndOfParagraph.js +19 -0
  29. package/dist/esm/MarkdownControl/plugins/blocks/locations/isCursorAtStartOfBlockType.js +19 -0
  30. package/dist/esm/MarkdownControl/plugins/blocks/locations/isCursorAtStartOfNonEmptyHeading.js +20 -0
  31. package/dist/esm/MarkdownControl/plugins/blocks/locations/isCursorInBlockType.js +20 -0
  32. package/dist/esm/MarkdownControl/plugins/blocks/locations/isCursorInNonDefaultBlock.js +20 -0
  33. package/dist/esm/MarkdownControl/plugins/blocks/transforms/splitIntoParagraph.js +23 -0
  34. package/dist/esm/MarkdownControl/plugins/blocks/transforms/unwrapIfCursorAtStart.js +36 -0
  35. package/dist/esm/MarkdownControl/plugins/blocks/transforms/wrapListItemsInBlock.js +27 -0
  36. package/dist/esm/MarkdownControl/plugins/blocks/withBlocks.js +19 -0
  37. package/dist/esm/MarkdownControl/plugins/inlines/events/keyDown.js +39 -0
  38. package/dist/esm/MarkdownControl/plugins/inlines/events/keyDownShiftEnter.js +27 -0
  39. package/dist/esm/MarkdownControl/plugins/inlines/events/toggleLink.js +24 -0
  40. package/dist/esm/MarkdownControl/plugins/inlines/events/toggleMark.js +18 -0
  41. package/dist/esm/MarkdownControl/plugins/inlines/locations/isMarkActive.js +17 -0
  42. package/dist/esm/MarkdownControl/plugins/inlines/selectors/getActiveLink.js +15 -0
  43. package/dist/esm/MarkdownControl/plugins/inlines/transforms/unwrapLink.js +14 -0
  44. package/dist/esm/MarkdownControl/plugins/inlines/transforms/wrapLink.js +45 -0
  45. package/dist/esm/MarkdownControl/plugins/inlines/withInlines.js +23 -0
  46. package/dist/esm/MarkdownControl/plugins/lists/events/keyDown.js +38 -0
  47. package/dist/esm/MarkdownControl/plugins/lists/events/keyDownBackspace.js +29 -0
  48. package/dist/esm/MarkdownControl/plugins/lists/events/keyDownEnter.js +44 -0
  49. package/dist/esm/MarkdownControl/plugins/lists/events/keyDownShiftTab.js +32 -0
  50. package/dist/esm/MarkdownControl/plugins/lists/events/keyDownTab.js +57 -0
  51. package/dist/esm/MarkdownControl/plugins/lists/events/toggleListType.js +29 -0
  52. package/dist/esm/MarkdownControl/plugins/lists/locations/isCursorAtListItemStart.js +18 -0
  53. package/dist/esm/MarkdownControl/plugins/lists/locations/isCursorAtNoninitialParagraphStart.js +17 -0
  54. package/dist/esm/MarkdownControl/plugins/lists/locations/isCursorInItemContainingNestedList.js +14 -0
  55. package/dist/esm/MarkdownControl/plugins/lists/locations/isCursorInListItem.js +20 -0
  56. package/dist/esm/MarkdownControl/plugins/lists/locations/isSelectionWithinNoninitialListItem.js +18 -0
  57. package/dist/esm/MarkdownControl/plugins/lists/selectors/getListContainedInListItem.js +18 -0
  58. package/dist/esm/MarkdownControl/plugins/lists/selectors/getLowestAncestorList.js +15 -0
  59. package/dist/esm/MarkdownControl/plugins/lists/selectors/getLowestAncestorQuote.js +15 -0
  60. package/dist/esm/MarkdownControl/plugins/lists/transforms/changeListType.js +24 -0
  61. package/dist/esm/MarkdownControl/plugins/lists/transforms/convertParagraphToListItem.js +27 -0
  62. package/dist/esm/MarkdownControl/plugins/lists/transforms/liftFirstMatchedParent.js +20 -0
  63. package/dist/esm/MarkdownControl/plugins/lists/transforms/liftListItem.js +37 -0
  64. package/dist/esm/MarkdownControl/plugins/lists/transforms/mergeWithPreviousListItem.js +19 -0
  65. package/dist/esm/MarkdownControl/plugins/lists/transforms/moveListToListItem.js +18 -0
  66. package/dist/esm/MarkdownControl/plugins/lists/transforms/splitListItem.js +37 -0
  67. package/dist/esm/MarkdownControl/plugins/lists/transforms/splitToNestedList.js +37 -0
  68. package/dist/esm/MarkdownControl/plugins/lists/transforms/unwrapFirstMatchedParent.js +14 -0
  69. package/dist/esm/MarkdownControl/plugins/lists/transforms/unwrapSelectionFromList.js +25 -0
  70. package/dist/esm/MarkdownControl/plugins/lists/transforms/wrapFirstMatchedParent.js +14 -0
  71. package/dist/esm/MarkdownControl/plugins/lists/transforms/wrapSelectionInList.js +27 -0
  72. package/dist/esm/MarkdownControl/plugins/lists/withLists.js +67 -0
  73. package/dist/esm/MarkdownControl/plugins/matchers/lowestMatchedAncestor.js +13 -0
  74. package/dist/esm/MarkdownControl/plugins/matchers/matchLink.js +14 -0
  75. package/dist/esm/MarkdownControl/plugins/matchers/matchedAncestors.js +15 -0
  76. package/dist/esm/MarkdownControl/plugins/shortcodes/insertShortcode.js +35 -0
  77. package/dist/esm/MarkdownControl/plugins/shortcodes/locations/isCursorInEmptyParagraph.js +20 -0
  78. package/dist/esm/MarkdownControl/plugins/shortcodes/withShortcodes.js +30 -0
  79. package/dist/esm/MarkdownControl/plugins/util.js +18 -0
  80. package/dist/esm/MarkdownControl/renderers.js +326 -0
  81. package/dist/esm/MarkdownPreview.js +47 -0
  82. package/dist/esm/index.js +31 -0
  83. package/dist/esm/regexHelper.js +151 -0
  84. package/dist/esm/schema.js +35 -0
  85. package/dist/esm/serializers/index.js +233 -0
  86. package/dist/esm/serializers/rehypePaperEmoji.js +24 -0
  87. package/dist/esm/serializers/remarkAllowHtmlEntities.js +55 -0
  88. package/dist/esm/serializers/remarkAssertParents.js +89 -0
  89. package/dist/esm/serializers/remarkEscapeMarkdownEntities.js +271 -0
  90. package/dist/esm/serializers/remarkImagesToText.js +41 -0
  91. package/dist/esm/serializers/remarkPaddedLinks.js +127 -0
  92. package/dist/esm/serializers/remarkRehypeShortcodes.js +93 -0
  93. package/dist/esm/serializers/remarkShortcodes.js +123 -0
  94. package/dist/esm/serializers/remarkSlate.js +518 -0
  95. package/dist/esm/serializers/remarkSquashReferences.js +88 -0
  96. package/dist/esm/serializers/remarkStripTrailingBreaks.js +61 -0
  97. package/dist/esm/serializers/remarkWrapHtml.js +24 -0
  98. package/dist/esm/serializers/slateRemark.js +512 -0
  99. package/dist/esm/styles.js +18 -0
  100. package/dist/esm/types.js +10 -0
  101. package/package.json +64 -0
  102. package/src/MarkdownControl/RawEditor.js +100 -0
  103. package/src/MarkdownControl/Toolbar.js +278 -0
  104. package/src/MarkdownControl/ToolbarButton.js +48 -0
  105. package/src/MarkdownControl/VisualEditor.js +293 -0
  106. package/src/MarkdownControl/__tests__/VisualEditor.spec.js +56 -0
  107. package/src/MarkdownControl/__tests__/__snapshots__/parser.spec.js.snap +543 -0
  108. package/src/MarkdownControl/__tests__/parser.spec.js +668 -0
  109. package/src/MarkdownControl/components/Shortcode.js +74 -0
  110. package/src/MarkdownControl/components/VoidBlock.js +58 -0
  111. package/src/MarkdownControl/index.js +125 -0
  112. package/src/MarkdownControl/plugins/BreakToDefaultBlock.js +23 -0
  113. package/src/MarkdownControl/plugins/CloseBlock.js +25 -0
  114. package/src/MarkdownControl/plugins/CommandsAndQueries.js +156 -0
  115. package/src/MarkdownControl/plugins/ForceInsert.js +38 -0
  116. package/src/MarkdownControl/plugins/Hotkey.js +29 -0
  117. package/src/MarkdownControl/plugins/LineBreak.js +15 -0
  118. package/src/MarkdownControl/plugins/Link.js +40 -0
  119. package/src/MarkdownControl/plugins/blocks/defaultEmptyBlock.js +8 -0
  120. package/src/MarkdownControl/plugins/blocks/events/keyDown.js +47 -0
  121. package/src/MarkdownControl/plugins/blocks/events/keyDownBackspace.js +27 -0
  122. package/src/MarkdownControl/plugins/blocks/events/keyDownEnter.js +26 -0
  123. package/src/MarkdownControl/plugins/blocks/events/toggleBlock.js +39 -0
  124. package/src/MarkdownControl/plugins/blocks/locations/areCurrentAndPreviousBlocksOfType.js +15 -0
  125. package/src/MarkdownControl/plugins/blocks/locations/getListTypeAtCursor.js +11 -0
  126. package/src/MarkdownControl/plugins/blocks/locations/isCursorAtEndOfParagraph.js +14 -0
  127. package/src/MarkdownControl/plugins/blocks/locations/isCursorAtStartOfBlockType.js +14 -0
  128. package/src/MarkdownControl/plugins/blocks/locations/isCursorAtStartOfNonEmptyHeading.js +22 -0
  129. package/src/MarkdownControl/plugins/blocks/locations/isCursorInBlockType.js +27 -0
  130. package/src/MarkdownControl/plugins/blocks/locations/isCursorInNonDefaultBlock.js +17 -0
  131. package/src/MarkdownControl/plugins/blocks/transforms/splitIntoParagraph.js +13 -0
  132. package/src/MarkdownControl/plugins/blocks/transforms/unwrapIfCursorAtStart.js +30 -0
  133. package/src/MarkdownControl/plugins/blocks/transforms/wrapListItemsInBlock.js +11 -0
  134. package/src/MarkdownControl/plugins/blocks/withBlocks.js +15 -0
  135. package/src/MarkdownControl/plugins/inlines/events/keyDown.js +38 -0
  136. package/src/MarkdownControl/plugins/inlines/events/keyDownShiftEnter.js +28 -0
  137. package/src/MarkdownControl/plugins/inlines/events/toggleLink.js +17 -0
  138. package/src/MarkdownControl/plugins/inlines/events/toggleMark.js +13 -0
  139. package/src/MarkdownControl/plugins/inlines/locations/isMarkActive.js +11 -0
  140. package/src/MarkdownControl/plugins/inlines/selectors/getActiveLink.js +10 -0
  141. package/src/MarkdownControl/plugins/inlines/transforms/unwrapLink.js +9 -0
  142. package/src/MarkdownControl/plugins/inlines/transforms/wrapLink.js +30 -0
  143. package/src/MarkdownControl/plugins/inlines/withInlines.js +20 -0
  144. package/src/MarkdownControl/plugins/lists/events/keyDown.js +34 -0
  145. package/src/MarkdownControl/plugins/lists/events/keyDownBackspace.js +31 -0
  146. package/src/MarkdownControl/plugins/lists/events/keyDownEnter.js +39 -0
  147. package/src/MarkdownControl/plugins/lists/events/keyDownShiftTab.js +27 -0
  148. package/src/MarkdownControl/plugins/lists/events/keyDownTab.js +55 -0
  149. package/src/MarkdownControl/plugins/lists/events/toggleListType.js +23 -0
  150. package/src/MarkdownControl/plugins/lists/locations/isCursorAtListItemStart.js +13 -0
  151. package/src/MarkdownControl/plugins/lists/locations/isCursorAtNoninitialParagraphStart.js +11 -0
  152. package/src/MarkdownControl/plugins/lists/locations/isCursorInItemContainingNestedList.js +9 -0
  153. package/src/MarkdownControl/plugins/lists/locations/isCursorInListItem.js +21 -0
  154. package/src/MarkdownControl/plugins/lists/locations/isSelectionWithinNoninitialListItem.js +14 -0
  155. package/src/MarkdownControl/plugins/lists/selectors/getListContainedInListItem.js +12 -0
  156. package/src/MarkdownControl/plugins/lists/selectors/getLowestAncestorList.js +11 -0
  157. package/src/MarkdownControl/plugins/lists/selectors/getLowestAncestorQuote.js +11 -0
  158. package/src/MarkdownControl/plugins/lists/transforms/changeListType.js +16 -0
  159. package/src/MarkdownControl/plugins/lists/transforms/convertParagraphToListItem.js +19 -0
  160. package/src/MarkdownControl/plugins/lists/transforms/liftFirstMatchedParent.js +11 -0
  161. package/src/MarkdownControl/plugins/lists/transforms/liftListItem.js +30 -0
  162. package/src/MarkdownControl/plugins/lists/transforms/mergeWithPreviousListItem.js +13 -0
  163. package/src/MarkdownControl/plugins/lists/transforms/moveListToListItem.js +13 -0
  164. package/src/MarkdownControl/plugins/lists/transforms/splitListItem.js +33 -0
  165. package/src/MarkdownControl/plugins/lists/transforms/splitToNestedList.js +33 -0
  166. package/src/MarkdownControl/plugins/lists/transforms/unwrapFirstMatchedParent.js +9 -0
  167. package/src/MarkdownControl/plugins/lists/transforms/unwrapSelectionFromList.js +14 -0
  168. package/src/MarkdownControl/plugins/lists/transforms/wrapFirstMatchedParent.js +9 -0
  169. package/src/MarkdownControl/plugins/lists/transforms/wrapSelectionInList.js +17 -0
  170. package/src/MarkdownControl/plugins/lists/withLists.js +66 -0
  171. package/src/MarkdownControl/plugins/matchers/lowestMatchedAncestor.js +6 -0
  172. package/src/MarkdownControl/plugins/matchers/matchLink.js +9 -0
  173. package/src/MarkdownControl/plugins/matchers/matchedAncestors.js +18 -0
  174. package/src/MarkdownControl/plugins/shortcodes/insertShortcode.js +34 -0
  175. package/src/MarkdownControl/plugins/shortcodes/locations/isCursorInEmptyParagraph.js +17 -0
  176. package/src/MarkdownControl/plugins/shortcodes/withShortcodes.js +26 -0
  177. package/src/MarkdownControl/plugins/util.js +11 -0
  178. package/src/MarkdownControl/renderers.js +352 -0
  179. package/src/MarkdownPreview.js +27 -0
  180. package/src/__tests__/__snapshots__/renderer.spec.js.snap +239 -0
  181. package/src/__tests__/renderer.spec.js +261 -0
  182. package/src/index.js +16 -0
  183. package/src/regexHelper.js +137 -0
  184. package/src/schema.js +35 -0
  185. package/src/serializers/__tests__/__fixtures__/commonmarkExpected.json +625 -0
  186. package/src/serializers/__tests__/__fixtures__/duplicate_marks_github_issue_3280.md +1 -0
  187. package/src/serializers/__tests__/commonmark.spec.js +110 -0
  188. package/src/serializers/__tests__/index.spec.js +52 -0
  189. package/src/serializers/__tests__/remarkAllowHtmlEntities.spec.js +25 -0
  190. package/src/serializers/__tests__/remarkAssertParents.spec.js +171 -0
  191. package/src/serializers/__tests__/remarkEscapeMarkdownEntities.spec.js +84 -0
  192. package/src/serializers/__tests__/remarkPaddedLinks.spec.js +43 -0
  193. package/src/serializers/__tests__/remarkPlugins.spec.js +299 -0
  194. package/src/serializers/__tests__/remarkShortcodes.spec.js +106 -0
  195. package/src/serializers/__tests__/remarkSlate.spec.js +67 -0
  196. package/src/serializers/__tests__/remarkStripTrailingBreaks.spec.js +23 -0
  197. package/src/serializers/__tests__/slate.spec.js +300 -0
  198. package/src/serializers/index.js +226 -0
  199. package/src/serializers/rehypePaperEmoji.js +16 -0
  200. package/src/serializers/remarkAllowHtmlEntities.js +58 -0
  201. package/src/serializers/remarkAssertParents.js +83 -0
  202. package/src/serializers/remarkEscapeMarkdownEntities.js +269 -0
  203. package/src/serializers/remarkImagesToText.js +26 -0
  204. package/src/serializers/remarkPaddedLinks.js +120 -0
  205. package/src/serializers/remarkRehypeShortcodes.js +67 -0
  206. package/src/serializers/remarkShortcodes.js +106 -0
  207. package/src/serializers/remarkSlate.js +425 -0
  208. package/src/serializers/remarkSquashReferences.js +73 -0
  209. package/src/serializers/remarkStripTrailingBreaks.js +56 -0
  210. package/src/serializers/remarkWrapHtml.js +20 -0
  211. package/src/serializers/slateRemark.js +468 -0
  212. package/src/styles.js +13 -0
  213. package/src/types.js +3 -0
  214. package/test-helpers/h.js +32 -0
  215. package/webpack.config.js +3 -0
@@ -0,0 +1,293 @@
1
+ // @refresh reset
2
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import ImmutablePropTypes from 'react-immutable-proptypes';
5
+ import { ClassNames, css as coreCss } from '@emotion/core';
6
+ import { lengths, fonts, zIndex } from 'decap-cms-ui-default';
7
+ import styled from '@emotion/styled';
8
+ import { createEditor, Transforms, Editor as SlateEditor } from 'slate';
9
+ import { Editable, ReactEditor, Slate, withReact } from 'slate-react';
10
+ import { withHistory } from 'slate-history';
11
+ import { fromJS } from 'immutable';
12
+ import { isEqual } from 'lodash';
13
+
14
+ import { editorStyleVars, EditorControlBar } from '../styles';
15
+ import Toolbar from './Toolbar';
16
+ import { Element, Leaf } from './renderers';
17
+ import withLists from './plugins/lists/withLists';
18
+ import withBlocks from './plugins/blocks/withBlocks';
19
+ import withInlines from './plugins/inlines/withInlines';
20
+ import toggleMark from './plugins/inlines/events/toggleMark';
21
+ import toggleLink from './plugins/inlines/events/toggleLink';
22
+ import getActiveLink from './plugins/inlines/selectors/getActiveLink';
23
+ import isMarkActive from './plugins/inlines/locations/isMarkActive';
24
+ import isCursorInBlockType from './plugins/blocks/locations/isCursorInBlockType';
25
+ import { markdownToSlate, slateToMarkdown } from '../serializers';
26
+ import withShortcodes from './plugins/shortcodes/withShortcodes';
27
+ import insertShortcode from './plugins/shortcodes/insertShortcode';
28
+ import defaultEmptyBlock from './plugins/blocks/defaultEmptyBlock';
29
+
30
+ function visualEditorStyles({ minimal }) {
31
+ return `
32
+ position: relative;
33
+ overflow: auto;
34
+ font-family: ${fonts.primary};
35
+ min-height: ${minimal ? 'auto' : lengths.richTextEditorMinHeight};
36
+ border-top-left-radius: 0;
37
+ border-top-right-radius: 0;
38
+ border-top: 0;
39
+ margin-top: -${editorStyleVars.stickyDistanceBottom};
40
+ padding: 0;
41
+ display: flex;
42
+ flex-direction: column;
43
+ z-index: ${zIndex.zIndex100};
44
+ `;
45
+ }
46
+
47
+ const InsertionPoint = styled.div`
48
+ flex: 1 1 auto;
49
+ cursor: text;
50
+ `;
51
+
52
+ export function mergeMediaConfig(editorComponents, field) {
53
+ // merge editor media library config to image components
54
+ if (editorComponents.has('image')) {
55
+ const imageComponent = editorComponents.get('image');
56
+ const fields = imageComponent?.fields;
57
+
58
+ if (fields) {
59
+ imageComponent.fields = fields.update(
60
+ fields.findIndex(f => f.get('widget') === 'image'),
61
+ f => {
62
+ // merge `media_library` config
63
+ if (field.has('media_library')) {
64
+ f = f.set(
65
+ 'media_library',
66
+ field.get('media_library').mergeDeep(f.get('media_library')),
67
+ );
68
+ }
69
+ // merge 'media_folder'
70
+ if (field.has('media_folder') && !f.has('media_folder')) {
71
+ f = f.set('media_folder', field.get('media_folder'));
72
+ }
73
+ // merge 'public_folder'
74
+ if (field.has('public_folder') && !f.has('public_folder')) {
75
+ f = f.set('public_folder', field.get('public_folder'));
76
+ }
77
+ return f;
78
+ },
79
+ );
80
+ }
81
+ }
82
+ }
83
+
84
+ function Editor(props) {
85
+ const {
86
+ onAddAsset,
87
+ getAsset,
88
+ className,
89
+ field,
90
+ isShowModeToggle,
91
+ t,
92
+ isDisabled,
93
+ getEditorComponents,
94
+ getRemarkPlugins,
95
+ onChange,
96
+ } = props;
97
+
98
+ const editor = useMemo(
99
+ () =>
100
+ withReact(withHistory(withShortcodes(withBlocks(withLists(withInlines(createEditor())))))),
101
+ [],
102
+ );
103
+
104
+ const emptyValue = [defaultEmptyBlock()];
105
+ let editorComponents = getEditorComponents();
106
+ const codeBlockComponent = fromJS(editorComponents.find(({ type }) => type === 'code-block'));
107
+
108
+ editorComponents =
109
+ codeBlockComponent || editorComponents.has('code-block')
110
+ ? editorComponents
111
+ : editorComponents.set('code-block', { label: 'Code Block', type: 'code-block' });
112
+
113
+ mergeMediaConfig(editorComponents, field);
114
+
115
+ const [editorValue, setEditorValue] = useState(
116
+ props.value
117
+ ? markdownToSlate(props.value, {
118
+ voidCodeBlock: !!codeBlockComponent,
119
+ remarkPlugins: getRemarkPlugins(),
120
+ })
121
+ : emptyValue,
122
+ );
123
+
124
+ const renderElement = useCallback(
125
+ props => (
126
+ <Element {...props} classNameWrapper={className} codeBlockComponent={codeBlockComponent} />
127
+ ),
128
+ [],
129
+ );
130
+ const renderLeaf = useCallback(props => <Leaf {...props} />, []);
131
+
132
+ useEffect(() => {
133
+ if (props.pendingFocus) {
134
+ ReactEditor.focus(editor);
135
+ }
136
+ }, []);
137
+
138
+ function handleMarkClick(format) {
139
+ ReactEditor.focus(editor);
140
+ toggleMark(editor, format);
141
+ }
142
+
143
+ function handleBlockClick(format) {
144
+ ReactEditor.focus(editor);
145
+ if (format.endsWith('-list')) {
146
+ editor.toggleList(format);
147
+ } else {
148
+ editor.toggleBlock(format);
149
+ }
150
+ }
151
+
152
+ function handleLinkClick() {
153
+ toggleLink(editor, t('editor.editorWidgets.markdown.linkPrompt'));
154
+ ReactEditor.focus(editor);
155
+ }
156
+
157
+ function handleToggleMode() {
158
+ props.onMode('raw');
159
+ }
160
+
161
+ function handleInsertShortcode(pluginConfig) {
162
+ insertShortcode(editor, pluginConfig);
163
+ }
164
+
165
+ function handleKeyDown(event) {
166
+ for (const handler of editor.keyDownHandlers || []) {
167
+ if (handler(event, editor) === false) {
168
+ break;
169
+ }
170
+ }
171
+ ReactEditor.focus(editor);
172
+ }
173
+
174
+ function handleClickBelowDocument() {
175
+ ReactEditor.focus(editor);
176
+ Transforms.select(editor, { path: [0, 0], offset: 0 });
177
+ Transforms.select(editor, SlateEditor.end(editor, []));
178
+ }
179
+ const [toolbarKey, setToolbarKey] = useState(0);
180
+
181
+ function handleChange(newValue) {
182
+ if (!isEqual(newValue, editorValue)) {
183
+ setEditorValue(() => newValue);
184
+ onChange(
185
+ slateToMarkdown(newValue, {
186
+ voidCodeBlock: !!codeBlockComponent,
187
+ remarkPlugins: getRemarkPlugins(),
188
+ }),
189
+ );
190
+ }
191
+ setToolbarKey(prev => prev + 1);
192
+ }
193
+
194
+ function hasMark(format) {
195
+ return isMarkActive(editor, format);
196
+ }
197
+
198
+ function hasInline(format) {
199
+ if (format == 'link') {
200
+ return !!getActiveLink(editor);
201
+ }
202
+ return false;
203
+ }
204
+
205
+ function hasBlock(format) {
206
+ return isCursorInBlockType(editor, format);
207
+ }
208
+ function hasQuote() {
209
+ return isCursorInBlockType(editor, 'quote');
210
+ }
211
+ function hasListItems(type) {
212
+ return isCursorInBlockType(editor, type);
213
+ }
214
+
215
+ return (
216
+ <div
217
+ css={coreCss`
218
+ position: relative;
219
+ `}
220
+ >
221
+ <Slate editor={editor} value={editorValue} onChange={handleChange}>
222
+ <EditorControlBar>
223
+ {
224
+ <Toolbar
225
+ key={toolbarKey}
226
+ onMarkClick={handleMarkClick}
227
+ onBlockClick={handleBlockClick}
228
+ onLinkClick={handleLinkClick}
229
+ onToggleMode={handleToggleMode}
230
+ plugins={editorComponents}
231
+ onSubmit={handleInsertShortcode}
232
+ onAddAsset={onAddAsset}
233
+ getAsset={getAsset}
234
+ buttons={field.get('buttons')}
235
+ editorComponents={field.get('editor_components')}
236
+ hasMark={hasMark}
237
+ hasInline={hasInline}
238
+ hasBlock={hasBlock}
239
+ hasQuote={hasQuote}
240
+ hasListItems={hasListItems}
241
+ isShowModeToggle={isShowModeToggle}
242
+ t={t}
243
+ disabled={isDisabled}
244
+ />
245
+ }
246
+ </EditorControlBar>
247
+ {
248
+ <ClassNames>
249
+ {({ css, cx }) => (
250
+ <div
251
+ className={cx(
252
+ className,
253
+ css`
254
+ ${visualEditorStyles({ minimal: field.get('minimal') })}
255
+ `,
256
+ )}
257
+ >
258
+ {editorValue.length !== 0 && (
259
+ <Editable
260
+ className={css`
261
+ padding: 16px 20px 0;
262
+ `}
263
+ renderElement={renderElement}
264
+ renderLeaf={renderLeaf}
265
+ onKeyDown={handleKeyDown}
266
+ autoFocus={false}
267
+ />
268
+ )}
269
+ <InsertionPoint onClick={handleClickBelowDocument} />
270
+ </div>
271
+ )}
272
+ </ClassNames>
273
+ }
274
+ </Slate>
275
+ </div>
276
+ );
277
+ }
278
+
279
+ Editor.propTypes = {
280
+ onAddAsset: PropTypes.func.isRequired,
281
+ getAsset: PropTypes.func.isRequired,
282
+ onChange: PropTypes.func.isRequired,
283
+ onMode: PropTypes.func.isRequired,
284
+ className: PropTypes.string.isRequired,
285
+ value: PropTypes.string,
286
+ field: ImmutablePropTypes.map.isRequired,
287
+ getEditorComponents: PropTypes.func.isRequired,
288
+ getRemarkPlugins: PropTypes.func.isRequired,
289
+ isShowModeToggle: PropTypes.bool.isRequired,
290
+ t: PropTypes.func.isRequired,
291
+ };
292
+
293
+ export default Editor;
@@ -0,0 +1,56 @@
1
+ import { Map, fromJS } from 'immutable';
2
+
3
+ import { mergeMediaConfig } from '../VisualEditor';
4
+
5
+ describe('VisualEditor', () => {
6
+ describe('mergeMediaConfig', () => {
7
+ it('should copy editor media settings to image component', () => {
8
+ const editorComponents = Map({
9
+ image: {
10
+ id: 'image',
11
+ label: 'Image',
12
+ type: 'shortcode',
13
+ icon: 'exclamation-triangle',
14
+ widget: 'object',
15
+ pattern: {},
16
+ fields: fromJS([
17
+ {
18
+ label: 'Image',
19
+ name: 'image',
20
+ widget: 'image',
21
+ media_library: { allow_multiple: false },
22
+ },
23
+ { label: 'Alt Text', name: 'alt' },
24
+ { label: 'Title', name: 'title' },
25
+ ]),
26
+ },
27
+ });
28
+
29
+ const field = fromJS({
30
+ label: 'Body',
31
+ name: 'body',
32
+ widget: 'markdown',
33
+ media_folder: '/{{media_folder}}/posts/images/widget/body',
34
+ public_folder: '{{public_folder}}/posts/images/widget/body',
35
+ media_library: { config: { max_file_size: 1234 } },
36
+ });
37
+
38
+ mergeMediaConfig(editorComponents, field);
39
+
40
+ expect(editorComponents.get('image').fields).toEqual(
41
+ fromJS([
42
+ {
43
+ label: 'Image',
44
+ name: 'image',
45
+ widget: 'image',
46
+ media_library: { allow_multiple: false, config: { max_file_size: 1234 } },
47
+ media_folder: '/{{media_folder}}/posts/images/widget/body',
48
+ public_folder: '{{public_folder}}/posts/images/widget/body',
49
+ },
50
+ { label: 'Alt Text', name: 'alt' },
51
+ { label: 'Title', name: 'title' },
52
+ ]),
53
+ );
54
+ });
55
+ });
56
+ });