From a5f4170162cefd1c9458544402bb8f2266e05ead Mon Sep 17 00:00:00 2001 From: Tommy Dong Date: Tue, 10 Nov 2020 20:56:25 -0600 Subject: [PATCH] Editor.next and Editor.previous now return the first match (#3957) * Fixes to Editor.next and Editor.previous along with methods used therein (Editor.before, Editor.after, Editor.positions). --- packages/slate/src/interfaces/editor.ts | 69 ++++++++++++++----- .../interfaces/Editor/after/path-void.tsx | 19 +++++ .../interfaces/Editor/after/point-void.tsx | 16 +++++ .../interfaces/Editor/after/range-void.tsx | 24 +++++++ .../interfaces/Editor/before/path-void.tsx | 17 +++++ .../interfaces/Editor/before/point-void.tsx | 16 +++++ .../interfaces/Editor/before/range-void.tsx | 24 +++++++ .../voids-true/block-all-reverse.tsx | 20 ++++++ .../Editor/positions/voids-true/block-all.tsx | 18 +++++ .../voids-true/inline-all-reverse.tsx | 32 +++++++++ .../positions/voids-true/inline-all.tsx | 30 ++++++++ .../Editor/string/block-voids-true.tsx | 16 +++++ .../transforms/moveNodes/path/text-nodes.tsx | 17 +++-- .../transforms/moveNodes/voids-true/block.tsx | 8 ++- 14 files changed, 299 insertions(+), 27 deletions(-) create mode 100644 packages/slate/test/interfaces/Editor/after/path-void.tsx create mode 100644 packages/slate/test/interfaces/Editor/after/point-void.tsx create mode 100644 packages/slate/test/interfaces/Editor/after/range-void.tsx create mode 100644 packages/slate/test/interfaces/Editor/before/path-void.tsx create mode 100644 packages/slate/test/interfaces/Editor/before/point-void.tsx create mode 100644 packages/slate/test/interfaces/Editor/before/range-void.tsx create mode 100644 packages/slate/test/interfaces/Editor/positions/voids-true/block-all-reverse.tsx create mode 100644 packages/slate/test/interfaces/Editor/positions/voids-true/block-all.tsx create mode 100644 packages/slate/test/interfaces/Editor/positions/voids-true/inline-all-reverse.tsx create mode 100644 packages/slate/test/interfaces/Editor/positions/voids-true/inline-all.tsx create mode 100644 packages/slate/test/interfaces/Editor/string/block-voids-true.tsx diff --git a/packages/slate/src/interfaces/editor.ts b/packages/slate/src/interfaces/editor.ts index 32991524c..8e8ff7197 100755 --- a/packages/slate/src/interfaces/editor.ts +++ b/packages/slate/src/interfaces/editor.ts @@ -121,6 +121,7 @@ export const Editor = { options: { distance?: number unit?: 'offset' | 'character' | 'word' | 'line' | 'block' + voids?: boolean } = {} ): Point | undefined { const anchor = Editor.point(editor, at, { edge: 'end' }) @@ -130,7 +131,10 @@ export const Editor = { let d = 0 let target - for (const p of Editor.positions(editor, { ...options, at: range })) { + for (const p of Editor.positions(editor, { + ...options, + at: range, + })) { if (d > distance) { break } @@ -155,6 +159,7 @@ export const Editor = { options: { distance?: number unit?: 'offset' | 'character' | 'word' | 'line' | 'block' + voids?: boolean } = {} ): Point | undefined { const anchor = Editor.start(editor, []) @@ -570,9 +575,13 @@ export const Editor = { return } - const [, from] = Editor.last(editor, at) + const pointAfterLocation = Editor.after(editor, at, { voids }) + + if (!pointAfterLocation) return + const [, to] = Editor.last(editor, []) - const span: Span = [from, to] + + const span: Span = [pointAfterLocation.path, to] if (Path.isPath(at) && at.length === 0) { throw new Error(`Cannot get the next node from the root node!`) @@ -587,7 +596,7 @@ export const Editor = { } } - const [, next] = Editor.nodes(editor, { at: span, match, mode, voids }) + const [next] = Editor.nodes(editor, { at: span, match, mode, voids }) return next }, @@ -973,8 +982,9 @@ export const Editor = { * can pass the `unit: 'character'` option to moved forward one character, word, * or line at at time. * - * Note: void nodes are treated as a single point, and iteration will not - * happen inside their content. + * Note: By default void nodes are treated as a single point and iteration + * will not happen inside their content unless you pass in true for the + * voids option, then iteration will occur. */ *positions( @@ -983,9 +993,15 @@ export const Editor = { at?: Location unit?: 'offset' | 'character' | 'word' | 'line' | 'block' reverse?: boolean + voids?: boolean } = {} ): Generator { - const { at = editor.selection, unit = 'offset', reverse = false } = options + const { + at = editor.selection, + unit = 'offset', + reverse = false, + voids = false, + } = options if (!at) { return @@ -1024,11 +1040,12 @@ export const Editor = { distance = available >= 0 ? null : 0 - available } - for (const [node, path] of Editor.nodes(editor, { at, reverse })) { + for (const [node, path] of Editor.nodes(editor, { at, reverse, voids })) { if (Element.isElement(node)) { - // Void nodes are a special case, since we don't want to iterate over - // their content. We instead always just yield their first point. - if (editor.isVoid(node)) { + // Void nodes are a special case, so by default we will always + // yield their first point. If the voids option is set to true, + // then we will iterate over their content + if (!voids && editor.isVoid(node)) { yield Editor.start(editor, path) continue } @@ -1045,7 +1062,7 @@ export const Editor = { ? start : Editor.start(editor, path) - const text = Editor.string(editor, { anchor: s, focus: e }) + const text = Editor.string(editor, { anchor: s, focus: e }, { voids }) string = reverse ? reverseText(text) : text isNewBlock = true } @@ -1107,9 +1124,17 @@ export const Editor = { return } - const [, from] = Editor.first(editor, at) + const pointBeforeLocation = Editor.before(editor, at, { voids }) + + if (!pointBeforeLocation) { + return + } + const [, to] = Editor.first(editor, []) - const span: Span = [from, to] + + // The search location is from the start of the document to the path of + // the point before the location passed in + const span: Span = [pointBeforeLocation.path, to] if (Path.isPath(at) && at.length === 0) { throw new Error(`Cannot get the previous node from the root node!`) @@ -1124,7 +1149,7 @@ export const Editor = { } } - const [, previous] = Editor.nodes(editor, { + const [previous] = Editor.nodes(editor, { reverse: true, at: span, match, @@ -1217,11 +1242,18 @@ export const Editor = { /** * Get the text string content of a location. * - * Note: the text of void nodes is presumed to be an empty string, regardless - * of what their actual content is. + * Note: by default the text of void nodes is considered to be an empty + * string, regardless of content, unless you pass in true for the voids option */ - string(editor: Editor, at: Location): string { + string( + editor: Editor, + at: Location, + options: { + voids?: boolean + } = {} + ): string { + const { voids = false } = options const range = Editor.range(editor, at) const [start, end] = Range.edges(range) let text = '' @@ -1229,6 +1261,7 @@ export const Editor = { for (const [node, path] of Editor.nodes(editor, { at: range, match: Text.isText, + voids, })) { let t = node.text diff --git a/packages/slate/test/interfaces/Editor/after/path-void.tsx b/packages/slate/test/interfaces/Editor/after/path-void.tsx new file mode 100644 index 000000000..5864507d0 --- /dev/null +++ b/packages/slate/test/interfaces/Editor/after/path-void.tsx @@ -0,0 +1,19 @@ +/** @jsx jsx */ + +import { Editor } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + + one + two + + +) + +export const test = editor => { + return Editor.after(editor, [0, 0], { voids: true }) +} + +export const output = { path: [0, 1], offset: 0 } diff --git a/packages/slate/test/interfaces/Editor/after/point-void.tsx b/packages/slate/test/interfaces/Editor/after/point-void.tsx new file mode 100644 index 000000000..8b297c880 --- /dev/null +++ b/packages/slate/test/interfaces/Editor/after/point-void.tsx @@ -0,0 +1,16 @@ +/** @jsx jsx */ + +import { Editor } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + one + +) + +export const test = editor => { + return Editor.after(editor, { path: [0, 0], offset: 1 }, { voids: true }) +} + +export const output = { path: [0, 0], offset: 2 } diff --git a/packages/slate/test/interfaces/Editor/after/range-void.tsx b/packages/slate/test/interfaces/Editor/after/range-void.tsx new file mode 100644 index 000000000..9d058d4d5 --- /dev/null +++ b/packages/slate/test/interfaces/Editor/after/range-void.tsx @@ -0,0 +1,24 @@ +/** @jsx jsx */ + +import { Editor } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + one + two + +) + +export const test = editor => { + return Editor.after( + editor, + { + anchor: { path: [0, 0], offset: 1 }, + focus: { path: [1, 0], offset: 2 }, + }, + { voids: true } + ) +} + +export const output = { path: [1, 0], offset: 3 } diff --git a/packages/slate/test/interfaces/Editor/before/path-void.tsx b/packages/slate/test/interfaces/Editor/before/path-void.tsx new file mode 100644 index 000000000..6644821ca --- /dev/null +++ b/packages/slate/test/interfaces/Editor/before/path-void.tsx @@ -0,0 +1,17 @@ +/** @jsx jsx */ + +import { Editor } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + one + two + +) + +export const test = editor => { + return Editor.before(editor, [1, 0], { voids: true }) +} + +export const output = { path: [0, 0], offset: 3 } diff --git a/packages/slate/test/interfaces/Editor/before/point-void.tsx b/packages/slate/test/interfaces/Editor/before/point-void.tsx new file mode 100644 index 000000000..d656eb0c6 --- /dev/null +++ b/packages/slate/test/interfaces/Editor/before/point-void.tsx @@ -0,0 +1,16 @@ +/** @jsx jsx */ + +import { Editor } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + one + +) + +export const test = editor => { + return Editor.before(editor, { path: [0, 0], offset: 1 }, { voids: true }) +} + +export const output = { path: [0, 0], offset: 0 } diff --git a/packages/slate/test/interfaces/Editor/before/range-void.tsx b/packages/slate/test/interfaces/Editor/before/range-void.tsx new file mode 100644 index 000000000..bb737ddd4 --- /dev/null +++ b/packages/slate/test/interfaces/Editor/before/range-void.tsx @@ -0,0 +1,24 @@ +/** @jsx jsx */ + +import { Editor } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + one + two + +) + +export const test = editor => { + return Editor.before( + editor, + { + anchor: { path: [0, 0], offset: 1 }, + focus: { path: [0, 1], offset: 2 }, + }, + { voids: true } + ) +} + +export const output = { path: [0, 0], offset: 0 } diff --git a/packages/slate/test/interfaces/Editor/positions/voids-true/block-all-reverse.tsx b/packages/slate/test/interfaces/Editor/positions/voids-true/block-all-reverse.tsx new file mode 100644 index 000000000..f85911f67 --- /dev/null +++ b/packages/slate/test/interfaces/Editor/positions/voids-true/block-all-reverse.tsx @@ -0,0 +1,20 @@ +/** @jsx jsx */ +import { Editor } from 'slate' +import { jsx } from '../../../..' + +export const input = ( + + one + +) +export const test = editor => { + return Array.from( + Editor.positions(editor, { at: [], reverse: true, voids: true }) + ) +} +export const output = [ + { path: [0, 0], offset: 3 }, + { path: [0, 0], offset: 2 }, + { path: [0, 0], offset: 1 }, + { path: [0, 0], offset: 0 }, +] diff --git a/packages/slate/test/interfaces/Editor/positions/voids-true/block-all.tsx b/packages/slate/test/interfaces/Editor/positions/voids-true/block-all.tsx new file mode 100644 index 000000000..08127eacd --- /dev/null +++ b/packages/slate/test/interfaces/Editor/positions/voids-true/block-all.tsx @@ -0,0 +1,18 @@ +/** @jsx jsx */ +import { Editor } from 'slate' +import { jsx } from '../../../..' + +export const input = ( + + one + +) +export const test = editor => { + return Array.from(Editor.positions(editor, { at: [], voids: true })) +} +export const output = [ + { path: [0, 0], offset: 0 }, + { path: [0, 0], offset: 1 }, + { path: [0, 0], offset: 2 }, + { path: [0, 0], offset: 3 }, +] diff --git a/packages/slate/test/interfaces/Editor/positions/voids-true/inline-all-reverse.tsx b/packages/slate/test/interfaces/Editor/positions/voids-true/inline-all-reverse.tsx new file mode 100644 index 000000000..a3cb2f1b2 --- /dev/null +++ b/packages/slate/test/interfaces/Editor/positions/voids-true/inline-all-reverse.tsx @@ -0,0 +1,32 @@ +/** @jsx jsx */ +import { Editor } from 'slate' +import { jsx } from '../../../..' + +export const input = ( + + + onetwothree + + +) +export const test = editor => { + return Array.from( + Editor.positions(editor, { at: [], reverse: true, voids: true }) + ) +} +export const output = [ + { path: [0, 2], offset: 5 }, + { path: [0, 2], offset: 4 }, + { path: [0, 2], offset: 3 }, + { path: [0, 2], offset: 2 }, + { path: [0, 2], offset: 1 }, + { path: [0, 2], offset: 0 }, + { path: [0, 1, 0], offset: 3 }, + { path: [0, 1, 0], offset: 2 }, + { path: [0, 1, 0], offset: 1 }, + { path: [0, 1, 0], offset: 0 }, + { path: [0, 0], offset: 3 }, + { path: [0, 0], offset: 2 }, + { path: [0, 0], offset: 1 }, + { path: [0, 0], offset: 0 }, +] diff --git a/packages/slate/test/interfaces/Editor/positions/voids-true/inline-all.tsx b/packages/slate/test/interfaces/Editor/positions/voids-true/inline-all.tsx new file mode 100644 index 000000000..50a3b222c --- /dev/null +++ b/packages/slate/test/interfaces/Editor/positions/voids-true/inline-all.tsx @@ -0,0 +1,30 @@ +/** @jsx jsx */ +import { Editor } from 'slate' +import { jsx } from '../../../..' + +export const input = ( + + + onetwothree + + +) +export const test = editor => { + return Array.from(Editor.positions(editor, { at: [], voids: true })) +} +export const output = [ + { path: [0, 0], offset: 0 }, + { path: [0, 0], offset: 1 }, + { path: [0, 0], offset: 2 }, + { path: [0, 0], offset: 3 }, + { path: [0, 1, 0], offset: 0 }, + { path: [0, 1, 0], offset: 1 }, + { path: [0, 1, 0], offset: 2 }, + { path: [0, 1, 0], offset: 3 }, + { path: [0, 2], offset: 0 }, + { path: [0, 2], offset: 1 }, + { path: [0, 2], offset: 2 }, + { path: [0, 2], offset: 3 }, + { path: [0, 2], offset: 4 }, + { path: [0, 2], offset: 5 }, +] diff --git a/packages/slate/test/interfaces/Editor/string/block-voids-true.tsx b/packages/slate/test/interfaces/Editor/string/block-voids-true.tsx new file mode 100644 index 000000000..8e324969a --- /dev/null +++ b/packages/slate/test/interfaces/Editor/string/block-voids-true.tsx @@ -0,0 +1,16 @@ +/** @jsx jsx */ +import { Editor } from 'slate' +import { jsx } from '../../..' + +export const input = ( + + + one + two + + +) +export const test = editor => { + return Editor.string(editor, [0], { voids: true }) +} +export const output = `onetwo` diff --git a/packages/slate/test/transforms/moveNodes/path/text-nodes.tsx b/packages/slate/test/transforms/moveNodes/path/text-nodes.tsx index 1a21bd9db..14c856f43 100644 --- a/packages/slate/test/transforms/moveNodes/path/text-nodes.tsx +++ b/packages/slate/test/transforms/moveNodes/path/text-nodes.tsx @@ -4,10 +4,13 @@ import { jsx } from '../../..' export const input = ( - one + + bar + foo + - two + baz ) @@ -17,12 +20,14 @@ export const run = editor => { export const output = ( - + foo - one - - two + + bar + + baz + ) diff --git a/packages/slate/test/transforms/moveNodes/voids-true/block.tsx b/packages/slate/test/transforms/moveNodes/voids-true/block.tsx index f5e713c4d..09fb016a5 100644 --- a/packages/slate/test/transforms/moveNodes/voids-true/block.tsx +++ b/packages/slate/test/transforms/moveNodes/voids-true/block.tsx @@ -6,20 +6,22 @@ export const input = ( one two + three ) export const run = editor => { Transforms.moveNodes(editor, { - at: [0, 0], - to: [1, 0], + at: [1, 0], + to: [2, 0], voids: true, }) } export const output = ( + one - onetwo + twothree )