diff --git a/docs/docs/parser.md b/docs/docs/parser.md index d48a565..88e65ae 100644 --- a/docs/docs/parser.md +++ b/docs/docs/parser.md @@ -300,7 +300,7 @@ Let's see what parameters we have: #
A Text
``` -* **`fragment_context`** - Parses a fragment as if it were the contents of this context element (like setting `innerHTML` on it). Pass a tag name such as `"td"`, or a `QualName` for an element in another namespace, such as `QualName("svg", "svg")`; a name without a namespace is an HTML element. Implies `full_document=False`. default: None (fragments are parsed in a `body` context). +* **`fragment_context`** - Parses a fragment as if it were the contents of this context element (like setting `innerHTML` on it). Pass a tag name such as `"td"`, or a `QualName` for an element in another namespace, such as `QualName("svg", "svg")`; a name without a namespace is an HTML element. Implies `full_document=False`. The parsed tree is serialized as the contents of the context element, so that, for example, text parsed in a `script` context isn't escaped. default: None (fragments are parsed in a `body` context). === "\"tbody\"" diff --git a/python/tests/test_dom.py b/python/tests/test_dom.py index 7220e41..dc8d2be 100644 --- a/python/tests/test_dom.py +++ b/python/tests/test_dom.py @@ -546,3 +546,14 @@ def test_attach_beside_orphan(): orphan.create_element("b", ordering=ordering) assert dom.serialize(indent=0) == "x
" + + +def test_serializer_children_raw_text(): + dom = markupever.parse( + "a < b
", + markupever.HtmlOptions(full_document=False), + ) + script, style, p = dom.root().children() + assert script.serialize(indent=0, include_self=False) == "if (a < b && c) {}" + assert style.serialize(indent=0, include_self=False) == "a > b { }" + assert p.serialize(indent=0, include_self=False) == "a < b" diff --git a/python/tests/test_parser.py b/python/tests/test_parser.py index 4672305..fe3d2d8 100644 --- a/python/tests/test_parser.py +++ b/python/tests/test_parser.py @@ -139,3 +139,32 @@ def test_meta_content_ending_in_charset(): f'x
' ) assert dom.select_one("p").text() == "x" + + +def test_fragment_context_serialize(): + # A fragment is serialized as the children of its context element, so that it round-trips. + src = 'console.log("a < b
", markupever.HtmlOptions(fragment_context="div") + ) + assert dom.serialize() == "a < b
" diff --git a/src/parser.rs b/src/parser.rs index f563b18..f3f2cf7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -482,10 +482,21 @@ pub fn serialize( let serializer = ::treedom::Serializer::new(&dom, node.id, indent); - let traversal_scope = if include_self { + let value = dom.get(node.id).unwrap().value(); + + let traversal_scope = if let Some(context) = value.document().and(dom.fragment_context()) { + // A fragment's nodes are the children of the document node, but were parsed as + // children of the context element, so serialize them as its children: for example, + // text parsed in a