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,712 @@
1
+ # -* coding: UTF-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ module Meteor
5
+ module Ml
6
+ module Html4
7
+ #
8
+ # HTML4 parser (HTMLパーサ)
9
+ #
10
+ class ParserImpl < Meteor::Core::Kernel
11
+ # KAIGYO_CODE = "\r?\n|\r"
12
+ # KAIGYO_CODE = "\r\n|\n|\r"
13
+ KAIGYO_CODE = ["\r\n", "\n", "\r"]
14
+ BR = "<br>"
15
+
16
+ # @@match_tag = "br|hr|img|input|meta|base"
17
+ #[Array] void elemets (空要素)
18
+ @@match_tag = ["br", "hr", "img", "input", "meta", "base"]
19
+ # @@match_tag_2 = "textarea|option|pre"
20
+ #[Array] elements where line breaks do not need to be converted to <br> (改行を<br>に変換する必要のない要素)
21
+ @@match_tag_2 = ["textarea", "option", "pre"]
22
+
23
+ #[Array] non-nestable elements (入れ子にできない要素)
24
+ @@match_tag_sng = ["texarea", "select", "option", "form", "fieldset"]
25
+
26
+ #[Array] boolean elements (論理値で指定する属性)
27
+ @@attr_logic = ["disabled", "readonly", "checked", "selected", "multiple"]
28
+
29
+ # DISABLE_ELEMENT = "input|textarea|select|optgroup"
30
+ #[Array] elements with the disabled attribute (disabled属性のある要素)
31
+ DISABLE_ELEMENT = ["input", "textarea", "select", "optgroup"]
32
+ # READONLY_TYPE = "text|password"
33
+ #[Array] the type of an input element with a readonly attribute (readonly属性のあるinput要素のタイプ)
34
+ READONLY_TYPE = ["text", "password"]
35
+
36
+ SELECTED_M = "\\sselected\\s|\\sselected$|\\sSELECTED\\s|\\sSELECTED$"
37
+ # SELECTED_M = [' selected ',' selected',' SELECTED ',' SELECTED']
38
+ SELECTED_R = "selected\\s|selected$|SELECTED\\s|SELECTED$"
39
+ CHECKED_M = "\\schecked\\s|\\schecked$|\\sCHECKED\\s|\\sCHECKED$"
40
+ # CHECKED_M = [' checked ',' checked',' CHECKED ',' CHECKED']
41
+ CHECKED_R = "checked\\s|checked$|CHECKED\\s|CHECKED$"
42
+ DISABLED_M = "\\sdisabled\\s|\\sdisabled$|\\sDISABLED\\s|\\sDISABLED$"
43
+ # DISABLED_M = [' disabled ',' disiabled',' DISABLED ',' DISABLED']
44
+ DISABLED_R = "disabled\\s|disabled$|DISABLED\\s|DISABLED$"
45
+ READONLY_M = "\\sreadonly\\s|\\sreadonly$|\\sREADONLY\\s|\\sREADONLY$"
46
+ # READONLY_M = [' readonly ',' readonly',' READONLY ',' READONLY']
47
+ READONLY_R = "readonly\\s|readonly$|READONLY\\s|READONLY$"
48
+ MULTIPLE_M = "\\smultiple\\s|\\smultiple$|\\sMULTIPLE\\s|\\sMULTIPLE$"
49
+ # MULTIPLE_M = [' multiple ',' multiple',' MULTIPLE ',' MULTIPLE']
50
+ MULTIPLE_R = "multiple\\s|multiple$|MULTIPLE\\s|MULTIPLE$"
51
+
52
+ # @@pattern_true = Regexp.new("true")
53
+ # @@pattern_false = Regexp.new("false")
54
+
55
+ PATTERN_UNESCAPE = "&(amp|quot|apos|gt|lt|nbsp);"
56
+ GET_ATTRS_MAP2 = "\\s(disabled|readonly|checked|selected|multiple)"
57
+
58
+ @@pattern_selected_m = Regexp.new(SELECTED_M)
59
+ @@pattern_selected_r = Regexp.new(SELECTED_R)
60
+ @@pattern_checked_m = Regexp.new(CHECKED_M)
61
+ @@pattern_checked_r = Regexp.new(CHECKED_R)
62
+ @@pattern_disabled_m = Regexp.new(DISABLED_M)
63
+ @@pattern_disabled_r = Regexp.new(DISABLED_R)
64
+ @@pattern_readonly_m = Regexp.new(READONLY_M)
65
+ @@pattern_readonly_r = Regexp.new(READONLY_R)
66
+ @@pattern_multiple_m = Regexp.new(MULTIPLE_M)
67
+ @@pattern_multiple_r = Regexp.new(MULTIPLE_R)
68
+
69
+ @@pattern_unescape = Regexp.new(PATTERN_UNESCAPE)
70
+ @@pattern_get_attrs_map2 = Regexp.new(GET_ATTRS_MAP2)
71
+
72
+ # @@pattern_match_tag = Regexp.new(@@match_tag)
73
+ # @@pattern_match_tag2 = Regexp.new(@@match_tag_2)
74
+
75
+ TABLE_FOR_ESCAPE_ = {
76
+ "&" => "&amp;",
77
+ "\"" => "&quot;",
78
+ "'" => "&apos;",
79
+ "<" => "&lt;",
80
+ ">" => "&gt;",
81
+ " " => "&nbsp;"
82
+ }
83
+
84
+ TABLE_FOR_ESCAPE_CONTENT_ = {
85
+ "&" => "&amp;",
86
+ "\"" => "&quot;",
87
+ "'" => "&apos;",
88
+ "<" => "&lt;",
89
+ ">" => "&gt;",
90
+ " " => "&nbsp;",
91
+ "\r\n" => "<br>",
92
+ "\r" => "<br>",
93
+ "\n" => "<br>"
94
+ }
95
+
96
+ PATTERN_ESCAPE = "[&\"'<> ]"
97
+ PATTERN_ESCAPE_CONTENT = "[&\"'<> \\n]"
98
+
99
+ @@pattern_escape = Regexp.new(PATTERN_ESCAPE)
100
+ @@pattern_escape_content = Regexp.new(PATTERN_ESCAPE_CONTENT)
101
+ @@pattern_br_2 = Regexp.new(BR)
102
+
103
+ #
104
+ # initializer (イニシャライザ)
105
+ # @overload initialize
106
+ # @overload initialize(ps)
107
+ # @param [Meteor::Parser] ps parser (パーサ)
108
+ #
109
+ def initialize(*args)
110
+ super()
111
+ @doc_type = Parser::HTML4
112
+ case args.length
113
+ when ZERO
114
+ # initialize_0
115
+ when ONE
116
+ initialize_1(args[0])
117
+ else
118
+ raise ArgumentError
119
+ end
120
+ end
121
+
122
+ #
123
+ # initializer (イニシャライザ)
124
+ #
125
+ # def initialize_0
126
+ # end
127
+ #
128
+ # private :initialize_0
129
+
130
+ #
131
+ # initializer (イニシャライザ)
132
+ # @param [Meteor::Parser] ps paser (パーサ)
133
+ #
134
+ def initialize_1(ps)
135
+ @root.document = String.new(ps.document)
136
+ self.document_hook = String.new(ps.document_hook)
137
+ @root.content_type = String.new(ps.root_element.content_type)
138
+ @root.charset = ps.root_element.charset
139
+ @root.kaigyo_code = ps.root_element.kaigyo_code
140
+ end
141
+
142
+ private :initialize_1
143
+
144
+ #
145
+ # parse document (ドキュメントを解析する)
146
+ #
147
+ def parse
148
+ analyze_ml
149
+ end
150
+
151
+ #
152
+ # analyze document (ドキュメントをパースする)
153
+ #
154
+ def analyze_ml
155
+ analyze_content_type
156
+ analyze_kaigyo_code
157
+
158
+ @res = nil
159
+ end
160
+
161
+ private :analyze_ml
162
+
163
+ #
164
+ # get content type (コンテントタイプを取得する)
165
+ # @return [String] conent type (コンテントタイプ)
166
+ #
167
+ def content_type
168
+ @root.content_type
169
+ end
170
+
171
+ #
172
+ # analyze document , set content type (ドキュメントをパースし、コンテントタイプをセットする)
173
+ #
174
+ def analyze_content_type
175
+ @error_check = false
176
+
177
+ element_3("meta", "http-equiv", "Content-Type")
178
+
179
+ if !@elm_
180
+ element_3("meta", "http-equiv", "Content-Type")
181
+ end
182
+
183
+ @error_check = true
184
+
185
+ if @elm_
186
+ content = @elm_.attr("content")
187
+ content_arr = content&.split(";")
188
+ @root.content_type = content_arr&.at(0) || ""
189
+ @root.charset = content_arr&.at(1)&.split("=")&.at(1) || ""
190
+ else
191
+ @root.content_type = ""
192
+ end
193
+ end
194
+
195
+ protected :analyze_content_type
196
+
197
+ #
198
+ # analuze document , set newline (ドキュメントをパースし、改行コードをセットする)
199
+ #
200
+ def analyze_kaigyo_code
201
+ for a in KAIGYO_CODE
202
+ if @root.document.include?(a)
203
+ @root.kaigyo_code = a
204
+ # puts "kaigyo:" << @root.kaigyo_code
205
+ end
206
+ end
207
+ end
208
+
209
+ protected :analyze_kaigyo_code
210
+
211
+ #
212
+ # get element using tag name (要素のタグ名で検索し、要素を取得する)
213
+ # @param [String] name tag name (タグ名)
214
+ # @return [Meteor::Element] element (要素)
215
+ #
216
+ def element_1(name)
217
+ @_name = Regexp.quote(name)
218
+
219
+ # case of void element (空要素の場合(<->内容あり要素の場合))
220
+ if is_match(@@match_tag, name)
221
+ # void element search pattern (空要素検索用パターン)
222
+ @pattern_cc = String.new("") << "<" << @_name << "(|\\s[^<>]*)>"
223
+ # @pattern_cc = "<#{@_name}(|\\s[^<>]*)>"
224
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
225
+ @res = @pattern.match(@root.document)
226
+ if @res
227
+ element_without_1(name)
228
+ else
229
+ if @error_check
230
+ puts(Meteor::Exception::NoSuchElementException.new(name).message)
231
+ end
232
+
233
+ @elm_ = nil
234
+ end
235
+ else
236
+ # search pattern of element with content (内容あり要素検索用パターン()
237
+ # @pattern_cc = String.new('') << "<" << @_name << '(|\\s[^<>]*)>(((?!(' << @_name
238
+ # @pattern_cc << '[^<>]*>)).)*)<\\/' << @_name << '>'
239
+ @pattern_cc = "<#{@_name}(|\\s[^<>]*)>(((?!(#{tag}[^<>]*>)).)*)<\\/#{@_name}>"
240
+
241
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
242
+ # search of element with content (内容あり要素検索)
243
+ @res = @pattern.match(@root.document)
244
+ # case of element with content (内容あり要素の場合)
245
+ if @res
246
+ element_with_1(name)
247
+ else
248
+ if @error_check
249
+ puts(Meteor::Exception::NoSuchElementException.new(name).message)
250
+ end
251
+
252
+ @elm_ = nil
253
+ end
254
+ end
255
+
256
+ @elm_
257
+ end
258
+
259
+ private :element_1
260
+
261
+ def element_without_1(name)
262
+ @elm_ = Meteor::Element.new(name)
263
+ # attribute (属性)
264
+ @elm_.attributes = @res[1]
265
+ # void element search pattern (空要素検索用パターン)
266
+ @elm_.pattern = @pattern_cc
267
+
268
+ @elm_.document = @res[0]
269
+
270
+ @elm_.parser = self
271
+ end
272
+
273
+ private :element_without_1
274
+
275
+ #
276
+ # get element using tag name and attribute(name="value") (要素のタグ名、属性(属性名="属性値")で検索し、要素を取得する)
277
+ # @param [String] name tag name (タグ名)
278
+ # @param [String] attr_name attribute name (属性名)
279
+ # @param [String] attr_value attribute value (属性値)
280
+ # @param [true,false] quote quote flag (クオート・フラグ)
281
+ # @return [Meteor::Element] element (要素)
282
+ #
283
+ def element_3(name, attr_name, attr_value, quote = true)
284
+
285
+ element_quote_3(name, attr_name, attr_value) if quote
286
+
287
+ # case of void element (空要素の場合(<->内容あり要素の場合))
288
+ if is_match(@@match_tag, name)
289
+ # void element search pattern (空要素検索パターン)
290
+ # @pattern_cc = String.new('') << "<" << @_name << '(\\s[^<>]*' << @_attr_name << '="'
291
+ # @pattern_cc << @_attr_value << '"[^<>]*)>'
292
+ @pattern_cc = "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)>"
293
+
294
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
295
+ # void element search (空要素検索)
296
+ @res = @pattern.match(@root.document)
297
+ if @res
298
+ element_without_3(name)
299
+ else
300
+ if @error_check
301
+ puts(Meteor::Exception::NoSuchElementException.new(name, attr_name, attr_value).message)
302
+ end
303
+
304
+ @elm_ = nil
305
+ end
306
+ else
307
+ # search pattern of element with content (内容あり要素検索パターン)
308
+ # @pattern_cc = String.new('') << "<" << @_name << '(\\s[^<>]*' << @_attr_name << '="'
309
+ # @pattern_cc << @_attr_value << '"[^<>]*)>(((?!(' << @_name
310
+ # @pattern_cc << '[^<>]*>)).)*)<\\/' << @_name << '>'
311
+ @pattern_cc = "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
312
+
313
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
314
+ # search of element with content (内容あり要素検索)
315
+ @res = @pattern.match(@root.document)
316
+
317
+ if !@res && !is_match(@@match_tag_sng, name)
318
+ @res = element_with_3_2
319
+ end
320
+
321
+ if @res
322
+ element_with_3_1(name)
323
+ else
324
+ if @error_check
325
+ puts(Meteor::Exception::NoSuchElementException.new(name, attr_name, attr_value).message)
326
+ end
327
+
328
+ @elm_ = nil
329
+ end
330
+ end
331
+
332
+ @elm_
333
+ end
334
+
335
+ private :element_3
336
+
337
+ def element_without_3(name)
338
+ element_without_3_1(name, "\"[^<>]*)>")
339
+ end
340
+
341
+ private :element_without_3
342
+
343
+ #
344
+ # get element using attribute(name="value") (属性(属性名="属性値")で検索し、要素を取得する)
345
+ # @param [String] attr_name attribute name (属性名)
346
+ # @param [String] attr_value attribute value (属性値)
347
+ # @return [Meteor::Element] element (要素)
348
+ #
349
+ def element_2(attr_name, attr_value)
350
+
351
+ element_quote_2(attr_name, attr_value)
352
+
353
+ # @pattern_cc = String.new('') << '<([^<>"]*)\\s[^<>]*' << @_attr_name << '="' << @_attr_value
354
+ # @pattern_cc << '"[^<>]*>'
355
+ @pattern_cc = "<([^<>\"]*)\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*>"
356
+
357
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
358
+ @res = @pattern.match(@root.document)
359
+
360
+ if @res
361
+ element_3(@res[1], attr_name, attr_value)
362
+ else
363
+ if @error_check
364
+ puts(Meteor::Exception::NoSuchElementException.new(attr_name, attr_value).message)
365
+ end
366
+
367
+ @elm_ = nil
368
+ end
369
+
370
+ @elm_
371
+ end
372
+
373
+ private :element_2
374
+
375
+ #
376
+ # get element using tag name and attribute1,2(name="value") (要素のタグ名と属性1・属性2(属性名="属性値")で検索し、要素を取得する)
377
+ # @param [String] name tag name (タグ名)
378
+ # @param [String] attr_name1 attribute name1 (属性名1)
379
+ # @param [String] attr_value1 attribute value1 (属性値1)
380
+ # @param [String] attr_name2 attribute name2 (属性名2)
381
+ # @param [String] attr_value2 attribute value2 (属性値2)
382
+ # @return [Meteor::Element] element (要素)
383
+ #
384
+ def element_5(name, attr_name1, attr_value1, attr_name2, attr_value2)
385
+
386
+ element_quote_5(name, attr_name1, attr_value1, attr_name2, attr_value2)
387
+
388
+ # 空要素の場合(<->内容あり要素の場合)
389
+ if is_match(@@match_tag, name)
390
+ # void element search pattern (空要素検索パターン)
391
+ # @pattern_cc = String.new('') << "<" << @_name << '(\\s[^<>]*(?:' << @_attr_name1 << '="'
392
+ # @pattern_cc << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
393
+ # @pattern_cc << @_attr_value2 << '"|' << @_attr_name2 << '="'
394
+ # @pattern_cc << @_attr_value2 << '"[^<>]*' << @_attr_name1 << '="'
395
+ # @pattern_cc << @_attr_value1 << '")[^<>]*)>'
396
+ @pattern_cc = "<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")[^<>]*)>"
397
+
398
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
399
+ # void element search (空要素検索)
400
+ @res = @pattern.match(@root.document)
401
+
402
+ if @res
403
+ element_without_5(name)
404
+ else
405
+ if @error_check
406
+ puts(
407
+ Meteor::Exception::NoSuchElementException
408
+ .new(name, attr_name1, attr_value1, attr_name2, attr_value2)
409
+ .message
410
+ )
411
+ end
412
+
413
+ @elm_ = nil
414
+ end
415
+ else
416
+ # search pattern of element with content (内容あり要素検索パターン)
417
+ # @pattern_cc = String.new('') << "<" << @_name << '(\\s[^<>]*(?:' << @_attr_name1 << '="'
418
+ # @pattern_cc << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
419
+ # @pattern_cc << @_attr_value2 << '"|' << @_attr_name2 << '="'
420
+ # @pattern_cc << @_attr_value2 << '"[^<>]*' << @_attr_name1 << '="'
421
+ # @pattern_cc << @_attr_value1 << '")[^<>]*)>(((?!(' << @_name
422
+ # @pattern_cc << '[^<>]*>)).)*)<\\/' << @_name << '>'
423
+ @pattern_cc = "<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
424
+
425
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
426
+ # search of element with content (内容あり要素検索)
427
+ @res = @pattern.match(@root.document)
428
+
429
+ if !@res && !is_match(@@match_tag_sng, tag)
430
+ @res = element_with_5_2
431
+ end
432
+
433
+ if @res
434
+ element_with_5_1(name)
435
+ else
436
+ if @error_check
437
+ puts(
438
+ Meteor::Exception::NoSuchElementException
439
+ .new(name, attr_name1, attr_value1, attr_name2, attr_value2)
440
+ .message
441
+ )
442
+ end
443
+
444
+ @elm_ = nil
445
+ end
446
+ end
447
+
448
+ @elm_
449
+ end
450
+
451
+ private :element_5
452
+
453
+ def element_without_5(name)
454
+ element_without_5_1(name, "\")[^<>]*)>")
455
+ end
456
+
457
+ private :element_without_5
458
+
459
+ #
460
+ # get element using attribute1,2(name="value") (属性1・属性2(属性名="属性値")で検索し、要素を取得する)
461
+ #
462
+ # @param [String] attr_name1 attribute name1 (属性名1)
463
+ # @param [String] attr_value1 attribute value1 (属性値1)
464
+ # @param [String] attr_name2 attribute name2 (属性名2)
465
+ # @param [String] attr_value2 attribute value2 (属性値2)
466
+ # @return [Meteor::Element] element (要素)
467
+ #
468
+ def element_4(attr_name1, attr_value1, attr_name2, attr_value2)
469
+ element_quote_4(attr_name1, attr_value1, attr_name2, attr_value2)
470
+
471
+ # @pattern_cc = String.new('') << '<([^<>"]*)\\s([^<>]*(' << @_attr_name1 << '="' << @_attr_value1
472
+ # @pattern_cc << '"[^<>]*' << @_attr_name2 << '="' << @_attr_value2
473
+ # @pattern_cc << '"|' << @_attr_name2 << '="' << @_attr_value2
474
+ # @pattern_cc << '"[^<>]*' << @_attr_name1 << '="' << @_attr_value1
475
+ # @pattern_cc << '")[^<>]*)>'
476
+ @pattern_cc = "<([^<>\"]*)\\s([^<>]*(#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")[^<>]*)>"
477
+
478
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
479
+
480
+ @res = @pattern.match(@root.document)
481
+
482
+ if @res
483
+ element_5(@res[1], attr_name1, attr_value1, attr_name2, attr_value2)
484
+ else
485
+ if @error_check
486
+ puts(
487
+ Meteor::Exception::NoSuchElementException.new(attr_name1, attr_value1, attr_name2, attr_value2).message
488
+ )
489
+ end
490
+
491
+ @elm_ = nil
492
+ end
493
+
494
+ @elm_
495
+ end
496
+
497
+ private :element_4
498
+
499
+ def edit_attrs_(elm, attr_name, attr_value)
500
+ if is_match("selected", attr_name) && is_match("option", elm.name)
501
+ edit_attrs_5(elm, attr_name, attr_value, @@pattern_selected_m, @@pattern_selected_r)
502
+ elsif is_match("multiple", attr_name) && is_match("select", elm.name)
503
+ edit_attrs_5(elm, attr_name, attr_value, @@pattern_multiple_m, @@pattern_multiple_r)
504
+ elsif is_match("disabled", attr_name) && is_match(DISABLE_ELEMENT, elm.name)
505
+ edit_attrs_5(elm, attr_name, attr_value, @@pattern_disabled_m, @@pattern_disabled_r)
506
+ elsif is_match("checked", attr_name) && is_match("input", elm.name) && is_match("radio", get_type(elm))
507
+ edit_attrs_5(elm, attr_name, attr_value, @@pattern_checked_m, @@pattern_checked_r)
508
+ elsif is_match("readonly", attr_name) &&
509
+ (is_match("textarea", elm.name) || (is_match("input", elm.name) && is_match(READONLY_TYPE, get_type(elm))))
510
+ edit_attrs_5(elm, attr_name, attr_value, @@pattern_readonly_m, @@pattern_readonly_r)
511
+ else
512
+ super(elm, attr_name, attr_value)
513
+ end
514
+ end
515
+
516
+ private :edit_attrs_
517
+
518
+ def edit_attrs_5(elm, attr_name, attr_value, match_p, replace)
519
+ if true.equal?(attr_value) || is_match("true", attr_value)
520
+ @res = match_p.match(elm.attributes)
521
+
522
+ if !@res
523
+ if !"".eql?(elm.attributes) && !"".eql?(elm.attributes.strip)
524
+ elm.attributes = String.new("") << " " << elm.attributes.strip
525
+ else
526
+ elm.attributes = String.new("")
527
+ end
528
+
529
+ elm.attributes << " " << attr_name
530
+ # else
531
+ end
532
+ elsif false.equal?(attr_value) || is_match("false", attr_value)
533
+ elm.attributes.sub!(replace, "")
534
+ end
535
+ end
536
+
537
+ private :edit_attrs_5
538
+
539
+ def edit_document_1(elm)
540
+ edit_document_2(elm, ">")
541
+ end
542
+
543
+ private :edit_document_1
544
+
545
+ def get_attr_value_(elm, attr_name)
546
+ if is_match("selected", attr_name) && is_match("option", elm.name)
547
+ get_attr_value_r(elm, @@pattern_selected_m)
548
+ elsif is_match("multiple", attr_name) && is_match("select", elm.name)
549
+ get_attr_value_r(elm, @@pattern_multiple_m)
550
+ elsif is_match("disabled", attr_name) && is_match(DISABLE_ELEMENT, elm.name)
551
+ get_attr_value_r(elm, @@pattern_disabled_m)
552
+ elsif is_match("checked", attr_name) && is_match("input", elm.name) && is_match("radio", get_type(elm))
553
+ get_attr_value_r(elm, @@pattern_checked_m)
554
+ elsif is_match("readonly", attr_name) &&
555
+ (is_match("textarea", elm.name) || (is_match("input", elm.name) && is_match(READONLY_TYPE, get_type(elm))))
556
+ get_attr_value_r(elm, @@pattern_readonly_m)
557
+ else
558
+ super(elm, attr_name)
559
+ end
560
+ end
561
+
562
+ private :get_attr_value_
563
+
564
+ def get_type(elm)
565
+ if !elm.type_value
566
+ elm.type_value = get_attr_value_(elm, "type")
567
+ if !elm.type_value
568
+ elm.type_value = get_attr_value_(elm, "TYPE")
569
+ end
570
+ end
571
+
572
+ elm.type_value
573
+ end
574
+
575
+ private :get_type
576
+
577
+ def get_attr_value_r(elm, match_p)
578
+
579
+ @res = match_p.match(elm.attributes)
580
+
581
+ if @res
582
+ "true"
583
+ else
584
+ "false"
585
+ end
586
+ end
587
+
588
+ private :get_attr_value_r
589
+
590
+ #
591
+ # get attribute map (属性マップを取得する)
592
+ # @param [Meteor::Element] elm element (要素)
593
+ # @return [Hash] attribute map (属性マップ)
594
+ #
595
+ def get_attrs(elm)
596
+ attrs = Hash.new
597
+
598
+ elm.attributes.scan(@@pattern_get_attrs_map) do |a, b|
599
+ attrs.store(a, unescape(b))
600
+ end
601
+
602
+ elm.attributes.scan(@@pattern_get_attrs_map2) do |a|
603
+ attrs.store(a[0], "true")
604
+ end
605
+
606
+ attrs
607
+ end
608
+
609
+ private :get_attrs
610
+
611
+ #
612
+ # get attribute map of element (要素の属性マップを取得する)
613
+ # @param [Meteor::Element] elm element (要素)
614
+ # @return [Meteor::AttributeMap] attribute map (属性マップ)
615
+ #
616
+ def get_attr_map(elm)
617
+ attrs = Meteor::AttributeMap.new
618
+
619
+ elm.attributes.scan(@@pattern_get_attrs_map) do |a, b|
620
+ attrs.store(a, unescape(b))
621
+ end
622
+
623
+ elm.attributes.scan(@@pattern_get_attrs_map2) do |a|
624
+ attrs.store(a[0], "true")
625
+ end
626
+
627
+ attrs.recordable = true
628
+
629
+ attrs
630
+ end
631
+
632
+ private :get_attr_map
633
+
634
+ def remove_attrs_(elm, attr_name)
635
+ if !is_match(@@attr_logic, attr_name)
636
+ # attribute search pattern (属性検索用パターン)
637
+ @pattern = Meteor::Core::Util::PatternCache.get(String.new("") << attr_name << "=\"[^\"]*\"\\s?")
638
+ # @pattern = Meteor::Core::Util::PatternCache.get("#{attr_name}=\"[^\"]*\"\\s?")
639
+ elm.attributes.sub!(@pattern, "")
640
+ else
641
+ # attribute search pattern (属性検索用パターン)
642
+ @pattern = Meteor::Core::Util::PatternCache.get(attr_name)
643
+ elm.attributes.sub!(@pattern, "")
644
+ end
645
+ end
646
+
647
+ private :remove_attrs_
648
+
649
+ def escape(content)
650
+ # 特殊文字の置換
651
+ content = content.gsub(@@pattern_escape, TABLE_FOR_ESCAPE_)
652
+
653
+ content
654
+ end
655
+
656
+ def escape_content(content, elm)
657
+ # 特殊文字の置換
658
+ content = content.gsub(@@pattern_escape_content, TABLE_FOR_ESCAPE_CONTENT_)
659
+
660
+ content
661
+ end
662
+
663
+ private :escape
664
+ private :escape_content
665
+
666
+ def unescape(content)
667
+ # replace special character (特殊文字の置換)
668
+ # 「<」<-「&lt;」
669
+ # 「>」<-「&gt;」
670
+ # 「"」<-「&quotl」
671
+ # 「 」<-「&nbsp;」
672
+ # 「&」<-「&amp;」
673
+ content.gsub(@@pattern_unescape) do
674
+ case $1
675
+ when "amp"
676
+ "&"
677
+ when "quot"
678
+ "\""
679
+ when "apos"
680
+ "'"
681
+ when "gt"
682
+ ">"
683
+ when "lt"
684
+ "<"
685
+ when "nbsp"
686
+ " "
687
+ end
688
+ end
689
+
690
+ content
691
+ end
692
+
693
+ private :unescape
694
+
695
+ def unescape_content(content, elm)
696
+ content_ = unescape(content)
697
+
698
+ if elm.cx || !is_match(@@match_tag_2, elm.name)
699
+ if content.include?(BR)
700
+ # 「<br>」->「¥r?¥n」
701
+ content_.gsub!(@@pattern_br_2, @root.kaigyo_code)
702
+ end
703
+ end
704
+
705
+ content_
706
+ end
707
+
708
+ private :unescape_content
709
+ end
710
+ end
711
+ end
712
+ end