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.
- 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
@@ -87,7 +87,7 @@ end #self
|
|
87
87
|
# Duplicating this here rather than including Cheri::AWT. (See note re: performance)
|
88
88
|
#++
|
89
89
|
def awt(*r,&k)
|
90
|
-
if
|
90
|
+
if ctx = __cheri_ctx
|
91
91
|
if k
|
92
92
|
AWTFrame.new(ctx,*r,&k).run
|
93
93
|
else
|
@@ -101,7 +101,7 @@ end #self
|
|
101
101
|
# swing([*args] [, &block]) -> SwingProxy if no block given, else result of block
|
102
102
|
#
|
103
103
|
def swing(*r,&k)
|
104
|
-
if
|
104
|
+
if ctx = __cheri_ctx
|
105
105
|
if k
|
106
106
|
if ctx.empty? && (c = ctx.client).kind_of?(RPC) || c.kind_of?(JComp)
|
107
107
|
ctx.fsend(CheriYieldFactory,:cheri_yield,c,&k)
|
@@ -36,6 +36,17 @@ XmlConnecter = Cheri::Builder::TypeConnecter.new do
|
|
36
36
|
connect XmlElement
|
37
37
|
end
|
38
38
|
|
39
|
+
type TextElem do
|
40
|
+
connect XmlElement
|
41
|
+
connect Cheri::Builder::Content
|
42
|
+
connect Object
|
43
|
+
end
|
44
|
+
|
45
|
+
type Namespace do
|
46
|
+
connect XmlElement do |namespace,elem|
|
47
|
+
elem.ns ||= namespace.__prefix__
|
48
|
+
end
|
49
|
+
end
|
39
50
|
end #XmlConnecter
|
40
51
|
|
41
52
|
end #Xml
|
@@ -32,18 +32,18 @@ end #XmlElement
|
|
32
32
|
|
33
33
|
# Included by all Cheri::Xml builders
|
34
34
|
module XmlBuilder
|
35
|
-
|
35
|
+
TCE = ' />'.freeze #:nodoc:
|
36
36
|
|
37
37
|
def empty_s(str='')
|
38
|
-
str <<
|
38
|
+
str << TCE
|
39
39
|
end
|
40
40
|
|
41
41
|
def empty_io(ios)
|
42
|
-
ios <<
|
42
|
+
ios << TCE
|
43
43
|
end
|
44
44
|
|
45
45
|
def esc(inp,out=nil)
|
46
|
-
if @
|
46
|
+
if @opt[:esc] && (cs = Charsets.charset(inp))
|
47
47
|
cs.xlat(inp,(out ||= ''))
|
48
48
|
out
|
49
49
|
elsif out
|
@@ -58,10 +58,26 @@ class Elem
|
|
58
58
|
include Cheri::Builder::MarkupBuilder
|
59
59
|
include XmlBuilder
|
60
60
|
include XmlElement
|
61
|
+
|
62
|
+
def initialize(ctx,*r,&k)
|
63
|
+
opt = @opt = ctx[:xml_opts] || {}
|
64
|
+
@fmt = true if opt[:format]
|
65
|
+
@amap = opt[:attr] if opt[:attr]
|
66
|
+
super
|
67
|
+
end
|
61
68
|
|
62
69
|
def mod
|
63
70
|
Cheri::Xml
|
64
71
|
end
|
72
|
+
|
73
|
+
def margin
|
74
|
+
@mrg || @opt[:margin] || @ctx[:margin] || 0
|
75
|
+
end
|
76
|
+
|
77
|
+
def indent
|
78
|
+
@idt || @opt[:indent] || @ctx[:indent] || 0
|
79
|
+
end
|
80
|
+
|
65
81
|
end
|
66
82
|
|
67
83
|
class EmptyElem
|
@@ -69,40 +85,53 @@ class EmptyElem
|
|
69
85
|
include XmlBuilder
|
70
86
|
include XmlElement
|
71
87
|
|
88
|
+
def initialize(ctx,*r,&k)
|
89
|
+
opt = @opt = ctx[:xml_opts] || {}
|
90
|
+
@fmt = true if opt[:format]
|
91
|
+
@amap = opt[:attr] if opt[:attr]
|
92
|
+
super
|
93
|
+
end
|
94
|
+
|
72
95
|
def mod
|
73
96
|
Cheri::Xml
|
74
97
|
end
|
75
98
|
|
76
|
-
def
|
99
|
+
def add?(value)
|
77
100
|
raise XmlException,"content not allowed for empty element #{@sym}: #{value}"
|
78
101
|
end
|
79
|
-
end
|
80
102
|
|
103
|
+
def margin
|
104
|
+
@mrg || @opt[:margin] || @ctx[:margin] || 0
|
105
|
+
end
|
106
|
+
|
107
|
+
def indent
|
108
|
+
@idt || @opt[:indent] || @ctx[:indent] || 0
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
81
112
|
|
82
113
|
class TextElem
|
83
|
-
include Cheri::Builder::
|
84
|
-
include Cheri::Builder::Content
|
85
|
-
include Cheri::Builder::ContentArgs
|
114
|
+
include Cheri::Builder::MarkupLikeBuilder
|
86
115
|
include XmlBuilder
|
87
116
|
|
88
|
-
def
|
89
|
-
|
117
|
+
def initialize(ctx,*r,&k)
|
118
|
+
@opt = ctx[:xml_opts] || {}
|
119
|
+
super
|
90
120
|
end
|
91
121
|
|
92
|
-
def
|
93
|
-
|
122
|
+
def set?(n,v)
|
123
|
+
raise XmlException,"attribute not allowed for text element #{@sym}: #{n}=#{v}"
|
94
124
|
end
|
125
|
+
private :set?
|
95
126
|
|
96
|
-
def
|
97
|
-
|
98
|
-
add(value) if String === value
|
99
|
-
#add(value) if value && !(Appendable === value || BaseProxy === value)
|
100
|
-
self
|
127
|
+
def mod
|
128
|
+
Cheri::Xml
|
101
129
|
end
|
102
130
|
|
103
131
|
# Appends content to +str+, or to an empty string if +str+ is omitted.
|
104
132
|
# Returns the result.
|
105
133
|
def to_s(str='')
|
134
|
+
return to_io(str) unless String === str
|
106
135
|
@cont.each do |c|
|
107
136
|
if String === c
|
108
137
|
esc(c,str)
|
@@ -127,6 +156,7 @@ class TextElem
|
|
127
156
|
|
128
157
|
end
|
129
158
|
|
159
|
+
# Like TextElem, but always escapes values, regardless of :esc setting
|
130
160
|
class EscElem < TextElem
|
131
161
|
|
132
162
|
def esc(inp,out=nil)
|
@@ -142,14 +172,54 @@ class EscElem < TextElem
|
|
142
172
|
|
143
173
|
end
|
144
174
|
|
175
|
+
class CommentElem
|
176
|
+
include Cheri::Builder::CommentBuilder
|
177
|
+
include XmlBuilder
|
178
|
+
include XmlElement
|
179
|
+
# :stopdoc:
|
180
|
+
CO = '<!-- '.freeze
|
181
|
+
CC = ' -->'.freeze
|
182
|
+
CCLF = " -->\n".freeze
|
183
|
+
# :startdoc:
|
184
|
+
def initialize(ctx,*r,&k)
|
185
|
+
opt = @opt = ctx[:xml_opts] || {}
|
186
|
+
@fmt = true if opt[:format]
|
187
|
+
super
|
188
|
+
end
|
189
|
+
|
190
|
+
def set?(n,v)
|
191
|
+
raise XmlException,"attribute not allowed for comment #{@sym}: #{n}=#{v}"
|
192
|
+
end
|
193
|
+
private :set?
|
194
|
+
|
195
|
+
def mod
|
196
|
+
Cheri::Xml
|
197
|
+
end
|
198
|
+
|
199
|
+
def margin
|
200
|
+
@mrg || @opt[:margin] || @ctx[:margin] || 0
|
201
|
+
end
|
202
|
+
|
203
|
+
def indent
|
204
|
+
@idt || @opt[:indent] || @ctx[:indent] || 0
|
205
|
+
end
|
206
|
+
|
207
|
+
end #CommentElem
|
208
|
+
|
145
209
|
# TODO: special handling for these:
|
146
210
|
|
147
211
|
class XmlRoot
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
include Cheri::Builder::
|
212
|
+
# :stopdoc:
|
213
|
+
XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>".freeze
|
214
|
+
# :startdoc:
|
215
|
+
include Cheri::Builder::MarkupBuilder
|
152
216
|
include XmlBuilder
|
217
|
+
|
218
|
+
def initialize(ctx,*r,&k)
|
219
|
+
opt = @opt = ctx[:xml_opts] || {}
|
220
|
+
@fmt = true if opt[:format]
|
221
|
+
super
|
222
|
+
end
|
153
223
|
|
154
224
|
def mod
|
155
225
|
Cheri::Xml
|
@@ -167,17 +237,29 @@ class XmlRoot
|
|
167
237
|
# Appends content to +str+ (or new String if +str+ is omitted). Returns the result.
|
168
238
|
def to_s(str='')
|
169
239
|
return to_io(str) unless String === str
|
240
|
+
str << ' ' * @opt[:margin] if @fmt && @opt[:margin]
|
170
241
|
str << XML
|
242
|
+
str << 10 if @fmt
|
171
243
|
cont_s(str)
|
172
244
|
str
|
173
245
|
end
|
174
246
|
|
175
247
|
# Appends content to +ios+. Returns the result.
|
176
248
|
def to_io(ios)
|
249
|
+
ios << ' ' * @opt[:margin] if @fmt && @opt[:margin]
|
177
250
|
ios << XML
|
251
|
+
ios << LF if @fmt
|
178
252
|
cont_io(ios)
|
179
253
|
ios
|
180
254
|
end
|
255
|
+
|
256
|
+
def format!
|
257
|
+
@fmt = true
|
258
|
+
end
|
259
|
+
|
260
|
+
def depth
|
261
|
+
-1
|
262
|
+
end
|
181
263
|
|
182
264
|
end
|
183
265
|
|
@@ -185,5 +267,42 @@ end
|
|
185
267
|
class ProcElem < Elem
|
186
268
|
end
|
187
269
|
|
270
|
+
class Namespace
|
271
|
+
alias_method :__methods__,:methods
|
272
|
+
keep = /^(__|<|>|=)|^(class|inspect|to_s)$|(\?|!|=)$/
|
273
|
+
instance_methods.each do |m|
|
274
|
+
undef_method m unless m =~ keep
|
275
|
+
end
|
276
|
+
|
277
|
+
def initialize(ctx,prefix,uri=nil)
|
278
|
+
@ctx = ctx
|
279
|
+
@pfx = prefix.to_sym
|
280
|
+
@uri = uri if uri
|
281
|
+
end
|
282
|
+
|
283
|
+
def __prefix__
|
284
|
+
@pfx
|
285
|
+
end
|
286
|
+
|
287
|
+
def __uri__
|
288
|
+
@uri
|
289
|
+
end
|
290
|
+
|
291
|
+
def mod
|
292
|
+
Cheri::Xml
|
293
|
+
end
|
294
|
+
private :mod
|
295
|
+
|
296
|
+
def method_missing(sym,*r,&k)
|
297
|
+
@ctx.nsend(mod,@pfx,sym,*r,&k)
|
298
|
+
end
|
299
|
+
private :method_missing
|
300
|
+
|
301
|
+
def inspect
|
302
|
+
"#<#{self.class}:instance>"
|
303
|
+
end
|
304
|
+
|
305
|
+
end #Namespace
|
306
|
+
|
188
307
|
end #Xml
|
189
308
|
end #Cheri
|
@@ -41,7 +41,7 @@ class << self
|
|
41
41
|
|
42
42
|
def connecter
|
43
43
|
XmlConnecter
|
44
|
-
end
|
44
|
+
end
|
45
45
|
|
46
46
|
end #self
|
47
47
|
|
@@ -51,33 +51,170 @@ end #self
|
|
51
51
|
# xml([*args] [, &block]) -> XmlProxy if no block given, else result of block
|
52
52
|
#
|
53
53
|
def xml(*r,&k)
|
54
|
-
if
|
54
|
+
if ctx = __cheri_ctx
|
55
|
+
unless copts = ctx[:xml_opts]
|
56
|
+
iopts = ctx.ictx[:xml_opts] ||= XmlOptions.new
|
57
|
+
copts = ctx[:xml_opts] = XmlOptions.new(iopts)
|
58
|
+
end
|
55
59
|
if k
|
56
60
|
if ctx.tos(XmlBuilder)
|
57
61
|
XmlFrame.new(ctx,*r,&k).run
|
58
62
|
else
|
59
|
-
|
63
|
+
copts.ingest_args(*r) unless r.empty?
|
64
|
+
ctx.msend(Cheri::Xml,:xml,&k)
|
60
65
|
end
|
61
66
|
else
|
67
|
+
copts.ingest_args(*r) unless r.empty?
|
62
68
|
ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
|
63
69
|
end
|
64
70
|
end
|
65
71
|
end
|
66
72
|
private :xml
|
67
|
-
|
68
|
-
|
73
|
+
|
69
74
|
module XmlFactory
|
70
75
|
def self.builder(ctx,sym,*r,&k)
|
76
|
+
opts = ctx[:xml_opts] || {}
|
77
|
+
if ((als = opts[:alias]) && (asym = als[sym])) || (asym = Aliases[sym])
|
78
|
+
sym = asym
|
79
|
+
end
|
71
80
|
if (clazz = Types[sym])
|
72
81
|
clazz.new(ctx,sym,*r,&k)
|
73
|
-
elsif
|
82
|
+
elsif :no_ns == sym || ((hns = opts[:ns]) && hns[sym])
|
83
|
+
ns = (ctx[:xml_ns] ||= {})[sym] ||= Namespace.new(ctx,sym)
|
84
|
+
NamespaceBuilder.new(ns,ctx,sym,*r,&k)
|
85
|
+
elsif opts[:any] || ((acc = opts[:accept]) && acc[sym])
|
74
86
|
Elem.new(ctx,sym,*r,&k)
|
75
87
|
else
|
76
|
-
nil
|
88
|
+
nil
|
77
89
|
end
|
78
90
|
end
|
79
91
|
end #XmlFactory
|
80
92
|
|
93
|
+
class XmlOptions < Cheri::Builder::BaseOptions
|
94
|
+
def validate(key,value)
|
95
|
+
raise Cheri.type_error(key,Symbol) unless Symbol === key
|
96
|
+
case key
|
97
|
+
when :any : validate_boolean_nil(value) || nil
|
98
|
+
when :esc : validate_boolean_nil(value) || nil
|
99
|
+
when :format : validate_boolean_nil(value) || nil
|
100
|
+
when :indent
|
101
|
+
unless Fixnum === value
|
102
|
+
if true == value
|
103
|
+
value = 2
|
104
|
+
elsif false == value || nil == value
|
105
|
+
value = nil
|
106
|
+
else
|
107
|
+
raise Cheri.type_error(value,Fixnum,TrueClass,FalseClass,NilClass)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
store(:format,true) if value
|
111
|
+
value
|
112
|
+
when :margin
|
113
|
+
unless Fixnum === value
|
114
|
+
if false == value || nil == value
|
115
|
+
value = nil
|
116
|
+
else
|
117
|
+
raise Cheri.type_error(value,Fixnum,FalseClass,NilClass)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
store(:format,true) if value
|
121
|
+
value
|
122
|
+
when :ns
|
123
|
+
value = value.to_sym if String === value
|
124
|
+
if Symbol === value
|
125
|
+
hns = self[:ns] || {}
|
126
|
+
hns[value] = true
|
127
|
+
hns
|
128
|
+
elsif Array === value
|
129
|
+
hns = self[:ns] || {}
|
130
|
+
value.each do |ns|
|
131
|
+
if String === ns
|
132
|
+
ns = ns.to_sym
|
133
|
+
else
|
134
|
+
validate_symbol(ns)
|
135
|
+
end
|
136
|
+
hns[ns] = true
|
137
|
+
end
|
138
|
+
warn "warning: empty array specified in xml :ns" if value.empty?
|
139
|
+
hns
|
140
|
+
elsif Hash === value
|
141
|
+
value.each_pair do |k,v|
|
142
|
+
validate_symbol(k)
|
143
|
+
validate_boolean_nil(v)
|
144
|
+
end
|
145
|
+
value
|
146
|
+
else
|
147
|
+
raise Cheri.type_error(value,Symbol,Array,Hash)
|
148
|
+
end
|
149
|
+
when :accept
|
150
|
+
value = value.to_sym if String === value
|
151
|
+
if Symbol === value
|
152
|
+
acc = self[:accept] || {}
|
153
|
+
acc[value] = true
|
154
|
+
acc
|
155
|
+
elsif Array === value
|
156
|
+
acc = self[:accept] || {}
|
157
|
+
value.each do |a|
|
158
|
+
if String === a
|
159
|
+
a = a.to_sym
|
160
|
+
else
|
161
|
+
validate_symbol(a)
|
162
|
+
end
|
163
|
+
acc[a] = true
|
164
|
+
end
|
165
|
+
warn "warning: empty array specified in xml :accept" if value.empty?
|
166
|
+
store(:any,false)
|
167
|
+
acc
|
168
|
+
elsif Hash === value
|
169
|
+
value.each_pair do |k,v|
|
170
|
+
validate_symbol(k)
|
171
|
+
validate_boolean_nil(v)
|
172
|
+
end
|
173
|
+
value
|
174
|
+
else
|
175
|
+
raise Cheri.type_error(value,Symbol,Array,Hash)
|
176
|
+
end
|
177
|
+
when :alias
|
178
|
+
if Array === value
|
179
|
+
raise ArgumentError,"odd number of values for :alias" if ((len = value.length) & 1) == 1
|
180
|
+
als = self[:alias] || {}
|
181
|
+
(len>>1).times do |i|
|
182
|
+
als[value[i*2].to_sym] = value[i*2+1].to_sym
|
183
|
+
end
|
184
|
+
als
|
185
|
+
elsif Hash === value
|
186
|
+
value.each_pair do |k,v|
|
187
|
+
validate_symbol(k)
|
188
|
+
validate_symbol(v)
|
189
|
+
end
|
190
|
+
value
|
191
|
+
else
|
192
|
+
raise Cheri.type_error(value,Array,Hash)
|
193
|
+
end
|
194
|
+
when :attr
|
195
|
+
if Array === value
|
196
|
+
raise ArgumentError,"odd number of values for :attr" if ((len = value.length) & 1) == 1
|
197
|
+
als = self[:attr] || {}
|
198
|
+
(len>>1).times do |i|
|
199
|
+
als[value[i*2].to_sym] = value[i*2+1].to_sym
|
200
|
+
end
|
201
|
+
als
|
202
|
+
elsif Hash === value
|
203
|
+
value.each_pair do |k,v|
|
204
|
+
validate_symbol(k)
|
205
|
+
validate_symbol(v)
|
206
|
+
end
|
207
|
+
value
|
208
|
+
else
|
209
|
+
raise Cheri.type_error(value,Array,Hash)
|
210
|
+
end
|
211
|
+
else
|
212
|
+
raise ArgumentError,"invalid xml option: #{key}"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end #XmlOptions
|
216
|
+
|
217
|
+
|
81
218
|
class XmlProxy < Cheri::Builder::BaseProxy
|
82
219
|
|
83
220
|
impl(Types.keys)
|
@@ -87,43 +224,62 @@ class XmlProxy < Cheri::Builder::BaseProxy
|
|
87
224
|
end
|
88
225
|
private :mod
|
89
226
|
|
90
|
-
def [](
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
elsif Hash === opts
|
98
|
-
@ctx[:xml_any] = opts[:any] != false if opts[:any] != nil
|
99
|
-
@ctx[:xml_esc] = opts[:esc] != false if opts[:esc] != nil
|
100
|
-
if (accept = opts[:accept])
|
101
|
-
raise Cheri.type_error(accept,Array) unless Array === accept
|
102
|
-
acc = {}
|
103
|
-
accept.each do |a|
|
104
|
-
raise Cheri.type_error(a,Symbol) unless Symbol === a
|
105
|
-
acc[a] = true
|
106
|
-
end
|
107
|
-
@ctx[:xml_accept] = acc
|
108
|
-
@ctx[:xml_any] = nil
|
109
|
-
end
|
110
|
-
else
|
111
|
-
raise Cheri.type_error(opts,Hash,Symbol)
|
112
|
-
end
|
227
|
+
def [](*args)
|
228
|
+
ictx = (ctx = @ctx).ictx
|
229
|
+
iopts = ictx[:xml_opts] ||= XmlOptions.new
|
230
|
+
iopts.ingest_args(*args)
|
231
|
+
copts = ctx[:xml_opts] ||= XmlOptions.new
|
232
|
+
copts.ingest_args(*args)
|
113
233
|
nil
|
114
234
|
end
|
115
235
|
|
116
236
|
end #XmlProxy
|
117
237
|
|
238
|
+
class NamespaceBuilder
|
239
|
+
include Cheri::Builder::Builder
|
240
|
+
def initialize(ns,*r,&k)
|
241
|
+
super(*r,&k)
|
242
|
+
@obj = ns
|
243
|
+
end
|
244
|
+
def child?
|
245
|
+
false
|
246
|
+
end
|
247
|
+
def parent?
|
248
|
+
false
|
249
|
+
end
|
250
|
+
def any?
|
251
|
+
true
|
252
|
+
end
|
253
|
+
def mod
|
254
|
+
Cheri::Xml
|
255
|
+
end
|
256
|
+
end #NamespaceBuilder
|
257
|
+
|
118
258
|
class XmlFrame
|
119
259
|
include Cheri::Builder::Frame
|
120
260
|
def initialize(ctx,*r,&k)
|
121
|
-
super
|
122
|
-
@obj = ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
|
261
|
+
super(ctx,&k)
|
262
|
+
@obj = ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
|
263
|
+
@args = r unless r.empty?
|
123
264
|
end
|
124
265
|
def mod
|
125
266
|
Cheri::Xml
|
126
267
|
end
|
268
|
+
def run
|
269
|
+
if blk = @blk
|
270
|
+
if args = @args
|
271
|
+
opts = (ctx = @ctx)[:xml_opts]
|
272
|
+
temp = XmlOptions.new(opts)
|
273
|
+
temp.ingest_args(*args)
|
274
|
+
ctx[:xml_opts] = temp
|
275
|
+
result = ctx.call(self,&blk)
|
276
|
+
ctx[:xml_opts] = opts
|
277
|
+
result
|
278
|
+
else
|
279
|
+
@ctx.call(self,&blk)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
127
283
|
end #XmlFrame
|
128
284
|
|
129
285
|
end #Xml
|