def test_ast_find():
    text = (
        '<div class="a"><div class="c"><x/><y>z</y><div class="a b"></div></div></div>'
    )
    ast = tokenize_html(text)
    found = list(ast.find("div", classes=["a"]))
    assert [e.attrs.classes for e in found] == [["a"], ["a", "b"]]
def test_render_overrides():
    text = "<div><abc></abc></div>"
    ast = tokenize_html(text)

    def _render_abc(element, *args, **kwargs):
        return "hallo"

    output = ast.render(tag_overrides={"abc": _render_abc})
    assert output == "<div>hallo</div>"
Exemple #3
0
def html_to_nodes(
    text: str, line_number: int, renderer: DocutilsRenderer
) -> list[nodes.Element]:
    """Convert HTML to docutils nodes."""
    if renderer.md_config.gfm_only:
        text, _ = RE_FLOW.subn(lambda s: s.group(0).replace("<", "&lt;"), text)

    enable_html_img = "html_image" in renderer.md_config.enable_extensions
    enable_html_admonition = "html_admonition" in renderer.md_config.enable_extensions
    if not (enable_html_img or enable_html_admonition):
        return default_html(text, renderer.document["source"], line_number)

    # parse the HTML to AST
    try:
        root = tokenize_html(text).strip(inplace=True, recurse=False)
    except Exception:
        msg_node = renderer.create_warning(
            "HTML could not be parsed", line=line_number, subtype="html"
        )
        return ([msg_node] if msg_node else []) + default_html(
            text, renderer.document["source"], line_number
        )

    if len(root) < 1:
        # if empty
        return default_html(text, renderer.document["source"], line_number)

    if not all(
        (enable_html_img and child.name == "img")
        or (
            enable_html_admonition
            and child.name == "div"
            and "admonition" in child.attrs.classes
        )
        for child in root
    ):
        return default_html(text, renderer.document["source"], line_number)

    nodes_list = []
    for child in root:

        if child.name == "img":
            if "src" not in child.attrs:
                return [
                    renderer.reporter.error(
                        "<img> missing 'src' attribute", line=line_number
                    )
                ]
            content = "\n".join(
                f":{k}: {v}"
                for k, v in sorted(child.attrs.items())
                if k in OPTION_KEYS_IMAGE
            )
            nodes_list.extend(
                renderer.run_directive(
                    "image", child.attrs["src"], content, line_number
                )
            )

        else:
            children = child.strip().children
            if (
                children
                and children[0].name in ("div", "p")
                and (
                    "title" in children[0].attrs.classes
                    or "admonition-title" in children[0].attrs.classes
                )
            ):
                title = "".join(child.render() for child in children.pop(0))
            else:
                title = "Note"

            options = "\n".join(
                f":{k}: {v}"
                for k, v in sorted(child.attrs.items())
                if k in OPTION_KEYS_ADMONITION
            ).rstrip()
            new_children = []
            for child in children:
                if child.name == "p":
                    new_children.extend(child.children)
                    new_children.append(Data("\n\n"))
                else:
                    new_children.append(child)
            content = (
                options
                + ("\n\n" if options else "")
                + "".join(child.render() for child in new_children).lstrip()
            )

            nodes_list.extend(
                renderer.run_directive("admonition", title, content, line_number)
            )

    return nodes_list
def test_html_round_trip(file_params):
    ast = tokenize_html(file_params.content)
    file_params.assert_expected(str(ast), rstrip=True)
def test_html_ast(file_params):
    tokens = "\n".join(
        repr(t)
        for t in tokenize_html(file_params.content).walk(include_self=True))
    file_params.assert_expected(tokens, rstrip=True)