deface 1.0.0.rc2 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,16 +1,12 @@
1
1
  script: "bundle exec rake"
2
2
  rvm:
3
- - 1.8.7
4
- - 1.9.2
5
3
  - 1.9.3
6
4
  - 2.0.0
7
- - jruby-18mode
8
- - jruby-19mode
9
5
  gemfile:
10
6
  - gemfiles/rails3_1.gemfile
11
7
  - gemfiles/rails3_2.gemfile
8
+ - gemfiles/rails4_0.gemfile
12
9
  - gemfiles/haml4_0.gemfile
13
-
14
10
  notifications:
15
11
  email:
16
12
  - brian@spreecommerce.com
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gemspec
3
+ gem 'rails', ENV['RAILS'] || '~> 3.2.13'
4
4
 
5
+ gemspec
data/README.markdown CHANGED
@@ -7,7 +7,7 @@
7
7
  Deface
8
8
  ======
9
9
 
10
- Deface is a library that allows you to customize HTML (ERB and HAML) views in a Rails application without editing the underlying view.
10
+ Deface is a library that allows you to customize HTML (ERB, Haml and Slim) views in a Rails application without editing the underlying view.
11
11
 
12
12
  It allows you to easily target html & erb elements as the hooks for customization using CSS selectors as supported by Nokogiri.
13
13
 
@@ -59,7 +59,7 @@ You should save your overrides in the ````app/overrides````, normally one overri
59
59
 
60
60
  * <tt>:insert_bottom</tt> - Inserts inside all elements that match the supplied selector, as the last child.
61
61
 
62
- * <tt>:set_</tt> - Sets attributes on all elements that match the supplied selector, replacing existing attribute value if present or adding if not. Expects :attributes option to be passed.
62
+ * <tt>:set_attributes</tt> - Sets attributes on all elements that match the supplied selector, replacing existing attribute value if present or adding if not. Expects :attributes option to be passed.
63
63
 
64
64
  * <tt>:add_to_attributes</tt> - Appends value to attributes on all elements that match the supplied selector, adds attribute if not present. Expects :attributes option to be passed.
65
65
 
data/deface.gemspec CHANGED
@@ -1,26 +1,27 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "deface"
3
- s.version = "1.0.0.rc2"
3
+ s.version = "1.0.0.rc3"
4
4
 
5
5
  s.authors = ["Brian D Quinn"]
6
- s.description = "Deface is a library that allows you to customize ERB & HAML views in a Rails application without editing the underlying view."
6
+ s.description = "Deface is a library that allows you to customize ERB, Haml and Slim views in a Rails application without editing the underlying view."
7
7
  s.email = "brian@spreecommerce.com"
8
8
  s.extra_rdoc_files = [
9
9
  "README.markdown"
10
10
  ]
11
11
  s.files = `git ls-files`.split("\n")
12
12
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
- s.homepage = "http://github.com/railsdog/deface"
13
+ s.homepage = "https://github.com/spree/deface"
14
14
  s.rdoc_options = ["--charset=UTF-8"]
15
15
  s.require_paths = ["lib"]
16
- s.summary = "Deface is a library that allows you to customize ERB & HAML views in Rails"
16
+ s.summary = "Deface is a library that allows you to customize ERB, Haml and Slim views in Rails"
17
17
 
18
- s.add_dependency('nokogiri', '~> 1.5.9')
19
- s.add_dependency('rails', '~> 3.1')
18
+ s.add_dependency('nokogiri', '~> 1.6.0')
19
+ s.add_dependency('rails', '>= 3.1')
20
20
  s.add_dependency('colorize', '>= 0.5.8')
21
21
 
22
22
  s.add_development_dependency('rspec', '>= 2.11.0')
23
23
  s.add_development_dependency('haml', '>= 3.1.4')
24
+ s.add_development_dependency('slim', '>= 2.0.0')
24
25
  s.add_development_dependency('simplecov', '>= 0.6.4')
25
26
  s.add_development_dependency('generator_spec', '~> 0.8.5')
26
27
  end
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "rails", "~> 4.0.0.rc1"
4
+
5
+ gemspec :path => "../"
data/lib/deface.rb CHANGED
@@ -11,6 +11,7 @@ require "deface/sources/source"
11
11
  require "deface/sources/text"
12
12
  require "deface/sources/erb"
13
13
  require "deface/sources/haml"
14
+ require "deface/sources/slim"
14
15
  require "deface/sources/partial"
15
16
  require "deface/sources/template"
16
17
  require "deface/sources/copy"
@@ -46,5 +47,5 @@ module Deface
46
47
  class DefaceError < StandardError; end
47
48
 
48
49
  class NotSupportedError < DefaceError; end
49
-
50
+
50
51
  end
@@ -2,12 +2,16 @@ ActionView::Template.class_eval do
2
2
  alias_method :initialize_without_deface, :initialize
3
3
 
4
4
  def initialize(source, identifier, handler, details)
5
- if Rails.application.config.deface.enabled && should_be_defaced?(handler)
6
- haml = handler.to_s == "Haml::Plugin"
5
+ syntax = determine_syntax(handler)
7
6
 
8
- processed_source = Deface::Override.apply(source, details, true, haml )
7
+ if Rails.application.config.deface.enabled && should_be_defaced?(syntax)
9
8
 
10
- if haml && processed_source != source
9
+ processed_source = Deface::Override.apply(source, details, true, syntax)
10
+
11
+ # force change in handler before continuing to original Rails method
12
+ # as we've just converted some other template language into ERB!
13
+ #
14
+ if [:slim, :haml].include?(syntax) && processed_source != source
11
15
  handler = ActionView::Template::Handlers::ERB
12
16
  end
13
17
  else
@@ -53,8 +57,20 @@ ActionView::Template.class_eval do
53
57
 
54
58
  private
55
59
 
56
- def should_be_defaced?(handler)
57
- handler.to_s.demodulize == "ERB" || handler.class.to_s.demodulize == "ERB" || handler.to_s == "Haml::Plugin"
60
+ def should_be_defaced?(syntax)
61
+ syntax != :unknown
62
+ end
63
+
64
+ def determine_syntax(handler)
65
+ if handler.to_s == "Haml::Plugin"
66
+ :haml
67
+ elsif handler.class.to_s == "Slim::RailsTemplate"
68
+ :slim
69
+ elsif handler.to_s.demodulize == "ERB" || handler.class.to_s.demodulize == "ERB"
70
+ :erb
71
+ else
72
+ :unknown
73
+ end
58
74
  end
59
75
  end
60
76
 
@@ -3,7 +3,7 @@ module Deface
3
3
  module ClassMethods
4
4
  # applies all applicable overrides to given source
5
5
  #
6
- def apply(source, details, log=true, haml=false)
6
+ def apply(source, details, log=true, syntax=:erb)
7
7
  overrides = find(details)
8
8
 
9
9
  if log && overrides.size > 0
@@ -11,9 +11,12 @@ module Deface
11
11
  end
12
12
 
13
13
  unless overrides.empty?
14
- if haml
14
+ case syntax
15
+ when :haml
15
16
  #convert haml to erb before parsing before
16
17
  source = Deface::HamlConverter.new(source).result
18
+ when :slim
19
+ source = Slim::ERBConverter.new.call(source)
17
20
  end
18
21
 
19
22
  doc = Deface::Parser.convert(source)
@@ -6,8 +6,8 @@ module Deface
6
6
  module DSL
7
7
  class Loader
8
8
  def self.load(filename, options = nil, &block)
9
- unless File.basename(filename) =~ /^[^\.]+(.html.(erb|haml)){0,1}.deface$/
10
- raise "Deface::DSL does not know how to read '#{filename}'. Override files should end with just .deface, .html.erb.deface, or .html.haml.deface"
9
+ unless File.basename(filename) =~ /^[^\.]+(.html.(erb|haml|slim)){0,1}.deface$/
10
+ raise "Deface::DSL does not know how to read '#{filename}'. Override files should end with just .deface, .html.erb.deface, .html.haml.deface or .html.slim.deface"
11
11
  end
12
12
 
13
13
  unless file_in_dir_below_overrides?(filename)
@@ -37,6 +37,15 @@ module Deface
37
37
  context.instance_eval(dsl_commands)
38
38
  context.haml(the_rest)
39
39
  context.create_override
40
+ elsif context_name.end_with?('.html.slim')
41
+ dsl_commands, the_rest = extract_dsl_commands_from_slim(file_contents)
42
+
43
+ context_name = context_name.gsub('.html.slim', '')
44
+ context = Context.new(context_name)
45
+ context.virtual_path(determine_virtual_path(filename))
46
+ context.instance_eval(dsl_commands)
47
+ context.slim(the_rest)
48
+ context.create_override
40
49
  else
41
50
  context = Context.new(context_name)
42
51
  context.virtual_path(determine_virtual_path(filename))
@@ -99,7 +108,12 @@ module Deface
99
108
  [dsl_commands, file_contents]
100
109
  end
101
110
 
102
- private
111
+ class << self
112
+ alias_method :extract_dsl_commands_from_slim, :extract_dsl_commands_from_haml
113
+ end
114
+
115
+
116
+ private
103
117
 
104
118
  def self.starts_with_html_comment?(line)
105
119
  line.lstrip.index('<!--') == 0
@@ -126,4 +140,4 @@ module Deface
126
140
  end
127
141
  end
128
142
  end
129
- end
143
+ end
@@ -3,14 +3,15 @@ module Deface
3
3
  Actions::SurroundContents, Actions::InsertBefore, Actions::InsertAfter, Actions::InsertTop,
4
4
  Actions::InsertBottom, Actions::SetAttributes, Actions::AddToAttributes, Actions::RemoveFromAttributes ]
5
5
 
6
- DEFAULT_SOURCES = [ Sources::Text, Sources::Erb, Sources::Haml, Sources::Partial, Sources::Template, Sources::Cut, Sources::Copy]
6
+ DEFAULT_SOURCES = [ Sources::Text, Sources::Erb, Sources::Haml, Sources::Slim, Sources::Partial, Sources::Template, Sources::Cut, Sources::Copy]
7
7
 
8
8
  class Environment
9
- attr_accessor :overrides, :enabled, :haml_support, :namespaced
9
+ attr_accessor :overrides, :enabled, :haml_support, :namespaced, :slim_support
10
10
  def initialize
11
11
  @overrides = Overrides.new
12
12
  @enabled = true
13
13
  @haml_support = false
14
+ @slim_support = false
14
15
  @actions = []
15
16
  @sources = []
16
17
  @namespaced = false
@@ -51,16 +52,21 @@ module Deface
51
52
  end
52
53
 
53
54
  def load_all(app)
54
- #clear overrides before reloading them
55
+ # clear overrides before reloading them
55
56
  app.config.deface.overrides.all.clear
56
57
  Deface::DSL::Loader.register
57
58
 
58
59
  # check all railties / engines / extensions / application for overrides
59
- app.railties.all.dup.push(app).each do |railtie|
60
+ railties = if Rails.version >= "4.0"
61
+ app.railties._all
62
+ else
63
+ app.railties.all
64
+ end
65
+
66
+ railties.dup.push(app).each do |railtie|
60
67
  next unless railtie.respond_to? :root
61
68
  load_overrides(railtie)
62
69
  end
63
-
64
70
  end
65
71
 
66
72
  def early_check
data/lib/deface/parser.rb CHANGED
@@ -71,23 +71,29 @@ module Deface
71
71
  source.gsub!("#{match[0]}#{match[1]}#{match[2]}") { |m| m = "#{match[0]}#{ CGI.unescapeHTML match[1] }#{match[2]}" }
72
72
  end
73
73
 
74
+ if RUBY_PLATFORM == 'java'
75
+ #un-escapes changes from Nokogiri under Java, where " are converted to %22 when in an attribute of an element
76
+ #
77
+ source.scan(/(<%.*?)((?:(?!%>)[\s\S])*)(%>)/).each do |match|
78
+ source.gsub!("#{match[0]}#{match[1]}#{match[2]}") { |m| m = "#{match[0]}#{ match[1].gsub('%22', '"') }#{match[2]}" }
79
+ end
80
+ end
81
+
74
82
  source
75
83
  end
76
84
 
77
85
  def self.convert(source)
78
- if source.encoding_aware?
79
- # Look for # encoding: *. If we find one, we'll encode the
80
- # String in that encoding, otherwise, we'll use the
81
- # default external encoding.
82
- encoding = source.scan(/#{ActionView::Template::Handlers::ERB.const_get(:ENCODING_TAG)}/).first.try(:last) || Encoding.default_external
83
-
84
- # Tag the source with the default external encoding
85
- # or the encoding specified in the file
86
- source.force_encoding(encoding)
87
-
88
- unless source.valid_encoding?
89
- raise ActionView::WrongEncodingError.new(source, encoding)
90
- end
86
+ # Look for # encoding: *. If we find one, we'll encode the
87
+ # String in that encoding, otherwise, we'll use the
88
+ # default external encoding.
89
+ encoding = source.scan(/#{ActionView::Template::Handlers::ERB.const_get(:ENCODING_TAG)}/).first.try(:last) || Encoding.default_external
90
+
91
+ # Tag the source with the default external encoding
92
+ # or the encoding specified in the file
93
+ source.force_encoding(encoding)
94
+
95
+ unless source.valid_encoding?
96
+ raise ActionView::WrongEncodingError.new(source, encoding)
91
97
  end
92
98
 
93
99
  erb_markup!(source)
@@ -100,6 +106,5 @@ module Deface
100
106
  Nokogiri::HTML::DocumentFragment.parse(source)
101
107
  end
102
108
  end
103
-
104
109
  end
105
110
  end
@@ -39,9 +39,14 @@ module Deface
39
39
  app.config.eager_load_paths.reject! {|path| path =~ /app\/overrides\z/ }
40
40
 
41
41
  # railites / engines / extensions
42
- app.railties.all.each do |railtie|
43
- next unless railtie.respond_to? :root
42
+ railties = if Rails.version >= "4.0"
43
+ app.railties._all
44
+ else
45
+ app.railties.all
46
+ end
44
47
 
48
+ railties.each do |railtie|
49
+ next unless railtie.respond_to? :root
45
50
  railtie.config.eager_load_paths.reject! {|path| path =~ /app\/overrides\z/ }
46
51
  end
47
52
  end
@@ -63,6 +68,11 @@ module Deface
63
68
  require 'deface/haml_converter'
64
69
  end
65
70
 
71
+ if defined?(Slim)
72
+ app.config.deface.slim_support = true
73
+ require 'slim/erb_converter'
74
+ end
75
+
66
76
  # catchs any overrides that we required manually
67
77
  app.config.deface.overrides.early_check
68
78
 
@@ -0,0 +1,13 @@
1
+ module Deface
2
+ module Sources
3
+ class Slim < Source
4
+ def self.execute(override)
5
+ if Rails.application.config.deface.slim_support
6
+ ::Slim::ERBConverter.new.call(override.args[:slim])
7
+ else
8
+ raise Deface::NotSupportedError, "`#{override.name}` supplies :slim source, but slim_support is not detected."
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -22,6 +22,8 @@ module Deface
22
22
 
23
23
  if view.handler.to_s == "Haml::Plugin"
24
24
  Deface::HamlConverter.new(view.source).result
25
+ elsif view.handler.class.to_s == "Slim::RailsTemplate"
26
+ Slim::ERBConverter.new.call(view.source)
25
27
  else
26
28
  view.source
27
29
  end
@@ -0,0 +1,3 @@
1
+ /
2
+ insert_after 'h1'
3
+ h2 These robots are awesome.
@@ -0,0 +1 @@
1
+ div class="some" id="message"= "Hi, World!"
@@ -0,0 +1,5 @@
1
+ #content
2
+ .left
3
+ p= print_information
4
+ .right(id=@right)
5
+ = render :partial => "sidebar"
@@ -86,7 +86,8 @@ module ActionView
86
86
  expectations.each do |handler, expected|
87
87
  @template = ActionView::Template.new("xml.post => :blah", "/some/path/to/file.erb", handler, {:virtual_path=>"posts/index", :format=>:xml, :updated_at => (Time.now - 100)})
88
88
  @template.is_a?(ActionView::Template).should == true
89
- @template.send(:should_be_defaced?, handler).should eq(expected), "unexpected result for handler "+handler.to_s
89
+ syntax = @template.send(:determine_syntax, handler)
90
+ @template.send(:should_be_defaced?, syntax).should eq(expected), "unexpected result for handler "+handler.to_s
90
91
  end
91
92
  end
92
93
  end
@@ -10,7 +10,7 @@ describe Deface::DSL::Loader do
10
10
  filename = 'app/overrides/example_name.deface'
11
11
 
12
12
  lambda { Deface::DSL::Loader.load(filename) }.should_not raise_error(
13
- "Deface::DSL does not know how to read 'app/overrides/example_name.deface'. Override files should end with just .deface, .html.erb.deface, or .html.haml.deface")
13
+ "Deface::DSL does not know how to read 'app/overrides/example_name.deface'. Override files should end with just .deface, .html.erb.deface, .html.haml.deface or .html.slim.deface")
14
14
  end
15
15
 
16
16
  it 'should succeed if file ends with .html.erb.deface' do
@@ -18,7 +18,7 @@ describe Deface::DSL::Loader do
18
18
  filename = 'app/overrides/example_name.html.erb.deface'
19
19
 
20
20
  lambda { Deface::DSL::Loader.load(filename) }.should_not raise_error(
21
- "Deface::DSL does not know how to read 'app/overrides/example_name.html.erb.deface'. Override files should end with just .deface, .html.erb.deface, or .html.haml.deface")
21
+ "Deface::DSL does not know how to read 'app/overrides/example_name.html.erb.deface'. Override files should end with just .deface, .html.erb.deface, .html.haml.deface or .html.slim.deface")
22
22
  end
23
23
 
24
24
  it 'should succeed if file ends with .html.haml.deface' do
@@ -26,7 +26,15 @@ describe Deface::DSL::Loader do
26
26
  filename = 'app/overrides/example_name.html.haml.deface'
27
27
 
28
28
  lambda { Deface::DSL::Loader.load(filename) }.should_not raise_error(
29
- "Deface::DSL does not know how to read 'app/overrides/example_name.html.haml.deface'. Override files should end with just .deface, .html.erb.deface, or .html.haml.deface")
29
+ "Deface::DSL does not know how to read 'app/overrides/example_name.html.haml.deface'. Override files should end with just .deface, .html.erb.deface, .html.haml.deface or .html.slim.deface")
30
+ end
31
+
32
+ it 'should succeed if file ends with .html.slim.deface' do
33
+ file = mock('deface file')
34
+ filename = 'app/overrides/example_name.html.slim.deface'
35
+
36
+ lambda { Deface::DSL::Loader.load(filename) }.should_not raise_error(
37
+ "Deface::DSL does not know how to read 'app/overrides/example_name.html.slim.deface'. Override files should end with just .deface, .html.erb.deface, .html.haml.deface or .html.slim.deface")
30
38
  end
31
39
 
32
40
  it 'should fail if file ends with .blargh.deface' do
@@ -34,7 +42,7 @@ describe Deface::DSL::Loader do
34
42
  filename = 'app/overrides/example_name.blargh.deface'
35
43
 
36
44
  lambda { Deface::DSL::Loader.load(filename) }.should raise_error(
37
- "Deface::DSL does not know how to read 'app/overrides/example_name.blargh.deface'. Override files should end with just .deface, .html.erb.deface, or .html.haml.deface")
45
+ "Deface::DSL does not know how to read 'app/overrides/example_name.blargh.deface'. Override files should end with just .deface, .html.erb.deface, .html.haml.deface or .html.slim.deface")
38
46
  end
39
47
 
40
48
  it "should suceed if parent directory has a dot(.) in it's name" do
@@ -42,7 +50,7 @@ describe Deface::DSL::Loader do
42
50
  filename = 'app/overrides/parent.dir.with.dot/example_name.html.haml.deface'
43
51
 
44
52
  lambda { Deface::DSL::Loader.load(filename) }.should_not raise_error(
45
- "Deface::DSL does not know how to read 'app/overrides/parent.dir.with.dot/example_name.html.haml.deface'. Override files should end with just .deface, .html.erb.deface, or .html.haml.deface")
53
+ "Deface::DSL does not know how to read 'app/overrides/parent.dir.with.dot/example_name.html.haml.deface'. Override files should end with just .deface, .html.erb.deface, .html.haml.deface or .html.slim.deface")
46
54
  end
47
55
  end
48
56
 
@@ -124,6 +132,31 @@ describe Deface::DSL::Loader do
124
132
  Deface::DSL::Loader.load(filename)
125
133
  end
126
134
 
135
+ it 'should set the virtual_path for a .html.slim.deface file in a directory below overrides' do
136
+ file = mock('html/slim/deface file')
137
+ filename = 'app/overrides/path/to/view/example_name.html.slim.deface'
138
+ File.should_receive(:open).with(filename).and_yield(file)
139
+
140
+ override_name = 'example_name'
141
+ context = mock('dsl context')
142
+ Deface::DSL::Context.should_receive(:new).with(override_name).
143
+ and_return(context)
144
+
145
+ file_contents = mock('file contents')
146
+ file.should_receive(:read).and_return(file_contents)
147
+
148
+ Deface::DSL::Loader.should_receive(:extract_dsl_commands_from_slim).
149
+ with(file_contents).
150
+ and_return(['dsl commands', 'slim'])
151
+
152
+ context.should_receive(:virtual_path).with('path/to/view').ordered
153
+ context.should_receive(:instance_eval).with('dsl commands').ordered
154
+ context.should_receive(:slim).with('slim').ordered
155
+ context.should_receive(:create_override).ordered
156
+
157
+ Deface::DSL::Loader.load(filename)
158
+ end
159
+
127
160
  end
128
161
 
129
162
  context '.register' do
@@ -220,6 +253,28 @@ describe Deface::DSL::Loader do
220
253
  dsl_commands.should == ""
221
254
  the_rest.should == example
222
255
  end
256
+ end
257
+
258
+ context '.extract_dsl_commands_from_slim' do
259
+ it 'should work in the simplest case' do
260
+ example = "/ test 'command'\n/ another 'command'\nh1 Wow!"
261
+ dsl_commands, the_rest = Deface::DSL::Loader.extract_dsl_commands_from_slim(example)
262
+ dsl_commands.should == "test 'command'\nanother 'command'\n"
263
+ the_rest.should == "h1 Wow!"
264
+ end
223
265
 
266
+ it 'should work with a block style comment using spaces' do
267
+ example = "/\n test 'command'\n another 'command'\nh1 Wow!"
268
+ dsl_commands, the_rest = Deface::DSL::Loader.extract_dsl_commands_from_slim(example)
269
+ dsl_commands.should == "\ntest 'command'\nanother 'command'\n"
270
+ the_rest.should == "h1 Wow!"
271
+ end
272
+
273
+ it 'should leave internal comments alone' do
274
+ example = "br\n/ test 'command'\n/ another 'command'\nh1 Wow!"
275
+ dsl_commands, the_rest = Deface::DSL::Loader.extract_dsl_commands_from_erb(example)
276
+ dsl_commands.should == ""
277
+ the_rest.should == example
278
+ end
224
279
  end
225
280
  end