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 ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in simple_decorator.gemspec
4
+ gemspec
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,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = "spec/**/*_spec.rb"
8
+ end
9
+
10
+ task :default => :spec
@@ -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,7 @@
1
+ module SimpleDecorator
2
+ class Railtie < Rails::Railtie
3
+ initializer "simple_decorator.configure_rails_initialization" do |app|
4
+ app.middleware.use SimpleDecorator::Filter::Decorator
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleDecorator
2
+ VERSION = "0.0.1"
3
+ 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
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/simple_decorator/filter/response_weaver.rb')
2
+ Dir["#{File.dirname(__FILE__)}/matchers/**/*.rb"].each {|f| require f}
3
+
4
+ RSpec.configure do |config|
5
+ config.include(CustomHtmlMatcher)
6
+ end
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