markaby 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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