markaby 0.4 → 0.5
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/README +116 -50
- data/Rakefile +6 -1
- data/lib/markaby.rb +3 -2
- data/lib/markaby/builder.rb +148 -85
- data/lib/markaby/cssproxy.rb +16 -0
- data/lib/markaby/rails.rb +46 -0
- data/lib/markaby/tags.rb +160 -10
- data/test/test_markaby.rb +77 -26
- data/tools/rakehelp.rb +7 -1
- metadata +8 -8
- data/lib/markaby/helper.rb +0 -14
- data/lib/markaby/view.rb +0 -10
data/README
CHANGED
@@ -73,44 +73,13 @@ This doesn't effect Rails users, but when used in regular Ruby code, it can
|
|
73
73
|
be a bit disorienting. You are recommended to put your Markaby code in a
|
74
74
|
module where it won't mix with anything.
|
75
75
|
|
76
|
-
=
|
77
|
-
|
78
|
-
When used in Rails templates, the Rails helper object is passed into
|
79
|
-
Markaby::Builder. When you call helper methods inside Markaby, the output
|
80
|
-
from those methods will be output to the stream. This is incredibly
|
81
|
-
handy, since most Rails helpers output HTML tags.
|
82
|
-
|
83
|
-
head do
|
84
|
-
javascript_include_tag 'prototype'
|
85
|
-
autodiscovery_link_tag
|
86
|
-
end
|
87
|
-
|
88
|
-
However, some methods are designed to give back a String which you can use
|
89
|
-
elsewhere. Call the <tt>@helpers</tt> object with the method and you'll get
|
90
|
-
the String back and nothing will be output.
|
91
|
-
|
92
|
-
p "Total is: #{@helper.number_to_human_size @file_bytes}"
|
93
|
-
|
94
|
-
Conversely, you may call instance variables from your controller by using
|
95
|
-
a method and its value will be returned, nothing will be output.
|
96
|
-
|
97
|
-
# Inside imaginary ProductController
|
98
|
-
def list
|
99
|
-
@products = Product.find :all
|
100
|
-
end
|
101
|
-
|
102
|
-
# Inside app/views/product/list.mab
|
103
|
-
products.each do |product|
|
104
|
-
p product.title
|
105
|
-
end
|
106
|
-
|
107
|
-
= A Quick Tour
|
76
|
+
= The Six Steps of Markaby
|
108
77
|
|
109
78
|
If you dive right into Markaby, it'll probably make good sense, but you're
|
110
|
-
likely to run into a few kinks.
|
111
|
-
|
79
|
+
likely to run into a few kinks. Why not review these six steps and commit
|
80
|
+
them memory so you can really *know* what you're doing?
|
112
81
|
|
113
|
-
== Element Classes
|
82
|
+
== 1. Element Classes
|
114
83
|
|
115
84
|
Element classes may be added by hooking methods onto container elements:
|
116
85
|
|
@@ -128,15 +97,15 @@ Which results in:
|
|
128
97
|
<div class="entryContent">Okay, once again, the idea here is ...</div>
|
129
98
|
</div>
|
130
99
|
|
131
|
-
== Element IDs
|
100
|
+
== 2. Element IDs
|
132
101
|
|
133
102
|
IDs may be added by the use of bang methods:
|
134
103
|
|
135
|
-
div.page!
|
136
|
-
div.content!
|
104
|
+
div.page! {
|
105
|
+
div.content! {
|
137
106
|
h1 "A Short Short Saintly Dog"
|
138
|
-
|
139
|
-
|
107
|
+
}
|
108
|
+
}
|
140
109
|
|
141
110
|
Which results in:
|
142
111
|
|
@@ -146,29 +115,87 @@ Which results in:
|
|
146
115
|
</div>
|
147
116
|
</div>
|
148
117
|
|
149
|
-
==
|
118
|
+
== 3. Validate Your XHTML 1.0 Output
|
150
119
|
|
151
|
-
|
152
|
-
|
120
|
+
If you'd like Markaby to help you assemble valid XHTML documents,
|
121
|
+
you can use the <tt>xhtml_transitional</tt> or <tt>xhtml_strict</tt>
|
122
|
+
methods in place of the normal <tt>html</tt> tag.
|
153
123
|
|
154
124
|
xhtml_strict do
|
155
|
-
|
125
|
+
head { ... }
|
126
|
+
body { ... }
|
156
127
|
end
|
157
128
|
|
158
|
-
|
129
|
+
This will add the XML instruction and the doctype tag to your document.
|
130
|
+
Also, a character set meta tag will be placed inside your <tt>head</tt>
|
131
|
+
tag.
|
132
|
+
|
133
|
+
Now, since Markaby knows which doctype you're using, it checks a big
|
134
|
+
list of valid tags and attributes before printing anything.
|
135
|
+
|
136
|
+
>> div :styl => "padding: 10px" do
|
137
|
+
>> img :src => "samorost.jpg"
|
138
|
+
>> end
|
139
|
+
InvalidHtmlError: no such attribute `styl'
|
140
|
+
|
141
|
+
Markaby will also make sure you don't use the same element ID twice!
|
142
|
+
|
143
|
+
== 4. Escape or No Escape?
|
144
|
+
|
145
|
+
Markaby uses a simple convention for escaping stuff: if a string
|
146
|
+
is an argument, it gets escaped. If the string is in a block, it
|
147
|
+
doesn't.
|
148
|
+
|
149
|
+
This is handy if you're using something like RedCloth or
|
150
|
+
RDoc inside an element. Pass the string back through the block
|
151
|
+
and it'll skip out of escaping.
|
152
|
+
|
153
|
+
div.comment { RedCloth.new(str).to_html }
|
154
|
+
|
155
|
+
But, if we have some raw text that needs escaping, pass it in
|
156
|
+
as an argument:
|
157
|
+
|
158
|
+
div.comment raw_str
|
159
|
+
|
160
|
+
One caveat: if you have other tags inside a block, the string
|
161
|
+
passed back will be ignored.
|
159
162
|
|
160
|
-
|
161
|
-
|
163
|
+
div.comment {
|
164
|
+
div.author "_why"
|
165
|
+
div.says "Torpedoooooes!"
|
166
|
+
"<div>Silence.</div>"
|
167
|
+
}
|
162
168
|
|
163
|
-
|
169
|
+
The final div above won't appear in the output. You can't mix
|
170
|
+
tag modes like that, friend.
|
171
|
+
|
172
|
+
== 5. Auto-stringification
|
173
|
+
|
174
|
+
If you end up using any of your Markaby "tags" as a string, the
|
175
|
+
tag won't be output. It'll be up to you to add the new string
|
176
|
+
back into the HTML output.
|
177
|
+
|
178
|
+
This means if you call <tt>to_s</tt>, you'll get a string back.
|
179
|
+
|
180
|
+
div.title { "Rock Bottom" + span(" by Robert Wyatt").to_s }
|
181
|
+
|
182
|
+
But, when you're adding strings in Ruby, <tt>to_s</tt> happens automatically.
|
183
|
+
|
184
|
+
div.title { "Rock Bottom" + span(" by Robert Wyatt") }
|
185
|
+
|
186
|
+
Interpolation works fine.
|
187
|
+
|
188
|
+
div.title { "Rock Bottom #{span(" by Robert Wyatt")}" }
|
189
|
+
|
190
|
+
And any other operation you might perform on a string.
|
164
191
|
|
165
192
|
div.menu! \
|
166
193
|
['5.gets', 'bits', 'cult', 'inspect', '-h'].map do |category|
|
167
|
-
|
194
|
+
link_to category
|
168
195
|
end.
|
169
196
|
join( " | " )
|
170
197
|
|
171
|
-
== The <tt>tag!</tt> Method
|
198
|
+
== 6. The <tt>tag!</tt> Method
|
172
199
|
|
173
200
|
If you need to force a tag at any time, call <tt>tag!</tt> with the
|
174
201
|
tag name followed by the possible arguments and block. The CssProxy
|
@@ -180,6 +207,45 @@ won't work with this technique.
|
|
180
207
|
end
|
181
208
|
end
|
182
209
|
|
210
|
+
= A Note About Rails Helpers
|
211
|
+
|
212
|
+
When used in Rails templates, the Rails helper object is passed into
|
213
|
+
Markaby::Builder. When you call helper methods inside Markaby, the output
|
214
|
+
from those methods will be output to the stream. This is incredibly
|
215
|
+
handy, since most Rails helpers output HTML tags.
|
216
|
+
|
217
|
+
head do
|
218
|
+
javascript_include_tag 'prototype'
|
219
|
+
autodiscovery_link_tag
|
220
|
+
end
|
221
|
+
|
222
|
+
However, some methods are designed to give back a String which you can use
|
223
|
+
elsewhere. That's okay! Every method returns a Fragment object, which can
|
224
|
+
be used as a string.
|
225
|
+
|
226
|
+
p { "Total is: #{number_to_human_size @file_bytes}" }
|
227
|
+
|
228
|
+
Also see the Quick Tour above, specifically the stuff about auto-stringification.
|
229
|
+
|
230
|
+
If for any reason you have trouble with fragments, you can just
|
231
|
+
call the <tt>@helpers</tt> object with the method and you'll get
|
232
|
+
the String back and nothing will be output.
|
233
|
+
|
234
|
+
p { "Total is: #{@helper.number_to_human_size @file_bytes}" }
|
235
|
+
|
236
|
+
Conversely, you may call instance variables from your controller by using
|
237
|
+
a method and its value will be returned, nothing will be output.
|
238
|
+
|
239
|
+
# Inside imaginary ProductController
|
240
|
+
def list
|
241
|
+
@products = Product.find :all
|
242
|
+
end
|
243
|
+
|
244
|
+
# Inside app/views/product/list.mab
|
245
|
+
products.each do |product|
|
246
|
+
p product.title
|
247
|
+
end
|
248
|
+
|
183
249
|
= Credits
|
184
250
|
|
185
251
|
Markaby is a work of immense hope by Tim Fletcher and why the lucky stiff.
|
data/Rakefile
CHANGED
@@ -7,9 +7,14 @@ require 'tools/rakehelp'
|
|
7
7
|
require 'fileutils'
|
8
8
|
include FileUtils
|
9
9
|
|
10
|
+
REV = File.read(".svn/entries")[/committed-rev="(\d+)"/, 1] rescue nil
|
11
|
+
VERS = ENV['VERSION'] || "0.5" + (REV ? ".#{REV}" : "")
|
12
|
+
|
13
|
+
task :default => [:package]
|
14
|
+
|
10
15
|
setup_tests
|
11
16
|
setup_rdoc ['README', 'CHANGELOG', 'lib/**/*.rb']
|
12
17
|
|
13
18
|
summary = "Markup as Ruby, write HTML in your native Ruby tongue"
|
14
19
|
test_file = "test/test_markaby.rb"
|
15
|
-
setup_gem("markaby",
|
20
|
+
setup_gem("markaby", VERS, "Tim Fletcher and _why", summary, [['builder', '>=2.0.0']], test_file)
|
data/lib/markaby.rb
CHANGED
@@ -19,7 +19,9 @@ $:.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
|
-
VERSION = '0.
|
22
|
+
VERSION = '0.5'
|
23
|
+
|
24
|
+
class InvalidXhtmlError < Exception; end
|
23
25
|
end
|
24
26
|
|
25
27
|
unless defined?(Builder)
|
@@ -30,5 +32,4 @@ end
|
|
30
32
|
require 'markaby/builder'
|
31
33
|
require 'markaby/cssproxy'
|
32
34
|
require 'markaby/metaid'
|
33
|
-
require 'markaby/tags'
|
34
35
|
require 'markaby/template'
|
data/lib/markaby/builder.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'markaby/tags'
|
2
|
+
|
1
3
|
module Markaby
|
2
4
|
# The Markaby::Builder class is the central gear in the system. When using
|
3
5
|
# from Ruby code, this is the only class you need to instantiate directly.
|
@@ -19,22 +21,27 @@ module Markaby
|
|
19
21
|
class Builder
|
20
22
|
|
21
23
|
@@default = {
|
22
|
-
:indent =>
|
24
|
+
:indent => 0,
|
23
25
|
:output_helpers => true,
|
24
26
|
:output_xml_instruction => true,
|
25
27
|
:output_meta_tag => true,
|
26
|
-
:
|
28
|
+
:auto_validation => true,
|
29
|
+
:tagset => Markaby::XHTMLTransitional
|
27
30
|
}
|
28
31
|
|
29
32
|
def self.set(option, value)
|
30
33
|
@@default[option] = value
|
31
34
|
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def self.ignored_helpers
|
37
|
+
@@ignored_helpers ||= []
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.ignore_helpers(*helpers)
|
41
|
+
ignored_helpers.concat helpers
|
42
|
+
end
|
36
43
|
|
37
|
-
attr_accessor :output_helpers
|
44
|
+
attr_accessor :output_helpers, :tagset
|
38
45
|
|
39
46
|
# Create a Markaby builder object. Pass in a hash of variable assignments to
|
40
47
|
# +assigns+ which will be available as instance variables inside tag construction
|
@@ -52,14 +59,13 @@ module Markaby
|
|
52
59
|
# }
|
53
60
|
#
|
54
61
|
def initialize(assigns = {}, helpers = nil, &block)
|
55
|
-
@
|
62
|
+
@streams = [[]]
|
56
63
|
@assigns = assigns
|
57
|
-
@
|
64
|
+
@elements = {}
|
58
65
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
@output_xml_instruction = @@default[:output_xml_instruction]
|
66
|
+
@@default.each do |k, v|
|
67
|
+
instance_variable_set("@#{k}", @assigns[k] || v)
|
68
|
+
end
|
63
69
|
|
64
70
|
if helpers.nil?
|
65
71
|
@helpers = nil
|
@@ -79,18 +85,19 @@ module Markaby
|
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
82
|
-
@
|
83
|
-
|
88
|
+
@builder = ::Builder::XmlMarkup.new(:indent => @indent, :target => @streams.last)
|
89
|
+
class << @builder
|
90
|
+
attr_accessor :target, :level
|
91
|
+
end
|
84
92
|
|
85
93
|
if block
|
86
|
-
|
87
|
-
text(r) if to_s.empty?
|
94
|
+
text(capture(&block))
|
88
95
|
end
|
89
96
|
end
|
90
97
|
|
91
98
|
# Returns a string containing the HTML stream. Internally, the stream is stored as an Array.
|
92
99
|
def to_s
|
93
|
-
@
|
100
|
+
@streams.last.to_s
|
94
101
|
end
|
95
102
|
|
96
103
|
# Write a +string+ to the HTML stream without escaping it.
|
@@ -111,89 +118,111 @@ module Markaby
|
|
111
118
|
# => "<h1>TITLE</h1>\n<h2>CAPTURE ME</h2>\n"
|
112
119
|
#
|
113
120
|
def capture(&block)
|
114
|
-
|
115
|
-
@
|
116
|
-
str = instance_eval(&block)
|
117
|
-
str = @
|
118
|
-
@
|
121
|
+
@streams.push(builder.target = [])
|
122
|
+
@builder.level += 1
|
123
|
+
str = instance_eval(&block)
|
124
|
+
str = @streams.last.join if @streams.last.any?
|
125
|
+
@streams.pop
|
126
|
+
@builder.level -= 1
|
127
|
+
builder.target = @streams.last
|
119
128
|
str
|
120
129
|
end
|
121
130
|
|
122
|
-
# Content_for will store the given block in an instance variable for later use
|
123
|
-
# in another template or in the layout.
|
124
|
-
#
|
125
|
-
# The name of the instance variable is content_for_<name> to stay consistent
|
126
|
-
# with @content_for_layout which is used by ActionView's layouts.
|
127
|
-
#
|
128
|
-
# Example:
|
129
|
-
#
|
130
|
-
# content_for("header") do
|
131
|
-
# h1 "Half Shark and Half Lion"
|
132
|
-
# end
|
133
|
-
#
|
134
|
-
# If used several times, the variable will contain all the parts concatenated.
|
135
|
-
def content_for(name, &block)
|
136
|
-
eval "@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)"
|
137
|
-
end
|
138
|
-
|
139
131
|
# Create a tag named +tag+. Other than the first argument which is the tag name,
|
140
132
|
# the arguments are the same as the tags implemented via method_missing.
|
141
133
|
def tag!(tag, *args, &block)
|
134
|
+
ele_id = nil
|
135
|
+
if @auto_validation and @tagset
|
136
|
+
if !@tagset.tagset.has_key?(tag)
|
137
|
+
raise InvalidXhtmlError, "no element `#{tag}' for #{tagset.doctype}"
|
138
|
+
elsif args.last.respond_to?(:to_hash)
|
139
|
+
attrs = args.last.to_hash
|
140
|
+
attrs.each do |k, v|
|
141
|
+
atname = k.to_s.downcase.intern
|
142
|
+
unless k =~ /:/ or @tagset.tagset[tag].include? atname
|
143
|
+
raise InvalidXhtmlError, "no attribute `#{k}' on #{tag} elements"
|
144
|
+
end
|
145
|
+
if atname == :id
|
146
|
+
ele_id = v.to_s
|
147
|
+
if @elements.has_key? ele_id
|
148
|
+
raise InvalidXhtmlError, "id `#{ele_id}' already used (id's must be unique)."
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
142
154
|
if block
|
143
155
|
str = capture &block
|
144
156
|
block = proc { text(str) }
|
145
157
|
end
|
146
|
-
|
158
|
+
|
159
|
+
f = fragment { @builder.method_missing(tag, *args, &block) }
|
160
|
+
@elements[ele_id] = f if ele_id
|
161
|
+
f
|
147
162
|
end
|
148
163
|
|
149
|
-
#
|
150
|
-
# invoked directly, but is called for each markup method in the markup block.
|
151
|
-
#
|
152
|
-
# This method is also used to intercept calls to helper methods and instance
|
164
|
+
# This method is used to intercept calls to helper methods and instance
|
153
165
|
# variables. Here is the order of interception:
|
154
166
|
#
|
155
|
-
# * If +sym+ is a recognized HTML tag, the tag is output
|
156
|
-
# or a CssProxy is returned if no arguments are given.
|
157
|
-
# * If +sym+ appears to be a self-closing tag, its block
|
158
|
-
# is ignored, thus outputting a valid self-closing tag.
|
159
|
-
# * If +sym+ is also the name of an instance variable, the
|
160
|
-
# value of the instance variable is returned.
|
161
167
|
# * If +sym+ is a helper method, the helper method is called
|
162
168
|
# and output to the stream.
|
163
|
-
# *
|
169
|
+
# * If +sym+ is a Builder::XmlMarkup method, it is passed on to the builder object.
|
170
|
+
# * If +sym+ is also the name of an instance variable, the
|
171
|
+
# value of the instance variable is returned.
|
172
|
+
# * If +sym+ has come this far and no +tagset+ is found, +sym+ and its arguments are passed to tag!
|
173
|
+
# * If a tagset is found, though, +NoMethodError+ is raised.
|
174
|
+
#
|
175
|
+
# method_missing used to be the lynchpin in Markaby, but it's no longer used to handle
|
176
|
+
# HTML tags. See html_tag for that.
|
164
177
|
def method_missing(sym, *args, &block)
|
165
|
-
if
|
166
|
-
if args.empty? and block.nil?
|
167
|
-
return CssProxy.new do |args, block|
|
168
|
-
if FORM_TAGS.include?(sym) and args.last.respond_to?(:to_hash) and args.last[:id]
|
169
|
-
args.last[:name] ||= args.last[:id]
|
170
|
-
end
|
171
|
-
tag!(sym, *args, &block)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
if args.first.respond_to? :to_hash
|
175
|
-
block ||= proc{}
|
176
|
-
end
|
177
|
-
tag!(sym, *args, &block)
|
178
|
-
elsif SELF_CLOSING_TAGS.include?(sym)
|
179
|
-
tag!(sym, *args)
|
180
|
-
elsif @helpers.respond_to?(sym)
|
178
|
+
if @helpers.respond_to?(sym, true) && !self.class.ignored_helpers.include?(sym)
|
181
179
|
r = @helpers.send(sym, *args, &block)
|
182
|
-
@
|
183
|
-
|
184
|
-
|
180
|
+
if @output_helpers and r.respond_to? :to_str
|
181
|
+
fragment { @builder << r }
|
182
|
+
else
|
183
|
+
r
|
184
|
+
end
|
185
|
+
elsif ::Builder::XmlMarkup.instance_methods.include?(sym.to_s)
|
186
|
+
@builder.__send__(sym, *args, &block)
|
187
|
+
elsif instance_variables.include?("@#{sym}")
|
185
188
|
instance_variable_get("@#{sym}")
|
186
|
-
|
189
|
+
elsif @tagset.nil?
|
187
190
|
tag!(sym, *args, &block)
|
191
|
+
else
|
192
|
+
raise NoMethodError, "no such method `#{sym}'"
|
188
193
|
end
|
189
194
|
end
|
190
195
|
|
191
|
-
|
192
|
-
|
196
|
+
# Every HTML tag method goes through an html_tag call. So, calling <tt>div</tt> is equivalent
|
197
|
+
# to calling <tt>html_tag(:div)</tt>. All HTML tags in Markaby's list are given generated wrappers
|
198
|
+
# for this method.
|
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"
|
205
|
+
end
|
206
|
+
if args.empty? and block.nil? and not NO_PROXY.include?(sym)
|
207
|
+
return CssProxy.new do |args, block|
|
208
|
+
if @tagset.forms.include?(sym) and args.last.respond_to?(:to_hash) and args.last[:id]
|
209
|
+
args.last[:name] ||= args.last[:id]
|
210
|
+
end
|
211
|
+
tag!(sym, *args, &block)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
if not @tagset.self_closing.include?(sym) and args.first.respond_to?(:to_hash)
|
215
|
+
block ||= proc{}
|
216
|
+
end
|
217
|
+
tag!(sym, *args, &block)
|
218
|
+
end
|
193
219
|
|
194
|
-
|
195
|
-
|
196
|
-
|
220
|
+
XHTMLTransitional.tags.each do |k|
|
221
|
+
class_eval %{
|
222
|
+
def #{k}(*args, &block)
|
223
|
+
html_tag(#{k.inspect}, *args, &block)
|
224
|
+
end
|
225
|
+
}
|
197
226
|
end
|
198
227
|
|
199
228
|
# Builds a head tag. Adds a <tt>meta</tt> tag inside with Content-Type
|
@@ -201,25 +230,59 @@ module Markaby
|
|
201
230
|
def head(*args, &block)
|
202
231
|
tag!(:head, *args) do
|
203
232
|
tag!(:meta, "http-equiv" => "Content-Type", "content" => "text/html; charset=utf-8") if @output_meta_tag
|
204
|
-
instance_eval
|
233
|
+
instance_eval(&block)
|
205
234
|
end
|
206
235
|
end
|
207
236
|
|
208
237
|
# Builds an html tag. An XML 1.0 instruction and an XHTML 1.0 Transitional doctype
|
209
238
|
# are prepended. Also assumes <tt>:xmlns => "http://www.w3.org/1999/xhtml",
|
210
|
-
#
|
211
|
-
def
|
212
|
-
|
213
|
-
|
214
|
-
@builder.declare!(:DOCTYPE, :html, :PUBLIC, *doctype)
|
215
|
-
tag!(:html, :xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en", &block)
|
239
|
+
# :lang => "en"</tt>.
|
240
|
+
def xhtml_transitional(&block)
|
241
|
+
self.tagset = Markaby::XHTMLTransitional
|
242
|
+
xhtml_html &block
|
216
243
|
end
|
217
|
-
alias_method :xhtml_transitional, :html
|
218
244
|
|
219
245
|
# Builds an html tag with XHTML 1.0 Strict doctype instead.
|
220
246
|
def xhtml_strict(&block)
|
221
|
-
|
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
|
+
def fragment
|
260
|
+
stream = @streams.last
|
261
|
+
f1 = stream.length
|
262
|
+
yield
|
263
|
+
f2 = stream.length - f1
|
264
|
+
Fragment.new(stream, f1, f2)
|
222
265
|
end
|
223
266
|
|
224
267
|
end
|
268
|
+
|
269
|
+
# Every tag method in Markaby returns a Fragment. If any method gets called on the Fragment,
|
270
|
+
# the tag is removed from the Markaby stream and given back as a string. Usually the fragment
|
271
|
+
# is never used, though, and the stream stays intact.
|
272
|
+
#
|
273
|
+
# For a more practical explanation, check out the README.
|
274
|
+
class Fragment < ::Builder::BlankSlate
|
275
|
+
def initialize(s, a, b)
|
276
|
+
@s, @f1, @f2 = s, a, b
|
277
|
+
end
|
278
|
+
def method_missing(*a)
|
279
|
+
unless @str
|
280
|
+
@str = @s[@f1, @f2].to_s
|
281
|
+
@s[@f1, @f2] = [nil] * @f2
|
282
|
+
@str
|
283
|
+
end
|
284
|
+
@str.send(*a)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
225
288
|
end
|
data/lib/markaby/cssproxy.rb
CHANGED
@@ -12,12 +12,22 @@ module Markaby
|
|
12
12
|
@blk = blk
|
13
13
|
end
|
14
14
|
|
15
|
+
# Adds attributes to an element, for internal use only. For example, if you
|
16
|
+
# want to write a wrapper which sets a bunch of default attributes for a certain
|
17
|
+
# tag. Like the default `img' method included with Markaby automatically sets an
|
18
|
+
# empty alt attribute.
|
19
|
+
def merge!(opts)
|
20
|
+
@opts.merge! opts
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
15
24
|
# Adds attributes to an element. Bang methods set the :id attribute.
|
16
25
|
# Other methods add to the :class attribute. If a block is supplied,
|
17
26
|
# it is executed with a merged hash (@opts + args).
|
18
27
|
def method_missing(id_or_class, *args, &blk)
|
19
28
|
idc = id_or_class.to_s
|
20
29
|
case idc
|
30
|
+
when "pass"
|
21
31
|
when /!$/
|
22
32
|
@opts[:id] = $`
|
23
33
|
else
|
@@ -33,5 +43,11 @@ module Markaby
|
|
33
43
|
@blk.call(args, blk)
|
34
44
|
end
|
35
45
|
end
|
46
|
+
|
47
|
+
def to_str
|
48
|
+
@blk.call([[@opts]]).to_s
|
49
|
+
end
|
50
|
+
alias_method :to_s, :to_str
|
51
|
+
|
36
52
|
end
|
37
53
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Markaby
|
2
|
+
|
3
|
+
# Markaby helpers for Rails.
|
4
|
+
module ActionControllerHelpers
|
5
|
+
# Returns a string of HTML built from the attached +block+. Any +options+ are
|
6
|
+
# passed into the render method.
|
7
|
+
#
|
8
|
+
# Use this method in your controllers to output Markaby directly from inside.
|
9
|
+
def render_markaby(options = {}, &block)
|
10
|
+
render options.merge({ :text => Builder.new({}, self, &block).to_s })
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ActionViewTemplateHandler
|
15
|
+
def initialize(action_view)
|
16
|
+
@action_view = action_view
|
17
|
+
end
|
18
|
+
def render(template, local_assigns = {})
|
19
|
+
Template.new(template).render(@action_view.assigns.merge(local_assigns), @action_view)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Builder
|
24
|
+
# Emulate ERB to satisfy helpers like <tt>form_for</tt>.
|
25
|
+
def _erbout; self end
|
26
|
+
|
27
|
+
# Content_for will store the given block in an instance variable for later use
|
28
|
+
# in another template or in the layout.
|
29
|
+
#
|
30
|
+
# The name of the instance variable is content_for_<name> to stay consistent
|
31
|
+
# with @content_for_layout which is used by ActionView's layouts.
|
32
|
+
#
|
33
|
+
# Example:
|
34
|
+
#
|
35
|
+
# content_for("header") do
|
36
|
+
# h1 "Half Shark and Half Lion"
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# If used several times, the variable will contain all the parts concatenated.
|
40
|
+
def content_for(name, &block)
|
41
|
+
@helpers.assigns["content_for_#{name}"] =
|
42
|
+
eval("@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/lib/markaby/tags.rb
CHANGED
@@ -1,15 +1,165 @@
|
|
1
1
|
module Markaby
|
2
2
|
|
3
|
-
TAGS = [
|
4
|
-
:a, :abbr, :acronym, :span, :b, :caption, :del, :cite, :code, :col,
|
5
|
-
:colgroup, :dd, :dfn, :dt, :em, :fieldset, :i, :img, :ins, :kbd, :p,
|
6
|
-
:label, :legend, :li, :optgroup, :option, :select, :small, :span, :strong,
|
7
|
-
:sub, :sup, :tbody, :td, :textarea, :thead, :title, :th, :tr, :tfoot,
|
8
|
-
:tt, :address, :blockquote, :body, :div, :dl, :form, :h1, :h2, :h3, :head,
|
9
|
-
:noscript, :object, :ol, :pre, :q, :samp, :script, :style, :table, :ul
|
10
|
-
]
|
11
|
-
|
12
3
|
FORM_TAGS = [ :form, :input, :select, :textarea ]
|
13
|
-
SELF_CLOSING_TAGS = [ :hr, :br, :
|
4
|
+
SELF_CLOSING_TAGS = [ :base, :meta, :link, :hr, :br, :param, :img, :area, :input, :col ]
|
5
|
+
NO_PROXY = [ :hr, :br ]
|
6
|
+
|
7
|
+
# Common sets of attributes.
|
8
|
+
AttrCore = [:id, :class, :style, :title]
|
9
|
+
AttrI18n = [:lang, 'xml:lang'.intern, :dir]
|
10
|
+
AttrEvents = [:onclick, :ondblclick, :onmousedown, :onmouseup, :onmouseover, :onmousemove,
|
11
|
+
:onmouseout, :onkeypress, :onkeydown, :onkeyup]
|
12
|
+
AttrFocus = [:accesskey, :tabindex, :onfocus, :onblur]
|
13
|
+
AttrHAlign = [:align, :char, :charoff]
|
14
|
+
AttrVAlign = [:valign]
|
15
|
+
Attrs = AttrCore + AttrI18n + AttrEvents
|
16
|
+
|
17
|
+
# All the tags and attributes from XHTML 1.0 Strict
|
18
|
+
class XHTMLStrict
|
19
|
+
class << self
|
20
|
+
attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
|
21
|
+
end
|
22
|
+
@doctype = ["-//W3C//DTD XHTML 1.0 Strict//EN", "DTD/xhtml1-strict.dtd"]
|
23
|
+
@tagset = {
|
24
|
+
:html => AttrI18n + [:id, :xmlns],
|
25
|
+
:head => AttrI18n + [:id, :profile],
|
26
|
+
:title => AttrI18n + [:id],
|
27
|
+
:base => [:href, :id],
|
28
|
+
:meta => AttrI18n + [:id, :http, :name, :content, :scheme, 'http-equiv'.intern],
|
29
|
+
:link => Attrs + [:charset, :href, :hreflang, :type, :rel, :rev, :media],
|
30
|
+
:style => AttrI18n + [:id, :type, :media, :title, 'xml:space'.intern],
|
31
|
+
:script => [:id, :charset, :type, :src, :defer, 'xml:space'.intern],
|
32
|
+
:noscript => Attrs,
|
33
|
+
:body => Attrs + [:onload, :onunload],
|
34
|
+
:div => Attrs,
|
35
|
+
:p => Attrs,
|
36
|
+
:ul => Attrs,
|
37
|
+
:ol => Attrs,
|
38
|
+
:li => Attrs,
|
39
|
+
:dl => Attrs,
|
40
|
+
:dt => Attrs,
|
41
|
+
:dd => Attrs,
|
42
|
+
:address => Attrs,
|
43
|
+
:hr => Attrs,
|
44
|
+
:pre => Attrs + ['xml:space'.intern],
|
45
|
+
:blockquote => Attrs + [:cite],
|
46
|
+
:ins => Attrs + [:cite, :datetime],
|
47
|
+
:del => Attrs + [:cite, :datetime],
|
48
|
+
:a => Attrs + AttrFocus + [:charset, :type, :name, :href, :hreflang, :rel, :rev, :shape, :coords],
|
49
|
+
:span => Attrs,
|
50
|
+
:bdo => AttrCore + AttrEvents + [:lang, 'xml:lang'.intern, :dir],
|
51
|
+
:br => AttrCore,
|
52
|
+
:em => Attrs,
|
53
|
+
:strong => Attrs,
|
54
|
+
:dfn => Attrs,
|
55
|
+
:code => Attrs,
|
56
|
+
:samp => Attrs,
|
57
|
+
:kbd => Attrs,
|
58
|
+
:var => Attrs,
|
59
|
+
:cite => Attrs,
|
60
|
+
:abbr => Attrs,
|
61
|
+
:acronym => Attrs,
|
62
|
+
:q => Attrs + [:cite],
|
63
|
+
:sub => Attrs,
|
64
|
+
:sup => Attrs,
|
65
|
+
:tt => Attrs,
|
66
|
+
:i => Attrs,
|
67
|
+
:b => Attrs,
|
68
|
+
:big => Attrs,
|
69
|
+
:small => Attrs,
|
70
|
+
:object => Attrs + [:declare, :classid, :codebase, :data, :type, :codetype, :archive, :standby, :height, :width, :usemap, :name, :tabindex],
|
71
|
+
:param => [:id, :name, :value, :valuetype, :type],
|
72
|
+
:img => Attrs + [:src, :alt, :longdesc, :height, :width, :usemap, :ismap],
|
73
|
+
:map => AttrI18n + AttrEvents + [:id, :class, :style, :title, :name],
|
74
|
+
:area => Attrs + AttrFocus + [:shape, :coords, :href, :nohref, :alt],
|
75
|
+
:form => Attrs + [:action, :method, :enctype, :onsubmit, :onreset, :accept, :accept],
|
76
|
+
:label => Attrs + [:for, :accesskey, :onfocus, :onblur],
|
77
|
+
:input => Attrs + AttrFocus + [:type, :name, :value, :checked, :disabled, :readonly, :size, :maxlength, :src, :alt, :usemap, :onselect, :onchange, :accept],
|
78
|
+
:select => Attrs + [:name, :size, :multiple, :disabled, :tabindex, :onfocus, :onblur, :onchange],
|
79
|
+
:optgroup => Attrs + [:disabled, :label],
|
80
|
+
:option => Attrs + [:selected, :disabled, :label, :value],
|
81
|
+
:textarea => Attrs + AttrFocus + [:name, :rows, :cols, :disabled, :readonly, :onselect, :onchange],
|
82
|
+
:fieldset => Attrs,
|
83
|
+
:legend => Attrs + [:accesskey],
|
84
|
+
:button => Attrs + AttrFocus + [:name, :value, :type, :disabled],
|
85
|
+
:table => Attrs + [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding],
|
86
|
+
:caption => Attrs,
|
87
|
+
:colgroup => Attrs + AttrHAlign + AttrVAlign + [:span, :width],
|
88
|
+
:col => Attrs + AttrHAlign + AttrVAlign + [:span, :width],
|
89
|
+
:thead => Attrs + AttrHAlign + AttrVAlign,
|
90
|
+
:tfoot => Attrs + AttrHAlign + AttrVAlign,
|
91
|
+
:tbody => Attrs + AttrHAlign + AttrVAlign,
|
92
|
+
:tr => Attrs + AttrHAlign + AttrVAlign,
|
93
|
+
:th => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
|
94
|
+
:td => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
|
95
|
+
:h1 => Attrs,
|
96
|
+
:h2 => Attrs,
|
97
|
+
:h3 => Attrs,
|
98
|
+
:h4 => Attrs,
|
99
|
+
:h5 => Attrs,
|
100
|
+
:h6 => Attrs
|
101
|
+
}
|
102
|
+
|
103
|
+
@tags = @tagset.keys
|
104
|
+
@forms = @tags & FORM_TAGS
|
105
|
+
@self_closing = @tags & SELF_CLOSING_TAGS
|
106
|
+
end
|
107
|
+
|
108
|
+
# Additional tags found in XHTML 1.0 Transitional
|
109
|
+
class XHTMLTransitional
|
110
|
+
class << self
|
111
|
+
attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
|
112
|
+
end
|
113
|
+
@doctype = ["-//W3C//DTD XHTML 1.0 Transitional//EN", "DTD/xhtml1-transitional.dtd"]
|
114
|
+
@tagset = XHTMLStrict.tagset.merge \
|
115
|
+
:strike => Attrs,
|
116
|
+
:center => Attrs,
|
117
|
+
:dir => Attrs + [:compact],
|
118
|
+
:noframes => Attrs,
|
119
|
+
:basefont => [:id, :size, :color, :face],
|
120
|
+
:u => Attrs,
|
121
|
+
:menu => Attrs + [:compact],
|
122
|
+
:iframe => AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :scrolling, :align, :height, :width],
|
123
|
+
:font => AttrCore + AttrI18n + [:size, :color, :face],
|
124
|
+
:s => Attrs,
|
125
|
+
:applet => AttrCore + [:codebase, :archive, :code, :object, :alt, :name, :width, :height, :align, :hspace, :vspace],
|
126
|
+
:isindex => AttrCore + AttrI18n + [:prompt]
|
127
|
+
|
128
|
+
# Additional attributes found in XHTML 1.0 Transitional
|
129
|
+
{ :script => [:language],
|
130
|
+
:a => [:target],
|
131
|
+
:td => [:bgcolor, :nowrap, :width, :height],
|
132
|
+
:p => [:align],
|
133
|
+
:h5 => [:align],
|
134
|
+
:h3 => [:align],
|
135
|
+
:li => [:type, :value],
|
136
|
+
:div => [:align],
|
137
|
+
:pre => [:width],
|
138
|
+
:body => [:background, :bgcolor, :text, :link, :vlink, :alink],
|
139
|
+
:ol => [:type, :compact, :start],
|
140
|
+
:h4 => [:align],
|
141
|
+
:h2 => [:align],
|
142
|
+
:object => [:align, :border, :hspace, :vspace],
|
143
|
+
:img => [:name, :align, :border, :hspace, :vspace],
|
144
|
+
:link => [:target],
|
145
|
+
:legend => [:align],
|
146
|
+
:dl => [:compact],
|
147
|
+
:input => [:align],
|
148
|
+
:h6 => [:align],
|
149
|
+
:hr => [:align, :noshade, :size, :width],
|
150
|
+
:base => [:target],
|
151
|
+
:ul => [:type, :compact],
|
152
|
+
:br => [:clear],
|
153
|
+
:form => [:name, :target],
|
154
|
+
:area => [:target],
|
155
|
+
:h1 => [:align]
|
156
|
+
}.each do |k, v|
|
157
|
+
@tagset[k] += v
|
158
|
+
end
|
159
|
+
|
160
|
+
@tags = @tagset.keys
|
161
|
+
@forms = @tags & FORM_TAGS
|
162
|
+
@self_closing = @tags & SELF_CLOSING_TAGS
|
163
|
+
end
|
14
164
|
|
15
165
|
end
|
data/test/test_markaby.rb
CHANGED
@@ -5,54 +5,105 @@ module MarkabyTestHelpers
|
|
5
5
|
def link_to(obj)
|
6
6
|
%{<a href="">#{obj}</a>}
|
7
7
|
end
|
8
|
-
def pluralize(
|
9
|
-
|
8
|
+
def pluralize(string)
|
9
|
+
string + "s"
|
10
10
|
end
|
11
11
|
module_function :link_to, :pluralize
|
12
12
|
end
|
13
13
|
|
14
14
|
class MarkabyTest < Test::Unit::TestCase
|
15
|
-
|
16
|
-
def mab(
|
17
|
-
Markaby::
|
15
|
+
|
16
|
+
def mab(*args, &block)
|
17
|
+
Markaby::Builder.new(*args, &block).to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def assert_exception(exclass, exmsg, *mab_args, &block)
|
21
|
+
begin
|
22
|
+
mab(*mab_args, &block)
|
23
|
+
rescue Exception => e
|
24
|
+
assert_equal exclass, e.class
|
25
|
+
assert_equal exmsg, e.message
|
26
|
+
end
|
18
27
|
end
|
19
28
|
|
20
29
|
def test_simple
|
21
|
-
assert_equal "<hr
|
22
|
-
assert_equal "<p>foo</p
|
23
|
-
assert_equal "<p
|
30
|
+
assert_equal "<hr/>", mab { hr }
|
31
|
+
assert_equal "<p>foo</p>", mab { p 'foo' }
|
32
|
+
assert_equal "<p>foo</p>", mab { p { 'foo' } }
|
24
33
|
end
|
25
34
|
|
26
35
|
def test_classes_and_ids
|
27
|
-
assert_equal %{<div class="one"></div
|
28
|
-
assert_equal %{<div class="one two"></div
|
29
|
-
assert_equal %{<div id="three"></div
|
36
|
+
assert_equal %{<div class="one"></div>}, mab { div.one '' }
|
37
|
+
assert_equal %{<div class="one two"></div>}, mab { div.one.two '' }
|
38
|
+
assert_equal %{<div id="three"></div>}, mab { div.three! '' }
|
30
39
|
end
|
31
40
|
|
32
41
|
def test_escaping
|
33
|
-
assert_equal "<h1>Apples & Oranges</h1
|
34
|
-
assert_equal "<h1
|
35
|
-
assert_equal "<h1 class=\"fruits&floots\">Apples</h1
|
42
|
+
assert_equal "<h1>Apples & Oranges</h1>", mab { h1 'Apples & Oranges' }
|
43
|
+
assert_equal "<h1>Apples & Oranges</h1>", mab { h1 { 'Apples & Oranges' } }
|
44
|
+
assert_equal "<h1 class=\"fruits&floots\">Apples</h1>", mab { h1 'Apples', :class => 'fruits&floots' }
|
36
45
|
end
|
37
46
|
|
38
47
|
def test_capture
|
39
|
-
|
40
|
-
|
41
|
-
assert_equal
|
42
|
-
assert
|
48
|
+
builder = Markaby::Builder.new
|
49
|
+
assert builder.to_s.empty?
|
50
|
+
assert_equal "<h1>TEST</h1>", builder.capture { h1 'TEST' }
|
51
|
+
assert builder.to_s.empty?
|
52
|
+
assert mab { capture { h1 'hello world' }; nil }.empty?
|
53
|
+
assert_equal mab { div { h1 'TEST' } }, mab { div { capture { h1 'TEST' } } }
|
43
54
|
end
|
44
55
|
|
45
56
|
def test_ivars
|
46
|
-
html = "<div
|
47
|
-
assert_equal html, mab
|
48
|
-
assert_equal html, mab
|
49
|
-
assert_equal html, mab(
|
50
|
-
|
57
|
+
html = "<div><h1>Steve</h1><div><h2>Gerald</h2></div><h3>Gerald</h3></div>"
|
58
|
+
assert_equal html, mab { div { @name = 'Steve'; h1 @name; div { @name = 'Gerald'; h2 @name }; h3 @name } }
|
59
|
+
assert_equal html, mab { div { @name = 'Steve'; h1 @name; self << capture { div { @name = 'Gerald'; h2 @name } }; h3 @name } }
|
60
|
+
assert_equal html, mab(:name => 'Steve') { div { h1 @name; self << capture { div { @name = 'Gerald'; h2 @name } }; h3 @name } }
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_ivars_without_at_symbol
|
64
|
+
assert_equal "<h1>Hello World</h1>", mab { @message = 'Hello World'; h1 message }
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_helpers
|
68
|
+
Markaby::Builder.ignored_helpers.clear
|
69
|
+
assert_equal %{squirrels}, mab({}, MarkabyTestHelpers) { pluralize('squirrel') }
|
70
|
+
assert_equal %{<a href="">edit</a>}, mab({}, MarkabyTestHelpers) { link_to('edit') }
|
71
|
+
assert mab({}, MarkabyTestHelpers) { @output_helpers = false; link_to('edit'); nil }.empty?
|
72
|
+
Markaby::Builder.ignore_helpers :pluralize
|
73
|
+
assert_exception(NoMethodError, "no such method `pluralize'", {}, MarkabyTestHelpers) { pluralize('squirrel') }
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_builder_bang_methods
|
77
|
+
assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", mab { instruct! }
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_fragments
|
81
|
+
assert_equal %{<div><h1>Monkeys</h1><h2>Giraffes <small>Miniature</small> and <strong>Large</strong></h2><h3>Donkeys</h3><h4>Parakeet <b><i>Innocent IV</i></b> in Classic Chartreuse</h4></div>},
|
82
|
+
mab { div { h1 "Monkeys"; h2 { "Giraffes #{small 'Miniature' } and #{strong 'Large'}" }; h3 "Donkeys"; h4 { "Parakeet #{b { i 'Innocent IV' }} in Classic Chartreuse" } } }
|
83
|
+
assert_equal %{<div><h1>Monkeys</h1><h2>Giraffes <strong>Miniature</strong></h2><h3>Donkeys</h3></div>},
|
84
|
+
mab { div { h1 "Monkeys"; h2 { "Giraffes #{strong 'Miniature' }" }; h3 "Donkeys" } }
|
85
|
+
assert_equal %{<div><h1>Monkeys</h1><h2>Giraffes <small>Miniature</small> and <strong>Large</strong></h2><h3>Donkeys</h3><h4>Parakeet <strong>Large</strong> as well...</h4></div>},
|
86
|
+
mab { div { @a = small 'Miniature'; @b = strong 'Large'; h1 "Monkeys"; h2 { "Giraffes #{@a} and #{@b}" }; h3 "Donkeys"; h4 { "Parakeet #{@b} as well..." } } }
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_invalid_xhtml
|
90
|
+
assert_exception(NoMethodError, "no such method `dav'") { dav {} }
|
91
|
+
assert_exception(Markaby::InvalidXhtmlError, "no attribute `styl' on div elements") { div(:styl => 'ok') {} }
|
92
|
+
assert_exception(Markaby::InvalidXhtmlError, "no attribute `class' on tbody elements") { tbody.okay {} }
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_full_doc_transitional
|
96
|
+
doc = mab { instruct!; xhtml_transitional { head { title 'OKay' } } }
|
97
|
+
assert doc =~ /^<\?xml version="1.0" encoding="UTF-8"\?>/
|
98
|
+
assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">})
|
99
|
+
assert doc.include?(%{<title>OKay</title>})
|
51
100
|
end
|
52
101
|
|
53
|
-
def
|
54
|
-
|
55
|
-
assert
|
102
|
+
def test_full_doc_strict
|
103
|
+
doc = mab { xhtml_strict { head { title 'OKay' } } }
|
104
|
+
assert doc =~ /^<\?xml version="1.0" encoding="UTF-8"\?>/
|
105
|
+
assert doc.include?(%{"-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">})
|
106
|
+
assert doc.include?(%{<title>OKay</title>})
|
56
107
|
end
|
57
108
|
|
58
109
|
end
|
data/tools/rakehelp.rb
CHANGED
@@ -79,7 +79,7 @@ def setup_gem(pkg_name, pkg_version, author, summary, dependencies, test_file)
|
|
79
79
|
s.has_rdoc = true
|
80
80
|
s.extra_rdoc_files = [ "README" ]
|
81
81
|
dependencies.each do |dep|
|
82
|
-
s.add_dependency(dep)
|
82
|
+
s.add_dependency(*dep)
|
83
83
|
end
|
84
84
|
s.files = %w(README Rakefile setup.rb) +
|
85
85
|
Dir.glob("{bin,doc,test,lib}/**/*") +
|
@@ -97,4 +97,10 @@ def setup_gem(pkg_name, pkg_version, author, summary, dependencies, test_file)
|
|
97
97
|
p.gem_spec = spec
|
98
98
|
p.need_tar = true
|
99
99
|
end
|
100
|
+
|
101
|
+
task :install do
|
102
|
+
sh %{rake package}
|
103
|
+
sh %{gem install pkg/#{pkg_name}-#{pkg_version}}
|
104
|
+
end
|
105
|
+
|
100
106
|
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.0.1
|
3
3
|
specification_version: 1
|
4
4
|
name: markaby
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2006-
|
6
|
+
version: "0.5"
|
7
|
+
date: 2006-10-03 00:00:00 -06:00
|
8
8
|
summary: Markup as Ruby, write HTML in your native Ruby tongue
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
|
+
post_install_message:
|
28
29
|
authors:
|
29
30
|
- Tim Fletcher and _why
|
30
31
|
files:
|
@@ -34,12 +35,11 @@ files:
|
|
34
35
|
- test/test_markaby.rb
|
35
36
|
- lib/markaby
|
36
37
|
- lib/markaby.rb
|
37
|
-
- lib/markaby/helper.rb
|
38
|
-
- lib/markaby/tags.rb
|
39
38
|
- lib/markaby/metaid.rb
|
39
|
+
- lib/markaby/tags.rb
|
40
40
|
- lib/markaby/builder.rb
|
41
41
|
- lib/markaby/cssproxy.rb
|
42
|
-
- lib/markaby/
|
42
|
+
- lib/markaby/rails.rb
|
43
43
|
- lib/markaby/template.rb
|
44
44
|
- tools/rakehelp.rb
|
45
45
|
test_files:
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
version_requirement:
|
61
61
|
version_requirements: !ruby/object:Gem::Version::Requirement
|
62
62
|
requirements:
|
63
|
-
- - "
|
63
|
+
- - ">="
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
version:
|
65
|
+
version: 2.0.0
|
66
66
|
version:
|
data/lib/markaby/helper.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
module Markaby
|
2
|
-
# Markaby helpers for Rails.
|
3
|
-
module ActionControllerHelper
|
4
|
-
# Returns a string of HTML built from the attached +block+. Any +options+ are
|
5
|
-
# passed into the render method.
|
6
|
-
#
|
7
|
-
# Use this method in your controllers to output Markaby directly from inside.
|
8
|
-
def render_markaby(options = {}, &block)
|
9
|
-
render options.merge({
|
10
|
-
:text => Builder.new(nil, self, &block).to_s
|
11
|
-
})
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/lib/markaby/view.rb
DELETED