(parent: etree._Element, vdom: VdomDict | dict[str, Any])
| 157 | |
| 158 | |
| 159 | def _add_vdom_to_etree(parent: etree._Element, vdom: VdomDict | dict[str, Any]) -> None: |
| 160 | try: |
| 161 | tag = vdom["tagName"] |
| 162 | except KeyError as e: |
| 163 | msg = f"Expected a VDOM dict, not {vdom}" |
| 164 | raise TypeError(msg) from e |
| 165 | else: |
| 166 | vdom = cast(VdomDict, vdom) |
| 167 | |
| 168 | if tag: |
| 169 | element = etree.SubElement(parent, tag) |
| 170 | element.attrib.update( |
| 171 | _vdom_attr_to_html_str(k, v) for k, v in vdom.get("attributes", {}).items() |
| 172 | ) |
| 173 | else: |
| 174 | element = parent |
| 175 | |
| 176 | for c in vdom.get("children", []): |
| 177 | if isinstance(c, dict): |
| 178 | _add_vdom_to_etree(element, c) |
| 179 | else: |
| 180 | """ |
| 181 | LXML handles string children by storing them under `text` and `tail` |
| 182 | attributes of Element objects. The `text` attribute, if present, effectively |
| 183 | becomes that element's first child. Then the `tail` attribute, if present, |
| 184 | becomes a sibling that follows that element. For example, consider the |
| 185 | following HTML: |
| 186 | |
| 187 | <p><a>hello</a>world</p> |
| 188 | |
| 189 | In this code sample, "hello" is the `text` attribute of the `<a>` element |
| 190 | and "world" is the `tail` attribute of that same `<a>` element. It's for |
| 191 | this reason that, depending on whether the element being constructed has |
| 192 | non-string a child element, we need to assign a `text` vs `tail` attribute |
| 193 | to that element or the last non-string child respectively. |
| 194 | """ |
| 195 | if len(element): |
| 196 | last_child = element[-1] |
| 197 | last_child.tail = f"{last_child.tail or ''}{c}" |
| 198 | else: |
| 199 | element.text = f"{element.text or ''}{c}" |
| 200 | |
| 201 | |
| 202 | def _mutate_vdom(vdom: VdomDict) -> None: |
no test coverage detected