Class: Prosereflect::Transform::Structure

Inherits:
Object
  • Object
show all
Defined in:
lib/prosereflect/transform/structure.rb

Overview

Structure predicates and helpers for document manipulation

Class Method Summary collapse

Class Method Details

.can_join?(doc, pos) ⇒ Boolean

Check if nodes can be joined at a position

Returns:

  • (Boolean)


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)

Returns:

  • (Boolean)


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

Returns:

  • (Boolean)


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