diff --git a/packages/engine/src/change/paste.ts b/packages/engine/src/change/paste.ts
index d4e40fa9..0dc15408 100644
--- a/packages/engine/src/change/paste.ts
+++ b/packages/engine/src/change/paste.ts
@@ -44,7 +44,6 @@ export default class Paste {
const defaultStyle = this.getDefaultStyle();
const { inline } = this.engine;
const nodeApi = this.engine.node;
- // 第一轮预处理,主要处理 span 节点
$(fragment).traverse((node) => {
// 跳过Card
if (node.isCard() || fragment === node.fragment) {
@@ -97,9 +96,32 @@ export default class Paste {
if (nodeApi.isBlock(node, this.schema)) {
this.engine.block.brToBlock(node);
}
+ } else {
+ let text = node.text();
+ if (/\s/.test(text)) {
+ text = text.replace(/\s/g, ' ');
+ node.text(text);
+ }
+ if (/\u200b/.test(text)) {
+ let isRemove = true;
+ const next = node.next();
+ const prev = node.prev();
+ const parent = node.parent();
+ if (parent && nodeApi.isMark(parent, this.schema))
+ isRemove = false;
+ else if (parent && nodeApi.isInline(parent, this.schema))
+ isRemove = false;
+ else if (next && nodeApi.isInline(next, this.schema))
+ isRemove = false;
+ else if (prev && nodeApi.isInline(prev, this.schema))
+ isRemove = false;
+ if (isRemove) {
+ text = text.replace(/\u200b/g, '');
+ node.text(text);
+ }
+ }
}
});
- // 第二轮处理
$(fragment).traverse((node) => {
let parent = node.parent();
// 跳过已被删除的节点
@@ -228,7 +250,25 @@ export default class Paste {
// 处理嵌套
let nodeParent = parent;
+ const handleBlock = (node: NodeInterface) => {
+ if (
+ nodeParent &&
+ !nodeParent.fragment &&
+ nodeApi.isBlock(node, this.schema) &&
+ nodeApi.isBlock(nodeParent, this.schema) &&
+ !this.schema.isAllowIn(nodeParent.name, node.name)
+ ) {
+ const children = node.children();
+ nodeApi.unwrap(node);
+ children.each((_, index) => {
+ handleBlock(children.eq(index)!);
+ });
+ }
+ };
+ handleBlock(node);
+
while (
+ node.length > 0 &&
nodeParent &&
!nodeParent.fragment &&
nodeApi.isBlock(node, this.schema) &&
@@ -244,6 +284,7 @@ export default class Paste {
// mark 相同的嵌套
nodeParent = parent;
while (
+ node.length > 0 &&
nodeParent &&
nodeApi.isMark(nodeParent, this.schema) &&
nodeApi.isMark(node, this.schema)
diff --git a/packages/engine/src/node/index.ts b/packages/engine/src/node/index.ts
index 413c6028..6c4e188e 100644
--- a/packages/engine/src/node/index.ts
+++ b/packages/engine/src/node/index.ts
@@ -854,6 +854,15 @@ class NodeModel implements NodeModelInterface {
) {
childNode.append($('
'));
}
+ if (
+ this.editor.node.isBlock(childNode) &&
+ childNode.children().length === 1 &&
+ childNode.first()?.isText() &&
+ this.isEmptyWithTrim(childNode)
+ ) {
+ childNode.html('
');
+ }
+
this.removeSide(childNode);
childNode = nextNode;
}
diff --git a/packages/engine/src/ot/producer.ts b/packages/engine/src/ot/producer.ts
index 7da59e5a..20f61e05 100644
--- a/packages/engine/src/ot/producer.ts
+++ b/packages/engine/src/ot/producer.ts
@@ -207,7 +207,11 @@ class Producer extends EventEmitter2 {
const oldPath = path.slice();
ops.forEach((op) => {
- for (let p = 0; p < path!.length; p++) {
+ for (
+ let p = 0;
+ p < path!.length && op.p.length < path!.length;
+ p++
+ ) {
if (('li' in op || 'ld' in op) && op.p.length === p + 1) {
if (op.p[p] <= path![p]) {
if ('li' in op) oldPath[p] = oldPath[p] - 1;
diff --git a/packages/engine/src/ot/utils.ts b/packages/engine/src/ot/utils.ts
index 1f73f482..26859412 100644
--- a/packages/engine/src/ot/utils.ts
+++ b/packages/engine/src/ot/utils.ts
@@ -143,12 +143,7 @@ export const isReverseOp = (op: Op, next: Op) => {
// 节点增加和删除
if (insertOp.li && deleteNext.ld) {
- return (
- isEqual(insertOp.li, deleteNext.ld) &&
- (isEqual(op.p, next.p) ||
- isReversePath(op.p, next.p) ||
- isReversePath(next.p, op.p))
- );
+ return isEqual(insertOp.li, deleteNext.ld) && isEqual(op.p, next.p);
}
if (deleteOp.ld && insertNext.li) {
@@ -202,6 +197,8 @@ export const updateIndex = (
export const opsSort = (ops: Op[]) => {
ops.sort((op1, op2) => {
let diff = 0;
+ if (isCursorOp(op1)) return 1;
+ if (isCursorOp(op2)) return -1;
for (let p = 0; p < op1.p.length; p++) {
const v1 = op1.p[p];
// od oi 最后一个参数是属性名称
@@ -234,8 +231,12 @@ export const opsSort = (ops: Op[]) => {
return -1;
}
// 如果删除节点比增加的节点索引小,排在加入节点前面
- if (diff < 1 && 'ld' in op1 && 'li' in op2) return -1;
-
+ if ('ld' in op1 && 'li' in op2) return -1;
+ if ('li' in op1 && 'ld' in op2) return 1;
+ if (diff < 1 && 'ld' in op1 && 'si' in op2) return 1;
+ if (diff > 0 && 'ld' in op1 && 'si' in op2) return -1;
+ if (diff < 1 && 'si' in op1 && 'ld' in op2) return 1;
+ if (diff > 0 && 'si' in op1 && 'ld' in op2) return -1;
const isLi = 'li' in op1 && 'li' in op2;
const isLd = 'ld' in op1 && 'ld' in op2;
// 都是新增节点,越小排越前面
diff --git a/packages/engine/src/parser/index.ts b/packages/engine/src/parser/index.ts
index 3ade3d08..6bb2e93b 100644
--- a/packages/engine/src/parser/index.ts
+++ b/packages/engine/src/parser/index.ts
@@ -126,6 +126,7 @@ class Parser implements ParserInterface {
const { rule } = value;
oldRules.push(rule);
const { name, attributes, style } = value.node;
+ delete attributes['data-id'];
const newNode = $(`<${name} />`);
nodeApi.setAttributes(newNode, {
...attributes,
@@ -285,7 +286,8 @@ class Parser implements ParserInterface {
if (
parent &&
nodeApi.isBlock(parent, schema) &&
- parent.children().length === 1
+ parent.children().length === 1 &&
+ child.children().length === 0
) {
const newChild = $('
');
child.before(newChild);