Ejemplo n.º 1
0
def test_render_link_marker_success():
    for text in sample_texts:
        node = Span(_type='span', marks=['linkId'], text=text)
        block = Block(
            _type='block', children=[node.__dict__], markDefs=[{'_type': 'link', '_key': 'linkId', 'href': text}]
        )
        assert LinkMarkerDefinition.render_text(node, 'linkId', block) == f'{text}'
        assert LinkMarkerDefinition.render(node, 'linkId', block) == f'<a href="{text}">{text}</a>'
Ejemplo n.º 2
0
def test_render_underline_marker_success():
    for text in sample_texts:
        node = Span(_type='span', text=text)
        block = Block(_type='block', children=[node.__dict__])
        assert UnderlineMarkerDefinition.render_text(node, 'u', block) == f'{text}'
        assert (
            UnderlineMarkerDefinition.render(node, 'u', block)
            == f'<span style="text-decoration:underline;">{text}</span>'
        )
Ejemplo n.º 3
0
    def _render_node(self,
                     node: dict,
                     context: Optional[Block] = None,
                     list_item: bool = False) -> str:
        """
        Call the correct render method depending on the node type.

        :param node: Block content node - can be block, span, or list (block).
        :param context: Optional context. Spans are passed with a Block instance as context for mark lookups.
        :param list_item: Whether we are handling a list upstream (impacts block handling).
        """
        if is_list(node):
            logger.debug('Rendering node as list')
            block = Block(**node,
                          marker_definitions=self._custom_marker_definitions)
            return self._render_list(block, context)

        elif is_block(node):
            logger.debug('Rendering node as block')
            block = Block(**node,
                          marker_definitions=self._custom_marker_definitions)
            return self._render_block(block, list_item=list_item)

        elif is_span(node):
            logger.debug('Rendering node as span')
            span = Span(**node)
            context = cast(Block,
                           context)  # context should always be a Block here
            return self._render_span(span, block=context)

        elif self._custom_serializers.get(node.get('_type', '')):
            return self._custom_serializers.get(node.get('_type', ''))(
                node, context, list_item)  # type: ignore

        else:
            if '_type' in node:
                raise MissingSerializerError(
                    f'Found unhandled node type: {node["_type"]}. '
                    'Most likely this requires a custom serializer.')
            else:
                raise UnhandledNodeError(
                    f'Received node that we cannot handle: {node}')
Ejemplo n.º 4
0
    def render(self) -> str:
        """Render HTML from self._blocks."""
        logger.debug('Rendering HTML')

        if not self._blocks:
            return ''

        result = ''
        list_nodes: List[Dict] = []

        for node in self._blocks:

            if list_nodes and not is_list(node):
                tree = self._normalize_list_tree(list_nodes)
                result += ''.join([
                    self._render_node(n, Block(**node), list_item=True)
                    for n in tree
                ])
                list_nodes = []  # reset list_nodes

            if is_list(node):
                list_nodes.append(node)
                continue  # handle all elements ^ when the list ends

            result += self._render_node(
                node)  # render non-list nodes immediately

        if list_nodes:
            tree = self._normalize_list_tree(list_nodes)
            result += ''.join(
                self._render_node(n, Block(**node), list_item=True)
                for n in tree)

        result = result.strip()

        if self._wrapper_element:
            return f'<{self._wrapper_element}>{result}</{self._wrapper_element}>'
        return result
Ejemplo n.º 5
0
    def _render_span(self, span: Span, block: Block) -> str:
        logger.debug('Rendering span')
        result: str = ''
        prev_node, next_node = block.get_node_siblings(span)

        prev_marks = prev_node.get('marks', []) if prev_node else []
        next_marks = next_node.get('marks', []) if next_node else []

        sorted_marks = sorted(span.marks,
                              key=lambda x: -block.marker_frequencies[x])
        for mark in sorted_marks:
            if mark in prev_marks:
                continue

            marker_callable = block.marker_definitions.get(
                mark, DefaultMarkerDefinition)()
            result += marker_callable.render_prefix(span, mark, block)

        # to avoid rendering the text multiple times,
        # only the first custom mark will be used
        custom_mark_text_rendered = False
        if sorted_marks:
            for mark in sorted_marks:
                if custom_mark_text_rendered or mark in prev_marks:
                    continue
                marker_callable = block.marker_definitions.get(
                    mark, DefaultMarkerDefinition)()
                result += marker_callable.render_text(span, mark, block)
                custom_mark_text_rendered = True

        if not custom_mark_text_rendered:
            result += html.escape(span.text).replace('\n', '<br/>')

        for mark in reversed(sorted_marks):
            if mark in next_marks:
                continue

            marker_callable = block.marker_definitions.get(
                mark, DefaultMarkerDefinition)()
            result += marker_callable.render_suffix(span, mark, block)

        return result
Ejemplo n.º 6
0
def test_render_comment_marker_success():
    for text in sample_texts:
        node = Span(_type='span', text=text)
        block = Block(_type='block', children=[node.__dict__])
        assert CommentMarkerDefinition.render(node, 'comment', block) == f'<!-- {text} -->'
Ejemplo n.º 7
0
def test_render_strikethrough_marker_success():
    for text in sample_texts:
        node = Span(_type='span', text=text)
        block = Block(_type='block', children=[node.__dict__])
        assert StrikeThroughMarkerDefinition.render_text(node, 'strike', block) == f'{text}'
        assert StrikeThroughMarkerDefinition.render(node, 'strike', block) == f'<del>{text}</del>'
Ejemplo n.º 8
0
def test_render_strong_marker_success():
    for text in sample_texts:
        node = Span(_type='span', text=text)
        block = Block(_type='block', children=[node.__dict__])
        assert StrongMarkerDefinition.render_text(node, 'strong', block) == f'{text}'
        assert StrongMarkerDefinition.render(node, 'strong', block) == f'<strong>{text}</strong>'
Ejemplo n.º 9
0
def test_render_emphasis_marker_success():
    for text in sample_texts:
        node = Span(_type='span', text=text)
        block = Block(_type='block', children=[node.__dict__])
        assert EmphasisMarkerDefinition.render_text(node, 'em', block) == f'{text}'
        assert EmphasisMarkerDefinition.render(node, 'em', block) == f'<em>{text}</em>'