Class: Prosereflect::Transform::Structure
- Inherits:
-
Object
- Object
- Prosereflect::Transform::Structure
- Defined in:
- lib/prosereflect/transform/structure.rb
Overview
Structure predicates and helpers for document manipulation
Class Method Summary collapse
-
.can_join?(doc, pos) ⇒ Boolean
Check if nodes can be joined at a position.
-
.can_split?(doc, pos, types = nil) ⇒ Boolean
Check if we can split at a position Returns true if the position allows a split (e.g., inside a text node).
-
.find_wrapping(fragment, _from, to, node_type, attrs = nil) ⇒ Object
Find wrapper nodes needed to wrap a range Returns array of node types that would wrap the range.
-
.join_point?(doc, pos) ⇒ Boolean
Find positions where a join can happen.
-
.lift_target(fragment, from, to) ⇒ Object
Find the target depth for lifting content out of a wrapper Returns the depth to which content should be lifted.
Class Method Details
.can_join?(doc, pos) ⇒ Boolean
Check if nodes can be joined at a position
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/prosereflect/transform/structure.rb', line 74 def can_join?(doc, pos) return false if pos <= 0 || pos >= doc.node_size resolved = doc.resolve(pos) # We need to be at a boundary between two children # Check the node at the depth where we're at a child boundary depth = resolved.depth return false unless depth.positive? parent = resolved.node(depth - 1) return false unless parent.respond_to?(:content) return false if parent.content.nil? index = resolved.index(depth) return false unless index.positive? && index < parent.content.size prev_node = parent.content[index - 1] next_node = parent.content[index] prev_node.type == next_node.type end |
.can_split?(doc, pos, types = nil) ⇒ Boolean
Check if we can split at a position Returns true if the position allows a split (e.g., inside a text node)
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/prosereflect/transform/structure.rb', line 13 def can_split?(doc, pos, types = nil) return false if pos.negative? || pos > doc.node_size resolved = doc.resolve(pos) parent = resolved.parent return false unless parent.respond_to?(:content) node_type = parent.respond_to?(:type) ? parent.type : nil if types types.all? { |t| t.respond_to?(:name) ? t.name == node_type : t == node_type } else true end end |
.find_wrapping(fragment, _from, to, node_type, attrs = nil) ⇒ Object
Find wrapper nodes needed to wrap a range Returns array of node types that would wrap the range
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/prosereflect/transform/structure.rb', line 53 def find_wrapping(fragment, _from, to, node_type, attrs = nil) wrappers = [] current_depth = 0 pos = 0 fragment.content.each do |node| node_end = pos + node.node_size break if pos >= to if node.respond_to?(:defining?) && node.defining? && current_depth.zero? # Found a defining node at the boundary wrappers << build_wrapper(node_type, attrs) end pos = node_end end wrappers end |
.join_point?(doc, pos) ⇒ Boolean
Find positions where a join can happen
98 99 100 101 102 |
# File 'lib/prosereflect/transform/structure.rb', line 98 def join_point?(doc, pos) return false unless can_join?(doc, pos) pos end |
.lift_target(fragment, from, to) ⇒ Object
Find the target depth for lifting content out of a wrapper Returns the depth to which content should be lifted
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/prosereflect/transform/structure.rb', line 32 def lift_target(fragment, from, to) depth = 0 pos = 0 fragment.content.each do |node| node_end = pos + node.node_size break if pos >= to # This node is within the range being lifted if pos < to && node_end > from && node.respond_to?(:defining?) && node.defining? depth += 1 end pos = node_end end depth end |