draftjs_exporter
draftjs_exporter copied to clipboard
Nested inline style configuration question
- [X] In the https://www.draftail.org/ documentation I searched for: nested inline style.
- [X] In the issues / pull requests, I searched for: nested inline style
- [X] In Stack Overflow, I searched for: draftjs exporter nested inline style
I have this block
{
"key": "",
"text": "Bold Italic Underline",
"type": "unstyled",
"depth": 0,
"inlineStyleRanges": [
{"offset": 0, "length": 21, "style": "BOLD"},
{"offset": 5, "length": 16, "style": "ITALIC"},
{"offset": 12, "length": 9, "style": "UNDERLINE"},
],
"entityRanges": [],
"data": {},
},
I expect it to render HTML as
<p><strong>Bold <em>Italic <u>Underline</u></em></strong></p>
but it renders HTML as
<p><strong>Bold </strong><strong><em>Italic </em></strong><strong><em><u>Underline</u></em></strong></p>
Is it a bug or is there any configuration?
Hey @drxcheng, good question. This is how the exporter is intended to work, is this output causing any issues for you?
I haven’t looked at this in a while but from what I recall the current implementation is because Draft.js allows inline style ranges to partially overlap, so converting style ranges to HTML can’t be as simple as mapping single ranges to single tags. For example in a case like:
{
"text": "Bold Both Italic",
"type": "unstyled",
"inlineStyleRanges": [
{
"offset": 0,
"length": 10,
"style": "BOLD"
},
{
"offset": 5,
"length": 11,
"style": "ITALIC"
}
]
}
This is even more important when style ranges overlap with entity ranges, since a given entity should always map to a single HTML tag – so style tags have to be split like the exporter does. The case you provide where we could shorten the output didn’t feel worthwhile to implement differently.
Thanks for the reply. It is currently causing me some minor issue because another library (https://github.com/niuware/mui-rte) behaves differently. I honestly don't know what's the expected behaviour. Feel free to close the ticket if you think it's not an issue.
👍 thank you for the extra details. I think it would be cool to change the implementation to use the representation you suggest when the ranges are strictly nested rather than overlapping, since admittedly the HTML is much more elegant like that.
I’m not entirely sure how much work that would be so won’t commit to it myself for now, but for future reference the logic is around here: https://github.com/springload/draftjs_exporter/blob/2ec7b82a9e7d5c3ef36039d7efeb45d5523e8c36/draftjs_exporter/html.py#L118-L126
Commentary mostly for my future benefit: style_state.render_styles is where the style tags are created "early" – the logic is to create all of the tags currently applied, every time a new tag is encountered. We’d need to change that to "only render when the closing tag is to be reached". One of the likely issues is that this "only render when closing is reached" is what the entity_state does… keeping the stack of elements along the way. So it might be "simplest" to combine style and entity state into a single "inline state", so the stack of inline elements is shared. Just with different logic between style and entities to resolve overlaps.