ianstormtaylor / slate

A completely customizable framework for building rich text editors. (Currently in beta.)
http://slatejs.org
MIT License
29.77k stars 3.24k forks source link

`Transforms.setNodes` unexpected behavior of `children` #5686

Open electroluxcode opened 2 months ago

electroluxcode commented 2 months ago

Description

it refer https://docs.slatejs.org/api/transforms#transforms.setnodes-editor-editor-props-partial-less-than-node-greater-than-options

Transforms.setNodes(editor: Editor, props: Partial<Node>, options?)

props: Partial<Node> has a prop named children ,However, when I read the source code in path packages\slate\src\interfaces\transforms\general.ts, I found that the props parameter named children did not render . There's this code

if (key === 'children' || key === 'text') {
  throw new Error(`Cannot set the "${key}" property of nodes! `)
}

this code makes it impossible for setNodes to handle nested cases with 'children'

Expectation

maybe setNodes should be able to handle nested cases with 'children'

Environment

eg

for example

   const path = ReactEditor.findPath(editor, element)
      const newProperties = {
        "type": "one",
        "children": [
          {
            "type": "two",
            "children": [
              {
                "type": "three",
                children:[{
                  text:"shouldbe replace"
                }]
              }
            ]
          }
        ]
      } as any

      Transforms.setNodes(editor, newProperties, { at: path })

this code will only render first level and missing children

it seem deliberate in reading source,i have quesion why would do that

thanks

WindRunnerMax commented 2 months ago

Adding nodes should not use setNodes, but rather APIs such as insertNodes

electroluxcode commented 2 months ago

Adding nodes should not use setNodes, but rather APIs such as insertNodes

hi, @WindrunnerMax thanks for your reply I understand your point; indeed, I can use the insertNode API. However, my requirement is to transform a section of nodes entirely into another node.

For example, in Markdown syntax, inputting - Your content automatically transforms into a ul (unordered list).

Currently, my workaround is to first use the removeNode API and then the insertNode API to replace setNodes, but this approach doesn't seem to be expectations and semantics.

for example,After removing andinsert nodes, the cursor will be positioned on the next line. You need to manually control the cursor position by developer

12joan commented 2 months ago

@electroluxcode Changing the content using setNodes wouldn't solve the selection problem. This isn't supported by Slate for the same reason that Slate isn't a controlled component. I wrote the following essay explaining why.

https://github.com/ianstormtaylor/slate/issues/5281#issuecomment-2234431664

electroluxcode commented 1 month ago

slate-diff can indeed solve the problem of setNodes. However, I think that slate should import the slate-diff library and use it as the logic of setNodes instead of making users perform additional operations.

12joan commented 1 month ago

slate-diff can indeed solve the problem of setNodes. However, I think that slate should import the slate-diff library and use it as the logic of setNodes instead of making users perform additional operations.

Unfortunately, that would severely increase Slate's bundle size and code complexity, and harm the predictability of its API. I don't think it's a good candidate for inclusion in core.