deface 0.3.0 → 0.4.0

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/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