jig 0.1.0
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/History.txt +5 -0
- data/Manifest.txt +12 -0
- data/README.txt +114 -0
- data/Rakefile +39 -0
- data/lib/jig.rb +903 -0
- data/lib/jig/css.rb +307 -0
- data/lib/jig/xhtml.rb +283 -0
- data/lib/jig/xml.rb +320 -0
- data/test/test_css.rb +143 -0
- data/test/test_jig.rb +513 -0
- data/test/test_xhtml.rb +26 -0
- data/test/test_xml.rb +148 -0
- metadata +67 -0
data/lib/jig/css.rb
ADDED
@@ -0,0 +1,307 @@
|
|
1
|
+
|
2
|
+
require 'jig'
|
3
|
+
|
4
|
+
class Jig
|
5
|
+
# Jig::CSS is a subclass of Jig designed to facilitate the
|
6
|
+
# construction of CSS rule sets. This class should be considered
|
7
|
+
# experimental. The documentation uses C instead Jig::CSS to
|
8
|
+
# simplify the examples.
|
9
|
+
#
|
10
|
+
# An instance of Jig::CSS represents a CSS rule consisting of
|
11
|
+
# a selector list and an associated declaration block. The
|
12
|
+
# selector list or the delcaration block or both may be empty.
|
13
|
+
# Declarations are specified via a hash.
|
14
|
+
#
|
15
|
+
# C.new # => {}
|
16
|
+
# C.new('h1') # => h1 {}
|
17
|
+
# C.new(nil, 'color' => 'red') # => {color: red; }
|
18
|
+
#
|
19
|
+
# A simple CSS type selector with an empty declaration is the
|
20
|
+
# default construction:
|
21
|
+
#
|
22
|
+
# C.div # => div {}
|
23
|
+
# C.li # => li {}
|
24
|
+
#
|
25
|
+
# Rules can be combined with each other or with a hash via the
|
26
|
+
# 'pipe' operator.
|
27
|
+
#
|
28
|
+
# big = { 'font-size' => '24pt' }
|
29
|
+
# bold = { 'font-weight' => 'bold' }
|
30
|
+
# big_div = C.div | big # => div {font-size: 24pt; }
|
31
|
+
# big_bold_div = bigger | bold # => div {font-size: 24pt; font-weight: bold; }
|
32
|
+
# C.h1 | C.h2 # => h1, h2 { }
|
33
|
+
# C.h1 | big | C.h2 | bold # => h1, h2 { font-size: 24pt; font-weight: bold; }
|
34
|
+
class CSS < Jig
|
35
|
+
module IntegerHelper
|
36
|
+
def in; "#{self}in"; end
|
37
|
+
def cm; "#{self}cm"; end
|
38
|
+
def mm; "#{self}mm"; end
|
39
|
+
def pt; "#{self}pt"; end
|
40
|
+
def pc; "#{self}pc"; end
|
41
|
+
def em; "#{self}em"; end
|
42
|
+
def ex; "#{self}ex"; end
|
43
|
+
def px; "#{self}px"; end
|
44
|
+
def pct; "#{self}%"; end
|
45
|
+
end
|
46
|
+
|
47
|
+
module FloatHelper
|
48
|
+
def pct; "%.2f%%" % (self*100); end
|
49
|
+
end
|
50
|
+
|
51
|
+
Integer.class_eval { include IntegerHelper }
|
52
|
+
Float.class_eval { include FloatHelper }
|
53
|
+
|
54
|
+
Newlines = [:html, :head, :body, :title, :div, :p, :table, :script, :form]
|
55
|
+
Encode = Hash[*%w{& amp " quot > gt < lt}]
|
56
|
+
|
57
|
+
class <<self
|
58
|
+
# Construct a simple type selector based on the method name.
|
59
|
+
# C.new('div') # => div {}
|
60
|
+
# C.div # => div {}
|
61
|
+
def method_missing(sym, *args)
|
62
|
+
new(sym.to_s, *args)
|
63
|
+
end
|
64
|
+
|
65
|
+
def media(*types)
|
66
|
+
indent = Gap.new(:___) { |text| Jig.new { text.to_s.split("\n").map { |line| " #{line}" }.join("\n")} }
|
67
|
+
Jig.new("@media #{types.join(', ')} {\n", indent, "\n}\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
def import(url, *types)
|
71
|
+
Jig.new("@import url(\"#{url}\") #{types.join(', ')}")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Construct a CSS rule.
|
76
|
+
def initialize(selector='*', declarations=nil)
|
77
|
+
super(selector, :__s, " {", :__ds, to_declarations(declarations), :__de, "}").freeze
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_declarations(hash)
|
81
|
+
return nil unless hash
|
82
|
+
hash.inject(Jig.null) do |djig, (property, value)|
|
83
|
+
djig.push(
|
84
|
+
case value
|
85
|
+
when Gap
|
86
|
+
value
|
87
|
+
when Symbol
|
88
|
+
Gap.new(value) { |fill| declaration(property, fill) }
|
89
|
+
else
|
90
|
+
declaration(property, value)
|
91
|
+
end
|
92
|
+
)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Convert property/value pair for use in a CSS rule jig.
|
97
|
+
# Any underscores in the property are converted to hyphens.
|
98
|
+
# If the property ends in '!', the '!' is stripped and the
|
99
|
+
# declaration is marked with the CSS keyword '!important'.
|
100
|
+
# * If +value+ is nil or false, the empty string is returned.
|
101
|
+
# * If +value+ is a symbol, a declaration gap is returned.
|
102
|
+
# * If +value+ is a gap, the gap is returned.
|
103
|
+
# * If +value+ is a proc, method, or jig, a deferred
|
104
|
+
# declaration gap is returned by wrapping the construction
|
105
|
+
# in a lambda in a jig.
|
106
|
+
# * If the +value+ is an array, it is converted to a string
|
107
|
+
# via #join. If the property is 'font-family', the values
|
108
|
+
# are joined with a comma, otherwise a space is used.
|
109
|
+
# * Otherwise property and value are converted to strings and
|
110
|
+
# a CSS declaration string is returned.
|
111
|
+
def declaration(property, value)
|
112
|
+
case value
|
113
|
+
when nil, false
|
114
|
+
""
|
115
|
+
when Symbol
|
116
|
+
Gap.new(value) { |fill| declaration(property, fill) }
|
117
|
+
when Gap
|
118
|
+
value
|
119
|
+
when Jig
|
120
|
+
Jig.new { declaration(property, value.to_s) }
|
121
|
+
when Proc, Method
|
122
|
+
Jig.new { declaration(property, value.call) }
|
123
|
+
when Array
|
124
|
+
seperator = (property == 'font[-_]family' ? ", " : " ")
|
125
|
+
declaration(property, value.join(seperator))
|
126
|
+
else
|
127
|
+
property.to_s =~ /\A(.*[^!])(!?)\z/
|
128
|
+
property = $1.to_s.tr('_','-')
|
129
|
+
"#{property}: #{value}#{" !important" unless $2.empty?}; "
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Construct a child selector. The parent is the lhs selector and
|
134
|
+
# the child is the rhs selector.
|
135
|
+
# div > p # => "div > p {}"
|
136
|
+
def >(other)
|
137
|
+
before(:__s, " > ", other.selector).before(:__de, other.declarations)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Construct an adjacent sibling selector. The first sibling is
|
141
|
+
# the lhs selector and the other sibling is rhs selector.
|
142
|
+
# h1 + p # => "h1 + p {}"
|
143
|
+
def +(other)
|
144
|
+
before(:__s, " + ", other.selector).before(:__de, other.declarations)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Construct a general sibling selector. The first sibling is
|
148
|
+
# the lhs selector and the other sibling is rhs selector.
|
149
|
+
# div ~ p # => "div ~ p {}"
|
150
|
+
def ~(other)
|
151
|
+
before(:__s, "~", other.selector).before(:__de, other.declarations)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Construct an id selector. The id is the rhs value.
|
155
|
+
# h1 * 'chapter-one' # => "h1#chapter-one {}"
|
156
|
+
def *(id)
|
157
|
+
before(:__s, "#", id.to_s)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Construct a pseudo-selector.
|
161
|
+
# h1/:first_letter # => "h1:first-letter {}"
|
162
|
+
# a/:active # => "a:active {}"
|
163
|
+
def /(pseudo)
|
164
|
+
before(:__s, ":", pseudo.to_s)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Construct a descendent selector. The parent is the lhs selector and
|
168
|
+
# the descendent is the rhs selector.
|
169
|
+
# div >> p # => "div p {}"
|
170
|
+
def >>(other)
|
171
|
+
before(:__s, " ", other.selector).before(:__de, other.declarations)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Construct a negation pseudo class. The delcarations associated
|
175
|
+
# with the other selector are discarded.
|
176
|
+
# div - p # => "div:not(p) {}"
|
177
|
+
def -(other)
|
178
|
+
before(:__s, ":not(", other.selector, ")")
|
179
|
+
end
|
180
|
+
|
181
|
+
# Construct a nth_child pseudo class.
|
182
|
+
def nth_child(a=0,b=0)
|
183
|
+
before(:__s, ":nth-child(#{a}n+#{b})")
|
184
|
+
end
|
185
|
+
|
186
|
+
# Construct a nth_last_child pseudo class.
|
187
|
+
def nth_last_child(a=0,b=0)
|
188
|
+
before(:__s, ":nth-last-child(#{a}n+#{b})")
|
189
|
+
end
|
190
|
+
|
191
|
+
# Construct a nth-of-type pseudo class.
|
192
|
+
def nth_of_type(a=0,b=0)
|
193
|
+
before(:__s, ":nth-of-type(#{a}n+#{b})")
|
194
|
+
end
|
195
|
+
|
196
|
+
# Construct a nth-last-of-type pseudo class.
|
197
|
+
def nth_last_of_type(a=0,b=0)
|
198
|
+
before(:__s, ":nth-last-of-type(#{a}n+#{b})")
|
199
|
+
end
|
200
|
+
|
201
|
+
# Construct a lang pseudo class.
|
202
|
+
def lang(lang)
|
203
|
+
before(:__s, ":lang(#{lang})")
|
204
|
+
end
|
205
|
+
|
206
|
+
# Merge this rule with another object.
|
207
|
+
# * If the other object is a hash, the hash is converted
|
208
|
+
# to a CSS declaration list and merged with the current list.
|
209
|
+
# * If the other object is a rule, the other selectors and
|
210
|
+
# declarations are merged with the current selectors and
|
211
|
+
# declarations.
|
212
|
+
# * Any other object is assumed to be a selector string
|
213
|
+
# and is merged with the current selectors.
|
214
|
+
#
|
215
|
+
# C.div.merge(:color => 'red') # => div { color: red; }
|
216
|
+
# C.div.merge(C.h1) # => div, h1 {}
|
217
|
+
# C.div(:color => 'blue').merge(C.h1(:font_size => '10pt'))
|
218
|
+
# # => div, h1 { color: blue; font-size: 10pt }
|
219
|
+
# C.div.merge('h1, h2, h3') # => div, h1, h2, h3 {}
|
220
|
+
def merge(other)
|
221
|
+
return self unless other
|
222
|
+
case other
|
223
|
+
when Hash
|
224
|
+
before(:__de, to_declarations(other))
|
225
|
+
when self.class
|
226
|
+
before(:__s, ", ", other.selector).before(:__de, other.declarations)
|
227
|
+
else
|
228
|
+
before(:__s, ", ", other)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# Returns a standard jig representation of the CSS jig. Gaps that are
|
233
|
+
# used internally by the CSS class are closed. #to_jig should be used before
|
234
|
+
# combining one or more CSS jigs.
|
235
|
+
def to_jig
|
236
|
+
Jig.new(plug( :__s => nil, :__de => nil, :__ds => nil ))
|
237
|
+
end
|
238
|
+
|
239
|
+
alias | :merge
|
240
|
+
|
241
|
+
# Extract the selector list from the rule as a jig.
|
242
|
+
# (div | h1).selector # => Jig["div, h1"]
|
243
|
+
def selector
|
244
|
+
slice(0...index(:__s))
|
245
|
+
end
|
246
|
+
|
247
|
+
# Extract the declaration list from the rule. The list is returned as
|
248
|
+
# a jig and not as a hash.
|
249
|
+
# div(:color => 'red').declarations # => Jig["color: red; ", :__de]
|
250
|
+
def declarations
|
251
|
+
slice(index(:__ds)+1..index(:__de)-1)
|
252
|
+
end
|
253
|
+
|
254
|
+
# Missing methods are rewritten as calls to #class_, which
|
255
|
+
# constructs class selectors.
|
256
|
+
# C.div.class_('urgent') # => div.urgent {}
|
257
|
+
# C.div.urgent # => div.urgent {}
|
258
|
+
# C.div.note.caution # => div.note.caution {}
|
259
|
+
def method_missing(sym, declarations=nil)
|
260
|
+
class_(sym, declarations)
|
261
|
+
end
|
262
|
+
|
263
|
+
# Add a class selector to pending selector. Usually
|
264
|
+
# this method is called indirectly via method_missing.
|
265
|
+
# C.div.class_('urgent') # => div.urgent {}
|
266
|
+
# C.div.urgent # => div.urgent {}
|
267
|
+
def class_(klass, declarations=nil)
|
268
|
+
before(:__s, ".#{klass}") | declarations
|
269
|
+
end
|
270
|
+
|
271
|
+
# Construct an attribute selector. If the argument is a
|
272
|
+
# simple string a simple attribute selector is constructed. If
|
273
|
+
# the argument is a hash with a string as the value, an exact
|
274
|
+
# attribute selector is constructed. If the value is a regular
|
275
|
+
# expression, a partial attribute selector is constructed. If
|
276
|
+
# the key is the literal string 'lang', a language attribute
|
277
|
+
# selector is constructed.
|
278
|
+
#
|
279
|
+
# input[:type] # => input[type] {}
|
280
|
+
# input[:type => 'password'] # => input[type="password"] {}
|
281
|
+
# input[:lang => 'en'] # => input[lang|="en"] {}
|
282
|
+
# input[:class => /heading/] # => input[class=~"heading"] {}
|
283
|
+
def [](*args)
|
284
|
+
if args.size == 1 && args.first.respond_to?(:to_hash) && args.first.size == 1
|
285
|
+
k,v = *args.first.to_a.first
|
286
|
+
case v
|
287
|
+
when String
|
288
|
+
before(:__s, %Q{[#{k}="#{v}"]})
|
289
|
+
when Regexp
|
290
|
+
v = v.to_s.split(':').last.chop # strip out the processing flags
|
291
|
+
if k.to_s == 'lang'
|
292
|
+
before(:__s, %Q{[lang|="#{v}"]})
|
293
|
+
else
|
294
|
+
before(:__s, %Q{[#{k}~="#{v}"]})
|
295
|
+
end
|
296
|
+
else
|
297
|
+
self
|
298
|
+
end
|
299
|
+
elsif args.size == 1 && args.first.respond_to?(:to_s)
|
300
|
+
before(:__s, "[#{args.first}]")
|
301
|
+
else
|
302
|
+
self
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
end
|
data/lib/jig/xhtml.rb
ADDED
@@ -0,0 +1,283 @@
|
|
1
|
+
require 'jig'
|
2
|
+
require 'jig/xml'
|
3
|
+
|
4
|
+
class Jig
|
5
|
+
# Jig::XHTML is a subclass of Jig::XML and is designed to assist in the
|
6
|
+
# construction of XHTML documents.
|
7
|
+
class XHTML < XML
|
8
|
+
attr_accessor :extra
|
9
|
+
protected :extra
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
super
|
13
|
+
@extra = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize_copy(other)
|
17
|
+
super
|
18
|
+
@extra = other.extra.dup
|
19
|
+
end
|
20
|
+
|
21
|
+
def freeze
|
22
|
+
@extra.freeze
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def eid
|
27
|
+
extra[:eid]
|
28
|
+
end
|
29
|
+
|
30
|
+
def eid=(eid)
|
31
|
+
raise RuntimeError, "no eid reassignment permitted" if extra[:eid]
|
32
|
+
extra[:eid] = eid
|
33
|
+
end
|
34
|
+
|
35
|
+
class <<self
|
36
|
+
# Construct a jig for an XHTML element with _tag as the tag and include
|
37
|
+
# an ID attribute with a guaranteed unique value.
|
38
|
+
# Example:
|
39
|
+
# puts Jig::XHTML.element_with_id('div') # <div id="x2354322">\n</div>
|
40
|
+
def element_with_id(tag, *args)
|
41
|
+
attrs = { 'id' => :id }
|
42
|
+
attrs = attrs.merge!(args.pop) if args.last.respond_to?(:fetch)
|
43
|
+
args.push(Proc.new) if block_given?
|
44
|
+
args.push attrs
|
45
|
+
newjig = element(tag, *args)
|
46
|
+
newjig.eid = "x#{newjig.object_id}"
|
47
|
+
newjig.plug!(:id, newjig.eid )
|
48
|
+
end
|
49
|
+
|
50
|
+
# Construct a jig for an emtpy XHTML element with _tag as the tag and include
|
51
|
+
# an ID attribute with a guaranteed unique value. The selected id is
|
52
|
+
# accessible via the eid attribute.
|
53
|
+
# Example:
|
54
|
+
# j = Jig::XHTML.element_with_id('input', :name=>'login')
|
55
|
+
# puts j # <input name="login" id="x2354328"/>
|
56
|
+
# puts j.eid # x2354328
|
57
|
+
def element_with_id!(tag, *args)
|
58
|
+
attrs = { 'id' => :id }
|
59
|
+
attrs = attrs.merge!(args.pop) if args.last.respond_to?(:fetch)
|
60
|
+
args.push(Proc.new) if block_given?
|
61
|
+
args.push attrs
|
62
|
+
jig = element!(tag, *args)
|
63
|
+
jig.eid = "x#{newjig.object_id}"
|
64
|
+
jig.plug!(:id, jig.eid)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Construct an element based on the method name. If the method name
|
68
|
+
# ends in '_with_id' or '_with_id!', the element is constructed with
|
69
|
+
# a unique XML id attribute otherwise the Jig::XML element construction
|
70
|
+
# rules apply.
|
71
|
+
def method_missing(sym, *args, &block)
|
72
|
+
text = sym.to_s
|
73
|
+
if text.to_s =~ /_with_id!*$/
|
74
|
+
element_with_id(text.sub(/_with_id!*$/,'').to_sym, *args, &block)
|
75
|
+
else
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
DOCTYPES = {
|
81
|
+
:strict, %{"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"},
|
82
|
+
:transitional, %{"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"},
|
83
|
+
:frameset, %{"-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"}
|
84
|
+
}
|
85
|
+
|
86
|
+
# Construct an XHTML DOCTYPE declaration. The first argument, _dtype_, specifies
|
87
|
+
# the type of document: :strict, :transitional, or :frameset. Any additional
|
88
|
+
# arguments are rendered after the DOCTYPE declaration. A default gap is *not*
|
89
|
+
# inserted if their are no arguments. Examples:
|
90
|
+
#
|
91
|
+
# puts X.doctype(:strict)
|
92
|
+
# # => <!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd>
|
93
|
+
# puts X.doctype(:strict).gaps.size # 0
|
94
|
+
def doctype(dtype, *args, &block)
|
95
|
+
new(%{<!DOCTYPE html PUBLIC #{DOCTYPES.fetch(dtype)}>\n}, *args, &block)
|
96
|
+
end
|
97
|
+
|
98
|
+
# call-seq:
|
99
|
+
# xhtml([attributes]) -> a_jig
|
100
|
+
# xhtml(doctype, [attributes]) -> a_jig
|
101
|
+
# xhtml(doctype, *items, [attributes]) -> a_jig
|
102
|
+
# xhtml(*items, [attributes]) -> a_jig
|
103
|
+
# Construct a generic XHTML document. With no arguments, a transitional
|
104
|
+
# document with three gaps, <tt>:title</tt>, <tt>:head</tt>, and <tt>:___</tt>
|
105
|
+
# is generated. The default gap represents the contents of the body element.
|
106
|
+
#
|
107
|
+
# With a single symbol argument, <i>doctype</i>, an XHTMl document is generated
|
108
|
+
# with a corresponding DOCTYPE declaration (see #doctype).
|
109
|
+
#
|
110
|
+
# If any arguments are provided other than a doctype, the additional arguments
|
111
|
+
# are used as the contents of the HTML element.
|
112
|
+
#
|
113
|
+
# A trailing hash argument is assumed to represent additional XML attributes for
|
114
|
+
# the html element.
|
115
|
+
# X.xhtml # transitional document with :title, :head, and :___
|
116
|
+
# X.xhtml :strict # strict document with :title, :head, and :___
|
117
|
+
# X.xhtml(:strict, head, body) # strict document with explicit head & body
|
118
|
+
# X.xhtml(head, body) # transitional document with explicit head & body
|
119
|
+
# X.xhtml :lang => 'jp' # transition document with HTML attributes merged
|
120
|
+
def xhtml(dtype=:transitional, *args, &block)
|
121
|
+
unless Symbol === dtype
|
122
|
+
dtype,args = :transitional,args.unshift(dtype)
|
123
|
+
end
|
124
|
+
attrs = {:lang=>'en', "xml:lang"=>'en', :xmlns=>'http://www.w3.org/1999/xhtml'}
|
125
|
+
attrs.merge!(args.pop) if args.last.respond_to?(:fetch)
|
126
|
+
args.push(Proc.new) if block_given?
|
127
|
+
args.push(head(title(:title),:head),body) if args.empty?
|
128
|
+
args.push(attrs)
|
129
|
+
doctype(dtype,html(*args))
|
130
|
+
end
|
131
|
+
|
132
|
+
# A convenience method for constructing an XHTML element with a named
|
133
|
+
# CSS class and an unique XHTML element ID.
|
134
|
+
#
|
135
|
+
# X.container('span', 'urgent', 'This is urgent!')
|
136
|
+
# => <span class="urgent" id="x2337852"></span>
|
137
|
+
def container(tag, css, *args)
|
138
|
+
args.push(Proc.new) if block_given?
|
139
|
+
args.push(:class => css)
|
140
|
+
jig = element_with_id(tag, *args)
|
141
|
+
jig.send(:extra)[:css] = css
|
142
|
+
jig
|
143
|
+
end
|
144
|
+
|
145
|
+
# An even shorter way to construct a div container
|
146
|
+
#
|
147
|
+
# X.divc('urgent', 'This is urgent!')
|
148
|
+
# => <div class="urgent" id="x2337852"></div>
|
149
|
+
def divc(css_class, *args, &block)
|
150
|
+
container(:div, css_class, *args, &block)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Generate a link element for a favicon. Extra attributes
|
154
|
+
# may be specified via the optional argument, _extra_.
|
155
|
+
#
|
156
|
+
# X.link_favicon
|
157
|
+
# => <link src="/favicon.ico" type="image/x-icon" rel="icon"/>
|
158
|
+
def link_favicon(extra={})
|
159
|
+
attrs = {:type=>"image/x-icon", :rel=>"icon", :src=>'/favicon.ico'}
|
160
|
+
attrs.merge! extra
|
161
|
+
link!(attrs)
|
162
|
+
end
|
163
|
+
|
164
|
+
# XXX: is this no longer needed?
|
165
|
+
def normalize_args(args, attrs={}) # :nodoc"
|
166
|
+
attrs.merge!(args.pop) if args.last.respond_to?(:fetch)
|
167
|
+
args.push(Proc.new) if block_given?
|
168
|
+
args.push INNER if args.empty?
|
169
|
+
return args, attrs
|
170
|
+
end
|
171
|
+
|
172
|
+
# Generate a CSS style sheet element. If a 'src' attribute
|
173
|
+
# is provided the contents is empty. Without a 'src' attribute
|
174
|
+
# a CDATA block wraps the contents of the element.
|
175
|
+
#
|
176
|
+
# j = Jig::XHTML.style
|
177
|
+
# puts j.plug('/* CSS style sheet */')
|
178
|
+
#
|
179
|
+
# <style media="all" type="text/css">
|
180
|
+
# <![CDATA[
|
181
|
+
# /* CSS style sheet */
|
182
|
+
# ]]>
|
183
|
+
# </style>
|
184
|
+
def style(*args, &block)
|
185
|
+
attrs = {:type=>"text/css", :media=>"all"}
|
186
|
+
attrs.merge!(args.pop) if args.last.respond_to?(:fetch)
|
187
|
+
args.push(Proc.new) if block_given?
|
188
|
+
if attrs.has_key?(:src)
|
189
|
+
args = [attrs]
|
190
|
+
else
|
191
|
+
args = ["\n", cdata(*args.push("\n")), attrs]
|
192
|
+
end
|
193
|
+
element(:style, *args)
|
194
|
+
end
|
195
|
+
|
196
|
+
def style_link(src)
|
197
|
+
link!('rel' => 'stylesheet', 'type' => 'text/css', 'href' => src)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Generate a script element. XXX
|
201
|
+
#
|
202
|
+
# j = Jig::XHTML.script
|
203
|
+
# puts j.plug(cdata("# the script"))
|
204
|
+
#
|
205
|
+
# <script type=">
|
206
|
+
# <![CDATA[
|
207
|
+
# # the script
|
208
|
+
# ]]>
|
209
|
+
# </script>
|
210
|
+
def script(*args, &block)
|
211
|
+
attrs = args.pop if args.last.respond_to?(:fetch)
|
212
|
+
args.push(Proc.new) if block_given?
|
213
|
+
if attrs.has_key?(:fetch)
|
214
|
+
args = [attrs]
|
215
|
+
else
|
216
|
+
args.push(attrs)
|
217
|
+
end
|
218
|
+
element(:script, *args)
|
219
|
+
end
|
220
|
+
|
221
|
+
def input(*args, &block)
|
222
|
+
element_with_id!(:input, *args, &block)
|
223
|
+
end
|
224
|
+
def textarea(*args, &block)
|
225
|
+
element_with_id(:textarea, *args, &block)
|
226
|
+
end
|
227
|
+
def select(*args, &block)
|
228
|
+
element_with_id(:select, *args, &block)
|
229
|
+
end
|
230
|
+
|
231
|
+
def more(ajig, bjig)
|
232
|
+
body = div_with_id({:style => 'display: none'}, bjig)
|
233
|
+
new(a({:href=>"#", :onclick => "toggle(#{body.eid})"}, '(details)'), body)
|
234
|
+
end
|
235
|
+
|
236
|
+
# Generate a Javascript comment.
|
237
|
+
#
|
238
|
+
# j = Jig::XHTML.js_comment
|
239
|
+
# puts j.plug("comment")
|
240
|
+
#
|
241
|
+
# /* comment */
|
242
|
+
def js_comment(*args, &block)
|
243
|
+
gap = Jig::Gap.new(:comment) { |*filling|
|
244
|
+
filling.map {|item|
|
245
|
+
item.to_s.split("\n").map {|line| "// #{line}" }
|
246
|
+
}.join("\n")
|
247
|
+
}
|
248
|
+
new(gap, "\n").plug(:comment, *args)
|
249
|
+
end
|
250
|
+
|
251
|
+
# Generate a multiline Javascript comment.
|
252
|
+
#
|
253
|
+
# j = Jig::XHTML.js_comments
|
254
|
+
# puts j.plug("line 1\nline 2")
|
255
|
+
#
|
256
|
+
# /*
|
257
|
+
# line 1
|
258
|
+
# line 2
|
259
|
+
# */
|
260
|
+
def js_mlcomment(*args, &block)
|
261
|
+
new("/*\n", new(*args, &block), "\n */\n")
|
262
|
+
end
|
263
|
+
|
264
|
+
# Generate an inline script element for javascript.
|
265
|
+
# The body of the script is wrapped in a CDATA block.
|
266
|
+
#
|
267
|
+
# j = Jig::XHTML.javascript
|
268
|
+
# puts j.plug("// the script")
|
269
|
+
#
|
270
|
+
# <script type="text/javascript" language="JavaScript">
|
271
|
+
# <![CDATA[
|
272
|
+
# // the script
|
273
|
+
# ]]>
|
274
|
+
# </script>
|
275
|
+
def javascript(*args, &block)
|
276
|
+
attrs = {:type=>"text/javascript", :language=>"JavaScript"}
|
277
|
+
attrs.merge!(args.pop) if args.last.respond_to?(:fetch)
|
278
|
+
args.push(Proc.new) if block_given?
|
279
|
+
script("//<![CDATA[\n", new(*args), "\n//]]>\n", attrs)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|