x-star-editor 0.2.6 → 0.3.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.
@@ -3,7 +3,7 @@ import classNames from 'classnames';
3
3
  import React, { useEffect, useImperativeHandle, useMemo, useRef } from 'react';
4
4
  import Toolbar, { getDefaultToolbarItemMap, getDefaultToolbarItems } from "../components/Toolbar";
5
5
  import { LocaleProvider } from "../locales";
6
- import { getRange, useContainer } from "../utils/container";
6
+ import { createSelection, getRange, useContainer } from "../utils/container";
7
7
  import { prefix } from "../utils/global";
8
8
  import { composeHandlers, getDefaultKeyboardEventHandlers } from "../utils/handler";
9
9
  import { useHistory } from "../utils/history";
@@ -26,11 +26,14 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
26
26
  sourceCode = _useHistory.sourceCode,
27
27
  selection = _useHistory.selection,
28
28
  dispatch = _useHistory.dispatch;
29
+ var ignoreNext = useRef(false);
29
30
  var initialized = useRef(false);
30
31
 
31
32
  // 将文本同步到容器
32
33
  useEffect(function () {
33
- container.setText(sourceCode);
34
+ if (!ignoreNext.current) {
35
+ container.setText(sourceCode);
36
+ }
34
37
  if (initialized.current) {
35
38
  onChange === null || onChange === void 0 ? void 0 : onChange(sourceCode);
36
39
  }
@@ -38,16 +41,14 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
38
41
 
39
42
  // 将选区同步到容器
40
43
  useEffect(function () {
41
- if (initialized.current) {
44
+ if (!ignoreNext.current && initialized.current) {
42
45
  container.setSelection(selection);
43
46
  }
44
47
  }, [selection]);
45
48
  useEffect(function () {
49
+ ignoreNext.current = false;
46
50
  initialized.current = true;
47
- return function () {
48
- initialized.current = false;
49
- };
50
- }, []);
51
+ }, [sourceCode, selection]);
51
52
  var historyLatest = useRef(history);
52
53
  historyLatest.current = history;
53
54
  var sourceCodeLatest = useRef(sourceCode);
@@ -97,110 +98,41 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
97
98
  e.clipboardData.setData('text/plain', sourceCode.slice(startOffset, endOffset));
98
99
  if (e.type === 'cut') {
99
100
  dispatch({
100
- type: 'delete',
101
+ type: 'insert',
102
+ payload: {
103
+ text: ''
104
+ },
101
105
  selection: selection
102
106
  });
103
107
  }
104
108
  }
105
109
  break;
106
110
  }
107
- case 'paste':
108
- {
109
- e.preventDefault();
110
- if (e.clipboardData.types.includes('text/plain')) {
111
- dispatch({
112
- type: 'insert',
113
- payload: {
114
- text: e.clipboardData.getData('text/plain')
115
- },
116
- selection: selection
117
- });
118
- } else if (e.clipboardData.types.includes('Files')) {
119
- var _file = e.clipboardData.files[0];
120
- onInsertFile === null || onInsertFile === void 0 ? void 0 : onInsertFile(_file, {
121
- description: _file.name,
122
- image: _file.type.startsWith('image/')
123
- });
124
- }
125
- break;
126
- }
127
111
  }
128
112
  };
129
-
130
- /**
131
- * 开始组合时的选区
132
- */
133
- var compositionStartSelection = useRef();
134
-
135
- /**
136
- * 容器同步控制器
137
- */
138
- var syncController = useMemo(function () {
139
- var timer = 0;
140
-
141
- /**
142
- * 将最新的文本和选区同步到容器
143
- */
144
- var sync = function sync() {
145
- if (compositionStartSelection.current) {
146
- var _selection = getSelection();
147
- container.setText(sourceCodeLatest.current);
148
- container.setSelection(_selection);
149
- compositionStartSelection.current = undefined;
150
- }
151
- timer = 0;
152
- };
153
- return {
154
- /**
155
- * 在下个事件循环中同步
156
- */
157
- start: function start() {
158
- if (!timer) {
159
- timer = window.setTimeout(sync);
160
- }
161
- },
162
- /**
163
- * 立即执行下个事件循环中的同步
164
- */
165
- flush: function flush() {
166
- if (timer) {
167
- window.clearTimeout(timer);
168
- sync();
169
- }
170
- }
171
- };
172
- }, []);
173
113
  var compositionEventHandler = function compositionEventHandler(e) {
174
114
  switch (e.type) {
175
115
  case 'compositionend':
176
116
  {
177
- syncController.start();
178
- break;
179
- }
180
- case 'compositionstart':
181
- {
182
- syncController.flush();
183
- compositionStartSelection.current = getSelection();
117
+ var _selection = getSelection();
118
+ container.setText(sourceCodeLatest.current);
119
+ container.setSelection(_selection);
184
120
  break;
185
121
  }
186
122
  }
187
123
  };
188
124
  var dragEventHandler = function dragEventHandler(e) {
125
+ var selection = getSelection();
126
+ var _getRange2 = getRange(selection),
127
+ startOffset = _getRange2.startOffset,
128
+ endOffset = _getRange2.endOffset;
189
129
  switch (e.type) {
190
- case 'drop':
130
+ case 'dragstart':
191
131
  {
192
- var _selection2 = getSelection();
193
- window.setTimeout(function () {
194
- container.normalize();
195
- dispatch({
196
- type: 'set',
197
- payload: {
198
- sourceCode: container.getText(),
199
- selection: getSelection()
200
- },
201
- selection: _selection2
202
- });
203
- });
132
+ if (startOffset < endOffset) {
133
+ e.dataTransfer.clearData();
134
+ e.dataTransfer.setData('text/plain', sourceCode.slice(startOffset, endOffset));
135
+ }
204
136
  break;
205
137
  }
206
138
  }
@@ -214,26 +146,6 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
214
146
  }
215
147
  }
216
148
  };
217
- var formEventHandler = function formEventHandler(e) {
218
- switch (e.type) {
219
- case 'beforeinput':
220
- {
221
- e.preventDefault();
222
- if ('data' in e && typeof e.data === 'string') {
223
- var _compositionStartSele;
224
- dispatch({
225
- type: 'insert',
226
- payload: {
227
- text: e.data
228
- },
229
- selection: (_compositionStartSele = compositionStartSelection.current) !== null && _compositionStartSele !== void 0 ? _compositionStartSele : getSelection()
230
- });
231
- compositionStartSelection.current = undefined;
232
- }
233
- break;
234
- }
235
- }
236
- };
237
149
  var onInsertFileLatest = useRef(onInsertFile);
238
150
  onInsertFileLatest.current = onInsertFile;
239
151
  var options = useMemo(function () {
@@ -250,9 +162,7 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
250
162
  switch (e.type) {
251
163
  case 'keydown':
252
164
  {
253
- if (compositionStartSelection.current) {
254
- e.preventDefault();
255
- } else {
165
+ if (!e.nativeEvent.isComposing) {
256
166
  composeHandlers(options.keyboardEventHandlers)({
257
167
  history: history,
258
168
  sourceCode: sourceCode,
@@ -265,6 +175,174 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
265
175
  }
266
176
  }
267
177
  };
178
+ useEffect(function () {
179
+ var _containerRef$current;
180
+ var listener = function listener(e) {
181
+ switch (e.type) {
182
+ case 'beforeinput':
183
+ {
184
+ var targetRange = e.getTargetRanges()[0];
185
+ if (containerRef.current && targetRange) {
186
+ var startOffset = container.getOffset(containerRef.current, targetRange.startContainer, targetRange.startOffset);
187
+ var endOffset = container.getOffset(containerRef.current, targetRange.endContainer, targetRange.endOffset);
188
+ var _selection2 = createSelection(startOffset, endOffset);
189
+ switch (e.inputType) {
190
+ case 'insertText':
191
+ {
192
+ e.preventDefault();
193
+ if (e.data !== null) {
194
+ dispatch({
195
+ type: 'insert',
196
+ payload: {
197
+ text: e.data
198
+ },
199
+ selection: _selection2
200
+ });
201
+ }
202
+ break;
203
+ }
204
+ case 'insertReplacementText':
205
+ case 'insertFromDrop':
206
+ case 'insertFromPaste':
207
+ {
208
+ var _e$dataTransfer, _e$dataTransfer2;
209
+ e.preventDefault();
210
+ if ((_e$dataTransfer = e.dataTransfer) !== null && _e$dataTransfer !== void 0 && _e$dataTransfer.types.includes('text/plain')) {
211
+ dispatch({
212
+ type: 'insert',
213
+ payload: {
214
+ text: e.dataTransfer.getData('text/plain')
215
+ },
216
+ selection: _selection2
217
+ });
218
+ } else if ((_e$dataTransfer2 = e.dataTransfer) !== null && _e$dataTransfer2 !== void 0 && _e$dataTransfer2.types.includes('Files')) {
219
+ var _file = e.dataTransfer.files[0];
220
+ onInsertFile === null || onInsertFile === void 0 ? void 0 : onInsertFile(_file, {
221
+ description: _file.name,
222
+ image: _file.type.startsWith('image/')
223
+ });
224
+ }
225
+ break;
226
+ }
227
+ case 'insertLineBreak':
228
+ case 'insertParagraph':
229
+ {
230
+ e.preventDefault();
231
+ dispatch({
232
+ type: 'insert',
233
+ payload: {
234
+ text: '\n'
235
+ },
236
+ selection: _selection2
237
+ });
238
+ break;
239
+ }
240
+ case 'insertCompositionText':
241
+ case 'insertFromComposition':
242
+ {
243
+ if (e.data !== null) {
244
+ ignoreNext.current = true;
245
+ dispatch({
246
+ type: 'insert',
247
+ payload: {
248
+ text: e.data
249
+ },
250
+ selection: _selection2
251
+ });
252
+ }
253
+ break;
254
+ }
255
+ case 'deleteWordBackward':
256
+ case 'deleteWordForward':
257
+ case 'deleteContentBackward':
258
+ case 'deleteContentForward':
259
+ {
260
+ e.preventDefault();
261
+ if (startOffset < endOffset) {
262
+ dispatch({
263
+ type: 'insert',
264
+ payload: {
265
+ text: ''
266
+ },
267
+ selection: _selection2
268
+ });
269
+ } else if (e.inputType.endsWith('Backward')) {
270
+ if (startOffset) {
271
+ dispatch({
272
+ type: 'insert',
273
+ payload: {
274
+ text: ''
275
+ },
276
+ selection: createSelection(startOffset - 1, endOffset)
277
+ });
278
+ }
279
+ } else {
280
+ if (endOffset < sourceCodeLatest.current.length - 1) {
281
+ dispatch({
282
+ type: 'insert',
283
+ payload: {
284
+ text: ''
285
+ },
286
+ selection: createSelection(startOffset, endOffset + 1)
287
+ });
288
+ }
289
+ }
290
+ break;
291
+ }
292
+ case 'deleteByDrag':
293
+ case 'deleteCompositionText':
294
+ {
295
+ ignoreNext.current = true;
296
+ dispatch({
297
+ type: 'insert',
298
+ payload: {
299
+ text: ''
300
+ },
301
+ selection: _selection2
302
+ });
303
+ break;
304
+ }
305
+ case 'formatBold':
306
+ {
307
+ e.preventDefault();
308
+ dispatch({
309
+ type: 'toggle',
310
+ payload: {
311
+ type: 'strong'
312
+ },
313
+ selection: _selection2
314
+ });
315
+ break;
316
+ }
317
+ case 'formatItalic':
318
+ {
319
+ e.preventDefault();
320
+ dispatch({
321
+ type: 'toggle',
322
+ payload: {
323
+ type: 'emphasis'
324
+ },
325
+ selection: _selection2
326
+ });
327
+ break;
328
+ }
329
+ default:
330
+ {
331
+ e.preventDefault();
332
+ break;
333
+ }
334
+ }
335
+ }
336
+ break;
337
+ }
338
+ }
339
+ };
340
+ (_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.addEventListener('beforeinput', listener);
341
+ return function () {
342
+ var _containerRef$current2;
343
+ return (_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 ? void 0 : _containerRef$current2.removeEventListener('beforeinput', listener);
344
+ };
345
+ }, []);
268
346
  return /*#__PURE__*/React.createElement(LocaleProvider, {
269
347
  locale: locale
270
348
  }, /*#__PURE__*/React.createElement(Toolbar, {
@@ -280,15 +358,12 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
280
358
  height: height
281
359
  }),
282
360
  contentEditable: true,
283
- onBeforeInput: formEventHandler,
284
361
  onBlur: focusEventHandler,
285
362
  onCompositionEnd: compositionEventHandler,
286
- onCompositionStart: compositionEventHandler,
287
363
  onCopy: clipboardEventHandler,
288
364
  onCut: clipboardEventHandler,
289
- onDrop: dragEventHandler,
290
- onKeyDown: keyboardEventHandler,
291
- onPaste: clipboardEventHandler
365
+ onDragStart: dragEventHandler,
366
+ onKeyDown: keyboardEventHandler
292
367
  }));
293
368
  });
294
369
  if (process.env.NODE_ENV !== 'production') {
@@ -36,6 +36,10 @@ export interface XStarMdViewerProps {
36
36
  * 查看器的高度
37
37
  */
38
38
  height?: React.CSSProperties['height'];
39
+ /**
40
+ * 内置主题
41
+ */
42
+ theme?: string;
39
43
  /**
40
44
  * 文本
41
45
  */
@@ -1,4 +1,5 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
3
  import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
3
4
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
4
5
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
@@ -9,13 +10,11 @@ var workerRaw = "(()=>{var e={470:e=>{\"use strict\";var t=Object.prototype.hasO
9
10
  import { prefix } from "../utils/global";
10
11
  import { composeHandlers } from "../utils/handler";
11
12
  import { getDefaultSchema, postViewerRender, preViewerRender, viewerRender } from "../utils/markdown";
12
- var workerURL = URL.createObjectURL(new Blob([workerRaw], {
13
- type: 'text/javascript'
14
- }));
15
13
  var XStarMdViewer = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
16
14
  var className = _ref.className,
17
15
  style = _ref.style,
18
16
  height = _ref.height,
17
+ theme = _ref.theme,
19
18
  _ref$value = _ref.value,
20
19
  value = _ref$value === void 0 ? '' : _ref$value,
21
20
  plugins = _ref.plugins,
@@ -44,7 +43,9 @@ var XStarMdViewer = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
44
43
  var worker = useRef();
45
44
  useEffect(function () {
46
45
  if (enableWebWorker) {
47
- worker.current = new Worker(workerURL);
46
+ worker.current = new Worker(URL.createObjectURL(new Blob([workerRaw], {
47
+ type: 'text/javascript'
48
+ })));
48
49
  worker.current.addEventListener('message', function (_ref2) {
49
50
  var data = _ref2.data;
50
51
  return setChildren(postViewerRender(data, optionsLatest.current));
@@ -79,7 +80,7 @@ var XStarMdViewer = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
79
80
  }, [value, options]);
80
81
  return /*#__PURE__*/React.createElement("div", {
81
82
  ref: containerRef,
82
- className: classNames("".concat(prefix, "md-viewer"), className),
83
+ className: classNames("".concat(prefix, "md-viewer"), _defineProperty({}, "".concat(prefix, "theme-").concat(theme), theme), className),
83
84
  style: _objectSpread(_objectSpread({}, style), {}, {
84
85
  height: height
85
86
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x-star-editor",
3
- "version": "0.2.6",
3
+ "version": "0.3.0",
4
4
  "description": "An editor developed by turingstar",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",