meteor 0.9.18 → 0.9.20

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea632b32536a814320a44110909a51a869dc09a9546d55307c8ca6e22e1e12ec
4
- data.tar.gz: 2e5be17d0c3654208400db5731f389cb67fe9b616c1004965f820757c8d9a03b
3
+ metadata.gz: 634ddb57832e251c0d8dfeb25a124c0c92046f296fb31c8cb4c375ecf841ee27
4
+ data.tar.gz: 7f553a1b7ac314cca77e92fd45d1f541636590aebead0a687058ee450efed8de
5
5
  SHA512:
6
- metadata.gz: 573c2429e3de96abd5551c92cbd14ebf15ebf5b87a9edf86559c3905d1701dc9a094ab86c2a72af52ab1ff17f367c57832560df2a53e9a4a5e15166113cebe13
7
- data.tar.gz: 32874256cd55783e984614448088ecc8abd05fbc638cd718ca2e9a8114a453dec708f3f03dfd915f4157142a266f76ab88ff9a0f9c4bf37b8c2da021e8065965
6
+ metadata.gz: 44091d7eb8d9bf3abea743b3543b60cc0f705f470927a0386c4598779268ecad39cee285ff856d117cbf4cdff5f48e945609c0ee2afa6828c7e6be6026ea740f
7
+ data.tar.gz: ede1106a3c620bd3a6031637f3acfc8d5a3c7e86bae7b85e75324bf36ce539a0fff939135b9857ebdb7b8fb8cd422b0c0383d7f38b28aec55a3d085b8b81d8cd
data/ChangeLog CHANGED
@@ -1,4 +1,12 @@
1
- 0.9.18 / 2026-06-20 Yasumasa Ashida <ys.ashida@gmail.com>
1
+ == 0.9.20 / 2026-06-20 Yasumasa Ashida <ys.ashida@gmail.com>
2
+
3
+ * Refactoring
4
+
5
+ == 0.9.19 / 2026-06-20 Yasumasa Ashida <ys.ashida@gmail.com>
6
+
7
+ * Refactoring
8
+
9
+ == 0.9.18 / 2026-06-20 Yasumasa Ashida <ys.ashida@gmail.com>
2
10
 
3
11
  * Fixnum → Integer
4
12
  * Refactoring
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- meteor (0.9.17)
4
+ meteor (0.9.20)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -278,13 +278,13 @@ module Meteor
278
278
  # @return [Meteor::Element] element(要素)
279
279
  #
280
280
  def element_1(name)
281
- @_name = Regexp.quote(name)
281
+ quote_name(name)
282
282
 
283
283
  # element search pattern (要素検索用パターン)
284
284
  @pattern_cc = "<#{@_name}(|\\s[^<>]*)\\/>|<#{@_name}((?:|\\s[^<>]*))>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
285
285
 
286
286
  @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
287
- # search of element with content (内容あり要素検索)
287
+ # search of content-rich element (内容あり要素検索)
288
288
  @res = @pattern.match(@root.document)
289
289
 
290
290
  if @res
@@ -323,7 +323,7 @@ module Meteor
323
323
  # document (全体)
324
324
  @elm_.document = @res[0]
325
325
  end
326
- # search pattern of element with content (内容あり要素検索用パターン)
326
+ # search pattern of content-rich element (内容あり要素検索用パターン)
327
327
  # @pattern_cc = String.new('') << "<" << @_name << '(?:|\\s[^<>]*)>((?!(' << @_name
328
328
  # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
329
329
  @pattern_cc = "<#{@_name}(|\\s[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
@@ -469,7 +469,7 @@ module Meteor
469
469
  @elm_.mixed_content = @res[3]
470
470
  # document (全体)
471
471
  @elm_.document = @res[0]
472
- # search pattern of element with content (内容あり要素検索用パターン)
472
+ # search pattern of content-rich element (内容あり要素検索用パターン)
473
473
  # @pattern_cc = String.new('')<< "<" << @_name << '\\s[^<>]*' << @_attr_name << '="'
474
474
  # @pattern_cc << @_attr_value << '"[^<>]*>((?!(' << @_name
475
475
  # @pattern_cc << '[^<>]*>)).)*<\\/' << @_name << '>'
@@ -497,7 +497,7 @@ module Meteor
497
497
  end
498
498
  # document (全体)
499
499
  @elm_.document = @res[0]
500
- # search pattern of element with content (内容あり要素検索用パターン)
500
+ # search pattern of content-rich element (内容あり要素検索用パターン)
501
501
  @elm_.pattern = @pattern_cc
502
502
 
503
503
  @elm_.empty = true
@@ -544,7 +544,7 @@ module Meteor
544
544
  @pattern_cc_2_2 = String.new("") << ".*?)<\\/" << @_name << ">"
545
545
  # @pattern_cc_2_2 = ".*?)<\\/#{@_name}>"
546
546
 
547
- # search of element with content (内容あり要素検索)
547
+ # search of content-rich element (内容あり要素検索)
548
548
  @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
549
549
 
550
550
  @sbuf = String.new("")
@@ -753,7 +753,7 @@ module Meteor
753
753
  # @pattern_cc_1 << @_attr_value << '(?:[^<>\\/]*>|(?:(?!([^<>]*\\/>))[^<>]*>)))'
754
754
  @pattern_cc_1 = "<([^<>\"]*)(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}(?:[^<>\\/]*>|(?:(?!([^<>]*\\/>))[^<>]*>)))"
755
755
 
756
- # search of element with content (内容あり要素検索)
756
+ # search of content-rich element (内容あり要素検索)
757
757
  @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
758
758
  @sbuf = String.new('')
759
759
 
@@ -877,7 +877,7 @@ module Meteor
877
877
  private :element_5
878
878
 
879
879
  def quote_element_5(name, attr_name1, attr_value1, attr_name2, attr_value2)
880
- @_name = Regexp.quote(name)
880
+ quote_name(name)
881
881
  @_attr_name1 = Regexp.quote(attr_name1)
882
882
  @_attr_name2 = Regexp.quote(attr_name2)
883
883
  @_attr_value1 = Regexp.quote(attr_value1)
@@ -942,7 +942,7 @@ module Meteor
942
942
  @elm_.mixed_content = @res[3]
943
943
  # document (全体)
944
944
  @elm_.document = @res[0]
945
- # search pattern of element with content (要素ありタグ検索用パターン)
945
+ # search pattern of content-rich element (要素ありタグ検索用パターン)
946
946
  @elm_.pattern = @pattern_cc
947
947
 
948
948
  @elm_.empty = true
@@ -996,7 +996,7 @@ module Meteor
996
996
  # @pattern_cc_2_1 = ".*?<\\/#{@_name}>"
997
997
  # @pattern_cc_2_2 = ".*?)<\\/#{@_name}>"
998
998
 
999
- # search of element with content (内容あり要素検索)
999
+ # search of content-rich element (内容あり要素検索)
1000
1000
  @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
1001
1001
 
1002
1002
  @sbuf = String.new("")
@@ -1895,10 +1895,10 @@ module Meteor
1895
1895
  # @return [Meteor::Element] element (要素)
1896
1896
  #
1897
1897
  def cxtag_2(name, id)
1898
- @_name = Regexp.quote(name)
1898
+ quote_name(name)
1899
1899
  @_id = Regexp.quote(id)
1900
1900
 
1901
- # CX tag search pattern (CXタグ検索用パターン)
1901
+ # CX tag search pattern (CXタグ検索用パターン)
1902
1902
  # @pattern_cc = String.new('') << "<!--\\s@" << @_name << '\\s([^<>]*id="'
1903
1903
  # @pattern_cc << id << '"[^<>]*)-->(((?!(<!--\\s/@' << @_name << ")).)*)<!--\\s/@" << @_name << "\\s-->"
1904
1904
  # @pattern_cc = "<!--\\s@#{tag}\\s([^<>]*id=\"#{id}\"[^<>]*)-->(((?!(<!--\\s\\/@#{tag})).)*)<!--\\s\\/@#{tag}\\s-->"
@@ -2094,7 +2094,7 @@ module Meteor
2094
2094
  #
2095
2095
  def shadow(elm)
2096
2096
  if elm.empty
2097
- # case of element with content (内容あり要素の場合)
2097
+ # case of content-rich element (内容あり要素の場合)
2098
2098
  set_mono_info(elm)
2099
2099
 
2100
2100
  pif2 = create(self)
@@ -15,8 +15,8 @@ module Meteor
15
15
  # @option @deprecated opts [String] :base_dir root directory (基準ディレクトリ)
16
16
  # @option opts [String] :enc default character encoding (デフォルト文字エンコーディング)
17
17
  # @option @deprecated opts [String] :base_enc default character encoding (デフォルト文字エンコーディング)
18
- # @option opts [FixNum,Symbol] :type default type of parser (デフォルトのパーサ・タイプ)
19
- # @option @deprecated opts [FixNum | Symbol] :base_type default type of parser (デフォルトのパーサ・タイプ)
18
+ # @option opts [Integer,Symbol] :type default type of parser (デフォルトのパーサ・タイプ)
19
+ # @option @deprecated opts [Integer | Symbol] :base_type default type of parser (デフォルトのパーサ・タイプ)
20
20
  #
21
21
  def self.options=(opts)
22
22
  @@pf.options = opts
@@ -33,7 +33,7 @@ module Meteor
33
33
  ]
34
34
 
35
35
  #[Array] boolean attributes (論理値で指定する属性)
36
- ATTR_LOGIC = ["disabled", "readonly", "checked", "selected", "multiple", "required"]
36
+ ATTR_BOOL = ["disabled", "readonly", "checked", "selected", "multiple", "required"]
37
37
 
38
38
  #[Array] elements with the disabled attribute (disabled属性のある要素)
39
39
  DISABLE_ELEMENT = ["input", "textarea", "select", "optgroup", "fieldset"]
@@ -58,7 +58,7 @@ module Meteor
58
58
  super()
59
59
  @@match_tag = MATCH_TAG
60
60
  @@MATCH_TAG_NNE = MATCH_TAG_NNE
61
- @@attr_logic = ATTR_LOGIC
61
+ @@attr_bool = ATTR_BOOL
62
62
  @doc_type = Parser::HTML
63
63
  case args.length
64
64
  when ZERO
@@ -21,10 +21,10 @@ module Meteor
21
21
  @@match_tag_2 = ["textarea", "option", "pre"]
22
22
 
23
23
  #[Array] non-nestable elements (入れ子にできない要素)
24
- @@match_tag_sng = ["texarea", "select", "option", "form", "fieldset"]
24
+ @@match_tag_nne = ["texarea", "select", "option", "form", "fieldset"]
25
25
 
26
- #[Array] boolean elements (論理値で指定する属性)
27
- @@attr_logic = ["disabled", "readonly", "checked", "selected", "multiple"]
26
+ #[Array] boolean attributes (論理値で指定する属性)
27
+ @@attr_bool = ["disabled", "readonly", "checked", "selected", "multiple"]
28
28
 
29
29
  # DISABLE_ELEMENT = "input|textarea|select|optgroup"
30
30
  #[Array] elements with the disabled attribute (disabled属性のある要素)
@@ -234,15 +234,15 @@ module Meteor
234
234
  @elm_ = nil
235
235
  end
236
236
  else
237
- # search pattern of element with content (内容あり要素検索用パターン()
237
+ # search pattern of content-rich element (内容あり要素検索用パターン()
238
238
  # @pattern_cc = String.new('') << "<" << @_name << '(|\\s[^<>]*)>(((?!(' << @_name
239
239
  # @pattern_cc << '[^<>]*>)).)*)<\\/' << @_name << '>'
240
240
  @pattern_cc = "<#{@_name}(|\\s[^<>]*)>(((?!(#{tag}[^<>]*>)).)*)<\\/#{@_name}>"
241
241
 
242
242
  @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
243
- # search of element with content (内容あり要素検索)
243
+ # search of content-rich element (内容あり要素検索)
244
244
  @res = @pattern.match(@root.document)
245
- # case of element with content (内容あり要素の場合)
245
+ # case of content-rich element (内容あり要素の場合)
246
246
  if @res
247
247
  element_with_1(name)
248
248
  else
@@ -308,17 +308,17 @@ module Meteor
308
308
  @elm_ = nil
309
309
  end
310
310
  else
311
- # search pattern of element with content (内容あり要素検索パターン)
311
+ # search pattern of content-rich element (内容あり要素検索パターン)
312
312
  # @pattern_cc = String.new('') << "<" << @_name << '(\\s[^<>]*' << @_attr_name << '="'
313
313
  # @pattern_cc << @_attr_value << '"[^<>]*)>(((?!(' << @_name
314
314
  # @pattern_cc << '[^<>]*>)).)*)<\\/' << @_name << '>'
315
315
  @pattern_cc = "<#{@_name}(\\s[^<>]*#{@_attr_name}=\"#{@_attr_value}\"[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
316
316
 
317
317
  @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
318
- # search of element with content (内容あり要素検索)
318
+ # search of content-rich element (内容あり要素検索)
319
319
  @res = @pattern.match(@root.document)
320
320
 
321
- if !@res && !is_match(@@match_tag_sng, name)
321
+ if !@res && !is_match(@@match_tag_nne, name)
322
322
  @res = element_with_3_2
323
323
  end
324
324
 
@@ -415,7 +415,7 @@ module Meteor
415
415
  @elm_ = nil
416
416
  end
417
417
  else
418
- # search pattern of element with content (内容あり要素検索パターン)
418
+ # search pattern of content-rich element (内容あり要素検索パターン)
419
419
  # @pattern_cc = String.new('') << "<" << @_name << '(\\s[^<>]*(?:' << @_attr_name1 << '="'
420
420
  # @pattern_cc << @_attr_value1 << '"[^<>]*' << @_attr_name2 << '="'
421
421
  # @pattern_cc << @_attr_value2 << '"|' << @_attr_name2 << '="'
@@ -425,10 +425,10 @@ module Meteor
425
425
  @pattern_cc = "<#{@_name}(\\s[^<>]*(?:#{@_attr_name1}=\"#{@_attr_value1}\"[^<>]*#{@_attr_name2}=\"#{@_attr_value2}\"|#{@_attr_name2}=\"#{@_attr_value2}\"[^<>]*#{@_attr_name1}=\"#{@_attr_value1}\")[^<>]*)>(((?!(#{@_name}[^<>]*>)).)*)<\\/#{@_name}>"
426
426
 
427
427
  @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
428
- # search of element with content (内容あり要素検索)
428
+ # search of content-rich element (内容あり要素検索)
429
429
  @res = @pattern.match(@root.document)
430
430
 
431
- if !@res && !is_match(@@match_tag_sng, tag)
431
+ if !@res && !is_match(@@match_tag_nne, tag)
432
432
  @res = element_with_5_2
433
433
  end
434
434
 
@@ -633,7 +633,7 @@ module Meteor
633
633
  private :get_attr_map
634
634
 
635
635
  def remove_attrs_(elm, attr_name)
636
- if !is_match(@@attr_logic, attr_name)
636
+ if !is_match(@@attr_bool, attr_name)
637
637
  # attribute search pattern (属性検索用パターン)
638
638
  @pattern = Meteor::Core::Util::PatternCache.get(String.new("") << attr_name << "=\"[^\"]*\"\\s?")
639
639
  # @pattern = Meteor::Core::Util::PatternCache.get("#{attr_name}=\"[^\"]*\"\\s?")
@@ -693,15 +693,19 @@ module Meteor
693
693
 
694
694
  private :unescape
695
695
 
696
+ def br_to_kaigyo(content)
697
+ if (elm.cx || !is_match(@@match_tag_2, elm.name)) && content.include?(BR)
698
+ # 「<br>」->「¥r?¥n」
699
+ content.gsub!(@@pattern_br_2, @root.kaigyo_code)
700
+ end
701
+ end
702
+
703
+ private :br_to_kaigyo
704
+
696
705
  def unescape_content(content, elm)
697
706
  content_ = unescape(content)
698
707
 
699
- if elm.cx || !is_match(@@match_tag_2, elm.name)
700
- if content.include?(BR)
701
- # 「<br>」->「¥r?¥n」
702
- content_.gsub!(@@pattern_br_2, @root.kaigyo_code)
703
- end
704
- end
708
+ br_to_kaigyo(content_)
705
709
 
706
710
  content_
707
711
  end
@@ -8,13 +8,13 @@ module Meteor
8
8
  # XHTML parser (XHTMLパーサ)
9
9
  #
10
10
  class ParserImpl < Meteor::Ml::Xhtml4::ParserImpl
11
- #[Array] 論理値で指定する属性
12
- ATTR_LOGIC = ["disabled", "readonly", "checked", "selected", "multiple", "required"]
11
+ #[Array] boolean attributes (論理値で指定する属性)
12
+ ATTR_BOOL = ["disabled", "readonly", "checked", "selected", "multiple", "required"]
13
13
 
14
- #[Array] disabled属性のある要素
14
+ #[Array] elements with the disabled attribute (disabled属性のある要素)
15
15
  DISABLE_ELEMENT = ["input", "textarea", "select", "optgroup", "fieldset"]
16
16
 
17
- #[Array] required属性のある要素
17
+ #[Array] elements with a readonly attribute (required属性のある要素)
18
18
  REQUIRE_ELEMENT = ["input", "textarea"]
19
19
 
20
20
  REQUIRED_M = "\\srequired=\"[^\"]*\"\\s|\\srequired=\"[^\"]*\"$"
@@ -34,7 +34,7 @@ module Meteor
34
34
  #
35
35
  def initialize(*args)
36
36
  super()
37
- @@attr_logic = ATTR_LOGIC
37
+ @@attr_bool = ATTR_BOOL
38
38
  @doc_type = Parser::XHTML
39
39
  case args.length
40
40
  when ZERO
@@ -17,14 +17,14 @@ module Meteor
17
17
  #[Array] 改行を<br/>に変換する必要のない要素
18
18
  @@match_tag_2 = ["textarea", "option", "pre"]
19
19
 
20
- #[Array] 論理値で指定する属性
21
- @@attr_logic = ["disabled", "readonly", "checked", "selected", "multiple"]
20
+ #[Array] boolean attributes (論理値で指定する属性)
21
+ @@attr_bool = ["disabled", "readonly", "checked", "selected", "multiple"]
22
22
 
23
23
  # DISABLE_ELEMENT = "input|textarea|select|optgroup"
24
24
  #[Array] element with disablled attribute (disabled属性のある要素)
25
25
  DISABLE_ELEMENT = ["input", "textarea", "select", "optgroup"]
26
26
  # READONLY_TYPE = "text|password"
27
- #[Array] readonly属性のあるinput要素のタイプ
27
+ #[Array] the type of an input element with a readonly attribute (readonly属性のあるinput要素のタイプ)
28
28
  READONLY_TYPE = ["text", "password"]
29
29
 
30
30
  SELECTED_M = "\\sselected=\"[^\"]*\"\\s|\\sselected=\"[^\"]*\"$"
@@ -326,7 +326,7 @@ module Meteor
326
326
  attrs = Meteor::AttributeMap.new
327
327
 
328
328
  elm.attributes.scan(@@pattern_get_attrs_map) do |a, b|
329
- if is_match(@@attr_logic, a) && a == b
329
+ if is_match(@@attr_bool, a) && a == b
330
330
  attrs.store(a, "true")
331
331
  else
332
332
  attrs.store(a, unescape(b))
@@ -386,13 +386,17 @@ module Meteor
386
386
 
387
387
  private :unescape
388
388
 
389
- def unescape_content(content, elm)
390
- content_ = unescape(content)
391
-
389
+ def br_to_kaigyo(content)
392
390
  if (elm.cx || !is_match(@@match_tag_2, elm.name)) && content.include?(BR)
393
391
  # 「<br>」->「¥r?¥n」
394
- content_.gsub!(@@pattern_br_2, @root.kaigyo_code)
392
+ content.gsub!(@@pattern_br_2, @root.kaigyo_code)
395
393
  end
394
+ end
395
+
396
+ def unescape_content(content, elm)
397
+ content_ = unescape(content)
398
+
399
+ br_to_kaigyo(content_)
396
400
 
397
401
  content_
398
402
  end
@@ -6,7 +6,7 @@ module Meteor
6
6
  # Parser Factory Class (パーサ・ファクトリ クラス)
7
7
  #
8
8
  # @!attribute [rw] type
9
- # @return [FixNum,Symbol] default type of parser (デフォルトのパーサ・タイプ)
9
+ # @return [Integer,Symbol] default type of parser (デフォルトのパーサ・タイプ)
10
10
  # @!attribute [rw] root
11
11
  # @return [String] root root directory (基準ディレクトリ)
12
12
  # @!attribute [rw] enc
@@ -36,7 +36,7 @@ module Meteor
36
36
  # @param [String] root root directory (基準ディレクトリ)
37
37
  # @param [String] enc default character encoding (デフォルトエンコーディング)
38
38
  # @overload initialize(type, root, enc)
39
- # @param [FixNum,Symbol] type default type of parser (デフォルトのパーサ・タイプ)
39
+ # @param [Integer,Symbol] type default type of parser (デフォルトのパーサ・タイプ)
40
40
  # @param [String] root root directory (基準ディレクトリ)
41
41
  # @param [String] enc default character encoding (デフォルト文字エンコーディング)
42
42
  #
@@ -89,7 +89,7 @@ module Meteor
89
89
 
90
90
  #
91
91
  # イニシャライザ
92
- # @param [FixNum,Symbol] type default type of parser (デフォルトのパーサ・タイプ)
92
+ # @param [Integer,Symbol] type default type of parser (デフォルトのパーサ・タイプ)
93
93
  # @param [String] root root directory (基準ディレクトリ)
94
94
  # @param [String] enc default character encoding (デフォルト文字エンコーディング)
95
95
  #
@@ -109,8 +109,8 @@ module Meteor
109
109
  # @option @deprecated opts [String] :base_dir root directory (基準ディレクトリ)
110
110
  # @option opts [String] :enc default character encoding (デフォルト文字エンコーディング)
111
111
  # @option @deprecated opts [String] :base_enc default character encoding (デフォルト文字エンコーディング)
112
- # @option opts [FixNum,Symbol] :type default type of parser (デフォルトのパーサ・タイプ)
113
- # @option @deprecated opts [FixNum | Symbol] :base_type default type of parser (デフォルトのパーサ・タイプ)
112
+ # @option opts [Integer,Symbol] :type default type of parser (デフォルトのパーサ・タイプ)
113
+ # @option @deprecated opts [Integer | Symbol] :base_type default type of parser (デフォルトのパーサ・タイプ)
114
114
  #
115
115
  def options=(opts)
116
116
  if opts.kind_of?(Hash)
data/lib/meteor.rb CHANGED
@@ -36,11 +36,11 @@ require "meteor/ml/xml/parser_impl"
36
36
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37
37
  #
38
38
  # @author Yasumasa Ashida
39
- # @version 0.9.18
39
+ # @version 0.9.20
40
40
  #
41
41
 
42
42
  module Meteor
43
- VERSION = "0.9.18"
43
+ VERSION = "0.9.20"
44
44
 
45
45
  # require 'fileutils'
46
46
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meteor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.18
4
+ version: 0.9.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yasumasa Ashida