(driver, bs_element: BeautifulSoup, selenium_element)
| 43 | return computed_style, bbox, svg_bbox |
| 44 | |
| 45 | def parse_svg_tree(driver, bs_element: BeautifulSoup, selenium_element): |
| 46 | tag_name = bs_element.name |
| 47 | assert not isinstance(bs_element, NavigableString), "bs_element should not be NavigableString" |
| 48 | |
| 49 | attributes = dict(bs_element.attrs) |
| 50 | computed_style, bbox, svg_bbox = None, None, None |
| 51 | if selenium_element: |
| 52 | computed_style, bbox, svg_bbox = parse_element_with_style_and_bbox(driver, selenium_element) |
| 53 | |
| 54 | node_info = { |
| 55 | "tag": tag_name, |
| 56 | "attributes": attributes, |
| 57 | "computed_style": computed_style, |
| 58 | "bounding_box": bbox, |
| 59 | "svg_bounding_box": svg_bbox, |
| 60 | "html": str(bs_element), |
| 61 | "children": [] |
| 62 | } |
| 63 | |
| 64 | if len(bs_element.find_all(recursive=False)) > 5000: |
| 65 | print(f"--- {bs_element.name} has too many children: {len(bs_element.find_all(recursive=False))}") |
| 66 | return node_info |
| 67 | |
| 68 | for child in bs_element.find_all(recursive=False): |
| 69 | siblings = child.find_previous_siblings(child.name) |
| 70 | index = len(siblings) + 1 |
| 71 | child_sele = selenium_element.find_element(By.XPATH, f'./*[local-name()="{child.name}"][{index}]') |
| 72 | child_info = parse_svg_tree(driver, child, child_sele) |
| 73 | if child_info: |
| 74 | node_info["children"].append(child_info) |
| 75 | if not node_info["children"]: |
| 76 | # judge if has text |
| 77 | text_content = bs_element.text.strip() |
| 78 | if text_content: |
| 79 | node_info["text"] = text_content |
| 80 | |
| 81 | |
| 82 | return node_info |
| 83 | |
| 84 | def parse_tree_from_html(driver: webdriver.Chrome, html_path: str, save_svg=True): |
| 85 | driver.get(f'file://{html_path}') |
no test coverage detected