simple_decorator 0.0.1
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 +4 -0
- data/Gemfile +4 -0
- data/README.md +19 -0
- data/Rakefile +10 -0
- data/lib/simple_decorator/controller.rb +22 -0
- data/lib/simple_decorator/filter/decorator.rb +19 -0
- data/lib/simple_decorator/filter/response_weaver.rb +67 -0
- data/lib/simple_decorator/railtie.rb +7 -0
- data/lib/simple_decorator/version.rb +3 -0
- data/lib/simple_decorator.rb +10 -0
- data/simple_decorator.gemspec +24 -0
- data/spec/matchers/have_same_markup.rb +28 -0
- data/spec/response_weaver_spec.rb +91 -0
- data/spec/spec_helper.rb +6 -0
- metadata +85 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Simple decorator
|
2
|
+
|
3
|
+
A simple sitemesh-like rack filter for Rails apps
|
4
|
+
|
5
|
+
This gem lets you specify a url to a place to fetch the layout for your application using a method in you controllers.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
In your Gemfile
|
10
|
+
|
11
|
+
gem 'simple_decorator', '0.0.1', git: 'git://github.com/Posten-konsernportal/simple_decorator.git'
|
12
|
+
|
13
|
+
In any controller
|
14
|
+
|
15
|
+
# usually you put this in your ApplicationController
|
16
|
+
# but feel free to override in any other controller
|
17
|
+
def decorator_url
|
18
|
+
"some url to a velocity style decorator"
|
19
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module SimpleDecorator
|
2
|
+
module Controller
|
3
|
+
## this one manages the usual self.included, klass_eval stuff
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
after_filter :call_decorator_url
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def call_decorator_url
|
12
|
+
return unless respond_to? :decorator_url
|
13
|
+
|
14
|
+
request.env['simple_decorator.layout.url'] = decorator_url
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
::ActionController::Base.send :include, SimpleDecorator::Controller
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rack-plastic'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module SimpleDecorator
|
5
|
+
module Filter
|
6
|
+
class Decorator < Rack::Plastic
|
7
|
+
def change_html_string(html)
|
8
|
+
return html unless request.env["simple_decorator.layout.url"]
|
9
|
+
|
10
|
+
layout = request.env["simple_decorator.layout.url"]
|
11
|
+
|
12
|
+
decorator = open(layout, :proxy => nil).read
|
13
|
+
|
14
|
+
weaver = ResponseWeaver.new(decorator)
|
15
|
+
weaver.apply(html)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class ResponseWeaver
|
2
|
+
|
3
|
+
def initialize(decorator)
|
4
|
+
@init_time = Time.now
|
5
|
+
@decorator = decorator
|
6
|
+
@placeholders = build_placeholders(decorator)
|
7
|
+
@fields = keys(@placeholders)
|
8
|
+
end
|
9
|
+
|
10
|
+
def apply(response)
|
11
|
+
response_array = @placeholders
|
12
|
+
|
13
|
+
@fields.each do |tag_name|
|
14
|
+
content_for_tag = extract_from_response(response, tag_name)
|
15
|
+
|
16
|
+
#<title> is nested within <head>, so we will have to remove the <title> tag from the head placeholder
|
17
|
+
content_for_tag = remove_nested_tags(content_for_tag)
|
18
|
+
response_array[response_array.index("$#{tag_name}")] = content_for_tag
|
19
|
+
end
|
20
|
+
|
21
|
+
#build a response string from the array
|
22
|
+
ret = ''
|
23
|
+
response_array.each { |str| ret << str }
|
24
|
+
|
25
|
+
#puts "time since init: #{Time.now - @init_time} "
|
26
|
+
ret
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def remove_nested_tags(content)
|
33
|
+
@fields.each do |tag_name|
|
34
|
+
content = content.gsub(/<#{tag_name}>.*<\/#{tag_name}>/im, '')
|
35
|
+
end
|
36
|
+
content
|
37
|
+
end
|
38
|
+
|
39
|
+
def extract_from_response(response, tag_name)
|
40
|
+
matchdata = /<#{tag_name}>(.*)<\/#{tag_name}>/im.match(response)
|
41
|
+
if matchdata
|
42
|
+
matchdata[1]
|
43
|
+
else
|
44
|
+
""
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# returns an array containing the enire page, but splitted with keys as separate elements
|
49
|
+
# ['<some body html>' , '$title', '<morebody>', '$head', '<more body>']
|
50
|
+
def build_placeholders(template_string)
|
51
|
+
template_string.split(/(\$[\w]+)/)
|
52
|
+
end
|
53
|
+
|
54
|
+
def keys(page_array)
|
55
|
+
ret_keys = []
|
56
|
+
page_array.each {|elem| ret_keys << keyname(elem) if key?(elem)}
|
57
|
+
ret_keys
|
58
|
+
end
|
59
|
+
|
60
|
+
def key?(str)
|
61
|
+
str.start_with?('$')
|
62
|
+
end
|
63
|
+
|
64
|
+
def keyname(str)
|
65
|
+
str.gsub(/\$/, '')
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "simple_decorator/version"
|
2
|
+
|
3
|
+
require 'simple_decorator/filter/response_weaver'
|
4
|
+
require 'simple_decorator/filter/decorator'
|
5
|
+
require 'simple_decorator/controller'
|
6
|
+
require 'simple_decorator/railtie' if defined?(Rails)
|
7
|
+
|
8
|
+
module SimpleDecorator
|
9
|
+
|
10
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "simple_decorator/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "simple_decorator"
|
7
|
+
s.version = SimpleDecorator::VERSION
|
8
|
+
s.authors = ["Eirik Lied"]
|
9
|
+
s.email = ["eiriklied@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/Posten-Konsernportal/simple_decorator"
|
11
|
+
s.summary = %q{A ruby sitemesh-like implementation}
|
12
|
+
s.description = %q{A simple gem to give sitemesh-like functionality in a rack app using decorators.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "simple_decorator"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
s.add_runtime_dependency "rack-plastic"
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module CustomHtmlMatcher
|
2
|
+
class HaveSameMarkup
|
3
|
+
def initialize(expected)
|
4
|
+
@expected = expected
|
5
|
+
end
|
6
|
+
|
7
|
+
def matches?(target)
|
8
|
+
@target = target
|
9
|
+
normalize_whitespaces(@target).eql?(normalize_whitespaces(@expected))
|
10
|
+
end
|
11
|
+
def failure_message
|
12
|
+
"expected #{@target} to match #{@expected}"
|
13
|
+
end
|
14
|
+
def negative_failure_message
|
15
|
+
"expected #{@target} not to match #{@expected}"
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def normalize_whitespaces(str)
|
20
|
+
str.gsub(/\s+/, ' ') #replace all whitespace occurences with just once space
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def be_same_markup(expected)
|
26
|
+
HaveSameMarkup.new(expected)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe ResponseWeaver do
|
4
|
+
|
5
|
+
it "should strip out placeholders in response" do
|
6
|
+
response = ResponseWeaver.new('<html>$some_placeholder</html>').apply('Jadajada')
|
7
|
+
response.should == "<html></html>"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should inject a tag from apply to placeholder with matching name" do
|
11
|
+
response =
|
12
|
+
ResponseWeaver.new('<html><head><script scr="http://jquery.com/jquery.js"/>$head</head><body></body></html>').
|
13
|
+
apply('<html class="bladi"><head><title>should be applied</title></head><body></body></html>')
|
14
|
+
|
15
|
+
response.should == '<html><head><script scr="http://jquery.com/jquery.js"/><title>should be applied</title></head><body></body></html>'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be case insensitive when injecting tags into placeholders" do
|
19
|
+
response =
|
20
|
+
ResponseWeaver.new('<Html><head>$HEad</head><body></body></html>').
|
21
|
+
apply('<HTML><HEAD>MYHEADCONTENT</head><body></body></html>')
|
22
|
+
response.should == '<Html><head>MYHEADCONTENT</head><body></body></html>'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should match multiline responses" do
|
26
|
+
response =
|
27
|
+
ResponseWeaver.new(%{
|
28
|
+
<html>
|
29
|
+
<head>
|
30
|
+
<script scr="http://jquery.com/jquery.js"></script>
|
31
|
+
<meta name="description" value="blasbdlasbd"/>
|
32
|
+
$head
|
33
|
+
</head>
|
34
|
+
<body>
|
35
|
+
Some body
|
36
|
+
$body
|
37
|
+
</body>
|
38
|
+
</html>
|
39
|
+
}).
|
40
|
+
apply(%{
|
41
|
+
<html>
|
42
|
+
<head>
|
43
|
+
<head_tag_to_be_applied/>
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
</body>
|
47
|
+
</html>
|
48
|
+
})
|
49
|
+
|
50
|
+
response.should be_same_markup(%{
|
51
|
+
<html>
|
52
|
+
<head>
|
53
|
+
<script scr="http://jquery.com/jquery.js"></script>
|
54
|
+
<meta name="description" value="blasbdlasbd"/>
|
55
|
+
<head_tag_to_be_applied/>
|
56
|
+
</head>
|
57
|
+
<body>
|
58
|
+
Some body
|
59
|
+
</body>
|
60
|
+
</html>
|
61
|
+
})
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should remove nested tags that apply to other placeholders" do
|
65
|
+
response =
|
66
|
+
ResponseWeaver.new(%{
|
67
|
+
<html>
|
68
|
+
<head>
|
69
|
+
<title>$title</title>
|
70
|
+
$head
|
71
|
+
</head>
|
72
|
+
<body></body>
|
73
|
+
</html>
|
74
|
+
}).apply(%{
|
75
|
+
<html>
|
76
|
+
<head><title>This should appear once</title>
|
77
|
+
</head>
|
78
|
+
<body></body>
|
79
|
+
</html>
|
80
|
+
})
|
81
|
+
response.should be_same_markup(%{
|
82
|
+
<html>
|
83
|
+
<head>
|
84
|
+
<title>This should appear once</title>
|
85
|
+
</head>
|
86
|
+
<body></body>
|
87
|
+
</html>
|
88
|
+
})
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_decorator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eirik Lied
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &2153198560 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2153198560
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rack-plastic
|
27
|
+
requirement: &2153198140 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2153198140
|
36
|
+
description: A simple gem to give sitemesh-like functionality in a rack app using
|
37
|
+
decorators.
|
38
|
+
email:
|
39
|
+
- eiriklied@gmail.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- README.md
|
47
|
+
- Rakefile
|
48
|
+
- lib/simple_decorator.rb
|
49
|
+
- lib/simple_decorator/controller.rb
|
50
|
+
- lib/simple_decorator/filter/decorator.rb
|
51
|
+
- lib/simple_decorator/filter/response_weaver.rb
|
52
|
+
- lib/simple_decorator/railtie.rb
|
53
|
+
- lib/simple_decorator/version.rb
|
54
|
+
- simple_decorator.gemspec
|
55
|
+
- spec/matchers/have_same_markup.rb
|
56
|
+
- spec/response_weaver_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
homepage: https://github.com/Posten-Konsernportal/simple_decorator
|
59
|
+
licenses: []
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project: simple_decorator
|
78
|
+
rubygems_version: 1.8.10
|
79
|
+
signing_key:
|
80
|
+
specification_version: 3
|
81
|
+
summary: A ruby sitemesh-like implementation
|
82
|
+
test_files:
|
83
|
+
- spec/matchers/have_same_markup.rb
|
84
|
+
- spec/response_weaver_spec.rb
|
85
|
+
- spec/spec_helper.rb
|