minimal 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +22 -0
- data/Rakefile +19 -0
- data/lib/minimal/template/form_builder_proxy.rb +23 -0
- data/lib/minimal/template.rb +59 -0
- data/lib/minimal/version.rb +3 -0
- data/lib/minimal.rb +6 -0
- data/test/fixtures/views/foo/_partial.rb +7 -0
- data/test/fixtures/views/foo/form_for.rb +11 -0
- data/test/fixtures/views/foo/form_tag.rb +11 -0
- data/test/fixtures/views/foo/misc_helpers.rb +16 -0
- data/test/fixtures/views/foo/partial.rb +12 -0
- data/test/fixtures/views/foo/simple.rb +18 -0
- data/test/fixtures/views/foo/table.rb +11 -0
- data/test/template_test.rb +111 -0
- data/test/test_helper.rb +48 -0
- metadata +77 -0
data/README.textile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Minimal::Template is an experimental, minimalistic templating engine inspired by "Markaby":http://github.com/markaby/markaby & "Erector":http://erector.rubyforge.org but much smaller (~60 loc) and targeted at Rails 3.
|
2
|
+
|
3
|
+
<pre># views/foo/bar.rb
|
4
|
+
module Foo
|
5
|
+
class Bar < Minimal::Template
|
6
|
+
def content
|
7
|
+
html do
|
8
|
+
head
|
9
|
+
body do
|
10
|
+
h1 'plain'
|
11
|
+
p local
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# somewhere else
|
19
|
+
view = ActionView::Base.new('path/to/your/views')
|
20
|
+
view.render(:file => 'foo/bar', :locals => { :local => 'local' })
|
21
|
+
|
22
|
+
# => '<html><head></head><body><h1>plain</h1><p>local</p></body></html>'</pre>
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
require File.expand_path("../lib/minimal/version", __FILE__)
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = "minimal"
|
9
|
+
s.version = Minimal::VERSION
|
10
|
+
s.summary = "Minimal templating engine inspired by Markaby & Erector"
|
11
|
+
s.email = "svenfuchs@artweb-design.de"
|
12
|
+
s.homepage = "http://github.com/svenfuchs/minimal"
|
13
|
+
s.description = "Minimal templating engine inspired by Markaby & Erector and targeted at Rails 3"
|
14
|
+
s.authors = ['Sven Fuchs']
|
15
|
+
s.files = FileList["[A-Z]*", "{lib,test}/**/*"]
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Minimal::Template
|
2
|
+
module FormBuilderProxy
|
3
|
+
class Proxy
|
4
|
+
attr_reader :template, :builder
|
5
|
+
|
6
|
+
def initialize(template, builder)
|
7
|
+
@template, @builder = template, builder
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(method, *args, &block)
|
11
|
+
template << builder.send(method, *args, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(method, *args, &block)
|
16
|
+
if [:form_for, :fields_for].include?(method)
|
17
|
+
view.form_for(*args) { |builder| yield(Proxy.new(self, builder)) }
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Minimal::Template
|
2
|
+
autoload :FormBuilderProxy, 'minimal/template/form_builder_proxy'
|
3
|
+
|
4
|
+
class Handler < ActionView::Template::Handler
|
5
|
+
include ActionView::Template::Handlers::Compilable
|
6
|
+
|
7
|
+
def compile(template)
|
8
|
+
require template.identifier
|
9
|
+
klass = template.identifier =~ %r(views/(.*).rb) && $1.camelize
|
10
|
+
"@output_buffer = ActiveSupport::SafeBuffer.new;#{klass}.new(self)._render(local_assigns)"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
AUTO_BUFFER = %r(render|tag|error_message_|select|debug|_to|_for)
|
15
|
+
NO_AUTO_BUFFER = %r(form_tag|form_for)
|
16
|
+
|
17
|
+
TAG_NAMES = %w(a body div em fieldset form h1 h2 h3 h4 head html img input
|
18
|
+
label li link ol option p pre script select span strong table td th tr ul)
|
19
|
+
|
20
|
+
module Base
|
21
|
+
attr_reader :view, :buffers, :locals
|
22
|
+
|
23
|
+
def initialize(view = nil)
|
24
|
+
@view, @buffers = view, []
|
25
|
+
end
|
26
|
+
|
27
|
+
def _render(locals = nil)
|
28
|
+
@locals = locals || {}
|
29
|
+
content
|
30
|
+
view.output_buffer
|
31
|
+
end
|
32
|
+
|
33
|
+
TAG_NAMES.each do |name|
|
34
|
+
define_method(name) { |*args, &block| content_tag(name, *args, &block) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def <<(output)
|
38
|
+
view.output_buffer << output
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def method_missing(method, *args, &block)
|
44
|
+
locals.key?(method) ? locals[method] :
|
45
|
+
view.instance_variable_defined?("@#{method}") ? view.instance_variable_get("@#{method}") :
|
46
|
+
view.respond_to?(method) ? call_view(method, *args, &block) : super
|
47
|
+
end
|
48
|
+
|
49
|
+
def call_view(method, *args, &block)
|
50
|
+
block = lambda { |*args| self << view.with_output_buffer { yield(*args) } } if block
|
51
|
+
view.send(method, *args, &block).tap { |result| self << result if auto_buffer?(method) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def auto_buffer?(method)
|
55
|
+
AUTO_BUFFER =~ method.to_s && NO_AUTO_BUFFER !~ method.to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
include Base
|
59
|
+
end
|
data/lib/minimal.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Foo
|
2
|
+
class MiscHelpers < Minimal::Template
|
3
|
+
def content
|
4
|
+
image_tag('http://no-asset-host.com/rails.png')
|
5
|
+
debug('foo')
|
6
|
+
javascript_tag("alert('All is good')")
|
7
|
+
div_for(Record.new) { self << 'content' }
|
8
|
+
tag('br')
|
9
|
+
content_tag(:p, 'Hello world!')
|
10
|
+
content_tag(:p) { self << 'Hello world!' }
|
11
|
+
content_tag(:p) { em 'Hello world!' }
|
12
|
+
content_tag(:p) { em { self << 'Hello world!' } }
|
13
|
+
link_to('foo', '#')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Foo
|
2
|
+
class Partial < Minimal::Template
|
3
|
+
def content
|
4
|
+
div do
|
5
|
+
%w(foo bar).each do |local|
|
6
|
+
render :partial => 'foo/partial', :locals => { :local => local }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
render :partial => 'foo/partial', :locals => { :local => 'baz' }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class TemplateTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@view = @template = nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def view
|
9
|
+
@view ||= ActionView::Base.new(FIXTURES_PATH).tap do |view|
|
10
|
+
view.output_buffer = ActiveSupport::SafeBuffer.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def template
|
15
|
+
@template ||= Minimal::Template.new(view)
|
16
|
+
end
|
17
|
+
|
18
|
+
test "capturing a block" do
|
19
|
+
result = view.with_output_buffer do
|
20
|
+
view.concat('foo')
|
21
|
+
view.concat('bar')
|
22
|
+
'baz'
|
23
|
+
end
|
24
|
+
assert_equal 'foobar', result
|
25
|
+
end
|
26
|
+
|
27
|
+
test "capturing a helper with a block" do
|
28
|
+
block = lambda do
|
29
|
+
view.concat('foo')
|
30
|
+
view.concat('bar')
|
31
|
+
'baz'
|
32
|
+
end
|
33
|
+
result = view.content_tag(:div, &lambda { view.with_output_buffer(&block) })
|
34
|
+
assert_equal '<div>foobar</div>', result
|
35
|
+
end
|
36
|
+
|
37
|
+
test "call_view calling a non-concating helper without a block" do
|
38
|
+
result = template.send(:call_view, :number_with_precision, 1234)
|
39
|
+
assert_equal '1234.000', result
|
40
|
+
end
|
41
|
+
|
42
|
+
test "call_view calling a non-concating helper with a block" do
|
43
|
+
template.send(:call_view, :content_tag, :div) do
|
44
|
+
template << 'foo'
|
45
|
+
template << 'bar'
|
46
|
+
'baz'
|
47
|
+
end
|
48
|
+
assert_equal '<div>foobar</div>', view.output_buffer
|
49
|
+
end
|
50
|
+
|
51
|
+
test "call_view calling a concating helper with a block" do
|
52
|
+
template.send(:call_view, :form_for, 'foo', :url => '/foo') do |f|
|
53
|
+
template << f.text_field('foo')
|
54
|
+
template << f.text_field('bar')
|
55
|
+
'baz'
|
56
|
+
end
|
57
|
+
html = '<form action="/foo" method="post">' +
|
58
|
+
'<input id="foo_foo" name="foo[foo]" size="30" type="text" />' +
|
59
|
+
'<input id="foo_bar" name="foo[bar]" size="30" type="text" />' +
|
60
|
+
'</form>'
|
61
|
+
assert_equal html, view.output_buffer
|
62
|
+
end
|
63
|
+
|
64
|
+
test "simple render with local assigns" do
|
65
|
+
html = '<html><head></head><body><h1>plain</h1><p>local</p><div><div>nested</div></div></body></html>'
|
66
|
+
assert_equal html, view.render(:file => 'foo/simple', :locals => { :local => 'local' })
|
67
|
+
end
|
68
|
+
|
69
|
+
test "partial rendering" do
|
70
|
+
html = '<div><p>foo</p><p>bar</p></div><p>baz</p>'
|
71
|
+
assert_equal html, view.render(:file => 'foo/partial')
|
72
|
+
end
|
73
|
+
|
74
|
+
test "table" do
|
75
|
+
html = '<table><tr><td>foo</td><td>bar</td><td>baz</td></tr></table>'
|
76
|
+
assert_equal html, view.render(:file => 'foo/table')
|
77
|
+
end
|
78
|
+
|
79
|
+
test "form_tag with input_tags" do
|
80
|
+
html = '<div>foo</div>' +
|
81
|
+
'<form action="/foo" method="post">' +
|
82
|
+
'<div><input id="bar" name="bar" type="text" /></div>' +
|
83
|
+
'<input id="baz" name="baz" type="text" />' +
|
84
|
+
'</form>'
|
85
|
+
assert_equal html, view.render(:file => 'foo/form_tag')
|
86
|
+
end
|
87
|
+
|
88
|
+
test "form_for" do
|
89
|
+
html = '<div>foo</div>' +
|
90
|
+
'<form action="/foo" method="post">' +
|
91
|
+
'<div><input id="foo_bar" name="foo[bar]" size="30" type="text" /></div>' +
|
92
|
+
'<input id="foo_baz" name="foo[baz]" size="30" type="text" />' +
|
93
|
+
'</form>'
|
94
|
+
assert_equal html, view.render(:file => 'foo/form_for')
|
95
|
+
end
|
96
|
+
|
97
|
+
test "misc_helpers" do
|
98
|
+
html = '<img alt="Rails" src="http://no-asset-host.com/rails.png" />' +
|
99
|
+
"<pre class='debug_dump'>--- foo</pre>" +
|
100
|
+
'<script type="text/javascript">//<![CDATA[alert(\'All is good\')//]]></script>' +
|
101
|
+
'<div class="record" id="record_1">content</div>' +
|
102
|
+
'<br />' +
|
103
|
+
'<p>Hello world!</p>' +
|
104
|
+
'<p>Hello world!</p>' +
|
105
|
+
'<p><em>Hello world!</em></p>' +
|
106
|
+
'<p><em>Hello world!</em></p>' +
|
107
|
+
'<a href="#">foo</a>'
|
108
|
+
html
|
109
|
+
assert_equal html, view.render(:file => 'foo/misc_helpers').gsub("\n", '')
|
110
|
+
end
|
111
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
$: << File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'pp'
|
6
|
+
require 'minimal'
|
7
|
+
require 'action_controller'
|
8
|
+
require 'active_model'
|
9
|
+
|
10
|
+
Minimal::Template.send(:include, Minimal::Template::FormBuilderProxy)
|
11
|
+
|
12
|
+
ActionView::Template.register_template_handler('rb', Minimal::Template::Handler)
|
13
|
+
|
14
|
+
ActionView::Base.class_eval { def protect_against_forgery?; false end } # HAX
|
15
|
+
|
16
|
+
FIXTURES_PATH = File.expand_path('../fixtures/views', __FILE__)
|
17
|
+
|
18
|
+
class Record
|
19
|
+
def self.model_name; ActiveModel::Name.new(self) end
|
20
|
+
def id; 1 end
|
21
|
+
end
|
22
|
+
|
23
|
+
module TestMethod
|
24
|
+
def self.included(base)
|
25
|
+
base.class_eval do
|
26
|
+
def test(name, &block)
|
27
|
+
test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
|
28
|
+
defined = instance_method(test_name) rescue false
|
29
|
+
raise "#{test_name} is already defined in #{self}" if defined
|
30
|
+
if block_given?
|
31
|
+
define_method(test_name, &block)
|
32
|
+
else
|
33
|
+
define_method(test_name) do
|
34
|
+
flunk "No implementation provided for #{name}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Module
|
43
|
+
include TestMethod
|
44
|
+
end
|
45
|
+
|
46
|
+
class Test::Unit::TestCase
|
47
|
+
include TestMethod
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: minimal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sven Fuchs
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-03-08 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Minimal templating engine inspired by Markaby & Erector and targeted at Rails 3
|
17
|
+
email: svenfuchs@artweb-design.de
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.textile
|
24
|
+
files:
|
25
|
+
- README.textile
|
26
|
+
- Rakefile
|
27
|
+
- lib/minimal.rb
|
28
|
+
- lib/minimal/template.rb
|
29
|
+
- lib/minimal/template/form_builder_proxy.rb
|
30
|
+
- lib/minimal/version.rb
|
31
|
+
- test/fixtures/views/foo/_partial.rb
|
32
|
+
- test/fixtures/views/foo/form_for.rb
|
33
|
+
- test/fixtures/views/foo/form_tag.rb
|
34
|
+
- test/fixtures/views/foo/misc_helpers.rb
|
35
|
+
- test/fixtures/views/foo/partial.rb
|
36
|
+
- test/fixtures/views/foo/simple.rb
|
37
|
+
- test/fixtures/views/foo/table.rb
|
38
|
+
- test/template_test.rb
|
39
|
+
- test/test_helper.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/svenfuchs/minimal
|
42
|
+
licenses: []
|
43
|
+
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --charset=UTF-8
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 1.3.5
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: Minimal templating engine inspired by Markaby & Erector
|
68
|
+
test_files:
|
69
|
+
- test/fixtures/views/foo/_partial.rb
|
70
|
+
- test/fixtures/views/foo/form_for.rb
|
71
|
+
- test/fixtures/views/foo/form_tag.rb
|
72
|
+
- test/fixtures/views/foo/misc_helpers.rb
|
73
|
+
- test/fixtures/views/foo/partial.rb
|
74
|
+
- test/fixtures/views/foo/simple.rb
|
75
|
+
- test/fixtures/views/foo/table.rb
|
76
|
+
- test/template_test.rb
|
77
|
+
- test/test_helper.rb
|