cheri 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README +387 -15
- data/lib/cheri/awt.rb +4 -2
- data/lib/cheri/builder.rb +1 -0
- data/lib/cheri/builder/awt/main.rb +1 -1
- data/lib/cheri/builder/base.rb +1 -321
- data/lib/cheri/builder/config.rb +6 -2
- data/lib/cheri/builder/context.rb +103 -26
- data/lib/cheri/builder/generator.rb +38 -32
- data/lib/cheri/builder/html/element.rb +106 -16
- data/lib/cheri/builder/html/main.rb +125 -19
- data/lib/cheri/builder/html/types.rb +12 -2
- data/lib/cheri/builder/main.rb +200 -7
- data/lib/cheri/builder/markup.rb +608 -0
- data/lib/cheri/builder/swing/main.rb +2 -2
- data/lib/cheri/builder/xml/connecter.rb +11 -0
- data/lib/cheri/builder/xml/element.rb +141 -22
- data/lib/cheri/builder/xml/main.rb +188 -32
- data/lib/cheri/builder/xml/types.rb +5 -0
- data/lib/cheri/cheri.rb +1 -1
- data/lib/cheri/explorer.rb +4 -2
- data/lib/cheri/explorer/explorer.rb +4 -2
- data/lib/cheri/java/builder/main.rb +32 -11
- data/lib/cheri/jruby.rb +4 -2
- data/lib/cheri/jruby/explorer.rb +4 -2
- data/lib/cheri/swing.rb +4 -2
- metadata +3 -2
@@ -112,12 +112,22 @@ Types = Hash[
|
|
112
112
|
:frame => EmptyElem,
|
113
113
|
:text => TextElem,
|
114
114
|
:t => TextElem,
|
115
|
-
:
|
116
|
-
:
|
115
|
+
:text! => TextElem,
|
116
|
+
:t1 => TextElem,
|
117
|
+
:proc! => ProcElem,
|
118
|
+
:esc => EscElem,
|
119
|
+
:esc! => EscElem,
|
120
|
+
:comment => CommentElem,
|
121
|
+
:comment! => CommentElem,
|
117
122
|
|
118
123
|
# TODO: iframe, noframes
|
119
124
|
|
120
125
|
]
|
121
126
|
|
127
|
+
Aliases = Hash[
|
128
|
+
:para => :p,
|
129
|
+
:p! => :p,
|
130
|
+
]
|
131
|
+
|
122
132
|
end #Html
|
123
133
|
end #Cheri
|
data/lib/cheri/builder/main.rb
CHANGED
@@ -183,11 +183,11 @@ end
|
|
183
183
|
|
184
184
|
# a base class for proxies
|
185
185
|
class BaseProxy
|
186
|
-
|
186
|
+
alias_method :__methods__,:methods
|
187
|
+
keep = /^(__|<|>|=)|^(class|inspect|to_s)$|(\?|!|=)$/
|
187
188
|
instance_methods.each do |m|
|
188
189
|
undef_method m unless m =~ keep
|
189
190
|
end
|
190
|
-
|
191
191
|
|
192
192
|
class << self
|
193
193
|
def impl(meths)
|
@@ -245,9 +245,33 @@ end #self
|
|
245
245
|
end #BaseProxy
|
246
246
|
|
247
247
|
class CheriProxy < BaseProxy
|
248
|
-
|
249
|
-
|
250
|
-
|
248
|
+
def [](*args)
|
249
|
+
h = Hash === args.last ? args.pop : {}
|
250
|
+
args.each {|a| h[a] = true}
|
251
|
+
h.each_pair do |name,value|
|
252
|
+
raise Cheri.type_error(name,Symbol) unless Symbol === name
|
253
|
+
case name
|
254
|
+
when :alias
|
255
|
+
if Array === value
|
256
|
+
raise ArgumentError,"odd number of values for :alias" if ((len = value.length) & 1) == 1
|
257
|
+
v = {}
|
258
|
+
(len>>1).times {|i| v[value[i*2]] = value[i*2+1] }
|
259
|
+
value = v
|
260
|
+
else
|
261
|
+
raise Cheri.type_error(value,Hash,Array) unless Hash === value
|
262
|
+
end
|
263
|
+
aliases = @ctx.aliases
|
264
|
+
value.each_pair do |als,name|
|
265
|
+
als = als.to_sym if String === als
|
266
|
+
name = name.to_sym if String === name
|
267
|
+
raise Cheri.type_error(als,Symbol,String) unless Symbol === als
|
268
|
+
raise Cheri.type_error(name,Symbol,String) unless Symbol === name
|
269
|
+
aliases[als] = name
|
270
|
+
end
|
271
|
+
else raise NameError,"unknown cheri[] option #{name}"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
251
275
|
end #CheriProxy
|
252
276
|
|
253
277
|
class CheriFrame
|
@@ -261,6 +285,80 @@ class CheriFrame
|
|
261
285
|
end
|
262
286
|
end #CheriFrame
|
263
287
|
|
288
|
+
class BaseOptions < Hash
|
289
|
+
def initialize(opts=nil)
|
290
|
+
raise Cheri.type_error(opts,self.class,Hash) if opts && !(Hash === opts)
|
291
|
+
super()
|
292
|
+
merge!(opts) if opts
|
293
|
+
end
|
294
|
+
|
295
|
+
def store(key,value)
|
296
|
+
val = validate(key,value)
|
297
|
+
if nil == val
|
298
|
+
delete(key)
|
299
|
+
else
|
300
|
+
super(key,val)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
#alias_method :store,:[]=
|
304
|
+
|
305
|
+
def validate_boolean(value)
|
306
|
+
raise Cheri.type_error(value,TrueClass,FalseClass,NilClass) unless true == value || false == value
|
307
|
+
value
|
308
|
+
end
|
309
|
+
|
310
|
+
def validate_boolean_nil(value)
|
311
|
+
raise Cheri.type_error(value,TrueClass,FalseClass,NilClass) unless true == value || false == value || nil == value
|
312
|
+
value
|
313
|
+
end
|
314
|
+
|
315
|
+
def validate_fixnum(value)
|
316
|
+
raise Cheri.type_error(value,Fixnum) unless Fixnum === value
|
317
|
+
value
|
318
|
+
end
|
319
|
+
|
320
|
+
def validate_fixnum_nil(value)
|
321
|
+
raise Cheri.type_error(value,Fixnum) unless Fixnum === value || nil == value
|
322
|
+
value
|
323
|
+
end
|
324
|
+
|
325
|
+
def validate_symbol(value)
|
326
|
+
raise Cheri.type_error(value,Symbol) unless Symbol === value
|
327
|
+
value
|
328
|
+
end
|
329
|
+
|
330
|
+
def validate_string(value)
|
331
|
+
raise Cheri.type_error(value,String) unless String === value
|
332
|
+
value
|
333
|
+
end
|
334
|
+
|
335
|
+
def merge(other)
|
336
|
+
raise Cheri.type_error(other,self.class,Hash) unless Hash === other
|
337
|
+
opts = self.dup
|
338
|
+
other.each_pair {|k,v| opts.store(k,v) }
|
339
|
+
opts
|
340
|
+
end
|
341
|
+
|
342
|
+
def merge!(other)
|
343
|
+
raise Cheri.type_error(other,self.class,Hash) unless Hash === other
|
344
|
+
other.each_pair {|k,v| store(k,v) }
|
345
|
+
self
|
346
|
+
end
|
347
|
+
|
348
|
+
def ingest_args(*args)
|
349
|
+
args.each do |arg|
|
350
|
+
if Symbol === arg
|
351
|
+
store(arg,true)
|
352
|
+
elsif Hash === arg
|
353
|
+
merge!(arg)
|
354
|
+
else
|
355
|
+
raise Cheri.type_error(arg,Symbol,Hash)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
self
|
359
|
+
end
|
360
|
+
end #BaseOptions
|
361
|
+
|
264
362
|
module DefaultConsumer
|
265
363
|
G = 'get_' #:nodoc:
|
266
364
|
S = 'set_' #:nodoc:
|
@@ -271,7 +369,6 @@ I = 'is_' #:nodoc:
|
|
271
369
|
#
|
272
370
|
def self.consume(ctx,bld,sym,*args,&k)
|
273
371
|
obj = bld.object
|
274
|
-
puts "default consumer called for #{sym}"
|
275
372
|
s = sym.to_s
|
276
373
|
# if sym is already clearly a getter/setter/is-er (xxx=, xxx?, get_xxx, set_xxx, is_xxx),
|
277
374
|
# then leave it as is.
|
@@ -330,7 +427,6 @@ DefaultConnecter = TypeConnecter.new do
|
|
330
427
|
if parent.respond_to?(snd = (s = sym.to_s) + Eq) ||
|
331
428
|
parent.respond_to?(snd = St + s) ||
|
332
429
|
parent.respond_to?(snd = :add)
|
333
|
-
#puts "Builder::DefaultConnecter for #{parent}, #{obj}: #{snd}"
|
334
430
|
parent.__send__(snd,obj) rescue nil
|
335
431
|
end
|
336
432
|
nil
|
@@ -478,6 +574,103 @@ DefaultFactory = SuperFactory.new do |f|
|
|
478
574
|
f << CheriYieldFactory
|
479
575
|
end
|
480
576
|
|
577
|
+
# BuildType used with generic factories/builders
|
578
|
+
class BuildType
|
579
|
+
BLD_PARENT = 1 << 0
|
580
|
+
BLD_CHILD = 1 << 1
|
581
|
+
BLD_ANY = 1 << 2
|
582
|
+
BLD_DEFAULT = BLD_PARENT | BLD_CHILD
|
583
|
+
|
584
|
+
def initialize(clazz,sym=nil,&k)
|
585
|
+
raise Cheri.type_error(clazz,Class) unless Class === clazz
|
586
|
+
@clazz = clazz
|
587
|
+
if sym
|
588
|
+
raise Cheri.type_error(sym,Symbol) unless Symbol === sym
|
589
|
+
@sym = sym
|
590
|
+
end
|
591
|
+
@flags = BLD_DEFAULT
|
592
|
+
instance_eval(&k) if k
|
593
|
+
end
|
594
|
+
|
595
|
+
def clazz
|
596
|
+
@clazz
|
597
|
+
end
|
598
|
+
|
599
|
+
def sym
|
600
|
+
@sym
|
601
|
+
end
|
602
|
+
|
603
|
+
def sym=(sym)
|
604
|
+
raise Cheri.type_error(sym,Symbol) unless Symbol === sym
|
605
|
+
@sym = sym
|
606
|
+
end
|
607
|
+
|
608
|
+
def flags
|
609
|
+
@flags || BLD_DEFAULT
|
610
|
+
end
|
611
|
+
|
612
|
+
def build_as(*opts)
|
613
|
+
@flags = 0
|
614
|
+
opts.each do |opt|
|
615
|
+
raise Cheri.type_error(opt,Symbol) unless Symbol === opt
|
616
|
+
case opt
|
617
|
+
when :parent : @flags |= BLD_PARENT
|
618
|
+
when :child : @flags |= BLD_CHILD
|
619
|
+
when :parent_any : @flags |= BLD_ANY
|
620
|
+
when :default : @flags |= BLD_DEFAULT
|
621
|
+
else
|
622
|
+
raise ArgumentError,"invalid build_as type: #{opt}"
|
623
|
+
end
|
624
|
+
end
|
625
|
+
@flags = BLD_DEFAULT if @flags == 0
|
626
|
+
end
|
627
|
+
|
628
|
+
def parent?
|
629
|
+
(@flags & BLD_PARENT) != 0
|
630
|
+
end
|
631
|
+
|
632
|
+
def child?
|
633
|
+
(@flags & BLD_CHILD) != 0
|
634
|
+
end
|
635
|
+
|
636
|
+
def any?
|
637
|
+
(@flags & BLD_ANY) != 0
|
638
|
+
end
|
639
|
+
|
640
|
+
def ==(other)
|
641
|
+
if BuildType === other
|
642
|
+
@clazz == other.clazz
|
643
|
+
else
|
644
|
+
@clazz == other
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
def eql?(other)
|
649
|
+
if BuildType === other
|
650
|
+
@clazz.eql?(other.clazz)
|
651
|
+
else
|
652
|
+
@clazz.eql?(other)
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
end #BuildType
|
657
|
+
|
658
|
+
class BuildTypes < Hash
|
659
|
+
def []=(sym,type)
|
660
|
+
raise Cheri.type_error(sym,Symbol) unless Symbol === sym
|
661
|
+
raise Cheri.type_error(type,BuildType) unless BuildType === type
|
662
|
+
super
|
663
|
+
end
|
664
|
+
alias_method :store,:[]=
|
665
|
+
|
666
|
+
def invert
|
667
|
+
inv = {}
|
668
|
+
each_pair do |sym,type|
|
669
|
+
inv[type.clazz] = sym
|
670
|
+
end
|
671
|
+
inv
|
672
|
+
end
|
673
|
+
end #BuildTypes
|
481
674
|
|
482
675
|
end #Builder
|
483
676
|
end #Cheri
|
@@ -0,0 +1,608 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
#
|
24
|
+
|
25
|
+
module Cheri
|
26
|
+
module Builder
|
27
|
+
|
28
|
+
class MarkupException < Cheri::CheriException; end
|
29
|
+
|
30
|
+
# Methods to support content (primarily intended for use with XML/HTML markup).
|
31
|
+
# Include after Attributes if both are used.
|
32
|
+
module Content
|
33
|
+
def initialize(*r,&k)
|
34
|
+
super
|
35
|
+
@args.each do |arg|
|
36
|
+
add arg
|
37
|
+
end if @args
|
38
|
+
end
|
39
|
+
|
40
|
+
# Adds +value+ to the content array (@cont) for this object if #add?(+value+)
|
41
|
+
# returns +true+.
|
42
|
+
def add(value)
|
43
|
+
if add?(value)
|
44
|
+
(@cont ||= []) << value
|
45
|
+
@data = true unless Markup === value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
alias_method :<<, :add
|
49
|
+
|
50
|
+
# Override to validate content before it is added. The default
|
51
|
+
# implementation accepts any value.
|
52
|
+
def add?(value)
|
53
|
+
true
|
54
|
+
end
|
55
|
+
private :add?
|
56
|
+
|
57
|
+
# Returns the content array (@cont) if present, otherwise +nil+.
|
58
|
+
def content
|
59
|
+
@cont
|
60
|
+
end
|
61
|
+
|
62
|
+
# Iterates over the content array (@cont) for this object. Equivalent to
|
63
|
+
# calling #content#each.
|
64
|
+
def each
|
65
|
+
@cont.each do |content_elem|
|
66
|
+
yield content_elem
|
67
|
+
end if @cont && block_given?
|
68
|
+
end
|
69
|
+
end #Content
|
70
|
+
|
71
|
+
# Methods to support attributes (primarily intended for use with XML/HTML markup).
|
72
|
+
# Include before Content if both are used.
|
73
|
+
module Attributes
|
74
|
+
def initialize(*r,&k)
|
75
|
+
super
|
76
|
+
if (args = @args) && Hash === args.last
|
77
|
+
args.pop.each_pair {|n,v| set(n,v) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Sets an attribute. Called by #initialize to add/validate attributes
|
82
|
+
# passed as arguments.
|
83
|
+
def set(name,value)
|
84
|
+
if @amap && (mname = @amap[name])
|
85
|
+
name = mname
|
86
|
+
end
|
87
|
+
name = name.to_s.strip
|
88
|
+
if set?(name,value)
|
89
|
+
(@attrs ||= {})[name] = value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
alias_method :[]=, :set
|
93
|
+
|
94
|
+
# Override to validate each attribute before it is set. The default
|
95
|
+
# implementation accepts any name/value.
|
96
|
+
def set?(name,value)
|
97
|
+
true
|
98
|
+
end
|
99
|
+
private :set?
|
100
|
+
|
101
|
+
# Returns the attibutes hash (@attrs), if any.
|
102
|
+
def attrs
|
103
|
+
@attrs
|
104
|
+
end
|
105
|
+
|
106
|
+
# Returns the attribute value for +name+, or +nil+ if not set.
|
107
|
+
def [](name)
|
108
|
+
@attrs[name] if @attrs
|
109
|
+
end
|
110
|
+
|
111
|
+
# Iterates over the attributes hash (@attrs) for this object. Equivalent to
|
112
|
+
# calling #attrs#each_pair.
|
113
|
+
def each_attr
|
114
|
+
@attrs.each_pair do |n,v|
|
115
|
+
yield n,v
|
116
|
+
end if @attrs && block_given?
|
117
|
+
end
|
118
|
+
|
119
|
+
end #Attributes
|
120
|
+
|
121
|
+
# Markup methods, used by Markup and MarkupLike
|
122
|
+
module MarkupMethods
|
123
|
+
# :stopdoc:
|
124
|
+
TC = '</'.freeze
|
125
|
+
TE = '>'.freeze
|
126
|
+
TEC = '></'.freeze
|
127
|
+
TO = '<'.freeze
|
128
|
+
TCE = ' />'.freeze
|
129
|
+
LF = "\n".freeze
|
130
|
+
TELF = ">\n".freeze
|
131
|
+
S = ' '.freeze
|
132
|
+
Q = '"'.freeze
|
133
|
+
E = '='.freeze
|
134
|
+
# :startdoc:
|
135
|
+
|
136
|
+
# Append this markup to +str+ (or an empty string if +str+ is not supplied),
|
137
|
+
# and return the result. Redirects to #to_io if +str+ is not a String. Both
|
138
|
+
# methods use the +<<+ operator to append their output; this method (like the other
|
139
|
+
# ..._s methods) is faster because Fixnum values can be appended directly, without
|
140
|
+
# being converted to (or passed as) strings. This takes on particular significance
|
141
|
+
# when output is being escaped, and values passed one character at a time.
|
142
|
+
def to_s(str='')
|
143
|
+
unless @fmt
|
144
|
+
open_s(str)
|
145
|
+
attr_s(str) if @attrs
|
146
|
+
if @cont
|
147
|
+
str << ?>
|
148
|
+
cont_s(str)
|
149
|
+
close_s(str)
|
150
|
+
else
|
151
|
+
empty_s(str)
|
152
|
+
end
|
153
|
+
else
|
154
|
+
indent_s(str)
|
155
|
+
open_s(str)
|
156
|
+
attr_s(str) if @attrs
|
157
|
+
if @cont
|
158
|
+
unless @data
|
159
|
+
str << TELF
|
160
|
+
cont_s(str)
|
161
|
+
indent_s(str)
|
162
|
+
else
|
163
|
+
str << ?>
|
164
|
+
cont_s(str)
|
165
|
+
end
|
166
|
+
close_s(str)
|
167
|
+
str << 10
|
168
|
+
else
|
169
|
+
empty_s(str)
|
170
|
+
str << 10
|
171
|
+
end
|
172
|
+
end
|
173
|
+
str
|
174
|
+
end
|
175
|
+
|
176
|
+
# Calls #to_s. Provided so that Markup/MarkupLike objects may be coerced to
|
177
|
+
# Strings automatically. Implemented this way rather than through alias_method
|
178
|
+
# to counter the possibility that overriders will forget to re-alias to_str.
|
179
|
+
def to_str(str='')
|
180
|
+
to_s(str)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Append value to the supplied output stream +ios+. If #esc is overridden
|
184
|
+
# value will be escaped first.
|
185
|
+
def to_io(ios)
|
186
|
+
unless @fmt
|
187
|
+
open_io(ios)
|
188
|
+
attr_io(ios) if @attrs
|
189
|
+
if @cont
|
190
|
+
ios << TE
|
191
|
+
cont_io(ios)
|
192
|
+
close_io(ios)
|
193
|
+
else
|
194
|
+
empty_io(ios)
|
195
|
+
end
|
196
|
+
else
|
197
|
+
indent_io(ios)
|
198
|
+
open_io(ios)
|
199
|
+
attr_io(ios) if @attrs
|
200
|
+
if @cont
|
201
|
+
unless @data
|
202
|
+
ios << TELF
|
203
|
+
cont_io(ios)
|
204
|
+
indent_io(ios)
|
205
|
+
else
|
206
|
+
ios << TE
|
207
|
+
cont_io(ios)
|
208
|
+
end
|
209
|
+
close_io(ios)
|
210
|
+
ios << LF
|
211
|
+
else
|
212
|
+
empty_io(ios)
|
213
|
+
ios << LF
|
214
|
+
end
|
215
|
+
end
|
216
|
+
ios
|
217
|
+
end
|
218
|
+
|
219
|
+
# Append open tag (<tagname) to +str+ using +<<+.
|
220
|
+
def open_s(str)
|
221
|
+
str << ?< << (@tag ||= (@ns && :no_ns != @ns ? "#{@ns}:#{@sym}" : @sym.to_s))
|
222
|
+
end
|
223
|
+
|
224
|
+
# Append open tag (<tagname) to +ios+ using +<<+.
|
225
|
+
def open_io(ios)
|
226
|
+
ios << TO << (@tag ||= (@ns && :no_ns != @ns ? "#{@ns}:#{@sym}" : @sym.to_s))
|
227
|
+
end
|
228
|
+
|
229
|
+
# Append close tag (</tagname>) to +str+ using +<<+.
|
230
|
+
def close_s(str)
|
231
|
+
str << TC << @tag << ?>
|
232
|
+
end
|
233
|
+
|
234
|
+
# Append close tag (</tagname>) to +ios+ using +<<+. (Use slightly faster
|
235
|
+
# #close_s for strings.)
|
236
|
+
def close_io(ios)
|
237
|
+
ios << TC << @tag << TE
|
238
|
+
end
|
239
|
+
|
240
|
+
# Append empty close tag (...></tagname>) to +str+. Note that HTML/XML elements
|
241
|
+
# with empty content models should close with <tt>' />'</tt> instead.
|
242
|
+
def empty_s(str)
|
243
|
+
str << TEC << @tag << ?>
|
244
|
+
end
|
245
|
+
|
246
|
+
# Append empty close tag (...></tagname>) to +ios+. Note that HTML/XML elements
|
247
|
+
# with empty content models should close with <tt>' />'</tt> instead.
|
248
|
+
def empty_io(ios)
|
249
|
+
ios << TEC << @tag << TE
|
250
|
+
end
|
251
|
+
|
252
|
+
def indent_s(str)
|
253
|
+
if (ind = margin + (indent * depth)) > 0
|
254
|
+
str << Markup.sp(ind)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
alias_method :indent_io,:indent_s
|
258
|
+
|
259
|
+
# Writes attributes to a new string, or appends to an existing string
|
260
|
+
# (using <<) if supplied.
|
261
|
+
def attr_s(str='')
|
262
|
+
@attrs.each_pair do |k,v|
|
263
|
+
str << 32 << k << ?= << 34
|
264
|
+
esc(v.to_s,str)
|
265
|
+
str << 34
|
266
|
+
end if @attrs
|
267
|
+
str
|
268
|
+
end
|
269
|
+
|
270
|
+
# Writes attributes to the supplied IO stream (or Array, etc.) using <<.
|
271
|
+
def attr_io(ios)
|
272
|
+
@attrs.each_pair do |k,v|
|
273
|
+
ios << S << k << E << Q << esc(v.to_s) << Q
|
274
|
+
end if @attrs
|
275
|
+
ios
|
276
|
+
end
|
277
|
+
|
278
|
+
# Appends concatenated and escaped content (@cont) to +str+, if supplied, using
|
279
|
+
# the +<<+ operator. Assumes String === +str+. Use #cont_io to append to IO or Array.
|
280
|
+
def cont_s(str='')
|
281
|
+
@cont.each do |v|
|
282
|
+
case v
|
283
|
+
when String : esc(v,str)
|
284
|
+
when Markup
|
285
|
+
v.data! if @data
|
286
|
+
v.depth = depth + 1
|
287
|
+
v.to_s(str)
|
288
|
+
when MarkupLike
|
289
|
+
v.data! if @data
|
290
|
+
v.to_s(str)
|
291
|
+
else esc(v.to_s,str)
|
292
|
+
end
|
293
|
+
end if @cont
|
294
|
+
str
|
295
|
+
end
|
296
|
+
|
297
|
+
# Appends concatenated and escaped content (@cont) to +ios+ using the +<<+ operator.
|
298
|
+
# Use for appending to IO or Array. Use #cont_s to append more efficiently to strings.
|
299
|
+
def cont_io(ios)
|
300
|
+
@cont.each do |v|
|
301
|
+
case v
|
302
|
+
when String : ios << esc(v)
|
303
|
+
when Markup
|
304
|
+
v.data! if @data
|
305
|
+
v.depth = depth + 1
|
306
|
+
v.to_io(ios)
|
307
|
+
when MarkupLike
|
308
|
+
v.data! if @data
|
309
|
+
v.to_io(ios)
|
310
|
+
else ios << esc(v.to_s)
|
311
|
+
end
|
312
|
+
end if @cont
|
313
|
+
ios
|
314
|
+
end
|
315
|
+
|
316
|
+
# Override to escape values (default implementation appends or returns
|
317
|
+
# the input value unaltered).
|
318
|
+
def esc(inp,out=nil)
|
319
|
+
out ? out << inp : inp
|
320
|
+
end
|
321
|
+
|
322
|
+
def format?
|
323
|
+
@fmt
|
324
|
+
end
|
325
|
+
|
326
|
+
def format!
|
327
|
+
@fmt = true
|
328
|
+
end
|
329
|
+
|
330
|
+
def format=(fmt)
|
331
|
+
@fmt = fmt
|
332
|
+
end
|
333
|
+
|
334
|
+
# Returns +true+ if content includes any non-Markup data. Not calling this cdata, as
|
335
|
+
# that might not be accurate. Used by formatting code.
|
336
|
+
def data?
|
337
|
+
@data
|
338
|
+
end
|
339
|
+
|
340
|
+
# Indicate that this element is embedded in data (mixed content) and should
|
341
|
+
# therefore not be formatted. This element should convey this to its
|
342
|
+
# child elements, if any.
|
343
|
+
def data!
|
344
|
+
@data = true
|
345
|
+
@fmt = false
|
346
|
+
end
|
347
|
+
|
348
|
+
def margin
|
349
|
+
@mrg || @ctx[:margin] || 0
|
350
|
+
end
|
351
|
+
|
352
|
+
def margin=(n)
|
353
|
+
@mrg = n
|
354
|
+
end
|
355
|
+
|
356
|
+
def indent
|
357
|
+
@idt || @ctx[:indent] || 0
|
358
|
+
end
|
359
|
+
|
360
|
+
def indent=(n)
|
361
|
+
@idt = n
|
362
|
+
end
|
363
|
+
|
364
|
+
def depth
|
365
|
+
@dpt || 0
|
366
|
+
end
|
367
|
+
|
368
|
+
def depth=(n)
|
369
|
+
@dpt = n
|
370
|
+
end
|
371
|
+
|
372
|
+
def tag
|
373
|
+
@tag
|
374
|
+
end
|
375
|
+
|
376
|
+
def tag=(tag)
|
377
|
+
@tag = tag
|
378
|
+
end
|
379
|
+
|
380
|
+
# namespace
|
381
|
+
def ns
|
382
|
+
@ns
|
383
|
+
end
|
384
|
+
|
385
|
+
# set namespace
|
386
|
+
def ns=(ns)
|
387
|
+
@ns = ns
|
388
|
+
end
|
389
|
+
end #MarkupMethods
|
390
|
+
|
391
|
+
module Markup
|
392
|
+
include Attributes
|
393
|
+
include Content
|
394
|
+
include MarkupMethods
|
395
|
+
# :stopdoc:
|
396
|
+
@s = {}
|
397
|
+
# :startdoc:
|
398
|
+
|
399
|
+
# Return cached spaces string of length +n+
|
400
|
+
def self.sp(n)
|
401
|
+
@s[n] ||= (S * n).freeze
|
402
|
+
end
|
403
|
+
end #Markup
|
404
|
+
|
405
|
+
# Includes the functionality of Markup, but isn't treated as Markup
|
406
|
+
# by other components. Used for Text/Esc elements, etc. so they can
|
407
|
+
# still embed Markup. (Useful for outputting viewable HTML, etc.)
|
408
|
+
module MarkupLike
|
409
|
+
include Attributes
|
410
|
+
include Content
|
411
|
+
include MarkupMethods
|
412
|
+
end #MarkupLike
|
413
|
+
|
414
|
+
module EmptyMarkup
|
415
|
+
include Markup
|
416
|
+
# :stopdoc:
|
417
|
+
TCE = ' />'.freeze
|
418
|
+
# :startdoc:
|
419
|
+
|
420
|
+
def add?(value)
|
421
|
+
false
|
422
|
+
end
|
423
|
+
|
424
|
+
def empty_s(str='')
|
425
|
+
str << TCE
|
426
|
+
end
|
427
|
+
|
428
|
+
def empty_io(ios)
|
429
|
+
ios << TCE
|
430
|
+
end
|
431
|
+
|
432
|
+
end #EmptyMarkup
|
433
|
+
|
434
|
+
module Comment
|
435
|
+
include Markup
|
436
|
+
# :stopdoc:
|
437
|
+
CO = '<!-- '.freeze
|
438
|
+
CC = ' -->'.freeze
|
439
|
+
CCLF = " -->\n".freeze
|
440
|
+
SPSP = ' '.freeze
|
441
|
+
# :startdoc:
|
442
|
+
|
443
|
+
def set?(n,v)
|
444
|
+
raise MarkupException,"attribute not allowed for comment #{@sym}: #{n}=#{v}"
|
445
|
+
end
|
446
|
+
private :set?
|
447
|
+
|
448
|
+
def to_s(str='')
|
449
|
+
return to_io(str) unless String === str
|
450
|
+
unless @fmt
|
451
|
+
str << CO
|
452
|
+
cont_s(str) if @cont
|
453
|
+
str << CC
|
454
|
+
else
|
455
|
+
indent_s(str)
|
456
|
+
str << CO
|
457
|
+
if @cont
|
458
|
+
str << 10
|
459
|
+
@data = nil
|
460
|
+
cont_s(str)
|
461
|
+
indent_s(str)
|
462
|
+
str << CCLF
|
463
|
+
else
|
464
|
+
str << CCLF
|
465
|
+
end
|
466
|
+
end
|
467
|
+
str
|
468
|
+
end
|
469
|
+
|
470
|
+
def to_io(ios)
|
471
|
+
unless @fmt
|
472
|
+
ios << CO
|
473
|
+
cont_io(ios) if @cont
|
474
|
+
ios << CC
|
475
|
+
else
|
476
|
+
indent_io(ios)
|
477
|
+
ios << CO
|
478
|
+
if @cont
|
479
|
+
ios << LF
|
480
|
+
@data = nil
|
481
|
+
cont_io(ios)
|
482
|
+
indent_io(ios)
|
483
|
+
ios << CCLF
|
484
|
+
else
|
485
|
+
ios << CCLF
|
486
|
+
end
|
487
|
+
end
|
488
|
+
ios
|
489
|
+
end
|
490
|
+
|
491
|
+
def cont_s(str='')
|
492
|
+
@cont.each do |v|
|
493
|
+
case v
|
494
|
+
when String
|
495
|
+
if @fmt
|
496
|
+
indent_s(str)
|
497
|
+
str << SPSP
|
498
|
+
esc(v,str)
|
499
|
+
str << 10
|
500
|
+
else
|
501
|
+
esc(v,str)
|
502
|
+
end
|
503
|
+
when Markup
|
504
|
+
v.data! if @data
|
505
|
+
v.depth = depth + 1
|
506
|
+
v.to_s(str)
|
507
|
+
when MarkupLike
|
508
|
+
v.data! if @data
|
509
|
+
v.to_s(str)
|
510
|
+
else esc(v.to_s,str)
|
511
|
+
end
|
512
|
+
end if @cont
|
513
|
+
str
|
514
|
+
end
|
515
|
+
def cont_io(ios)
|
516
|
+
@cont.each do |v|
|
517
|
+
case v
|
518
|
+
when String
|
519
|
+
if @fmt
|
520
|
+
indent_io(ios)
|
521
|
+
ios << SPSP
|
522
|
+
ios << esc(v)
|
523
|
+
ios << LF
|
524
|
+
else
|
525
|
+
ios << esc(v)
|
526
|
+
end
|
527
|
+
when Markup
|
528
|
+
v.data! if @data
|
529
|
+
v.depth = depth + 1
|
530
|
+
v.to_io(ios)
|
531
|
+
when MarkupLike
|
532
|
+
v.data! if @data
|
533
|
+
v.to_io(ios)
|
534
|
+
else ios << esc(v.to_s)
|
535
|
+
end
|
536
|
+
end if @cont
|
537
|
+
ios
|
538
|
+
end
|
539
|
+
|
540
|
+
end #Comment
|
541
|
+
|
542
|
+
module MarkupBuilder
|
543
|
+
include Builder
|
544
|
+
include Markup
|
545
|
+
|
546
|
+
def object
|
547
|
+
self
|
548
|
+
end
|
549
|
+
|
550
|
+
def run
|
551
|
+
if (k = @blk) && (val = @ctx.call(self,&k))
|
552
|
+
add(val) if String === val
|
553
|
+
end
|
554
|
+
self
|
555
|
+
end
|
556
|
+
end #MarkupBuilder
|
557
|
+
|
558
|
+
module MarkupLikeBuilder
|
559
|
+
include Builder
|
560
|
+
include MarkupLike
|
561
|
+
|
562
|
+
def object
|
563
|
+
self
|
564
|
+
end
|
565
|
+
|
566
|
+
def run
|
567
|
+
if (k = @blk) && (val = @ctx.call(self,&k))
|
568
|
+
add(val) if String === val
|
569
|
+
end
|
570
|
+
self
|
571
|
+
end
|
572
|
+
end #MarkupLikeBuilder
|
573
|
+
|
574
|
+
module EmptyMarkupBuilder
|
575
|
+
include Builder
|
576
|
+
include EmptyMarkup
|
577
|
+
|
578
|
+
def object
|
579
|
+
self
|
580
|
+
end
|
581
|
+
|
582
|
+
def run
|
583
|
+
if (k = @blk) && (val = @ctx.call(self,&k))
|
584
|
+
# this should fail in add?
|
585
|
+
add(val) if String === val
|
586
|
+
end
|
587
|
+
self
|
588
|
+
end
|
589
|
+
end #EmptyMarkupBuilder
|
590
|
+
|
591
|
+
module CommentBuilder
|
592
|
+
include Builder
|
593
|
+
include Comment
|
594
|
+
|
595
|
+
def object
|
596
|
+
self
|
597
|
+
end
|
598
|
+
|
599
|
+
def run
|
600
|
+
if (k = @blk) && (val = @ctx.call(self,&k))
|
601
|
+
add(val) if String === val
|
602
|
+
end
|
603
|
+
self
|
604
|
+
end
|
605
|
+
end #CommentBuilder
|
606
|
+
|
607
|
+
end #Builder
|
608
|
+
end #Cheri
|