cheri 0.0.5 → 0.0.6

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.
@@ -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