x-star-editor 0.0.8 → 0.1.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 (46) hide show
  1. package/dist/components/Fade.d.ts +9 -0
  2. package/dist/components/Fade.js +38 -0
  3. package/dist/components/FileInput.js +11 -8
  4. package/dist/components/Toolbar.d.ts +9 -5
  5. package/dist/components/Toolbar.js +167 -100
  6. package/dist/index.d.ts +7 -7
  7. package/dist/index.js +4 -4
  8. package/dist/locales/en_US.d.ts +27 -0
  9. package/dist/locales/en_US.js +26 -0
  10. package/dist/locales/index.d.ts +115 -0
  11. package/dist/locales/index.js +41 -0
  12. package/dist/locales/zh_CN.d.ts +27 -0
  13. package/dist/locales/zh_CN.js +26 -0
  14. package/dist/styles/icons/blockquote.svg +18 -0
  15. package/dist/styles/icons/code.svg +18 -1
  16. package/dist/styles/icons/delete.svg +18 -0
  17. package/dist/styles/icons/emphasis.svg +18 -0
  18. package/dist/styles/icons/heading.svg +16 -0
  19. package/dist/styles/icons/image.svg +18 -1
  20. package/dist/styles/icons/inline-code.svg +19 -0
  21. package/dist/styles/icons/inline-math.svg +20 -0
  22. package/dist/styles/icons/link.svg +18 -1
  23. package/dist/styles/icons/math.svg +17 -0
  24. package/dist/styles/icons/redo.svg +18 -0
  25. package/dist/styles/icons/strong.svg +18 -0
  26. package/dist/styles/icons/thematic-break.svg +18 -0
  27. package/dist/styles/icons/undo.svg +18 -0
  28. package/dist/styles/index.css +358 -396
  29. package/dist/utils/container.js +23 -1
  30. package/dist/utils/global.d.ts +1 -1
  31. package/dist/utils/global.js +1 -1
  32. package/dist/utils/history.d.ts +20 -4
  33. package/dist/utils/history.js +89 -72
  34. package/dist/utils/markdown.d.ts +7 -0
  35. package/dist/utils/markdown.js +60 -57
  36. package/dist/{XStarEditor → x-star-editor}/index.d.ts +22 -3
  37. package/dist/{XStarEditor → x-star-editor}/index.js +30 -20
  38. package/dist/{XStarMdEditor → x-star-md-editor}/index.d.ts +31 -3
  39. package/dist/{XStarMdEditor → x-star-md-editor}/index.js +23 -14
  40. package/dist/{XStarMdViewer → x-star-md-viewer}/index.d.ts +12 -0
  41. package/dist/{XStarMdViewer → x-star-md-viewer}/index.js +3 -1
  42. package/package.json +6 -4
  43. package/dist/styles/icons/bold.svg +0 -1
  44. package/dist/styles/icons/code-library.svg +0 -1
  45. package/dist/styles/icons/italic.svg +0 -1
  46. package/dist/styles/icons/strikethrough.svg +0 -1
@@ -49,6 +49,16 @@ export var useContainer = function useContainer() {
49
49
  */
50
50
  var ref = useRef(null);
51
51
 
52
+ /**
53
+ * 是否在遍历时忽略节点及其子节点
54
+ *
55
+ * @param node 节点
56
+ * @returns 是否忽略
57
+ */
58
+ var isIgnore = function isIgnore(node) {
59
+ return node instanceof HTMLElement && node.dataset.ignore !== undefined;
60
+ };
61
+
52
62
  /**
53
63
  * 将 DOM 树规范化
54
64
  *
@@ -59,6 +69,9 @@ export var useContainer = function useContainer() {
59
69
  return;
60
70
  }
61
71
  var traverse = function traverse(node, depth) {
72
+ if (isIgnore(node)) {
73
+ return;
74
+ }
62
75
  if (depth === 2) {
63
76
  var _node$lastChild;
64
77
  // 检查行节点的末尾
@@ -102,6 +115,9 @@ export var useContainer = function useContainer() {
102
115
  }
103
116
  var text = '';
104
117
  var traverse = function traverse(node) {
118
+ if (isIgnore(node)) {
119
+ return;
120
+ }
105
121
  if (node.nodeType === Node.TEXT_NODE) {
106
122
  if (node.nodeValue) {
107
123
  text += node.nodeValue;
@@ -152,7 +168,7 @@ export var useContainer = function useContainer() {
152
168
  }
153
169
  } else {
154
170
  // 节点名称相同,更新属性和子节点
155
- if (newChild instanceof Element && oldChild instanceof Element) {
171
+ if (newChild instanceof HTMLElement && oldChild instanceof HTMLElement) {
156
172
  var _iterator = _createForOfIteratorHelper(oldChild.getAttributeNames()),
157
173
  _step;
158
174
  try {
@@ -234,6 +250,9 @@ export var useContainer = function useContainer() {
234
250
  }
235
251
  var offset = 0;
236
252
  var traverse = function traverse(node) {
253
+ if (isIgnore(node)) {
254
+ return;
255
+ }
237
256
  if (node === targetNode) {
238
257
  if (node.nodeType === Node.TEXT_NODE) {
239
258
  if (node.nodeValue) {
@@ -296,6 +315,9 @@ export var useContainer = function useContainer() {
296
315
  }
297
316
  var offset = targetOffset;
298
317
  var traverse = function traverse(node) {
318
+ if (isIgnore(node)) {
319
+ return;
320
+ }
299
321
  if (node.nodeType === Node.TEXT_NODE) {
300
322
  if (node.nodeValue) {
301
323
  if (offset < node.nodeValue.length || offset === node.nodeValue.length && !node.nodeValue.endsWith("\u200B")) {
@@ -1 +1 @@
1
- export declare const prefix = "x-star-";
1
+ export declare const prefix = "x-star-editor-";
@@ -1 +1 @@
1
- export var prefix = 'x-star-';
1
+ export var prefix = 'x-star-editor-';
@@ -25,12 +25,15 @@ export interface DeleteAction {
25
25
  export interface ToggleAction {
26
26
  type: 'toggle';
27
27
  payload: {
28
+ type: 'blockquote' | 'delete' | 'emphasis' | 'inlineCode' | 'inlineMath' | 'math' | 'strong' | 'thematicBreak';
29
+ } | {
30
+ type: 'code';
31
+ language: string;
32
+ } | {
28
33
  type: 'heading';
29
34
  depth: 1 | 2 | 3 | 4 | 5 | 6;
30
35
  } | {
31
- type: 'thematicBreak' | 'blockquote' | 'code' | 'emphasis' | 'strong' | 'inlineCode' | 'delete' | 'math' | 'inlineMath';
32
- } | {
33
- type: 'link' | 'image';
36
+ type: 'image' | 'link';
34
37
  url: string;
35
38
  description: string;
36
39
  };
@@ -41,6 +44,17 @@ export interface SetAction {
41
44
  payload: State;
42
45
  selection: ContainerSelection;
43
46
  }
47
+ type StateAction = InsertAction | DeleteAction | ToggleAction | SetAction;
48
+ /**
49
+ * 编辑器历史
50
+ */
51
+ interface History {
52
+ states: (State & {
53
+ action: StateAction;
54
+ })[];
55
+ index: number;
56
+ selection: ContainerSelection;
57
+ }
44
58
  export interface UndoAction {
45
59
  type: 'undo';
46
60
  }
@@ -51,9 +65,11 @@ export interface SelectAction {
51
65
  type: 'select';
52
66
  selection: ContainerSelection;
53
67
  }
68
+ type HistoryAction = UndoAction | RedoAction | SelectAction;
54
69
  export declare const useHistory: (initialSourceCode: string) => {
70
+ history: History;
55
71
  sourceCode: string;
56
72
  selection: ContainerSelection;
57
- dispatch: import("react").Dispatch<InsertAction | DeleteAction | ToggleAction | SetAction | UndoAction | RedoAction | SelectAction>;
73
+ dispatch: import("react").Dispatch<StateAction | HistoryAction>;
58
74
  };
59
75
  export {};
@@ -84,26 +84,22 @@ var stateReducer = function stateReducer(_ref, action) {
84
84
  var lineBefore = sourceCode.slice(0, lineStartOffset);
85
85
  var lineAfter = sourceCode.slice(lineEndOffset);
86
86
  switch (action.payload.type) {
87
- case 'heading':
87
+ case 'blockquote':
88
88
  {
89
- var depth = action.payload.depth;
90
89
  var lines = sourceCode.slice(lineStartOffset, lineEndOffset).split('\n');
91
90
  var values = lines.map(function (line) {
92
- return [1, 2, 3, 4, 5, 6].find(function (value) {
93
- return new RegExp("^ {0,3}#{".concat(value, "} +")).test(line);
94
- });
91
+ return /^ {0,3}> */.test(line);
95
92
  });
96
93
  for (var i = 0; i < values.length; i++) {
97
- var value = values[i];
98
- if (value) {
99
- lines[i] = lines[i].replace(new RegExp("^ {0,3}#{".concat(value, "} +")), '');
94
+ if (values[i]) {
95
+ lines[i] = lines[i].replace(/^ {0,3}> */, '');
100
96
  }
101
97
  }
102
98
  if (values.some(function (value) {
103
- return value !== depth;
99
+ return !value;
104
100
  })) {
105
101
  for (var _i = 0; _i < lines.length; _i++) {
106
- lines[_i] = "".concat('#'.repeat(depth), " ").concat(lines[_i]);
102
+ lines[_i] = "> ".concat(lines[_i]);
107
103
  }
108
104
  }
109
105
  var _text = lines.join('\n');
@@ -112,83 +108,92 @@ var stateReducer = function stateReducer(_ref, action) {
112
108
  selection: createSelection(lineStartOffset + _text.length)
113
109
  };
114
110
  }
115
- case 'thematicBreak':
111
+ case 'code':
116
112
  {
113
+ var language = action.payload.language;
117
114
  return {
118
- sourceCode: "".concat(sourceCode.slice(0, lineEndOffset), "\n***\n").concat(lineAfter),
119
- selection: createSelection(lineEndOffset + 5)
115
+ sourceCode: "".concat(sourceCode.slice(0, lineEndOffset), "\n```").concat(language, " showLineNumbers\n\n```\n").concat(lineAfter),
116
+ selection: createSelection(lineEndOffset + language.length + 21)
120
117
  };
121
118
  }
122
- case 'blockquote':
119
+ case 'delete':
120
+ case 'emphasis':
121
+ case 'inlineCode':
122
+ case 'inlineMath':
123
+ case 'strong':
124
+ {
125
+ var type = action.payload.type;
126
+ var delimiters = type === 'emphasis' ? ['*', '_'] : type === 'strong' ? ['**', '__'] : type === 'inlineCode' ? ['`'] : type === 'delete' ? ['~~'] : ['$'];
127
+ var _text2 = sourceCode.slice(startOffset, endOffset);
128
+ for (var _i2 = 0, _delimiters = delimiters; _i2 < _delimiters.length; _i2++) {
129
+ var _delimiter = _delimiters[_i2];
130
+ if (before.endsWith(_delimiter) && after.startsWith(_delimiter)) {
131
+ // 删除分隔文本
132
+ return {
133
+ sourceCode: "".concat(before.slice(0, before.length - _delimiter.length)).concat(_text2).concat(after.slice(_delimiter.length)),
134
+ selection: createSelection(anchorOffset - _delimiter.length, focusOffset - _delimiter.length)
135
+ };
136
+ }
137
+ }
138
+ var delimiter = delimiters[0];
139
+ // 插入分隔文本
140
+ return {
141
+ sourceCode: "".concat(before).concat(delimiter).concat(_text2).concat(delimiter).concat(after),
142
+ selection: createSelection(anchorOffset + delimiter.length, focusOffset + delimiter.length)
143
+ };
144
+ }
145
+ case 'heading':
123
146
  {
147
+ var depth = action.payload.depth;
124
148
  var _lines = sourceCode.slice(lineStartOffset, lineEndOffset).split('\n');
125
149
  var _values = _lines.map(function (line) {
126
- return /^ {0,3}> */.test(line);
150
+ return [1, 2, 3, 4, 5, 6].find(function (value) {
151
+ return new RegExp("^ {0,3}#{".concat(value, "} +")).test(line);
152
+ });
127
153
  });
128
- for (var _i2 = 0; _i2 < _values.length; _i2++) {
129
- if (_values[_i2]) {
130
- _lines[_i2] = _lines[_i2].replace(/^ {0,3}> */, '');
154
+ for (var _i3 = 0; _i3 < _values.length; _i3++) {
155
+ var value = _values[_i3];
156
+ if (value) {
157
+ _lines[_i3] = _lines[_i3].replace(new RegExp("^ {0,3}#{".concat(value, "} +")), '');
131
158
  }
132
159
  }
133
160
  if (_values.some(function (value) {
134
- return !value;
161
+ return value !== depth;
135
162
  })) {
136
- for (var _i3 = 0; _i3 < _lines.length; _i3++) {
137
- _lines[_i3] = "> ".concat(_lines[_i3]);
163
+ for (var _i4 = 0; _i4 < _lines.length; _i4++) {
164
+ _lines[_i4] = "".concat('#'.repeat(depth), " ").concat(_lines[_i4]);
138
165
  }
139
166
  }
140
- var _text2 = _lines.join('\n');
167
+ var _text3 = _lines.join('\n');
141
168
  return {
142
- sourceCode: "".concat(lineBefore).concat(_text2).concat(lineAfter),
143
- selection: createSelection(lineStartOffset + _text2.length)
169
+ sourceCode: "".concat(lineBefore).concat(_text3).concat(lineAfter),
170
+ selection: createSelection(lineStartOffset + _text3.length)
144
171
  };
145
172
  }
146
- case 'code':
147
- case 'math':
173
+ case 'image':
174
+ case 'link':
148
175
  {
149
- var type = action.payload.type;
150
- var delimiter = type === 'code' ? '```' : '$$';
176
+ var _action$payload2 = action.payload,
177
+ _type = _action$payload2.type,
178
+ url = _action$payload2.url,
179
+ description = _action$payload2.description;
151
180
  return {
152
- sourceCode: "".concat(sourceCode.slice(0, lineEndOffset), "\n").concat(delimiter, "\n\n").concat(delimiter, "\n").concat(lineAfter),
153
- selection: createSelection(lineEndOffset + delimiter.length + 2)
181
+ sourceCode: "".concat(before).concat(_type === 'link' ? '' : '!', "[").concat(description, "](").concat(url, ")").concat(after),
182
+ selection: createSelection(startOffset + url.length + description.length + 4 + (_type === 'link' ? 0 : 1))
154
183
  };
155
184
  }
156
- case 'emphasis':
157
- case 'strong':
158
- case 'inlineCode':
159
- case 'delete':
160
- case 'inlineMath':
185
+ case 'math':
161
186
  {
162
- var _type = action.payload.type;
163
- var delimiters = _type === 'emphasis' ? ['*', '_'] : _type === 'strong' ? ['**', '__'] : _type === 'inlineCode' ? ['`'] : _type === 'delete' ? ['~~'] : ['$'];
164
- var _text3 = sourceCode.slice(startOffset, endOffset);
165
- for (var _i4 = 0, _delimiters = delimiters; _i4 < _delimiters.length; _i4++) {
166
- var _delimiter = _delimiters[_i4];
167
- if (before.endsWith(_delimiter) && after.startsWith(_delimiter)) {
168
- // 删除分隔文本
169
- return {
170
- sourceCode: "".concat(before.slice(0, before.length - _delimiter.length)).concat(_text3).concat(after.slice(_delimiter.length)),
171
- selection: createSelection(anchorOffset - _delimiter.length, focusOffset - _delimiter.length)
172
- };
173
- }
174
- }
175
- var _delimiter2 = delimiters[0];
176
- // 插入分隔文本
177
187
  return {
178
- sourceCode: "".concat(before).concat(_delimiter2).concat(_text3).concat(_delimiter2).concat(after),
179
- selection: createSelection(anchorOffset + _delimiter2.length, focusOffset + _delimiter2.length)
188
+ sourceCode: "".concat(sourceCode.slice(0, lineEndOffset), "\n$$\n\n$$\n").concat(lineAfter),
189
+ selection: createSelection(lineEndOffset + 4)
180
190
  };
181
191
  }
182
- case 'link':
183
- case 'image':
192
+ case 'thematicBreak':
184
193
  {
185
- var _action$payload2 = action.payload,
186
- _type2 = _action$payload2.type,
187
- url = _action$payload2.url,
188
- description = _action$payload2.description;
189
194
  return {
190
- sourceCode: "".concat(before).concat(_type2 === 'link' ? '' : '!', "[").concat(description, "](").concat(url, ")").concat(after),
191
- selection: createSelection(startOffset + url.length + description.length + 4 + (_type2 === 'link' ? 0 : 1))
195
+ sourceCode: "".concat(sourceCode.slice(0, lineEndOffset), "\n***\n").concat(lineAfter),
196
+ selection: createSelection(lineEndOffset + 5)
192
197
  };
193
198
  }
194
199
  default:
@@ -237,7 +242,7 @@ var historyReducer = function historyReducer(_ref2, action) {
237
242
  return {
238
243
  states: states,
239
244
  index: index - 1,
240
- selection: states[index].actionSelection
245
+ selection: states[index].action.selection
241
246
  };
242
247
  }
243
248
  case 'redo':
@@ -275,29 +280,41 @@ var historyReducer = function historyReducer(_ref2, action) {
275
280
  };
276
281
  }
277
282
  return {
278
- states: [].concat(_toConsumableArray(states.slice(index < 32 ? 0 : index - 31, index + 1)), [_objectSpread(_objectSpread({}, state), {}, {
279
- actionSelection: action.selection
283
+ states: [].concat(_toConsumableArray(states.slice(index < 100 ? 0 : index - 99, index + 1)), [_objectSpread(_objectSpread({}, state), {}, {
284
+ action: action
280
285
  })]),
281
- index: index < 32 ? index + 1 : 32,
286
+ index: index < 100 ? index + 1 : 100,
282
287
  selection: state.selection
283
288
  };
284
289
  }
285
290
  }
286
291
  };
287
292
  export var useHistory = function useHistory(initialSourceCode) {
288
- var _useReducer = useReducer(historyReducer, {
289
- states: [{
290
- sourceCode: initialSourceCode,
291
- selection: createSelection(0),
292
- actionSelection: createSelection(0)
293
- }],
294
- index: 0,
295
- selection: createSelection(0)
293
+ var _useReducer = useReducer(historyReducer, initialSourceCode, function (text) {
294
+ var action = {
295
+ type: 'insert',
296
+ payload: {
297
+ text: text
298
+ },
299
+ selection: createSelection(0)
300
+ };
301
+ var state = stateReducer({
302
+ sourceCode: '',
303
+ selection: createSelection(0)
304
+ }, action);
305
+ return {
306
+ states: [_objectSpread(_objectSpread({}, state), {}, {
307
+ action: action
308
+ })],
309
+ index: 0,
310
+ selection: state.selection
311
+ };
296
312
  }),
297
313
  _useReducer2 = _slicedToArray(_useReducer, 2),
298
314
  history = _useReducer2[0],
299
315
  dispatch = _useReducer2[1];
300
316
  return {
317
+ history: history,
301
318
  sourceCode: history.states[history.index].sourceCode,
302
319
  selection: history.selection,
303
320
  dispatch: dispatch
@@ -56,4 +56,11 @@ export declare const toHTML: (sourceCode: string) => string;
56
56
  * @returns Markdown 文本
57
57
  */
58
58
  export declare const toMarkdown: (sourceCode: string) => string;
59
+ /**
60
+ * 将 Markdown 文本转成纯文本
61
+ *
62
+ * @param sourceCode Markdown 文本
63
+ * @returns 纯文本
64
+ */
65
+ export declare const toText: (sourceCode: string) => string;
59
66
  export {};
@@ -25,19 +25,23 @@ import remarkMath from 'remark-math';
25
25
  import remarkParse from 'remark-parse';
26
26
  import remarkRehype from 'remark-rehype';
27
27
  import remarkStringify from 'remark-stringify';
28
+ import strip from 'strip-markdown';
28
29
  import { unified } from 'unified';
29
30
  import { prefix } from "./global";
30
31
  export var getDefaultSchema = function getDefaultSchema() {
31
- var _defaultSchema$tagNam, _defaultSchema$attrib, _defaultSchema$attrib2, _defaultSchema$attrib3, _defaultSchema$attrib4, _defaultSchema$attrib5, _defaultSchema$attrib6, _defaultSchema$attrib7, _defaultSchema$attrib8;
32
+ var _defaultSchema$attrib, _defaultSchema$attrib2, _defaultSchema$attrib3, _defaultSchema$attrib4, _defaultSchema$attrib5, _defaultSchema$attrib6, _defaultSchema$attrib7, _defaultSchema$attrib8, _defaultSchema$protoc, _defaultSchema$protoc2, _defaultSchema$tagNam;
32
33
  return _objectSpread(_objectSpread({}, defaultSchema), {}, {
33
- tagNames: [].concat(_toConsumableArray((_defaultSchema$tagNam = defaultSchema.tagNames) !== null && _defaultSchema$tagNam !== void 0 ? _defaultSchema$tagNam : []), ['custom']),
34
34
  attributes: _objectSpread(_objectSpread({}, defaultSchema.attributes), {}, {
35
35
  pre: [].concat(_toConsumableArray((_defaultSchema$attrib = (_defaultSchema$attrib2 = defaultSchema.attributes) === null || _defaultSchema$attrib2 === void 0 ? void 0 : _defaultSchema$attrib2.pre) !== null && _defaultSchema$attrib !== void 0 ? _defaultSchema$attrib : []), ['className', 'style']),
36
36
  code: [].concat(_toConsumableArray((_defaultSchema$attrib3 = (_defaultSchema$attrib4 = defaultSchema.attributes) === null || _defaultSchema$attrib4 === void 0 ? void 0 : _defaultSchema$attrib4.code) !== null && _defaultSchema$attrib3 !== void 0 ? _defaultSchema$attrib3 : []), ['className', 'style']),
37
37
  div: [].concat(_toConsumableArray((_defaultSchema$attrib5 = (_defaultSchema$attrib6 = defaultSchema.attributes) === null || _defaultSchema$attrib6 === void 0 ? void 0 : _defaultSchema$attrib6.div) !== null && _defaultSchema$attrib5 !== void 0 ? _defaultSchema$attrib5 : []), ['className', 'style']),
38
38
  span: [].concat(_toConsumableArray((_defaultSchema$attrib7 = (_defaultSchema$attrib8 = defaultSchema.attributes) === null || _defaultSchema$attrib8 === void 0 ? void 0 : _defaultSchema$attrib8.span) !== null && _defaultSchema$attrib7 !== void 0 ? _defaultSchema$attrib7 : []), ['className', 'style', 'line']),
39
39
  custom: ['meta', 'value']
40
- })
40
+ }),
41
+ protocols: _objectSpread(_objectSpread({}, defaultSchema.protocols), {}, {
42
+ src: [].concat(_toConsumableArray((_defaultSchema$protoc = (_defaultSchema$protoc2 = defaultSchema.protocols) === null || _defaultSchema$protoc2 === void 0 ? void 0 : _defaultSchema$protoc2.src) !== null && _defaultSchema$protoc !== void 0 ? _defaultSchema$protoc : []), ['data'])
43
+ }),
44
+ tagNames: [].concat(_toConsumableArray((_defaultSchema$tagNam = defaultSchema.tagNames) !== null && _defaultSchema$tagNam !== void 0 ? _defaultSchema$tagNam : []), ['custom'])
41
45
  });
42
46
  };
43
47
 
@@ -59,25 +63,7 @@ var processor = unified().use(remarkParse).use(remarkBreaks).use(remarkGfm).use(
59
63
  }
60
64
  }).use(rehypePrism, {
61
65
  ignoreMissing: true
62
- }).use(rehypeKatex).use(rehypeRaw).use(function () {
63
- return function (root) {
64
- var _iterator = _createForOfIteratorHelper(root.children),
65
- _step;
66
- try {
67
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
68
- var node = _step.value;
69
- if ('properties' in node && node.properties) {
70
- var _node$position;
71
- node.properties.line = (_node$position = node.position) === null || _node$position === void 0 ? void 0 : _node$position.start.line;
72
- }
73
- }
74
- } catch (err) {
75
- _iterator.e(err);
76
- } finally {
77
- _iterator.f();
78
- }
79
- };
80
- }).freeze();
66
+ }).use(rehypeKatex).use(rehypeRaw).freeze();
81
67
 
82
68
  /**
83
69
  * Mdast 节点
@@ -93,7 +79,7 @@ export var editorRender = function editorRender(sourceCode) {
93
79
  /**
94
80
  * CSS 类名前缀
95
81
  */
96
- var classNamePrefix = "".concat(prefix, "md-editor-");
82
+ var mdPrefix = "".concat(prefix, "md-");
97
83
 
98
84
  /**
99
85
  * 扫描偏移量,表示已经添加到 DOM 树的文本
@@ -101,7 +87,7 @@ export var editorRender = function editorRender(sourceCode) {
101
87
  var scanOffset = 0;
102
88
 
103
89
  /**
104
- * 遍历 Mdast 树时的栈,保存 Mdast 节点、对应的 DOM 元素、是否为 Mdast 节点的第一个子元素
90
+ * 遍历 Mdast 树时的栈,保存 Mdast 节点、对应的 DOM 元素、为第几个子元素
105
91
  */
106
92
  var stack = [];
107
93
 
@@ -122,47 +108,35 @@ export var editorRender = function editorRender(sourceCode) {
122
108
  * @returns 子节点是否为流内容
123
109
  */
124
110
  var isFlowContent = function isFlowContent(node) {
125
- return node.type === 'blockquote' || node.type === 'listItem' || node.type === 'footnoteDefinition';
111
+ return node.type === 'blockquote' || node.type === 'footnoteDefinition' || node.type === 'listItem';
126
112
  };
127
113
 
128
114
  /**
129
115
  * 将栈中指定索引的 DOM 元素推到对应的父元素中
130
116
  *
131
117
  * @param index 索引
132
- * @param last 是否为 Mdast 节点的最后一个子元素,默认为 `false`
133
118
  */
134
119
  var pushElement = function pushElement(index) {
135
- var last = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
136
- var _stack$index = stack[index],
137
- node = _stack$index.node,
138
- first = _stack$index.first;
120
+ var node = stack[index].node;
139
121
 
140
122
  // 如果节点为流内容,则将样式添加到该行的 `<div>` 元素上,否则添加到该节点的元素上
141
123
  var styleElement = stack[index && !isFlowContent(stack[index - 1].node) ? index : 0].el;
142
- styleElement.classList.add("".concat(classNamePrefix).concat(node.type));
124
+ styleElement.classList.add("".concat(mdPrefix).concat(node.type));
143
125
  if (node.type === 'heading') {
144
- styleElement.classList.add("".concat(classNamePrefix, "heading").concat(node.depth));
145
- } else if (node.type === 'html' || node.type === 'code' || node.type === 'math') {
146
- if (first) {
147
- styleElement.classList.add("".concat(classNamePrefix, "first"));
148
- }
149
- if (last) {
150
- styleElement.classList.add("".concat(classNamePrefix, "last"));
151
- }
126
+ styleElement.classList.add("".concat(mdPrefix, "heading").concat(node.depth));
152
127
  }
153
128
 
154
129
  // 如果索引为 0,则父节点为块级元素,否则为前一个索引的 DOM 元素
155
130
  var parentElement = index ? stack[index - 1].el : block;
156
131
  parentElement.append(stack[index].el);
157
132
  stack[index].el = document.createElement(index ? 'span' : 'div');
158
- stack[index].first = false;
133
+ stack[index].counter++;
159
134
  };
160
135
 
161
136
  /**
162
137
  * 将块级元素推到 DOM 树根元素中
163
138
  */
164
139
  var pushBlock = function pushBlock() {
165
- block.classList.add("".concat(classNamePrefix, "block"));
166
140
  el.append(block);
167
141
  block = document.createElement('div');
168
142
  };
@@ -176,7 +150,7 @@ export var editorRender = function editorRender(sourceCode) {
176
150
  var createDelimiter = function createDelimiter(text) {
177
151
  var temp = document.createElement('span');
178
152
  temp.append(text);
179
- temp.classList.add("".concat(classNamePrefix, "delimiter"));
153
+ temp.classList.add("".concat(mdPrefix, "delimiter"));
180
154
  return temp;
181
155
  };
182
156
 
@@ -235,14 +209,14 @@ export var editorRender = function editorRender(sourceCode) {
235
209
  * @param parentEndOffset 父节点终点偏移量
236
210
  */
237
211
  var getChildren = function getChildren(nodes, parentEndOffset) {
238
- var _iterator2 = _createForOfIteratorHelper(nodes),
239
- _step2;
212
+ var _iterator = _createForOfIteratorHelper(nodes),
213
+ _step;
240
214
  try {
241
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
242
- var _node$position2, _node$position3;
243
- var node = _step2.value;
244
- var startOffset = (_node$position2 = node.position) === null || _node$position2 === void 0 ? void 0 : _node$position2.start.offset;
245
- var endOffset = (_node$position3 = node.position) === null || _node$position3 === void 0 ? void 0 : _node$position3.end.offset;
215
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
216
+ var _node$position, _node$position2;
217
+ var node = _step.value;
218
+ var startOffset = (_node$position = node.position) === null || _node$position === void 0 ? void 0 : _node$position.start.offset;
219
+ var endOffset = (_node$position2 = node.position) === null || _node$position2 === void 0 ? void 0 : _node$position2.end.offset;
246
220
  if (startOffset === undefined || endOffset === undefined) {
247
221
  continue;
248
222
  }
@@ -262,7 +236,7 @@ export var editorRender = function editorRender(sourceCode) {
262
236
  stack.push({
263
237
  node: node,
264
238
  el: document.createElement(stack.length ? 'span' : 'div'),
265
- first: true
239
+ counter: 0
266
240
  });
267
241
  if ('children' in node) {
268
242
  getChildren(node.children, endOffset);
@@ -270,13 +244,13 @@ export var editorRender = function editorRender(sourceCode) {
270
244
  addText(sourceCode.slice(scanOffset, endOffset));
271
245
  }
272
246
  if (stack.length > 1) {
273
- pushElement(stack.length - 1, true);
247
+ pushElement(stack.length - 1);
274
248
  } else {
275
- var _node$position4;
249
+ var _node$position3;
276
250
  // 如果栈大小为 1,说明为块级元素终点
277
251
  stack[0].el.append("\u200B");
278
- pushElement(0, true);
279
- block.setAttribute('line', "".concat((_node$position4 = node.position) === null || _node$position4 === void 0 ? void 0 : _node$position4.start.line));
252
+ pushElement(0);
253
+ block.dataset.line = "".concat((_node$position3 = node.position) === null || _node$position3 === void 0 ? void 0 : _node$position3.start.line);
280
254
  pushBlock();
281
255
  scanOffset++;
282
256
  }
@@ -285,9 +259,9 @@ export var editorRender = function editorRender(sourceCode) {
285
259
 
286
260
  // 添加扫描偏移量与父节点终点偏移量间的分隔文本
287
261
  } catch (err) {
288
- _iterator2.e(err);
262
+ _iterator.e(err);
289
263
  } finally {
290
- _iterator2.f();
264
+ _iterator.f();
291
265
  }
292
266
  addText(sourceCode.slice(scanOffset, parentEndOffset), true);
293
267
  };
@@ -307,7 +281,25 @@ export var editorRender = function editorRender(sourceCode) {
307
281
  * @returns React 虚拟 DOM 树
308
282
  */
309
283
  export var viewerRender = function viewerRender(sourceCode, options) {
310
- return toJsxRuntime(processor().use(rehypeSanitize, options.customSchema).runSync(processor.parse(sourceCode)), {
284
+ return toJsxRuntime(processor().use(rehypeSanitize, options.customSchema).use(function () {
285
+ return function (root) {
286
+ var _iterator2 = _createForOfIteratorHelper(root.children),
287
+ _step2;
288
+ try {
289
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
290
+ var node = _step2.value;
291
+ if ('properties' in node && node.properties) {
292
+ var _node$position4;
293
+ node.properties['data-line'] = (_node$position4 = node.position) === null || _node$position4 === void 0 ? void 0 : _node$position4.start.line;
294
+ }
295
+ }
296
+ } catch (err) {
297
+ _iterator2.e(err);
298
+ } finally {
299
+ _iterator2.f();
300
+ }
301
+ };
302
+ }).runSync(processor.parse(sourceCode)), {
311
303
  Fragment: Fragment,
312
304
  jsx: jsx,
313
305
  jsxs: jsxs,
@@ -347,4 +339,15 @@ var toMarkdownProcessor = unified().use(rehypeRemark).use(remarkGfm).use(remarkB
347
339
  */
348
340
  export var toMarkdown = function toMarkdown(sourceCode) {
349
341
  return toMarkdownProcessor.stringify(toMarkdownProcessor.runSync(toHastProcessor.runSync(toHastProcessor.parse(sourceCode))));
342
+ };
343
+ var toTextProcessor = unified().use(strip).freeze();
344
+
345
+ /**
346
+ * 将 Markdown 文本转成纯文本
347
+ *
348
+ * @param sourceCode Markdown 文本
349
+ * @returns 纯文本
350
+ */
351
+ export var toText = function toText(sourceCode) {
352
+ return toTextProcessor.processSync(sourceCode).toString();
350
353
  };
@@ -1,15 +1,34 @@
1
1
  import React from 'react';
2
- import type { XStarMdEditorHandle, XStarMdEditorProps } from '../XStarMdEditor';
3
- import type { XStarMdViewerHandle, XStarMdViewerProps } from '../XStarMdViewer';
2
+ import type { XStarMdEditorHandle, XStarMdEditorProps } from '../x-star-md-editor';
3
+ import type { XStarMdViewerHandle, XStarMdViewerProps } from '../x-star-md-viewer';
4
4
  export interface XStarEditorHandle {
5
5
  getEditor: () => XStarMdEditorHandle | null;
6
6
  getViewer: () => XStarMdViewerHandle | null;
7
7
  }
8
8
  export interface XStarEditorProps {
9
+ /**
10
+ * 编辑器和浏览器的高度(不包括工具栏)
11
+ */
9
12
  height?: React.CSSProperties['height'];
13
+ /**
14
+ * 语言
15
+ */
16
+ locale?: string;
17
+ /**
18
+ * 初始文本
19
+ */
10
20
  initialValue?: string;
11
- editorProps?: Omit<XStarMdEditorProps, 'initialValue' | 'onChange'>;
21
+ /**
22
+ * 编辑器属性
23
+ */
24
+ editorProps?: Omit<XStarMdEditorProps, 'locale' | 'initialValue' | 'onChange'>;
25
+ /**
26
+ * 浏览器属性
27
+ */
12
28
  viewerProps?: Omit<XStarMdViewerProps, 'value'>;
29
+ /**
30
+ * 文本变化回调函数
31
+ */
13
32
  onChange?: (value: string) => void;
14
33
  }
15
34
  declare const XStarEditor: React.ForwardRefExoticComponent<XStarEditorProps & React.RefAttributes<XStarEditorHandle>>;