diff --git a/README.md b/README.md index 6b212f4..6593930 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This package provides Python implementations of the following [ProseMirror](https://prosemirror.net/) packages: - [`prosemirror-model`](https://github.com/ProseMirror/prosemirror-model) version 1.18.1 -- [`prosemirror-transform`](https://github.com/ProseMirror/prosemirror-transform) version 1.7.1 +- [`prosemirror-transform`](https://github.com/ProseMirror/prosemirror-transform) version 1.7.5 - [`prosemirror-test-builder`](https://github.com/ProseMirror/prosemirror-test-builder) - [`prosemirror-schema-basic`](https://github.com/ProseMirror/prosemirror-schema-basic) version 1.1.2 - [`prosemirror-schema-list`](https://github.com/ProseMirror/prosemirror-schema-list) diff --git a/prosemirror/transform/structure.py b/prosemirror/transform/structure.py index 7240f5f..ce878b0 100644 --- a/prosemirror/transform/structure.py +++ b/prosemirror/transform/structure.py @@ -122,14 +122,17 @@ def can_split(doc, pos, depth=None, types_after=None): if node.type.spec.get("isolating"): return False rest = node.content.cut_by_index(index, node.child_count) + if types_after and len(types_after) > i: + override_child = types_after[i + 1] + rest = rest.replace_child( + 0, override_child["type"].create(override_child.get("attrs")) + ) after = None if types_after and len(types_after) > i: after = types_after[i] if not after: after = node if isinstance(after, dict): - if after != node: - rest = rest.replace_child(0, after["type"].create(after.get("attrs"))) if not node.can_replace(index + 1, node.child_count) or not after[ "type" ].valid_content(rest): diff --git a/prosemirror/transform/transform.py b/prosemirror/transform/transform.py index 131d03b..ac67a4d 100644 --- a/prosemirror/transform/transform.py +++ b/prosemirror/transform/transform.py @@ -1,3 +1,4 @@ +import re from typing import Union from prosemirror.model import Fragment, Mark, MarkType, Node, NodeType, Slice @@ -156,24 +157,43 @@ def clear_incompatible(self, pos, parent_type, match=None): if match is None: match = parent_type.content_match node = self.doc.node_at(pos) - del_steps = [] + repl_steps = [] cur = pos + 1 for i in range(node.child_count): child = node.child(i) end = cur + child.node_size allowed = match.match_type(child.type, child.attrs) if not allowed: - del_steps.append(ReplaceStep(cur, end, Slice.empty)) + repl_steps.append(ReplaceStep(cur, end, Slice.empty)) else: match = allowed for j in range(len(child.marks)): if not parent_type.allows_mark_type(child.marks[j].type): self.step(RemoveMarkStep(cur, end, child.marks[j])) + if child.is_text and not parent_type.spec.get("code"): + newline = re.compile(r"\r?\n|\r") + slice = None + m = newline.search(child.text) + while m: + if slice is None: + slice = Slice( + Fragment.from_( + parent_type.schema.text( + " ", parent_type.allowed_marks(child.marks) + ) + ), + 0, + 0, + ) + repl_steps.append( + ReplaceStep(cur + m.start(), cur + m.end(), slice) + ) + m = newline.search(child.text, m.end()) cur = end if not match.valid_end: fill = match.fill_before(Fragment.empty, True) self.replace(cur, cur, Slice(fill, 0, 0)) - for item in reversed(del_steps): + for item in reversed(repl_steps): self.step(item) return self @@ -240,11 +260,13 @@ def replace_range(self, from_, to, slice): d = preferred_depth - 1 while d >= 0: - type = left_nodes[d].type - def_ = defines_content(type) - if def_ and from__.node(preferred_target_index).type.name != type.name: + left_node = left_nodes[d] + def_ = defines_content(left_node.type) + if def_ and not left_node.same_markup( + from__.node(abs(preferred_target) - 1) + ): preferred_depth = d - elif def_ or not type.is_text_block: + elif def_ or not left_node.type.is_text_block: break d -= 1 diff --git a/tests/prosemirror_transform/tests/test_trans.py b/tests/prosemirror_transform/tests/test_trans.py index 573a3d8..a1cf79c 100644 --- a/tests/prosemirror_transform/tests/test_trans.py +++ b/tests/prosemirror_transform/tests/test_trans.py @@ -502,6 +502,18 @@ def test_wrap(doc, expect, type, attrs, test_transform): "code_block", None, ), + ( + doc(p("one", img(), "two", img(), "three")), + doc(pre("onetwothree")), + "code_block", + None, + ), + ( + doc(pre("one\ntwo\nthree")), + doc(p("one two three")), + "paragraph", + None, + ), ], ) def test_set_block_type(doc, expect, node_type, attrs, test_transform): @@ -718,6 +730,16 @@ def test_set_node_attribute(doc, expect, attr, value, test_transform): doc(blockquote(blockquote(blockquote(p("hi"))))).slice(3, 6, True), doc(p("hi")), ), + ( + doc(ul(li(p("list1"), blockquote(p(""))))), + doc(blockquote(p("one"))), + doc(ul(li(p("list1"), blockquote(p("one"))))), + ), + ( + doc(ul(li(p("list1"), ul(li(p("list2"), blockquote(p(""))))))), + doc(blockquote(p("one"))), + doc(ul(li(p("list1"), ul(li(p("list2"), blockquote(p("one"))))))), + ), ], ) def test_replace(doc, source, expect, test_transform):