Class: Prosereflect::Schema::Fragment
- Inherits:
-
Object
- Object
- Prosereflect::Schema::Fragment
- Defined in:
- lib/prosereflect/schema/fragment.rb
Overview
Lightweight Fragment class for schema validation This is a minimal implementation focused on the operations needed by ContentMatch
Instance Attribute Summary collapse
-
#content ⇒ Object
readonly
Returns the value of attribute content.
Class Method Summary collapse
Instance Method Summary collapse
- #<<(node) ⇒ Object
- #[](index) ⇒ Object
- #[]=(index, value) ⇒ Object
- #append(other) ⇒ Object
- #cut(from = 0, to = nil) ⇒ Object
- #descendants(f) ⇒ Object
- #each(&block) ⇒ Object
- #empty? ⇒ Boolean
- #eq?(other) ⇒ Boolean
- #first ⇒ Object
-
#initialize(content = []) ⇒ Fragment
constructor
A new instance of Fragment.
- #last ⇒ Object
- #length ⇒ Object
- #nodes_between(from, to, f, node_start = 0) ⇒ Object
- #replace_child(index, replacement) ⇒ Object
- #size ⇒ Object
- #to_s ⇒ Object
Constructor Details
#initialize(content = []) ⇒ Fragment
Returns a new instance of Fragment.
10 11 12 |
# File 'lib/prosereflect/schema/fragment.rb', line 10 def initialize(content = []) @content = content.is_a?(Array) ? content : [content].compact end |
Instance Attribute Details
#content ⇒ Object (readonly)
Returns the value of attribute content.
8 9 10 |
# File 'lib/prosereflect/schema/fragment.rb', line 8 def content @content end |
Class Method Details
.empty ⇒ Object
150 151 152 |
# File 'lib/prosereflect/schema/fragment.rb', line 150 def empty @empty ||= new([]) end |
.from(nodes) ⇒ Object
154 155 156 157 158 159 160 161 162 |
# File 'lib/prosereflect/schema/fragment.rb', line 154 def from(nodes) return empty if nodes.nil? || (nodes.is_a?(Array) && nodes.empty?) case nodes when Fragment then nodes when Array then new(nodes) else new([nodes]) end end |
Instance Method Details
#<<(node) ⇒ Object
46 47 48 49 |
# File 'lib/prosereflect/schema/fragment.rb', line 46 def <<(node) @content << node self end |
#[](index) ⇒ Object
30 31 32 |
# File 'lib/prosereflect/schema/fragment.rb', line 30 def [](index) @content[index] end |
#[]=(index, value) ⇒ Object
34 35 36 |
# File 'lib/prosereflect/schema/fragment.rb', line 34 def []=(index, value) @content[index] = value end |
#append(other) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/prosereflect/schema/fragment.rb', line 51 def append(other) return self if other.empty? return other if empty? last_node = @content.last first_other = other.first if last_node.text? && first_other.text? && last_node.same_markup?(first_other) merged = last_node.with_text(last_node.text + first_other.text) new_content = @content[0...-1] + [merged] + other.content[1..] Fragment.new(new_content) else Fragment.new(@content + other.content) end end |
#cut(from = 0, to = nil) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/prosereflect/schema/fragment.rb', line 67 def cut(from = 0, to = nil) to ||= size return Fragment.empty if from.zero? && to == size return Fragment.empty if to <= from result = [] pos = 0 i = 0 while pos < to && i < @content.length child = @content[i] child_end = pos + child.node_size if child_end > from if pos < from || child_end > to if child.text? start_offset = [0, from - pos].max end_offset = [child.text.length, to - pos].min else start_offset = [0, from - pos - 1].max end_offset = [child.content.size, to - pos - 1].min end cut_child = child.cut(start_offset, end_offset) result << cut_child if cut_child else result << child end end pos = child_end i += 1 end Fragment.new(result) end |
#descendants(f) ⇒ Object
141 142 143 |
# File 'lib/prosereflect/schema/fragment.rb', line 141 def descendants(f) nodes_between(0, size, f) end |
#each(&block) ⇒ Object
42 43 44 |
# File 'lib/prosereflect/schema/fragment.rb', line 42 def each(&block) @content.each(&block) end |
#empty? ⇒ Boolean
18 19 20 |
# File 'lib/prosereflect/schema/fragment.rb', line 18 def empty? @content.empty? end |
#eq?(other) ⇒ Boolean
112 113 114 115 116 |
# File 'lib/prosereflect/schema/fragment.rb', line 112 def eq?(other) return false unless @content.length == other.content.length @content.each_with_index.all? { |node, i| node.eq?(other.content[i]) } end |
#first ⇒ Object
22 23 24 |
# File 'lib/prosereflect/schema/fragment.rb', line 22 def first @content.first end |
#last ⇒ Object
26 27 28 |
# File 'lib/prosereflect/schema/fragment.rb', line 26 def last @content.last end |
#length ⇒ Object
38 39 40 |
# File 'lib/prosereflect/schema/fragment.rb', line 38 def length @content.length end |
#nodes_between(from, to, f, node_start = 0) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/prosereflect/schema/fragment.rb', line 118 def nodes_between(from, to, f, node_start = 0) i = 0 pos = 0 while pos < to && i < @content.length child = @content[i] end_pos = pos + child.node_size if end_pos > from && f.call(child, node_start + pos, i) != false && child.content.size.positive? child.nodes_between( [0, from - pos].max, [child.content.size, to - pos].min, f, node_start + pos + 1, ) end pos = end_pos i += 1 end end |
#replace_child(index, replacement) ⇒ Object
104 105 106 107 108 109 110 |
# File 'lib/prosereflect/schema/fragment.rb', line 104 def replace_child(index, replacement) return self if @content[index] == replacement new_content = @content.dup new_content[index] = replacement Fragment.new(new_content) end |
#size ⇒ Object
14 15 16 |
# File 'lib/prosereflect/schema/fragment.rb', line 14 def size @content.sum(&:node_size) end |
#to_s ⇒ Object
145 146 147 |
# File 'lib/prosereflect/schema/fragment.rb', line 145 def to_s "<#{@content.join(', ')}>" end |