From aa3b588cf40d350710d345e13df8f04656577e1f Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Tue, 5 Dec 2017 16:40:52 +0000 Subject: [PATCH] Gracefully handle bare content at the top level --- .../converters/html_to_contentstate.py | 14 +++++++---- wagtail/admin/tests/test_contentstate.py | 24 +++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/wagtail/admin/rich_text/converters/html_to_contentstate.py b/wagtail/admin/rich_text/converters/html_to_contentstate.py index c53ffc0cb8..cd3627a1eb 100644 --- a/wagtail/admin/rich_text/converters/html_to_contentstate.py +++ b/wagtail/admin/rich_text/converters/html_to_contentstate.py @@ -58,7 +58,6 @@ class BlockElementHandler(object): self.block_type = block_type def create_block(self, name, attrs, state, contentstate): - assert state.current_block is None, "%s element found nested inside another block" % name return Block(self.block_type, depth=state.list_depth) def handle_starttag(self, name, attrs, state, contentstate): @@ -248,7 +247,14 @@ class HtmlToContentStateHandler(HTMLParser): def handle_data(self, content): if self.state.current_block is None: - assert not content.strip(), "Bare text content found at the top level: %r" % content + content = content.strip() + if content: + # create a new paragraph block for this content + block = Block('unstyled', depth=self.state.list_depth) + self.contentstate.blocks.append(block) + self.state.current_block = block + else: + # ignore top-level whitespace + return - else: - self.state.current_block.text += content + self.state.current_block.text += content diff --git a/wagtail/admin/tests/test_contentstate.py b/wagtail/admin/tests/test_contentstate.py index e0c0adf16a..88d2301821 100644 --- a/wagtail/admin/tests/test_contentstate.py +++ b/wagtail/admin/tests/test_contentstate.py @@ -53,6 +53,7 @@ class TestHtmlToContentState(TestCase): result = json.loads(converter.from_database_format( ''' Hello world! + I said hello world!

Goodbye world!

''' )) @@ -60,6 +61,29 @@ class TestHtmlToContentState(TestCase): 'entityMap': {}, 'blocks': [ {'inlineStyleRanges': [], 'text': 'Hello world!', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []}, + {'inlineStyleRanges': [], 'text': 'I said hello world!', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []}, {'inlineStyleRanges': [], 'text': 'Goodbye world!', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []}, ] }) + + def test_bare_text_becomes_paragraph(self): + converter = ContentstateConverter(features=[]) + result = json.loads(converter.from_database_format( + ''' + before +

paragraph

+ between +

paragraph

+ after + ''' + )) + self.assertContentStateEqual(result, { + 'entityMap': {}, + 'blocks': [ + {'inlineStyleRanges': [], 'text': 'before', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []}, + {'inlineStyleRanges': [], 'text': 'paragraph', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []}, + {'inlineStyleRanges': [], 'text': 'between', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []}, + {'inlineStyleRanges': [], 'text': 'paragraph', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []}, + {'inlineStyleRanges': [], 'text': 'after', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []}, + ] + })