deface 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -3,25 +3,12 @@ Deface
3
3
 
4
4
  Deface is a library that allows you to customize ERB views in a Rails application without editing the underlying view.
5
5
 
6
- It allows you to easily target html & erb elements as the hooks for customization using both CSS and XPath selectors as supported by Nokogiri.
6
+ It allows you to easily target html & erb elements as the hooks for customization using CSS selectors as supported by Nokogiri.
7
7
 
8
- Deface temporarily converts ERB files into a pseudo HTML markup that can be parsed and queired by Nokogiri, using the following approach:
9
-
10
- <%= some ruby code %>
11
-
12
- becomes
13
-
14
- <code erb-loud> some ruby code </code>
15
-
16
- and
17
-
18
- <% other ruby code %>
19
-
20
- becomes
21
-
22
- <code erb-silent> other ruby code </code>
8
+ Demo & Testing
9
+ ---------------
10
+ You can play with Deface and see it's parsing in action at [deface.heroku.com](http://deface.heroku.com)
23
11
 
24
- Deface overrides have full access to all variables accessible to the view being customized.
25
12
 
26
13
  Deface::Override
27
14
  =======
@@ -42,6 +29,10 @@ Action
42
29
 
43
30
  * <tt>:insert_before</tt> - Inserts before all elements that match the supplied selector
44
31
 
32
+ * <tt>:insert_top</tt> - Inserts inside all elements that match the supplied selector, as the first child.
33
+
34
+ * <tt>:insert_bottom</tt> - Inserts inside all elements that match the supplied selector, as the last child.
35
+
45
36
  Source
46
37
  ------
47
38
  * <tt>:text</tt> - String containing markup
@@ -83,3 +74,45 @@ Removes any instance of `<%= helper_method %>` in the `posts/new.html.erb" templ
83
74
  Deface::Override.new(:virtual_path => "posts/new",
84
75
  :name => "example-4",
85
76
  :remove => "code[erb-loud]:contains('helper_method')" )
77
+
78
+
79
+ Implementation
80
+ ==============
81
+
82
+ Deface temporarily converts ERB files into a pseudo HTML markup that can be parsed and queired by Nokogiri, using the following approach:
83
+
84
+ <%= some ruby code %>
85
+
86
+ becomes
87
+
88
+ <code erb-loud> some ruby code </code>
89
+
90
+ and
91
+
92
+ <% other ruby code %>
93
+
94
+ becomes
95
+
96
+ <code erb-silent> other ruby code </code>
97
+
98
+ ERB that is contained inside a HTML tag definition is converted slightly differently to ensure a valid HTML document that Nokogiri can parse:
99
+
100
+ <p id="<%= dom_id @product %>" <%= "style='display:block';" %>>
101
+
102
+ becomes
103
+
104
+ <p data-erb-id="&lt;%= dom_id @product %&gt;" data-erb-0="&lt;%= &quot;style='display:block';&quot; %&gt;">
105
+
106
+ Deface overrides have full access to all variables accessible to the view being customized.
107
+
108
+ Caveats
109
+ ======
110
+
111
+ Due to the use of the Nokogiri library for parsing HTML / view files you need to ensure that your layout views include doctype, html, head and body tags in a single file, as Nokogiri will create such elements if it detects any of these tags have been incorrectly nested.
112
+
113
+ Parsing will fail and result in invalid output if ERB blocks are responsible for closing a HTML tag what was opened normally, i.e. don't do this:
114
+
115
+
116
+ <div <%= ">" %>
117
+
118
+
data/deface.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{deface}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.authors = ["Brian Quinn"]
11
11
  s.description = %q{Deface is a library that allows you to customize ERB views in a Rails application without editing the underlying view.}
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  ]
16
16
  s.files = `git ls-files`.split("\n")
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.homepage = %q{http://github.com/BDQ/Deface}
18
+ s.homepage = %q{http://github.com/railsdog/deface}
19
19
  s.rdoc_options = ["--charset=UTF-8"]
20
20
  s.require_paths = ["lib"]
21
21
  s.summary = %q{Deface is a library that allows you to customize ERB views in Rails}
data/lib/deface/parser.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'nokogiri'
2
- require 'erubis'
3
2
  require 'cgi'
4
3
 
5
4
  module Deface
@@ -7,6 +6,35 @@ module Deface
7
6
  # converts erb to markup
8
7
  #
9
8
  def self.erb_markup!(source)
9
+
10
+ #all opening html tags that contain <% %> blocks
11
+ source.scan(/<\w+[^<>]+(?:<%.*?%>[^<>]*)+/m).each do |line|
12
+
13
+ #regexs to catch <% %> inside attributes id="<% something %>" - with double, single or no quotes
14
+ erb_attrs_regexs = [/([\w-]+)(\s?=\s?)(")([^"]*<%.*?%>[^"]*)/m,
15
+ /([\w-]+)(\s?=\s?)(')([^']*<%.*?%>[^']*)'/m,
16
+ /([\w-]+)(\s?=\s?)()(<%.*?%>)(?:\s|>|\z)/m]
17
+
18
+ replace_line = erb_attrs_regexs.inject(line.clone) do |replace_line, regex|
19
+
20
+ replace_line = line.scan(regex).inject(replace_line) do |replace_line, match|
21
+ replace_line.sub("#{match[0]}#{match[1]}#{match[2]}#{match[3]}#{match[2]}") { |m| m = " data-erb-#{match[0]}=\"#{CGI.escapeHTML(match[3])}\"" }
22
+ end
23
+
24
+ replace_line
25
+ end
26
+
27
+
28
+ i = -1
29
+ #catch all <% %> inside tags id <p <%= test %>> , not inside attrs
30
+ replace_line.scan(/(<%.*?%>)/m).each do |match|
31
+ replace_line.sub!(match[0]) { |m| m = " data-erb-#{i += 1}=\"#{CGI.escapeHTML(match[0])}\"" }
32
+ end
33
+
34
+ source.sub!(line) { |m| m = replace_line }
35
+ end
36
+
37
+ #replaces all <% %> not inside opening html tags
10
38
  replacements = [ {"<%=" => "<code erb-loud>"},
11
39
  {"<%" => "<code erb-silent>"},
12
40
  {"%>" => "</code>"} ]
@@ -14,7 +42,7 @@ module Deface
14
42
  replacements.each{ |h| h.each { |replace, with| source.gsub! replace, with } }
15
43
 
16
44
  source.scan(/(<code.*?>)((?:(?!<\/code>)[\s\S])*)(<\/code>)/).each do |match|
17
- source.gsub!("#{match[0]}#{match[1]}#{match[2]}", "#{match[0]}#{CGI.escapeHTML(match[1])}#{match[2]}")
45
+ source.sub!("#{match[0]}#{match[1]}#{match[2]}") { |m| m = "#{match[0]}#{CGI.escapeHTML(match[1])}#{match[2]}" }
18
46
  end
19
47
 
20
48
  source
@@ -25,18 +53,21 @@ module Deface
25
53
  def self.undo_erb_markup!(source)
26
54
  replacements = [ {"<code erb-silent>" => '<%'},
27
55
  {"<code erb-loud>" => '<%='},
28
- {"</code>" => '%>'},
29
- {/(<|&lt;)code(\s|%20)erb-silent(&gt;|>)/ => '<%'},
30
- {/(<|&lt;)code(\s|%20)erb-loud(&gt;|>)/ => '<%='},
31
- {/(<|&lt;)\/code(&gt;|>)/ => '%>'} ]
56
+ {"</code>" => '%>'}]
32
57
 
33
58
  replacements.each{ |h| h.each { |replace, with| source.gsub! replace, with } }
34
59
 
60
+ source.scan(/data-erb-(\d+)+=(['"])(.*?)\2/m).each do |match|
61
+ source.gsub!("data-erb-#{match[0]}=#{match[1]}#{match[2]}#{match[1]}") { |m| m = CGI.unescapeHTML(match[2]) }
62
+ end
63
+
64
+ source.scan(/data-erb-([\w-]+)+=(["'])(.*?)\2/m).each do |match|
65
+ source.gsub!("data-erb-#{match[0]}=#{match[1]}#{match[2]}#{match[1]}") { |m| "#{match[0]}=#{match[1]}#{CGI.unescapeHTML(match[2])}#{match[1]}" }
66
+ end
67
+
35
68
  #un-escape changes from Nokogiri and erb-markup!
36
69
  source.scan(/(<%.*?)((?:(?!%>)[\s\S])*)(%>)/).each do |match|
37
- escaped = URI.unescape match[1]
38
- escaped = CGI.unescapeHTML CGI.unescapeHTML(escaped)
39
- source.gsub!("#{match[0]}#{match[1]}#{match[2]}", "#{match[0]}#{escaped}#{match[2]}")
70
+ source.gsub!("#{match[0]}#{match[1]}#{match[2]}") { |m| m = "#{match[0]}#{ CGI.unescapeHTML match[1] }#{match[2]}" }
40
71
  end
41
72
 
42
73
  source
@@ -37,12 +37,34 @@ module Deface
37
37
  Deface::Parser.convert("<%= method_name %>").to_s.should == "<code erb-loud> method_name </code>"
38
38
  end
39
39
 
40
- it "should convert nested <% ... %>" do
41
- Deface::Parser.convert("<p id=\"<% method_name %>\"></p>").to_s.should == "<p id=\"&lt;code erb-silent&gt; method_name &lt;/code&gt;\"></p>"
40
+ it "should convert first <% ... %> inside html tag" do
41
+ Deface::Parser.convert("<p <% method_name %>></p>").to_s.should == "<p data-erb-0=\"&lt;% method_name %&gt;\"></p>"
42
42
  end
43
43
 
44
- it "should convert nested <%= ... %> including href attribute" do
45
- Deface::Parser.convert(%(<a href="<%= x 'y' + "z" %>">A Link</a>)).to_s.should == "<a href=\"&lt;code%20erb-loud&gt;%20x%20'y'%20+%20%22z%22%20&lt;/code&gt;\">A Link</a>"
44
+ it "should convert second <% ... %> inside html tag" do
45
+ Deface::Parser.convert("<p <% method_name %> <% x = y %>></p>").to_s.should == "<p data-erb-0=\"&lt;% method_name %&gt;\" data-erb-1=\"&lt;% x = y %&gt;\"></p>"
46
+ end
47
+
48
+ it "should convert <% ... %> inside double quoted attr value" do
49
+ Deface::Parser.convert("<p id=\"<% method_name %>\"></p>").to_s.should == "<p data-erb-id=\"&lt;% method_name %&gt;\"></p>"
50
+ end
51
+
52
+ it "should convert <% ... %> inside single quoted attr value" do
53
+ Deface::Parser.convert("<p id='<% method_name %>'></p>").to_s.should == "<p data-erb-id=\"&lt;% method_name %&gt;\"></p>"
54
+ end
55
+
56
+ it "should convert <% ... %> inside non-quoted attr value" do
57
+ Deface::Parser.convert("<p id=<% method_name %>></p>").to_s.should == "<p data-erb-id=\"&lt;% method_name %&gt;\"></p>"
58
+ Deface::Parser.convert("<p id=<% method_name %> alt=\"test\"></p>").to_s.should == "<p data-erb-id=\"&lt;% method_name %&gt;\" alt=\"test\"></p>"
59
+ end
60
+
61
+ it "should convert multiple <% ... %> inside html tag" do
62
+ Deface::Parser.convert(%q{<p <%= method_name %> alt="<% x = 'y' +
63
+ \"2\" %>" title='<% method_name %>' <%= other_method %></p>}).to_s.should == "<p data-erb-0=\"&lt;%= method_name %&gt;\" data-erb-alt=\"&lt;% x = 'y' + \n \\&quot;2\\&quot; %&gt;\" data-erb-title=\"&lt;% method_name %&gt;\" data-erb-1=\"&lt;%= other_method %&gt;\"></p>"
64
+ end
65
+
66
+ it "should convert <%= ... %> including href attribute" do
67
+ Deface::Parser.convert(%(<a href="<%= x 'y' + "z" %>">A Link</a>)).to_s.should == "<a data-erb-href=\"&lt;%= x 'y' + &quot;z&quot; %&gt;\">A Link</a>"
46
68
  end
47
69
 
48
70
  it "should escape contents code tags" do
@@ -59,21 +81,16 @@ module Deface
59
81
  Deface::Parser.undo_erb_markup!("<code erb-loud> method_name </code>").should == "<%= method_name %>"
60
82
  end
61
83
 
62
- it "should revert nested <code erb-silent>" do
63
- Deface::Parser.undo_erb_markup!("<p id=\"&lt;code erb-silent&gt; method_name > 1 &lt;/code&gt;\"></p>").should == "<p id=\"<% method_name > 1 %>\"></p>"
64
- end
65
-
66
- it "should revert nested <code erb-silent> including href attribute" do
67
- Deface::Parser.undo_erb_markup!("<a href=\"&lt;code%20erb-silent&gt;%20method_name%20&lt;/code&gt;\">A Link</a>").should == "<a href=\"<% method_name %>\">A Link</a>"
84
+ it "should revert data-erb-x attrs inside html tag" do
85
+ Deface::Parser.undo_erb_markup!("<p data-erb-0=\"&lt;% method_name %&gt;\" data-erb-1=\"&lt;% x = y %&gt;\"></p>").should == "<p <% method_name %> <% x = y %>></p>"
68
86
  end
69
87
 
70
- it "should revert nested <code erb-loud>" do
71
- Deface::Parser.undo_erb_markup!("<p id=\"&lt;code erb-loud&gt; method_name < 2 &lt;/code&gt;\"></p>").should == "<p id=\"<%= method_name < 2 %>\"></p>"
88
+ it "should revert data-erb-id attr inside html tag" do
89
+ Deface::Parser.undo_erb_markup!("<p data-erb-id=\"&lt;% method_name &gt; 1 %&gt;\"></p>").should == "<p id=\"<% method_name > 1 %>\"></p>"
72
90
  end
73
91
 
74
- it "should revert nested <code erb-loud> including href attribute" do
75
- Deface::Parser.undo_erb_markup!("<a href=\"&lt;code%20erb-loud&gt;%20x%20'y'%20+%20'z'%20&lt;/code&gt;\">A Link</a>").should == %(<a href="<%= x 'y' + 'z' %>">A Link</a>)
76
- Deface::Parser.undo_erb_markup!("<a href=\"&lt;code%20erb-loud&gt;%20x%20'y'%20+%20%22z%22%20&lt;/code&gt;\">A Link</a>").should == %(<a href="<%= x 'y' + "z" %>">A Link</a>)
92
+ it "should revert data-erb-href attr inside html tag" do
93
+ Deface::Parser.undo_erb_markup!("<a data-erb-href=\"&lt;%= x 'y' + &quot;z&quot; %&gt;\">A Link</a>").should == %(<a href="<%= x 'y' + \"z\" %>">A Link</a>)
77
94
  end
78
95
 
79
96
  it "should unescape contents of code tags" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deface
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
5
- prerelease:
4
+ hash: 15
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brian Quinn
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-13 00:00:00 +01:00
18
+ date: 2011-05-24 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -80,7 +80,7 @@ files:
80
80
  - spec/deface/template_spec.rb
81
81
  - spec/spec_helper.rb
82
82
  has_rdoc: true
83
- homepage: http://github.com/BDQ/Deface
83
+ homepage: http://github.com/railsdog/deface
84
84
  licenses: []
85
85
 
86
86
  post_install_message:
@@ -109,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
109
  requirements: []
110
110
 
111
111
  rubyforge_project:
112
- rubygems_version: 1.5.0
112
+ rubygems_version: 1.3.7
113
113
  signing_key:
114
114
  specification_version: 3
115
115
  summary: Deface is a library that allows you to customize ERB views in Rails