markaby 0.5 → 0.6.6
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 +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
|