cheri 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -112,12 +112,22 @@ Types = Hash[
112
112
  :frame => EmptyElem,
113
113
  :text => TextElem,
114
114
  :t => TextElem,
115
- :proc => ProcElem,
116
- :esc => EscElem
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
@@ -183,11 +183,11 @@ end
183
183
 
184
184
  # a base class for proxies
185
185
  class BaseProxy
186
- keep = /^(methods|instance_|__|=|class|to_s|eql\?|equal\?|inspect|instance_eval|instance_exec|respond_to\?)/
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
- # def [](opts)
249
- # self
250
- # end
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