From e4e48b9fa75bda5f7006269d5b6d9570b149a00a Mon Sep 17 00:00:00 2001 From: Tim Buckley Date: Wed, 31 Mar 2021 16:44:26 -0400 Subject: [PATCH] `Text.equals` now works with more nested Text nodes, and non-primitive attributes. (#3532) * Use lodash.isEqual to compare text nodes The key improvement here is that this allows Text nodes to have more complex attributes like objects. The previous behavior failed to find equivalent object properties as equal due to JS's !== reference check. * Install lodash in slate's pkgjson --- packages/slate/package.json | 1 + packages/slate/src/interfaces/text.ts | 27 +++++-------------- .../Text/equals/complex-exact-equals.js | 20 ++++++++++++++ .../Text/equals/complex-exact-not-equal.js | 20 ++++++++++++++ .../Text/equals/complex-loose-equals.js | 20 ++++++++++++++ .../Text/equals/complex-loose-not-equal.js | 20 ++++++++++++++ .../interfaces/Text/equals/exact-equals.js | 12 +++++++++ .../interfaces/Text/equals/exact-not-equal.js | 12 +++++++++ .../interfaces/Text/equals/loose-equals.js | 12 +++++++++ .../interfaces/Text/equals/loose-not-equal.js | 12 +++++++++ 10 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 packages/slate/test/interfaces/Text/equals/complex-exact-equals.js create mode 100644 packages/slate/test/interfaces/Text/equals/complex-exact-not-equal.js create mode 100644 packages/slate/test/interfaces/Text/equals/complex-loose-equals.js create mode 100644 packages/slate/test/interfaces/Text/equals/complex-loose-not-equal.js create mode 100644 packages/slate/test/interfaces/Text/equals/exact-equals.js create mode 100644 packages/slate/test/interfaces/Text/equals/exact-not-equal.js create mode 100644 packages/slate/test/interfaces/Text/equals/loose-equals.js create mode 100644 packages/slate/test/interfaces/Text/equals/loose-not-equal.js diff --git a/packages/slate/package.json b/packages/slate/package.json index 39c6534e1..ebb79e9d8 100644 --- a/packages/slate/package.json +++ b/packages/slate/package.json @@ -18,6 +18,7 @@ "esrever": "^0.2.0", "immer": "^7.0.0", "is-plain-object": "^3.0.0", + "lodash": "^4.17.4", "tiny-warning": "^1.0.3" }, "keywords": [ diff --git a/packages/slate/src/interfaces/text.ts b/packages/slate/src/interfaces/text.ts index cdadaef69..d9cfc244b 100755 --- a/packages/slate/src/interfaces/text.ts +++ b/packages/slate/src/interfaces/text.ts @@ -1,4 +1,6 @@ import isPlainObject from 'is-plain-object' +import isEqual from 'lodash/isEqual' +import omit from 'lodash/omit' import { Range } from '..' import { ExtendedType } from './custom-types' @@ -35,27 +37,10 @@ export const Text: TextInterface = { ): boolean { const { loose = false } = options - for (const key in text) { - if (loose && key === 'text') { - continue - } - - if (text[key] !== another[key]) { - return false - } - } - - for (const key in another) { - if (loose && key === 'text') { - continue - } - - if (text[key] !== another[key]) { - return false - } - } - - return true + return isEqual( + loose ? omit(text, 'text') : text, + loose ? omit(another, 'text') : another + ) }, /** diff --git a/packages/slate/test/interfaces/Text/equals/complex-exact-equals.js b/packages/slate/test/interfaces/Text/equals/complex-exact-equals.js new file mode 100644 index 000000000..ab6511b49 --- /dev/null +++ b/packages/slate/test/interfaces/Text/equals/complex-exact-equals.js @@ -0,0 +1,20 @@ +import { Text } from 'slate' + +export const input = { + textNodeA: { + text: 'same text', + bold: true, + italic: { origin: 'inherited', value: false }, + }, + textNodeB: { + text: 'same text', + bold: true, + italic: { origin: 'inherited', value: false }, + }, +} + +export const test = ({ textNodeA, textNodeB }) => { + return Text.equals(textNodeA, textNodeB, { loose: false }) +} + +export const output = true diff --git a/packages/slate/test/interfaces/Text/equals/complex-exact-not-equal.js b/packages/slate/test/interfaces/Text/equals/complex-exact-not-equal.js new file mode 100644 index 000000000..fa4578648 --- /dev/null +++ b/packages/slate/test/interfaces/Text/equals/complex-exact-not-equal.js @@ -0,0 +1,20 @@ +import { Text } from 'slate' + +export const input = { + textNodeA: { + text: 'same text', + bold: true, + italic: { origin: 'inherited', value: false }, + }, + textNodeB: { + text: 'same text', + bold: true, + italic: { origin: 'inherited', value: true }, + }, +} + +export const test = ({ textNodeA, textNodeB }) => { + return Text.equals(textNodeA, textNodeB, { loose: false }) +} + +export const output = false diff --git a/packages/slate/test/interfaces/Text/equals/complex-loose-equals.js b/packages/slate/test/interfaces/Text/equals/complex-loose-equals.js new file mode 100644 index 000000000..8eae2339f --- /dev/null +++ b/packages/slate/test/interfaces/Text/equals/complex-loose-equals.js @@ -0,0 +1,20 @@ +import { Text } from 'slate' + +export const input = { + textNodeA: { + text: 'same text', + bold: true, + italic: { origin: 'inherited', value: false }, + }, + textNodeB: { + text: 'diff text', + bold: true, + italic: { origin: 'inherited', value: false }, + }, +} + +export const test = ({ textNodeA, textNodeB }) => { + return Text.equals(textNodeA, textNodeB, { loose: true }) +} + +export const output = true diff --git a/packages/slate/test/interfaces/Text/equals/complex-loose-not-equal.js b/packages/slate/test/interfaces/Text/equals/complex-loose-not-equal.js new file mode 100644 index 000000000..fa4578648 --- /dev/null +++ b/packages/slate/test/interfaces/Text/equals/complex-loose-not-equal.js @@ -0,0 +1,20 @@ +import { Text } from 'slate' + +export const input = { + textNodeA: { + text: 'same text', + bold: true, + italic: { origin: 'inherited', value: false }, + }, + textNodeB: { + text: 'same text', + bold: true, + italic: { origin: 'inherited', value: true }, + }, +} + +export const test = ({ textNodeA, textNodeB }) => { + return Text.equals(textNodeA, textNodeB, { loose: false }) +} + +export const output = false diff --git a/packages/slate/test/interfaces/Text/equals/exact-equals.js b/packages/slate/test/interfaces/Text/equals/exact-equals.js new file mode 100644 index 000000000..bbfe4ef00 --- /dev/null +++ b/packages/slate/test/interfaces/Text/equals/exact-equals.js @@ -0,0 +1,12 @@ +import { Text } from 'slate' + +export const input = { + textNodeA: { text: 'same text', bold: true }, + textNodeB: { text: 'same text', bold: true }, +} + +export const test = ({ textNodeA, textNodeB }) => { + return Text.equals(textNodeA, textNodeB, { loose: false }) +} + +export const output = true diff --git a/packages/slate/test/interfaces/Text/equals/exact-not-equal.js b/packages/slate/test/interfaces/Text/equals/exact-not-equal.js new file mode 100644 index 000000000..ca2010918 --- /dev/null +++ b/packages/slate/test/interfaces/Text/equals/exact-not-equal.js @@ -0,0 +1,12 @@ +import { Text } from 'slate' + +export const input = { + textNodeA: { text: 'same text', bold: true }, + textNodeB: { text: 'same text', bold: true, italic: true }, +} + +export const test = ({ textNodeA, textNodeB }) => { + return Text.equals(textNodeA, textNodeB, { loose: false }) +} + +export const output = false diff --git a/packages/slate/test/interfaces/Text/equals/loose-equals.js b/packages/slate/test/interfaces/Text/equals/loose-equals.js new file mode 100644 index 000000000..e0133f181 --- /dev/null +++ b/packages/slate/test/interfaces/Text/equals/loose-equals.js @@ -0,0 +1,12 @@ +import { Text } from 'slate' + +export const input = { + textNodeA: { text: 'some text', bold: true }, + textNodeB: { text: 'diff text', bold: true }, +} + +export const test = ({ textNodeA, textNodeB }) => { + return Text.equals(textNodeA, textNodeB, { loose: true }) +} + +export const output = true diff --git a/packages/slate/test/interfaces/Text/equals/loose-not-equal.js b/packages/slate/test/interfaces/Text/equals/loose-not-equal.js new file mode 100644 index 000000000..5e3714a32 --- /dev/null +++ b/packages/slate/test/interfaces/Text/equals/loose-not-equal.js @@ -0,0 +1,12 @@ +import { Text } from 'slate' + +export const input = { + textNodeA: { text: 'same text', bold: true }, + textNodeB: { text: 'same text', bold: true, italic: true }, +} + +export const test = ({ textNodeA, textNodeB }) => { + return Text.equals(textNodeA, textNodeB, { loose: true }) +} + +export const output = false