From edb7c3bd3cff49455e47b47668a90fb72e9db59d Mon Sep 17 00:00:00 2001 From: urugator Date: Wed, 21 Mar 2018 22:08:15 +0100 Subject: [PATCH] Fix normalize empty inline (#1698) * add test for normalization of nested empty inlines * fix normalization of nested empty inlines * add test for normalization of inlines with empty void * fix normalization of inlines containing empty void * fix linting errors --- .../slate/src/constants/core-schema-rules.js | 22 ++-- .../core/preserve-inline-with-empty-void.js | 101 ++++++++++++++++++ .../schema/core/remove-nested-empty-inline.js | 75 +++++++++++++ 3 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 packages/slate/test/schema/core/preserve-inline-with-empty-void.js create mode 100644 packages/slate/test/schema/core/remove-nested-empty-inline.js diff --git a/packages/slate/src/constants/core-schema-rules.js b/packages/slate/src/constants/core-schema-rules.js index 0f574e131..5b163eca3 100644 --- a/packages/slate/src/constants/core-schema-rules.js +++ b/packages/slate/src/constants/core-schema-rules.js @@ -95,20 +95,30 @@ const CORE_SCHEMA_RULES = [ /** * Ensure that inline non-void nodes are never empty. * - * This rule is applied to all blocks, because when they contain an empty - * inline, we need to remove the inline from that parent block. If `validate` - * was to be memoized, it should be against the parent node, not the inline - * themselves. + * This rule is applied to all blocks and inlines, because when they contain an empty + * inline, we need to remove the empty inline from that parent node. If `validate` + * was to be memoized, it should be against the parent node, not the empty inline itself. * * @type {Object} */ { validateNode(node) { - if (node.object != 'block') return + if (node.object != 'inline' && node.object != 'block') return + + function isEmpty(n) { + // text node is empty when text is empty + if (n.object === 'text') { + return n.text === '' + } + // void is always considered non-empty regardless of actual content + if (n.isVoid) return false + // otherwise node is empty if all children are empty + return !n.nodes.some(child => !isEmpty(child)) + } const invalids = node.nodes.filter( - n => n.object === 'inline' && n.isVoid === false && n.text === '' + child => child.object === 'inline' && isEmpty(child) ) if (!invalids.size) return diff --git a/packages/slate/test/schema/core/preserve-inline-with-empty-void.js b/packages/slate/test/schema/core/preserve-inline-with-empty-void.js new file mode 100644 index 000000000..4c17f9d51 --- /dev/null +++ b/packages/slate/test/schema/core/preserve-inline-with-empty-void.js @@ -0,0 +1,101 @@ +/** @jsx h */ + +import h from '../../helpers/h' + +export const schema = {} + +export const input = ( + + + + + + + + + +) + +export const output = { + object: 'value', + document: { + object: 'document', + data: {}, + nodes: [ + { + object: 'block', + type: 'paragraph', + isVoid: false, + data: {}, + nodes: [ + { + object: 'text', + leaves: [ + { + object: 'leaf', + text: '', + marks: [], + }, + ], + }, + { + object: 'inline', + type: 'link', + isVoid: false, + data: {}, + nodes: [ + { + object: 'text', + leaves: [ + { + object: 'leaf', + text: '', + marks: [], + }, + ], + }, + { + object: 'inline', + type: '', + isVoid: true, + data: {}, + nodes: [ + { + object: 'text', + leaves: [ + { + object: 'leaf', + text: '', + marks: [], + }, + ], + }, + ], + }, + { + object: 'text', + leaves: [ + { + object: 'leaf', + text: '', + marks: [], + }, + ], + }, + ], + }, + { + object: 'text', + leaves: [ + { + object: 'leaf', + text: '', + marks: [], + }, + ], + }, + ], + }, + ], + }, +} diff --git a/packages/slate/test/schema/core/remove-nested-empty-inline.js b/packages/slate/test/schema/core/remove-nested-empty-inline.js new file mode 100644 index 000000000..b6daa9d6e --- /dev/null +++ b/packages/slate/test/schema/core/remove-nested-empty-inline.js @@ -0,0 +1,75 @@ +/** @jsx h */ + +import h from '../../helpers/h' + +export const schema = {} + +export const input = ( + + + + + one + + two + + + + +) + +export const output = { + object: 'value', + document: { + object: 'document', + data: {}, + nodes: [ + { + object: 'block', + type: 'paragraph', + isVoid: false, + data: {}, + nodes: [ + { + object: 'text', + leaves: [ + { + object: 'leaf', + text: '', + marks: [], + }, + ], + }, + { + object: 'inline', + type: 'link', + isVoid: false, + data: {}, + nodes: [ + { + object: 'text', + leaves: [ + { + object: 'leaf', + text: 'onetwo', + marks: [], + }, + ], + }, + ], + }, + { + object: 'text', + leaves: [ + { + object: 'leaf', + text: '', + marks: [], + }, + ], + }, + ], + }, + ], + }, +}