tiny 0.2.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/.gitignore +10 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/README.md +388 -0
- data/Rakefile +1 -0
- data/lib/tiny.rb +519 -0
- data/lib/tiny/erubis.rb +63 -0
- data/lib/tiny/html.rb +177 -0
- data/lib/tiny/safe_string.rb +16 -0
- data/lib/tiny/tag.rb +47 -0
- data/lib/tiny/version.rb +3 -0
- data/spec/erubis_spec.rb +48 -0
- data/spec/fixtures/erb_list.erb +20 -0
- data/spec/fixtures/erb_list_with_helpers.erb +5 -0
- data/spec/fixtures/haml_list.haml +16 -0
- data/spec/fixtures/haml_list_with_helpers.haml +4 -0
- data/spec/helpers_spec.rb +303 -0
- data/spec/integration/erb_spec.rb +83 -0
- data/spec/integration/haml_spec.rb +59 -0
- data/spec/integration/rails_spec.rb +42 -0
- data/spec/integration/sinatra_spec.rb +42 -0
- data/spec/spec_helper.rb +54 -0
- data/spec/support/form_helper.rb +34 -0
- data/spec/support/list_helper.rb +14 -0
- data/spec/support/rails_app.rb +44 -0
- data/spec/support/sinatra_app.rb +26 -0
- data/spec/widget_spec.rb +146 -0
- data/tiny.gemspec +31 -0
- metadata +237 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'markup helpers' do
|
5
|
+
include Tiny::Helpers
|
6
|
+
|
7
|
+
let(:output) do
|
8
|
+
Capybara::Node::Simple.new(@output)
|
9
|
+
end
|
10
|
+
|
11
|
+
def span &block
|
12
|
+
with_buffer do
|
13
|
+
tag(:span, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_block &block
|
18
|
+
erb_block?(block).should be_true
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should determine block origin' do
|
22
|
+
Tilt['erb'].new { '<% check_block do %><% end %>' }.render(self)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should capture erb' do
|
26
|
+
Tilt['erb'].new { '<% mk = with_buffer("Tiny!") do |s| %>Hello <%= s %><% end %><%- mk.should == "Hello Tiny!" %>' }.render(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should emit tag' do
|
30
|
+
@output = Tilt['erb'].new { '<%= tag(:div) %>' }.render(self)
|
31
|
+
output.should have_css 'div', :count => 1
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should not buffer multiple tags' do
|
35
|
+
template = Tilt['erb'].new { '<%= yield %>' }
|
36
|
+
output = template.render(self) { tag(:span); tag(:a) }
|
37
|
+
output.should == '<a></a>'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should buffer multiple tags inside with_buffer block' do
|
41
|
+
template = Tilt['erb'].new { '<%= yield %>' }
|
42
|
+
output = template.render(self) { with_buffer { tag(:span); tag(:a) } }
|
43
|
+
output.should == "<span></span>\n<a></a>\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should concat erb block' do
|
47
|
+
template = Tilt['erb'].new(:outvar => '@_out_buf') { '<%= span do %>Hello<% end %>' }
|
48
|
+
template.render(self).should == "<span>\n Hello\n</span>\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'block passing' do
|
52
|
+
describe 'shallow' do
|
53
|
+
before do
|
54
|
+
@output = Tilt['erb'].new(:outvar => '@_out_buf') do
|
55
|
+
<<-ERB
|
56
|
+
<%= tag(:div) do %>
|
57
|
+
<%= tag(:a) do %>
|
58
|
+
Hello
|
59
|
+
<% end %>
|
60
|
+
<% end %>
|
61
|
+
ERB
|
62
|
+
end.render(self)
|
63
|
+
end
|
64
|
+
it { output.should have_css 'div', :count => 1 }
|
65
|
+
it { output.should have_css 'a', :count => 1 }
|
66
|
+
it { output.should have_css 'div > a', :text => 'Hello' }
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'nested' do
|
70
|
+
before do
|
71
|
+
@output = Renderer.new('erb_list.erb').render
|
72
|
+
end
|
73
|
+
it_should_behave_like 'it renders my list'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'with helpers' do
|
78
|
+
before do
|
79
|
+
@output = Renderer.new('erb_list_with_helpers.erb').render
|
80
|
+
end
|
81
|
+
it_should_behave_like 'it renders my list'
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'markup helpers' do
|
5
|
+
include Tiny::Helpers
|
6
|
+
|
7
|
+
let(:output) do
|
8
|
+
Capybara::Node::Simple.new(@output)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'tag' do
|
12
|
+
it 'should emit tag' do
|
13
|
+
@output = Tilt['haml'].new { '= tag(:div)' }.render(self)
|
14
|
+
output.should have_css 'div', :count => 1
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should emit haml block' do
|
18
|
+
@output = Tilt['haml'].new do
|
19
|
+
<<-HAML
|
20
|
+
= tag(:div) do
|
21
|
+
Hello
|
22
|
+
HAML
|
23
|
+
end.render(self)
|
24
|
+
output.should have_css 'div', :text => "Hello", :count => 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'passing blocks' do
|
29
|
+
describe 'shallow' do
|
30
|
+
before do
|
31
|
+
@output = Tilt['haml'].new do
|
32
|
+
<<-HAML
|
33
|
+
= tag(:div) do
|
34
|
+
= tag(:a) do
|
35
|
+
Hello
|
36
|
+
HAML
|
37
|
+
end.render(self)
|
38
|
+
end
|
39
|
+
it { output.should have_css 'div', :count => 1 }
|
40
|
+
it { output.should have_css 'a', :count => 1 }
|
41
|
+
it { output.should have_css 'div > a', :text => 'Hello' }
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'nested' do
|
45
|
+
before do
|
46
|
+
@output = Tilt.new("#{FIXTURES}/haml_list.haml").render(self)
|
47
|
+
end
|
48
|
+
|
49
|
+
it_should_behave_like 'it renders my list'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'with helpers' do
|
54
|
+
before do
|
55
|
+
@output = Renderer.new('haml_list_with_helpers.haml').render
|
56
|
+
end
|
57
|
+
it_should_behave_like 'it renders my list'
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require "#{SUPPORT}/rails_app"
|
3
|
+
|
4
|
+
describe 'Rails compatibility', :type => :request do
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
let(:output) do
|
8
|
+
Capybara::Node::Simple.new(page.body)
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
Capybara.app = RailsTestApp::Application
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'using Tiny from erb template' do
|
16
|
+
before do
|
17
|
+
visit '/erb'
|
18
|
+
end
|
19
|
+
it_should_behave_like 'it renders my list'
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'using Tiny helpers from erb template' do
|
23
|
+
before do
|
24
|
+
visit '/erb_helpers'
|
25
|
+
end
|
26
|
+
it_should_behave_like 'it renders my list'
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'using Tiny from haml template' do
|
30
|
+
before do
|
31
|
+
visit '/haml'
|
32
|
+
end
|
33
|
+
it_should_behave_like 'it renders my list'
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'using Tiny helpers from haml template' do
|
37
|
+
before do
|
38
|
+
visit '/haml_helpers'
|
39
|
+
end
|
40
|
+
it_should_behave_like 'it renders my list'
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require "#{SUPPORT}/sinatra_app"
|
3
|
+
|
4
|
+
describe 'Sinatra compatibility', :type => :request do
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
let(:output) do
|
8
|
+
Capybara::Node::Simple.new(page.body)
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
Capybara.app = SinatraTestApp
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'using Tiny from erb template' do
|
16
|
+
before do
|
17
|
+
visit '/erb'
|
18
|
+
end
|
19
|
+
it_should_behave_like 'it renders my list'
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'using Tiny helpers from erb template' do
|
23
|
+
before do
|
24
|
+
visit '/erb_helpers'
|
25
|
+
end
|
26
|
+
it_should_behave_like 'it renders my list'
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'using Tiny from haml template' do
|
30
|
+
before do
|
31
|
+
visit '/haml'
|
32
|
+
end
|
33
|
+
it_should_behave_like 'it renders my list'
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'using Tiny helpers from haml template' do
|
37
|
+
before do
|
38
|
+
visit '/haml_helpers'
|
39
|
+
end
|
40
|
+
it_should_behave_like 'it renders my list'
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'rspec'
|
4
|
+
require 'capybara/rspec'
|
5
|
+
# require 'erubis'
|
6
|
+
require 'rails'
|
7
|
+
require 'action_controller/railtie'
|
8
|
+
require 'haml'
|
9
|
+
require 'sinatra'
|
10
|
+
require 'tiny'
|
11
|
+
|
12
|
+
$:.unshift File.dirname(__FILE__)
|
13
|
+
require 'support/list_helper'
|
14
|
+
|
15
|
+
FIXTURES = "#{File.dirname __FILE__}/fixtures"
|
16
|
+
SUPPORT = "#{File.dirname __FILE__}/support"
|
17
|
+
|
18
|
+
shared_examples_for 'it renders my list' do
|
19
|
+
it { output.should have_css 'ul', :count => 1 }
|
20
|
+
it { output.should have_css 'li', :count => 3 }
|
21
|
+
it { output.should have_css 'a', :count => 3 }
|
22
|
+
it { output.should have_css 'span', :count => 3 }
|
23
|
+
it { output.should have_css 'ul > li' }
|
24
|
+
it { output.should have_css 'ul > li > a' }
|
25
|
+
it { output.should have_css 'ul > li > a', :text => 'A' }
|
26
|
+
it { output.should have_css 'ul > li > a > span', :text => '1' }
|
27
|
+
it { output.should have_css 'ul > li > a', :text => 'B' }
|
28
|
+
it { output.should have_css 'ul > li > a > span', :text => '2' }
|
29
|
+
it { output.should have_css 'ul > li > a', :text => 'C' }
|
30
|
+
it { output.should have_css 'ul > li > a > span', :text => '3' }
|
31
|
+
end
|
32
|
+
|
33
|
+
shared_examples_for 'it renders my form' do
|
34
|
+
it { output.should have_css 'form', :count => 1 }
|
35
|
+
it { output.should have_css 'form[action="/login"]', :count => 1 }
|
36
|
+
it { output.should have_css 'form > fieldset', :count => 1 }
|
37
|
+
it { output.should have_css 'form > fieldset > label', :count => 1}
|
38
|
+
it { output.should have_css 'form > fieldset > label[for=email]', :text => 'Email', :count => 1}
|
39
|
+
it { output.should have_css 'form > fieldset > input', :count => 1}
|
40
|
+
it { output.should have_css 'form > fieldset > input#email[type=text][value="email@example.com"]', :count => 1 }
|
41
|
+
end
|
42
|
+
|
43
|
+
class Renderer
|
44
|
+
include Tiny::Helpers
|
45
|
+
include ListHelper
|
46
|
+
|
47
|
+
def initialize template
|
48
|
+
@template = template
|
49
|
+
end
|
50
|
+
|
51
|
+
def render
|
52
|
+
Tilt.new("#{FIXTURES}/#{@template}", :outvar => '@output').render(self)
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module FormHelper
|
2
|
+
class MyForm < Tiny::Widget
|
3
|
+
def initialize(action)
|
4
|
+
@action = action
|
5
|
+
end
|
6
|
+
|
7
|
+
def markup
|
8
|
+
form(:action => @action) do
|
9
|
+
fieldset do
|
10
|
+
yield(self)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def text_input(name, value)
|
16
|
+
TextInput.new(name, value).to_html
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class TextInput < Tiny::Widget
|
21
|
+
def initialize(name, value)
|
22
|
+
@name, @value = name, value
|
23
|
+
end
|
24
|
+
|
25
|
+
def markup
|
26
|
+
label(@name.capitalize, :for => @name)
|
27
|
+
input(:type => 'text', :id => @name, :name => @name, :value => @value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def my_form(action, &block)
|
32
|
+
MyForm.new(action).to_html(&block)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
Rails.logger = Logger.new(STDOUT)
|
2
|
+
Rails.logger.level = 3
|
3
|
+
|
4
|
+
ActionController::Base.view_paths = FIXTURES
|
5
|
+
|
6
|
+
module RailsTestApp
|
7
|
+
class Application < Rails::Application
|
8
|
+
config.secret_token = '572c86f5ede338bd8aba8dae0fd3a326aabababc98d1e6ce34b9f5'
|
9
|
+
|
10
|
+
routes.draw do
|
11
|
+
get '/erb' => 'rails_test_app/test#erb'
|
12
|
+
get '/erb_helpers' => 'rails_test_app/test#erb_helpers'
|
13
|
+
get '/haml' => 'rails_test_app/test#haml'
|
14
|
+
get '/haml_helpers' => 'rails_test_app/test#haml_helpers'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class TestController < ActionController::Base
|
19
|
+
helper do
|
20
|
+
include ActionView::Helpers::TextHelper
|
21
|
+
include ActionView::Helpers::UrlHelper
|
22
|
+
include ListHelper
|
23
|
+
end
|
24
|
+
|
25
|
+
def erb
|
26
|
+
render :template => "erb_list"
|
27
|
+
end
|
28
|
+
|
29
|
+
def erb_helpers
|
30
|
+
render :template => "erb_list_with_helpers"
|
31
|
+
end
|
32
|
+
|
33
|
+
def haml
|
34
|
+
render :template => "haml_list"
|
35
|
+
end
|
36
|
+
|
37
|
+
def haml_helpers
|
38
|
+
render :template => "haml_list_with_helpers"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Rails app boot
|
44
|
+
require 'haml/template'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
|
3
|
+
class SinatraTestApp < Sinatra::Base
|
4
|
+
enable :sessions
|
5
|
+
set :environment, :test
|
6
|
+
set :views, "#{File.dirname __FILE__}/../fixtures"
|
7
|
+
|
8
|
+
helpers Tiny::Helpers
|
9
|
+
helpers ListHelper
|
10
|
+
|
11
|
+
get '/erb' do
|
12
|
+
erb :erb_list
|
13
|
+
end
|
14
|
+
|
15
|
+
get '/haml' do
|
16
|
+
haml :haml_list
|
17
|
+
end
|
18
|
+
|
19
|
+
get '/erb_helpers' do
|
20
|
+
erb :erb_list_with_helpers
|
21
|
+
end
|
22
|
+
|
23
|
+
get '/haml_helpers' do
|
24
|
+
haml :haml_list_with_helpers
|
25
|
+
end
|
26
|
+
end
|
data/spec/widget_spec.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'support/form_helper'
|
4
|
+
|
5
|
+
describe Tiny::Widget do
|
6
|
+
include Tiny::Helpers
|
7
|
+
|
8
|
+
let(:output) do
|
9
|
+
Capybara::Node::Simple.new(@output)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "simple widget" do
|
13
|
+
it 'should output content' do
|
14
|
+
output = Class.new(Tiny::Widget) do
|
15
|
+
def markup
|
16
|
+
append! '<div></div>'
|
17
|
+
end
|
18
|
+
end.new.to_html
|
19
|
+
output.should == "<div></div>\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should output content with block' do
|
23
|
+
output = Class.new(Tiny::Widget) do
|
24
|
+
def markup
|
25
|
+
append! "<div>"
|
26
|
+
yield
|
27
|
+
append! "</div>"
|
28
|
+
end
|
29
|
+
end.new.to_html { text 'Hello' }
|
30
|
+
output.should == "<div>\nHello\n</div>\n"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "page widget" do
|
35
|
+
before do
|
36
|
+
@output = Class.new(Tiny::Widget) do
|
37
|
+
def markup
|
38
|
+
head { title "Tiny Page!" }
|
39
|
+
body { h1 "Hello Tiny!" }
|
40
|
+
end
|
41
|
+
end.new.to_html
|
42
|
+
end
|
43
|
+
|
44
|
+
it { output.should have_css 'head', :count => 1 }
|
45
|
+
it { output.should have_css 'head > title', :text => "Tiny Page!", :count => 1 }
|
46
|
+
it { output.should have_css 'body', :count => 1 }
|
47
|
+
it { output.should have_css 'body > h1', :text => "Hello Tiny!", :count => 1 }
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'content from different methods' do
|
51
|
+
before do
|
52
|
+
@output = Class.new(Tiny::Widget) do
|
53
|
+
def notices
|
54
|
+
div :id => :notices do
|
55
|
+
h1 'Notices'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def main
|
60
|
+
div :id => :content do
|
61
|
+
h1 "Content"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def markup
|
66
|
+
notices
|
67
|
+
main
|
68
|
+
end
|
69
|
+
end.new.to_html
|
70
|
+
end
|
71
|
+
|
72
|
+
it { output.should have_css 'div#notices', :count => 1 }
|
73
|
+
it { output.should have_css 'div#notices > h1', :text => "Notices", :count => 1 }
|
74
|
+
it { output.should have_css 'div#content', :count => 1 }
|
75
|
+
it { output.should have_css 'div#content > h1', :text => "Content", :count => 1 }
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'rendering a tag from outside' do
|
79
|
+
before do
|
80
|
+
@title = "Content" # no need to smuggle instance variables
|
81
|
+
@output = Class.new(Tiny::Widget) do
|
82
|
+
def markup
|
83
|
+
div :id => :content do
|
84
|
+
yield
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end.new.to_html { tag :h1, @title }
|
88
|
+
end
|
89
|
+
|
90
|
+
it { output.should have_css 'div#content', :count => 1 }
|
91
|
+
it { output.should have_css 'div#content > h1', :text => "Content", :count => 1 }
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'rendering a block from outside with concatenated tags' do
|
95
|
+
before do
|
96
|
+
@output = Class.new(Tiny::Widget) do
|
97
|
+
def markup &block
|
98
|
+
div(:id => :content, &block)
|
99
|
+
end
|
100
|
+
end.new.to_html { tag(:h1, "Title"); tag(:p, "Content") }
|
101
|
+
end
|
102
|
+
|
103
|
+
it { output.should have_css 'div#content', :count => 1 }
|
104
|
+
it { output.should have_css 'div#content > h1', :text => "Title", :count => 1 }
|
105
|
+
it { output.should have_css 'div#content > p', :text => "Content", :count => 1 }
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'rendering an erb block' do
|
109
|
+
before do
|
110
|
+
widget = Class.new(Tiny::Widget) do
|
111
|
+
def markup &block
|
112
|
+
div(:id => :content, &block)
|
113
|
+
end
|
114
|
+
end.new
|
115
|
+
@output = Tilt['erb'].new { '<%= widget.to_html do %><h1>Title</h1><p>Content</p><% end %>' }.render(self, :widget => widget)
|
116
|
+
end
|
117
|
+
|
118
|
+
it { output.should have_css 'div#content', :count => 1 }
|
119
|
+
it { output.should have_css 'div#content > h1', :text => "Title", :count => 1 }
|
120
|
+
it { output.should have_css 'div#content > p', :text => "Content", :count => 1 }
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'widget with no content overriden' do
|
124
|
+
it 'should raise not implemented' do
|
125
|
+
lambda do
|
126
|
+
Class.new(Tiny::Widget).new.to_html
|
127
|
+
end.should raise_error(NotImplementedError)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'view helpers using Widget' do
|
132
|
+
include FormHelper
|
133
|
+
before do
|
134
|
+
@output = my_form('/login') { |form| append! form.text_input 'email', 'email@example.com' }
|
135
|
+
end
|
136
|
+
it_should_behave_like 'it renders my form'
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'ERB view helpers using Widget' do
|
140
|
+
include FormHelper
|
141
|
+
before do
|
142
|
+
@output = Tilt['erb'].new { '<%= my_form("/login") do |form| %><%= form.text_input "email", "email@example.com" %><% end %>' }.render(self)
|
143
|
+
end
|
144
|
+
it_should_behave_like 'it renders my form'
|
145
|
+
end
|
146
|
+
end
|