Example #1
0
 def test_get_raises_exception(self):
     with self.assertRaises(ConfigException):
         self.assertEqual(
             Options.get(Options.map({
                 'BOLD': 'strong',
             }, 'FALLBACK'), 'ITALIC', 'FALLBACK'),
             Options('BOLD', 'strong'))
 def test_map_works(self):
     self.assertEqual(
         Options.map(
             {
                 "BOLD": "strong",
                 "HIGHLIGHT": {
                     "element": "strong",
                     "props": {
                         "style": {
                             "textDecoration": "underline"
                         }
                     },
                 },
             },
             "FALLBACK",
         ),
         {
             "BOLD":
             Options("BOLD", "strong"),
             "HIGHLIGHT":
             Options(
                 "HIGHLIGHT",
                 "strong",
                 props={"style": {
                     "textDecoration": "underline"
                 }},
             ),
         },
     )
Example #3
0
 def test_get_uses_fallback(self):
     self.assertEqual(
         Options.get(
             Options.map({
                 'BOLD': 'strong',
                 'FALLBACK': 'span',
             }, 'FALLBACK'), 'ITALIC', 'FALLBACK'),
         Options('FALLBACK', 'span'))
 def test_get_raises_exception(self):
     with self.assertRaises(ConfigException):
         self.assertEqual(
             Options.get(
                 Options.map({"BOLD": "strong"}, "FALLBACK"),
                 "ITALIC",
                 "FALLBACK",
             ),
             Options("BOLD", "strong"),
         )
 def test_create_uses_fallback(self):
     self.assertEqual(
         Options.create(
             {
                 "header-one": "h1",
                 "fallback": "div"
             },
             "header-two",
             "fallback",
         ),
         Options("header-two", "div"),
     )
 def test_get_uses_fallback(self):
     self.assertEqual(
         Options.get(
             Options.map({
                 "BOLD": "strong",
                 "FALLBACK": "span"
             }, "FALLBACK"),
             "ITALIC",
             "FALLBACK",
         ),
         Options("FALLBACK", "span"),
     )
Example #7
0
    def __init__(self, config: Optional[Config] = None) -> None:
        if config is None:
            config = {}

        self.composite_decorators = config.get("composite_decorators", [])

        self.entity_options = Options.map_entities(
            config.get("entity_decorators", {}))
        self.block_options = Options.map_blocks(
            config.get("block_map", BLOCK_MAP))
        self.style_options = Options.map_styles(
            config.get("style_map", STYLE_MAP))

        DOM.use(config.get("engine", DOM.STRING))
Example #8
0
    def __init__(self, config=None):
        if config is None:
            config = {}

        self.composite_decorators = config.get('composite_decorators', [])
        self.has_decorators = len(self.composite_decorators) > 0

        self.entity_options = Options.map_entities(
            config.get('entity_decorators', {}))
        self.block_options = Options.map_blocks(
            config.get('block_map', BLOCK_MAP))
        self.style_options = Options.map_styles(
            config.get('style_map', STYLE_MAP))

        DOM.use(config.get('engine', DOM.STRING))
    def render_entities(self, style_node):
        # We have a complete (start, stop) entity to render.
        if self.completed_entity is not None:
            entity_details = self.get_entity_details(self.completed_entity)
            opts = Options.for_entity(self.entity_decorators, entity_details['type'])
            props = entity_details['data'].copy()
            props['entity'] = {
                'type': entity_details['type'],
            }

            if len(self.element_stack) == 1:
                children = self.element_stack[0]
            else:
                children = DOM.create_element()

                for n in self.element_stack:
                    DOM.append_child(children, n)

            self.completed_entity = None
            self.element_stack = []

            # Is there still another entity? (adjacent) if so add the current style_node for it.
            if self.has_entity():
                self.element_stack.append(style_node)

            return DOM.create_element(opts.element, props, children)

        if self.has_entity():
            self.element_stack.append(style_node)
            return None

        return style_node
Example #10
0
    def render_entities(self, style_node):
        # We have a complete (start, stop) entity to render.
        if self.completed_entity is not None:
            entity_details = self.get_entity_details(self.completed_entity)
            opts = Options.for_entity(self.entity_decorators,
                                      entity_details['type'])
            props = entity_details['data'].copy()
            props['entity'] = {
                'type': entity_details['type'],
            }

            if len(self.element_stack) == 1:
                children = self.element_stack[0]
            else:
                children = DOM.create_element()

                for n in self.element_stack:
                    DOM.append_child(children, n)

            self.completed_entity = None
            self.element_stack = []

            # Is there still another entity? (adjacent) if so add the current style_node for it.
            if self.has_entity():
                self.element_stack.append(style_node)

            return DOM.create_element(opts.element, props, children)

        if self.has_entity():
            self.element_stack.append(style_node)
            return None

        return style_node
    def render_entities(self, style_node):

        if self.completed_entity is not None:
            entity_details = self.get_entity_details(self.completed_entity)
            opts = Options.for_entity(self.entity_decorators,
                                      entity_details['type'])
            props = entity_details['data'].copy()
            props['entity'] = {
                'type': entity_details['type'],
            }

            nodes = DOM.create_element()

            for n in self.element_stack:
                DOM.append_child(nodes, n)

            elt = DOM.create_element(opts.element, props, nodes)

            self.completed_entity = None
            self.element_stack = []
        elif self.has_no_entity():
            elt = style_node
        else:
            self.element_stack.append(style_node)
            elt = None

        return elt
Example #12
0
    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'))
Example #13
0
    def test_render_entities_data(self):
        blocks = [{
            "key": "5s7g9",
            "text": "test",
            "type": "unstyled",
            "depth": 0,
            "inlineStyleRanges": [],
            "entityRanges": [],
        }]

        def component(props):
            self.assertEqual(props["entity"]["blocks"], blocks)
            self.assertEqual(props["entity"]["block"], blocks[0])
            self.assertEqual(props["entity"]["type"], "LINK")
            self.assertEqual(props["entity"]["mutability"], "MUTABLE")
            self.assertEqual(props["entity"]["entity_range"]["key"], "0")
            return None

        entity_state = EntityState(Options.map_entities({"LINK": component}),
                                   entity_map)

        entity_state.apply(Command("start_entity", 0, "0"))
        entity_state.render_entities("Test text", blocks[0], blocks)
        entity_state.apply(Command("stop_entity", 9, "0"))
        entity_state.render_entities("Test text", blocks[0], blocks)
Example #14
0
 def test_get_works(self):
     self.assertEqual(
         Options.get(
             Options.map(
                 {
                     'BOLD': 'strong',
                     'HIGHLIGHT': {
                         'element': 'strong',
                         'props': {
                             'style': {
                                 'textDecoration': 'underline'
                             }
                         },
                     },
                 }, 'FALLBACK'), 'BOLD', 'FALLBACK'),
         Options('BOLD', 'strong'))
Example #15
0
    def test_render_entities_data(self):
        blocks = [
            {
                'key': '5s7g9',
                'text': 'test',
                'type': 'unstyled',
                'depth': 0,
                'inlineStyleRanges': [],
                'entityRanges': [],
            },
        ]

        def component(props):
            self.assertEqual(props['entity']['blocks'], blocks)
            self.assertEqual(props['entity']['block'], blocks[0])
            self.assertEqual(props['entity']['type'], 'LINK')
            self.assertEqual(props['entity']['mutability'], 'MUTABLE')
            self.assertEqual(props['entity']['entity_range']['key'], '0')
            return None

        entity_state = EntityState(Options.map_entities({
            'LINK': component,
        }), entity_map)

        entity_state.apply(Command('start_entity', 0, '0'))
        entity_state.render_entities('Test text', blocks[0], blocks)
        entity_state.apply(Command('stop_entity', 9, '0'))
        entity_state.render_entities('Test text', blocks[0], blocks)
Example #16
0
    def render_styles(self, text_node):
        node = text_node
        if not self.is_empty():
            # Nest the tags.
            for s in sorted(self.styles, reverse=True):
                opt = Options.for_style(self.style_map, s)
                node = DOM.create_element(opt.element, opt.props, node)

        return node
Example #17
0
    def test_render_entities_data_no_mutability(self):
        def component(props):
            self.assertEqual(props["entity"]["mutability"], None)
            return None

        entity_state = EntityState(Options.map_entities({"LINK": component}),
                                   entity_map)

        entity_state.apply(Command("start_entity", 0, "2"))
        entity_state.render_entities("Test text", {}, [])
        entity_state.apply(Command("stop_entity", 9, "2"))
        entity_state.render_entities("Test text", {}, [])
Example #18
0
    def test_render_entities_data_no_mutability(self):
        def component(props):
            self.assertEqual(props['entity']['mutability'], None)
            return None

        entity_state = EntityState(Options.map_entities({
            'LINK': component,
        }), entity_map)

        entity_state.apply(Command('start_entity', 0, '2'))
        entity_state.render_entities('Test text', {}, [])
        entity_state.apply(Command('stop_entity', 9, '2'))
        entity_state.render_entities('Test text', {}, [])
    def element_for(self, block, block_content):
        type_ = block['type']
        depth = block['depth']
        options = Options.for_block(self.block_map, type_)
        props = dict(options.props)
        props['block'] = block
        props['blocks'] = self.blocks

        # Make an element from the options specified in the block map.
        elt = DOM.create_element(options.element, props, block_content)

        parent = self.parent_for(options, depth, elt)

        return parent
Example #20
0
    def element_for(self, block, block_content):
        type_ = block['type']
        depth = block['depth']
        options = Options.for_block(self.block_map, type_)
        props = dict(options.props)
        props['block'] = block
        props['blocks'] = self.blocks

        # Make an element from the options specified in the block map.
        elt = DOM.create_element(options.element, props, block_content)

        parent = self.parent_for(options, depth, elt)

        return parent
Example #21
0
    def element_for(self, block, block_content):
        type_ = block['type'] if 'type' in block else 'unstyled'
        depth = block['depth'] if 'depth' in block else 0
        options = Options.get(self.block_options, type_, BLOCK_TYPES.FALLBACK)
        props = dict(options.props)
        props['block'] = block
        props['blocks'] = self.blocks

        # Make an element from the options specified in the block map.
        elt = DOM.create_element(options.element, props, block_content)

        parent = self.parent_for(options, depth, elt)

        return parent
    def setUp(self):
        DOM.use(DOM.STRING)

        self.wrapper_state = WrapperState(
            Options.map_blocks({
                'header-one': 'h1',
                'unstyled': 'div',
                'atomic': lambda props: props['children'],
                'ignore': None,
                'blockquote': blockquote,
                'ordered-list-item': {
                    'element': list_item,
                    'wrapper': ordered_list
                },
            }), [])
Example #23
0
    def render_styles(self, decorated_node, block, blocks):
        node = decorated_node
        if not self.is_empty():
            # Nest the tags.
            for style in sorted(self.styles, reverse=True):
                opt = Options.for_style(self.style_map, style)
                props = dict(opt.props)
                props['block'] = block
                props['blocks'] = blocks
                props['inline_style_range'] = {
                    'style': style,
                }
                node = DOM.create_element(opt.element, props, node)

        return node
Example #24
0
    def render_entities(self, style_node: Element, block: Block,
                        blocks: Sequence[Block]) -> Element:
        # We have a complete (start, stop) entity to render.
        if self.completed_entity is not None:
            entity_details = self.get_entity_details(self.completed_entity)
            options = Options.get(
                self.entity_options,
                entity_details["type"],
                ENTITY_TYPES.FALLBACK,
            )
            props = entity_details["data"].copy()
            props["entity"] = {
                "type":
                entity_details["type"],
                "mutability":
                entity_details["mutability"]
                if "mutability" in entity_details else None,
                "block":
                block,
                "blocks":
                blocks,
                "entity_range": {
                    "key": self.completed_entity
                },
            }

            if len(self.element_stack) == 1:
                children = self.element_stack[0]
            else:
                children = DOM.create_element()

                for n in self.element_stack:
                    DOM.append_child(children, n)

            self.completed_entity = None
            self.element_stack = []

            # Is there still another entity? (adjacent) if so add the current style_node for it.
            if self.has_entity():
                self.element_stack.append(style_node)

            return DOM.create_element(options.element, props, children)

        if self.has_entity():
            self.element_stack.append(style_node)
            return None

        return style_node
    def element_for(
            self, block: Block,
            block_content: Union[Element, Sequence[Element]]) -> Element:
        type_ = block["type"] if "type" in block else "unstyled"
        depth = block["depth"] if "depth" in block else 0
        options = Options.get(self.block_options, type_, BLOCK_TYPES.FALLBACK)
        props = dict(options.props)
        props["block"] = block
        props["blocks"] = self.blocks

        # Make an element from the options specified in the block map.
        elt = DOM.create_element(options.element, props, block_content)

        parent = self.parent_for(options, depth, elt)

        return parent
Example #26
0
    def render_styles(self, decorated_node: Element, block: Block,
                      blocks: Sequence[Block]) -> Element:
        node = decorated_node
        if not self.is_empty():
            # This will mutate self.styles, but it’s going to be reset after rendering anyway.
            self.styles.sort(reverse=True)

            # Nest the tags.
            for style in self.styles:
                options = Options.get(self.style_options, style,
                                      INLINE_STYLES.FALLBACK)
                props = dict(options.props)
                props["block"] = block
                props["blocks"] = blocks
                props["inline_style_range"] = {"style": style}
                node = DOM.create_element(options.element, props, node)

        return node
Example #27
0
    def element_for(self, block, block_content):
        type_ = block['type']
        depth = block['depth']
        data = block.get('data', {})
        options = Options.for_block(self.block_map, type_)
        props = dict(options.props)
        props['block'] = {
            'type': type_,
            'depth': depth,
            'data': data,
        }

        # Make an element from the options specified in the block map.
        elt = DOM.create_element(options.element, props, block_content)

        parent = self.parent_for(options, depth, elt)

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

        def unstyled(props):
            self.assertEqual(props['blocks'], blocks)
            self.assertEqual(props['block'], blocks[0])

        WrapperState(Options.map_blocks({'unstyled': unstyled}),
                     blocks).element_for(blocks[0], 'test')
Example #29
0
    def test_element_for_data(self):
        blocks = [
            {
                "key": "5s7g9",
                "text": "test",
                "type": "unstyled",
                "depth": 0,
                "inlineStyleRanges": [],
                "entityRanges": [],
            }
        ]

        def unstyled(props):
            self.assertEqual(props["blocks"], blocks)
            self.assertEqual(props["block"], blocks[0])

        WrapperState(
            Options.map_blocks({"unstyled": unstyled}), blocks
        ).element_for(blocks[0], "test")
Example #30
0
    def setUp(self):
        DOM.use(DOM.STRING)

        self.wrapper_state = WrapperState(
            Options.map_blocks(
                {
                    "header-one": "h1",
                    "unstyled": "div",
                    "atomic": lambda props: props["children"],
                    "ignore": None,
                    "blockquote": blockquote,
                    "ordered-list-item": {
                        "element": list_item,
                        "wrapper": ordered_list,
                    },
                }
            ),
            [],
        )
    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"))
Example #32
0
    def render_entities(self, style_node: Element, block: Block, blocks: Sequence[Block]) -> Element:
        # We have a complete (start, stop) entity to render.
        if self.completed_entity is not None:
            entity_details = self.get_entity_details(self.completed_entity)
            options = Options.get(self.entity_options, entity_details['type'], ENTITY_TYPES.FALLBACK)
            props = entity_details['data'].copy()
            props['entity'] = {
                'type': entity_details['type'],
                'mutability': entity_details['mutability'] if 'mutability' in entity_details else None,
                'block': block,
                'blocks': blocks,
                'entity_range': {
                    'key': self.completed_entity,
                },
            }

            if len(self.element_stack) == 1:
                children = self.element_stack[0]
            else:
                children = DOM.create_element()

                for n in self.element_stack:
                    DOM.append_child(children, n)

            self.completed_entity = None
            self.element_stack = []

            # Is there still another entity? (adjacent) if so add the current style_node for it.
            if self.has_entity():
                self.element_stack.append(style_node)

            return DOM.create_element(options.element, props, children)

        if self.has_entity():
            self.element_stack.append(style_node)
            return None

        return style_node
 def test_for_block_uses_fallback(self):
     self.assertEqual(Options.for_block({'header-one': 'h1', 'fallback': 'div'}, 'header-two'), Options('header-two', 'div'))
 def test_for_block_raises_missing_type(self):
     with self.assertRaises(ConfigException):
         Options.for_block({'header-one': 'h1'}, 'header-two')
 def test_for_block_simplest(self):
     self.assertEqual(Options.for_block({'unordered-list-item': 'li'}, 'unordered-list-item'), Options('unordered-list-item', 'li'))
 def test_for_style_simplest(self):
     self.assertEqual(Options.for_style({'ITALIC': 'em'}, 'ITALIC'), Options('ITALIC', 'em'))
 def test_for_block_raises_missing_element(self):
     with self.assertRaises(ConfigException):
         Options.for_block({'header-one': {}}, 'header-one')
 def test_for_style_raises_missing_type(self):
     with self.assertRaises(ConfigException):
         Options.for_style({'BOLD': 'strong'}, 'CODE')
 def test_for_style_uses_fallback(self):
     self.assertEqual(Options.for_style({'BOLD': 'strong', 'FALLBACK': 'span'}, 'CODE'), Options('CODE', 'span'))
 def test_for_entity_raises_missing_element(self):
     with self.assertRaises(ConfigException):
         Options.for_entity({'HORIZONTAL_RULE': {}}, 'HORIZONTAL_RULE')
 def test_for_entity_raises_missing_type(self):
     with self.assertRaises(ConfigException):
         Options.for_entity({'HORIZONTAL_RULE': 'hr'}, 'TEST')
 def test_for_entity_uses_fallback(self):
     self.assertEqual(Options.for_entity({'HORIZONTAL_RULE': 'hr', 'FALLBACK': 'div'}, 'TEST'), Options('TEST', 'div'))
 def test_for_entity_simplest(self):
     self.assertEqual(Options.for_entity({'HORIZONTAL_RULE': 'hr'}, 'HORIZONTAL_RULE'), Options('HORIZONTAL_RULE', 'hr'))
 def test_for_style_raises_missing_element(self):
     with self.assertRaises(ConfigException):
         Options.for_style({'BOLD': {}}, 'BOLD')