minimal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ module Minimal
2
+ VERSION = "0.0.1"
3
+ end
data/lib/minimal.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'action_view'
2
+
3
+ module Minimal
4
+ autoload :Template, 'minimal/template'
5
+ autoload :Tidy, 'minimal/tidy'
6
+ end
@@ -0,0 +1,7 @@
1
+ module Foo
2
+ class Partial < Minimal::Template
3
+ def content
4
+ p local
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Foo
2
+ class FormFor < Minimal::Template
3
+ def content
4
+ div 'foo'
5
+ form_for 'foo', :url => '/foo' do |f|
6
+ div { f.text_field('bar') }
7
+ f.text_field('baz')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Foo
2
+ class FormTag < Minimal::Template
3
+ def content
4
+ div 'foo'
5
+ form_tag '/foo' do
6
+ div { text_field_tag('bar') }
7
+ text_field_tag('baz')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -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,18 @@
1
+ module Foo
2
+ class Simple < Minimal::Template
3
+ def content
4
+ html do
5
+ head
6
+ body do
7
+ h1 'plain'
8
+ bar
9
+ div { div 'nested' }
10
+ end
11
+ end
12
+ end
13
+
14
+ def bar
15
+ p escape_once(local)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ module Foo
2
+ class Table < Minimal::Template
3
+ def content
4
+ table do
5
+ tr do
6
+ %w(foo bar baz).each { |text| td text }
7
+ end
8
+ end
9
+ end
10
+ end
11
+ 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
@@ -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