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.
Files changed (63) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +1 -0
  4. data/README.markdown +139 -59
  5. data/deface.gemspec +4 -2
  6. data/gemfiles/haml3_2.gemfile +5 -0
  7. data/lib/deface.rb +28 -1
  8. data/lib/deface/action_view_extensions.rb +7 -1
  9. data/lib/deface/actions/action.rb +19 -0
  10. data/lib/deface/actions/add_to_attributes.rb +15 -0
  11. data/lib/deface/actions/attribute_action.rb +33 -0
  12. data/lib/deface/actions/element_action.rb +13 -0
  13. data/lib/deface/actions/insert_after.rb +9 -0
  14. data/lib/deface/actions/insert_before.rb +9 -0
  15. data/lib/deface/actions/insert_bottom.rb +14 -0
  16. data/lib/deface/actions/insert_top.rb +14 -0
  17. data/lib/deface/actions/remove.rb +13 -0
  18. data/lib/deface/actions/remove_from_attributes.rb +13 -0
  19. data/lib/deface/actions/replace.rb +14 -0
  20. data/lib/deface/actions/replace_contents.rb +19 -0
  21. data/lib/deface/actions/set_attributes.rb +12 -0
  22. data/lib/deface/actions/surround.rb +24 -0
  23. data/lib/deface/actions/surround_action.rb +15 -0
  24. data/lib/deface/actions/surround_contents.rb +33 -0
  25. data/lib/deface/applicator.rb +35 -191
  26. data/lib/deface/dsl/context.rb +7 -3
  27. data/lib/deface/dsl/loader.rb +5 -2
  28. data/lib/deface/environment.rb +31 -1
  29. data/lib/deface/haml_converter.rb +33 -5
  30. data/lib/deface/matchers/element.rb +13 -0
  31. data/lib/deface/matchers/range.rb +52 -0
  32. data/lib/deface/override.rb +28 -57
  33. data/lib/deface/sources/copy.rb +15 -0
  34. data/lib/deface/sources/cut.rb +25 -0
  35. data/lib/deface/sources/erb.rb +9 -0
  36. data/lib/deface/sources/haml.rb +14 -0
  37. data/lib/deface/sources/partial.rb +13 -0
  38. data/lib/deface/sources/source.rb +11 -0
  39. data/lib/deface/sources/template.rb +13 -0
  40. data/lib/deface/sources/text.rb +9 -0
  41. data/lib/deface/utils/failure_finder.rb +41 -0
  42. data/spec/deface/action_view_template_spec.rb +28 -2
  43. data/spec/deface/actions/add_to_attributes_spec.rb +62 -0
  44. data/spec/deface/actions/insert_after_spec.rb +19 -0
  45. data/spec/deface/actions/insert_before_spec.rb +19 -0
  46. data/spec/deface/actions/insert_bottom_spec.rb +28 -0
  47. data/spec/deface/actions/insert_top_spec.rb +28 -0
  48. data/spec/deface/actions/remove_from_attributes_spec.rb +81 -0
  49. data/spec/deface/actions/remove_spec.rb +30 -0
  50. data/spec/deface/actions/replace_contents_spec.rb +29 -0
  51. data/spec/deface/actions/replace_spec.rb +52 -0
  52. data/spec/deface/actions/set_attributes_spec.rb +62 -0
  53. data/spec/deface/actions/surround_contents_spec.rb +57 -0
  54. data/spec/deface/actions/surround_spec.rb +57 -0
  55. data/spec/deface/applicator_spec.rb +0 -354
  56. data/spec/deface/dsl/context_spec.rb +14 -7
  57. data/spec/deface/dsl/loader_spec.rb +12 -4
  58. data/spec/deface/override_spec.rb +26 -3
  59. data/spec/deface/template_helper_spec.rb +11 -0
  60. data/spec/deface/utils/failure_finder_spec.rb +76 -0
  61. data/spec/spec_helper.rb +21 -2
  62. data/tasks/utils.rake +24 -0
  63. metadata +91 -14
@@ -19,7 +19,7 @@ module Deface
19
19
  @virtual_path = name
20
20
  end
21
21
 
22
- Deface::Override.actions.each do |action_name|
22
+ def self.define_action_method(action_name)
23
23
  define_method(action_name) do |selector|
24
24
  if @action.present?
25
25
  Rails.logger.error "\e[1;32mDeface: [WARNING]\e[0m Multiple action methods have been called. The last one will be used."
@@ -29,7 +29,7 @@ module Deface
29
29
  end
30
30
  end
31
31
 
32
- Deface::Override.sources.each do |source_name|
32
+ def self.define_source_method(source_name)
33
33
  define_method(source_name) do |value|
34
34
  if @source.present?
35
35
  Rails.logger.error "\e[1;32mDeface: [WARNING]\e[0m Multiple source methods have been called. The last one will be used."
@@ -62,6 +62,10 @@ module Deface
62
62
  def disabled
63
63
  @options[:disabled] = true
64
64
  end
65
+
66
+ def namespaced
67
+ @options[:namespaced] = true
68
+ end
65
69
  end
66
70
  end
67
- end
71
+ end
@@ -36,7 +36,7 @@ module Deface
36
36
  context.virtual_path(determine_virtual_path(filename))
37
37
  context.instance_eval(dsl_commands)
38
38
  context.haml(the_rest)
39
- context.create_override
39
+ context.create_override
40
40
  else
41
41
  context = Context.new(context_name)
42
42
  context.virtual_path(determine_virtual_path(filename))
@@ -61,7 +61,10 @@ module Deface
61
61
  comment = html_file_contents[first_open_comment_index..first_close_comment_index+2]
62
62
  end
63
63
 
64
- dsl_commands << comment.gsub('<!--', '').gsub('-->', '').strip + "\n"
64
+ comment.gsub('<!--', '').gsub('-->', '').strip.scan(/[^\s"']+|"[^"]*"|'[^']*'/).each do |part|
65
+ dsl_commands =~ /('|")\z/ || part =~ /\w\z/ ? dsl_commands << "\n" : dsl_commands << ' '
66
+ dsl_commands << part
67
+ end
65
68
 
66
69
  html_file_contents = html_file_contents.gsub(comment, '')
67
70
  end
@@ -1,12 +1,42 @@
1
1
  module Deface
2
+ DEFAULT_ACTIONS = [ Actions::Remove, Actions::Replace, Actions::ReplaceContents, Actions::Surround,
3
+ Actions::SurroundContents, Actions::InsertBefore, Actions::InsertAfter, Actions::InsertTop,
4
+ Actions::InsertBottom, Actions::SetAttributes, Actions::AddToAttributes, Actions::RemoveFromAttributes ]
5
+
6
+ DEFAULT_SOURCES = [ Sources::Text, Sources::Erb, Sources::Haml, Sources::Partial, Sources::Template, Sources::Cut, Sources::Copy]
2
7
 
3
8
  class Environment
4
- attr_accessor :overrides, :enabled, :haml_support
9
+ attr_accessor :overrides, :enabled, :haml_support, :namespaced
5
10
  def initialize
6
11
  @overrides = Overrides.new
7
12
  @enabled = true
8
13
  @haml_support = false
14
+ @actions = []
15
+ @sources = []
16
+ @namespaced = false
17
+
18
+ Deface::DEFAULT_ACTIONS.each { |action| register_action(action) }
19
+ Deface::DEFAULT_SOURCES.each { |source| register_source(source) }
20
+ end
21
+
22
+ def register_action(action)
23
+ @actions << action
24
+ Deface::DSL::Context.define_action_method(action.to_sym)
25
+ end
26
+
27
+ def actions
28
+ @actions.dup
9
29
  end
30
+
31
+ def register_source(source)
32
+ @sources << source
33
+ Deface::DSL::Context.define_source_method(source.to_sym)
34
+ end
35
+
36
+ def sources
37
+ @sources.dup
38
+ end
39
+
10
40
  end
11
41
 
12
42
  class Environment::Overrides
@@ -1,9 +1,6 @@
1
1
  module Deface
2
- class HamlConverter < Haml::Engine
3
- def result
4
- Deface::Parser.undo_erb_markup! String.new(render)
5
- end
6
2
 
3
+ module HamlCompilerMethods
7
4
  def push_script(text, preserve_script, in_tag = false, preserve_tag = false,
8
5
  escape_html = false, nuke_inner_whitespace = false)
9
6
  push_text "<%= #{text.strip} %>"
@@ -17,7 +14,9 @@ module Deface
17
14
  def push_silent(text, can_suppress = false)
18
15
  push_text "<% #{text.strip} %>"
19
16
  end
17
+ end
20
18
 
19
+ module HamlParserMethods
21
20
  def parse_old_attributes(line)
22
21
  attributes_hash, rest, last_line = super(line)
23
22
 
@@ -34,7 +33,6 @@ module Deface
34
33
 
35
34
  return attributes, rest, last_line
36
35
  end
37
-
38
36
  private
39
37
 
40
38
  # coverts { attributes into deface compatibily attributes
@@ -72,6 +70,36 @@ module Deface
72
70
 
73
71
  attrs.join(', ')
74
72
  end
73
+ end
75
74
 
75
+ class HamlConverter < Haml::Engine
76
+
77
+ # spec coverage will always be bad on one-side
78
+ # or the other of this if, travis-ci gemfile takes
79
+ # care of 3.2 haml side for now (until 3.2 is relased)
80
+ # then we should reverse to test 3.1 with gemfile
81
+ #
82
+ if Haml::VERSION >= "3.2"
83
+ class Compiler < Haml::Compiler
84
+ include HamlCompilerMethods
85
+ end
86
+
87
+ class Parser < Haml::Parser
88
+ include HamlParserMethods
89
+ end
90
+
91
+ def initialize(template, options = {})
92
+ options[:compiler_class] = Compiler
93
+ options[:parser_class] = Parser
94
+ super(template, options)
95
+ end
96
+ else
97
+ include HamlParserMethods
98
+ include HamlCompilerMethods
99
+ end
100
+
101
+ def result
102
+ Deface::Parser.undo_erb_markup! String.new(render)
103
+ end
76
104
  end
77
105
  end
@@ -0,0 +1,13 @@
1
+ module Deface
2
+ module Matchers
3
+ class Element
4
+ def initialize(selector)
5
+ @selector = selector
6
+ end
7
+
8
+ def matches(document, log=true)
9
+ document.css(@selector).map { |match| [match] }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,52 @@
1
+ module Deface
2
+ module Matchers
3
+ class Range
4
+ def initialize(name, selector, end_selector)
5
+ @name = name
6
+ @selector = selector
7
+ @end_selector = end_selector
8
+ end
9
+
10
+ def matches(document, log=true)
11
+ starting, ending = select_endpoints(document, @selector, @end_selector)
12
+
13
+ if starting && ending
14
+ if log
15
+ Rails.logger.info("\e[1;32mDeface:\e[0m '#{@name}' matched starting with '#{@selector}' and ending with '#{@end_selector}'")
16
+ end
17
+
18
+ return [select_range(starting, ending)]
19
+ else
20
+ if starting.nil?
21
+ Rails.logger.info("\e[1;32mDeface:\e[0m '#{@name}' failed to match with starting selector '#{@selector}'")
22
+ else
23
+ Rails.logger.info("\e[1;32mDeface:\e[0m '#{@name}' failed to match with end selector '#{@end_selector}'")
24
+ end
25
+ return []
26
+ end
27
+ end
28
+
29
+ def select_endpoints(doc, start, finish)
30
+ # targeting range of elements as end_selector is present
31
+ #
32
+ finish = "#{start} ~ #{finish}"
33
+ starting = doc.css(start).first
34
+
35
+ ending = if starting && starting.parent
36
+ starting.parent.css(finish).first
37
+ else
38
+ doc.css(finish).first
39
+ end
40
+
41
+ return starting, ending
42
+
43
+ end
44
+
45
+ # finds all elements upto closing sibling in nokgiri document
46
+ #
47
+ def select_range(first, last)
48
+ first == last ? [first] : [first, *select_range(first.next, last)]
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,16 +1,14 @@
1
1
  module Deface
2
2
  class Override
3
- include TemplateHelper
4
3
  include OriginalValidator
4
+ include Applicator
5
5
  extend Applicator::ClassMethods
6
6
  extend Search::ClassMethods
7
7
 
8
- cattr_accessor :actions, :sources, :_early, :current_railtie
9
- attr_accessor :args, :parsed_document
8
+ cattr_accessor :_early, :current_railtie
9
+ attr_accessor :args, :parsed_document, :failure
10
10
 
11
11
  @@_early = []
12
- @@actions = [:remove, :replace, :replace_contents, :surround, :surround_contents, :insert_after, :insert_before, :insert_top, :insert_bottom, :set_attributes, :add_to_attributes, :remove_from_attributes]
13
- @@sources = [:text, :erb, :haml, :partial, :template, :cut, :copy]
14
12
 
15
13
  # Initializes new override, you must supply only one Target, Action & Source
16
14
  # parameter for each override (and any number of Optional parameters).
@@ -32,6 +30,7 @@ module Deface
32
30
  raise(ArgumentError, ":virtual_path must be defined") if args[:virtual_path].blank?
33
31
 
34
32
  args[:text] = content.call if block_given?
33
+ args[:name] = "#{current_railtie.underscore}_#{args[:name]}" if Rails.application.try(:config).try(:deface).try(:namespaced) || args.delete(:namespaced)
35
34
 
36
35
  virtual_key = args[:virtual_path].to_sym
37
36
  name_key = args[:name].to_s.parameterize
@@ -44,13 +43,13 @@ module Deface
44
43
  @args = self.class.all[virtual_key][name_key].args
45
44
 
46
45
  #check if the action is being redefined, and reject old action
47
- if (@@actions & args.keys).present?
48
- @args.reject!{|key, value| (@@actions & @args.keys).include? key }
46
+ if (self.class.actions & args.keys).present?
47
+ @args.reject!{|key, value| (self.class.actions & @args.keys).include? key }
49
48
  end
50
49
 
51
50
  #check if the source is being redefined, and reject old action
52
- if (@@sources & args.keys).present?
53
- @args.reject!{|key, value| (@@sources & @args.keys).include? key }
51
+ if (Deface::DEFAULT_SOURCES.map(&:to_sym) & args.keys).present?
52
+ @args.reject!{|key, value| (Deface::DEFAULT_SOURCES.map(&:to_sym) & @args.keys).include? key }
54
53
  end
55
54
 
56
55
  @args.merge!(args)
@@ -122,69 +121,34 @@ module Deface
122
121
  end
123
122
 
124
123
  def action
125
- (@@actions & @args.keys).first
124
+ (self.class.actions & @args.keys).first
126
125
  end
127
126
 
127
+ # Returns the markup to be inserted / used
128
+ #
128
129
  def source
129
- erb = case source_argument
130
- when :partial
131
- load_template_source(@args[:partial], true)
132
- when :template
133
- load_template_source(@args[:template], false)
134
- when :text
135
- @args[:text]
136
- when :erb
137
- @args[:erb]
138
- when :cut
139
- cut = @args[:cut]
140
-
141
- if cut.is_a? Hash
142
- starting, ending = self.class.select_endpoints(self.parsed_document, cut[:start], cut[:end])
143
-
144
- range = self.class.select_range(starting, ending)
145
- range.map &:remove
146
-
147
- Deface::Parser.undo_erb_markup! range.map(&:to_s).join
148
-
149
- else
150
- Deface::Parser.undo_erb_markup! self.parsed_document.css(cut).first.remove.to_s.clone
151
- end
152
-
153
- when :copy
154
- copy = @args[:copy]
155
-
156
- if copy.is_a? Hash
157
- starting, ending = self.class.select_endpoints(self.parsed_document, copy[:start], copy[:end])
158
-
159
- range = self.class.select_range(starting, ending)
160
-
161
- Deface::Parser.undo_erb_markup! range.map(&:to_s).join
162
- else
163
- Deface::Parser.undo_erb_markup! parsed_document.css(copy).first.to_s.clone
164
- end
130
+ sources = Rails.application.config.deface.sources
131
+ source = sources.find { |source| source.to_sym == source_argument }
132
+ raise(DefaceError, "Source #{source} not found.") unless source
165
133
 
166
- when :haml
167
- if Rails.application.config.deface.haml_support
168
- haml_engine = Deface::HamlConverter.new(@args[:haml])
169
- haml_engine.render
170
- else
171
- raise Deface::NotSupportedError, "`#{self.name}` supplies :haml source, but haml_support is not detected."
172
- end
173
- end
174
-
175
- erb
134
+ source.execute(self) || ''
176
135
  end
177
136
 
178
137
  # Returns a :symbol for the source argument present
179
138
  #
180
139
  def source_argument
181
- @@sources.detect { |source| @args.key? source }
140
+ Deface::DEFAULT_SOURCES.detect { |source| @args.key? source.to_sym }.try :to_sym
182
141
  end
183
142
 
184
143
  def source_element
185
144
  Deface::Parser.convert(source.clone)
186
145
  end
187
146
 
147
+ def safe_source_element
148
+ return unless source_argument
149
+ source_element
150
+ end
151
+
188
152
  def disabled?
189
153
  @args.key?(:disabled) ? @args[:disabled] : false
190
154
  end
@@ -194,6 +158,8 @@ module Deface
194
158
  @args[:closing_selector]
195
159
  end
196
160
 
161
+ # returns attributes hash for attribute related actions
162
+ #
197
163
  def attributes
198
164
  @args[:attributes] || []
199
165
  end
@@ -227,6 +193,11 @@ module Deface
227
193
  Rails.application.config.deface.overrides.all
228
194
  end
229
195
 
196
+ def self.actions
197
+ Rails.application.config.deface.actions.map &:to_sym
198
+ end
199
+
200
+
230
201
  private
231
202
 
232
203
  # check if method is compiled for the current virtual path
@@ -0,0 +1,15 @@
1
+ module Deface
2
+ module Sources
3
+ class Copy < Source
4
+ def self.execute(override)
5
+ copy = override.args[:copy]
6
+ if copy.is_a? Hash
7
+ range = Deface::Matchers::Range.new('Copy', copy[:start], copy[:end]).matches(override.parsed_document).first
8
+ Deface::Parser.undo_erb_markup! range.map(&:to_s).join
9
+ else
10
+ Deface::Parser.undo_erb_markup! override.parsed_document.css(copy).first.to_s.clone
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ module Deface
2
+ module Sources
3
+ class Cut < Source
4
+ def self.execute(override)
5
+ cut = override.args[:cut]
6
+ if cut.is_a? Hash
7
+ range = Deface::Matchers::Range.new('Cut', cut[:start], cut[:end]).matches(override.parsed_document).first
8
+ range.map &:remove
9
+
10
+ Deface::Parser.undo_erb_markup! range.map(&:to_s).join
11
+
12
+ else
13
+ element = override.parsed_document.css(cut).first
14
+
15
+ if element.nil?
16
+ override.failure = "failed to match :cut selector '#{cut}'"
17
+ nil
18
+ else
19
+ Deface::Parser.undo_erb_markup! element.remove.to_s.clone
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ module Deface
2
+ module Sources
3
+ class Erb < Source
4
+ def self.execute(override)
5
+ override.args[:erb]
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module Deface
2
+ module Sources
3
+ class Haml < Source
4
+ def self.execute(override)
5
+ if Rails.application.config.deface.haml_support
6
+ haml_engine = Deface::HamlConverter.new(override.args[:haml])
7
+ haml_engine.render
8
+ else
9
+ raise Deface::NotSupportedError, "`#{override.name}` supplies :haml source, but haml_support is not detected."
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Deface
2
+ module Sources
3
+ class Partial < Source
4
+ class << self
5
+ include TemplateHelper
6
+ end
7
+
8
+ def self.execute(override)
9
+ load_template_source(override.args[:partial], true)
10
+ end
11
+ end
12
+ end
13
+ end