meteor 0.9.12 → 0.9.13

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.
@@ -0,0 +1,2182 @@
1
+ # -* coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ module Meteor
5
+ module Core
6
+ # Parser Core Class (パーサ・コア クラス)
7
+ #
8
+ # @!attribute [rw] element_cache
9
+ # @return [Hash] element cache (要素キャッシュ)
10
+ # @!attribute [rw] doc_type
11
+ # @return [Fixnum] document type (ドキュメントタイプ)
12
+ # @!attribute [rw] document_hook
13
+ # @return [String] hook document (フック・ドキュメント)
14
+ # @!attribute [rw] element_hook
15
+ # @return [Meteor::Element] element (要素)
16
+ #
17
+ class Kernel < Meteor::Parser
18
+ # find
19
+ # E
20
+ PATTERN_FIND_1 = '^([^,\\[\\]#\\.]+)$'
21
+ # # id_attribute_value
22
+ PATTERN_FIND_2_1 = '^#([^\\.,\\[\\]#][^,\\[\\]#]*)$'
23
+ # .class_attribute_value
24
+ PATTERN_FIND_2_2 = '^\\.([^\\.,\\[\\]#][^,\\[\\]#]*)$'
25
+ # [attribute_name=attribute_value]
26
+ PATTERN_FIND_2_3 = '^\\[([^\\[\\],]+)=([^\\[\\],]+)\\]$'
27
+ # E[attribute_name=attribute_value]
28
+ PATTERN_FIND_3_1 = '^([^\\.,\\[\\]#][^,\\[\\]#]+)\\[([^,\\[\\]]+)=([^,\\[\\]]+)\\]$'
29
+ # E# id_attribute_value
30
+ PATTERN_FIND_3_2 = '^([^\\.,\\[\\]#][^,\\[\\]#]+)#([^\\.,\\[\\]#][^,\\[\\]#]*)$'
31
+ # E.class_attribute_value
32
+ PATTERN_FIND_3_3 = '^([^\\.,\\[\\]#][^,\\[\\]#]+)\\.([^\\.,\\[\\]#][^,\\[\\]#]*)$'
33
+ # [attribute_name1=attribute_value1][attribute_name2=attribute_value2]
34
+ PATTERN_FIND_4 = '^\\[([^,]+)=([^,]+)\\]\\[([^,]+)=([^,]+)\\]$'
35
+ # E[attribute_name1=attribute_value1][attribute_name2=attribute_value2]
36
+ PATTERN_FIND_5 = '^([^\\.,\\[\\]#][^,\\[\\]#]+)\\[([^,]+)=([^,]+)\\]\\[([^,]+)=([^,]+)\\]$'
37
+
38
+ @@pattern_find_1 = Regexp.new(PATTERN_FIND_1)
39
+ @@pattern_find_2_1 = Regexp.new(PATTERN_FIND_2_1)
40
+ @@pattern_find_2_2 = Regexp.new(PATTERN_FIND_2_2)
41
+ @@pattern_find_2_3 = Regexp.new(PATTERN_FIND_2_3)
42
+ @@pattern_find_3_1 = Regexp.new(PATTERN_FIND_3_1)
43
+ @@pattern_find_3_2 = Regexp.new(PATTERN_FIND_3_2)
44
+ @@pattern_find_3_3 = Regexp.new(PATTERN_FIND_3_3)
45
+ @@pattern_find_4 = Regexp.new(PATTERN_FIND_4)
46
+ @@pattern_find_5 = Regexp.new(PATTERN_FIND_5)
47
+
48
+ @@pattern_set_mono1 = Regexp.new('\\A[^<>]*\\Z')
49
+
50
+ @@pattern_get_attrs_map = Regexp.new('([^\\s]*)="([^\"]*)"')
51
+
52
+ @@pattern_clean1 = Regexp.new('<!--\\s@[^<>]*\\s[^<>]*(\\s)*-->')
53
+ @@pattern_clean2 = Regexp.new('<!--\\s\\/@[^<>]*(\\s)*-->')
54
+
55
+ attr_accessor :element_cache
56
+ attr_accessor :doc_type
57
+ attr_accessor :document_hook
58
+ attr_accessor :element_hook
59
+
60
+ #
61
+ # set document (ドキュメントをセットする)
62
+ #
63
+ # @param [String] doc document (ドキュメント)
64
+ #
65
+ def document=(doc)
66
+ @root.document = doc
67
+ end
68
+
69
+ #
70
+ # get document (ドキュメントを取得する)
71
+ # @return [String] document (ドキュメント)
72
+ #
73
+ def document
74
+ @root.document
75
+ end
76
+
77
+ #
78
+ # set character encoding (文字エンコーディングをセットする)
79
+ # @param [String] enc character encoding (文字エンコーディング)
80
+ #
81
+ def character_encoding=(enc)
82
+ @root.character_encoding = enc
83
+ end
84
+
85
+ #
86
+ # get character encoding (文字エンコーディングを取得する)
87
+ # @return [String] character encoding (文字エンコーディング)
88
+ #
89
+ def character_encoding
90
+ @root.character_encoding
91
+ end
92
+
93
+ #
94
+ # get root element (ルート要素を取得する)
95
+ # @return [Meteor::RootElement] root element (ルート要素)
96
+ #
97
+ def root_element
98
+ @root
99
+ end
100
+
101
+ #
102
+ # initializer (イニシャライザ)
103
+ #
104
+ def initialize
105
+ # parent element (親要素)
106
+ # @parent = nil
107
+
108
+ # pattern (正規表現パターン)
109
+ # @pattern = nil
110
+ # root element (ルート要素)
111
+ @root = RootElement.new
112
+ @root.parser = self
113
+ # element cache (要素キャッシュ)
114
+ @element_cache = Hash.new
115
+ # document hook (フック・ドキュメント)
116
+ @document_hook = String.new('')
117
+
118
+ @error_check = true
119
+ end
120
+
121
+ #
122
+ # read file , set in parser (ファイルを読み込み、パーサにセットする)
123
+ # @param [String] file_path absolute path of input file (入力ファイルの絶対パス)
124
+ # @param [String] enc character encoding of input file (入力ファイルの文字コード)
125
+ #
126
+ def read(file_path, enc)
127
+
128
+ # try {
129
+ @character_encoding = enc
130
+ # open file (ファイルのオープン)
131
+ if "UTF-8".eql?(enc)
132
+ # io = File.open(file_path,"r:" << enc)
133
+ io = File.open(file_path, "r:UTF-8")
134
+ else
135
+ io = File.open(file_path, String.new('') << "r:" << enc << ":utf-8")
136
+ end
137
+
138
+ # load and save (読込及び格納)
139
+ @root.document = io.read
140
+
141
+ parse
142
+
143
+ # close file (ファイルのクローズ)
144
+ io.close
145
+
146
+ return @root.document
147
+ end
148
+
149
+ #
150
+ # psrse document (ドキュメントを解析する)
151
+ # @param [String] document document (ドキュメント)
152
+ #
153
+ def parse
154
+ end
155
+
156
+ #
157
+ # get element (要素を取得する)
158
+ # @overload element(name)
159
+ # get element using tag name (要素のタグ名で要素を取得する)
160
+ # @param [String,Symbol] name tag name (タグ名)
161
+ # @return [Meteor::Element] element(要素)
162
+ # @overload element(name,attrs)
163
+ # get element using tag name and attribute map (要素のタグ名と属性(属性名="属性値")あるいは属性1・属性2(属性名="属性値")で要素を取得する)
164
+ # @param [String,Symbol] name tag name (タグ名)
165
+ # @param [Hash<String,String>,Hash<Symbol,String>] attrs attribute map (属性マップ)
166
+ # @return [Meteor::Element] element (要素)
167
+ # @overload element(attrs)
168
+ # get element using attribute map (属性(属性名="属性値")あるいは属性1・属性2(属性名="属性値")で要素を取得する)
169
+ # @param [Hash<String,String>,Hash<Symbol,String>] attrs attribute map (属性マップ)
170
+ # @return [Meteor::Element] element (要素)
171
+ # @overload element(name,attr_name,attr_value)
172
+ # get element using tag name and attribute(name="value") (要素のタグ名と属性(属性名="属性値")で要素を取得する)
173
+ # @param [String,Symbol] name tag name (タグ名)
174
+ # @param [String,Symbol] attr_name attribute name (属性名)
175
+ # @param [String] attr_value attribute value (属性値)
176
+ # @return [Meteor::Element] element (要素)
177
+ # @overload element(attr_name,attr_value)
178
+ # get element using attribute(name="value") (属性(属性名="属性値")で要素を取得する)
179
+ # @param [String,Symbol] attr_name attribute name (属性名)
180
+ # @param [String] attr_value attribute value (属性値)
181
+ # @return [Meteor::Element] element (要素)
182
+ # @overload element(name,attr_name1,attr_value1,attr_name2,attr_value2)
183
+ # get element using tag name and attribute1,2(name="value") (要素のタグ名と属性1・属性2(属性名="属性値")で要素を取得する)
184
+ # @param [String,Symbol] name tag name (タグ名)
185
+ # @param [String,Symbol] attr_name1 attribute name1 (属性名1)
186
+ # @param [String] attr_value1 attribute value1 (属性値1)
187
+ # @param [String,Symbol] attr_name2 attribute name2 (属性名2)
188
+ # @param [String] attr_value2 attribute value2 (属性値2)
189
+ # @return [Meteor::Element] element (要素)
190
+ # @overload element(attr_name1,attr_value1,attr_name2,attr_value2)
191
+ # get element using attribute1,2(name="value") (属性1・属性2(属性名="属性値")で要素を取得する)
192
+ # @param [String,Symbol] attr_name1 attribute name1 (属性名1)
193
+ # @param [String] attr_value1 attribute value1 (属性値1)
194
+ # @param [String,Symbol] attr_name2 attribute name2 (属性名2)
195
+ # @param [String] attr_value2 attribute value2 (属性値2)
196
+ # @return [Meteor::Element] element (要素)
197
+ # @overload element(elm)
198
+ # mirror element (要素を射影する)
199
+ # @param [Meteor::Element] elm element (要素)
200
+ # @return [Meteor::Element] element (要素)
201
+ #
202
+ def element(elm, attrs = nil,*args)
203
+ if !attrs
204
+ if elm.kind_of?(String) || elm.kind_of?(Symbol)
205
+ element_1(elm.to_s)
206
+ if @elm_
207
+ @element_cache.store(@elm_.object_id, @elm_)
208
+ end
209
+ elsif elm.kind_of?(Meteor::Element)
210
+ shadow(elm)
211
+ elsif elm.kind_of?(Hash)
212
+ if elm.size == ONE
213
+ element_2(elm.keys[0].to_s, elm.values[0])
214
+ if @elm_
215
+ @element_cache.store(@elm_.object_id, @elm_)
216
+ end
217
+ elsif elm.size == TWO
218
+ element_4(elm.keys[0].to_s, elm.values[0], elm.keys[1].to_s, elm.values[1])
219
+ if @elm_
220
+ @element_cache.store(@elm_.object_id, @elm_)
221
+ end
222
+ else
223
+ raise ArgumentError
224
+ end
225
+ else
226
+ raise ArgumentError
227
+ end
228
+ elsif attrs.kind_of?(Hash)
229
+ if attrs.size == ONE
230
+ element_3(elm.to_s, attrs.keys[0].to_s, attrs.values[0])
231
+ if @elm_
232
+ @element_cache.store(@elm_.object_id, @elm_)
233
+ end
234
+ elsif attrs.size == TWO
235
+ element_5(elm.to_s, attrs.keys[0].to_s, attrs.values[0], attrs.keys[1].to_s, attrs.values[1])
236
+ if @elm_
237
+ @element_cache.store(@elm_.object_id, @elm_)
238
+ end
239
+ else
240
+ @elm_ = nil
241
+ raise ArgumentError
242
+ end
243
+ elsif attrs.kind_of?(String) || attrs.kind_of?(Symbol)
244
+ case args.length
245
+ when ZERO
246
+ element_2(elm.to_s,attrs.to_s)
247
+ if @elm_
248
+ @element_cache.store(@elm_.object_id, @elm_)
249
+ end
250
+ when ONE
251
+ element_3(elm.to_s, attrs.to_s, args[0])
252
+ if @elm_
253
+ @element_cache.store(@elm_.object_id, @elm_)
254
+ end
255
+ when TWO
256
+ element_4(elm.to_s, attrs.to_s, args[0].to_s,args[1])
257
+ if @elm_
258
+ @element_cache.store(@elm_.object_id, @elm_)
259
+ end
260
+ when THREE
261
+ element_5(elm.to_s, attrs.to_s, args[0],args[1].to_s,args[2])
262
+ if @elm_
263
+ @element_cache.store(@elm_.object_id, @elm_)
264
+ end
265
+ else
266
+ @elm_ = nil
267
+ raise ArgumentError
268
+ end
269
+ else
270
+ @elm_ = nil
271
+ raise ArgumentError
272
+ end
273
+ end
274
+
275
+ #
276
+ # get element using tag name (タグ名で検索し、要素を取得する)
277
+ # @param [String,Symbol] name tag name (タグ名)
278
+ # @return [Meteor::Element] element(要素)
279
+ #
280
+ def element_1(name)
281
+ @_name = Regexp.quote(name)
282
+
283
+ # element search pattern (要素検索用パターン)
284
+ @pattern_cc = "<#{@_name}(|\\s[^<>]*)\\/>|<#{@_name}((?:|\\s[^<>]*))>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
285
+
286
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
287
+ # search of element with content (内容あり要素検索)
288
+ @res = @pattern.match(@root.document)
289
+
290
+ if @res
291
+ if @res[1]
292
+ element_without_1(name)
293
+ else
294
+ # puts '---element_with_1'
295
+ element_with_1(name)
296
+ end
297
+ # else
298
+ end
299
+
300
+ @elm_
301
+ end
302
+
303
+ private :element_1
304
+
305
+ def element_with_1(name)
306
+ @elm_ = Meteor::Element.new(name)
307
+
308
+ unless @on_search
309
+ # puts '--on_search=false'
310
+ # puts @res.to_a
311
+ # attribute (属性)
312
+ @elm_.attributes = @res[2]
313
+ # content (内容)
314
+ @elm_.mixed_content = @res[3]
315
+ # document (全体)
316
+ @elm_.document = @res[0]
317
+ else
318
+ # puts '--on_search=true'
319
+ # attribute (属性)
320
+ @elm_.attributes = @res[1]
321
+ # content (内容)
322
+ @elm_.mixed_content = @res[2]
323
+ # document (全体)
324
+ @elm_.document = @res[0]
325
+ end
326
+ # search pattern of element with content (内容あり要素検索用パターン)
327
+ # @pattern_cc = String.new('') << "<" << @_name << '(?:|\\s[^<>]*)>((?!(' << @_name
328
+ # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
329
+ @pattern_cc = "<#{@_name}(|\\s[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
330
+
331
+ @elm_.pattern = @pattern_cc
332
+ @elm_.empty = true
333
+ @elm_.parser = self
334
+
335
+ @elm_
336
+ end
337
+
338
+ private :element_with_1
339
+
340
+ def element_without_1(name)
341
+ # element (要素)
342
+ @elm_ = Meteor::Element.new(name)
343
+ # attribute (属性)
344
+ @elm_.attributes = @res[1]
345
+ # document (全体)
346
+ @elm_.document = @res[0]
347
+ # void element search pattern (空要素検索用パターン)
348
+ @pattern_cc = String.new('') << "<" << @_name << '(|\\s[^<>]*)\\/>'
349
+ # @pattern_cc = "<#{@_name}(|\\s[^<>]*)\\/>"
350
+ @elm_.pattern = @pattern_cc
351
+
352
+ @elm_.empty = false
353
+
354
+ @elm_.parser = self
355
+
356
+ @elm_
357
+ end
358
+
359
+ private :element_without_1
360
+
361
+ #
362
+ # get element using tag name and attribute(name="value") (要素のタグ名と属性(属性名="属性値")で検索し、要素を取得する)
363
+ # @param [String] name tag name (タグ名)
364
+ # @param [String] attr_name attribute name (属性名)
365
+ # @param [String] attr_value attribute value (属性値)
366
+ # @param [true,false] quote flag (クオート・フラグ)
367
+ # @return [Meteor::Element] element (要素)
368
+ def element_3(name, attr_name, attr_value, quote = true)
369
+ element_quote_3(name,attr_name,attr_value)
370
+
371
+ @pattern_cc_1 = element_pattern_3
372
+
373
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
374
+ @res1 = @pattern.match(@root.document)
375
+
376
+ if @res1 && @res1[1] || !@res1
377
+ @res2 = element_with_3_2
378
+ @pattern_cc_2 = @pattern_cc
379
+
380
+ # puts @res2.captures.length
381
+ # puts @res2.regexp.to_s
382
+ end
383
+
384
+ if @res1 && @res2
385
+ if @res1.begin(0) < @res2.begin(0)
386
+ @res = @res1
387
+ # @pattern_cc = @pattern_cc_1
388
+ if @res[1]
389
+ element_without_3(name)
390
+ else
391
+ element_with_3_1(name)
392
+ end
393
+ elsif @res1.begin(0) > @res2.begin(0)
394
+ @res = @res2
395
+ # @pattern_cc = @pattern_cc_2
396
+ element_with_3_1(name)
397
+ end
398
+ elsif @res1 && !@res2
399
+ @res = @res1
400
+ # @pattern_cc = @pattern_cc_1
401
+ if @res[1]
402
+ element_without_3(name)
403
+ else
404
+ element_with_3_1(name)
405
+ end
406
+ elsif @res2 && !@res1
407
+ @res = @res2
408
+ # @pattern_cc = @pattern_cc_2
409
+ element_with_3_1(name)
410
+ else
411
+ if @error_check
412
+ puts Meteor::Exception::NoSuchElementException.new(name, attr_name, attr_value).message
413
+ end
414
+ @elm_ = nil
415
+ end
416
+
417
+ @elm_
418
+ end
419
+
420
+ private :element_3
421
+
422
+ def element_pattern_3
423
+ "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)\\/>|<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
424
+ end
425
+
426
+ private :element_pattern_3
427
+
428
+ def element_quote_3(name,attr_name,attr_value)
429
+ @_name = Regexp.quote(name)
430
+ @_attr_name = Regexp.quote(attr_name)
431
+ @_attr_value = Regexp.quote(attr_value)
432
+ end
433
+
434
+ private :element_quote_3
435
+
436
+ def element_with_3_1(name)
437
+ # puts @res.captures.length
438
+ case @res.captures.length
439
+ when FOUR
440
+ # 要素
441
+ @elm_ = Meteor::Element.new(name)
442
+ # 属性
443
+ @elm_.attributes = @res[1]
444
+ # 内容
445
+ @elm_.mixed_content = @res[2]
446
+ # 全体
447
+ @elm_.document = @res[0]
448
+ # 内容あり要素検索用パターン
449
+ # @pattern_cc = String.new('')<< "<" << @_name << '\\s[^<>]*' << @_attr_name << '="'
450
+ # @pattern_cc << @_attr_value << '"[^<>]*>((?!(' << @_name
451
+ # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
452
+ @pattern_cc = "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
453
+
454
+ @elm_.pattern = @pattern_cc
455
+
456
+ @elm_.empty = true
457
+
458
+ @elm_.parser = self
459
+
460
+ when FIVE
461
+ # element (要素)
462
+ @elm_ = Meteor::Element.new(name)
463
+ # attribute (属性)
464
+ @elm_.attributes = @res[2]
465
+ # content (内容)
466
+ @elm_.mixed_content = @res[3]
467
+ # document (全体)
468
+ @elm_.document = @res[0]
469
+ # search pattern of element with content (内容あり要素検索用パターン)
470
+ # @pattern_cc = String.new('')<< "<" << @_name << '\\s[^<>]*' << @_attr_name << '="'
471
+ # @pattern_cc << @_attr_value << '"[^<>]*>((?!(' << @_name
472
+ # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
473
+ @pattern_cc = "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)>((?!(#{@_name}[^<>]*>)).)*<\\/#{@_name}>"
474
+
475
+ @elm_.pattern = @pattern_cc
476
+
477
+ @elm_.empty = true
478
+
479
+ @elm_.parser = self
480
+
481
+ when THREE,SIX
482
+ # element (要素)
483
+ @elm_ = Meteor::Element.new(name)
484
+ unless @on_search
485
+ # attribute (属性)
486
+ @elm_.attributes = @res[1].chop
487
+ # content (内容)
488
+ @elm_.mixed_content = @res[3]
489
+ else
490
+ # attribute (属性)
491
+ @elm_.attributes = @res[1].chop
492
+ # content (内容)
493
+ @elm_.mixed_content = @res[3]
494
+ end
495
+ # document (全体)
496
+ @elm_.document = @res[0]
497
+ # search pattern of element with content (内容あり要素検索用パターン)
498
+ @elm_.pattern = @pattern_cc
499
+
500
+ @elm_.empty = true
501
+
502
+ @elm_.parser = self
503
+ end
504
+ @elm_
505
+ end
506
+
507
+ private :element_with_3_1
508
+
509
+ def element_with_3_2
510
+ element_pattern_with_3_2
511
+
512
+ if @sbuf.length == ZERO || @cnt != ZERO
513
+ return nil
514
+ end
515
+
516
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
517
+ @res = @pattern.match(@root.document)
518
+
519
+ @res
520
+ end
521
+
522
+ private :element_with_3_2
523
+
524
+ def element_pattern_with_3_2
525
+ # @pattern_cc_1 = String.new('') << "<" << @_name << '(\\s[^<>]*' << @_attr_name << '="'
526
+ # @pattern_cc_1 << @_attr_value << '(?:[^<>\\/]*>|(?:(?!([^<>]*\\/>))[^<>]*>)))'
527
+ @pattern_cc_1 = "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}(?:[^<>\\/]*>|(?:(?!([^<>]*\\/>))[^<>]*>)))"
528
+ @pattern_cc_1b = String.new('') << "<" << @_name << '(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))'
529
+ # @pattern_cc_1b = "<#{@_name}(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
530
+ # @pattern_cc_1_1 = String.new('') << "<" << @_name << '(\\s[^<>]*' << @_attr_name << '="'
531
+ # @pattern_cc_1_1 << @_attr_value << '"(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))('
532
+ @pattern_cc_1_1 = "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))("
533
+ @pattern_cc_1_2 = String.new('') << '.*?<' << @_name << '(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))'
534
+ # @pattern_cc_1_2 = ".*?<#{@_name}(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
535
+
536
+
537
+ @pattern_cc_2 = String.new('') << '<\\/' << @_name << '>'
538
+ # @pattern_cc_2 = String.new('') << "<\\/#{@_name}>"
539
+ @pattern_cc_2_1 = String.new('') << '.*?<\/' << @_name << '>'
540
+ # @pattern_cc_2_1 = ".*?<\\/#{@_name}>"
541
+ @pattern_cc_2_2 = String.new('') << '.*?)<\/' << @_name << '>'
542
+ # @pattern_cc_2_2 = ".*?)<\\/#{@_name}>"
543
+
544
+ # search of element with content (内容あり要素検索)
545
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
546
+
547
+ @sbuf = String.new('')
548
+
549
+ @pattern_2 = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
550
+ @pattern_1b = Meteor::Core::Util::PatternCache.get(@pattern_cc_1b)
551
+
552
+ @cnt = 0
553
+
554
+ create_element_pattern
555
+
556
+ @pattern_cc = @sbuf
557
+
558
+ end
559
+
560
+ private :element_pattern_with_3_2
561
+
562
+ def element_without_3(name)
563
+ element_without_3_1(name, '"[^<>]*)\\/>')
564
+ end
565
+
566
+ private :element_without_3
567
+
568
+ def element_without_3_1(name, closer)
569
+ # element (要素)
570
+ @elm_ = Meteor::Element.new(name)
571
+ # attribute (属性)
572
+ @elm_.attributes = @res[1]
573
+ # document (全体)
574
+ @elm_.document = @res[0]
575
+ # pattern (空要素検索用パターン)
576
+ @pattern_cc = String.new('') << "<" << @_name << '(\\s[^<>]*' << @_attr_name << '="' << @_attr_value << closer
577
+ # @pattern_cc = "<#{@_name}\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}#{closer}"
578
+ @elm_.pattern = @pattern_cc
579
+ @elm_.parser = self
580
+
581
+ @elm_
582
+ end
583
+
584
+ private :element_without_3_1
585
+
586
+ #
587
+ # get element using attribute(name="value") (属性(属性名="属性値")で検索し、要素を取得する)
588
+ # @param [String] attr_name attribute name (属性名)
589
+ # @param [String] attr_value attribute value (属性値)
590
+ # @return [Meteor::Element] element (要素)
591
+ #
592
+ def element_2(attr_name, attr_value)
593
+
594
+ element_quote_2(attr_name,attr_value)
595
+
596
+ element_pattern_2
597
+
598
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
599
+ @res = @pattern.match(@root.document)
600
+
601
+ if @res
602
+ element_3(@res[1], attr_name, attr_value)
603
+ else
604
+ if @error_check
605
+ puts Meteor::Exception::NoSuchElementException.new(attr_name, attr_value).message
606
+ end
607
+ @elm_ = nil
608
+ end
609
+ #=end
610
+
611
+ =begin
612
+ @pattern_cc_1 = "<([^<>\"]*)(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)\\/>|<([^<>\"]*)(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)>(((?!(\\3[^<>]*>)).)*)<\\/\\3>"
613
+
614
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
615
+ @res1 = @pattern.match(@root.document)
616
+
617
+ if @res1 && @res1[1] || !@res1
618
+ @res2 = element_with_2_2
619
+ @pattern_cc_2 = @pattern_cc
620
+
621
+ # puts @res2.captures.length
622
+ # puts @res2.regexp.to_s
623
+ end
624
+
625
+ if @res1 && @res2
626
+ if @res1.begin(0) < @res2.begin(0)
627
+ @res = @res1
628
+ # @pattern_cc = @pattern_cc_1
629
+ if @res[1]
630
+ element_without_2
631
+ else
632
+ element_with_2_1
633
+ end
634
+ elsif @res1.begin(0) > @res2.begin(0)
635
+ @res = @res2
636
+ # @pattern_cc = @pattern_cc_2
637
+ element_with_2_1
638
+ end
639
+ elsif @res1 && !@res2
640
+ @res = @res1
641
+ # @pattern_cc = @pattern_cc_1
642
+ if @res[1]
643
+ element_without_2
644
+ else
645
+ element_with_2_1
646
+ end
647
+ elsif @res2 && !@res1
648
+ @res = @res2
649
+ # @pattern_cc = @pattern_cc_2
650
+ element_with_2_1
651
+ else
652
+ if @error_check
653
+ puts Meteor::Exception::NoSuchElementException.new(attr_name, attr_value).message
654
+ end
655
+ @elm_ = nil
656
+ end
657
+ =end
658
+
659
+ @elm_
660
+ end
661
+
662
+ private :element_2
663
+
664
+ def element_quote_2(attr_name, attr_value)
665
+ @_attr_name = Regexp.quote(attr_name)
666
+ @_attr_value = Regexp.quote(attr_value)
667
+ end
668
+
669
+ private :element_quote_2
670
+
671
+ def element_pattern_2
672
+ # # @pattern_cc = String.new('') << '<([^<>"]*)\\s[^<>]*' << @_attr_name << '="' << @_attr_value << '(?:[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))'
673
+ # @pattern_cc = String.new('') << '<([^<>"]*)\\s[^<>]*' << @_attr_name << '="' << @_attr_value << '"'
674
+ @pattern_cc = "<([^<>\"]*)\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\""
675
+ end
676
+
677
+ private :element_pattern_2
678
+
679
+ =begin
680
+ def element_with_2_1
681
+ # puts @res.captures.length
682
+ case @res.captures.length
683
+ when FOUR
684
+ @_name = @res[1]
685
+ # eleement (要素)
686
+ @elm_ = Element.new(@_name)
687
+ # attribute (属性)
688
+ @elm_.attributes = @res[2]
689
+ # content (内容)
690
+ @elm_.mixed_content = @res[3]
691
+ # document (全体)
692
+ @elm_.document = @res[0]
693
+ # pattern (内容あり要素検索用パターン)
694
+ # @pattern_cc = String.new('') << "<" << @_name << '\\s[^<>]*' << @_attr_name << '="'
695
+ # @pattern_cc << @_attr_value << '"[^<>]*>((?!(' << @_name
696
+ # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
697
+ @ pattern_cc = "<#{@_name}\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*>((?!(#{@_name}[^<>]*>)).)*<\\/#{@_name}>"
698
+
699
+ @elm_.pattern = @pattern_cc
700
+ @elm_.empty = true
701
+ @elm_.parser = self
702
+ when FIVE,SEVEN
703
+ @_name = @res[3]
704
+ # element (要素)
705
+ @elm_ = Element.new(@_name)
706
+ # attribute (属性)
707
+ @elm_.attributes = @res[4]
708
+ # content (内容)
709
+ @elm_.mixed_content = @res[5]
710
+ # document (全体)
711
+ @elm_.document = @res[0]
712
+ # pattern (内容あり要素検索用パターン)
713
+ # @pattern_cc = String.new()<< "<" << @_name << '\\s[^<>]*' << @_attr_name << '="'
714
+ # @pattern_cc << @_attr_value << '"[^<>]*>((?!(' << @_name
715
+ # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
716
+ @pattern_cc = "<#{@_name}\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*>((?!(#{@_name}[^<>]*>)).)*<\\/#{@_name}>"
717
+
718
+ @elm_.pattern = @pattern_cc
719
+ @elm_.empty = true
720
+ @elm_.parser = self
721
+ when THREE,SIX
722
+ # puts @res[1]
723
+ # puts @res[3]
724
+ # @_name = @res[1]
725
+ # element (要素)
726
+ @elm_ = Element.new(@_name)
727
+ # attribute (属性)
728
+ @elm_.attributes = @res[1].chop
729
+ # content (内容)
730
+ @elm_.mixed_content = @res[3]
731
+ # document (全体)
732
+ @elm_.document = @res[0]
733
+ # pattern (内容あり要素検索用パターン)
734
+ @elm_.pattern = @pattern_cc
735
+
736
+ @elm_.empty = true
737
+ @elm_.parser = self
738
+ end
739
+ @elm_
740
+ end
741
+
742
+ private :element_with_2_1
743
+
744
+ def element_with_2_2
745
+ # @pattern_cc_1 = String.new('') << "<" << @_name << '(\\s[^<>]*' << @_attr_name << '="'
746
+ # @pattern_cc_1 << @_attr_value << '(?:[^<>\\/]*>|(?:(?!([^<>]*\\/>))[^<>]*>)))'
747
+ @pattern_cc_1 = "<([^<>\"]*)(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}(?:[^<>\\/]*>|(?:(?!([^<>]*\\/>))[^<>]*>)))"
748
+
749
+ # search of element with content (内容あり要素検索)
750
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
751
+ @sbuf = String.new('')
752
+
753
+ @cnt = 0
754
+
755
+ create_element_pattern_2(2)
756
+
757
+ @pattern_cc = @sbuf
758
+
759
+ if @sbuf.length == ZERO || @cnt != ZERO
760
+ return nil
761
+ end
762
+
763
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
764
+ @res = @pattern.match(@root.document)
765
+ end
766
+
767
+ private :element_with_2_2
768
+
769
+ def create_pattern_2(args_cnt)
770
+ @pattern_cc_1b = String.new('') << "<" << @_name << '(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))'
771
+
772
+ # @pattern_cc_1_1 = String.new('') << "<" << @_name << '(\\s[^<>]*' << @_attr_name << '="'
773
+ # @pattern_cc_1_1 << @_attr_value << '"(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))('
774
+ @pattern_cc_1_1 = "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))("
775
+ @pattern_cc_1_2 = String.new('') << '.*?<' << @_name << '(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))'
776
+ @pattern_cc_2 = String.new('') << '<\\/' << @_name << '>'
777
+ @pattern_cc_2_1 = String.new('') << '.*?<\/' << @_name << '>'
778
+ @pattern_cc_2_2 = String.new('') << '.*?)<\/' << @_name << '>'
779
+
780
+ @pattern_2 = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
781
+ @pattern_1b = Meteor::Core::Util::PatternCache.get(@pattern_cc_1b)
782
+ end
783
+
784
+ def element_without_2
785
+ element_without_2_1('"[^<>]*\\/>')
786
+ end
787
+
788
+ private :element_without_2
789
+
790
+ def element_without_2_1(closer)
791
+ # element (要素)
792
+ @elm_ = Element.new(@res[1])
793
+ # attribute (属性)
794
+ @elm_.attributes = @res[2]
795
+ # document (全体)
796
+ @elm_.document = @res[0]
797
+ # void element search pattern (空要素検索用パターン)
798
+ @pattern_cc = String.new('') << "<" << @_name << '\\s[^<>]*' << @_attr_name << '="' << @_attr_value << closer
799
+ @elm_.pattern = @pattern_cc
800
+ @elm_.parser = self
801
+
802
+ @elm_
803
+ end
804
+
805
+ private :element_without_2_1
806
+ =end
807
+
808
+ #
809
+ # get element using tag name and attribute1,2(name="value") (要素のタグ名と属性1・属性2(属性名="属性値")で検索し、要素を取得する)
810
+ # @param [String] name tag name (タグ名)
811
+ # @param [String] attr_name1 attribute name1 (属性名1)
812
+ # @param [String] attr_value1 attribute value1 (属性値1)
813
+ # @param [String] attr_name2 attribute name2 (属性名2)
814
+ # @param [String] attr_value2 attribute value2 (属性値2)
815
+ # @return [Meteor::Element] element (要素)
816
+ #
817
+ def element_5(name, attr_name1, attr_value1, attr_name2, attr_value2)
818
+
819
+ element_quote_5(name, attr_name1, attr_value1, attr_name2, attr_value2)
820
+
821
+ @pattern_cc_1 = "<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")[^<>]*)\\/>|<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
822
+
823
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
824
+ @res1 = @pattern.match(@root.document)
825
+
826
+ if @res1 && @res1[1] || !@res1
827
+ @res2 = element_with_5_2
828
+ @pattern_cc_2 = @pattern_cc
829
+
830
+ # puts @res2.captures.length
831
+ # puts @res2.regexp.to_s
832
+ end
833
+
834
+ if @res1 && @res2
835
+ if @res1.begin(0) < @res2.begin(0)
836
+ @res = @res1
837
+ # @pattern_cc = @pattern_cc_1
838
+ if @res[1]
839
+ element_without_5(name)
840
+ else
841
+ element_with_5_1(name)
842
+ end
843
+ elsif @res1.begin(0) > @res2.begin(0)
844
+ @res = @res2
845
+ # @pattern_cc = @pattern_cc_2
846
+ element_with_5_1(name)
847
+ end
848
+ elsif @res1 && !@res2
849
+ @res = @res1
850
+ # @pattern_cc = @pattern_cc_1
851
+ if @res[1]
852
+ element_without_5(name)
853
+ else
854
+ element_with_5_1(name)
855
+ end
856
+ elsif @res2 && !@res1
857
+ @res = @res2
858
+ # @pattern_cc = @pattern_cc_2
859
+ element_with_5_1(name)
860
+ else
861
+ if @error_check
862
+ puts Meteor::Exception::NoSuchElementException.new(name, attr_name, attr_value).message
863
+ end
864
+ @elm_ = nil
865
+ end
866
+
867
+ @elm_
868
+ end
869
+
870
+ private :element_5
871
+
872
+ def element_quote_5(name, attr_name1, attr_value1, attr_name2, attr_value2)
873
+ @_name = Regexp.quote(name)
874
+ @_attr_name1 = Regexp.quote(attr_name1)
875
+ @_attr_name2 = Regexp.quote(attr_name2)
876
+ @_attr_value1 = Regexp.quote(attr_value1)
877
+ @_attr_value2 = Regexp.quote(attr_value2)
878
+ end
879
+
880
+ private :element_quote_5
881
+
882
+ def element_with_5_1(name)
883
+
884
+ # puts @res.captures.length
885
+ case @res.captures.length
886
+ when FOUR
887
+ # eleemnt (要素)
888
+ @elm_ = Meteor::Element.new(name)
889
+ # attribute (属性)
890
+ @elm_.attributes = @res[1]
891
+ # content (内容)
892
+ @elm_.mixed_content = @res[2]
893
+ # document (全体)
894
+ @elm_.document = @res[0]
895
+ # pattern (内容あり要素検索用パターン)
896
+ # @pattern_cc = String.new('') << "<" << @_name << '\\s[^<>]*(?:' << @_attr_name1 << '="'
897
+ # @pattern_cc << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
898
+ # @pattern_cc << @_attr_value2 << '"|' << @_attr_name2 << '="'
899
+ # @pattern_cc << @_attr_value2 << '"[^<>]*' << @_attr_name1 << '="'
900
+ # @pattern_cc << @_attr_value1 << '")[^<>]*>((?!(' << @_name
901
+ # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
902
+ @pattern_cc = "<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
903
+
904
+ @elm_.pattern = @pattern_cc
905
+ @elm_.empty = true
906
+ @elm_.parser = self
907
+ when FIVE
908
+ # element (要素)
909
+ @elm_ = Meteor::Element.new(name)
910
+ # attribute (属性)
911
+ @elm_.attributes = @res[2]
912
+ # content (内容)
913
+ @elm_.mixed_content = @res[3]
914
+ # documement (全体)
915
+ @elm_.document = @res[0]
916
+ # pattern (内容あり要素検索用パターン)
917
+ # @pattern_cc = String.new('') << "<" << @_name << '\\s[^<>]*(?:' << @_attr_name1 << '="'
918
+ # @pattern_cc << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
919
+ # @pattern_cc << @_attr_value2 << '"|' << @_attr_name2 << '="'
920
+ # @pattern_cc << @_attr_value2 << '"[^<>]*' << @_attr_name1 << '="'
921
+ # @pattern_cc << @_attr_value1 << '")[^<>]*>((?!(' << @_name
922
+ # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
923
+ @pattern_cc = "<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
924
+
925
+ @elm_.pattern = @pattern_cc
926
+ @elm_.empty = true
927
+ @elm_.parser = self
928
+
929
+ when THREE,SIX
930
+ # element (要素)
931
+ @elm_ = Meteor::Element.new(name)
932
+ # attribute (属性)
933
+ @elm_.attributes = @res[1].chop
934
+ # content (内容)
935
+ @elm_.mixed_content = @res[3]
936
+ # document (全体)
937
+ @elm_.document = @res[0]
938
+ # search pattern of element with content (要素ありタグ検索用パターン)
939
+ @elm_.pattern = @pattern_cc
940
+
941
+ @elm_.empty = true
942
+ @elm_.parser = self
943
+ end
944
+ @elm_
945
+ end
946
+
947
+ private :element_with_5_1
948
+
949
+ def element_with_5_2
950
+
951
+ element_pattern_with_5_2
952
+
953
+ if @sbuf.length == ZERO || @cnt != ZERO
954
+ return nil
955
+ end
956
+
957
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
958
+ @res = @pattern.match(@root.document)
959
+
960
+ @res
961
+ end
962
+
963
+ private :element_with_5_2
964
+
965
+ def element_pattern_with_5_2
966
+
967
+ # @pattern_cc_1 = String.new('') << "<" << @_name << '(\\s[^<>]*(?:' << @_attr_name1 << '="'
968
+ # @pattern_cc_1 << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
969
+ # @pattern_cc_1 << @_attr_value2 << '"|' << @_attr_name2 << '="'
970
+ # @pattern_cc_1 << @_attr_value2 << '"[^<>]*' << @_attr_name1 << '="'
971
+ # @pattern_cc_1 << @_attr_value1 << '")([^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>)))'
972
+ @pattern_cc_1 = "<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")([^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>)))"
973
+ @pattern_cc_1b = String.new('') << "<" << @_name << '(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))'
974
+ # @pattern_cc_1b = "<#{@_name}(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
975
+
976
+ # @pattern_cc_1_1 = String.new('') << "<" << @_name << '(\\s[^<>]*(?:' << @_attr_name1 << '="'
977
+ # @pattern_cc_1_1 << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
978
+ # @pattern_cc_1_1 << @_attr_value2 << '"|' << @_attr_name2 << '="'
979
+ # @pattern_cc_1_1 << @_attr_value2 << '"[^<>]*' << @_attr_name1 << '="'
980
+ # @pattern_cc_1_1 << @_attr_value1 << '")(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))('
981
+ @pattern_cc_1_1 = "<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))("
982
+ @pattern_cc_1_2 = String.new('') << '.*?<' << @_name << '(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))'
983
+ @pattern_cc_2 = String.new('') << '<\\/' << @_name << '>'
984
+ @pattern_cc_2_1 = String.new('') << '.*?<\/' << @_name << '>'
985
+ @pattern_cc_2_2 = String.new('') << '.*?)<\/' << @_name << '>'
986
+
987
+ # @pattern_cc_1_2 = ".*?<#{@_name}(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
988
+ # @pattern_cc_2 = String.new('') << "<\\/#{@_name}>"
989
+ # @pattern_cc_2_1 = ".*?<\\/#{@_name}>"
990
+ # @pattern_cc_2_2 = ".*?)<\\/#{@_name}>"
991
+
992
+ # search of element with content (内容あり要素検索)
993
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
994
+
995
+ @sbuf = String.new('')
996
+
997
+ @pattern_2 = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
998
+ @pattern_1b = Meteor::Core::Util::PatternCache.get(@pattern_cc_1b)
999
+ @cnt = 0
1000
+
1001
+ create_element_pattern
1002
+ @pattern_cc = @sbuf
1003
+ end
1004
+
1005
+ private :element_pattern_with_5_2
1006
+
1007
+ def element_without_5(name)
1008
+ element_without_5_1(name, '")[^<>]*)\\/>')
1009
+ end
1010
+
1011
+ private :element_without_5
1012
+
1013
+ def element_without_5_1(name, closer)
1014
+ # element (要素)
1015
+ @elm_ = Meteor::Element.new(name)
1016
+ # attribute (属性)
1017
+ @elm_.attributes = @res[1]
1018
+ # document (全体)
1019
+ @elm_.document = @res[0]
1020
+ # pattern (空要素検索用パターン)
1021
+ # @pattern_cc = String.new('') << "<" << @_name << '\\s[^<>]*(?:' << @_attr_name1 << '="'
1022
+ # @pattern_cc << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
1023
+ # @pattern_cc << @_attr_value2 << '"|' << @_attr_name2 << '="'
1024
+ # @pattern_cc << @_attr_value2 << '"[^<>]*' << @_attr_name1 << '="'
1025
+ # @pattern_cc << @_attr_value1 << closer
1026
+ @pattern_cc = "<#{@_name}(\\s[^<>]*(#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}#{closer}"
1027
+ @elm_.pattern = @pattern_cc
1028
+ @elm_.parser = self
1029
+
1030
+ @elm_
1031
+ end
1032
+
1033
+ private :element_without_5_1
1034
+
1035
+ #
1036
+ # get element using attribute1,2(name="value") (属性1・属性2(属性名="属性値")で検索し、要素を取得する)
1037
+ # @param [String] attr_name1 attribute name1 (属性名1)
1038
+ # @param [String] attr_value1 attribute value1 (属性値1)
1039
+ # @param [String] attr_name2 attribute name2 (属性名2)
1040
+ # @param [String]attr_value2 attribute value2 (属性値2)
1041
+ # @return [Meteor::Element] element (要素)
1042
+ #
1043
+ def element_4(attr_name1, attr_value1, attr_name2, attr_value2)
1044
+
1045
+ element_quote_4(attr_name1, attr_value1, attr_name2, attr_value2)
1046
+
1047
+ element_pattern_4
1048
+
1049
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
1050
+ @res = @pattern.match(@root.document)
1051
+
1052
+ if @res
1053
+ # @elm_ = element_5(@res[1], attr_name1, attr_value1,attr_name2, attr_value2)
1054
+ element_5(@res[1], attr_name1, attr_value1, attr_name2, attr_value2)
1055
+ else
1056
+ if @error_check
1057
+ puts Meteor::Exception::NoSuchElementException.new(attr_name1, attr_value1, attr_name2, attr_value2).message
1058
+ end
1059
+ @elm_ = nil
1060
+ end
1061
+
1062
+ @elm_
1063
+ end
1064
+
1065
+ private :element_4
1066
+
1067
+ def element_quote_4(attr_name1, attr_value1, attr_name2, attr_value2)
1068
+ @_attr_name1 = Regexp.quote(attr_name1)
1069
+ @_attr_name2 = Regexp.quote(attr_name2)
1070
+ @_attr_value1 = Regexp.quote(attr_value1)
1071
+ @_attr_value2 = Regexp.quote(attr_value2)
1072
+ end
1073
+
1074
+ private :element_quote_4
1075
+
1076
+ def element_pattern_4
1077
+
1078
+ # @pattern_cc = String.new('') << '<([^<>"]*)\\s([^<>]*(' << @_attr_name1 << '="'
1079
+ # @pattern_cc << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
1080
+ # @pattern_cc << @_attr_value2 << '"|' << @_attr_name2 << '="'
1081
+ # @pattern_cc << @_attr_value2 << '"[^<>]*' << @_attr_name1 << '="'
1082
+ # @pattern_cc << @_attr_value1 << '"'
1083
+ @pattern_cc = "<([^<>\"]*)\\s[^<>]*(#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")"
1084
+
1085
+ end
1086
+
1087
+ private :element_pattern_4
1088
+
1089
+ def create_element_pattern
1090
+ @position = 0
1091
+
1092
+ while (@res = @pattern.match(@root.document, @position)) || @cnt > ZERO
1093
+ if @res
1094
+ if @cnt > ZERO
1095
+ @position2 = @res.end(0)
1096
+ @res = @pattern_2.match(@root.document, @position)
1097
+
1098
+ if @res
1099
+ @position = @res.end(0)
1100
+
1101
+ if @position > @position2
1102
+ @sbuf << @pattern_cc_1_2
1103
+ @cnt += 1
1104
+ @position = @position2
1105
+ else
1106
+ @cnt -= ONE
1107
+
1108
+ if @cnt != ZERO
1109
+ @sbuf << @pattern_cc_2_1
1110
+ else
1111
+ @sbuf << @pattern_cc_2_2
1112
+ break
1113
+ end
1114
+ end
1115
+ else
1116
+ @sbuf << @pattern_cc_1_2
1117
+ @cnt += 1
1118
+ @position = @position2
1119
+ end
1120
+ else
1121
+ @position = @res.end(0)
1122
+ @sbuf << @pattern_cc_1_1
1123
+ @cnt += ONE
1124
+ end
1125
+ else
1126
+ if @cnt == ZERO
1127
+ break
1128
+ end
1129
+
1130
+ @res = @pattern_2.match(@root.document, @position)
1131
+
1132
+ if @res
1133
+ @cnt -= ONE
1134
+
1135
+ if @cnt != ZERO
1136
+ @sbuf << @pattern_cc_2_1
1137
+ else
1138
+ @sbuf << @pattern_cc_2_2
1139
+ break
1140
+ end
1141
+
1142
+ @position = @res.end(0)
1143
+ else
1144
+ break
1145
+ end
1146
+ end
1147
+
1148
+ @pattern = @pattern_1b
1149
+ end
1150
+ end
1151
+
1152
+ private :create_element_pattern
1153
+
1154
+ =begin
1155
+ def create_element_pattern_2(args_cnt)
1156
+ @position = 0
1157
+
1158
+ while (@res = @pattern.match(@root.document, @position)) || @cnt > ZERO
1159
+ if @res
1160
+ if @cnt > ZERO
1161
+ @position2 = @res.end(0)
1162
+ @res = @pattern_2.match(@root.document, @position)
1163
+
1164
+ if @res
1165
+ @position = @res.end(0)
1166
+
1167
+ if @position > @position2
1168
+ @sbuf << @pattern_cc_1_2
1169
+ @cnt += 1
1170
+ @position = @position2
1171
+ else
1172
+ @cnt -= ONE
1173
+
1174
+ if @cnt != ZERO
1175
+ @sbuf << @pattern_cc_2_1
1176
+ else
1177
+ @sbuf << @pattern_cc_2_2
1178
+ break
1179
+ end
1180
+ end
1181
+ else
1182
+ @sbuf << @pattern_cc_1_2
1183
+ @cnt += 1
1184
+ @position = @position2
1185
+ end
1186
+ else
1187
+ @position = @res.end(0)
1188
+ @_name = @res[1]
1189
+
1190
+ create_pattern_2(args_cnt)
1191
+
1192
+ @sbuf << @pattern_cc_1_1
1193
+ @cnt += ONE
1194
+ end
1195
+ else
1196
+ if @cnt == ZERO
1197
+ break
1198
+ end
1199
+
1200
+ @res = @pattern_2.match(@root.document, @position)
1201
+
1202
+ if @res
1203
+ @cnt -= ONE
1204
+
1205
+ if @cnt != ZERO
1206
+ @sbuf << @pattern_cc_2_1
1207
+ else
1208
+ @sbuf << @pattern_cc_2_2
1209
+ break
1210
+ end
1211
+
1212
+ @position = @res.end(0)
1213
+ else
1214
+ break
1215
+ end
1216
+ end
1217
+
1218
+ @pattern = @pattern_1b
1219
+ end
1220
+ end
1221
+
1222
+ private :create_element_pattern_2
1223
+
1224
+ # def create_pattern_2
1225
+ # end
1226
+
1227
+ # private :create_pattern_2
1228
+ =end
1229
+
1230
+ # get elements (要素を取得する)
1231
+ # @overload elements(name)
1232
+ # get elements using tag name (要素のタグ名で要素を取得する)
1233
+ # @param [String,Symbol] name tag name (タグ名)
1234
+ # @return [Array<Meteor::Element>] element array(要素配列)
1235
+ # @overload elements(name,attrs)
1236
+ # get elements using tag name and attribute map (要素のタグ名と属性(属性名="属性値")あるいは属性1・属性2(属性名="属性値")で要素を取得する)
1237
+ # @param [String,Symbol] name tag name (タグ名)
1238
+ # @param [Hash<String,String>,Hash<Symbol,String>] attrs attribute map (属性マップ)
1239
+ # @return [Array<Meteor::Element>] element array (要素配列)
1240
+ # @overload elements(attrs)
1241
+ # get elements using attribute map (属性(属性名="属性値")あるいは属性1・属性2(属性名="属性値")で要素を取得する)
1242
+ # @param [Hash<String,String>,Hash<Symbol,String>] attrs attribute map (属性マップ)
1243
+ # @return [Array<Meteor::Element>] element array (要素配列)
1244
+ # @overload elements(name,attr_name,attr_value)
1245
+ # get elements using tag name and attribute(name="value") (要素のタグ名と属性(属性名="属性値")で要素を取得する)
1246
+ # @param [String,Symbol] name tag name (タグ名)
1247
+ # @param [String,Symbol] attr_name attribute name (属性名)
1248
+ # @param [String] attr_value attribute value (属性値)
1249
+ # @return [Array<Meteor::Element>] element array (要素配列)
1250
+ # @overload elements(attr_name,attr_value)
1251
+ # get elements using attribute(name="value") (属性(属性名="属性値")で要素を取得する)
1252
+ # @param [String,Symbol] attr_name attribute name (属性名)
1253
+ # @param [String] attr_value attribute value (属性値)
1254
+ # @return [Array<Meteor::Element>] element array (要素配列)
1255
+ # @overload elements(name,attr_name1,attr_value1,attr_name2,attr_value2)
1256
+ # get elements using tag name and attribute1,2(name="value") (要素のタグ名と属性1・属性2(属性名="属性値")で要素を取得する)
1257
+ # @param [String,Symbol] name tag name (タグ名)
1258
+ # @param [String,Symbol] attr_name1 attribute name1 (属性名1)
1259
+ # @param [String] attr_value1 attribute value1 (属性値1)
1260
+ # @param [String,Symbol] attr_name2 attribute name2 (属性名2)
1261
+ # @param [String] attr_value2 attribute value2 (属性値2)
1262
+ # @return [Array<Meteor::Element>] element array (要素配列)
1263
+ # @overload elements(attr_name1,attr_value1,attr_name2,attr_value2)
1264
+ # get elements using attribute1,2(name="value") (属性1・属性2(属性名="属性値")で要素を取得する)
1265
+ # @param [String,Symbol] attr_name1 attribute name1 (属性名1)
1266
+ # @param [String] attr_value1 attribute value1 (属性値1)
1267
+ # @param [String,Symbol] attr_name2 attribute name2 (属性名2)
1268
+ # @param [String] attr_value2 attribute value2 (属性値2)
1269
+ # @return [Array<Meteor::Element>] element array (要素配列)
1270
+ #
1271
+ def elements(elm, attrs = nil,*args)
1272
+ if !attrs
1273
+ if elm.kind_of?(String)
1274
+ elements_(elm)
1275
+ elsif elm.kind_of?(Hash)
1276
+ if elm.size == ONE
1277
+ elements_(elm.keys[0], elm.values[0])
1278
+ elsif elm.size == TWO
1279
+ elements_(elm.keys[0], elm.values[0], elm.keys[1], elm.values[1])
1280
+ else
1281
+ raise ArgumentError
1282
+ end
1283
+ else
1284
+ raise ArgumentError
1285
+ end
1286
+ elsif attrs.kind_of?(Hash)
1287
+ if attrs.size == ONE
1288
+ elements_(elm, attrs.keys[0], attrs.values[0])
1289
+ elsif attrs.size == TWO
1290
+ elements_(elm, attrs.keys[0], attrs.values[0], attrs.keys[1], attrs.values[1])
1291
+ else
1292
+ @elm_ = nil
1293
+ raise ArgumentError
1294
+ end
1295
+ elsif attrs.kind_of?(String)
1296
+ case args.length
1297
+ when ZERO
1298
+ elements_(elm,attrs)
1299
+ when ONE
1300
+ elements_(elm, attrs, args[0])
1301
+ when TWO
1302
+ elements_(elm, attrs, args[0],args[1])
1303
+ when THREE
1304
+ elements_(elm, attrs, args[0],args[1],args[2])
1305
+ else
1306
+ @elm_ = nil
1307
+ raise ArgumentError
1308
+ end
1309
+ else
1310
+ @elm_ = nil
1311
+ raise ArgumentError
1312
+ end
1313
+ end
1314
+
1315
+ def elements_(*args)
1316
+ elm_arr = Array.new
1317
+
1318
+ @on_search = true
1319
+
1320
+ case args.size
1321
+ when ONE
1322
+ @elm_ = element_1(*args)
1323
+ when TWO
1324
+ @elm_ = element_2(*args)
1325
+ when THREE
1326
+ @elm_ = element_3(*args)
1327
+ when FOUR
1328
+ @elm_ = element_4(*args)
1329
+ when FIVE
1330
+ @elm_ = element_5(*args)
1331
+ end
1332
+
1333
+ if !@elm_
1334
+ return elm_arr
1335
+ end
1336
+
1337
+ @pattern_cc = @elm_.pattern
1338
+
1339
+ # puts @pattern_cc
1340
+
1341
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
1342
+
1343
+ @position = 0
1344
+
1345
+ while (@res = @pattern.match(@root.document,@position))
1346
+ @position = @res.end(0)
1347
+ # puts @res[0]
1348
+ # if @res
1349
+ case args.size
1350
+ when ONE
1351
+ if @elm_.empty
1352
+ element_with_1(@elm_.name)
1353
+ else
1354
+ element_without_1(@elm_.name)
1355
+ end
1356
+ when TWO,THREE
1357
+ if @elm_.empty
1358
+ element_with_3_1(@elm_.name)
1359
+ else
1360
+ element_without_3(@elm_.name)
1361
+ end
1362
+ when FOUR,FIVE
1363
+ if @elm_.empty
1364
+ element_with_5_1(@elm_.name)
1365
+ else
1366
+ element_without_5(@elm_.name)
1367
+ end
1368
+ end
1369
+
1370
+ @elm_.pattern = Regexp.quote(@elm_.document)
1371
+ elm_arr << @elm_
1372
+
1373
+ @element_cache.store(@elm_.object_id, @elm_)
1374
+
1375
+ # else
1376
+ # break
1377
+ # end
1378
+ end
1379
+
1380
+ @on_search = false
1381
+
1382
+ elm_arr
1383
+ end
1384
+
1385
+ #
1386
+ # get elements using selector like CSS3 (CSS3のようにセレクタを用いて要素を取得する)
1387
+ # CSS3 selector partial support (CSS3セレクタの部分的サポート)
1388
+ # @param [String] selector selector (セレクタ)
1389
+ # @return [Array<Meteor::Element>] element array (要素配列)
1390
+ #
1391
+ def find(selector)
1392
+ open_count = selector.count('[')
1393
+
1394
+ case open_count
1395
+ when ZERO
1396
+ if selector.count('#.') == 0
1397
+ if @res = @@pattern_find_1.match(selector)
1398
+ elements_(@res[1])
1399
+ else
1400
+ nil
1401
+ end
1402
+ elsif selector.count('#') == 1
1403
+ if selector[0] == '#'
1404
+ if @res = @@pattern_find_2_1.match(selector)
1405
+ elements_('id', @res[1])
1406
+ else
1407
+ nil
1408
+ end
1409
+ else
1410
+ if @res = @@pattern_find_3_2.match(selector)
1411
+ elements_(@res[1], 'id', @res[2])
1412
+ else
1413
+ nil
1414
+ end
1415
+ end
1416
+ elsif selector.count('.') == 1
1417
+ if selector[0] == '.'
1418
+ if @res = @@pattern_find_2_2.match(selector)
1419
+ elements_('class', @res[1])
1420
+ else
1421
+ nil
1422
+ end
1423
+ else
1424
+ if @res = @@pattern_find_3_3.match(selector)
1425
+ elements_(@res[1], 'class', @res[2])
1426
+ else
1427
+ nil
1428
+ end
1429
+ end
1430
+ end
1431
+ when ONE
1432
+ if selector[0] == '['
1433
+ if @res = @@pattern_find_2_3.match(selector)
1434
+ elements_(@res[1], @res[2])
1435
+ else
1436
+ nil
1437
+ end
1438
+ else
1439
+ if @res = @@pattern_find_3_1.match(selector)
1440
+ elements_(@res[1], @res[2], @res[3])
1441
+ else
1442
+ nil
1443
+ end
1444
+ end
1445
+ when 2
1446
+ if selector[0] == '['
1447
+ if @res = @@pattern_find_4.match(selector)
1448
+ elements_(@res[1], @res[2], @res[3], @res[4])
1449
+ else
1450
+ nil
1451
+ end
1452
+ else
1453
+ if @res = @@pattern_find_5.match(selector)
1454
+ elements_(@res[1], @res[2], @res[3], @res[4], @res[5])
1455
+ else
1456
+ nil
1457
+ end
1458
+ end
1459
+ else
1460
+ nil
1461
+ end
1462
+ end
1463
+
1464
+ #
1465
+ # @overload attr(elm,attr)
1466
+ # set attribute of element (要素の属性をセットする)
1467
+ # @param [Meteor::Element] elm element (要素)
1468
+ # @param [Hash<String,String>,Hash<Symbol,String>] attr attribute (属性)
1469
+ # @return [Meteor::Element] element (要素)
1470
+ # @overload attr(elm,attr_name,attr_value)
1471
+ # set attribute of element (要素の属性をセットする)
1472
+ # @param [Meteor::Element] elm element (要素)
1473
+ # @param [String,Symbol] attr_name attribute name (属性名)
1474
+ # @param [String,true,false] attr_value attribute value (属性値)
1475
+ # @return [Meteor::Element] element (要素)
1476
+ # @overload attr(elm,attr_name)
1477
+ # get attribute value of element (要素の属性値を取得する)
1478
+ # @param [Meteor::Element] elm element (要素)
1479
+ # @param [String,Symbol] attr_name attribute name (属性名)
1480
+ # @return [String] attribute value (属性値)
1481
+ #
1482
+ def attr(elm, attr,*args)
1483
+ if attr.kind_of?(String) || attr.kind_of?(Symbol)
1484
+ case args.length
1485
+ when ZERO
1486
+ get_attr_value(elm, attr.to_s)
1487
+ when ONE
1488
+ if args[0] != nil
1489
+ elm.document_sync = true
1490
+ set_attribute_3(elm, attr.to_s,args[0])
1491
+ else
1492
+ remove_attr(elm, attr.to_s)
1493
+ end
1494
+ end
1495
+
1496
+ elsif attr.kind_of?(Hash) && attr.size == 1
1497
+ if attr.values[0] != nil
1498
+ elm.document_sync = true
1499
+ set_attribute_3(elm, attr.keys[0].to_s, attr.values[0])
1500
+ else
1501
+ remove_attr(elm, attr.keys[0].to_s)
1502
+ end
1503
+ # elsif attrs.kind_of?(Hash) && attrs.size >= 1
1504
+ # elm.document_sync = true
1505
+ # attrs.each{|name,value|
1506
+ # set_attribute_3(elm,name,value)
1507
+ # }
1508
+ else
1509
+ raise ArgumentError
1510
+ end
1511
+ end
1512
+
1513
+ #
1514
+ # set attribute of element (要素の属性を編集する)
1515
+ # @param [Meteor::Element] elm element (要素)
1516
+ # @param [String] attr_name attribute name (属性名)
1517
+ # @param [String,true,false] attr_value attribute value (属性値)
1518
+ # @return [Meteor::Element] element (要素)
1519
+ #
1520
+ def set_attribute_3(elm, attr_name, attr_value)
1521
+ if !elm.cx
1522
+ attr_value = escape(attr_value.to_s)
1523
+ # update attributes (属性群の更新)
1524
+ edit_attrs_(elm, attr_name, attr_value)
1525
+ end
1526
+ elm
1527
+ end
1528
+
1529
+ private :set_attribute_3
1530
+
1531
+ def edit_attrs_(elm, attr_name, attr_value)
1532
+
1533
+ # attribute search (属性検索)
1534
+ # @res = @pattern.match(elm.attributes)
1535
+
1536
+ # (検索対象属性の存在判定)
1537
+ if elm.attributes.include?(String.new(' ') << attr_name << '="')
1538
+ @_attr_value = attr_value
1539
+
1540
+ # replace attribute (属性の置換)
1541
+ @pattern = Meteor::Core::Util::PatternCache.get(String.new('') << attr_name << '="[^"]*"')
1542
+ # @pattern = Meteor::Core::Util::PatternCache.get("#{attr_name}=\"[^\"]*\"")
1543
+
1544
+ elm.attributes.sub!(@pattern, String.new('') << attr_name << '="' << @_attr_value << '"')
1545
+ # elm.attributes.sub!(@pattern, "#{attr_name}=\"#{@_attr_value}\"")
1546
+ else
1547
+ # add an attribute to attrubutes (属性文字列の最後に新規の属性を追加する)
1548
+ @_attr_value = attr_value
1549
+
1550
+ if '' != elm.attributes && '' != elm.attributes.strip
1551
+ elm.attributes = String.new('') << ' ' << elm.attributes.strip
1552
+ else
1553
+ elm.attributes = String.new('')
1554
+ end
1555
+
1556
+ elm.attributes << ' ' << attr_name << '="' << @_attr_value << '"'
1557
+ # elm.attributes << " #{attr_name}=\"#{@_attr_value}\""
1558
+ end
1559
+ end
1560
+
1561
+ private :edit_attrs_
1562
+
1563
+ #
1564
+ # get attribute value of element (要素の属性値を取得する)
1565
+ # @param [Meteor::Element] elm element (要素)
1566
+ # @param [String] attr_name attribute name (属性名)
1567
+ # @return [String] attribute value (属性値)
1568
+ #
1569
+ def get_attr_value(elm, attr_name)
1570
+ get_attr_value_(elm, attr_name)
1571
+ end
1572
+
1573
+ private :get_attr_value
1574
+
1575
+ def get_attr_value_(elm, attr_name)
1576
+
1577
+ # attribute search pattern (属性検索用パターン)
1578
+ @pattern = Meteor::Core::Util::PatternCache.get(String.new('') << attr_name << '="([^"]*)"')
1579
+ # @pattern = Meteor::Core::Util::PatternCache.get("#{attr_name}=\"([^\"]*)\"")
1580
+
1581
+ @res = @pattern.match(elm.attributes)
1582
+
1583
+ if @res
1584
+ unescape(@res[1])
1585
+ else
1586
+ nil
1587
+ end
1588
+ end
1589
+
1590
+ private :get_attr_value_
1591
+
1592
+ #
1593
+ # @overload attrs(elm,attrs)
1594
+ # @param [Meteor::element] elm element (要素)
1595
+ # @param [Hash<String,String>,Hash<Symbol,String>] attrs attribute map (属性マップ)
1596
+ # @overload attrs(elm)
1597
+ # @param [Meteor::element] elm element (要素)
1598
+ # @return [Hash<String,String>] attribute map (要素マップ)
1599
+ #
1600
+ def attrs(elm,*args)
1601
+ case args.length
1602
+ when ZERO
1603
+ get_attrs(elm)
1604
+ when ONE
1605
+ if args[0].kind_of?(Hash)
1606
+ if args[0].size == 1
1607
+ elm.document_sync = true
1608
+ set_attribute_3(elm, args[0].keys[0].to_s, args[0].values[0])
1609
+ elsif args[0].size >= 1
1610
+ set_attrs(elm, args[0])
1611
+ else
1612
+ raise ArgumentError
1613
+ end
1614
+ else
1615
+ raise ArgumentError
1616
+ end
1617
+ else
1618
+ raise ArgumentError
1619
+ end
1620
+ end
1621
+
1622
+ #
1623
+ # get attribute map (属性マップを取得する)
1624
+ # @param [Meteor::Element] elm element (要素)
1625
+ # @return [Hash<String,String>] attribute map (属性マップ)
1626
+ #
1627
+ def get_attrs(elm)
1628
+ attrs = Hash.new
1629
+
1630
+ elm.attributes.scan(@@pattern_get_attrs_map) do |a, b|
1631
+ attrs.store(a, unescape(b))
1632
+ end
1633
+
1634
+ attrs
1635
+ end
1636
+
1637
+ private :get_attrs
1638
+
1639
+ #
1640
+ # set attribute map (要素に属性マップをセットする)
1641
+ # @param [Meteor::Element] elm element (要素)
1642
+ # @param [Hash<String,String>] attr_map attribute map (属性マップ)
1643
+ # @return [Meteor::Element] element (要素)
1644
+ #
1645
+ def set_attrs(elm, attr_map)
1646
+ if !elm.cx
1647
+ elm.document_sync = true
1648
+ attr_map.each do |name, value|
1649
+ set_attribute_3(elm, name.to_s, value)
1650
+ end
1651
+ end
1652
+ elm
1653
+ end
1654
+
1655
+ private :set_attrs
1656
+
1657
+ #
1658
+ # @overload attr_map(elm,attr_map)
1659
+ # set attribute map (属性マップをセットする)
1660
+ # @param [Meteor::Element] elm element (要素)
1661
+ # @param [Meteor::AttributeMap] attr_map attribute map (属性マップ)
1662
+ # @return [Meteor::Element] element (要素)
1663
+ # @overload attr_map(elm)
1664
+ # get attribute map (属性マップを取得する)
1665
+ # @param [Meteor::Element] elm element (要素)
1666
+ # @return [Meteor::AttributeMap] attribute map (属性マップ)
1667
+ #
1668
+ def attr_map(elm,*args)
1669
+ case args.length
1670
+ when ZERO
1671
+ get_attr_map(elm)
1672
+ when ONE
1673
+ # if elm.kind_of?(Meteor::Element) && args[0].kind_of?(Meteor::AttributeMap)
1674
+ elm.document_sync = true
1675
+ set_attr_map(elm, args[0])
1676
+ # end
1677
+ else
1678
+ raise ArgumentError
1679
+ end
1680
+ end
1681
+
1682
+ #
1683
+ # get attribute map (属性マップを取得する)
1684
+ # @param [Meteor::Element] elm element (要素)
1685
+ # @return [Meteor::AttributeMap] attribute map (属性マップ)
1686
+ #
1687
+ def get_attr_map(elm)
1688
+ attrs = Meteor::AttributeMap.new
1689
+
1690
+ elm.attributes.scan(@@pattern_get_attrs_map) do |a, b|
1691
+ attrs.store(a, unescape(b))
1692
+ end
1693
+ attrs.recordable = true
1694
+
1695
+ attrs
1696
+ end
1697
+
1698
+ private :get_attr_map
1699
+
1700
+ #
1701
+ # set attribute map (要素に属性マップをセットする)
1702
+ # @param [Meteor::Element] elm element (要素)
1703
+ # @param [Meteor::AttributeMap] attr_map attribute map (属性マップ)
1704
+ # @return [Meteor::Element] element (要素)
1705
+ #
1706
+ def set_attr_map(elm, attr_map)
1707
+ if !elm.cx
1708
+ attr_map.map.each do |name, attr|
1709
+ if attr_map.changed(name)
1710
+ edit_attrs_(elm, name.to_s, attr.value)
1711
+ elsif attr_map.removed(name)
1712
+ remove_attrs_(elm, name.to_s)
1713
+ end
1714
+ end
1715
+ end
1716
+ elm
1717
+ end
1718
+
1719
+ private :set_attr_map
1720
+
1721
+ #
1722
+ # @overload content(elm,content,entity_ref=true)
1723
+ # set contents of element (要素の内容をセットする)
1724
+ # @param [Meteor::Element] elm element (要素)
1725
+ # @param [String] content content of element (要素の内容)
1726
+ # @param [true,false] entity_ref entity reference flag (エンティティ参照フラグ)
1727
+ # @return [Meteor::Element] element (要素)
1728
+ # @deprecated
1729
+ # @overload content(elm,content)
1730
+ # set content of element (要素の内容をセットする)
1731
+ # @param [Meteor::Element] elm element (要素)
1732
+ # @param [String] content content of element (要素の内容)
1733
+ # @return [Meteor::Element] element (要素)
1734
+ # @overload content(elm)
1735
+ # get content of element (要素の内容を取得する)
1736
+ # @param [Meteor::Element] elm element (要素)
1737
+ # @return [String] content (内容)
1738
+ #
1739
+ def content(*args)
1740
+ case args.length
1741
+ when ONE
1742
+ # if args[0].kind_of?(Meteor::Element)
1743
+ get_content_1(args[0])
1744
+ # else
1745
+ # raise ArgumentError
1746
+ # end
1747
+ when TWO
1748
+ # if args[0].kind_of?(Meteor::Element) && args[1].kind_of?(String)
1749
+ args[0].document_sync = true
1750
+ set_content_2(args[0], args[1].to_s)
1751
+ # else
1752
+ # raise ArgumentError
1753
+ # end
1754
+ when THREE
1755
+ args[0].document_sync = true
1756
+ set_content_3(args[0], args[1].to_s, args[2])
1757
+ else
1758
+ raise ArgumentError
1759
+ end
1760
+ end
1761
+
1762
+ #
1763
+ # set content of element (要素の内容をセットする)
1764
+ # @param [Meteor::Element] elm element (要素)
1765
+ # @param [String] content content of element (要素の内容)
1766
+ # @param [true,false] entity_ref entity reference flag (エンティティ参照フラグ)
1767
+ # @return [Meteor::Element] element (要素)
1768
+ #
1769
+ def set_content_3(elm, content, entity_ref=true)
1770
+
1771
+ if entity_ref || !elm.raw_content
1772
+ escape_content(content, elm)
1773
+ end
1774
+ elm.mixed_content = content
1775
+ elm
1776
+ end
1777
+
1778
+ private :set_content_3
1779
+
1780
+ #
1781
+ # set content of element (要素の内容をセットする)
1782
+ # @param [Meteor::Element] elm element (要素)
1783
+ # @param [String] content content of element (要素の内容)
1784
+ # @return [Meteor::Element] element (要素)
1785
+ #
1786
+ def set_content_2(elm, content)
1787
+ # set_content_3(elm, content)
1788
+ unless elm.raw_content
1789
+ escape_content(content, elm)
1790
+ end
1791
+ elm.mixed_content = content
1792
+ elm
1793
+ end
1794
+
1795
+ private :set_content_2
1796
+
1797
+ #
1798
+ # get content of element (要素の内容を取得する)
1799
+ # @param [Meteor::Element] elm element (要素)
1800
+ # @return [String] content (内容)
1801
+ #
1802
+ def get_content_1(elm)
1803
+ if !elm.cx
1804
+ if elm.empty
1805
+ unescape_content(elm.mixed_content, elm)
1806
+ else
1807
+ nil
1808
+ end
1809
+ else
1810
+ unescape_content(elm.mixed_content, elm)
1811
+ end
1812
+ end
1813
+
1814
+ private :get_content_1
1815
+
1816
+ #
1817
+ # remove attribute of element (要素の属性を消す)
1818
+ # @param [Meteor::Element] elm element (要素)
1819
+ # @param [String] attr_name attribute name (属性名)
1820
+ # @return [Meteor::Element] element (要素)
1821
+ #
1822
+ def remove_attr(elm, attr_name)
1823
+ if !elm.cx
1824
+ elm.document_sync = true
1825
+ remove_attrs_(elm, attr_name.to_s)
1826
+ end
1827
+
1828
+ elm
1829
+ end
1830
+
1831
+ def remove_attrs_(elm, attr_name)
1832
+ # attribute search pattern (属性検索用パターン)
1833
+ @pattern = Meteor::Core::Util::PatternCache.get(String.new('') << attr_name << '="[^"]*"\\s?')
1834
+ # @pattern = Meteor::Core::Util::PatternCache.get("#{attr_name}=\"[^\"]*\"\\s?")
1835
+ # replace attrubute (属性の置換)
1836
+ elm.attributes.sub!(@pattern, '')
1837
+ end
1838
+
1839
+ private :remove_attrs_
1840
+
1841
+ #
1842
+ # remove element (要素を消す)
1843
+ # @param [Meteor::Element] elm element (要素)
1844
+ #
1845
+ def remove_element(elm)
1846
+ elm.removed = true
1847
+ nil
1848
+ end
1849
+
1850
+ #
1851
+ # get cx(comment extension) tag (CX(コメント拡張)タグを取得する)
1852
+ # @overload cxtag(name,id)
1853
+ # get cx(comment extension) tag using tag name and id attribute (要素のタグ名とID属性(id="ID属性値")でCX(コメント拡張)タグを取得する)
1854
+ # @param [String,Symbol] name tag name (タグ名)
1855
+ # @param [String] id id attribute value (ID属性値)
1856
+ # @return [Meteor::Element] element (要素)
1857
+ # @overload cxtag(id)
1858
+ # get cx(comment extension) tag using id attribute (ID属性(id="ID属性値")でCX(コメント拡張)タグを取得する)
1859
+ # @param [String] id id attribute value (ID属性値)
1860
+ # @return [Meteor::Element] element (要素)
1861
+ #
1862
+ def cxtag(*args)
1863
+ case args.length
1864
+ when ONE
1865
+ cxtag_1(args[0].to_s)
1866
+ if @elm_
1867
+ @element_cache.store(@elm_.object_id, @elm_)
1868
+ end
1869
+ when TWO
1870
+ cxtag_2(args[0].to_s, args[1].to_s)
1871
+ if @elm_
1872
+ @element_cache.store(@elm_.object_id, @elm_)
1873
+ end
1874
+ else
1875
+ raise ArgumentError
1876
+ end
1877
+ end
1878
+
1879
+ #
1880
+ # get cx(comment extension) tag using tag name and id attribute (要素のタグ名とID属性(id="ID属性値")でCX(コメント拡張)タグを取得する)
1881
+ # @param [String] name tag name (タグ名)
1882
+ # @param [String] id id attribute value (ID属性値)
1883
+ # @return [Meteor::Element] element (要素)
1884
+ #
1885
+ def cxtag_2(name, id)
1886
+ @_name = Regexp.quote(name)
1887
+ @_id = Regexp.quote(id)
1888
+
1889
+ # CX tag search pattern (CXタグ検索用パターン)
1890
+ # @pattern_cc = String.new('') << "<!--\\s@" << @_name << '\\s([^<>]*id="'
1891
+ # @pattern_cc << id << '"[^<>]*)-->(((?!(<!--\\s/@' << @_name << ")).)*)<!--\\s/@" << @_name << "\\s-->"
1892
+ # @pattern_cc = "<!--\\s@#{tag}\\s([^<>]*id=\"#{id}\"[^<>]*)-->(((?!(<!--\\s\\/@#{tag})).)*)<!--\\s\\/@#{tag}\\s-->"
1893
+ @pattern_cc = "<!--\\s@#{@_name}\\s([^<>]*id=\"#{@_id}\"[^<>]*)-->(((?!(<!--\\s/@#{@_name})).)*)<!--\\s/@#{@_name}\\s-->"
1894
+
1895
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
1896
+ # CX tag search (CXタグ検索)
1897
+ @res = @pattern.match(@root.document)
1898
+
1899
+ if @res
1900
+ # element (要素)
1901
+ @elm_ = Meteor::Element.new(name)
1902
+
1903
+ @elm_.cx = true
1904
+ # attrubute (属性)
1905
+ @elm_.attributes = @res[1]
1906
+ # content (内容)
1907
+ @elm_.mixed_content = @res[2]
1908
+ # document (全体)
1909
+ @elm_.document = @res[0]
1910
+ # pattren (要素検索パターン)
1911
+ @elm_.pattern = @pattern_cc
1912
+
1913
+ @elm_.empty = true
1914
+
1915
+ @elm_.parser = self
1916
+ else
1917
+ @elm_ = nil
1918
+ end
1919
+
1920
+ @elm_
1921
+ end
1922
+
1923
+ private :cxtag_2
1924
+
1925
+ #
1926
+ # get cx(comment extension) tag using id attribute (ID属性(id="ID属性値")で検索し、CX(コメント拡張)タグを取得する)
1927
+ # @param [String] id id attribute value (ID属性値)
1928
+ # @return [Meteor::Element] element (要素)
1929
+ #
1930
+ def cxtag_1(id)
1931
+
1932
+ @_id = Regexp.quote(id)
1933
+
1934
+ @pattern_cc = String.new('') << '<!--\\s@([^<>]*)\\s[^<>]*id="' << @_id << '"'
1935
+ # @pattern_cc = "<!--\\s@([^<>]*)\\s[^<>]*id=\"#{@_id}\""
1936
+
1937
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
1938
+
1939
+ @res = @pattern.match(@root.document)
1940
+
1941
+ if @res
1942
+ # @elm_ = cxtag(@res[1],id)
1943
+ cxtag(@res[1], id)
1944
+ else
1945
+ @elm_ = nil
1946
+ end
1947
+
1948
+ @elm_
1949
+ end
1950
+
1951
+ private :cxtag_1
1952
+
1953
+ #
1954
+ # replace element (要素を置換する)
1955
+ # @param [Meteor::Element] elm element (要素)
1956
+ # @param [String] replace_document string for replacement (置換文字列)
1957
+ #
1958
+ def replace(elm, replace_document)
1959
+ # tag replacement pattern (タグ置換パターン)
1960
+ @pattern = Meteor::Core::Util::PatternCache.get(elm.pattern)
1961
+ # replace tag (タグ置換)
1962
+ @root.document.sub!(@pattern, replace_document)
1963
+ end
1964
+
1965
+ private :replace
1966
+
1967
+ def reflect
1968
+ # puts @element_cache.size.to_s
1969
+ @element_cache.values.each do |item|
1970
+ if item.usable
1971
+ # puts "#{item.name}:#{item.document}"
1972
+ if !item.removed
1973
+ if item.copy
1974
+ @pattern = Meteor::Core::Util::PatternCache.get(item.pattern)
1975
+ @root.document.sub!(@pattern, item.copy.parser.document_hook)
1976
+ # item.copy.parser.element_cache.clear
1977
+ item.copy = nil
1978
+ else
1979
+ edit_document_1(item)
1980
+ # edit_pattern_(item)
1981
+ end
1982
+ else
1983
+ replace(item, '')
1984
+ end
1985
+ item.usable = false
1986
+ end
1987
+ end
1988
+ end
1989
+
1990
+ protected :reflect
1991
+
1992
+ def edit_document_1(elm)
1993
+ edit_document_2(elm, '/>')
1994
+ end
1995
+
1996
+ private :edit_document_1
1997
+
1998
+ def edit_document_2(elm, closer)
1999
+
2000
+ # replace tag (タグ置換)
2001
+ @pattern = Meteor::Core::Util::PatternCache.get(elm.pattern)
2002
+ @root.document.sub!(@pattern, elm.document)
2003
+ end
2004
+
2005
+ private :edit_document_2
2006
+
2007
+ #
2008
+ # reflect (反映する)
2009
+ #
2010
+ def flash
2011
+
2012
+ if self.element_hook
2013
+ if self.element_hook.origin.mono
2014
+ if self.element_hook.origin.cx
2015
+ # @root.hookDocument << '<!-- @' << @root.element.name << ' '
2016
+ # @root.hookDocument << @root.element.attributes << '-->'
2017
+ # @root.hookDocument << @root.element.mixed_content << '<!-- /@'
2018
+ # @root.hookDocument << @root.element.name << ' -->'
2019
+ self.document_hook << "<!-- @#{self.element_hook.name} #{self.element_hook.attributes}-->#{self.element_hook.mixed_content}<!-- /@#{self.element_hook.name} -->"
2020
+
2021
+ # self.document_hook << @root.kaigyo_code << "<!-- @#{self.element_hook.name} #{self.element_hook.attributes}-->#{self.element_hook.mixed_content}<!-- /@#{self.element_hook.name} -->"
2022
+ else
2023
+ # @root.hookDocument << "<" << @root.element.name
2024
+ # @root.hookDocument << @root.element.attributes << '>' << @root.element.mixed_content
2025
+ # @root.hookDocument << '</' << @root.element.name << '>'
2026
+ self.document_hook << "<#{self.element_hook.name}#{self.element_hook.attributes}>#{self.element_hook.mixed_content}</#{self.element_hook.name}>"
2027
+
2028
+ # self.document_hook << @root.kaigyo_code << "<#{self.element_hook.name}#{self.element_hook.attributes}>#{self.element_hook.mixed_content}</#{self.element_hook.name}>"
2029
+ end
2030
+ self.element_hook = Element.new!(self.element_hook.origin, self)
2031
+ else
2032
+ reflect
2033
+ @_attributes = self.element_hook.attributes
2034
+
2035
+ if self.element_hook.origin.cx
2036
+ # @root.hookDocument << '<!-- @' << @root.element.name << ' '
2037
+ # @root.hookDocument << @_attributes << '-->'
2038
+ # @root.hookDocument << @root.document << '<!-- /@'
2039
+ # @root.hookDocument << @root.element.name << ' -->'
2040
+ self.document_hook << "<!-- @#{self.element_hook.name} #{@_attributes}-->#{@root.document}<!-- /@#{self.element_hook.name} -->"
2041
+
2042
+ # self.document_hook << @root.kaigyo_code << "<!-- @#{self.element_hook.name} #{@_attributes}-->#{@root.document}<!-- /@#{self.element_hook.name} -->"
2043
+ else
2044
+ # @root.hookDocument << "<" << @root.element.name
2045
+ # @root.hookDocument << @_attributes << '>' << @root.document
2046
+ # @root.hookDocument << '</' << @root.element.name << '>'
2047
+ self.document_hook << "<#{self.element_hook.name}#{@_attributes}>#{@root.document}</#{self.element_hook.name}>"
2048
+
2049
+ # self.document_hook << @root.kaigyo_code << "<#{self.element_hook.name}#{@_attributes}>#{@root.document}</#{self.element_hook.name}>"
2050
+ end
2051
+ self.element_hook = Element.new!(self.element_hook.origin, self)
2052
+ end
2053
+ else
2054
+ reflect
2055
+ @element_cache.clear
2056
+ # フック判定が"false"の場合
2057
+ clean
2058
+ end
2059
+ end
2060
+
2061
+ def clean
2062
+ # replace CX start tag (CX開始タグ置換)
2063
+ @pattern = @@pattern_clean1
2064
+ @root.document.gsub!(@pattern, '')
2065
+ # rplace CX end tag (CX終了タグ置換)
2066
+ @pattern = @@pattern_clean2
2067
+ @root.document.gsub!(@pattern, '')
2068
+ # @root.document << "<!-- Powered by Meteor (C)Yasumasa Ashida -->"
2069
+ end
2070
+
2071
+ private :clean
2072
+
2073
+ #
2074
+ # mirror element (要素を射影する)
2075
+ #
2076
+ # @param [Meteor::Element] elm element (要素)
2077
+ # @return [Meteor::Element] element (要素)
2078
+ #
2079
+ def shadow(elm)
2080
+ if elm.empty
2081
+ # case of element with content (内容あり要素の場合)
2082
+ set_mono_info(elm)
2083
+
2084
+ pif2 = create(self)
2085
+
2086
+ @elm_ = Element.new!(elm, pif2)
2087
+
2088
+ if !elm.mono
2089
+ pif2.root_element.document = String.new(elm.mixed_content)
2090
+ else
2091
+ pif2.root_element.document = String.new(elm.document)
2092
+ end
2093
+ pif2.root_element.kaigyo_code = elm.parser.root_element.kaigyo_code
2094
+
2095
+ @elm_
2096
+ end
2097
+ end
2098
+
2099
+ # private :shadow
2100
+
2101
+ def set_mono_info(elm)
2102
+
2103
+ @res = @@pattern_set_mono1.match(elm.mixed_content)
2104
+
2105
+ if @res
2106
+ elm.mono = true
2107
+ end
2108
+ end
2109
+
2110
+ private :set_mono_info
2111
+
2112
+ def is_match(regex, str)
2113
+ if regex.kind_of?(Regexp)
2114
+ is_match_r(regex, str)
2115
+ elsif regex.kind_of?(Array)
2116
+ is_match_a(regex, str)
2117
+ elsif regex.kind_of?(String)
2118
+ if regex.eql?(str.downcase)
2119
+ true
2120
+ else
2121
+ false
2122
+ end
2123
+ else
2124
+ raise ArgumentError
2125
+ end
2126
+ end
2127
+
2128
+ private :is_match
2129
+
2130
+ def is_match_r(regex, str)
2131
+ if regex.match(str.downcase)
2132
+ true
2133
+ else
2134
+ false
2135
+ end
2136
+ end
2137
+
2138
+ private :is_match_r
2139
+
2140
+ def is_match_a(regex, str)
2141
+ str = str.downcase
2142
+ regex.each do |item|
2143
+ if item.eql?(str)
2144
+ return true
2145
+ end
2146
+ end
2147
+ false
2148
+ end
2149
+
2150
+ private :is_match_a
2151
+
2152
+ def is_match_s(regex, str)
2153
+ if regex.match(str.downcase)
2154
+ true
2155
+ else
2156
+ false
2157
+ end
2158
+ end
2159
+
2160
+ private :is_match_s
2161
+
2162
+ def create(pif)
2163
+ case pif.doc_type
2164
+ when Parser::HTML4
2165
+ Meteor::Ml::Html4::ParserImpl.new
2166
+ when Parser::XHTML4
2167
+ Meteor::Ml::Xhtml4::ParserImpl.new
2168
+ when Parser::HTML
2169
+ Meteor::Ml::Html::ParserImpl.new
2170
+ when Parser::XHTML
2171
+ Meteor::Ml::Xhtml::ParserImpl.new
2172
+ when Parser::XML
2173
+ Meteor::Ml::Xml::ParserImpl.new
2174
+ else
2175
+ nil
2176
+ end
2177
+ end
2178
+
2179
+ private :create
2180
+ end
2181
+ end
2182
+ end