Esempio n. 1
0
    def render_block(self, block, entity_map, wrapper_state):
        if block['inlineStyleRanges'] or block['entityRanges']:
            content = DOM.create_element()
            entity_state = EntityState(self.entity_decorators, entity_map)
            style_state = StyleState(self.style_map)

            for (text, commands) in self.build_command_groups(block):
                for command in commands:
                    entity_state.apply(command)
                    style_state.apply(command)

                # Decorators are not rendered inside entities.
                if entity_state.has_no_entity() and self.has_decorators:
                    decorated_node = render_decorators(self.composite_decorators, text, block, wrapper_state.blocks)
                else:
                    decorated_node = text

                styled_node = style_state.render_styles(decorated_node, block, wrapper_state.blocks)
                entity_node = entity_state.render_entities(styled_node)

                if entity_node is not None:
                    DOM.append_child(content, entity_node)

                    # Check whether there actually are two different nodes, confirming we are not inserting an upcoming entity.
                    if styled_node != entity_node and entity_state.has_no_entity():
                        DOM.append_child(content, styled_node)
        # Fast track for blocks which do not contain styles nor entities, which is very common.
        elif self.has_decorators:
            content = render_decorators(self.composite_decorators, block['text'], block, wrapper_state.blocks)
        else:
            content = block['text']

        return wrapper_state.element_for(block, content)
Esempio n. 2
0
    def render_block(self, block, entity_map, wrapper_state):
        content = DOM.create_element()
        entity_state = EntityState(self.entity_decorators, entity_map)
        style_state = StyleState(self.style_map)

        for (text, commands) in self.build_command_groups(block):
            for command in commands:
                entity_state.apply(command)
                style_state.apply(command)

            # Decorators are not rendered inside entities.
            if text and entity_state.has_no_entity() and len(
                    self.composite_decorators) > 0:
                decorated_node = render_decorators(self.composite_decorators,
                                                   text, block)
            else:
                decorated_node = text

            styled_node = style_state.render_styles(decorated_node)
            entity_node = entity_state.render_entities(styled_node)

            if entity_node is not None:
                DOM.append_child(content, entity_node)
                if styled_node != entity_node:
                    DOM.append_child(content, styled_node)

        return wrapper_state.element_for(block, content)
Esempio n. 3
0
    def render_block(self, block: Block, entity_map: EntityMap,
                     wrapper_state: WrapperState) -> Element:
        has_styles = "inlineStyleRanges" in block and block["inlineStyleRanges"]
        has_entities = "entityRanges" in block and block["entityRanges"]
        has_decorators = should_render_decorators(self.composite_decorators,
                                                  block["text"])

        if has_styles or has_entities:
            content = DOM.create_element()
            entity_state = EntityState(self.entity_options, entity_map)
            style_state = StyleState(
                self.style_options) if has_styles else None

            for (text, commands) in self.build_command_groups(block):
                for command in commands:
                    entity_state.apply(command)
                    if style_state:
                        style_state.apply(command)

                # Decorators are not rendered inside entities.
                if has_decorators and entity_state.has_no_entity():
                    decorated_node = render_decorators(
                        self.composite_decorators,
                        text,
                        block,
                        wrapper_state.blocks,
                    )
                else:
                    decorated_node = text

                if style_state:
                    styled_node = style_state.render_styles(
                        decorated_node, block, wrapper_state.blocks)
                else:
                    styled_node = decorated_node
                entity_node = entity_state.render_entities(
                    styled_node, block, wrapper_state.blocks)

                if entity_node is not None:
                    DOM.append_child(content, entity_node)

                    # Check whether there actually are two different nodes, confirming we are not inserting an upcoming entity.
                    if (styled_node != entity_node
                            and entity_state.has_no_entity()):
                        DOM.append_child(content, styled_node)
        # Fast track for blocks which do not contain styles nor entities, which is very common.
        elif has_decorators:
            content = render_decorators(
                self.composite_decorators,
                block["text"],
                block,
                wrapper_state.blocks,
            )
        else:
            content = block["text"]

        return wrapper_state.element_for(block, content)
    def test_render_styles_data(self):
        blocks = [
            {
                'key': '5s7g9',
                'text': 'test',
                'type': 'unstyled',
                'depth': 0,
                'inlineStyleRanges': [],
                'entityRanges': [],
            },
        ]

        def component(props):
            self.assertEqual(props['blocks'], blocks)
            self.assertEqual(props['block'], blocks[0])
            self.assertEqual(props['inline_style_range']['style'], 'ITALIC')
            return None

        style_state = StyleState({
            'ITALIC': component,
        })

        style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        style_state.render_styles('Test text', blocks[0], blocks)
        style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))
Esempio n. 5
0
    def render(self, content_state):
        """
        Starts the export process on a given piece of content state.
        """
        self.wrapper_state = WrapperState(self.block_map)
        self.style_state = StyleState(self.style_map)
        entity_map = content_state.get('entityMap', {})

        for block in content_state.get('blocks', []):
            self.render_block(block, entity_map)

        self.wrapper_state.clean_up()

        return self.wrapper_state.to_string()
    def test_render_styles_data(self):
        blocks = [
            {
                'key': '5s7g9',
                'text': 'test',
                'type': 'unstyled',
                'depth': 0,
                'inlineStyleRanges': [],
                'entityRanges': [],
            },
        ]

        def component(props):
            self.assertEqual(props['blocks'], blocks)
            self.assertEqual(props['block'], blocks[0])
            self.assertEqual(props['inline_style_range']['style'], 'ITALIC')
            return None

        style_state = StyleState({
            'ITALIC': component,
        })

        style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        style_state.render_styles('Test text', blocks[0], blocks)
        style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))
Esempio n. 7
0
    def render_block(self, block, entity_map, wrapper_state):
        content = DOM.create_element()

        if block['inlineStyleRanges'] or block['entityRanges']:
            entity_state = EntityState(self.entity_decorators, entity_map)
            style_state = StyleState(self.style_map)

            for (text, commands) in self.build_command_groups(block):
                for command in commands:
                    entity_state.apply(command)
                    style_state.apply(command)

                # Decorators are not rendered inside entities.
                if text and entity_state.has_no_entity() and len(
                        self.composite_decorators) > 0:
                    decorated_node = render_decorators(
                        self.composite_decorators, text, block,
                        wrapper_state.blocks)
                else:
                    decorated_node = text

                styled_node = style_state.render_styles(
                    decorated_node, block, wrapper_state.blocks)
                entity_node = entity_state.render_entities(styled_node)

                if entity_node is not None:
                    DOM.append_child(content, entity_node)
                    if styled_node != entity_node:
                        DOM.append_child(content, styled_node)
        # Fast track for blocks which do not contain styles nor entities, which is very common.
        else:
            if len(self.composite_decorators) > 0:
                decorated_node = render_decorators(self.composite_decorators,
                                                   block['text'], block,
                                                   wrapper_state.blocks)
            else:
                decorated_node = block['text']

            DOM.append_child(content, decorated_node)

        return wrapper_state.element_for(block, content)
Esempio n. 8
0
    def render_block(self, block, entity_map, wrapper_state):
        if 'inlineStyleRanges' in block and block[
                'inlineStyleRanges'] or 'entityRanges' in block and block[
                    'entityRanges']:
            content = DOM.create_element()
            entity_state = EntityState(self.entity_options, entity_map)
            style_state = StyleState(self.style_options)

            for (text, commands) in self.build_command_groups(block):
                for command in commands:
                    entity_state.apply(command)
                    style_state.apply(command)

                # Decorators are not rendered inside entities.
                if entity_state.has_no_entity() and self.has_decorators:
                    decorated_node = render_decorators(
                        self.composite_decorators, text, block,
                        wrapper_state.blocks)
                else:
                    decorated_node = text

                styled_node = style_state.render_styles(
                    decorated_node, block, wrapper_state.blocks)
                entity_node = entity_state.render_entities(styled_node)

                if entity_node is not None:
                    DOM.append_child(content, entity_node)

                    # Check whether there actually are two different nodes, confirming we are not inserting an upcoming entity.
                    if styled_node != entity_node and entity_state.has_no_entity(
                    ):
                        DOM.append_child(content, styled_node)
        # Fast track for blocks which do not contain styles nor entities, which is very common.
        elif self.has_decorators:
            content = render_decorators(self.composite_decorators,
                                        block['text'], block,
                                        wrapper_state.blocks)
        else:
            content = block['text']

        return wrapper_state.element_for(block, content)
    def test_render_styles_data(self):
        blocks = [{
            "key": "5s7g9",
            "text": "test",
            "type": "unstyled",
            "depth": 0,
            "inlineStyleRanges": [],
            "entityRanges": [],
        }]

        def component(props):
            self.assertEqual(props["blocks"], blocks)
            self.assertEqual(props["block"], blocks[0])
            self.assertEqual(props["inline_style_range"]["style"], "ITALIC")
            return None

        style_state = StyleState(Options.map_styles({"ITALIC": component}))

        style_state.apply(Command("start_inline_style", 0, "ITALIC"))
        style_state.render_styles("Test text", blocks[0], blocks)
        style_state.apply(Command("stop_inline_style", 9, "ITALIC"))
Esempio n. 10
0
 def setUp(self):
     self.style_state = StyleState(style_map)
Esempio n. 11
0
class TestStyleState(unittest.TestCase):
    def setUp(self):
        self.style_state = StyleState(style_map)

    def test_init(self):
        self.assertIsInstance(self.style_state, StyleState)

    def test_apply_start_inline_style(self):
        self.assertEqual(self.style_state.styles, [])
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, ['ITALIC'])

    def test_apply_stop_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.style_state.apply(Command('stop_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, [])

    def test_is_unstyled_default(self):
        self.assertEqual(self.style_state.is_unstyled(), True)

    def test_is_unstyled_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.is_unstyled(), False)

    def test_get_style_value_empty(self):
        self.assertEqual(self.style_state.get_style_value(), '')

    def test_get_style_value_single(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.get_style_value(), '')

    def test_get_style_value_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'HIGHLIGHT'))
        self.assertEqual(self.style_state.get_style_value(), 'text-decoration: underline;')

    def test_create_node_unstyled(self):
        self.assertEqual(DOM.get_tag_name(self.style_state.create_nodes('Test text')[0]), 'textnode')
        self.assertEqual(DOM.get_text_content(self.style_state.create_nodes('Test text')[0]), 'Test text')

    def test_create_node_unicode(self):
        self.assertEqual(DOM.get_text_content(self.style_state.create_nodes('🍺')[0]), '🍺')

    def test_create_node_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(DOM.get_tag_name(self.style_state.create_nodes('Test text')[0]), 'em')
        self.assertEqual(self.style_state.create_nodes('Test text')[0].get('style'), None)
        self.assertEqual(DOM.get_text_content(self.style_state.create_nodes('Test text')[0]), 'Test text')
        self.style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))

    def test_create_node_styled_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'BOLD'))
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.get_style_tags(), ['em', 'strong'])
        self.assertEqual(DOM.get_tag_name(self.style_state.create_nodes('wow')[0]), 'em')
        self.assertEqual(DOM.get_tag_name(DOM.get_children(self.style_state.create_nodes('wow')[0])[0]), 'strong')
 def setUp(self):
     DOM.use(DOM.STRING)
     self.style_state = StyleState(style_map)
Esempio n. 13
0
class HTML:
    """
    Entry point of the exporter. Combines entity, wrapper and style state
    to generate the right HTML nodes.
    """
    def __init__(self, config=None):
        if config is None:
            config = {}

        self.entity_decorators = config.get('entity_decorators', {})
        self.block_map = config.get('block_map', BLOCK_MAP)
        self.style_map = config.get('style_map', STYLE_MAP)

    def render(self, content_state):
        """
        Starts the export process on a given piece of content state.
        """
        self.wrapper_state = WrapperState(self.block_map)
        self.style_state = StyleState(self.style_map)
        entity_map = content_state.get('entityMap', {})

        for block in content_state.get('blocks', []):
            self.render_block(block, entity_map)

        self.wrapper_state.clean_up()

        return self.wrapper_state.to_string()

    def render_block(self, block, entity_map):
        element = self.wrapper_state.element_for(block)
        entity_state = EntityState(self.entity_decorators, entity_map)

        for (text, commands) in self.build_command_groups(block):
            for command in commands:
                entity_state.apply(command)
                self.style_state.apply(command)

            style_node = self.style_state.create_node(text)
            entity_state.render_entitities(element, style_node)

    def build_command_groups(self, block):
        """
        Creates block modification commands, grouped by start index,
        with the text to apply them on.
        """
        text = block.get('text')

        commands = self.build_commands(block)
        # Tried using itertools.tee but for some reason that failed. Oh well.
        grouped = Command.grouped_by_index(commands)
        listed = list(Command.grouped_by_index(commands))
        sliced = []

        i = 0
        for start_index, commands in grouped:
            next_group = listed[i + 1] if i + 1 < len(listed) else False
            stop_index = next_group[0] if next_group else 0

            sliced.append((text[start_index:stop_index], list(commands)))
            i += 1

        return sliced

    def build_commands(self, block):
        """
        Build all of the manipulation commands for a given block.
        - One pair to set the text.
        - Multiple pairs for styles.
        - Multiple pairs for entities.
        """
        text_commands = Command.start_stop('text', 0, len(block.get('text')))
        style_commands = self.build_style_commands(block)
        entity_commands = self.build_entity_commands(block)

        return text_commands + style_commands + entity_commands

    def build_style_commands(self, block):
        ranges = block.get('inlineStyleRanges', [])
        return Command.from_ranges(ranges, 'inline_style', 'style')

    def build_entity_commands(self, block):
        ranges = block.get('entityRanges', [])
        return Command.from_ranges(ranges, 'entity', 'key')
class TestStyleState(unittest.TestCase):
    def setUp(self):
        DOM.use(DOM.STRING)
        self.style_state = StyleState(style_map)

    def test_init(self):
        self.assertIsInstance(self.style_state, StyleState)

    def test_apply_start_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, ['ITALIC'])

    def test_apply_stop_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.style_state.apply(Command('stop_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, [])

    def test_is_empty_default(self):
        self.assertEqual(self.style_state.is_empty(), True)

    def test_is_empty_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.is_empty(), False)

    def test_render_styles_unstyled(self):
        self.assertEqual(self.style_state.render_styles('Test text'), 'Test text')

    def test_render_styles_unicode(self):
        self.assertEqual(self.style_state.render_styles('🍺'), '🍺')

    def test_render_styles_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text')), '<em>Test text</em>')
        self.style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))

    def test_render_styles_styled_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'BOLD'))
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text')), '<strong><em>Test text</em></strong>')

    def test_render_styles_attributes(self):
        self.style_state.apply(Command('start_inline_style', 0, 'KBD'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text')), '<kbd class="o-keyboard-shortcut">Test text</kbd>')
        self.style_state.apply(Command('stop_inline_style', 9, 'KBD'))

    def test_render_styles_component(self):
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text')), '<strong style="color: red;">Test text</strong>')
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))

    def test_render_styles_component_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.style_state.apply(Command('start_inline_style', 0, 'SHOUT'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text')), '<strong style="color: red;"><span style="text-transform: uppercase;">Test text</span></strong>')
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))
        self.style_state.apply(Command('stop_inline_style', 9, 'SHOUT'))

    def test_render_styles_component_multiple_invert(self):
        self.style_state.apply(Command('start_inline_style', 0, 'SHOUT'))
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text')), '<strong style="color: red;"><span style="text-transform: uppercase;">Test text</span></strong>')
        self.style_state.apply(Command('stop_inline_style', 9, 'SHOUT'))
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))
class TestStyleState(unittest.TestCase):
    def setUp(self):
        self.style_state = StyleState(style_map)

    def test_init(self):
        self.assertIsInstance(self.style_state, StyleState)

    def test_apply_start_inline_style(self):
        self.assertEqual(self.style_state.styles, [])
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, ['ITALIC'])

    def test_apply_stop_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.style_state.apply(Command('stop_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, [])

    def test_is_unstyled_default(self):
        self.assertEqual(self.style_state.is_unstyled(), True)

    def test_is_unstyled_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.is_unstyled(), False)

    def test_get_style_value_empty(self):
        self.assertEqual(self.style_state.get_style_value(), '')

    def test_get_style_value_single(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.get_style_value(), '')

    def test_get_style_value_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'HIGHLIGHT'))
        self.assertEqual(self.style_state.get_style_value(), 'text-decoration: underline;')

    def test_add_node_unstyled(self):
        self.assertEqual(self.style_state.add_node(etree.Element('p'), 'Test text').tag, 'textnode')
        self.assertEqual(self.style_state.add_node(etree.Element('p'), 'Test text').text, 'Test text')

    def test_add_node_unicode(self):
        self.assertEqual(self.style_state.add_node(etree.Element('p'), '🍺').text, '🍺')

    def test_add_node_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.add_node(etree.Element('p'), 'Test text').tag, 'em')
        self.assertEqual(self.style_state.add_node(etree.Element('p'), 'Test text').get('style'), None)
        self.assertEqual(self.style_state.add_node(etree.Element('p'), 'Test text').text, 'Test text')
        self.style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))
 def setUp(self):
     DOM.use(DOM.STRING)
     self.style_state = StyleState(style_map)
class TestStyleState(unittest.TestCase):
    def setUp(self):
        DOM.use(DOM.STRING)
        self.style_state = StyleState(style_map)

    def test_init(self):
        self.assertIsInstance(self.style_state, StyleState)

    def test_apply_start_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, ['ITALIC'])

    def test_apply_stop_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.style_state.apply(Command('stop_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, [])

    def test_is_empty_default(self):
        self.assertEqual(self.style_state.is_empty(), True)

    def test_is_empty_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.is_empty(), False)

    def test_render_styles_unstyled(self):
        self.assertEqual(self.style_state.render_styles('Test text', {}, []), 'Test text')

    def test_render_styles_unicode(self):
        self.assertEqual(self.style_state.render_styles('🍺', {}, []), '🍺')

    def test_render_styles_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text', {}, [])), '<em>Test text</em>')
        self.style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))

    def test_render_styles_styled_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'BOLD'))
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text', {}, [])), '<strong><em>Test text</em></strong>')

    def test_render_styles_attributes(self):
        self.style_state.apply(Command('start_inline_style', 0, 'KBD'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text', {}, [])), '<kbd class="o-keyboard-shortcut">Test text</kbd>')
        self.style_state.apply(Command('stop_inline_style', 9, 'KBD'))

    def test_render_styles_component(self):
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text', {}, [])), '<strong style="color: red;">Test text</strong>')
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))

    def test_render_styles_component_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.style_state.apply(Command('start_inline_style', 0, 'SHOUT'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text', {}, [])), '<strong style="color: red;"><span style="text-transform: uppercase;">Test text</span></strong>')
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))
        self.style_state.apply(Command('stop_inline_style', 9, 'SHOUT'))

    def test_render_styles_component_multiple_invert(self):
        self.style_state.apply(Command('start_inline_style', 0, 'SHOUT'))
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.assertEqual(DOM.render_debug(self.style_state.render_styles('Test text', {}, [])), '<strong style="color: red;"><span style="text-transform: uppercase;">Test text</span></strong>')
        self.style_state.apply(Command('stop_inline_style', 9, 'SHOUT'))
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))

    def test_render_styles_data(self):
        blocks = [
            {
                'key': '5s7g9',
                'text': 'test',
                'type': 'unstyled',
                'depth': 0,
                'inlineStyleRanges': [],
                'entityRanges': [],
            },
        ]

        def component(props):
            self.assertEqual(props['blocks'], blocks)
            self.assertEqual(props['block'], blocks[0])
            self.assertEqual(props['inline_style_range']['style'], 'ITALIC')
            return None

        style_state = StyleState({
            'ITALIC': component,
        })

        style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        style_state.render_styles('Test text', blocks[0], blocks)
        style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))
class TestStyleState(unittest.TestCase):
    def setUp(self):
        DOM.use(DOM.STRING)
        self.style_state = StyleState(
            Options.map_styles(style_map)  # type: ignore
        )

    def test_init(self):
        self.assertIsInstance(self.style_state, StyleState)

    def test_apply_start_inline_style(self):
        self.style_state.apply(Command("start_inline_style", 0, "ITALIC"))
        self.assertEqual(self.style_state.styles, ["ITALIC"])

    def test_apply_stop_inline_style(self):
        self.style_state.apply(Command("start_inline_style", 0, "ITALIC"))
        self.style_state.apply(Command("stop_inline_style", 0, "ITALIC"))
        self.assertEqual(self.style_state.styles, [])

    def test_is_empty_default(self):
        self.assertEqual(self.style_state.is_empty(), True)

    def test_is_empty_styled(self):
        self.style_state.apply(Command("start_inline_style", 0, "ITALIC"))
        self.assertEqual(self.style_state.is_empty(), False)

    def test_render_styles_unstyled(self):
        self.assertEqual(self.style_state.render_styles("Test text", {}, []),
                         "Test text")

    def test_render_styles_unicode(self):
        self.assertEqual(self.style_state.render_styles("🍺", {}, []), "🍺")

    def test_render_styles_styled(self):
        self.style_state.apply(Command("start_inline_style", 0, "ITALIC"))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles("Test text", {}, [])),
            "<em>Test text</em>",
        )
        self.style_state.apply(Command("stop_inline_style", 9, "ITALIC"))

    def test_render_styles_styled_multiple(self):
        self.style_state.apply(Command("start_inline_style", 0, "BOLD"))
        self.style_state.apply(Command("start_inline_style", 0, "ITALIC"))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles("Test text", {}, [])),
            "<strong><em>Test text</em></strong>",
        )

    def test_render_styles_attributes(self):
        self.style_state.apply(Command("start_inline_style", 0, "KBD"))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles("Test text", {}, [])),
            '<kbd class="o-keyboard-shortcut">Test text</kbd>',
        )
        self.style_state.apply(Command("stop_inline_style", 9, "KBD"))

    def test_render_styles_component(self):
        self.style_state.apply(Command("start_inline_style", 0, "IMPORTANT"))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles("Test text", {}, [])),
            '<strong style="color: red;">Test text</strong>',
        )
        self.style_state.apply(Command("stop_inline_style", 9, "IMPORTANT"))

    def test_render_styles_component_multiple(self):
        self.style_state.apply(Command("start_inline_style", 0, "IMPORTANT"))
        self.style_state.apply(Command("start_inline_style", 0, "SHOUT"))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles("Test text", {}, [])),
            '<strong style="color: red;"><span style="text-transform: uppercase;">Test text</span></strong>',
        )
        self.style_state.apply(Command("stop_inline_style", 9, "IMPORTANT"))
        self.style_state.apply(Command("stop_inline_style", 9, "SHOUT"))

    def test_render_styles_component_multiple_invert(self):
        self.style_state.apply(Command("start_inline_style", 0, "SHOUT"))
        self.style_state.apply(Command("start_inline_style", 0, "IMPORTANT"))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles("Test text", {}, [])),
            '<strong style="color: red;"><span style="text-transform: uppercase;">Test text</span></strong>',
        )
        self.style_state.apply(Command("stop_inline_style", 9, "SHOUT"))
        self.style_state.apply(Command("stop_inline_style", 9, "IMPORTANT"))

    def test_render_styles_data(self):
        blocks = [{
            "key": "5s7g9",
            "text": "test",
            "type": "unstyled",
            "depth": 0,
            "inlineStyleRanges": [],
            "entityRanges": [],
        }]

        def component(props):
            self.assertEqual(props["blocks"], blocks)
            self.assertEqual(props["block"], blocks[0])
            self.assertEqual(props["inline_style_range"]["style"], "ITALIC")
            return None

        style_state = StyleState(Options.map_styles({"ITALIC": component}))

        style_state.apply(Command("start_inline_style", 0, "ITALIC"))
        style_state.render_styles("Test text", blocks[0], blocks)
        style_state.apply(Command("stop_inline_style", 9, "ITALIC"))
class TestStyleState(unittest.TestCase):
    def setUp(self):
        DOM.use(DOM.STRING)
        self.style_state = StyleState(style_map)

    def test_init(self):
        self.assertIsInstance(self.style_state, StyleState)

    def test_apply_start_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, ['ITALIC'])

    def test_apply_stop_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.style_state.apply(Command('stop_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, [])

    def test_is_empty_default(self):
        self.assertEqual(self.style_state.is_empty(), True)

    def test_is_empty_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.is_empty(), False)

    def test_render_styles_unstyled(self):
        self.assertEqual(self.style_state.render_styles('Test text', {}, []),
                         'Test text')

    def test_render_styles_unicode(self):
        self.assertEqual(self.style_state.render_styles('🍺', {}, []), '🍺')

    def test_render_styles_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles('Test text', {}, [])),
            '<em>Test text</em>')
        self.style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))

    def test_render_styles_styled_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'BOLD'))
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles('Test text', {}, [])),
            '<strong><em>Test text</em></strong>')

    def test_render_styles_attributes(self):
        self.style_state.apply(Command('start_inline_style', 0, 'KBD'))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles('Test text', {}, [])),
            '<kbd class="o-keyboard-shortcut">Test text</kbd>')
        self.style_state.apply(Command('stop_inline_style', 9, 'KBD'))

    def test_render_styles_component(self):
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles('Test text', {}, [])),
            '<strong style="color: red;">Test text</strong>')
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))

    def test_render_styles_component_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.style_state.apply(Command('start_inline_style', 0, 'SHOUT'))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles('Test text', {}, [])),
            '<strong style="color: red;"><span style="text-transform: uppercase;">Test text</span></strong>'
        )
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))
        self.style_state.apply(Command('stop_inline_style', 9, 'SHOUT'))

    def test_render_styles_component_multiple_invert(self):
        self.style_state.apply(Command('start_inline_style', 0, 'SHOUT'))
        self.style_state.apply(Command('start_inline_style', 0, 'IMPORTANT'))
        self.assertEqual(
            DOM.render_debug(
                self.style_state.render_styles('Test text', {}, [])),
            '<strong style="color: red;"><span style="text-transform: uppercase;">Test text</span></strong>'
        )
        self.style_state.apply(Command('stop_inline_style', 9, 'SHOUT'))
        self.style_state.apply(Command('stop_inline_style', 9, 'IMPORTANT'))

    def test_render_styles_data(self):
        blocks = [
            {
                'key': '5s7g9',
                'text': 'test',
                'type': 'unstyled',
                'depth': 0,
                'inlineStyleRanges': [],
                'entityRanges': [],
            },
        ]

        def component(props):
            self.assertEqual(props['blocks'], blocks)
            self.assertEqual(props['block'], blocks[0])
            self.assertEqual(props['inline_style_range']['style'], 'ITALIC')
            return None

        style_state = StyleState({
            'ITALIC': component,
        })

        style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        style_state.render_styles('Test text', blocks[0], blocks)
        style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))
 def setUp(self):
     self.style_state = StyleState(style_map)
Esempio n. 21
0
 def __init__(self, config={}):
     self.entity_decorators = config.get('entity_decorators', {})
     self.wrapper_state = WrapperState(config.get('block_map', BLOCK_MAP))
     self.style_state = StyleState(config.get('style_map', STYLE_MAP))
 def setUp(self):
     DOM.use(DOM.STRING)
     self.style_state = StyleState(
         Options.map_styles(style_map)  # type: ignore
     )
Esempio n. 23
0
class TestStyleState(unittest.TestCase):
    def setUp(self):
        self.style_state = StyleState(style_map)

    def test_init(self):
        self.assertIsInstance(self.style_state, StyleState)

    def test_apply_start_inline_style(self):
        self.assertEqual(self.style_state.styles, [])
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, ['ITALIC'])

    def test_apply_stop_inline_style(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.style_state.apply(Command('stop_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.styles, [])

    def test_is_unstyled_default(self):
        self.assertEqual(self.style_state.is_unstyled(), True)

    def test_is_unstyled_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.is_unstyled(), False)

    def test_get_style_value_empty(self):
        self.assertEqual(self.style_state.get_style_value(), '')

    def test_get_style_value_single(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(self.style_state.get_style_value(), '')

    def test_get_style_value_multiple(self):
        self.style_state.apply(Command('start_inline_style', 0, 'HIGHLIGHT'))
        self.assertEqual(self.style_state.get_style_value(),
                         'text-decoration: underline;')

    def test_get_class_value(self):
        self.style_state.apply(Command('start_inline_style', 0, 'OUTLINE'))
        self.assertEqual(self.style_state.get_class_value(), 'outline')

    def test_add_node_unstyled(self):
        self.assertEqual(
            DOM.get_tag_name(
                self.style_state.add_node(DOM.create_element('p'),
                                          'Test text')), 'textnode')
        self.assertEqual(
            DOM.get_text_content(
                self.style_state.add_node(DOM.create_element('p'),
                                          'Test text')), 'Test text')

    def test_add_node_unicode(self):
        self.assertEqual(
            DOM.get_text_content(
                self.style_state.add_node(DOM.create_element('p'), '🍺')), '🍺')

    def test_add_node_styled(self):
        self.style_state.apply(Command('start_inline_style', 0, 'ITALIC'))
        self.assertEqual(
            DOM.get_tag_name(
                self.style_state.add_node(DOM.create_element('p'),
                                          'Test text')), 'em')
        self.assertEqual(
            self.style_state.add_node(DOM.create_element('p'),
                                      'Test text').get('style'), None)
        self.assertEqual(
            DOM.get_text_content(
                self.style_state.add_node(DOM.create_element('p'),
                                          'Test text')), 'Test text')
        self.style_state.apply(Command('stop_inline_style', 9, 'ITALIC'))