x-star-editor 0.2.4 → 0.2.6
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.
- package/dist/components/Toolbar.d.ts +3 -3
- package/dist/components/Toolbar.js +53 -9
- package/dist/icons/EditOnly.d.ts +4 -0
- package/dist/icons/EditOnly.js +15 -0
- package/dist/icons/Help.d.ts +4 -0
- package/dist/icons/Help.js +26 -0
- package/dist/icons/Mermaid.d.ts +4 -0
- package/dist/icons/Mermaid.js +15 -0
- package/dist/icons/TaskList.d.ts +4 -0
- package/dist/icons/TaskList.js +24 -0
- package/dist/icons/ViewOnly.d.ts +4 -0
- package/dist/icons/ViewOnly.js +15 -0
- package/dist/index.d.ts +2 -1
- package/dist/locales/en_US.d.ts +5 -0
- package/dist/locales/en_US.js +6 -1
- package/dist/locales/index.d.ts +20 -0
- package/dist/locales/zh_CN.d.ts +5 -0
- package/dist/locales/zh_CN.js +6 -1
- package/dist/utils/container.js +14 -14
- package/dist/utils/history.d.ts +3 -1
- package/dist/utils/history.js +17 -13
- package/dist/utils/markdown.d.ts +3 -11
- package/dist/utils/markdown.js +55 -50
- package/dist/utils/rehype/rehype-line.d.ts +6 -0
- package/dist/utils/rehype/rehype-line.js +17 -0
- package/dist/utils/rehype/rehype-math.d.ts +13 -0
- package/dist/utils/rehype/rehype-math.js +175 -0
- package/dist/utils/rehype/rehype-raw-positions.d.ts +6 -0
- package/dist/utils/rehype/rehype-raw-positions.js +30 -0
- package/dist/x-star-md-editor/index.js +2 -5
- package/dist/x-star-md-viewer/index.js +6 -8
- package/package.json +4 -2
package/dist/utils/history.js
CHANGED
|
@@ -97,10 +97,14 @@ var stateReducer = function stateReducer(_ref, action) {
|
|
|
97
97
|
}
|
|
98
98
|
case 'code':
|
|
99
99
|
{
|
|
100
|
-
var
|
|
100
|
+
var _action$payload2 = action.payload,
|
|
101
|
+
lang = _action$payload2.lang,
|
|
102
|
+
value = _action$payload2.value,
|
|
103
|
+
showLineNumbers = _action$payload2.showLineNumbers;
|
|
104
|
+
var _startOffset = lineEndOffset + lang.length + (showLineNumbers ? 21 : 5);
|
|
101
105
|
return {
|
|
102
|
-
sourceCode: "".concat(sourceCode.slice(0, lineEndOffset), "\n```").concat(
|
|
103
|
-
selection: createSelection(
|
|
106
|
+
sourceCode: "".concat(sourceCode.slice(0, lineEndOffset), "\n```").concat(lang).concat(showLineNumbers ? ' showLineNumbers' : '', "\n").concat(value, "\n```\n").concat(lineAfter),
|
|
107
|
+
selection: createSelection(_startOffset, _startOffset + value.length)
|
|
104
108
|
};
|
|
105
109
|
}
|
|
106
110
|
case 'delete':
|
|
@@ -139,9 +143,9 @@ var stateReducer = function stateReducer(_ref, action) {
|
|
|
139
143
|
});
|
|
140
144
|
});
|
|
141
145
|
for (var _i3 = 0; _i3 < _values.length; _i3++) {
|
|
142
|
-
var
|
|
143
|
-
if (
|
|
144
|
-
_lines[_i3] = _lines[_i3].replace(new RegExp("^ {0,3}#{".concat(
|
|
146
|
+
var _value = _values[_i3];
|
|
147
|
+
if (_value) {
|
|
148
|
+
_lines[_i3] = _lines[_i3].replace(new RegExp("^ {0,3}#{".concat(_value, "} +")), '');
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
if (_values.some(function (value) {
|
|
@@ -160,10 +164,10 @@ var stateReducer = function stateReducer(_ref, action) {
|
|
|
160
164
|
case 'image':
|
|
161
165
|
case 'link':
|
|
162
166
|
{
|
|
163
|
-
var _action$
|
|
164
|
-
_type = _action$
|
|
165
|
-
url = _action$
|
|
166
|
-
description = _action$
|
|
167
|
+
var _action$payload3 = action.payload,
|
|
168
|
+
_type = _action$payload3.type,
|
|
169
|
+
url = _action$payload3.url,
|
|
170
|
+
description = _action$payload3.description;
|
|
167
171
|
return {
|
|
168
172
|
sourceCode: "".concat(before).concat(_type === 'link' ? '' : '!', "[").concat(description, "](").concat(url, ")").concat(after),
|
|
169
173
|
selection: createSelection(startOffset + url.length + description.length + 4 + (_type === 'link' ? 0 : 1))
|
|
@@ -192,9 +196,9 @@ var stateReducer = function stateReducer(_ref, action) {
|
|
|
192
196
|
}
|
|
193
197
|
case 'set':
|
|
194
198
|
{
|
|
195
|
-
var _action$
|
|
196
|
-
_sourceCode = _action$
|
|
197
|
-
selection = _action$
|
|
199
|
+
var _action$payload4 = action.payload,
|
|
200
|
+
_sourceCode = _action$payload4.sourceCode,
|
|
201
|
+
selection = _action$payload4.selection;
|
|
198
202
|
return {
|
|
199
203
|
sourceCode: _sourceCode.replace(/\r\n?/g, '\n'),
|
|
200
204
|
selection: selection
|
package/dist/utils/markdown.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import type { Root as HastRoot } from 'hast';
|
|
2
3
|
import { defaultSchema } from 'rehype-sanitize';
|
|
3
4
|
import type { ViewerOptions } from '../x-star-md-viewer';
|
|
4
5
|
/**
|
|
@@ -8,21 +9,13 @@ import type { ViewerOptions } from '../x-star-md-viewer';
|
|
|
8
9
|
* @returns DOM 树
|
|
9
10
|
*/
|
|
10
11
|
export declare const editorRender: (sourceCode: string) => HTMLDivElement;
|
|
11
|
-
/**
|
|
12
|
-
* 将 Mdast 树转成 Hast 树的处理器
|
|
13
|
-
*/
|
|
14
|
-
declare const toHastProcessor: import("unified").FrozenProcessor<import("mdast").Root, import("hast").Root, import("hast").Root, void>;
|
|
15
|
-
/**
|
|
16
|
-
* Hast 根节点
|
|
17
|
-
*/
|
|
18
|
-
export type HastRoot = Awaited<ReturnType<(typeof toHastProcessor)['run']>>;
|
|
19
12
|
/**
|
|
20
13
|
* 将 Markdown 文本转成 Hast 树
|
|
21
14
|
*
|
|
22
15
|
* @param sourceCode Markdown 文本
|
|
23
16
|
* @returns Hast 树
|
|
24
17
|
*/
|
|
25
|
-
export declare const preViewerRender: (sourceCode: string) => Promise<
|
|
18
|
+
export declare const preViewerRender: (sourceCode: string) => Promise<HastRoot>;
|
|
26
19
|
/**
|
|
27
20
|
* 过滤模式
|
|
28
21
|
*/
|
|
@@ -35,7 +28,7 @@ export declare const getDefaultSchema: () => Schema;
|
|
|
35
28
|
* @param schema 过滤模式
|
|
36
29
|
* @returns 新的 Hast 树
|
|
37
30
|
*/
|
|
38
|
-
export declare const viewerRender: (root: HastRoot, schema: Schema) =>
|
|
31
|
+
export declare const viewerRender: (root: HastRoot, schema: Schema) => HastRoot;
|
|
39
32
|
/**
|
|
40
33
|
* 将 Hast 树映射到 React 虚拟 DOM 树
|
|
41
34
|
*
|
|
@@ -65,4 +58,3 @@ export declare const toMarkdown: (sourceCode: string) => string;
|
|
|
65
58
|
* @returns 纯文本
|
|
66
59
|
*/
|
|
67
60
|
export declare const toText: (sourceCode: string) => string;
|
|
68
|
-
export {};
|
package/dist/utils/markdown.js
CHANGED
|
@@ -5,12 +5,13 @@ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
|
5
5
|
import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
|
|
6
6
|
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
7
7
|
import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
|
|
8
|
+
import { toText as hastToText } from 'hast-util-to-text';
|
|
8
9
|
import { Fragment, jsx, jsxs } from 'react/jsx-runtime';
|
|
9
10
|
import rehypeKatex from 'rehype-katex';
|
|
10
11
|
import rehypeMermaid from 'rehype-mermaidjs';
|
|
11
12
|
import rehypePrism from 'rehype-prism-plus';
|
|
12
13
|
import rehypeRaw from 'rehype-raw';
|
|
13
|
-
import rehypeRemark from 'rehype-remark';
|
|
14
|
+
import rehypeRemark, { defaultHandlers } from 'rehype-remark';
|
|
14
15
|
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
|
|
15
16
|
import rehypeStringify from 'rehype-stringify';
|
|
16
17
|
import remarkBreaks from 'remark-breaks';
|
|
@@ -22,16 +23,15 @@ import remarkStringify from 'remark-stringify';
|
|
|
22
23
|
import strip from 'strip-markdown';
|
|
23
24
|
import { unified } from 'unified';
|
|
24
25
|
import { prefix } from "./global";
|
|
26
|
+
import rehypeLine from "./rehype/rehype-line";
|
|
27
|
+
import rehypeMath, { isMathNode } from "./rehype/rehype-math";
|
|
28
|
+
import rehypeRawPositions from "./rehype/rehype-raw-positions";
|
|
25
29
|
|
|
26
30
|
/**
|
|
27
31
|
* 将 Markdown 文本解析为 Mdast 树的处理器
|
|
28
32
|
*/
|
|
29
33
|
var toMdastProcessor = unified().use(remarkParse).use(remarkGfm).use(remarkMath).freeze();
|
|
30
34
|
|
|
31
|
-
/**
|
|
32
|
-
* Mdast 根节点
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
35
|
/**
|
|
36
36
|
* 带缓存的解析函数
|
|
37
37
|
*
|
|
@@ -46,10 +46,6 @@ var cachedParse = function () {
|
|
|
46
46
|
};
|
|
47
47
|
}();
|
|
48
48
|
|
|
49
|
-
/**
|
|
50
|
-
* Mdast 节点
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
49
|
/**
|
|
54
50
|
* 将 Markdown 文本映射到 DOM 树,第一层为 `<div>` 块元素,第二层为 `<div>` 行元素,之后均为 `<span>` 元素
|
|
55
51
|
*
|
|
@@ -231,6 +227,7 @@ export var editorRender = function editorRender(sourceCode) {
|
|
|
231
227
|
// 如果栈大小为 1,说明为块级元素终点
|
|
232
228
|
stack[0].element.append("\u200B");
|
|
233
229
|
pushElement(0);
|
|
230
|
+
// 记录行号,用于同步滚动
|
|
234
231
|
block.dataset.line = "".concat((_node$position3 = node.position) === null || _node$position3 === void 0 ? void 0 : _node$position3.start.line);
|
|
235
232
|
pushBlock();
|
|
236
233
|
scanOffset++;
|
|
@@ -278,11 +275,7 @@ var toHastProcessor = unified().use(remarkBreaks).use(remarkRehype, {
|
|
|
278
275
|
strategy: 'img-svg'
|
|
279
276
|
}).use(rehypePrism, {
|
|
280
277
|
ignoreMissing: true
|
|
281
|
-
}).
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Hast 根节点
|
|
285
|
-
*/
|
|
278
|
+
}).freeze();
|
|
286
279
|
|
|
287
280
|
/**
|
|
288
281
|
* 将 Markdown 文本转成 Hast 树
|
|
@@ -341,25 +334,7 @@ export var getDefaultSchema = function getDefaultSchema() {
|
|
|
341
334
|
* @returns 新的 Hast 树
|
|
342
335
|
*/
|
|
343
336
|
export var viewerRender = function viewerRender(root, schema) {
|
|
344
|
-
return unified().use(rehypeRaw).use(rehypeSanitize, schema).use(
|
|
345
|
-
return function (root) {
|
|
346
|
-
var _iterator2 = _createForOfIteratorHelper(root.children),
|
|
347
|
-
_step2;
|
|
348
|
-
try {
|
|
349
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
350
|
-
var node = _step2.value;
|
|
351
|
-
if ('properties' in node && node.properties) {
|
|
352
|
-
var _node$position4;
|
|
353
|
-
node.properties['data-line'] = (_node$position4 = node.position) === null || _node$position4 === void 0 ? void 0 : _node$position4.start.line;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
} catch (err) {
|
|
357
|
-
_iterator2.e(err);
|
|
358
|
-
} finally {
|
|
359
|
-
_iterator2.f();
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
}).runSync(root);
|
|
337
|
+
return unified().use(rehypeRawPositions).use(rehypeRaw).use(rehypeMath).use(rehypeSanitize, schema).use(rehypeLine).runSync(root);
|
|
363
338
|
};
|
|
364
339
|
|
|
365
340
|
/**
|
|
@@ -370,25 +345,35 @@ export var viewerRender = function viewerRender(root, schema) {
|
|
|
370
345
|
* @returns React 虚拟 DOM 树
|
|
371
346
|
*/
|
|
372
347
|
export var postViewerRender = function postViewerRender(root, options) {
|
|
373
|
-
|
|
348
|
+
var components = _objectSpread(_objectSpread({}, options.customHTMLElements), {}, {
|
|
349
|
+
custom: function custom(props) {
|
|
350
|
+
var _options$customBlocks;
|
|
351
|
+
return jsx((_options$customBlocks = options.customBlocks[props.meta]) !== null && _options$customBlocks !== void 0 ? _options$customBlocks : 'div', {
|
|
352
|
+
children: props.value
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
return toJsxRuntime(unified().use(rehypeKatex).runSync(root), {
|
|
374
357
|
Fragment: Fragment,
|
|
375
358
|
jsx: jsx,
|
|
376
359
|
jsxs: jsxs,
|
|
377
|
-
components:
|
|
378
|
-
custom: function custom(_ref2) {
|
|
379
|
-
var _options$customBlocks;
|
|
380
|
-
var meta = _ref2.meta,
|
|
381
|
-
value = _ref2.value;
|
|
382
|
-
return jsx((_options$customBlocks = options.customBlocks[meta]) !== null && _options$customBlocks !== void 0 ? _options$customBlocks : 'div', {
|
|
383
|
-
children: value
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
})
|
|
360
|
+
components: components
|
|
387
361
|
});
|
|
388
362
|
};
|
|
389
|
-
var toHTMLProcessor = unified().use(remarkParse).use(remarkGfm).use(remarkRehype, {
|
|
390
|
-
allowDangerousHtml: true
|
|
391
|
-
|
|
363
|
+
var toHTMLProcessor = unified().use(remarkParse).use(remarkGfm).use(remarkMath).use(remarkRehype, {
|
|
364
|
+
allowDangerousHtml: true,
|
|
365
|
+
handlers: {
|
|
366
|
+
math: function math(h, node) {
|
|
367
|
+
return (
|
|
368
|
+
// 如果 Math 节点的 `meta` 属性不为空,则视为自定义块
|
|
369
|
+
node.meta ? h(node.position, 'custom', {
|
|
370
|
+
meta: node.meta,
|
|
371
|
+
value: node.value
|
|
372
|
+
}) : h(node, 'div')
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}).use(rehypeRawPositions).use(rehypeRaw).use(rehypeMath).use(rehypeStringify).freeze();
|
|
392
377
|
|
|
393
378
|
/**
|
|
394
379
|
* 将 Markdown 文本转成 HTML 文本
|
|
@@ -400,8 +385,21 @@ export var toHTML = function toHTML(sourceCode) {
|
|
|
400
385
|
return toHTMLProcessor.processSync(sourceCode).toString();
|
|
401
386
|
};
|
|
402
387
|
var toMarkdownProcessor = unified().use(rehypeRemark, {
|
|
403
|
-
newlines: true
|
|
404
|
-
|
|
388
|
+
newlines: true,
|
|
389
|
+
handlers: {
|
|
390
|
+
div: function div(h, node) {
|
|
391
|
+
return isMathNode(node) ? h(node, 'math', hastToText(node)) : defaultHandlers.div(h, node);
|
|
392
|
+
},
|
|
393
|
+
span: function span(h, node) {
|
|
394
|
+
return isMathNode(node) ? h(node, 'inlineMath', hastToText(node)) : defaultHandlers.span(h, node);
|
|
395
|
+
},
|
|
396
|
+
custom: function custom(h, node) {
|
|
397
|
+
return h(node, 'math', {
|
|
398
|
+
meta: node.properties.meta
|
|
399
|
+
}, node.properties.value);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}).use(remarkMath).use(remarkGfm).use(remarkStringify).freeze();
|
|
405
403
|
|
|
406
404
|
/**
|
|
407
405
|
* 将带有 HTML 的 Markdown 文本转成 Markdown 文本
|
|
@@ -412,7 +410,14 @@ var toMarkdownProcessor = unified().use(rehypeRemark, {
|
|
|
412
410
|
export var toMarkdown = function toMarkdown(sourceCode) {
|
|
413
411
|
return toMarkdownProcessor.stringify(toMarkdownProcessor.runSync(toHTMLProcessor.runSync(toHTMLProcessor.parse(sourceCode))));
|
|
414
412
|
};
|
|
415
|
-
var toTextProcessor = unified().use(remarkParse).use(remarkGfm).use(
|
|
413
|
+
var toTextProcessor = unified().use(remarkParse).use(remarkGfm).use(remarkMath).use(strip, {
|
|
414
|
+
remove: ['math', ['inlineMath', function (node) {
|
|
415
|
+
return {
|
|
416
|
+
type: 'text',
|
|
417
|
+
value: node.value
|
|
418
|
+
};
|
|
419
|
+
}]]
|
|
420
|
+
}).use(remarkStringify).freeze();
|
|
416
421
|
|
|
417
422
|
/**
|
|
418
423
|
* 将 Markdown 文本转成纯文本
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SKIP, visit } from 'unist-util-visit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 为第一层 Hast 节点添加行号属性
|
|
5
|
+
*/
|
|
6
|
+
var rehypeLine = function rehypeLine() {
|
|
7
|
+
return function (root) {
|
|
8
|
+
return visit(root, 'element', function (node) {
|
|
9
|
+
var _node$properties, _node$position;
|
|
10
|
+
(_node$properties = node.properties) !== null && _node$properties !== void 0 ? _node$properties : node.properties = {};
|
|
11
|
+
// 记录行号,用于同步滚动
|
|
12
|
+
node.properties['data-line'] = (_node$position = node.position) === null || _node$position === void 0 ? void 0 : _node$position.start.line;
|
|
13
|
+
return SKIP;
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export default rehypeLine;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RootContent as HastNode, Root as HastRoot } from 'hast';
|
|
2
|
+
/**
|
|
3
|
+
* 判断一个 Hast 节点是否属于行内公式或公式块
|
|
4
|
+
*
|
|
5
|
+
* @param node Hast 节点
|
|
6
|
+
* @returns 是否属于行内公式或公式块
|
|
7
|
+
*/
|
|
8
|
+
export declare const isMathNode: (node: HastRoot | HastNode) => boolean | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* 解析属于 Raw 节点的文本中的数学公式
|
|
11
|
+
*/
|
|
12
|
+
declare const rehypeMath: () => (root: HastRoot) => void;
|
|
13
|
+
export default rehypeMath;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
2
|
+
import { EXIT, SKIP, visit } from 'unist-util-visit';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 判断一个 Hast 节点是否属于行内代码或代码块
|
|
6
|
+
*
|
|
7
|
+
* @param node Hast 节点
|
|
8
|
+
* @returns 是否属于行内代码或代码块
|
|
9
|
+
*/
|
|
10
|
+
var isCodeNode = function isCodeNode(node) {
|
|
11
|
+
return node.type === 'element' && node.tagName === 'code';
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 判断一个 Hast 节点是否属于行内公式或公式块
|
|
16
|
+
*
|
|
17
|
+
* @param node Hast 节点
|
|
18
|
+
* @returns 是否属于行内公式或公式块
|
|
19
|
+
*/
|
|
20
|
+
export var isMathNode = function isMathNode(node) {
|
|
21
|
+
var _node$properties, _node$properties2;
|
|
22
|
+
return node.type === 'element' && Array.isArray((_node$properties = node.properties) === null || _node$properties === void 0 ? void 0 : _node$properties.className) && ((_node$properties2 = node.properties) === null || _node$properties2 === void 0 ? void 0 : _node$properties2.className.includes('math'));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 解析文本中的公式
|
|
27
|
+
*
|
|
28
|
+
* @param text 文本
|
|
29
|
+
* @returns Hast 节点
|
|
30
|
+
*/
|
|
31
|
+
var parseMath = function parseMath(text) {
|
|
32
|
+
var result = [];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 扫描文本
|
|
36
|
+
*/
|
|
37
|
+
var scan = '';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 是否转义
|
|
41
|
+
*/
|
|
42
|
+
var escape = false;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 连续 `$` 的数量
|
|
46
|
+
*/
|
|
47
|
+
var level = 0;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 是否在行内公式中
|
|
51
|
+
*/
|
|
52
|
+
var inline = false;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 是否在公式块中
|
|
56
|
+
*/
|
|
57
|
+
var block = false;
|
|
58
|
+
var push = function push() {
|
|
59
|
+
if (level === 1 && !block) {
|
|
60
|
+
result.push(inline ? {
|
|
61
|
+
type: 'element',
|
|
62
|
+
tagName: 'span',
|
|
63
|
+
properties: {
|
|
64
|
+
className: ['math', 'math-inline']
|
|
65
|
+
},
|
|
66
|
+
children: [{
|
|
67
|
+
type: 'text',
|
|
68
|
+
value: scan
|
|
69
|
+
}]
|
|
70
|
+
} : {
|
|
71
|
+
type: 'text',
|
|
72
|
+
value: scan
|
|
73
|
+
});
|
|
74
|
+
scan = '';
|
|
75
|
+
inline = !inline;
|
|
76
|
+
} else if (level === 2 && !inline) {
|
|
77
|
+
result.push(block ? {
|
|
78
|
+
type: 'element',
|
|
79
|
+
tagName: 'div',
|
|
80
|
+
properties: {
|
|
81
|
+
className: ['math', 'math-display']
|
|
82
|
+
},
|
|
83
|
+
children: [{
|
|
84
|
+
type: 'text',
|
|
85
|
+
value: scan
|
|
86
|
+
}]
|
|
87
|
+
} : {
|
|
88
|
+
type: 'text',
|
|
89
|
+
value: scan
|
|
90
|
+
});
|
|
91
|
+
scan = '';
|
|
92
|
+
block = !block;
|
|
93
|
+
} else if (level) {
|
|
94
|
+
scan += '$'.repeat(level);
|
|
95
|
+
}
|
|
96
|
+
level = 0;
|
|
97
|
+
};
|
|
98
|
+
for (var i = 0; i <= text.length; i++) {
|
|
99
|
+
var _text$i;
|
|
100
|
+
var c = (_text$i = text[i]) !== null && _text$i !== void 0 ? _text$i : '';
|
|
101
|
+
if (escape) {
|
|
102
|
+
if (c === '\\') {
|
|
103
|
+
scan += c;
|
|
104
|
+
} else {
|
|
105
|
+
scan += c === '$' ? c : "\\".concat(c);
|
|
106
|
+
escape = false;
|
|
107
|
+
}
|
|
108
|
+
} else if (c === '$') {
|
|
109
|
+
level++;
|
|
110
|
+
} else {
|
|
111
|
+
push();
|
|
112
|
+
if (c === '\\') {
|
|
113
|
+
escape = true;
|
|
114
|
+
} else {
|
|
115
|
+
scan += c;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (scan) {
|
|
120
|
+
result.push({
|
|
121
|
+
type: 'text',
|
|
122
|
+
value: scan
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 解析属于 Raw 节点的文本中的数学公式
|
|
130
|
+
*/
|
|
131
|
+
var rehypeMath = function rehypeMath() {
|
|
132
|
+
return function (root) {
|
|
133
|
+
var rawPositions = [];
|
|
134
|
+
var i = 0;
|
|
135
|
+
|
|
136
|
+
// 获取 rehype-raw-positions 记录的 Raw 节点的位置信息
|
|
137
|
+
visit(root, {
|
|
138
|
+
tagName: 'raw-positions'
|
|
139
|
+
}, function (node, index, parent) {
|
|
140
|
+
var _node$properties3;
|
|
141
|
+
if (typeof ((_node$properties3 = node.properties) === null || _node$properties3 === void 0 ? void 0 : _node$properties3.value) === 'string') {
|
|
142
|
+
rawPositions = node.properties.value.split(' ').map(function (offset) {
|
|
143
|
+
return parseInt(offset);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (index !== null && parent) {
|
|
147
|
+
parent.children.splice(index);
|
|
148
|
+
}
|
|
149
|
+
return EXIT;
|
|
150
|
+
}, true);
|
|
151
|
+
if (rawPositions.length < 2) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
visit(root, function (node, index, parent) {
|
|
155
|
+
if (isCodeNode(node) || isMathNode(node)) {
|
|
156
|
+
return SKIP;
|
|
157
|
+
}
|
|
158
|
+
if (node.type === 'text' && index !== null && parent) {
|
|
159
|
+
var _node$position;
|
|
160
|
+
var startOffset = (_node$position = node.position) === null || _node$position === void 0 ? void 0 : _node$position.start.offset;
|
|
161
|
+
if (startOffset === undefined) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
for (; i < rawPositions.length - 1 && rawPositions[i + 1] <= startOffset; i += 2);
|
|
165
|
+
if (i < rawPositions.length - 1 && rawPositions[i] <= startOffset) {
|
|
166
|
+
var _parent$children;
|
|
167
|
+
var result = parseMath(node.value);
|
|
168
|
+
(_parent$children = parent.children).splice.apply(_parent$children, [index, 1].concat(_toConsumableArray(result)));
|
|
169
|
+
return index + result.length;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
export default rehypeMath;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 保存 Raw 节点的位置信息
|
|
5
|
+
*/
|
|
6
|
+
var rehypeRawPositions = function rehypeRawPositions() {
|
|
7
|
+
return function (root) {
|
|
8
|
+
var rawPositions = [];
|
|
9
|
+
visit(root, 'raw', function (node) {
|
|
10
|
+
var _node$position, _node$position2;
|
|
11
|
+
var startOffset = (_node$position = node.position) === null || _node$position === void 0 ? void 0 : _node$position.start.offset;
|
|
12
|
+
var endOffset = (_node$position2 = node.position) === null || _node$position2 === void 0 ? void 0 : _node$position2.end.offset;
|
|
13
|
+
if (startOffset === undefined || endOffset === undefined) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
rawPositions.push(startOffset, endOffset);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// 记录在新的 Hast 节点上,防止被 rehype-raw 删除
|
|
20
|
+
root.children.push({
|
|
21
|
+
type: 'element',
|
|
22
|
+
tagName: 'raw-positions',
|
|
23
|
+
properties: {
|
|
24
|
+
value: rawPositions.join(' ')
|
|
25
|
+
},
|
|
26
|
+
children: []
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export default rehypeRawPositions;
|
|
@@ -238,12 +238,9 @@ var XStarMdEditor = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
238
238
|
onInsertFileLatest.current = onInsertFile;
|
|
239
239
|
var options = useMemo(function () {
|
|
240
240
|
return composeHandlers(plugins)({
|
|
241
|
-
toolbarItemMap: getDefaultToolbarItemMap(locale, function () {
|
|
241
|
+
toolbarItemMap: getDefaultToolbarItemMap(locale, function (file, options) {
|
|
242
242
|
var _onInsertFileLatest$c;
|
|
243
|
-
|
|
244
|
-
args[_key] = arguments[_key];
|
|
245
|
-
}
|
|
246
|
-
return (_onInsertFileLatest$c = onInsertFileLatest.current) === null || _onInsertFileLatest$c === void 0 ? void 0 : _onInsertFileLatest$c.call.apply(_onInsertFileLatest$c, [onInsertFileLatest].concat(args));
|
|
243
|
+
return (_onInsertFileLatest$c = onInsertFileLatest.current) === null || _onInsertFileLatest$c === void 0 ? void 0 : _onInsertFileLatest$c.call(onInsertFileLatest, file, options);
|
|
247
244
|
}),
|
|
248
245
|
toolbarItems: getDefaultToolbarItems(),
|
|
249
246
|
keyboardEventHandlers: getDefaultKeyboardEventHandlers()
|