deface 0.9.1 → 1.0.0.rc1
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.
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/.travis.yml +1 -0
- data/README.markdown +139 -59
- data/deface.gemspec +4 -2
- data/gemfiles/haml3_2.gemfile +5 -0
- data/lib/deface.rb +28 -1
- data/lib/deface/action_view_extensions.rb +7 -1
- data/lib/deface/actions/action.rb +19 -0
- data/lib/deface/actions/add_to_attributes.rb +15 -0
- data/lib/deface/actions/attribute_action.rb +33 -0
- data/lib/deface/actions/element_action.rb +13 -0
- data/lib/deface/actions/insert_after.rb +9 -0
- data/lib/deface/actions/insert_before.rb +9 -0
- data/lib/deface/actions/insert_bottom.rb +14 -0
- data/lib/deface/actions/insert_top.rb +14 -0
- data/lib/deface/actions/remove.rb +13 -0
- data/lib/deface/actions/remove_from_attributes.rb +13 -0
- data/lib/deface/actions/replace.rb +14 -0
- data/lib/deface/actions/replace_contents.rb +19 -0
- data/lib/deface/actions/set_attributes.rb +12 -0
- data/lib/deface/actions/surround.rb +24 -0
- data/lib/deface/actions/surround_action.rb +15 -0
- data/lib/deface/actions/surround_contents.rb +33 -0
- data/lib/deface/applicator.rb +35 -191
- data/lib/deface/dsl/context.rb +7 -3
- data/lib/deface/dsl/loader.rb +5 -2
- data/lib/deface/environment.rb +31 -1
- data/lib/deface/haml_converter.rb +33 -5
- data/lib/deface/matchers/element.rb +13 -0
- data/lib/deface/matchers/range.rb +52 -0
- data/lib/deface/override.rb +28 -57
- data/lib/deface/sources/copy.rb +15 -0
- data/lib/deface/sources/cut.rb +25 -0
- data/lib/deface/sources/erb.rb +9 -0
- data/lib/deface/sources/haml.rb +14 -0
- data/lib/deface/sources/partial.rb +13 -0
- data/lib/deface/sources/source.rb +11 -0
- data/lib/deface/sources/template.rb +13 -0
- data/lib/deface/sources/text.rb +9 -0
- data/lib/deface/utils/failure_finder.rb +41 -0
- data/spec/deface/action_view_template_spec.rb +28 -2
- data/spec/deface/actions/add_to_attributes_spec.rb +62 -0
- data/spec/deface/actions/insert_after_spec.rb +19 -0
- data/spec/deface/actions/insert_before_spec.rb +19 -0
- data/spec/deface/actions/insert_bottom_spec.rb +28 -0
- data/spec/deface/actions/insert_top_spec.rb +28 -0
- data/spec/deface/actions/remove_from_attributes_spec.rb +81 -0
- data/spec/deface/actions/remove_spec.rb +30 -0
- data/spec/deface/actions/replace_contents_spec.rb +29 -0
- data/spec/deface/actions/replace_spec.rb +52 -0
- data/spec/deface/actions/set_attributes_spec.rb +62 -0
- data/spec/deface/actions/surround_contents_spec.rb +57 -0
- data/spec/deface/actions/surround_spec.rb +57 -0
- data/spec/deface/applicator_spec.rb +0 -354
- data/spec/deface/dsl/context_spec.rb +14 -7
- data/spec/deface/dsl/loader_spec.rb +12 -4
- data/spec/deface/override_spec.rb +26 -3
- data/spec/deface/template_helper_spec.rb +11 -0
- data/spec/deface/utils/failure_finder_spec.rb +76 -0
- data/spec/spec_helper.rb +21 -2
- data/tasks/utils.rake +24 -0
- metadata +91 -14
@@ -0,0 +1,13 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class ElementAction < Action
|
4
|
+
attr_reader :source_element
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
super(options)
|
8
|
+
@source_element = options[:source_element]
|
9
|
+
raise(DefaceError, "No source_element option specified") unless @source_element
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class InsertBottom < ElementAction
|
4
|
+
def execute(target_element)
|
5
|
+
target_element = target_element.first
|
6
|
+
if target_element.children.size == 0
|
7
|
+
target_element.children = source_element
|
8
|
+
else
|
9
|
+
target_element.children.after(source_element)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class InsertTop < ElementAction
|
4
|
+
def execute(target_element)
|
5
|
+
target_element = target_element.first
|
6
|
+
if target_element.children.size == 0
|
7
|
+
target_element.children = source_element
|
8
|
+
else
|
9
|
+
target_element.children.before(source_element)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class RemoveFromAttributes < AttributeAction
|
4
|
+
def execute_for_attribute(target_element, name, value)
|
5
|
+
if target_element.attributes.key?(name)
|
6
|
+
target_element.set_attribute(name, target_element.attributes[name].value.gsub(value.to_s, '').strip)
|
7
|
+
elsif target_element.attributes.key?("data-erb-#{name}")
|
8
|
+
target_element.set_attribute("data-erb-#{name}", target_element.attributes["data-erb-#{name}"].value.gsub(value.to_s, '').strip)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class ReplaceContents < ElementAction
|
4
|
+
def execute(target_range)
|
5
|
+
if target_range.length == 1
|
6
|
+
target_range.first.children.remove
|
7
|
+
target_range.first.add_child(source_element)
|
8
|
+
else
|
9
|
+
target_range[1..-2].map(&:remove)
|
10
|
+
target_range.first.after(source_element)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def range_compatible?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class SetAttributes < AttributeAction
|
4
|
+
def execute_for_attribute(target_element, name, value)
|
5
|
+
target_element.remove_attribute(name)
|
6
|
+
target_element.remove_attribute("data-erb-#{name}")
|
7
|
+
|
8
|
+
target_element.set_attribute("data-erb-#{name}", value.to_s)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class Surround < SurroundAction
|
4
|
+
def execute(target_range)
|
5
|
+
original_placeholders.each do |placeholder|
|
6
|
+
start = target_range[0].clone(1)
|
7
|
+
placeholder.replace start
|
8
|
+
|
9
|
+
target_range[1..-1].each do |element|
|
10
|
+
element = element.clone(1)
|
11
|
+
start.after element
|
12
|
+
start = element
|
13
|
+
end
|
14
|
+
end
|
15
|
+
target_range.first.before(source_element)
|
16
|
+
target_range.map(&:remove)
|
17
|
+
end
|
18
|
+
|
19
|
+
def range_compatible?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class SurroundAction < ElementAction
|
4
|
+
def source_element
|
5
|
+
@cloned_source_element ||= super.clone(1)
|
6
|
+
end
|
7
|
+
|
8
|
+
def original_placeholders
|
9
|
+
@original_placeholders ||= source_element.css("code:contains('render_original')")
|
10
|
+
raise(DefaceError, "The surround action couldn't find <%= render_original %> in your template") unless @original_placeholders.first
|
11
|
+
@original_placeholders
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Deface
|
2
|
+
module Actions
|
3
|
+
class SurroundContents < SurroundAction
|
4
|
+
def execute(target_range)
|
5
|
+
if target_range.length == 1
|
6
|
+
target_element = target_range.first
|
7
|
+
original_placeholders.each do |placeholder|
|
8
|
+
placeholder.replace target_element.clone(1).children
|
9
|
+
end
|
10
|
+
target_element.children.remove
|
11
|
+
target_element.add_child(source_element)
|
12
|
+
else
|
13
|
+
original_placeholders.each do |placeholder|
|
14
|
+
start = target_range[1].clone(1)
|
15
|
+
placeholder.replace start
|
16
|
+
|
17
|
+
target_range[2...-1].each do |element|
|
18
|
+
element = element.clone(1)
|
19
|
+
start.after(element)
|
20
|
+
start = element
|
21
|
+
end
|
22
|
+
end
|
23
|
+
target_range.first.after(source_element)
|
24
|
+
target_range[1...-1].map(&:remove)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def range_compatible?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/deface/applicator.rb
CHANGED
@@ -25,171 +25,18 @@ module Deface
|
|
25
25
|
end
|
26
26
|
|
27
27
|
override.parsed_document = doc
|
28
|
+
matches = override.matcher.matches(doc, log)
|
28
29
|
|
29
|
-
if
|
30
|
-
#
|
31
|
-
|
32
|
-
matches = doc.css(override.selector)
|
33
|
-
|
34
|
-
if log
|
35
|
-
Rails.logger.send(matches.size == 0 ? :error : :info, "\e[1;32mDeface:\e[0m '#{override.name}' matched #{matches.size} times with '#{override.selector}'")
|
36
|
-
end
|
37
|
-
|
38
|
-
matches.each do |match|
|
39
|
-
override.validate_original(match)
|
40
|
-
|
41
|
-
case override.action
|
42
|
-
when :remove
|
43
|
-
match.replace ""
|
44
|
-
when :replace
|
45
|
-
match.replace override.source_element
|
46
|
-
when :replace_contents
|
47
|
-
match.children.remove
|
48
|
-
match.add_child(override.source_element)
|
49
|
-
when :surround, :surround_contents
|
50
|
-
|
51
|
-
new_source = override.source_element.clone(1)
|
52
|
-
|
53
|
-
if original = new_source.css("code:contains('render_original')").first
|
54
|
-
if override.action == :surround
|
55
|
-
original.replace match.clone(1)
|
56
|
-
match.replace new_source
|
57
|
-
elsif override.action == :surround_contents
|
58
|
-
original.replace match.children
|
59
|
-
match.children.remove
|
60
|
-
match.add_child new_source
|
61
|
-
end
|
62
|
-
else
|
63
|
-
#maybe we should log that the original wasn't found.
|
64
|
-
end
|
65
|
-
|
66
|
-
when :insert_before
|
67
|
-
match.before override.source_element
|
68
|
-
when :insert_after
|
69
|
-
match.after override.source_element
|
70
|
-
when :insert_top
|
71
|
-
if match.children.size == 0
|
72
|
-
match.children = override.source_element
|
73
|
-
else
|
74
|
-
match.children.before(override.source_element)
|
75
|
-
end
|
76
|
-
when :insert_bottom
|
77
|
-
if match.children.size == 0
|
78
|
-
match.children = override.source_element
|
79
|
-
else
|
80
|
-
match.children.after(override.source_element)
|
81
|
-
end
|
82
|
-
when :set_attributes
|
83
|
-
override.attributes.each do |name, value|
|
84
|
-
name = normalize_attribute_name(name)
|
85
|
-
|
86
|
-
match.remove_attribute(name)
|
87
|
-
match.remove_attribute("data-erb-#{name}")
|
88
|
-
|
89
|
-
if match.attributes.key? name
|
90
|
-
match.set_attribute name, value.to_s
|
91
|
-
else
|
92
|
-
match.set_attribute "data-erb-#{name}", value.to_s
|
93
|
-
end
|
94
|
-
end
|
95
|
-
when :add_to_attributes
|
96
|
-
override.attributes.each do |name, value|
|
97
|
-
name = normalize_attribute_name(name)
|
98
|
-
|
99
|
-
if match.attributes.key? name
|
100
|
-
match.set_attribute name, match.attributes[name].value << " #{value}"
|
101
|
-
elsif match.attributes.key? "data-erb-#{name}"
|
102
|
-
match.set_attribute "data-erb-#{name}", match.attributes["data-erb-#{name}"].value << " #{value}"
|
103
|
-
else
|
104
|
-
match.set_attribute "data-erb-#{name}", value.to_s
|
105
|
-
end
|
106
|
-
|
107
|
-
end
|
108
|
-
when :remove_from_attributes
|
109
|
-
override.attributes.each do |name, value|
|
110
|
-
name = normalize_attribute_name(name)
|
111
|
-
|
112
|
-
if match.attributes.key? name
|
113
|
-
match.set_attribute name, match.attributes[name].value.gsub(value.to_s, '').strip
|
114
|
-
elsif match.attributes.key? "data-erb-#{name}"
|
115
|
-
match.set_attribute "data-erb-#{name}", match.attributes["data-erb-#{name}"].value.gsub(value.to_s, '').strip
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
end
|
122
|
-
else
|
123
|
-
unless [:remove, :replace, :replace_contents, :surround, :surround_contents].include? override.action
|
124
|
-
raise Deface::NotSupportedError, ":#{override.action} action does not support :closing_selector"
|
125
|
-
end
|
126
|
-
# targeting range of elements as end_selector is present
|
127
|
-
starting, ending = select_endpoints(doc, override.selector, override.end_selector)
|
128
|
-
|
129
|
-
if starting && ending
|
130
|
-
if log
|
131
|
-
Rails.logger.info("\e[1;32mDeface:\e[0m '#{override.name}' matched starting with '#{override.selector}' and ending with '#{override.end_selector}'")
|
132
|
-
end
|
133
|
-
|
134
|
-
elements = select_range(starting, ending)
|
135
|
-
|
136
|
-
case override.action
|
137
|
-
when :remove
|
138
|
-
elements.map &:remove
|
139
|
-
when :replace
|
140
|
-
starting.before(override.source_element)
|
141
|
-
elements.map &:remove
|
142
|
-
when :replace_contents
|
143
|
-
elements[1..-2].map &:remove
|
144
|
-
starting.after(override.source_element)
|
145
|
-
when :surround, :surround_contents
|
146
|
-
|
147
|
-
new_source = override.source_element.clone(1)
|
148
|
-
|
149
|
-
if original = new_source.css("code:contains('render_original')").first
|
150
|
-
|
151
|
-
if override.action == :surround
|
152
|
-
start = elements[0].clone(1)
|
153
|
-
original.replace start
|
154
|
-
|
155
|
-
elements[1..-1].each do |element|
|
156
|
-
element = element.clone(1)
|
157
|
-
start.after element
|
158
|
-
start = element
|
159
|
-
end
|
160
|
-
|
161
|
-
starting.before(new_source)
|
162
|
-
elements.map &:remove
|
163
|
-
|
164
|
-
|
165
|
-
elsif override.action == :surround_contents
|
166
|
-
|
167
|
-
start = elements[1].clone(1)
|
168
|
-
original.replace start
|
169
|
-
|
170
|
-
elements[2...-1].each do |element|
|
171
|
-
element = element.clone(1)
|
172
|
-
start.after element
|
173
|
-
start = element
|
174
|
-
end
|
175
|
-
|
176
|
-
starting.after(new_source)
|
177
|
-
elements[1...-1].map &:remove
|
178
|
-
end
|
179
|
-
else
|
180
|
-
#maybe we should log that the original wasn't found.
|
181
|
-
end
|
182
|
-
end
|
183
|
-
else
|
184
|
-
if starting.nil?
|
185
|
-
Rails.logger.info("\e[1;32mDeface:\e[0m '#{override.name}' failed to match with starting selector '#{override.selector}'")
|
186
|
-
else
|
187
|
-
Rails.logger.info("\e[1;32mDeface:\e[0m '#{override.name}' failed to match with end selector '#{override.end_selector}'")
|
188
|
-
end
|
189
|
-
|
190
|
-
end
|
30
|
+
if log
|
31
|
+
Rails.logger.send(matches.size == 0 ? :error : :info, "\e[1;32mDeface:\e[0m '#{override.name}' matched #{matches.size} times with '#{override.selector}'")
|
191
32
|
end
|
192
33
|
|
34
|
+
if matches.empty?
|
35
|
+
override.failure = "failed to match :#{override.action} selector '#{override.selector}'"
|
36
|
+
else
|
37
|
+
override.failure = nil
|
38
|
+
matches.each {|match| override.execute_action match }
|
39
|
+
end
|
193
40
|
end
|
194
41
|
|
195
42
|
#prevents any caching by rails in development mode
|
@@ -202,41 +49,38 @@ module Deface
|
|
202
49
|
|
203
50
|
source
|
204
51
|
end
|
52
|
+
end
|
205
53
|
|
54
|
+
def execute_action(target_element)
|
55
|
+
validate_original(target_element)
|
56
|
+
create_action_command.execute(target_element)
|
57
|
+
end
|
206
58
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
finish = "#{start} ~ #{finish}"
|
211
|
-
starting = doc.css(start).first
|
212
|
-
|
213
|
-
ending = if starting && starting.parent
|
214
|
-
starting.parent.css(finish).first
|
215
|
-
else
|
216
|
-
doc.css(finish).first
|
217
|
-
end
|
218
|
-
|
219
|
-
return starting, ending
|
220
|
-
|
221
|
-
end
|
222
|
-
|
223
|
-
# finds all elements upto closing sibling in nokgiri document
|
224
|
-
#
|
225
|
-
def select_range(first, last)
|
226
|
-
first == last ? [first] : [first, *select_range(first.next, last)]
|
227
|
-
end
|
228
|
-
|
229
|
-
private
|
59
|
+
def execute_action_on_range(target_range)
|
60
|
+
create_action_command.execute_on_range(target_range)
|
61
|
+
end
|
230
62
|
|
231
|
-
|
232
|
-
|
63
|
+
def create_action_command
|
64
|
+
commands = Rails.application.config.deface.actions
|
65
|
+
command = commands.find { |command| command.to_sym == action }
|
66
|
+
raise(DefaceError, "Action #{action} not found") unless command
|
67
|
+
command.new(:source_element => safe_source_element, :attributes => attributes)
|
68
|
+
end
|
233
69
|
|
234
|
-
|
235
|
-
|
236
|
-
|
70
|
+
def compatible_with_end_selector?
|
71
|
+
create_action_command.range_compatible?
|
72
|
+
end
|
237
73
|
|
238
|
-
|
74
|
+
def matcher
|
75
|
+
if end_selector.blank?
|
76
|
+
Deface::Matchers::Element.new(selector) # single css selector
|
77
|
+
else
|
78
|
+
unless compatible_with_end_selector?
|
79
|
+
raise Deface::NotSupportedError, ":#{action} action does not support :closing_selector"
|
239
80
|
end
|
81
|
+
# targeting range of elements as end_selector is present
|
82
|
+
Deface::Matchers::Range.new(name, selector, end_selector)
|
83
|
+
end
|
240
84
|
end
|
241
85
|
end
|
242
86
|
end
|