meteor 0.9.12 → 0.9.14

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