ianstormtaylor / slate

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

Nesting Block Elements #5358

Open jayaike opened 1 year ago

jayaike commented 1 year ago

Problem

I am creating a FeedbackElement that can wrap any element. So it could appear at the root of the editor (ie. one of the editors children) or as a child of some block node: like a paragraph. FeedbackElements can contain other FeedbackElements, or really any element, like images, lists, etc.

The only issue with this is that the default normalizeNode does not permit this (especially as a child of a paragraph). I could get this to work by completely disabling normalisation using a plugin that modifies normalizeNode to a noop function. But, of course, you don't want to do this because it creates its own sets of bugs.

The type definition for feedback is as follows:

export type FeedbackElement = {
  type: "feedback";
  feedback: string;
  children: Element[];
};

Solution There should be a way to nest block elements.

[
    {
        "type": "paragraph",
        "children": [
            {
                "text": "example "
            },
            {
                "type": "feedback",
                "feedback": "great job with this!"
                "children": [
                     {
                          "text": "some text "
                    },
                ]
            },
        ]
    },
    {
        "type": "paragraph",
        "children": [
            {
                "text": ""
            }
        ]
    }
]
tiberiuichim commented 1 year ago

I also hit this problem, but with lists.

If I have a list like https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul

the slate editor will remove the sublist element in the <li> image

This is due to https://github.com/ianstormtaylor/slate/blob/1d8010be8500ef5c98dbd4179354db1986d5c8f4/packages/slate/src/create-editor.ts#L253-L256

More context: https://github.com/plone/volto/issues/4538

tiberiuichim commented 1 year ago

@jayaike I've been exploring this similar problem, here's possible fixes:

jayaike commented 1 year ago

@tiberiuichim yea im also thinking of modifying the default normalizeNode fn to support my needs.

I see no reason why block nodes should not be nested. Nested block nodes would be similar to inline-block in regular HTML which is of course a thing.

tiberiuichim commented 1 year ago

@jayaike We usually implement isInline => true for all our custom elements.

jayaike commented 1 year ago

@tiberiuichim yes i considered this but that wont cover the case (for me) of where i wrap maybe 4 block elements. since inline elements dont typically contain block elements.

whereas a block element can contain block elements and inline elements.

my use case would be something like this.

<feedback>
   <p>Here is some random <feedback>data</feedback></p>
   <feedback><img src="..." /></feedback>
</feedback>

so really it is an inline-block type of element you could say

allison-luminos commented 8 months ago

Does anyone have an example of how to overwrite the normalizeNode method to support this?