fix: the deleted node will produce the wrong index in ops

This commit is contained in:
yanmao 2021-12-26 01:09:22 +08:00
parent 9e30813f42
commit 0f7c02605a
3 changed files with 90 additions and 9 deletions

View File

@ -157,7 +157,13 @@ class Producer extends EventEmitter2 {
): Array<Op> { ): Array<Op> {
const addNodes: Array<Node> = []; const addNodes: Array<Node> = [];
const allOps: Array< const allOps: Array<
Op & { id?: string; bi?: number; addNode?: NodeInterface } Op & {
id?: string;
bi?: number;
addNode?: NodeInterface;
childIds?: string[];
oldPath?: Path;
}
> = []; > = [];
let ops: Array<RepairOp> = []; let ops: Array<RepairOp> = [];
let attrOps: Array<any> = []; let attrOps: Array<any> = [];
@ -281,10 +287,22 @@ class Producer extends EventEmitter2 {
p = p.concat([...newPath!], [rIndex]); p = p.concat([...newPath!], [rIndex]);
let op: Path = []; let op: Path = [];
op = op.concat([...newOldPath], [rIndex]); op = op.concat([...newOldPath], [rIndex]);
let childIds: string[] = [];
if (removedNode.nodeType === Node.ELEMENT_NODE) {
$(removedNode)
.allChildren()
.forEach((child) => {
const dataId = child.isElement()
? child.attributes(DATA_ID)
: undefined;
if (dataId) childIds.push(dataId);
});
}
const newOp = { const newOp = {
id: rootId, id: rootId,
bi: beginIndex, bi: beginIndex,
ld: true, ld: true,
childIds,
p, p,
newPath: p.slice(), newPath: p.slice(),
oldPath: op, oldPath: op,
@ -391,22 +409,78 @@ class Producer extends EventEmitter2 {
op.oldPath || [], op.oldPath || [],
); );
if (pathValue !== undefined) { if (pathValue !== undefined) {
const childIds = op.childIds || [];
const opDataId =
Array.isArray(pathValue) && pathValue[1]
? pathValue[1][DATA_ID]
: undefined;
const loopValue = (value: any) => {
if (Array.isArray(value)) {
const attr = value[1];
if (
attr &&
attr[DATA_ID] &&
attr[DATA_ID] !== op.id &&
(!opDataId || attr[DATA_ID] !== opDataId)
) {
childIds.push(attr[DATA_ID]);
}
for (let i = 2; i < value.length; i++) {
loopValue(value[i]);
}
}
};
loopValue(pathValue);
op.childIds = childIds;
const ldOp = { const ldOp = {
id: op.id, id: op.id,
bi: beginIndex, bi: beginIndex,
ld: pathValue, ld: pathValue,
p: op.p, p: op.p,
nl: op['nl'], nl: op['nl'],
childIds,
oldPath: op.oldPath,
}; };
// 比较删除深度,当前删除深度比已有的要深就忽略,当前删除的深度比已有的要浅就替换 let has = false;
const findResult = allOps.find((op, index) => { // 修复index
if ('ld' in op) { // 如果删除后合并__index 可能会发生变化,如果 <ul></ul> 被删除了,那么里面的 li 就取ul的路径组合当前li的路径
allOps.forEach((aOp) => {
if ('ld' in aOp) {
if (aOp.id && op.childIds?.includes(aOp.id)) {
aOp.p = op.p.concat(
aOp.p.slice(op.p.length),
);
aOp.oldPath = op.oldPath?.concat(
aOp.oldPath?.slice(op.oldPath.length) ||
[],
);
aOp.ld = getValue(
this.doc?.data,
aOp.oldPath || [],
);
} else if (
op.id &&
aOp.childIds?.includes(op.id)
) {
ldOp.p = aOp.p.concat(
op.p.slice(aOp.p.length),
);
ldOp.oldPath = aOp.oldPath?.concat(
op.oldPath?.slice(aOp.oldPath.length) ||
[],
);
ldOp.ld = getValue(
this.doc?.data,
ldOp.oldPath || [],
);
}
const strP = op.p.join(','); const strP = op.p.join(',');
const strLdP = ldOp.p.join(','); const strLdP = ldOp.p.join(',');
// 相等,不需要增加 // 相等,不需要增加
if (strP === strLdP) { if (!has && strP === strLdP) {
return true; has = true;
} }
// 比较删除深度,当前删除深度比已有的要深就忽略,当前删除的深度比已有的要浅就替换
// 删除深度比已有的要深,忽略 // 删除深度比已有的要深,忽略
// if(strLdP.startsWith(strP)) { // if(strLdP.startsWith(strP)) {
// return true // return true
@ -417,9 +491,8 @@ class Producer extends EventEmitter2 {
// return true // return true
// } // }
} }
return false;
}); });
if (!findResult) allOps.push(ldOp); if (!has) allOps.push(ldOp);
} }
} }
if ('li' in op) { if ('li' in op) {
@ -439,6 +512,9 @@ class Producer extends EventEmitter2 {
return allOps.map((op) => { return allOps.map((op) => {
if ('li' in op) { if ('li' in op) {
delete op.addNode; delete op.addNode;
} else if ('ld' in op) {
delete op.childIds;
delete op.oldPath;
} }
return op; return op;
}); });

View File

@ -284,7 +284,11 @@ export const opsSort = (ops: Op[]) => {
} }
// 都是删除节点,越大排越前面 // 都是删除节点,越大排越前面
else if (isLd) { else if (isLd) {
if (op1.p.length < op2.p.length) return 1; if (
op1.p.length < op2.p.length &&
op1.p.every((p, i) => p <= op2.p[i])
)
return 1;
if (diff === -1) return 1; if (diff === -1) return 1;
if (diff === 1) return -1; if (diff === 1) return -1;
} }

View File

@ -268,6 +268,7 @@ export type TargetOp = Op & {
export type RepairOp = TargetOp & { export type RepairOp = TargetOp & {
oldPath?: Path; oldPath?: Path;
newPath: Path; newPath: Path;
childIds?: string[];
}; };
export interface MutationInterface extends EventEmitter2 { export interface MutationInterface extends EventEmitter2 {