Skip to content

Commit

Permalink
Replace shouldDiffDescendants with elementsAreRelated
Browse files Browse the repository at this point in the history
  • Loading branch information
12joan committed Mar 2, 2024
1 parent c4696af commit a278858
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 20 deletions.
18 changes: 18 additions & 0 deletions .changeset/dirty-clocks-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"@udecode/plate-diff": minor
---

- Remove `shouldDiffDescendants` option in favour of `elementsAreRelated`.
- The `elementsAreRelated` option controls whether `computeDiff` treats a given pair of elements as "related" and thus tries to diff them. By default, elements are related if they have the same `children` OR they differ only in their `children`. Return null to use the default logic for a pair of elements.

- Use case: In addition to supporting the same use case as the deprecated `shouldDiffDescendants`, `elementsAreRelated` can be used to ensure that `computeDiff` compares the correct pair of paragraphs.

For example, by default, `computeDiff` would compare `My slightly modified paragraph.` with `New paragraph` in the following diff.

```diff
- My slightly modified paragraph.
+ New paragraph
+ My slightly modified paragraph!
```

If a custom `elementsAreRelated` function is provided that returns true for mostly similar paragraphs, `computeDiff` would instead compare `My slightly modified paragraph.` with `My slightly modified paragraph!`.
75 changes: 68 additions & 7 deletions packages/diff/src/computeDiff.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
* contributors. See /packages/diff/LICENSE for more information.
*/

import { isText, Value } from '@udecode/plate-common';
import { getNodeString, TElement, Value } from '@udecode/plate-common';

import { computeDiff, ComputeDiffOptions } from './computeDiff';

const ELEMENT_INLINE_VOID = 'inline-void';

interface ComputeDiffFixture
extends Pick<ComputeDiffOptions, 'lineBreakChar' | 'shouldDiffDescendants'> {
extends Pick<ComputeDiffOptions, 'lineBreakChar' | 'elementsAreRelated'> {
it?: typeof it;
input1: Value;
input2: Value;
Expand Down Expand Up @@ -1449,11 +1449,9 @@ const fixtures: Record<string, ComputeDiffFixture> = {
],
},

shouldNotDiffDescendants: {
shouldDiffDescendants: ([firstNode]) =>
!firstNode ||
!isText(firstNode) ||
!firstNode.text.startsWith('NO_DIFF_INLINE'),
unrelatedTexts: {
elementsAreRelated: (element) =>
!getNodeString(element).startsWith('NO_DIFF_INLINE'),
input1: [
{
type: 'paragraph',
Expand Down Expand Up @@ -1545,6 +1543,69 @@ const fixtures: Record<string, ComputeDiffFixture> = {
},
],
},

customRelatedFunction: {
elementsAreRelated: (element, nextElement) => {
const getId = (e: TElement) => getNodeString(e).split('/')[0];
return getId(element) === getId(nextElement);
},
input1: [
{
type: 'paragraph',
children: [{ text: '1/First paragraph' }],
},
{
type: 'paragraph',
children: [{ text: '2/Second paragraph' }],
},
],
input2: [
{
type: 'paragraph',
children: [{ text: '3/Added paragraph 1' }],
},
{
type: 'paragraph',
children: [{ text: '1/First paragraph modified' }],
},
{
type: 'paragraph',
children: [{ text: '4/Added paragraph 2' }],
},
{
type: 'paragraph',
children: [{ text: '2/Second paragraph modified' }],
},
],
expected: [
{
type: 'paragraph',
children: [{ text: '3/Added paragraph 1' }],
diff: true,
diffOperation: { type: 'insert' },
},
{
type: 'paragraph',
children: [
{ text: '1/First paragraph' },
{ text: ' modified', diff: true, diffOperation: { type: 'insert' } },
],
},
{
type: 'paragraph',
children: [{ text: '4/Added paragraph 2' }],
diff: true,
diffOperation: { type: 'insert' },
},
{
type: 'paragraph',
children: [
{ text: '2/Second paragraph' },
{ text: ' modified', diff: true, diffOperation: { type: 'insert' } },
],
},
],
},
};

describe('computeDiff', () => {
Expand Down
10 changes: 5 additions & 5 deletions packages/diff/src/computeDiff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* contributors. See /packages/diff/LICENSE for more information.
*/

import { PlateEditor, TDescendant } from '@udecode/plate-common';
import { PlateEditor, TDescendant, TElement } from '@udecode/plate-common';

import { transformDiffDescendants } from './internal/transforms/transformDiffDescendants';
import { dmp } from './internal/utils/dmp';
Expand All @@ -14,10 +14,10 @@ export interface ComputeDiffOptions {
isInline: PlateEditor['isInline'];
ignoreProps?: string[];
lineBreakChar?: string;
shouldDiffDescendants?: (
nodes: TDescendant[],
nextNodes: TDescendant[]
) => boolean;
elementsAreRelated?: (
element: TElement,
nextElement: TElement
) => boolean | null;
getInsertProps: (node: TDescendant) => any;
getDeleteProps: (node: TDescendant) => any;
getUpdateProps: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export function transformDiffDescendants(
}

// If not all nodes are text nodes, use diffNodes to generate operations
const diffResult = diffNodes(nodes, nextNodes);
const diffResult = diffNodes(nodes, nextNodes, options);
diffResult.forEach((item: NodeRelatedItem) => {
if (item.delete) {
deleteNode(item.originNode);
Expand Down
6 changes: 0 additions & 6 deletions packages/diff/src/internal/transforms/transformDiffNodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,12 @@ type Handler = (
* algorithm on the children.
*/
const childrenOnlyStrategy: Handler = (node, nextNode, options) => {
const { shouldDiffDescendants = () => true } = options;

if (
node['children'] != null &&
nextNode['children'] != null &&
isEqual(
copyWithout(node, ['children']),
copyWithout(nextNode, ['children'])
) &&
shouldDiffDescendants(
node['children'] as TDescendant[],
nextNode['children'] as TDescendant[]
)
) {
const children = computeDiff(
Expand Down
9 changes: 8 additions & 1 deletion packages/diff/src/internal/utils/diff-nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
import { isElement, isText, TDescendant } from '@udecode/plate-common';
import isEqual from 'lodash/isEqual.js';

import { ComputeDiffOptions } from '../../computeDiff';
import { copyWithout } from './copy-without';

export function diffNodes(
originNodes: TDescendant[],
targetNodes: TDescendant[]
targetNodes: TDescendant[],
{ elementsAreRelated }: ComputeDiffOptions
) {
const result: NodeRelatedItem[] = [];
let relatedNode: TDescendant | undefined;
Expand All @@ -20,6 +22,11 @@ export function diffNodes(
let childrenUpdated = false;
let nodeUpdated = false;
relatedNode = leftTargetNodes.find((targetNode: TDescendant) => {
if (isElement(originNode) && isElement(targetNode)) {
const relatedResult =
elementsAreRelated?.(originNode, targetNode) ?? null;
if (relatedResult !== null) return relatedResult;
}
if (isEqualNode(originNode, targetNode)) {
childrenUpdated = true;
}
Expand Down

0 comments on commit a278858

Please sign in to comment.