elm-rte-toolkit icon indicating copy to clipboard operation
elm-rte-toolkit copied to clipboard

`htmlToElementArray` fails to parse "empty paragraphs"

Open abradley2 opened this issue 4 years ago • 4 comments

If there's an empty paragraph with no spaces and no zero width spaces, this will fail to be parsed by htmlToElementArray. It will instead hit the "Invalid node type for empty fragment result array" error branch.

emptyParagraph =
    "<p></p>"


test "Tests that an empty paragraph works as expected" <|
    \_ ->  case htmlToElementArray markdown emptyParagraph of
          Ok _ -> Expect.pass
          Err _ -> Expect.fail "Failed to parse :("

The content type here when parsing is a TextBlockNodeType with an empty children array, instead of a BlockLeafNodeType as expect for that case

Here's my current working branch but I'm not confident the fix I landed on is actually what should be changed here (UPDATE: yeah already found issues with it). I would expect the empty paragraph to have a node tree that looks like:

block
    (element paragraph [])
    (inlineChildren (Array.fromList [])

but instead this yields:

block
    (element paragraph [])
    Leaf

and I'm wondering if I really need to just get it to output that former structure and have everything else be ok with it- or if I'm overthinking it and the "paragraph without inline children" is an acceptable case.

The following cases DO work though: elements with inline children where the only child is a zero width space "<p>\u{200B}</p>" or a single space "<p> </p>"

abradley2 avatar Jun 05 '20 12:06 abradley2

Thanks for bringing this issue up. This was one of the edge cases that I wasn't sure if it should be made possible. In the markdown spec for example, any case of having a text block node or block node without children could lead to issues in the editor, so I wanted to make it invalid. The reason for that being that if a text block node has no children, it has buggy behavior in the editor like not being able to type in it or add children.

I think one fix for this would be to add an empty text node to inline nodes in this case if the children are empty. This would at least default in a way that makes sense for most cases. E.g. in the method you changed, something like:

            TextBlockNodeType _ ->
                Ok <| inlineChildren (Array.fromList [plainText ""])

For nodes with block children though, I'm not sure there's a sane default if there are no children. I think keeping nodes with block children from being empty may be okay to keep invalid.

mweiss avatar Jun 06 '20 04:06 mweiss

@mweiss Any chance your suggested fix above can be incorporated? Or are there still open questions preventing this from being PR'd?

jmpressman avatar May 31 '22 20:05 jmpressman

Like @jmpressman said, are there any outstanding questions on this? It would be nice to have this fixed. Can the suggested fix be incorporated as is? If not, is there anything I can do to help get this fixed?

okkero avatar Jul 06 '22 11:07 okkero

Hey to all! I have similar issue. Working on editor and need ability to add and edit some text blocks, decided to use elm-rte-toolkit. After editing text block I save it on backend as String using RichText.Html.toHtml and then I'm get this string and trying to convert it to Block with RichText.Html.blockFromHtml.

All working well, instead of empty lines e.g we have just 1 line in editor such as Just added text

and then user press (commandMap configured with that action) Enter and we have result such as

`Just added text

`

After perform RichText.Html.toHtml on block above we getting "<div data-rte-doc=\"true\"><p>Just added text</p><p></p></div>" as expected

but when we parse that result with RichText.Html.blockFromHtml we getting Err "Could not create a valid editor node array from html node array:\n\nInvalid node type for empty fragment result array"

In my opinion if we getting true result after RichText.Html.toHtml it should parse with RichText.Html.blockFromHtml with no errors.

Sorry, I'm new to this tool and I could be wrong. Please help me with this.

Also my command map configured as on basic example

`Command.set [ Command.inputEvent "insertParagraph", Command.key [ Keys.enter ], Command.key [ Keys.return ] ]

            [ ( "insertNewline"
               , Command.transform <| Commands.insertNewline [ "code_block" ]
               )
             , ( "liftEmpty", Command.transform <| Commands.liftEmpty )
             , ( "splitBlockHeaderToNewParagraph"
               , Command.transform <|
                     Commands.splitBlockHeaderToNewParagraph
                         [ "heading" ]
                         (Element.element paragraph [])
               )
             , ( "insertLeaf"
               , Command.transform <|
                     Commands.insertBlock horizontalRuleBlock
               )
             , ( "insertEmptyParagraph"
               , Command.transform <|
                     Commands.insertAfterBlockLeaf emptyParagraph
               )
             ]`

But I can't find anywhere how to debug these commands, I mean to see how named commands performs.

Thanks in advance!

NikitaM8 avatar Jul 10 '22 16:07 NikitaM8