hexp 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/Changelog.md +10 -0
- data/README.md +1 -1
- data/Rakefile +2 -1
- data/hexp.gemspec +0 -1
- data/lib/hexp.rb +1 -1
- data/lib/hexp/css_selector.rb +24 -1
- data/lib/hexp/list.rb +5 -3
- data/lib/hexp/mutable_tree_walk.rb +79 -0
- data/lib/hexp/node.rb +13 -3
- data/lib/hexp/node/attributes.rb +1 -1
- data/lib/hexp/node/css_selection.rb +17 -53
- data/lib/hexp/node/normalize.rb +12 -5
- data/lib/hexp/text_node.rb +0 -2
- data/lib/hexp/version.rb +1 -1
- data/spec/unit/hexp/mutable_tree_walk_spec.rb +72 -0
- data/spec/unit/hexp/node/css_selection_spec.rb +1 -1
- metadata +5 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45fe82cfc464b888c41d8b632a929f6074d9b1cb
|
4
|
+
data.tar.gz: 9a015de7db34bd56cadf8304a940d51fea9f6d9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef380c391229dcb9716d9472882714ded77f5c3e0169f8ff98312a5e23bd1b61e3caed513f0e2c561e86b9e399b94ee88d0fbd7606f1ee83b353884199cff596
|
7
|
+
data.tar.gz: 29570e22c84b840bd04429ca27f5dc9535e3e4b080007ffda9e80f9472b61ae476ca1a4a036600c8db6f6cd9921a2be0cd44dc8c394505b7a5642874b6148454
|
data/.travis.yml
CHANGED
data/Changelog.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
[full diff](http://github.com/plexus/hexp/compare/v0.4.2...master)
|
4
4
|
|
5
|
+
### v0.4.3
|
6
|
+
|
7
|
+
Performance improvements
|
8
|
+
|
9
|
+
* Introduce MutableTreeWalk to speed up css selection
|
10
|
+
* Drop Adamantium. This means we have less of a guarantee of deep
|
11
|
+
immutability, but it does speed things up
|
12
|
+
* Prevent type coercion from happening if inputs are already valid
|
13
|
+
* Raise an exception when a node's tag is not a Symbol
|
14
|
+
|
5
15
|
### v0.4.2
|
6
16
|
|
7
17
|
* Added Hexp::List#append
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
# Hexp
|
14
14
|
|
15
|
-
**Hexp** (pronounced [ˈɦækspi:]) is a DOM API for Ruby. It lets you treat HTML in your applications as objects, instead of strings. It is a standalone, framework independent library. You can use it to build full web pages, or to clean up your helpers and presenters.
|
15
|
+
**Hexp** (pronounced [ˈɦækspi:]) is a DOM API for Ruby. It lets you treat HTML in your applications as objects, instead of strings. It is a standalone, framework independent library. You can use it to build full web pages, or just to clean up your helpers and presenters.
|
16
16
|
|
17
17
|
## Fundamentals
|
18
18
|
|
data/Rakefile
CHANGED
@@ -48,6 +48,7 @@ task :default => :mutant
|
|
48
48
|
|
49
49
|
task :mutant do
|
50
50
|
pattern = ENV.fetch('PATTERN', 'Hexp*')
|
51
|
-
|
51
|
+
opts = ENV.fetch('MUTANT_OPTS', '').split(' ')
|
52
|
+
result = Mutant::CLI.run(%w[-Ilib -rhexp --use rspec --score 100] + opts + [pattern])
|
52
53
|
fail unless result == Mutant::CLI::EXIT_SUCCESS
|
53
54
|
end
|
data/hexp.gemspec
CHANGED
@@ -19,7 +19,6 @@ Gem::Specification.new do |gem|
|
|
19
19
|
|
20
20
|
gem.add_runtime_dependency 'sass', '~> 3.2.19'
|
21
21
|
gem.add_runtime_dependency 'nokogiri', '~> 1.6'
|
22
|
-
gem.add_runtime_dependency 'adamantium', '~> 0.2'
|
23
22
|
gem.add_runtime_dependency 'equalizer', '~> 0.0'
|
24
23
|
gem.add_runtime_dependency 'concord', '~> 0.0'
|
25
24
|
|
data/lib/hexp.rb
CHANGED
@@ -4,7 +4,6 @@ require 'pathname'
|
|
4
4
|
|
5
5
|
require 'nokogiri'
|
6
6
|
require 'sass'
|
7
|
-
require 'adamantium'
|
8
7
|
require 'equalizer'
|
9
8
|
require 'concord'
|
10
9
|
|
@@ -126,3 +125,4 @@ require 'hexp/h'
|
|
126
125
|
|
127
126
|
require 'hexp/builder'
|
128
127
|
require 'hexp/unparser'
|
128
|
+
require 'hexp/mutable_tree_walk'
|
data/lib/hexp/css_selector.rb
CHANGED
@@ -4,7 +4,6 @@ module Hexp
|
|
4
4
|
#
|
5
5
|
module Members
|
6
6
|
include Equalizer.new(:members)
|
7
|
-
include Adamantium
|
8
7
|
|
9
8
|
extend Forwardable
|
10
9
|
def_delegator :@members, :empty?
|
@@ -106,6 +105,12 @@ module Hexp
|
|
106
105
|
sequence.head_matches?(element)
|
107
106
|
end
|
108
107
|
end
|
108
|
+
|
109
|
+
def matches_path?(path)
|
110
|
+
members.any? do |sequence|
|
111
|
+
sequence.matches_path?(path)
|
112
|
+
end
|
113
|
+
end
|
109
114
|
end
|
110
115
|
|
111
116
|
# A single CSS sequence like 'div span .foo'
|
@@ -124,6 +129,24 @@ module Hexp
|
|
124
129
|
members.first.matches?(element)
|
125
130
|
end
|
126
131
|
|
132
|
+
# Warning: Highly optimized cryptic code
|
133
|
+
def matches_path?(path)
|
134
|
+
return false if path.length < members.length
|
135
|
+
return false unless members.last.matches?(path.last)
|
136
|
+
|
137
|
+
path_idx = path.length - 2
|
138
|
+
mem_idx = members.length - 2
|
139
|
+
|
140
|
+
until path_idx < mem_idx || mem_idx == -1
|
141
|
+
if members[mem_idx].matches?(path[path_idx])
|
142
|
+
mem_idx -= 1
|
143
|
+
end
|
144
|
+
path_idx -= 1
|
145
|
+
end
|
146
|
+
|
147
|
+
mem_idx == -1
|
148
|
+
end
|
149
|
+
|
127
150
|
# Drop the first element of this Sequence
|
128
151
|
#
|
129
152
|
# This returns a new Sequence, with one member less.
|
data/lib/hexp/list.rb
CHANGED
@@ -2,8 +2,6 @@ module Hexp
|
|
2
2
|
# A list of nodes
|
3
3
|
#
|
4
4
|
class List < DelegateClass(Array)
|
5
|
-
include Adamantium
|
6
|
-
|
7
5
|
# Create new Hexp::List
|
8
6
|
#
|
9
7
|
# @example
|
@@ -14,7 +12,11 @@ module Hexp
|
|
14
12
|
#
|
15
13
|
# @api public
|
16
14
|
def initialize(nodes)
|
17
|
-
|
15
|
+
if nodes.instance_of?(List)
|
16
|
+
super(nodes.__getobj__).freeze
|
17
|
+
else
|
18
|
+
super nodes.to_ary.map(&Node::Normalize.method(:coerce_node)).freeze
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
22
|
# Convenience constructor
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Hexp
|
2
|
+
class MutableTreeWalk
|
3
|
+
attr_reader :root, :path, :result
|
4
|
+
|
5
|
+
def initialize(root)
|
6
|
+
@root = root
|
7
|
+
@path = [root]
|
8
|
+
@replacements = [{}]
|
9
|
+
@result = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def next!
|
13
|
+
return if end?
|
14
|
+
if current.children.any?
|
15
|
+
@path << current.children.first
|
16
|
+
@replacements << {}
|
17
|
+
elsif @path.length == 1
|
18
|
+
@result = @path.pop
|
19
|
+
else
|
20
|
+
backtrack_and_right!
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def backtrack_and_right!
|
25
|
+
while at_rightmost_child?
|
26
|
+
@path.pop
|
27
|
+
handle_replacements!
|
28
|
+
if @path.length == 1 #back at start, we're done
|
29
|
+
@result = @path.pop
|
30
|
+
return
|
31
|
+
end
|
32
|
+
end
|
33
|
+
go_right!
|
34
|
+
end
|
35
|
+
|
36
|
+
def replace!(val)
|
37
|
+
@replacements.last[current_idx] = val
|
38
|
+
end
|
39
|
+
|
40
|
+
def handle_replacements!
|
41
|
+
replacements = @replacements.pop
|
42
|
+
return if replacements.empty?
|
43
|
+
new_children = [*current.children]
|
44
|
+
replacements.each do |idx, val|
|
45
|
+
new_children[idx..idx] = val
|
46
|
+
end
|
47
|
+
new_node = current.set_children(new_children)
|
48
|
+
if @path.length == 1
|
49
|
+
@path = [new_node]
|
50
|
+
else
|
51
|
+
@replacements.last[current_idx] = new_node
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def at_rightmost_child?
|
56
|
+
current.equal? parent.children.last
|
57
|
+
end
|
58
|
+
|
59
|
+
def go_right!
|
60
|
+
@path[-1] = parent.children[current_idx + 1]
|
61
|
+
end
|
62
|
+
|
63
|
+
def current_idx
|
64
|
+
parent.children.find_index { |ch| current.equal?(ch) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def parent
|
68
|
+
@path[-2]
|
69
|
+
end
|
70
|
+
|
71
|
+
def current
|
72
|
+
@path.last
|
73
|
+
end
|
74
|
+
|
75
|
+
def end?
|
76
|
+
@path.empty?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/hexp/node.rb
CHANGED
@@ -53,14 +53,12 @@ module Hexp
|
|
53
53
|
#
|
54
54
|
class Node
|
55
55
|
include Concord::Public.new(:tag, :attributes, :children)
|
56
|
-
include Adamantium
|
57
56
|
extend Forwardable
|
58
57
|
|
59
58
|
include Hexp::Node::Attributes
|
60
59
|
include Hexp::Node::Children
|
61
60
|
|
62
61
|
alias attrs attributes
|
63
|
-
memoize :class_list
|
64
62
|
|
65
63
|
# The HTML tag of this node
|
66
64
|
#
|
@@ -125,7 +123,19 @@ module Hexp
|
|
125
123
|
# @api public
|
126
124
|
#
|
127
125
|
def initialize(*args)
|
128
|
-
|
126
|
+
tag_ok = args[0].instance_of?(Symbol)
|
127
|
+
raise "The tag of node should be a Symbol" unless tag_ok
|
128
|
+
|
129
|
+
attrs_ok = args[1].instance_of?(Hash) &&
|
130
|
+
args[1].all? {|k,v| k.instance_of?(String) && v.instance_of?(String) }
|
131
|
+
|
132
|
+
if attrs_ok && args[2].instance_of?(List)
|
133
|
+
super(args[0], args[1], args[2])
|
134
|
+
elsif attrs_ok && args[2].instance_of?(Array)
|
135
|
+
super(args[0], args[1], List.new(args[2]))
|
136
|
+
else
|
137
|
+
super(*Normalize.new(args).call)
|
138
|
+
end.freeze
|
129
139
|
end
|
130
140
|
|
131
141
|
# Standard hexp coercion protocol, return self
|
data/lib/hexp/node/attributes.rb
CHANGED
@@ -73,10 +73,15 @@ module Hexp
|
|
73
73
|
def each(&block)
|
74
74
|
return to_enum(:each) unless block_given?
|
75
75
|
|
76
|
-
@node
|
77
|
-
|
76
|
+
walk = MutableTreeWalk.new(@node)
|
77
|
+
|
78
|
+
until walk.end?
|
79
|
+
if comma_sequence.matches_path?(walk.path)
|
80
|
+
yield walk.current
|
81
|
+
end
|
82
|
+
walk.next!
|
78
83
|
end
|
79
|
-
|
84
|
+
|
80
85
|
self
|
81
86
|
end
|
82
87
|
|
@@ -91,14 +96,16 @@ module Hexp
|
|
91
96
|
def rewrite(&block)
|
92
97
|
return @node if @node.text?
|
93
98
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
+
walk = MutableTreeWalk.new(@node)
|
100
|
+
|
101
|
+
until walk.end?
|
102
|
+
if comma_sequence.matches_path?(walk.path)
|
103
|
+
walk.replace!(block.call(walk.current))
|
99
104
|
end
|
100
|
-
|
101
|
-
|
105
|
+
walk.next!
|
106
|
+
end
|
107
|
+
|
108
|
+
walk.result
|
102
109
|
end
|
103
110
|
|
104
111
|
private
|
@@ -131,49 +138,6 @@ module Hexp
|
|
131
138
|
comma_sequence.matches?(@node)
|
132
139
|
end
|
133
140
|
|
134
|
-
# Consume the matching part of the comma sequence, return the rest
|
135
|
-
#
|
136
|
-
# Returns a new comma sequence with the parts removed that have been
|
137
|
-
# consumed by matching against this node. If no part matches, returns nil.
|
138
|
-
#
|
139
|
-
# @return [Hexp::CssSelector::CommaSequence]
|
140
|
-
#
|
141
|
-
# @api private
|
142
|
-
def next_comma_sequence
|
143
|
-
@next_comma_sequence ||= CssSelector::CommaSequence.new(consume_matching_heads)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Recurse down a child down, passing in the remaining part of the selector
|
147
|
-
#
|
148
|
-
# @param [Hexp::Node] child
|
149
|
-
# One of the children of the node in this selection object
|
150
|
-
#
|
151
|
-
# @return [Hexp::Node::CssSelection]
|
152
|
-
#
|
153
|
-
# @api private
|
154
|
-
def next_selection_for(child)
|
155
|
-
self.class.new(child, next_comma_sequence)
|
156
|
-
end
|
157
|
-
|
158
|
-
# For each sequence in the comma sequence, remove the head if it matches
|
159
|
-
#
|
160
|
-
# For example, if this node is a `H[:div]`, and the selector is
|
161
|
-
# `span.foo, div a[:href]`, then the result of this method will be
|
162
|
-
# `span.foo, a[:href]`. This can then be used to match any child nodes.
|
163
|
-
#
|
164
|
-
# @return [Hexp::CssSelector::CommaSequence]
|
165
|
-
#
|
166
|
-
# @api private
|
167
|
-
def consume_matching_heads
|
168
|
-
comma_sequence.members.flat_map do |sequence|
|
169
|
-
if sequence.head_matches? @node
|
170
|
-
[sequence, sequence.drop_head]
|
171
|
-
else
|
172
|
-
[sequence]
|
173
|
-
end
|
174
|
-
end.reject(&:empty?)
|
175
|
-
end
|
176
|
-
|
177
141
|
end
|
178
142
|
end
|
179
143
|
end
|
data/lib/hexp/node/normalize.rb
CHANGED
@@ -43,6 +43,7 @@ module Hexp
|
|
43
43
|
#
|
44
44
|
# @api private
|
45
45
|
def normalized_attributes
|
46
|
+
return attributes if attributes.all? {|k,v| k.instance_of?(String) && v.instance_of?(String) }
|
46
47
|
Hash[*
|
47
48
|
attributes.flat_map do |key, value|
|
48
49
|
[key, value].map(&:to_s)
|
@@ -56,10 +57,12 @@ module Hexp
|
|
56
57
|
#
|
57
58
|
# @api private
|
58
59
|
def children
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
start = @raw[1].instance_of?(Hash) ? 2 : 1
|
61
|
+
if @raw[start].respond_to?(:to_ary)
|
62
|
+
@raw[start].to_ary
|
63
|
+
else
|
64
|
+
@raw.drop(start)
|
65
|
+
end
|
63
66
|
end
|
64
67
|
|
65
68
|
# Normalize the third element of a hexp node, the list of children
|
@@ -68,7 +71,11 @@ module Hexp
|
|
68
71
|
#
|
69
72
|
# @api private
|
70
73
|
def normalized_children
|
71
|
-
Hexp::List
|
74
|
+
if children.instance_of?(Hexp::List)
|
75
|
+
children
|
76
|
+
else
|
77
|
+
Hexp::List.new( children )
|
78
|
+
end
|
72
79
|
end
|
73
80
|
|
74
81
|
def self.coerce_node(node)
|
data/lib/hexp/text_node.rb
CHANGED
@@ -7,8 +7,6 @@ module Hexp
|
|
7
7
|
# converted to `TextNode` instances, so there is usually no reason to instantiate
|
8
8
|
# these yourself.
|
9
9
|
class TextNode < DelegateClass(String)
|
10
|
-
include Adamantium
|
11
|
-
|
12
10
|
# Inspect the TextNode
|
13
11
|
#
|
14
12
|
# This delegates to the underlying String, making it
|
data/lib/hexp/version.rb
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
RSpec.describe Hexp::MutableTreeWalk do
|
2
|
+
|
3
|
+
let(:node) { H[:ul, H[:p, [H[:li, 'foo', 'boo'], H[:li, 'bar']]]] }
|
4
|
+
let(:walk) { Hexp::MutableTreeWalk.new(node) }
|
5
|
+
|
6
|
+
it 'should start at the root' do
|
7
|
+
expect(walk.current).to eql node
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should not have a parent at the root' do
|
11
|
+
expect(walk.parent).to be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should descend to the children' do
|
15
|
+
walk.next!
|
16
|
+
expect(walk.current).to eql H[:p, [H[:li, ["foo", "boo"]], H[:li, ["bar"]]]]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should go depth first' do
|
20
|
+
2.times { walk.next! }
|
21
|
+
expect(walk.current).to eql H[:li, 'foo', 'boo']
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should also do text nodes' do
|
25
|
+
3.times { walk.next! }
|
26
|
+
expect(walk.current).to eq 'foo'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should go left to right' do
|
30
|
+
4.times { walk.next! }
|
31
|
+
expect(walk.current).to eq 'boo'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should go back up and right' do
|
35
|
+
5.times { walk.next! }
|
36
|
+
expect(walk.current).to eql H[:li, 'bar']
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should finish on nil' do
|
40
|
+
7.times { walk.next! }
|
41
|
+
expect(walk.current).to be_nil
|
42
|
+
expect(walk.end?).to be true
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'stays at the end' do
|
46
|
+
8.times { walk.next! }
|
47
|
+
expect(walk.end?).to be true
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should allow replacements' do
|
51
|
+
2.times { walk.next! }
|
52
|
+
walk.replace! H[:foo]
|
53
|
+
6.times { walk.next! }
|
54
|
+
expect(walk.result).to eql H[:ul, H[:p, H[:foo], H[:li, 'bar']]]
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should allow replacements' do
|
58
|
+
7.times do
|
59
|
+
walk.next!
|
60
|
+
if !walk.end? && !walk.current.text? && walk.current.tag?(:li)
|
61
|
+
walk.replace! H[:span, walk.current]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
expect(walk.result).to eql H[:ul,
|
66
|
+
H[:p,
|
67
|
+
H[:span, H[:li, 'foo', 'boo']],
|
68
|
+
H[:span, H[:li, 'bar']]]]
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
end
|
@@ -18,7 +18,7 @@ describe Hexp::Node::CssSelection do
|
|
18
18
|
let(:hexp) { H[:span, {id: 'span-1'}, H[:span, id: 'span-2']] }
|
19
19
|
|
20
20
|
it 'should match all nodes of that tag' do
|
21
|
-
expect(selection.to_a).to eq [ H[:span, id: 'span-2']
|
21
|
+
expect(selection.to_a).to eq [ hexp, H[:span, id: 'span-2'] ]
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hexp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arne Brasseur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sass
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.6'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: adamantium
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0.2'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0.2'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: equalizer
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -193,6 +179,7 @@ files:
|
|
193
179
|
- lib/hexp/errors.rb
|
194
180
|
- lib/hexp/h.rb
|
195
181
|
- lib/hexp/list.rb
|
182
|
+
- lib/hexp/mutable_tree_walk.rb
|
196
183
|
- lib/hexp/node.rb
|
197
184
|
- lib/hexp/node/attributes.rb
|
198
185
|
- lib/hexp/node/children.rb
|
@@ -222,6 +209,7 @@ files:
|
|
222
209
|
- spec/unit/hexp/dsl_spec.rb
|
223
210
|
- spec/unit/hexp/h_spec.rb
|
224
211
|
- spec/unit/hexp/list_spec.rb
|
212
|
+
- spec/unit/hexp/mutable_tree_walk_spec.rb
|
225
213
|
- spec/unit/hexp/node/attr_spec.rb
|
226
214
|
- spec/unit/hexp/node/attributes_spec.rb
|
227
215
|
- spec/unit/hexp/node/children_spec.rb
|
@@ -280,6 +268,7 @@ test_files:
|
|
280
268
|
- spec/unit/hexp/dsl_spec.rb
|
281
269
|
- spec/unit/hexp/h_spec.rb
|
282
270
|
- spec/unit/hexp/list_spec.rb
|
271
|
+
- spec/unit/hexp/mutable_tree_walk_spec.rb
|
283
272
|
- spec/unit/hexp/node/attr_spec.rb
|
284
273
|
- spec/unit/hexp/node/attributes_spec.rb
|
285
274
|
- spec/unit/hexp/node/children_spec.rb
|