@block-kit/react 1.0.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 (93) hide show
  1. package/dist/es/hooks/use-editor.d.ts +21 -0
  2. package/dist/es/hooks/use-editor.js +26 -0
  3. package/dist/es/hooks/use-readonly.d.ts +5 -0
  4. package/dist/es/hooks/use-readonly.js +6 -0
  5. package/dist/es/index.d.ts +18 -0
  6. package/dist/es/index.js +17 -0
  7. package/dist/es/model/block.d.ts +7 -0
  8. package/dist/es/model/block.js +142 -0
  9. package/dist/es/model/eol.d.ts +6 -0
  10. package/dist/es/model/eol.js +18 -0
  11. package/dist/es/model/leaf.d.ts +7 -0
  12. package/dist/es/model/leaf.js +38 -0
  13. package/dist/es/model/line.d.ts +7 -0
  14. package/dist/es/model/line.js +152 -0
  15. package/dist/es/plugin/index.d.ts +25 -0
  16. package/dist/es/plugin/index.js +3 -0
  17. package/dist/es/plugin/modules/priority.d.ts +13 -0
  18. package/dist/es/plugin/modules/priority.js +26 -0
  19. package/dist/es/plugin/modules/wrap.d.ts +26 -0
  20. package/dist/es/plugin/modules/wrap.js +72 -0
  21. package/dist/es/plugin/types/index.d.ts +35 -0
  22. package/dist/es/plugin/types/index.js +7 -0
  23. package/dist/es/preset/block-kit.d.ts +6 -0
  24. package/dist/es/preset/block-kit.js +17 -0
  25. package/dist/es/preset/editable.d.ts +16 -0
  26. package/dist/es/preset/editable.js +42 -0
  27. package/dist/es/preset/embed.d.ts +14 -0
  28. package/dist/es/preset/embed.js +23 -0
  29. package/dist/es/preset/isolate.d.ts +12 -0
  30. package/dist/es/preset/isolate.js +10 -0
  31. package/dist/es/preset/text.d.ts +9 -0
  32. package/dist/es/preset/text.js +34 -0
  33. package/dist/es/preset/void.d.ts +14 -0
  34. package/dist/es/preset/void.js +23 -0
  35. package/dist/es/preset/zero.d.ts +23 -0
  36. package/dist/es/preset/zero.js +20 -0
  37. package/dist/es/utils/constant.d.ts +2 -0
  38. package/dist/es/utils/constant.js +6 -0
  39. package/dist/es/utils/event.d.ts +2 -0
  40. package/dist/es/utils/event.js +7 -0
  41. package/dist/es/utils/is.d.ts +2 -0
  42. package/dist/es/utils/is.js +12 -0
  43. package/dist/es/utils/weak-map.d.ts +17 -0
  44. package/dist/es/utils/weak-map.js +15 -0
  45. package/dist/es/utils/wrapper.d.ts +7 -0
  46. package/dist/es/utils/wrapper.js +25 -0
  47. package/dist/lib/hooks/use-editor.d.ts +21 -0
  48. package/dist/lib/hooks/use-editor.js +53 -0
  49. package/dist/lib/hooks/use-readonly.d.ts +5 -0
  50. package/dist/lib/hooks/use-readonly.js +33 -0
  51. package/dist/lib/index.d.ts +18 -0
  52. package/dist/lib/index.js +40 -0
  53. package/dist/lib/model/block.d.ts +7 -0
  54. package/dist/lib/model/block.js +168 -0
  55. package/dist/lib/model/eol.d.ts +6 -0
  56. package/dist/lib/model/eol.js +24 -0
  57. package/dist/lib/model/leaf.d.ts +7 -0
  58. package/dist/lib/model/leaf.js +64 -0
  59. package/dist/lib/model/line.d.ts +7 -0
  60. package/dist/lib/model/line.js +178 -0
  61. package/dist/lib/plugin/index.d.ts +25 -0
  62. package/dist/lib/plugin/index.js +7 -0
  63. package/dist/lib/plugin/modules/priority.d.ts +13 -0
  64. package/dist/lib/plugin/modules/priority.js +31 -0
  65. package/dist/lib/plugin/modules/wrap.d.ts +26 -0
  66. package/dist/lib/plugin/modules/wrap.js +78 -0
  67. package/dist/lib/plugin/types/index.d.ts +35 -0
  68. package/dist/lib/plugin/types/index.js +10 -0
  69. package/dist/lib/preset/block-kit.d.ts +6 -0
  70. package/dist/lib/preset/block-kit.js +21 -0
  71. package/dist/lib/preset/editable.d.ts +16 -0
  72. package/dist/lib/preset/editable.js +46 -0
  73. package/dist/lib/preset/embed.d.ts +14 -0
  74. package/dist/lib/preset/embed.js +30 -0
  75. package/dist/lib/preset/isolate.d.ts +12 -0
  76. package/dist/lib/preset/isolate.js +14 -0
  77. package/dist/lib/preset/text.d.ts +9 -0
  78. package/dist/lib/preset/text.js +37 -0
  79. package/dist/lib/preset/void.d.ts +14 -0
  80. package/dist/lib/preset/void.js +30 -0
  81. package/dist/lib/preset/zero.d.ts +23 -0
  82. package/dist/lib/preset/zero.js +23 -0
  83. package/dist/lib/utils/constant.d.ts +2 -0
  84. package/dist/lib/utils/constant.js +9 -0
  85. package/dist/lib/utils/event.d.ts +2 -0
  86. package/dist/lib/utils/event.js +12 -0
  87. package/dist/lib/utils/is.d.ts +2 -0
  88. package/dist/lib/utils/is.js +16 -0
  89. package/dist/lib/utils/weak-map.d.ts +17 -0
  90. package/dist/lib/utils/weak-map.js +18 -0
  91. package/dist/lib/utils/wrapper.d.ts +7 -0
  92. package/dist/lib/utils/wrapper.js +29 -0
  93. package/package.json +38 -0
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.BlockModel = void 0;
27
+ const jsx_runtime_1 = require("react/jsx-runtime");
28
+ const core_1 = require("@block-kit/core");
29
+ const hooks_1 = require("@block-kit/utils/dist/es/hooks");
30
+ const react_1 = __importStar(require("react"));
31
+ const wrap_1 = require("../plugin/modules/wrap");
32
+ const is_1 = require("../utils/is");
33
+ const weak_map_1 = require("../utils/weak-map");
34
+ const wrapper_1 = require("../utils/wrapper");
35
+ const line_1 = require("./line");
36
+ /**
37
+ * Block Model
38
+ * @param props
39
+ */
40
+ const BlockView = props => {
41
+ const { editor, state } = props;
42
+ const flushing = (0, react_1.useRef)(false);
43
+ const [lines, setLines] = (0, react_1.useState)(() => state.getLines());
44
+ /**
45
+ * 设置行 DOM 节点
46
+ */
47
+ const setModel = (ref) => {
48
+ if (ref) {
49
+ editor.model.setBlockModel(ref, state);
50
+ }
51
+ };
52
+ /**
53
+ * 数据同步变更, 异步批量绘制变更
54
+ */
55
+ const onContentChange = (0, hooks_1.useMemoFn)(() => {
56
+ // 举个例子: 同步等待刷新的队列 => ||||||||
57
+ // 进入更新行为后, 异步行为等待, 同步的队列由于 !flushing 全部被守卫
58
+ // 主线程执行完毕后, 异步队列开始执行, 此时拿到的是最新数据, 以此批量重新渲染
59
+ if (flushing.current)
60
+ return void 0;
61
+ flushing.current = true;
62
+ Promise.resolve().then(() => {
63
+ flushing.current = false;
64
+ setLines(state.getLines());
65
+ editor.state.set(core_1.EDITOR_STATE.PAINTING, true);
66
+ });
67
+ });
68
+ /**
69
+ * 监听内容变更事件, 更新当前块视图
70
+ */
71
+ (0, react_1.useLayoutEffect)(() => {
72
+ editor.event.on(core_1.EDITOR_EVENT.CONTENT_CHANGE, onContentChange);
73
+ return () => {
74
+ editor.event.off(core_1.EDITOR_EVENT.CONTENT_CHANGE, onContentChange);
75
+ };
76
+ }, [editor.event, onContentChange]);
77
+ /**
78
+ * 视图更新需要重新设置选区 无依赖数组
79
+ */
80
+ (0, react_1.useLayoutEffect)(() => {
81
+ const selection = editor.selection.get();
82
+ if (!editor.state.get(core_1.EDITOR_STATE.COMPOSING) &&
83
+ editor.state.get(core_1.EDITOR_STATE.FOCUS) &&
84
+ selection) {
85
+ // 更新浏览器选区
86
+ editor.logger.debug("UpdateDOMSelection");
87
+ editor.selection.updateDOMSelection(true);
88
+ }
89
+ });
90
+ /**
91
+ * 视图更新需要触发视图绘制完成事件 无依赖数组
92
+ * state -> parent -> node -> child ->|
93
+ * effect <- parent <- node <- child <-|
94
+ */
95
+ (0, react_1.useEffect)(() => {
96
+ editor.logger.debug("OnPaint");
97
+ editor.state.set(core_1.EDITOR_STATE.PAINTING, false);
98
+ Promise.resolve().then(() => {
99
+ editor.event.trigger(core_1.EDITOR_EVENT.PAINT, {});
100
+ });
101
+ });
102
+ /**
103
+ * 处理行节点
104
+ */
105
+ const elements = (0, react_1.useMemo)(() => {
106
+ return lines.map((line, index) => {
107
+ const node = ((0, jsx_runtime_1.jsx)(line_1.LineModel, { editor: editor, lineState: line, index: index }, line.key));
108
+ weak_map_1.JSX_TO_STATE.set(node, line);
109
+ return node;
110
+ });
111
+ }, [editor, lines]);
112
+ /**
113
+ * 将行包装组合 O(N)
114
+ */
115
+ const children = (0, react_1.useMemo)(() => {
116
+ const wrapped = [];
117
+ const keys = wrap_1.EDITOR_TO_WRAP_LINE_KEYS.get(editor);
118
+ const plugins = wrap_1.EDITOR_TO_WRAP_LINE_PLUGINS.get(editor);
119
+ if (!keys || !plugins)
120
+ return elements;
121
+ const len = elements.length;
122
+ for (let i = 0; i < len; ++i) {
123
+ const element = elements[i];
124
+ const symbol = (0, wrapper_1.getWrapSymbol)(keys, element);
125
+ const line = weak_map_1.JSX_TO_STATE.get(element);
126
+ if (!element || !line || !symbol) {
127
+ wrapped.push(element);
128
+ continue;
129
+ }
130
+ // 执行到此处说明需要包装相关节点(即使仅单个节点)
131
+ const nodes = [element];
132
+ for (let k = i + 1; k < len; ++k) {
133
+ const next = elements[k];
134
+ const nextSymbol = (0, wrapper_1.getWrapSymbol)(keys, next);
135
+ if (!next || !nextSymbol || nextSymbol !== symbol) {
136
+ // 回退到上一个值, 以便下次循环时重新检查
137
+ i = k - 1;
138
+ break;
139
+ }
140
+ nodes.push(next);
141
+ i = k;
142
+ }
143
+ // 通过插件渲染包装节点
144
+ let wrapper = nodes;
145
+ const op = line.op;
146
+ for (const plugin of plugins) {
147
+ // 这里的状态以首个节点为准
148
+ const context = {
149
+ lineState: line,
150
+ children: wrapper,
151
+ };
152
+ if (plugin.match(line.op.attributes || {}, op) && plugin.wrapLine) {
153
+ wrapper = plugin.wrapLine(context);
154
+ }
155
+ }
156
+ const key = `${i - nodes.length + 1}-${i}`;
157
+ wrapped.push((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: wrapper }, key));
158
+ }
159
+ return wrapped;
160
+ }, [editor, elements]);
161
+ return ((0, jsx_runtime_1.jsxs)("div", { [core_1.BLOCK_KEY]: true, [core_1.BLOCK_ID_KEY]: state.key, ref: setModel, children: [props.placeholder && lines.length === 1 && (0, is_1.isStrictEmptyLine)(lines[0]) && ((0, jsx_runtime_1.jsx)("div", { [core_1.PLACEHOLDER_KEY]: true, style: {
162
+ position: "absolute",
163
+ opacity: "0.3",
164
+ userSelect: "none",
165
+ pointerEvents: "none",
166
+ }, children: props.placeholder })), children] }));
167
+ };
168
+ exports.BlockModel = react_1.default.memo(BlockView);
@@ -0,0 +1,6 @@
1
+ import type { Editor, LeafState } from "@block-kit/core";
2
+ import React from "react";
3
+ export declare const EOLModel: React.NamedExoticComponent<{
4
+ editor: Editor;
5
+ leafState: LeafState;
6
+ }>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EOLModel = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const core_1 = require("@block-kit/core");
9
+ const react_1 = __importDefault(require("react"));
10
+ const zero_1 = require("../preset/zero");
11
+ /**
12
+ * EOL Model
13
+ * @param props
14
+ */
15
+ const EOLView = props => {
16
+ const { editor, leafState } = props;
17
+ const setModel = (ref) => {
18
+ if (ref) {
19
+ editor.model.setLeafModel(ref, leafState);
20
+ }
21
+ };
22
+ return ((0, jsx_runtime_1.jsx)("span", { [core_1.LEAF_KEY]: true, ref: setModel, children: (0, jsx_runtime_1.jsx)(zero_1.ZeroSpace, { enter: true }) }));
23
+ };
24
+ exports.EOLModel = react_1.default.memo(EOLView);
@@ -0,0 +1,7 @@
1
+ import type { Editor, LeafState } from "@block-kit/core";
2
+ import React from "react";
3
+ export declare const LeafModel: React.NamedExoticComponent<{
4
+ editor: Editor;
5
+ index: number;
6
+ leafState: LeafState;
7
+ }>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.LeafModel = void 0;
27
+ const jsx_runtime_1 = require("react/jsx-runtime");
28
+ const core_1 = require("@block-kit/core");
29
+ const react_1 = __importStar(require("react"));
30
+ const text_1 = require("../preset/text");
31
+ const weak_map_1 = require("../utils/weak-map");
32
+ /**
33
+ * Leaf Model
34
+ * @param props
35
+ */
36
+ const LeafView = props => {
37
+ const { editor, leafState } = props;
38
+ const setModel = (ref) => {
39
+ if (ref) {
40
+ editor.model.setLeafModel(ref, leafState);
41
+ }
42
+ };
43
+ const runtime = (0, react_1.useMemo)(() => {
44
+ const text = leafState.getText();
45
+ const context = {
46
+ op: leafState.op,
47
+ classList: [],
48
+ lineState: leafState.parent,
49
+ leafState: leafState,
50
+ attributes: leafState.op.attributes,
51
+ style: {},
52
+ children: (0, jsx_runtime_1.jsx)(text_1.Text, { ref: el => weak_map_1.LEAF_TO_TEXT.set(leafState, el), children: text }),
53
+ };
54
+ const plugins = editor.plugin.getPriorityPlugins(core_1.PLUGIN_TYPE.RENDER_LEAF);
55
+ for (const plugin of plugins) {
56
+ if (plugin.match(context.attributes || {}, context.op)) {
57
+ context.children = plugin.renderLeaf(context);
58
+ }
59
+ }
60
+ return context;
61
+ }, [editor, leafState]);
62
+ return ((0, jsx_runtime_1.jsx)("span", { [core_1.LEAF_KEY]: true, ref: setModel, className: runtime.classList.join(" "), style: runtime.style, children: runtime.children }));
63
+ };
64
+ exports.LeafModel = react_1.default.memo(LeafView);
@@ -0,0 +1,7 @@
1
+ import type { Editor, LineState } from "@block-kit/core";
2
+ import React from "react";
3
+ export declare const LineModel: React.NamedExoticComponent<{
4
+ editor: Editor;
5
+ index: number;
6
+ lineState: LineState;
7
+ }>;
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.LineModel = void 0;
27
+ const jsx_runtime_1 = require("react/jsx-runtime");
28
+ const core_1 = require("@block-kit/core");
29
+ const delta_1 = require("@block-kit/delta");
30
+ const utils_1 = require("@block-kit/utils");
31
+ const hooks_1 = require("@block-kit/utils/dist/es/hooks");
32
+ const react_1 = __importStar(require("react"));
33
+ const wrap_1 = require("../plugin/modules/wrap");
34
+ const weak_map_1 = require("../utils/weak-map");
35
+ const wrapper_1 = require("../utils/wrapper");
36
+ const eol_1 = require("./eol");
37
+ const leaf_1 = require("./leaf");
38
+ /**
39
+ * Line Model
40
+ * @param props
41
+ */
42
+ const LineView = props => {
43
+ const { editor, lineState } = props;
44
+ /**
45
+ * 设置行 DOM 节点
46
+ */
47
+ const setModel = (ref) => {
48
+ if (ref) {
49
+ editor.model.setLineModel(ref, lineState);
50
+ }
51
+ };
52
+ /**
53
+ * 首次处理会将所有 DOM 渲染, 不需要执行脏数据检查
54
+ * 需要 LayoutEffect 以保证 DOM -> Sel 的执行顺序
55
+ */
56
+ (0, hooks_1.useUpdateLayoutEffect)(() => {
57
+ const leaves = lineState.getLeaves();
58
+ for (const leaf of leaves) {
59
+ const dom = weak_map_1.LEAF_TO_TEXT.get(leaf);
60
+ if (!dom)
61
+ continue;
62
+ const text = leaf.getText();
63
+ // 避免 React 非受控与 IME 造成的 DOM 内容问题
64
+ if (text === dom.textContent)
65
+ continue;
66
+ editor.logger.debug("Correct Text Node", dom);
67
+ const nodes = dom.childNodes;
68
+ for (let i = 1; i < nodes.length; ++i) {
69
+ const node = nodes[i];
70
+ node && node.remove();
71
+ }
72
+ if ((0, utils_1.isDOMText)(dom.firstChild)) {
73
+ dom.firstChild.nodeValue = text;
74
+ }
75
+ }
76
+ }, [lineState]);
77
+ /**
78
+ * 处理行内的节点
79
+ */
80
+ const elements = (0, react_1.useMemo)(() => {
81
+ const leaves = lineState.getLeaves();
82
+ const textLeaves = leaves.slice(0, -1);
83
+ const nodes = textLeaves.map((n, i) => {
84
+ const node = (0, jsx_runtime_1.jsx)(leaf_1.LeafModel, { editor: editor, index: i, leafState: n }, i);
85
+ weak_map_1.JSX_TO_STATE.set(node, n);
86
+ return node;
87
+ });
88
+ // 空行则仅存在一个 Leaf, 此时需要渲染空的占位节点
89
+ if (!nodes.length && leaves[0]) {
90
+ const leaf = leaves[0];
91
+ const node = (0, jsx_runtime_1.jsx)(eol_1.EOLModel, { editor: editor, leafState: leaf }, delta_1.EOL);
92
+ weak_map_1.JSX_TO_STATE.set(node, leaf);
93
+ nodes.push(node);
94
+ return nodes;
95
+ }
96
+ // inline-void(embed) 在行未时需要预设零宽字符来放置光标
97
+ const eolLeaf = leaves[leaves.length - 1];
98
+ const lastLeaf = textLeaves[textLeaves.length - 1];
99
+ if (lastLeaf && eolLeaf && lastLeaf.embed) {
100
+ const node = (0, jsx_runtime_1.jsx)(eol_1.EOLModel, { editor: editor, leafState: eolLeaf }, delta_1.EOL);
101
+ weak_map_1.JSX_TO_STATE.set(node, eolLeaf);
102
+ nodes.push(node);
103
+ return nodes;
104
+ }
105
+ return nodes;
106
+ }, [editor, lineState]);
107
+ /**
108
+ * 将行内节点包装组合 O(N)
109
+ */
110
+ const children = (0, react_1.useMemo)(() => {
111
+ const wrapped = [];
112
+ const keys = wrap_1.EDITOR_TO_WRAP_LEAF_KEYS.get(editor);
113
+ const plugins = wrap_1.EDITOR_TO_WRAP_LEAF_PLUGINS.get(editor);
114
+ if (!keys || !plugins)
115
+ return elements;
116
+ const len = elements.length;
117
+ for (let i = 0; i < len; ++i) {
118
+ const element = elements[i];
119
+ const symbol = (0, wrapper_1.getWrapSymbol)(keys, element);
120
+ const leaf = weak_map_1.JSX_TO_STATE.get(element);
121
+ if (!element || !leaf || !symbol) {
122
+ wrapped.push(element);
123
+ continue;
124
+ }
125
+ // 执行到此处说明需要包装相关节点(即使仅单个节点)
126
+ const nodes = [element];
127
+ for (let k = i + 1; k < len; ++k) {
128
+ const next = elements[k];
129
+ const nextSymbol = (0, wrapper_1.getWrapSymbol)(keys, next);
130
+ if (!next || !nextSymbol || nextSymbol !== symbol) {
131
+ // 回退到上一个值, 以便下次循环时重新检查
132
+ i = k - 1;
133
+ break;
134
+ }
135
+ nodes.push(next);
136
+ i = k;
137
+ }
138
+ // 通过插件渲染包装节点
139
+ let wrapper = nodes;
140
+ const op = leaf.op;
141
+ for (const plugin of plugins) {
142
+ // 这里的状态以首个节点为准
143
+ const context = {
144
+ leafState: leaf,
145
+ children: wrapper,
146
+ };
147
+ if (plugin.match(leaf.op.attributes || {}, op) && plugin.wrapLeaf) {
148
+ wrapper = plugin.wrapLeaf(context);
149
+ }
150
+ }
151
+ const key = `${i - nodes.length + 1}-${i}`;
152
+ wrapped.push((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: wrapper }, key));
153
+ }
154
+ return wrapped;
155
+ }, [editor, elements]);
156
+ /**
157
+ * 处理行级节点的渲染
158
+ */
159
+ const runtime = (0, react_1.useMemo)(() => {
160
+ const context = {
161
+ classList: [],
162
+ lineState: lineState,
163
+ attributes: lineState.attributes,
164
+ style: {},
165
+ children,
166
+ };
167
+ const plugins = editor.plugin.getPriorityPlugins(core_1.PLUGIN_TYPE.RENDER_LINE);
168
+ for (const plugin of plugins) {
169
+ const op = Object.assign(Object.assign({}, delta_1.EOL_OP), { attributes: context.attributes });
170
+ if (plugin.match(context.attributes, op)) {
171
+ context.children = plugin.renderLine(context);
172
+ }
173
+ }
174
+ return context;
175
+ }, [children, editor.plugin, lineState]);
176
+ return ((0, jsx_runtime_1.jsx)("div", { [core_1.NODE_KEY]: true, ref: setModel, dir: "auto", className: (0, utils_1.cs)(runtime.classList), style: runtime.style, children: runtime.children }));
177
+ };
178
+ exports.LineModel = react_1.default.memo(LineView);
@@ -0,0 +1,25 @@
1
+ /// <reference types="react" />
2
+ import { CorePlugin } from "@block-kit/core";
3
+ import type { ReactLeafContext, ReactLineContext, ReactWrapLeafContext, ReactWrapLineContext } from "./types";
4
+ export declare abstract class EditorPlugin extends CorePlugin {
5
+ /**
6
+ * 渲染包装行节点
7
+ * - 调度优先级值越大 DOM 结构在越外层
8
+ */
9
+ wrapLine?(children: ReactWrapLineContext): React.ReactNode;
10
+ /**
11
+ * 渲染包装叶子节点
12
+ * - 调度优先级值越大 DOM 结构在越外层
13
+ */
14
+ wrapLeaf?(context: ReactWrapLeafContext): React.ReactNode;
15
+ /**
16
+ * 渲染行节点
17
+ * - 调度优先级值越大 DOM 结构在越外层
18
+ */
19
+ renderLine?(context: ReactLineContext): React.ReactNode;
20
+ /**
21
+ * 渲染块级子节点
22
+ * - 调度优先级值越大 DOM 结构在越外层
23
+ */
24
+ renderLeaf?(context: ReactLeafContext): React.ReactNode;
25
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorPlugin = void 0;
4
+ const core_1 = require("@block-kit/core");
5
+ class EditorPlugin extends core_1.CorePlugin {
6
+ }
7
+ exports.EditorPlugin = EditorPlugin;
@@ -0,0 +1,13 @@
1
+ import type { CorePlugin } from "@block-kit/core";
2
+ /**
3
+ * 获取插件的优先级
4
+ * @param key
5
+ * @param plugin
6
+ */
7
+ export declare const getPluginPriority: (key: string, plugin: CorePlugin) => number;
8
+ /**
9
+ * 优先级定义装饰器
10
+ * - 兼容性实现, 非强制类型检查
11
+ * @param priority
12
+ */
13
+ export declare function Priority<T>(priority: number): (target: T, key: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Priority = exports.getPluginPriority = void 0;
4
+ const core_1 = require("@block-kit/core");
5
+ const utils_1 = require("@block-kit/utils");
6
+ /**
7
+ * 获取插件的优先级
8
+ * @param key
9
+ * @param plugin
10
+ */
11
+ const getPluginPriority = (key, plugin) => {
12
+ const priorityKey = `${core_1.PRIORITY_KEY}${key}`;
13
+ const priorityPlugin = plugin;
14
+ const priority = priorityPlugin[priorityKey];
15
+ return (0, utils_1.isNumber)(priority) ? priority : utils_1.DEFAULT_PRIORITY;
16
+ };
17
+ exports.getPluginPriority = getPluginPriority;
18
+ /**
19
+ * 优先级定义装饰器
20
+ * - 兼容性实现, 非强制类型检查
21
+ * @param priority
22
+ */
23
+ function Priority(priority) {
24
+ return function (target, key, descriptor) {
25
+ const priorityKey = `${core_1.PRIORITY_KEY}${key}`;
26
+ const plugin = target;
27
+ plugin[priorityKey] = priority;
28
+ return descriptor;
29
+ };
30
+ }
31
+ exports.Priority = Priority;
@@ -0,0 +1,26 @@
1
+ import type { CorePlugin, Editor } from "@block-kit/core";
2
+ import type { O, P } from "@block-kit/utils/dist/es/types";
3
+ import type { EditorPlugin } from "../index";
4
+ import { WRAP_TYPE } from "../types";
5
+ export declare const EDITOR_TO_WRAP_LINE_KEYS: WeakMap<Editor, string[]>;
6
+ export declare const EDITOR_TO_WRAP_LEAF_KEYS: WeakMap<Editor, string[]>;
7
+ export declare const EDITOR_TO_WRAP_LINE_PLUGINS: WeakMap<Editor, EditorPlugin[]>;
8
+ export declare const EDITOR_TO_WRAP_LEAF_PLUGINS: WeakMap<Editor, EditorPlugin[]>;
9
+ /**
10
+ * 为 WrapNode 定义 Key
11
+ * @param ...keys
12
+ */
13
+ export declare function InjectWrapKeys<T>(...keys: string[]): (target: T, key: O.Values<typeof WRAP_TYPE>, descriptor: PropertyDescriptor) => PropertyDescriptor;
14
+ /**
15
+ * 获取插件的 WrapKeys
16
+ * @param key
17
+ * @param plugin
18
+ */
19
+ export declare const getWrapKeys: (key: string, plugin: CorePlugin) => string[] | P.Undef;
20
+ /**
21
+ * 初始化 Wrap 模式的插件
22
+ * - Wrap 模式的插件化在 React 层面渲染时实现
23
+ * - 其是渲染时调度且不存在 WrapState 的概念
24
+ * @param editor
25
+ */
26
+ export declare const initWrapPlugins: (editor: Editor) => void;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initWrapPlugins = exports.getWrapKeys = exports.InjectWrapKeys = exports.EDITOR_TO_WRAP_LEAF_PLUGINS = exports.EDITOR_TO_WRAP_LINE_PLUGINS = exports.EDITOR_TO_WRAP_LEAF_KEYS = exports.EDITOR_TO_WRAP_LINE_KEYS = void 0;
4
+ const types_1 = require("../types");
5
+ const priority_1 = require("./priority");
6
+ exports.EDITOR_TO_WRAP_LINE_KEYS = new WeakMap();
7
+ exports.EDITOR_TO_WRAP_LEAF_KEYS = new WeakMap();
8
+ exports.EDITOR_TO_WRAP_LINE_PLUGINS = new WeakMap();
9
+ exports.EDITOR_TO_WRAP_LEAF_PLUGINS = new WeakMap();
10
+ /**
11
+ * 为 WrapNode 定义 Key
12
+ * @param ...keys
13
+ */
14
+ function InjectWrapKeys(...keys) {
15
+ return function (target, key, descriptor) {
16
+ const wrapPluginKey = `${key}Keys`;
17
+ const plugin = target;
18
+ plugin[wrapPluginKey] = keys;
19
+ return descriptor;
20
+ };
21
+ }
22
+ exports.InjectWrapKeys = InjectWrapKeys;
23
+ /**
24
+ * 获取插件的 WrapKeys
25
+ * @param key
26
+ * @param plugin
27
+ */
28
+ const getWrapKeys = (key, plugin) => {
29
+ const wrapPluginKey = `${key}Keys`;
30
+ const wrapPlugin = plugin;
31
+ const keys = wrapPlugin[wrapPluginKey];
32
+ return keys;
33
+ };
34
+ exports.getWrapKeys = getWrapKeys;
35
+ /**
36
+ * 初始化 Wrap 模式的插件
37
+ * - Wrap 模式的插件化在 React 层面渲染时实现
38
+ * - 其是渲染时调度且不存在 WrapState 的概念
39
+ * @param editor
40
+ */
41
+ const initWrapPlugins = (editor) => {
42
+ const plugins = editor.plugin.current;
43
+ const wrapLineKeys = [];
44
+ const wrapLeafKeys = [];
45
+ const wrapLinePlugins = [];
46
+ const wrapLeafPlugins = [];
47
+ for (const plugin of plugins) {
48
+ const lineKeys = (0, exports.getWrapKeys)(types_1.WRAP_TYPE.LINE, plugin);
49
+ if (lineKeys) {
50
+ wrapLineKeys.push(...lineKeys);
51
+ }
52
+ const leafKeys = (0, exports.getWrapKeys)(types_1.WRAP_TYPE.LEAF, plugin);
53
+ if (leafKeys) {
54
+ wrapLeafKeys.push(...leafKeys);
55
+ }
56
+ if (plugin.wrapLine) {
57
+ wrapLinePlugins.push(plugin);
58
+ }
59
+ if (plugin.wrapLeaf) {
60
+ wrapLeafPlugins.push(plugin);
61
+ }
62
+ }
63
+ wrapLinePlugins.sort((a, b) => {
64
+ const priorityA = (0, priority_1.getPluginPriority)(types_1.WRAP_TYPE.LINE, a);
65
+ const priorityB = (0, priority_1.getPluginPriority)(types_1.WRAP_TYPE.LINE, b);
66
+ return priorityA - priorityB;
67
+ });
68
+ wrapLeafPlugins.sort((a, b) => {
69
+ const priorityA = (0, priority_1.getPluginPriority)(types_1.WRAP_TYPE.LEAF, a);
70
+ const priorityB = (0, priority_1.getPluginPriority)(types_1.WRAP_TYPE.LEAF, b);
71
+ return priorityA - priorityB;
72
+ });
73
+ wrapLineKeys.length && exports.EDITOR_TO_WRAP_LINE_KEYS.set(editor, wrapLineKeys);
74
+ wrapLeafKeys.length && exports.EDITOR_TO_WRAP_LEAF_KEYS.set(editor, wrapLeafKeys);
75
+ wrapLinePlugins.length && exports.EDITOR_TO_WRAP_LINE_PLUGINS.set(editor, wrapLinePlugins);
76
+ wrapLeafPlugins.length && exports.EDITOR_TO_WRAP_LEAF_PLUGINS.set(editor, wrapLeafPlugins);
77
+ };
78
+ exports.initWrapPlugins = initWrapPlugins;