markaby 0.5 → 0.6.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/CHANGELOG.rdoc +79 -0
- data/Markaby.gemspec +103 -0
- data/{README → README.rdoc} +14 -6
- data/Rakefile +71 -14
- data/VERSION +1 -0
- data/garlic.rb +29 -0
- data/init.rb +6 -0
- data/lib/markaby.rb +4 -9
- data/lib/markaby/builder.rb +156 -143
- data/lib/markaby/builder_tags.rb +64 -0
- data/lib/markaby/cssproxy.rb +36 -34
- data/lib/markaby/kernel_method.rb +7 -0
- data/lib/markaby/rails.rb +64 -39
- data/lib/markaby/rails/current.rb +46 -0
- data/lib/markaby/rails/deprecated.rb +124 -0
- data/lib/markaby/rails/rails_builder.rb +50 -0
- data/lib/markaby/tags.rb +158 -130
- data/lib/markaby/tilt.rb +21 -0
- data/spec/markaby/builder_spec.rb +118 -0
- data/spec/markaby/css_proxy_spec.rb +47 -0
- data/spec/markaby/fragment_spec.rb +10 -0
- data/spec/markaby/markaby_other_static.mab +1 -0
- data/spec/markaby/markaby_spec.rb +232 -0
- data/spec/markaby/rails/spec_helper.rb +21 -0
- data/spec/markaby/rails/views/markaby/_a_partial.mab +3 -0
- data/spec/markaby/rails/views/markaby/_partial_child_with_locals.mab +1 -0
- data/spec/markaby/rails/views/markaby/access_to_helpers.mab +1 -0
- data/spec/markaby/rails/views/markaby/broken.mab +7 -0
- data/spec/markaby/rails/views/markaby/correct_template_values.mab +5 -0
- data/spec/markaby/rails/views/markaby/form_for.mab +2 -0
- data/spec/markaby/rails/views/markaby/form_for_with_fields.mab +3 -0
- data/spec/markaby/rails/views/markaby/form_for_with_multiple_fields.mab +4 -0
- data/spec/markaby/rails/views/markaby/no_values_passed.mab +3 -0
- data/spec/markaby/rails/views/markaby/partial_parent.mab +1 -0
- data/spec/markaby/rails/views/markaby/partial_parent_with_locals.mab +7 -0
- data/spec/markaby/rails/views/markaby/render_erb_without_explicit_render_call.erb +1 -0
- data/spec/markaby/rails/views/markaby/render_explicit_but_empty_markaby_layout.mab +0 -0
- data/spec/markaby/rails/views/markaby/render_mab_without_explicit_render_call.mab +3 -0
- data/spec/markaby/rails/views/markaby/render_with_ivar.mab +3 -0
- data/spec/markaby/rails/views/markaby/renders_erb.rhtml +1 -0
- data/spec/markaby/rails_spec.rb +249 -0
- data/spec/markaby/rails_version_spec.rb +37 -0
- data/spec/markaby/tilt/erb.erb +1 -0
- data/spec/markaby/tilt/locals.mab +1 -0
- data/spec/markaby/tilt/markaby.mab +1 -0
- data/spec/markaby/tilt/markaby_other_static.mab +1 -0
- data/spec/markaby/tilt/render_twice.mab +1 -0
- data/spec/markaby/tilt/scope.mab +1 -0
- data/spec/markaby/tilt/yielding.mab +2 -0
- data/spec/markaby/tilt_spec.rb +86 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +39 -0
- metadata +132 -52
- data/lib/markaby/metaid.rb +0 -16
- data/lib/markaby/template.rb +0 -12
- data/setup.rb +0 -1551
- data/test/test_markaby.rb +0 -109
- data/tools/rakehelp.rb +0 -106
data/.gitignore
ADDED
data/CHANGELOG.rdoc
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
= 0.6.6
|
2
|
+
|
3
|
+
* ruby 1.9.1 support. Closes Github Issues #10 & #11.
|
4
|
+
* Removed Tilt deprecation warnings
|
5
|
+
|
6
|
+
= 0.6.4
|
7
|
+
|
8
|
+
* Fixed a bug in which direct string values to Markaby::Builder wouldn't evaluate:
|
9
|
+
Markaby::Builder.new { 'foo' }.to_s #=> "foo"
|
10
|
+
|
11
|
+
* Fix critical bug with form_for, which was raising an error
|
12
|
+
* Introduce proxy object for form_for:
|
13
|
+
|
14
|
+
form_for :foo do |f|
|
15
|
+
f.text_field :bar
|
16
|
+
f.text_field :baz
|
17
|
+
end
|
18
|
+
|
19
|
+
* Remove support for rails 2.1.x series. We'll accept patches for them, if anyone cares enough.
|
20
|
+
|
21
|
+
== 0.6.2 / 0.6.3
|
22
|
+
|
23
|
+
* Add basic support for the Tilt templating engine (used with Sinatra):
|
24
|
+
|
25
|
+
require 'markaby'
|
26
|
+
require 'markaby/tilt'
|
27
|
+
|
28
|
+
== 0.6.1
|
29
|
+
|
30
|
+
* Support the following rails versions:
|
31
|
+
1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 2.1.0, 2.1.1, 2.1.2, 2.2.0,
|
32
|
+
2.2.1, 2.2.2, 2.2.3, 2.3.1, 2.3.2, 2.3.2.1, 2.3.3, 2.3.3.1, 2.3.4
|
33
|
+
* Only run rails tests when inside a rails plugins
|
34
|
+
* Run tests of the various versions of rails with garlic
|
35
|
+
* Start conversion to rspec. Use test/spec temporarily until conversion is done.
|
36
|
+
|
37
|
+
= 0.6
|
38
|
+
=== 23 August, 2009
|
39
|
+
|
40
|
+
* Canonical repo changed to http://github.com/joho/markaby
|
41
|
+
* Gem moved to Github (using jeweler)
|
42
|
+
* Rails init process changed to work with rails > 2.1
|
43
|
+
* Default attributes on the root (<html>) element can now be overidden
|
44
|
+
* Reworked CssProxy, allowing attributes on hr and br
|
45
|
+
* Added Kernel#mab convenience method (require 'markaby/kernel_method')
|
46
|
+
* WhenOnRails: Can now use :locals with render_markaby
|
47
|
+
* WhenOnRails: Template errors now report line number
|
48
|
+
|
49
|
+
= 0.5
|
50
|
+
=== 03 October, 2006
|
51
|
+
|
52
|
+
* XHTML Validation built in. So, if you have an invalid tag: error. Invalid attribute: error.
|
53
|
+
And two identical IDs in the same document: error. Optional, of course. But handy!
|
54
|
+
* New Markaby::Fragment class adds much flexibility. If it discovers you are using a tag as a string,
|
55
|
+
the tag is removed from the stream. (<tt>div { strong("Real") + " Giraffes" }</tt>)
|
56
|
+
* The prevailing rule now is: if you want it escaped, pass it as an arg. If not, pass it to a block.
|
57
|
+
* Again, escaped: <tt>h1("Me & You Have a Giraffe")</tt>
|
58
|
+
* And, not escaped: <tt>h1 { "<a href='/'>Home</a>" }</tt>
|
59
|
+
* Less method_missing, meaning: faster calls all around. Tag methods generated based on doctype.
|
60
|
+
* The <tt>html</tt> method doesn't write the doctype tags and meta tags. You must use <tt>xhtml_transitional</tt> or <tt>xhtml_strict</tt> methods to do that.
|
61
|
+
* The <tt>img</tt> method doesn't try to inject an empty alt tag and a zero border. No more of that.
|
62
|
+
|
63
|
+
= 0.3
|
64
|
+
=== 02nd February, 2006
|
65
|
+
|
66
|
+
* Allow Markaby::Builder.new without args.
|
67
|
+
* Rails helper method render_markaby.
|
68
|
+
|
69
|
+
= 0.2
|
70
|
+
=== 17th January, 2006
|
71
|
+
|
72
|
+
* Public announcement.
|
73
|
+
* DOCTYPES, head tags.
|
74
|
+
* Works with Rails helpers.
|
75
|
+
|
76
|
+
= 0.1
|
77
|
+
=== 05th January, 2006
|
78
|
+
|
79
|
+
* Initial import.
|
data/Markaby.gemspec
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{markaby}
|
8
|
+
s.version = "0.6.6"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["_why", "Tim Fletcher", "John Barton", "spox", "smtlaissezfaire"]
|
12
|
+
s.date = %q{2010-06-02}
|
13
|
+
s.description = %q{Tim Fletcher and _why's ruby driven HTML templating system}
|
14
|
+
s.email = %q{scott@railsnewbie.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"CHANGELOG.rdoc",
|
21
|
+
"Markaby.gemspec",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"garlic.rb",
|
26
|
+
"init.rb",
|
27
|
+
"lib/markaby.rb",
|
28
|
+
"lib/markaby/builder.rb",
|
29
|
+
"lib/markaby/builder_tags.rb",
|
30
|
+
"lib/markaby/cssproxy.rb",
|
31
|
+
"lib/markaby/kernel_method.rb",
|
32
|
+
"lib/markaby/rails.rb",
|
33
|
+
"lib/markaby/rails/current.rb",
|
34
|
+
"lib/markaby/rails/deprecated.rb",
|
35
|
+
"lib/markaby/rails/rails_builder.rb",
|
36
|
+
"lib/markaby/tags.rb",
|
37
|
+
"lib/markaby/tilt.rb",
|
38
|
+
"spec/markaby/builder_spec.rb",
|
39
|
+
"spec/markaby/css_proxy_spec.rb",
|
40
|
+
"spec/markaby/fragment_spec.rb",
|
41
|
+
"spec/markaby/markaby_other_static.mab",
|
42
|
+
"spec/markaby/markaby_spec.rb",
|
43
|
+
"spec/markaby/rails/spec_helper.rb",
|
44
|
+
"spec/markaby/rails/views/markaby/_a_partial.mab",
|
45
|
+
"spec/markaby/rails/views/markaby/_partial_child_with_locals.mab",
|
46
|
+
"spec/markaby/rails/views/markaby/access_to_helpers.mab",
|
47
|
+
"spec/markaby/rails/views/markaby/broken.mab",
|
48
|
+
"spec/markaby/rails/views/markaby/correct_template_values.mab",
|
49
|
+
"spec/markaby/rails/views/markaby/form_for.mab",
|
50
|
+
"spec/markaby/rails/views/markaby/form_for_with_fields.mab",
|
51
|
+
"spec/markaby/rails/views/markaby/form_for_with_multiple_fields.mab",
|
52
|
+
"spec/markaby/rails/views/markaby/no_values_passed.mab",
|
53
|
+
"spec/markaby/rails/views/markaby/partial_parent.mab",
|
54
|
+
"spec/markaby/rails/views/markaby/partial_parent_with_locals.mab",
|
55
|
+
"spec/markaby/rails/views/markaby/render_erb_without_explicit_render_call.erb",
|
56
|
+
"spec/markaby/rails/views/markaby/render_explicit_but_empty_markaby_layout.mab",
|
57
|
+
"spec/markaby/rails/views/markaby/render_mab_without_explicit_render_call.mab",
|
58
|
+
"spec/markaby/rails/views/markaby/render_with_ivar.mab",
|
59
|
+
"spec/markaby/rails/views/markaby/renders_erb.rhtml",
|
60
|
+
"spec/markaby/rails_spec.rb",
|
61
|
+
"spec/markaby/rails_version_spec.rb",
|
62
|
+
"spec/markaby/tilt/erb.erb",
|
63
|
+
"spec/markaby/tilt/locals.mab",
|
64
|
+
"spec/markaby/tilt/markaby.mab",
|
65
|
+
"spec/markaby/tilt/markaby_other_static.mab",
|
66
|
+
"spec/markaby/tilt/render_twice.mab",
|
67
|
+
"spec/markaby/tilt/scope.mab",
|
68
|
+
"spec/markaby/tilt/yielding.mab",
|
69
|
+
"spec/markaby/tilt_spec.rb",
|
70
|
+
"spec/spec.opts",
|
71
|
+
"spec/spec_helper.rb"
|
72
|
+
]
|
73
|
+
s.homepage = %q{http://joho.github.com/markaby/}
|
74
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
75
|
+
s.require_paths = ["lib"]
|
76
|
+
s.rubygems_version = %q{1.3.7}
|
77
|
+
s.summary = %q{Markup as Ruby, write HTML in your native Ruby tongue}
|
78
|
+
s.test_files = [
|
79
|
+
"spec/markaby/builder_spec.rb",
|
80
|
+
"spec/markaby/css_proxy_spec.rb",
|
81
|
+
"spec/markaby/fragment_spec.rb",
|
82
|
+
"spec/markaby/markaby_spec.rb",
|
83
|
+
"spec/markaby/rails/spec_helper.rb",
|
84
|
+
"spec/markaby/rails_spec.rb",
|
85
|
+
"spec/markaby/rails_version_spec.rb",
|
86
|
+
"spec/markaby/tilt_spec.rb",
|
87
|
+
"spec/spec_helper.rb"
|
88
|
+
]
|
89
|
+
|
90
|
+
if s.respond_to? :specification_version then
|
91
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
92
|
+
s.specification_version = 3
|
93
|
+
|
94
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
95
|
+
s.add_runtime_dependency(%q<builder>, [">= 2.0.0"])
|
96
|
+
else
|
97
|
+
s.add_dependency(%q<builder>, [">= 2.0.0"])
|
98
|
+
end
|
99
|
+
else
|
100
|
+
s.add_dependency(%q<builder>, [">= 2.0.0"])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
data/{README → README.rdoc}
RENAMED
@@ -14,14 +14,20 @@ Write Rails templates in pure Ruby. Example layout:
|
|
14
14
|
title 'Products: ' + action_name
|
15
15
|
stylesheet_link_tag 'scaffold'
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
body do
|
19
19
|
p flash[:notice], :style => "color: green"
|
20
|
-
|
20
|
+
|
21
21
|
self << content_for_layout
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
Markaby supports many versions of rails:
|
26
|
+
|
27
|
+
1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 2.2.0,
|
28
|
+
2.2.1, 2.2.2, 2.2.3, 2.3.1, 2.3.2, 2.3.2.1,
|
29
|
+
2.3.3, 2.3.3.1, 2.3.4
|
30
|
+
|
25
31
|
== Using Markaby as a Ruby class
|
26
32
|
|
27
33
|
Markaby is flaming easy to call from your Ruby classes.
|
@@ -69,7 +75,7 @@ that inside these blocks, <tt>self</tt> will be your Markaby::Builder object.
|
|
69
75
|
When you use instance variables in these blocks, they will be instance variables
|
70
76
|
of the Markaby::Builder object.
|
71
77
|
|
72
|
-
This doesn't
|
78
|
+
This doesn't affect Rails users, but when used in regular Ruby code, it can
|
73
79
|
be a bit disorienting. You are recommended to put your Markaby code in a
|
74
80
|
module where it won't mix with anything.
|
75
81
|
|
@@ -115,7 +121,7 @@ Which results in:
|
|
115
121
|
</div>
|
116
122
|
</div>
|
117
123
|
|
118
|
-
== 3. Validate Your XHTML 1.0 Output
|
124
|
+
== 3. Validate Your XHTML 1.0 Output
|
119
125
|
|
120
126
|
If you'd like Markaby to help you assemble valid XHTML documents,
|
121
127
|
you can use the <tt>xhtml_transitional</tt> or <tt>xhtml_strict</tt>
|
@@ -209,7 +215,7 @@ won't work with this technique.
|
|
209
215
|
|
210
216
|
= A Note About Rails Helpers
|
211
217
|
|
212
|
-
When used in Rails templates, the Rails helper object is passed into
|
218
|
+
When used in Rails templates, the Rails helper object is passed into
|
213
219
|
Markaby::Builder. When you call helper methods inside Markaby, the output
|
214
220
|
from those methods will be output to the stream. This is incredibly
|
215
221
|
handy, since most Rails helpers output HTML tags.
|
@@ -231,7 +237,7 @@ If for any reason you have trouble with fragments, you can just
|
|
231
237
|
call the <tt>@helpers</tt> object with the method and you'll get
|
232
238
|
the String back and nothing will be output.
|
233
239
|
|
234
|
-
p { "Total is: #{@
|
240
|
+
p { "Total is: #{@helpers.number_to_human_size @file_bytes}" }
|
235
241
|
|
236
242
|
Conversely, you may call instance variables from your controller by using
|
237
243
|
a method and its value will be returned, nothing will be output.
|
@@ -249,7 +255,9 @@ a method and its value will be returned, nothing will be output.
|
|
249
255
|
= Credits
|
250
256
|
|
251
257
|
Markaby is a work of immense hope by Tim Fletcher and why the lucky stiff.
|
258
|
+
It is maintained by joho, spox, and smtlaissezfaire.
|
252
259
|
Thankyou for giving it a whirl.
|
253
260
|
|
254
261
|
Markaby is inspired by the HTML library within cgi.rb. Hopefully it will
|
255
262
|
turn around and take some cues.
|
263
|
+
|
data/Rakefile
CHANGED
@@ -1,20 +1,77 @@
|
|
1
1
|
require 'rake'
|
2
|
-
require 'rake/
|
2
|
+
require 'spec/rake/spectask'
|
3
3
|
require 'rake/clean'
|
4
|
-
require 'rake/gempackagetask'
|
5
|
-
require 'rake/rdoctask'
|
6
|
-
require 'tools/rakehelp'
|
7
|
-
require 'fileutils'
|
8
|
-
include FileUtils
|
9
4
|
|
10
|
-
|
11
|
-
|
5
|
+
begin
|
6
|
+
require 'hanna/rdoctask'
|
12
7
|
|
13
|
-
|
8
|
+
Rake::RDocTask.new do |rdoc|
|
9
|
+
rdoc.rdoc_dir = 'doc/rdoc'
|
10
|
+
rdoc.options << '--line-numbers'
|
11
|
+
rdoc.rdoc_files.add(['README.rdoc', 'CHANGELOG.rdoc', 'lib/**/*.rb'])
|
12
|
+
end
|
13
|
+
rescue LoadError
|
14
|
+
puts "Could not load hanna-rdoc. Please install with mislav-hanna package"
|
15
|
+
end
|
14
16
|
|
15
|
-
|
16
|
-
setup_rdoc ['README', 'CHANGELOG', 'lib/**/*.rb']
|
17
|
+
task :default => :spec
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
desc 'Run the specs'
|
20
|
+
Spec::Rake::SpecTask.new do |t|
|
21
|
+
t.warning = false
|
22
|
+
t.spec_opts = ["--color"]
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
require 'jeweler'
|
27
|
+
|
28
|
+
Jeweler::Tasks.new do |gemspec|
|
29
|
+
gemspec.name = "markaby"
|
30
|
+
gemspec.summary = "Markup as Ruby, write HTML in your native Ruby tongue"
|
31
|
+
gemspec.description = "Tim Fletcher and _why's ruby driven HTML templating system"
|
32
|
+
gemspec.email = "scott@railsnewbie.com"
|
33
|
+
gemspec.homepage = "http://joho.github.com/markaby/"
|
34
|
+
gemspec.authors = ["_why", "Tim Fletcher", "John Barton", "spox", "smtlaissezfaire"]
|
35
|
+
gemspec.add_dependency 'builder', '>=2.0.0'
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "List any Markaby specific warnings"
|
42
|
+
task :warnings do
|
43
|
+
`ruby -w test/test_markaby.rb 2>&1`.split(/\n/).each do |line|
|
44
|
+
next unless line =~ /warning:/
|
45
|
+
next if line =~ /builder-/
|
46
|
+
puts line
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Start a Markaby-aware IRB session"
|
51
|
+
task :irb do
|
52
|
+
sh 'irb -I lib -r markaby -r markaby/kernel_method'
|
53
|
+
end
|
54
|
+
|
55
|
+
namespace :gemspec do
|
56
|
+
task :commit do
|
57
|
+
sh "git add ."
|
58
|
+
sh "git commit -m 'Update gemspec'"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
namespace :release do
|
63
|
+
task :patch => [:spec, "version:bump:patch", :update_gemspec, :rerdoc, :tag_release, :build, :push_tags]
|
64
|
+
|
65
|
+
task :update_gemspec => ["gemspec:generate", "gemspec:validate", "gemspec:commit"]
|
66
|
+
task :tag_release do
|
67
|
+
require File.dirname(__FILE__) + "/lib/markaby"
|
68
|
+
version = "v#{Markaby::VERSION}"
|
69
|
+
sh "git tag #{version}"
|
70
|
+
end
|
71
|
+
|
72
|
+
task :push_tags do
|
73
|
+
sh "git push --tags"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
task :release => "release:patch"
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.6.6
|
data/garlic.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/markaby/rails")
|
2
|
+
|
3
|
+
garlic do
|
4
|
+
# this plugin
|
5
|
+
repo "markaby", :path => '.'
|
6
|
+
|
7
|
+
# other repos
|
8
|
+
repo "rails", :url => "git://github.com/rails/rails"
|
9
|
+
|
10
|
+
# target railses
|
11
|
+
RAILS_TAREGETS = Markaby::Rails::SUPPORTED_RAILS_VERSIONS.map do |version|
|
12
|
+
"v#{version}"
|
13
|
+
end
|
14
|
+
|
15
|
+
RAILS_TAREGETS.each do |rails|
|
16
|
+
# declare how to prepare, and run each CI target
|
17
|
+
target "Rails: #{rails}", :tree_ish => rails do
|
18
|
+
prepare do
|
19
|
+
plugin "markaby", :clone => true # so we can work in targets
|
20
|
+
end
|
21
|
+
|
22
|
+
run do
|
23
|
+
cd "vendor/plugins/markaby" do
|
24
|
+
sh "rake"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/init.rb
ADDED
data/lib/markaby.rb
CHANGED
@@ -8,7 +8,7 @@ $:.unshift File.expand_path(File.dirname(__FILE__))
|
|
8
8
|
|
9
9
|
# Markaby is a module containing all of the great Markaby classes that
|
10
10
|
# do such an excellent job.
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# * Markaby::Builder: the class for actually calling the Ruby methods
|
13
13
|
# which write the HTML.
|
14
14
|
# * Markaby::CSSProxy: a class which adds element classes and IDs to
|
@@ -19,17 +19,12 @@ $:.unshift File.expand_path(File.dirname(__FILE__))
|
|
19
19
|
# * Markaby::Template: a class for hooking Markaby into Rails as a
|
20
20
|
# proper templating language.
|
21
21
|
module Markaby
|
22
|
-
|
22
|
+
version_file = File.expand_path(File.dirname(__FILE__) + "/../VERSION")
|
23
|
+
VERSION = File.read(version_file).strip
|
23
24
|
|
24
25
|
class InvalidXhtmlError < Exception; end
|
25
26
|
end
|
26
27
|
|
27
|
-
unless defined?(Builder)
|
28
|
-
require 'rubygems'
|
29
|
-
require 'builder'
|
30
|
-
end
|
31
|
-
|
28
|
+
require 'builder' unless defined?(Builder)
|
32
29
|
require 'markaby/builder'
|
33
30
|
require 'markaby/cssproxy'
|
34
|
-
require 'markaby/metaid'
|
35
|
-
require 'markaby/template'
|
data/lib/markaby/builder.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'markaby/tags'
|
2
|
+
require 'markaby/builder_tags'
|
2
3
|
|
3
4
|
module Markaby
|
5
|
+
RUBY_VERSION_ID = RUBY_VERSION.split(".").join.to_i
|
6
|
+
|
4
7
|
# The Markaby::Builder class is the central gear in the system. When using
|
5
8
|
# from Ruby code, this is the only class you need to instantiate directly.
|
6
9
|
#
|
@@ -19,33 +22,49 @@ module Markaby
|
|
19
22
|
# puts mab.to_s
|
20
23
|
#
|
21
24
|
class Builder
|
25
|
+
include Markaby::BuilderTags
|
22
26
|
|
23
|
-
|
24
|
-
:indent
|
25
|
-
:output_helpers
|
27
|
+
DEFAULT_OPTIONS = {
|
28
|
+
:indent => 0,
|
29
|
+
:output_helpers => true,
|
26
30
|
:output_xml_instruction => true,
|
27
|
-
:output_meta_tag
|
28
|
-
:auto_validation
|
29
|
-
:tagset
|
31
|
+
:output_meta_tag => true,
|
32
|
+
:auto_validation => true,
|
33
|
+
:tagset => Markaby::XHTMLTransitional,
|
34
|
+
:root_attributes => {
|
35
|
+
:xmlns => 'http://www.w3.org/1999/xhtml',
|
36
|
+
:'xml:lang' => 'en',
|
37
|
+
:lang => 'en'
|
38
|
+
}
|
30
39
|
}
|
31
40
|
|
41
|
+
@@options = DEFAULT_OPTIONS.dup
|
42
|
+
|
43
|
+
def self.restore_defaults!
|
44
|
+
@@options = DEFAULT_OPTIONS.dup
|
45
|
+
end
|
46
|
+
|
32
47
|
def self.set(option, value)
|
33
|
-
@@
|
48
|
+
@@options[option] = value
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.get(option)
|
52
|
+
@@options[option]
|
34
53
|
end
|
35
54
|
|
36
|
-
def self.ignored_helpers
|
37
|
-
@@ignored_helpers ||= []
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.ignore_helpers(*helpers)
|
41
|
-
ignored_helpers.concat helpers
|
42
|
-
end
|
55
|
+
def self.ignored_helpers
|
56
|
+
@@ignored_helpers ||= []
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.ignore_helpers(*helpers)
|
60
|
+
ignored_helpers.concat helpers
|
61
|
+
end
|
43
62
|
|
44
63
|
attr_accessor :output_helpers, :tagset
|
45
64
|
|
46
65
|
# Create a Markaby builder object. Pass in a hash of variable assignments to
|
47
66
|
# +assigns+ which will be available as instance variables inside tag construction
|
48
|
-
# blocks. If an object is passed in to +
|
67
|
+
# blocks. If an object is passed in to +helper+, its methods will be available
|
49
68
|
# from those same blocks.
|
50
69
|
#
|
51
70
|
# Pass in a +block+ to new and the block will be evaluated.
|
@@ -58,40 +77,43 @@ module Markaby
|
|
58
77
|
# end
|
59
78
|
# }
|
60
79
|
#
|
61
|
-
def initialize(assigns = {},
|
62
|
-
@streams = [
|
63
|
-
@assigns = assigns
|
64
|
-
@
|
80
|
+
def initialize(assigns = {}, helper = nil, &block)
|
81
|
+
@streams = [Stream.new]
|
82
|
+
@assigns = assigns.dup
|
83
|
+
@_helper = helper
|
84
|
+
@used_ids = {}
|
65
85
|
|
66
|
-
@@
|
67
|
-
instance_variable_set("@#{k}", @assigns
|
86
|
+
@@options.each do |k, v|
|
87
|
+
instance_variable_set("@#{k}", @assigns.delete(k) || v)
|
68
88
|
end
|
69
89
|
|
70
|
-
|
71
|
-
|
72
|
-
else
|
73
|
-
@helpers = helpers.dup
|
74
|
-
for iv in helpers.instance_variables
|
75
|
-
instance_variable_set(iv, helpers.instance_variable_get(iv))
|
76
|
-
end
|
90
|
+
@assigns.each do |k, v|
|
91
|
+
instance_variable_set("@#{k}", v)
|
77
92
|
end
|
78
93
|
|
79
|
-
|
80
|
-
for iv, val in assigns
|
81
|
-
instance_variable_set("@#{iv}", val)
|
82
|
-
unless @helpers.nil?
|
83
|
-
@helpers.instance_variable_set("@#{iv}", val)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
94
|
+
@builder = XmlMarkup.new(:indent => @indent, :target => @streams.last)
|
87
95
|
|
88
|
-
|
89
|
-
|
90
|
-
attr_accessor :target, :level
|
91
|
-
end
|
96
|
+
text(capture(&block)) if block
|
97
|
+
end
|
92
98
|
|
93
|
-
|
94
|
-
|
99
|
+
def helper=(helper)
|
100
|
+
@_helper = helper
|
101
|
+
end
|
102
|
+
|
103
|
+
def metaclass(&block)
|
104
|
+
metaclass = class << self; self; end
|
105
|
+
metaclass.class_eval(&block)
|
106
|
+
end
|
107
|
+
|
108
|
+
private :metaclass
|
109
|
+
|
110
|
+
def locals=(locals)
|
111
|
+
locals.each do |key, value|
|
112
|
+
metaclass do
|
113
|
+
define_method key do
|
114
|
+
value
|
115
|
+
end
|
116
|
+
end
|
95
117
|
end
|
96
118
|
end
|
97
119
|
|
@@ -102,29 +124,26 @@ module Markaby
|
|
102
124
|
|
103
125
|
# Write a +string+ to the HTML stream without escaping it.
|
104
126
|
def text(string)
|
105
|
-
@builder <<
|
127
|
+
@builder << string.to_s
|
106
128
|
nil
|
107
129
|
end
|
108
130
|
alias_method :<<, :text
|
109
131
|
alias_method :concat, :text
|
110
132
|
|
111
|
-
# Emulate ERB to satisfy helpers like <tt>form_for</tt>.
|
112
|
-
def _erbout; self end
|
113
|
-
|
114
133
|
# Captures the HTML code built inside the +block+. This is done by creating a new
|
115
134
|
# stream for the builder object, running the block and passing back its stream as a string.
|
116
135
|
#
|
117
136
|
# >> Markaby::Builder.new.capture { h1 "TEST"; h2 "CAPTURE ME" }
|
118
|
-
# => "<h1>
|
137
|
+
# => "<h1>TEST</h1><h2>CAPTURE ME</h2>"
|
119
138
|
#
|
120
139
|
def capture(&block)
|
121
|
-
@streams.push(builder.target =
|
140
|
+
@streams.push(@builder.target = Stream.new)
|
122
141
|
@builder.level += 1
|
123
142
|
str = instance_eval(&block)
|
124
143
|
str = @streams.last.join if @streams.last.any?
|
125
144
|
@streams.pop
|
126
145
|
@builder.level -= 1
|
127
|
-
builder.target = @streams.last
|
146
|
+
@builder.target = @streams.last
|
128
147
|
str
|
129
148
|
end
|
130
149
|
|
@@ -132,35 +151,43 @@ module Markaby
|
|
132
151
|
# the arguments are the same as the tags implemented via method_missing.
|
133
152
|
def tag!(tag, *args, &block)
|
134
153
|
ele_id = nil
|
135
|
-
if @auto_validation
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
154
|
+
if @auto_validation && @tagset
|
155
|
+
if !@tagset.tagset.has_key?(tag)
|
156
|
+
raise InvalidXhtmlError, "no element `#{tag}' for #{tagset.doctype}"
|
157
|
+
elsif args.last.respond_to?(:to_hash)
|
158
|
+
attrs = args.last.to_hash
|
159
|
+
|
160
|
+
if @tagset.forms.include?(tag) && attrs[:id]
|
161
|
+
attrs[:name] ||= attrs[:id]
|
162
|
+
end
|
163
|
+
|
164
|
+
attrs.each do |k, v|
|
165
|
+
atname = k.to_s.downcase.intern
|
166
|
+
unless k =~ /:/ or @tagset.tagset[tag].include? atname
|
167
|
+
raise InvalidXhtmlError, "no attribute `#{k}' on #{tag} elements"
|
168
|
+
end
|
169
|
+
if atname == :id
|
170
|
+
ele_id = v.to_s
|
171
|
+
if @used_ids.has_key? ele_id
|
172
|
+
raise InvalidXhtmlError, "id `#{ele_id}' already used (id's must be unique)."
|
151
173
|
end
|
174
|
+
end
|
152
175
|
end
|
176
|
+
end
|
153
177
|
end
|
178
|
+
|
154
179
|
if block
|
155
|
-
str = capture
|
180
|
+
str = capture(&block)
|
156
181
|
block = proc { text(str) }
|
157
182
|
end
|
158
183
|
|
159
184
|
f = fragment { @builder.method_missing(tag, *args, &block) }
|
160
|
-
@
|
185
|
+
@used_ids[ele_id] = f if ele_id
|
161
186
|
f
|
162
187
|
end
|
163
188
|
|
189
|
+
private
|
190
|
+
|
164
191
|
# This method is used to intercept calls to helper methods and instance
|
165
192
|
# variables. Here is the order of interception:
|
166
193
|
#
|
@@ -175,95 +202,61 @@ module Markaby
|
|
175
202
|
# method_missing used to be the lynchpin in Markaby, but it's no longer used to handle
|
176
203
|
# HTML tags. See html_tag for that.
|
177
204
|
def method_missing(sym, *args, &block)
|
178
|
-
if @
|
179
|
-
r = @
|
180
|
-
if @output_helpers
|
205
|
+
if @_helper.respond_to?(sym, true) && !self.class.ignored_helpers.include?(sym)
|
206
|
+
r = @_helper.send(sym, *args, &block)
|
207
|
+
if @output_helpers && r.respond_to?(:to_str)
|
181
208
|
fragment { @builder << r }
|
182
209
|
else
|
183
210
|
r
|
184
211
|
end
|
185
|
-
elsif
|
212
|
+
elsif @assigns.has_key?(sym)
|
213
|
+
@assigns[sym]
|
214
|
+
elsif @assigns.has_key?(stringy_key = sym.to_s)
|
215
|
+
# Rails' ActionView assigns hash has string keys for
|
216
|
+
# instance variables that are defined in the controller.
|
217
|
+
@assigns[stringy_key]
|
218
|
+
elsif instance_variables_for(self).include?(ivar = "@#{sym}".to_sym)
|
219
|
+
instance_variable_get(ivar)
|
220
|
+
elsif @_helper && instance_variables_for(@_helper).include?(ivar)
|
221
|
+
@_helper.instance_variable_get(ivar)
|
222
|
+
elsif instance_methods_for(::Builder::XmlMarkup).include?(sym)
|
186
223
|
@builder.__send__(sym, *args, &block)
|
187
|
-
elsif
|
188
|
-
instance_variable_get("@#{sym}")
|
189
|
-
elsif @tagset.nil?
|
224
|
+
elsif !@tagset
|
190
225
|
tag!(sym, *args, &block)
|
191
226
|
else
|
192
|
-
|
227
|
+
super
|
193
228
|
end
|
194
229
|
end
|
195
230
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
#
|
200
|
-
# If the @auto_validation setting is on, this method will check for many common mistakes which
|
201
|
-
# could lead to invalid XHTML.
|
202
|
-
def html_tag(sym, *args, &block)
|
203
|
-
if @auto_validation and @tagset.self_closing.include?(sym) and block
|
204
|
-
raise InvalidXhtmlError, "the `\#{sym}' element is self-closing, please remove the block"
|
231
|
+
if RUBY_VERSION_ID >= 191
|
232
|
+
def instance_variables_for(obj)
|
233
|
+
obj.instance_variables
|
205
234
|
end
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
args.last[:name] ||= args.last[:id]
|
210
|
-
end
|
211
|
-
tag!(sym, *args, &block)
|
212
|
-
end
|
235
|
+
|
236
|
+
def instance_methods_for(obj)
|
237
|
+
obj.instance_methods
|
213
238
|
end
|
214
|
-
|
215
|
-
|
239
|
+
else
|
240
|
+
def instance_variables_for(obj)
|
241
|
+
obj.instance_variables.map { |var| var.to_sym }
|
216
242
|
end
|
217
|
-
tag!(sym, *args, &block)
|
218
|
-
end
|
219
243
|
|
220
|
-
|
221
|
-
|
222
|
-
def #{k}(*args, &block)
|
223
|
-
html_tag(#{k.inspect}, *args, &block)
|
224
|
-
end
|
225
|
-
}
|
226
|
-
end
|
227
|
-
|
228
|
-
# Builds a head tag. Adds a <tt>meta</tt> tag inside with Content-Type
|
229
|
-
# set to <tt>text/html; charset=utf-8</tt>.
|
230
|
-
def head(*args, &block)
|
231
|
-
tag!(:head, *args) do
|
232
|
-
tag!(:meta, "http-equiv" => "Content-Type", "content" => "text/html; charset=utf-8") if @output_meta_tag
|
233
|
-
instance_eval(&block)
|
244
|
+
def instance_methods_for(obj)
|
245
|
+
obj.instance_methods.map { |m| m.to_sym }
|
234
246
|
end
|
235
247
|
end
|
236
248
|
|
237
|
-
# Builds an html tag. An XML 1.0 instruction and an XHTML 1.0 Transitional doctype
|
238
|
-
# are prepended. Also assumes <tt>:xmlns => "http://www.w3.org/1999/xhtml",
|
239
|
-
# :lang => "en"</tt>.
|
240
|
-
def xhtml_transitional(&block)
|
241
|
-
self.tagset = Markaby::XHTMLTransitional
|
242
|
-
xhtml_html &block
|
243
|
-
end
|
244
|
-
|
245
|
-
# Builds an html tag with XHTML 1.0 Strict doctype instead.
|
246
|
-
def xhtml_strict(&block)
|
247
|
-
self.tagset = Markaby::XHTMLStrict
|
248
|
-
xhtml_html &block
|
249
|
-
end
|
250
|
-
|
251
|
-
private
|
252
|
-
|
253
|
-
def xhtml_html(&block)
|
254
|
-
instruct! if @output_xml_instruction
|
255
|
-
declare!(:DOCTYPE, :html, :PUBLIC, *tagset.doctype)
|
256
|
-
tag!(:html, :xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en", &block)
|
257
|
-
end
|
258
|
-
|
259
249
|
def fragment
|
260
250
|
stream = @streams.last
|
261
|
-
|
251
|
+
start = stream.length
|
262
252
|
yield
|
263
|
-
|
264
|
-
Fragment.new(stream,
|
253
|
+
length = stream.length - start
|
254
|
+
Fragment.new(stream, start, length)
|
265
255
|
end
|
256
|
+
end
|
266
257
|
|
258
|
+
class Stream < Array
|
259
|
+
alias_method :to_s, :join
|
267
260
|
end
|
268
261
|
|
269
262
|
# Every tag method in Markaby returns a Fragment. If any method gets called on the Fragment,
|
@@ -272,17 +265,37 @@ module Markaby
|
|
272
265
|
#
|
273
266
|
# For a more practical explanation, check out the README.
|
274
267
|
class Fragment < ::Builder::BlankSlate
|
275
|
-
def initialize(
|
276
|
-
@
|
268
|
+
def initialize(*args)
|
269
|
+
@stream, @start, @length = args
|
270
|
+
@transformed_stream = false
|
277
271
|
end
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
272
|
+
|
273
|
+
if RUBY_VERSION_ID >= 191
|
274
|
+
undef_method :to_s, :inspect, :==
|
275
|
+
end
|
276
|
+
|
277
|
+
private
|
278
|
+
|
279
|
+
def method_missing(*args, &block)
|
280
|
+
transform_stream unless transformed_stream?
|
281
|
+
@str.__send__(*args, &block)
|
282
|
+
end
|
283
|
+
|
284
|
+
def transform_stream
|
285
|
+
@transformed_stream = true
|
286
|
+
|
287
|
+
# We can't do @stream.slice!(@start, @length),
|
288
|
+
# as it would invalidate the @starts and @lengths of other Fragment instances.
|
289
|
+
@str = @stream[@start, @length].to_s
|
290
|
+
@stream[@start, @length] = [nil] * @length
|
291
|
+
end
|
292
|
+
|
293
|
+
def transformed_stream?
|
294
|
+
@transformed_stream
|
285
295
|
end
|
286
296
|
end
|
287
297
|
|
298
|
+
class XmlMarkup < ::Builder::XmlMarkup
|
299
|
+
attr_accessor :target, :level
|
300
|
+
end
|
288
301
|
end
|