1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-04-22 14:21:54 +02:00

Consistent insert* methods (#5415)

* feat: add reviewpad.yml file

* Update reviewpad.yml

*  options to `Editor.insert*`

* 📝 options to `Editor.insert*`

*  getDefaultInsertLocation

*  getDefaultInsertLocation

*  getDefaultInsertLocation

* 📝 consistent selection

* Create tasty-lizards-remain.md

* Update tasty-lizards-remain.md

---------

Co-authored-by: reviewpad[bot] <104832597+reviewpad[bot]@users.noreply.github.com>
Co-authored-by: Dylan Schiemann <dylan@dojotoolkit.org>
This commit is contained in:
Ziad Beyens 2023-05-07 00:41:42 +02:00 committed by GitHub
parent 48c18b5368
commit 01f0210bcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 92 additions and 60 deletions

View File

@ -0,0 +1,6 @@
---
'slate': patch
---
`Editor.insertFragment`, `Editor.insertNode`, `Editor.insertText` now accept `options`.
For all insert methods, the default location is now the editor selection if `at` is not defined, or the end of document if `editor.selection` is not defined.

View File

@ -246,23 +246,23 @@ Delete the content in the current selection.
Insert a block break at the current selection.
#### `Editor.insertFragment(editor: Editor, fragment: Node[]) => void`
#### `Editor.insertFragment(editor: Editor, fragment: Node[], options?) => void`
Inserts a fragment _at the current selection_.
Inserts a fragment at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
If the selection is currently expanded, it will be deleted first. To atomically insert nodes (including at the very beginning or end), use [Transforms.insertNodes](../transforms.md#transformsinsertnodeseditor-editor-nodes-node--node-options).
Options: `{at?: Location, hanging?: boolean, voids?: boolean}`
#### `Editor.insertNode(editor: Editor, node: Node) => void`
#### `Editor.insertNode(editor: Editor, node: Node, options?) => void`
Inserts a node _at the current selection_.
Atomically insert `node` at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
If the selection is currently expanded, it will be deleted first. To atomically insert a node (including at the very beginning or end), use [Transforms.insertNodes](../transforms.md#transformsinsertnodeseditor-editor-nodes-node--node-options).
Options supported: `NodeOptions & {hanging?: boolean, select?: boolean}`.
#### `Editor.insertText(editor: Editor, text: string) => void`
#### `Editor.insertText(editor: Editor, text: string, options?) => void`
Inserts text _at the current selection_.
Insert a string of text at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
If the selection is currently expanded, it will be deleted first.
Options: `{at?: Location, voids?: boolean}`
#### `Editor.removeMark(editor: Editor, key: string) => void`

View File

@ -38,13 +38,13 @@ Transforms that operate on nodes.
#### `Transforms.insertFragment(editor: Editor, fragment: Node[], options?)`
Insert of fragment of nodes at the specified location in the document. If no location is specified, insert at the current selection.
Insert of fragment of nodes at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
Options: `{at?: Location, hanging?: boolean, voids?: boolean}`
#### `Transforms.insertNodes(editor: Editor, nodes: Node | Node[], options?)`
Atomically inserts `nodes` at the specified location in the document. If no location is specified, inserts at the current selection. If there is no selection, inserts at the end of the document.
Atomically inserts `nodes` at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
Options supported: `NodeOptions & {hanging?: boolean, select?: boolean}`.
@ -170,7 +170,7 @@ Options: `{at?: Location, distance?: number, unit?: 'character' | 'word' | 'line
#### `Transforms.insertText(editor: Editor, text: string, options?)`
Insert a string of text at the specified location in the document. If no location is specified, insert at the current selection.
Insert a string of text at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
Options: `{at?: Location, voids?: boolean}`

View File

@ -1,6 +1,10 @@
import { Transforms } from '../interfaces/transforms'
import { EditorInterface } from '../interfaces/editor'
export const insertNode: EditorInterface['insertNode'] = (editor, node) => {
Transforms.insertNodes(editor, node)
export const insertNode: EditorInterface['insertNode'] = (
editor,
node,
options
) => {
Transforms.insertNodes(editor, node, options)
}

View File

@ -11,7 +11,10 @@ export const insertText: EditorInterface['insertText'] = (
if (selection) {
if (marks) {
const node = { text, ...marks }
Transforms.insertNodes(editor, node)
Transforms.insertNodes(editor, node, {
at: options.at,
voids: options.voids,
})
} else {
Transforms.insertText(editor, text, options)
}

View File

@ -28,7 +28,11 @@ import {
} from '../types/types'
import { OmitFirstArg } from '../utils/types'
import { isEditor } from '../editor/is-editor'
import { TextInsertTextOptions } from './transforms/text'
import {
TextInsertFragmentOptions,
TextInsertTextOptions,
} from './transforms/text'
import { NodeInsertNodesOptions } from './transforms/node'
/**
* The `Editor` interface stores all the state of a Slate editor. It is extended
@ -412,18 +416,24 @@ export interface EditorInterface {
insertBreak: (editor: Editor) => void
/**
* Insert a fragment at the current selection.
*
* If the selection is currently expanded, it will be deleted first.
* Inserts a fragment
* at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
*/
insertFragment: (editor: Editor, fragment: Node[]) => void
insertFragment: (
editor: Editor,
fragment: Node[],
options?: TextInsertFragmentOptions
) => void
/**
* Insert a node at the current selection.
*
* If the selection is currently expanded, it will be deleted first.
* Atomically inserts `nodes`
* at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
*/
insertNode: (editor: Editor, node: Node) => void
insertNode: <T extends Node>(
editor: Editor,
node: Node,
options?: NodeInsertNodesOptions<T>
) => void
/**
* Insert a soft break at the current selection.
@ -433,9 +443,8 @@ export interface EditorInterface {
insertSoftBreak: (editor: Editor) => void
/**
* Insert text at the current selection.
*
* If the selection is currently expanded, it will be deleted first.
* Insert a string of text
* at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
*/
insertText: (
editor: Editor,
@ -774,8 +783,8 @@ export const Editor: EditorInterface = {
editor.insertBreak()
},
insertFragment(editor, fragment) {
editor.insertFragment(fragment)
insertFragment(editor, fragment, options) {
editor.insertFragment(fragment, options)
},
insertNode(editor, node) {

View File

@ -2,21 +2,24 @@ import { Editor, Element, Location, Node, Path } from '../../index'
import { NodeMatch, PropsCompare, PropsMerge } from '../editor'
import { MaximizeMode, RangeMode } from '../../types/types'
export interface NodeInsertNodesOptions<T extends Node> {
at?: Location
match?: NodeMatch<T>
mode?: RangeMode
hanging?: boolean
select?: boolean
voids?: boolean
}
export interface NodeTransforms {
/**
* Insert nodes at a specific location in the Editor.
* Insert nodes in the editor
* at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
*/
insertNodes: <T extends Node>(
editor: Editor,
nodes: Node | Node[],
options?: {
at?: Location
match?: NodeMatch<T>
mode?: RangeMode
hanging?: boolean
select?: boolean
voids?: boolean
}
options?: NodeInsertNodesOptions<T>
) => void
/**

View File

@ -1,5 +1,6 @@
import { Editor, Location, Node, Path, Range, Transforms } from '../../index'
import { TextUnit } from '../../types/types'
import { getDefaultInsertLocation } from '../../utils'
export interface TextDeleteOptions {
at?: Location
@ -28,7 +29,8 @@ export interface TextTransforms {
delete: (editor: Editor, options?: TextDeleteOptions) => void
/**
* Insert a fragment at a specific location in the editor.
* Insert a fragment in the editor
* at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
*/
insertFragment: (
editor: Editor,
@ -37,7 +39,8 @@ export interface TextTransforms {
) => void
/**
* Insert a string of text in the Editor.
* Insert a string of text in the editor
* at the specified location or (if not defined) the current selection or (if not defined) the end of the document.
*/
insertText: (
editor: Editor,
@ -61,11 +64,7 @@ export const TextTransforms: TextTransforms = {
): void {
Editor.withoutNormalizing(editor, () => {
const { voids = false } = options
let { at = editor.selection } = options
if (!at) {
return
}
let { at = getDefaultInsertLocation(editor) } = options
if (Path.isPath(at)) {
at = Editor.range(editor, at)

View File

@ -7,6 +7,7 @@ import { Point } from '../interfaces/point'
import { Text } from '../interfaces/text'
import { Element } from '../interfaces/element'
import { Path } from '../interfaces/path'
import { getDefaultInsertLocation } from '../utils'
export const insertNodes: NodeTransforms['insertNodes'] = (
editor,
@ -27,18 +28,8 @@ export const insertNodes: NodeTransforms['insertNodes'] = (
const [node] = nodes
// By default, use the selection as the target location. But if there is
// no selection, insert at the end of the document since that is such a
// common use case when inserting from a non-selected state.
if (!at) {
if (editor.selection) {
at = editor.selection
} else if (editor.children.length > 0) {
at = Editor.end(editor, [])
} else {
at = [0]
}
at = getDefaultInsertLocation(editor)
select = true
}

View File

@ -6,6 +6,7 @@ import { Element } from '../interfaces/element'
import { Node, NodeEntry } from '../interfaces/node'
import { Text } from '../interfaces/text'
import { TextTransforms } from '../interfaces/transforms/text'
import { getDefaultInsertLocation } from '../utils'
export const insertFragment: TextTransforms['insertFragment'] = (
editor,
@ -14,15 +15,13 @@ export const insertFragment: TextTransforms['insertFragment'] = (
) => {
Editor.withoutNormalizing(editor, () => {
const { hanging = false, voids = false } = options
let { at = editor.selection } = options
let { at = getDefaultInsertLocation(editor) } = options
if (!fragment.length) {
return
}
if (!at) {
return
} else if (Range.isRange(at)) {
if (Range.isRange(at)) {
if (!hanging) {
at = Editor.unhangRange(editor, at, { voids })
}

View File

@ -0,0 +1,17 @@
import { Editor, Location } from '../interfaces'
/**
* Get the default location to insert content into the editor.
* By default, use the selection as the target location. But if there is
* no selection, insert at the end of the document since that is such a
* common use case when inserting from a non-selected state.
*/
export const getDefaultInsertLocation = (editor: Editor): Location => {
if (editor.selection) {
return editor.selection
} else if (editor.children.length > 0) {
return Editor.end(editor, [])
} else {
return [0]
}
}

View File

@ -1,4 +1,5 @@
export * from './deep-equal'
export * from './get-default-insert-location'
export * from './match-path'
export * from './string'
export * from './types'