@pie-lib/editable-html 9.5.13 → 10.0.0-beta.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 (144) hide show
  1. package/CHANGELOG.md +0 -302
  2. package/lib/components.js +116 -0
  3. package/lib/components.js.map +1 -0
  4. package/lib/editor.js +418 -103
  5. package/lib/editor.js.map +1 -1
  6. package/lib/index.js +101 -155
  7. package/lib/index.js.map +1 -1
  8. package/lib/new-serialization.js +320 -0
  9. package/lib/new-serialization.js.map +1 -0
  10. package/lib/old-serialization.js +330 -0
  11. package/lib/parse-html.js +1 -1
  12. package/lib/parse-html.js.map +1 -1
  13. package/lib/plugins/characters/custom-popper.js +1 -1
  14. package/lib/plugins/characters/custom-popper.js.map +1 -1
  15. package/lib/plugins/characters/index.js +21 -19
  16. package/lib/plugins/characters/index.js.map +1 -1
  17. package/lib/plugins/characters/utils.js +1 -1
  18. package/lib/plugins/characters/utils.js.map +1 -1
  19. package/lib/plugins/hotKeys/index.js +67 -0
  20. package/lib/plugins/hotKeys/index.js.map +1 -0
  21. package/lib/plugins/image/alt-dialog.js +1 -6
  22. package/lib/plugins/image/alt-dialog.js.map +1 -1
  23. package/lib/plugins/image/component.js +70 -53
  24. package/lib/plugins/image/component.js.map +1 -1
  25. package/lib/plugins/image/image-toolbar.js +7 -9
  26. package/lib/plugins/image/image-toolbar.js.map +1 -1
  27. package/lib/plugins/image/index.js +83 -27
  28. package/lib/plugins/image/index.js.map +1 -1
  29. package/lib/plugins/image/insert-image-handler.js +72 -33
  30. package/lib/plugins/image/insert-image-handler.js.map +1 -1
  31. package/lib/plugins/index.js +23 -41
  32. package/lib/plugins/index.js.map +1 -1
  33. package/lib/plugins/list/index.js +64 -100
  34. package/lib/plugins/list/index.js.map +1 -1
  35. package/lib/plugins/math/index.js +86 -60
  36. package/lib/plugins/math/index.js.map +1 -1
  37. package/lib/plugins/media/index.js +202 -132
  38. package/lib/plugins/media/index.js.map +1 -1
  39. package/lib/plugins/media/media-dialog.js +17 -16
  40. package/lib/plugins/media/media-dialog.js.map +1 -1
  41. package/lib/plugins/media/media-toolbar.js +3 -3
  42. package/lib/plugins/media/media-toolbar.js.map +1 -1
  43. package/lib/plugins/media/media-wrapper.js +21 -58
  44. package/lib/plugins/media/media-wrapper.js.map +1 -1
  45. package/lib/plugins/respArea/drag-in-the-blank/choice.js +3 -3
  46. package/lib/plugins/respArea/drag-in-the-blank/choice.js.map +1 -1
  47. package/lib/plugins/respArea/drag-in-the-blank/index.js +3 -2
  48. package/lib/plugins/respArea/drag-in-the-blank/index.js.map +1 -1
  49. package/lib/plugins/respArea/explicit-constructed-response/index.js +3 -2
  50. package/lib/plugins/respArea/explicit-constructed-response/index.js.map +1 -1
  51. package/lib/plugins/respArea/icons/index.js +13 -15
  52. package/lib/plugins/respArea/icons/index.js.map +1 -1
  53. package/lib/plugins/respArea/index.js +87 -53
  54. package/lib/plugins/respArea/index.js.map +1 -1
  55. package/lib/plugins/respArea/inline-dropdown/index.js +4 -3
  56. package/lib/plugins/respArea/inline-dropdown/index.js.map +1 -1
  57. package/lib/plugins/respArea/utils.js +17 -20
  58. package/lib/plugins/respArea/utils.js.map +1 -1
  59. package/lib/plugins/table/icons/index.js +1 -1
  60. package/lib/plugins/table/icons/index.js.map +1 -1
  61. package/lib/plugins/table/index.js +381 -212
  62. package/lib/plugins/table/index.js.map +1 -1
  63. package/lib/plugins/table/table-toolbar.js +5 -6
  64. package/lib/plugins/table/table-toolbar.js.map +1 -1
  65. package/lib/plugins/toolbar/default-toolbar.js +55 -11
  66. package/lib/plugins/toolbar/default-toolbar.js.map +1 -1
  67. package/lib/plugins/toolbar/done-button.js +1 -1
  68. package/lib/plugins/toolbar/done-button.js.map +1 -1
  69. package/lib/plugins/toolbar/editor-and-toolbar.js +186 -232
  70. package/lib/plugins/toolbar/editor-and-toolbar.js.map +1 -1
  71. package/lib/plugins/toolbar/index.js +1 -2
  72. package/lib/plugins/toolbar/index.js.map +1 -1
  73. package/lib/plugins/toolbar/toolbar-buttons.js +1 -1
  74. package/lib/plugins/toolbar/toolbar-buttons.js.map +1 -1
  75. package/lib/plugins/toolbar/toolbar.js +253 -239
  76. package/lib/plugins/toolbar/toolbar.js.map +1 -1
  77. package/lib/plugins/utils.js +27 -2
  78. package/lib/plugins/utils.js.map +1 -1
  79. package/lib/serialization.js +1 -1
  80. package/lib/serialization.js.map +1 -1
  81. package/lib/slate-editor.js +302 -0
  82. package/lib/test-serializer.js +189 -0
  83. package/lib/test-serializer.js.map +1 -0
  84. package/lib/theme.js +1 -1
  85. package/lib/theme.js.map +1 -1
  86. package/package.json +18 -14
  87. package/playground/image/data.js +20 -20
  88. package/playground/image/index.html +22 -20
  89. package/playground/image/index.jsx +12 -10
  90. package/playground/index.html +25 -23
  91. package/playground/mathquill/index.html +23 -20
  92. package/playground/mathquill/index.jsx +18 -22
  93. package/playground/prod-test/index.html +24 -20
  94. package/playground/prod-test/index.jsx +5 -3
  95. package/playground/schema-override/data.js +10 -10
  96. package/playground/schema-override/image-plugin.jsx +3 -4
  97. package/playground/schema-override/index.html +21 -19
  98. package/playground/schema-override/index.jsx +13 -14
  99. package/playground/serialization/data.js +10 -10
  100. package/playground/serialization/image-plugin.jsx +3 -4
  101. package/playground/serialization/index.html +22 -20
  102. package/playground/table-examples.html +5 -8
  103. package/playground/webpack.config.js +10 -10
  104. package/src/components.js +135 -0
  105. package/src/editor.jsx +478 -141
  106. package/src/index.jsx +71 -95
  107. package/src/new-serialization.jsx +291 -0
  108. package/src/parse-html.js +1 -1
  109. package/src/plugins/characters/custom-popper.js +7 -7
  110. package/src/plugins/characters/index.jsx +33 -34
  111. package/src/plugins/characters/utils.js +81 -81
  112. package/src/plugins/hotKeys/index.js +54 -0
  113. package/src/plugins/image/alt-dialog.jsx +4 -5
  114. package/src/plugins/image/component.jsx +106 -89
  115. package/src/plugins/image/image-toolbar.jsx +27 -19
  116. package/src/plugins/image/index.jsx +75 -43
  117. package/src/plugins/image/insert-image-handler.js +62 -27
  118. package/src/plugins/index.jsx +23 -41
  119. package/src/plugins/list/index.jsx +70 -95
  120. package/src/plugins/math/index.jsx +102 -82
  121. package/src/plugins/media/index.jsx +159 -124
  122. package/src/plugins/media/media-dialog.js +98 -71
  123. package/src/plugins/media/media-toolbar.jsx +8 -8
  124. package/src/plugins/media/media-wrapper.jsx +29 -30
  125. package/src/plugins/respArea/drag-in-the-blank/choice.jsx +21 -19
  126. package/src/plugins/respArea/drag-in-the-blank/index.jsx +14 -11
  127. package/src/plugins/respArea/explicit-constructed-response/index.jsx +7 -6
  128. package/src/plugins/respArea/icons/index.jsx +11 -14
  129. package/src/plugins/respArea/index.jsx +92 -52
  130. package/src/plugins/respArea/inline-dropdown/index.jsx +9 -8
  131. package/src/plugins/respArea/utils.jsx +26 -35
  132. package/src/plugins/table/icons/index.jsx +17 -11
  133. package/src/plugins/table/index.jsx +288 -231
  134. package/src/plugins/table/table-toolbar.jsx +15 -11
  135. package/src/plugins/toolbar/default-toolbar.jsx +65 -19
  136. package/src/plugins/toolbar/done-button.jsx +4 -4
  137. package/src/plugins/toolbar/editor-and-toolbar.jsx +150 -145
  138. package/src/plugins/toolbar/index.jsx +2 -3
  139. package/src/plugins/toolbar/toolbar-buttons.jsx +11 -11
  140. package/src/plugins/toolbar/toolbar.jsx +244 -221
  141. package/src/plugins/utils.js +21 -4
  142. package/src/serialization.jsx +32 -32
  143. package/src/test-serializer.js +139 -0
  144. package/src/test-serializer.js.rej +20 -0
@@ -1,64 +1,90 @@
1
- import { Data, Inline } from 'slate';
1
+ import React from 'react';
2
+ import debug from 'debug';
3
+ import get from 'lodash/get';
4
+ import { Data, Editor, Inline, Node as SlateNode } from 'slate';
2
5
 
3
6
  import Image from '@material-ui/icons/Image';
4
7
  import ImageComponent from './component';
5
8
  import ImageToolbar from './image-toolbar';
6
9
  import InsertImageHandler from './insert-image-handler';
7
- import React from 'react';
8
- import debug from 'debug';
9
10
 
10
11
  const log = debug('@pie-lib:editable-html:plugins:image');
11
12
 
13
+ const getNodeBy = (editor, callback) => {
14
+ const descendants = SlateNode.descendants(editor, {
15
+ reverse: true
16
+ });
17
+
18
+ for (const [descendant, descendantPath] of descendants) {
19
+ if (callback(descendant, descendantPath)) {
20
+ return [descendant, descendantPath];
21
+ }
22
+ }
23
+ };
24
+
12
25
  export default function ImagePlugin(opts) {
13
26
  const toolbar = opts.insertImageRequested && {
14
27
  icon: <Image />,
15
- onClick: (value, onChange) => {
28
+ onClick: editor => {
16
29
  log('[toolbar] onClick');
17
- const inline = Inline.create({
30
+ const inline = {
18
31
  type: 'image',
19
- isVoid: true,
20
32
  data: {
33
+ newImage: true,
21
34
  loaded: false,
22
- src: undefined,
35
+ src: undefined
23
36
  },
24
- });
37
+ children: [{ text: '' }]
38
+ };
39
+
40
+ editor.insertNode(inline);
41
+
42
+ const [node, nodePath] = getNodeBy(
43
+ editor,
44
+ descendant => descendant.type === 'image' && get(descendant, 'data.newImage')
45
+ );
25
46
 
26
- const change = value.change().insertInline(inline);
27
- onChange(change);
28
- opts.insertImageRequested((getValue) => new InsertImageHandler(inline, getValue, onChange));
47
+ opts.insertImageRequested(() => new InsertImageHandler(node, nodePath, editor));
29
48
  },
30
- supports: (node) => node.object === 'inline' && node.type === 'image',
31
- customToolbar: (node, value, onToolbarDone) => {
32
- const alignment = node.data.get('alignment');
33
- const alt = node.data.get('alt');
34
- const imageLoaded = node.data.get('loaded') !== false;
35
- const onChange = (newValues, done) => {
49
+ customToolbar: (node, value, editor, onToolbarDone) => {
50
+ const alignment = node.data.alignment;
51
+ const alt = node.data.alt;
52
+ const imageLoaded = node.data.loaded !== false;
53
+ const onChange = newValues => {
36
54
  const update = {
37
55
  ...node.data.toObject(),
38
- ...newValues,
56
+ ...newValues
39
57
  };
40
58
 
41
59
  const change = value.change().setNodeByKey(node.key, { data: update });
42
- onToolbarDone(change, done);
60
+ onToolbarDone(change, false);
43
61
  };
44
62
 
45
63
  const Tb = () => (
46
- <ImageToolbar
47
- disableImageAlignmentButtons={opts.disableImageAlignmentButtons}
48
- alt={alt}
49
- imageLoaded={imageLoaded}
50
- alignment={alignment || 'left'}
51
- onChange={onChange}
52
- />
64
+ <ImageToolbar alt={alt} imageLoaded={imageLoaded} alignment={alignment || 'left'} onChange={onChange} />
53
65
  );
54
66
  return Tb;
55
67
  },
56
- showDone: true,
68
+ showDone: true
57
69
  };
58
70
 
59
71
  return {
60
72
  name: 'image',
61
73
  toolbar,
74
+ rules: editor => {
75
+ const { isVoid, isInline } = editor;
76
+
77
+ editor.isVoid = element => {
78
+ return element.type === 'image' ? true : isVoid(element);
79
+ };
80
+
81
+ editor.isInline = element => {
82
+ return element.type === 'image' ? true : isInline(element);
83
+ };
84
+
85
+ return editor;
86
+ },
87
+ supports: node => node.type === 'image',
62
88
  deleteNode: (e, node, value, onChange) => {
63
89
  e.preventDefault();
64
90
  if (opts.onDelete) {
@@ -72,7 +98,9 @@ export default function ImagePlugin(opts) {
72
98
  change = v.change().removeNodeByKey(node.key);
73
99
  } else {
74
100
  log('[error]: ', err);
75
- change = v.change().setNodeByKey(node.key, node.data.merge(Data.create({ deleteStatus: 'failed' })));
101
+ change = v
102
+ .change()
103
+ .setNodeByKey(node.key, node.data.merge(Data.create({ deleteStatus: 'failed' })));
76
104
  }
77
105
  onChange(change);
78
106
  });
@@ -81,8 +109,8 @@ export default function ImagePlugin(opts) {
81
109
  onChange(change);
82
110
  }
83
111
  },
84
- stopReset: (value) => {
85
- const imgPendingInsertion = value.document.findDescendant((n) => {
112
+ stopReset: value => {
113
+ const imgPendingInsertion = value.document.findDescendant(n => {
86
114
  if (n.type !== 'image') {
87
115
  return;
88
116
  }
@@ -99,21 +127,25 @@ export default function ImagePlugin(opts) {
99
127
  onFocus: opts.onFocus,
100
128
  onBlur: opts.onBlur,
101
129
  maxImageWidth: opts.maxImageWidth,
102
- maxImageHeight: opts.maxImageHeight,
130
+ maxImageHeight: opts.maxImageHeight
103
131
  },
104
- props,
132
+ props
133
+ );
134
+ return (
135
+ <ImageComponent {...all}>
136
+ {props.children}
137
+ </ImageComponent>
105
138
  );
106
- return <ImageComponent {...all} />;
107
139
  }
108
140
  },
109
- normalizeNode: (node) => {
141
+ normalizeNode: node => {
110
142
  const textNodeMap = {};
111
143
  const updateNodesArray = [];
112
144
  let index = 0;
113
145
 
114
146
  if (node.object !== 'document') return;
115
147
 
116
- node.findDescendant((d) => {
148
+ node.findDescendant(d => {
117
149
  if (d.object === 'text') {
118
150
  textNodeMap[index] = d;
119
151
  }
@@ -129,12 +161,12 @@ export default function ImagePlugin(opts) {
129
161
 
130
162
  if (!updateNodesArray.length) return;
131
163
 
132
- return (change) => {
164
+ return change => {
133
165
  change.withoutNormalization(() => {
134
- updateNodesArray.forEach((n) => change.insertTextByKey(n.key, 0, ' '));
166
+ updateNodesArray.forEach(n => change.insertTextByKey(n.key, 0, ' '));
135
167
  });
136
168
  };
137
- },
169
+ }
138
170
  };
139
171
  }
140
172
 
@@ -159,8 +191,8 @@ export const serialization = {
159
191
  margin: el.style.margin,
160
192
  justifyContent: el.style.justifyContent,
161
193
  alignment: el.getAttribute('alignment'),
162
- alt: el.getAttribute('alt'),
163
- },
194
+ alt: el.getAttribute('alt')
195
+ }
164
196
  };
165
197
  log('return object: ', out);
166
198
  return out;
@@ -172,7 +204,7 @@ export const serialization = {
172
204
  const src = data.get('src');
173
205
  const width = data.get('width');
174
206
  const height = data.get('height');
175
- const alignment = data.get('alignment') || 'left';
207
+ const alignment = data.get('alignment');
176
208
  const margin = data.get('margin');
177
209
  const justifyContent = data.get('margin');
178
210
  const alt = data.get('alt');
@@ -214,9 +246,9 @@ export const serialization = {
214
246
  src,
215
247
  style,
216
248
  alignment,
217
- alt,
249
+ alt
218
250
  };
219
251
 
220
252
  return <img {...props} />;
221
- },
253
+ }
222
254
  };
@@ -1,32 +1,32 @@
1
- import { Data } from 'slate';
1
+ import omit from 'lodash/omit';
2
2
  import debug from 'debug';
3
3
 
4
4
  const log = debug('@pie-lib:editable-html:image:insert-image-handler');
5
5
 
6
6
  /**
7
7
  * Handles user selection, insertion (or cancellation) of an image into the editor.
8
- * @param {Block} placeholderBlock - a block that has been added to the editor as a place holder for the image
8
+ * @param {Block} placeHolderPath - a block that has been added to the editor as a place holder for the image
9
9
  * @param {Function} getValue - a function to return the value of the editor
10
10
  * @param {Function} onChange - callback to notify changes applied by the handler
11
11
  * @param {Boolean} isPasted - a boolean that keeps track if the file is pasted
12
12
  */
13
13
  class InsertImageHandler {
14
- constructor(placeholderBlock, getValue, onChange, isPasted = false) {
15
- this.placeholderBlock = placeholderBlock;
16
- this.getValue = getValue;
17
- this.onChange = onChange;
14
+ constructor(node, placeHolderPath, editor, isPasted = false) {
15
+ this.node = node;
16
+ this.placeHolderPath = placeHolderPath;
17
+ this.editor = editor;
18
18
  this.isPasted = isPasted;
19
19
  }
20
20
 
21
21
  getPlaceholderInDocument(value) {
22
22
  const { document } = value;
23
- const directChild = document.getChild(this.placeholderBlock.key);
23
+ const directChild = document.getChild(this.placeHolderPath);
24
24
 
25
25
  if (directChild) {
26
26
  return directChild;
27
27
  }
28
28
 
29
- const child = document.getDescendant(this.placeholderBlock.key);
29
+ const child = document.getDescendant(this.placeHolderPath);
30
30
 
31
31
  if (child) {
32
32
  return child;
@@ -38,10 +38,10 @@ class InsertImageHandler {
38
38
 
39
39
  cancel() {
40
40
  log('insert cancelled');
41
- const c = this.getValue()
42
- .change()
43
- .removeNodeByKey(this.placeholderBlock.key);
44
- this.onChange(c);
41
+ this.editor.apply({
42
+ type: 'remove_node',
43
+ path: this.placeHolderPath
44
+ });
45
45
  }
46
46
 
47
47
  done(err, src) {
@@ -50,12 +50,30 @@ class InsertImageHandler {
50
50
  //eslint-disable-next-line
51
51
  console.log(err);
52
52
  } else {
53
- const value = this.getValue();
54
- const child = this.getPlaceholderInDocument(value);
55
- const data = child.data.merge(Data.create({ loaded: true, src, percent: 100 }));
53
+ this.editor.apply({
54
+ type: 'set_node',
55
+ path: this.placeHolderPath,
56
+ properties: {
57
+ data: this.node.data
58
+ },
59
+ newProperties: {
60
+ data: {
61
+ src,
62
+ loaded: true,
63
+ percent: 100
64
+ }
65
+ }
66
+ });
67
+ const newData = {
68
+ ...this.node.data,
69
+ src,
70
+ loaded: true,
71
+ percent: 100
72
+ };
56
73
 
57
- const change = value.change().setNodeByKey(this.placeholderBlock.key, { data });
58
- this.onChange(change);
74
+ this.node = Object.assign({}, this.node, {
75
+ data: omit(newData, 'newImage')
76
+ });
59
77
  }
60
78
  }
61
79
 
@@ -72,23 +90,40 @@ class InsertImageHandler {
72
90
  log('[fileChosen] file: ', file);
73
91
  const reader = new FileReader();
74
92
  reader.onload = () => {
75
- const value = this.getValue();
76
93
  const dataURL = reader.result;
77
- const child = this.getPlaceholderInDocument(value);
78
- const data = child.data.set('src', dataURL);
79
- const change = value.change().setNodeByKey(this.placeholderBlock.key, { data });
80
- this.onChange(change);
94
+
95
+ this.editor.apply({
96
+ type: 'set_node',
97
+ path: this.placeHolderPath,
98
+ properties: {
99
+ data: this.node.data
100
+ },
101
+ newProperties: {
102
+ data: {
103
+ ...this.node.data,
104
+ src: dataURL
105
+ }
106
+ }
107
+ });
108
+ this.node = Object.assign({}, this.node, { data: { src: dataURL } });
81
109
  };
82
110
  reader.readAsDataURL(file);
83
111
  }
84
112
 
85
113
  progress(percent, bytes, total) {
86
114
  log('progress: ', percent, bytes, total);
87
- const value = this.getValue();
88
- const child = this.getPlaceholderInDocument(value);
89
- const data = child.data.set('percent', percent);
90
- const change = value.change().setNodeByKey(this.placeholderBlock.key, { data });
91
- this.onChange(change);
115
+
116
+ this.editor.apply({
117
+ type: 'set_node',
118
+ path: this.placeHolderPath,
119
+ properties: {
120
+ data: this.node.data
121
+ },
122
+ newProperties: {
123
+ data: { ...this.node.data, percent }
124
+ }
125
+ });
126
+ this.node = Object.assign({}, this.node, { data: { percent } });
92
127
  }
93
128
  }
94
129
 
@@ -1,3 +1,6 @@
1
+ import { withHistory } from 'slate-history';
2
+ import { withReact } from 'slate-react';
3
+
1
4
  import Bold from '@material-ui/icons/FormatBold';
2
5
  // import Code from '@material-ui/icons/Code';
3
6
  import BulletedListIcon from '@material-ui/icons/FormatListBulleted';
@@ -17,43 +20,10 @@ import debug from 'debug';
17
20
  import List from './list';
18
21
  import TablePlugin from './table';
19
22
  import RespAreaPlugin from './respArea';
23
+ import MarkHotkey from './hotKeys';
20
24
 
21
25
  const log = debug('@pie-lib:editable-html:plugins');
22
26
 
23
- function MarkHotkey(options) {
24
- const { type, key, icon, tag } = options;
25
-
26
- // Return our "plugin" object, containing the `onKeyDown` handler.
27
- return {
28
- toolbar: {
29
- isMark: true,
30
- type,
31
- icon,
32
- onToggle: (change) => {
33
- log('[onToggleMark] type: ', type);
34
- return change.toggleMark(type);
35
- },
36
- },
37
- renderMark(props) {
38
- if (props.mark.type === type) {
39
- const K = tag || type;
40
- return <K>{props.children}</K>;
41
- }
42
- },
43
- onKeyDown(event, change) {
44
- // Check that the key pressed matches our `key` option.
45
- if (!event.metaKey || event.key != key) return;
46
-
47
- // Prevent the default characters from being inserted.
48
- event.preventDefault();
49
-
50
- // Toggle the mark `type`.
51
- change.toggleMark(type);
52
- return true;
53
- },
54
- };
55
- }
56
-
57
27
  export const ALL_PLUGINS = [
58
28
  'bold',
59
29
  // 'code',
@@ -68,10 +38,10 @@ export const ALL_PLUGINS = [
68
38
  'table',
69
39
  'video',
70
40
  'audio',
71
- 'responseArea',
41
+ 'responseArea'
72
42
  ];
73
43
 
74
- export const DEFAULT_PLUGINS = ALL_PLUGINS.filter((plug) => plug !== 'responseArea');
44
+ export const DEFAULT_PLUGINS = ALL_PLUGINS.filter(plug => plug !== 'responseArea');
75
45
 
76
46
  export const buildPlugins = (activePlugins, opts) => {
77
47
  log('[buildPlugins] opts: ', opts);
@@ -82,7 +52,9 @@ export const buildPlugins = (activePlugins, opts) => {
82
52
  const imagePlugin = opts.image && opts.image.onDelete && ImagePlugin(opts.image);
83
53
  const mathPlugin = MathPlugin(opts.math);
84
54
  const respAreaPlugin =
85
- opts.responseArea && opts.responseArea.type && RespAreaPlugin(opts.responseArea, compact([mathPlugin]));
55
+ opts.responseArea &&
56
+ opts.responseArea.type &&
57
+ RespAreaPlugin(opts.responseArea, compact([mathPlugin]));
86
58
 
87
59
  return compact([
88
60
  addIf('table', TablePlugin(opts.table, compact([imagePlugin, mathPlugin, respAreaPlugin]))),
@@ -95,19 +67,29 @@ export const buildPlugins = (activePlugins, opts) => {
95
67
  key: '~',
96
68
  type: 'strikethrough',
97
69
  icon: <Strikethrough />,
98
- tag: 'del',
99
- }),
70
+ tag: 'del'
71
+ })
100
72
  ),
101
73
  addIf('underline', MarkHotkey({ key: 'u', type: 'underline', icon: <Underline />, tag: 'u' })),
102
74
  addIf('image', imagePlugin),
103
75
  addIf('video', MediaPlugin('video', opts.media)),
104
76
  addIf('audio', MediaPlugin('audio', opts.media)),
105
77
  addIf('math', mathPlugin),
106
- ...opts.languageCharacters.map((config) => addIf('languageCharacters', CharactersPlugin(config))),
78
+ ...opts.languageCharacters.map(config => addIf('languageCharacters', CharactersPlugin(config))),
107
79
  addIf('bulleted-list', List({ key: 'l', type: 'ul_list', icon: <BulletedListIcon /> })),
108
80
  addIf('numbered-list', List({ key: 'n', type: 'ol_list', icon: <NumberedListIcon /> })),
109
81
  ToolbarPlugin(opts.toolbar),
110
82
  SoftBreakPlugin({ shift: true }),
111
- addIf('responseArea', respAreaPlugin),
83
+ addIf('responseArea', respAreaPlugin)
112
84
  ]);
113
85
  };
86
+
87
+ export const withPlugins = (editor, activePlugins) => {
88
+ activePlugins.forEach(plugin => {
89
+ if (typeof plugin.rules === 'function') {
90
+ plugin.rules(editor);
91
+ }
92
+ });
93
+
94
+ return withHistory(withReact(editor));
95
+ };