sstur / draft-js-utils

DraftJS: import/export ContentState to and from HTML/Markdown
ISC License
883 stars 233 forks source link

stateToHTML creates nested html based on the order the options are defined and not chronologically. #256

Open dodosiz opened 2 years ago

dodosiz commented 2 years ago

Hello to everybody, I want to report an interesting bug I found in the stateToHMTL function.

Code

I have an array of CSS classes as options:

data.ts

export const textMarks = [
    {
        name: "white-over-green-background",
    },
    {
        name: "green-over-white-background",
    },
]

I use this array to generate the options for the Draftjs to HTML conversion:

get-options.ts

import { Options as ExportHTMLOptions } from "draft-js-export-html";
import { textMarks } from "./data";

export function getStateToHtmlOptions(): ExportHTMLOptions {
    const inlineStyles = textMarks.reduce(
        (map, textMark) => ({ ...map, [textMark.name]: { element: "span", attributes: { class: textMark.name } } }),
        {}
    );
    return {
        inlineStyles,
    };
}

And I convert the editor state to HTML using the stateToHTML function:

get-html.ts

import { EditorState } from "draft-js";
import { stateToHTML } from "draft-js-export-html";
import { getStateToHtmlOptions } from "./get-options";

export function getHTML(editorState: EditorState) {
    const content = editorState.getCurrentContent();
    return stateToHTML(currContent, getStateToHtmlOptions());
}

Case one: expected behaviour

Now I go to my application and select a text to mark it as green-over-white: 1

And then a nested part of the text to mark it as white-over-green: 2

The result is the one I would expect (a nested green inside the white): 3

The generated HTML is also the expected:

<span class="green-over-white-background">ipsum </span>
<span class="green-over-white-background">
    <span class="white-over-green-background">dolor sit amet, consectetur</span>
</span>
<span class="green-over-white-background"> adi</span>

Because I first applied green-over-white-background and then white-over-green-background, the nesting of the span elements is according to the chronological order here.

Case two: bug

If I try however the other way around, first white-over-green and then green-over-white: 4

Then I have the style applied, but it is not shown: 5

If I look at the generated HTML then I can understand the reason why:

<span class="white-over-green-background">ipsum dolor </span>
<span class="green-over-white-background">
    <span class="white-over-green-background">sit amet, consectetur</span>
</span>
<span class="white-over-green-background"> adipiscing</span>

The second applied style (green-over-white-background) is wrapping the first (white-over-green-background). This is correct based on the order I declared my options but wrong based on the order I applied the styles chronologically.