ymaps 0.0.2 → 0.0.3

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.
@@ -1,6 +1,8 @@
1
- = ymaps
1
+ = YMaps
2
2
 
3
- Description goes here.
3
+ Helpers for using Yandex Maps service.
4
+
5
+ It includes Geokit-based Geocoder and helper for generating YMapsML files with data for Yandex Maps.
4
6
 
5
7
  == Note on Patches/Pull Requests
6
8
 
@@ -12,6 +14,4 @@ Description goes here.
12
14
  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
15
  * Send me a pull request. Bonus points for topic branches.
14
16
 
15
- == Copyright
16
-
17
- Copyright (c) 2010 Alexander Semyonov. See LICENSE for details.
17
+ © Alexander Semyonov, 2010. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -1,13 +1,48 @@
1
1
  require 'geokit'
2
+ require 'geokit/inflector'
2
3
  require 'geokit/geocoders'
3
4
 
4
5
  module Geokit
5
6
  self.default_units = :kms
6
7
 
7
8
  class LatLng
8
- def pos
9
+ def gml_pos
9
10
  "#{lng} #{lat}"
10
11
  end
12
+
13
+ def ymaps_lnglat
14
+ "#{lng},#{lat}"
15
+ end
16
+
17
+ def ymaps_lnglat=(lnglat)
18
+ self.lng, self.lat = lnglat[0], lnglat[1]
19
+ end
20
+ end
21
+
22
+ class GeoLoc
23
+ attr_accessor :kind
24
+ attr_writer :street_number, :street_name
25
+
26
+ # Extracts the street number from the street address if the street address
27
+ # has a value.
28
+ def street_number
29
+ @street_number ||= street_address && street_address[/(\d*)/]
30
+ end
31
+
32
+ # Returns the street name portion of the street address.
33
+ def street_name
34
+ @street_name ||= street_address && street_address[street_number.length, street_address.length].strip
35
+ end
36
+
37
+ # Do not use ugly Geokit::Inflector::titleize when set city’s name
38
+ def city=(city)
39
+ @city = city
40
+ end
41
+
42
+ # Do not use ugly Geokit::Inflector::titleize when set street address
43
+ def street_address=(address)
44
+ @street_address = address
45
+ end
11
46
  end
12
47
 
13
48
  module Geocoders
@@ -20,6 +55,23 @@ module Geokit
20
55
  end
21
56
 
22
57
  class YandexGeocoder < Geocoder
58
+ KIND_ACCURACY_MAP = {
59
+ 'country' => 1,
60
+ 'province' => 2,
61
+ 'area' => 3,
62
+ # 5 postal code
63
+ 'locality' => 4,
64
+ 'street' => 6,
65
+ 'route' => 6,
66
+ # 7 kreuzung
67
+ 'house' => 8,
68
+ 'metro' => 8,
69
+ 'railway' => 8,
70
+ # 9 building
71
+ # district hydro vegetation cemetery bridge km other
72
+ # 0 #unknown
73
+ }
74
+ PRECISIONS = %w{unknown country state state city zip zip+4 street address building}
23
75
 
24
76
  private
25
77
  def self.call_geocoder_service(geocode)
@@ -30,18 +82,18 @@ module Geokit
30
82
  end
31
83
 
32
84
  xml = res.body
33
- logger.debug "Yandex geocoding: '#{geocode}'. Result: #{xml}"
85
+ logger.debug("Yandex geocoding: '#{geocode}'. Result: #{xml}")
34
86
  return xml2GeoLoc(xml)
35
87
  end
36
88
 
37
89
  def self.do_reverse_geocode(latlng)
38
90
  latlng = LatLng.normalize(latlng)
39
- call_geocoder_service(latlng.ll)
91
+ call_geocoder_service(latlng.ymaps_lnglat) || GeoLoc.new
40
92
  end
41
93
 
42
94
  def self.do_geocode(address, options = {})
43
95
  address_str = address.is_a?(GeoLoc) ? address.to_geocodable_s : address
44
- call_geocoder_service(address_str)
96
+ call_geocoder_service(address_str) || GeoLoc.new
45
97
  end
46
98
 
47
99
  def self.xml2GeoLoc(xml, address="")
@@ -63,7 +115,7 @@ module Geokit
63
115
 
64
116
  return geoloc
65
117
  else
66
- logger.ingo "Yandex was unable to geocode address: #{address}"
118
+ logger.info("Yandex was unable to geocode address: #{address}")
67
119
  return GeoLoc.new
68
120
  end
69
121
  end
@@ -73,21 +125,22 @@ module Geokit
73
125
  res.provider = 'yandex'
74
126
 
75
127
  # basics
76
- coordinates = doc.elements['.//Point/pos'].text.to_s.split(' ')
77
- res.lng = coordinates[0]
78
- res.lat = coordinates[1]
128
+ res.ymaps_lnglat = doc.elements['.//Point/pos'].text.to_s.split(' ')
79
129
 
80
130
  # extended -- false if not available
81
- res.city = doc.elements['.//LocalityName'].try(:text)
82
- res.state = doc.elements['.//AdministrativeAreaName'].try(:text)
83
- res.province = doc.elements['.//SubAdministrativeAreaName'].try(:text)
84
- res.full_address = doc.elements['.//GeocoderMetaData/text'].try(:text)
85
- res.zip = doc.elements['.//PostalCodeNumber'].try(:text)
86
- res.street_address = doc.elements['.//ThoroughfareName'].try(:text)
87
- res.country = doc.elements['.//CountryName'].try(:text)
88
- res.district = doc.elements['.//DependentLocalityName'].try(:text)
89
-
90
- # TODO: translate accuracy into Yahoo-style token address, street, zip, zip+4, city, state, country
131
+ res.full_address = doc.elements['.//GeocoderMetaData/text'].try(:text)
132
+ res.country = doc.elements['.//CountryName'].try(:text)
133
+ res.state = doc.elements['.//AdministrativeAreaName'].try(:text)
134
+ res.province = doc.elements['.//SubAdministrativeAreaName'].try(:text)
135
+ res.city = doc.elements['.//LocalityName'].try(:text)
136
+ res.district = doc.elements['.//DependentLocalityName'].try(:text)
137
+ res.street_name = doc.elements['.//ThoroughfareName'].try(:text)
138
+ res.street_number = doc.elements['.//PremiseNumber'].try(:text)
139
+ res.zip = doc.elements['.//PostalCodeNumber'].try(:text)
140
+
141
+ res.kind = doc.elements['.//GeocoderMetaData/kind'].try(:text)
142
+ res.accuracy = KIND_ACCURACY_MAP.fetch(res.kind) { 0 } if res.kind.present?
143
+ res.precision = PRECISIONS[res.accuracy]
91
144
 
92
145
  if suggested_bounds = doc.elements['.//boundedBy']
93
146
  res.suggested_bounds = Bounds.normalize(
@@ -97,7 +150,6 @@ module Geokit
97
150
  end
98
151
 
99
152
  res.success = true
100
-
101
153
  res
102
154
  end
103
155
  end
@@ -0,0 +1,22 @@
1
+ require 'geokit/geocoders'
2
+
3
+ module Geokit
4
+ module Inflector
5
+ if ''.respond_to?(:bytesize) # Ruby 1.9
6
+ def bytesize(string)
7
+ string.bytesize
8
+ end
9
+ else # Ruby 1.8
10
+ def bytesize(string)
11
+ string.size
12
+ end
13
+ end
14
+ module_function :bytesize
15
+
16
+ def url_escape(s)
17
+ s.gsub(/([^ a-zA-Z0-9_.-]+)/nu) {
18
+ '%' + $1.unpack('H2' * bytesize($1)).join('%').upcase
19
+ }.tr(' ', '+')
20
+ end
21
+ end
22
+ end
@@ -6,6 +6,14 @@ module YMaps
6
6
 
7
7
  def self.geocode(query)
8
8
  require 'geokit/geocoders/yandex_geocoder'
9
- Geokit::Geocoders::Yandex.geocode(query)
9
+ Geokit::Geocoders::YandexGeocoder.geocode(query)
10
10
  end
11
11
  end
12
+
13
+ if defined? ActionView
14
+ ActionView::Base.send(:include, YMaps::ActionView::Helpers)
15
+ end
16
+
17
+ if defined? Mime
18
+ Mime::Type.register 'application/xml', :ymapsml
19
+ end
@@ -3,15 +3,15 @@ module YMaps
3
3
  module HtmlHelper
4
4
  class StaticMapPoint < Struct.new('MapPoint', :style, :color, :size, :number, :lat, :lng)
5
5
  def to_s
6
- "#{ll},#{style}#{color}#{size}#{number}"
6
+ "#{ymaps_lnglat},#{style}#{color}#{size}#{number}"
7
7
  end
8
8
 
9
- def ll
10
- @ll ||= "#{lat},#{lng}"
9
+ def ymaps_lnglat
10
+ @ymaps_lnglat ||= "#{lng},#{lat}"
11
11
  end
12
12
 
13
- def ll=(latlng)
14
- @ll = latlng
13
+ def ymaps_lnglat=(latlng)
14
+ @ymaps_lnglat = latlng
15
15
  end
16
16
 
17
17
  def attributes=(attrs)
@@ -24,10 +24,13 @@ module YMaps
24
24
  def map_link(resource = nil, options = {})
25
25
  resource, options = nil, resource if resource.is_a?(Hash)
26
26
 
27
+ url_params = options.delete(:url) { {} }
27
28
  href = if resource
28
- polymorphic_url(resource, :format => :ymapsml)
29
+ polymorphic_url(resource, {:format => :ymapsml}.merge(url_params))
29
30
  else
30
- url_for(:format => :ymapsml, :only_path => false, :time => Time.now)
31
+ url_for({:format => :ymapsml,
32
+ :only_path => false,
33
+ :time => Time.now}.merge(url_params))
31
34
  end
32
35
 
33
36
  tag(:link,
@@ -37,14 +40,22 @@ module YMaps
37
40
  :type => 'application/ymapsml+xml'))
38
41
  end
39
42
 
40
- def ymaps_include_tag(key = nil)
43
+ def ymaps_javascript_path(key = nil)
41
44
  key ||= YMaps.key
42
- javascript_include_tag("http://api-maps.yandex.ru/1.1/index.xml?key=#{key}")
45
+ "http://api-maps.yandex.ru/1.1/index.xml?key=#{key}"
46
+ end
47
+
48
+ def ymaps_include_tag(key = nil)
49
+ javascript_include_tag(ymaps_javascript_path)
43
50
  end
44
51
 
45
52
  def static_map(resources, options = {})
46
53
  title = options.delete(:title) { resources.to_s }
47
54
  map_type = options.delete(:map) { 'map' }
55
+ width = options.delete(:width) { 600 }
56
+ height = options.delete(:height) { 450 }
57
+ map_size = "#{width},#{height}"
58
+ zoom = options.delete(:zoom) { 16 }
48
59
 
49
60
  common_point = StaticMapPoint.new(
50
61
  options.delete(:style) { 'pm' },
@@ -54,18 +65,20 @@ module YMaps
54
65
  )
55
66
 
56
67
  collection = Array(resources).inject([]) do |result, resource|
57
- common_point.ll = resource.latlng.ll
68
+ common_point.ymaps_lnglat = resource.latlng.ymaps_lnglat
58
69
  common_point.number += 1
59
70
  result << common_point.to_s
60
71
  result
61
72
  end.join('~')
62
73
 
63
74
  content_tag(:div, :class => 'b-map') do
64
- image_tag("http://static-maps.yandex.ru/1.x/?key=#{YMaps.key}&l=#{map_type}&pt=#{collection}",
65
- :title => title,
66
- :alt => title,
67
- :class => 'static'
68
- )
75
+ image_tag("http://static-maps.yandex.ru/1.x/?key=#{YMaps.key}&l=#{map_type}&pt=#{collection}&size=#{map_size}&z=#{zoom}", options.merge(
76
+ :title => title,
77
+ :alt => title,
78
+ :class => 'static',
79
+ :width => width,
80
+ :height => height
81
+ ))
69
82
  end
70
83
  end
71
84
 
@@ -28,7 +28,7 @@ module YMaps
28
28
  class Builder
29
29
  YMAPS_TAG_NAMES = %w(GeoObject GeoObjectCollection style ymaps AnyMetaData).map(&:to_sym)
30
30
  GML_TAG_NAMES = %w(boundedBy description Envelope exterior featureMember
31
- featureMembers interior LineString LinearString lowerCorner
31
+ featureMembers interior LineString LinearRing lowerCorner
32
32
  metaDataProperty name Point Polygon pos posList upperCorner).map(&:to_sym)
33
33
  REPR_TAG_NAMES = %w(balloonContentStyle fill fillColor hintContentStyle iconContentStyle
34
34
  lineStyle href iconStyle mapType offset outline parentStyle polygonStyle
@@ -39,9 +39,18 @@ module YMaps
39
39
  @xml = xml
40
40
  end
41
41
 
42
+ protected
43
+ def prefixed_method(method, *arguments, &block)
44
+ @xml.__send__(*xmlns_prefix!(method, arguments), &block)
45
+ end
46
+
47
+ def link_to(name, href)
48
+ prefixed_method(name, "\##{href}")
49
+ end
50
+
42
51
  private
43
52
  def method_missing(method, *arguments, &block)
44
- @xml.__send__(*xmlns_prefix!(method, arguments), &block)
53
+ prefixed_method(method, *arguments, &block)
45
54
  end
46
55
 
47
56
  def xmlns_prefix!(method, arguments)
@@ -56,6 +65,15 @@ module YMaps
56
65
  end
57
66
 
58
67
  class YMapsReprBuilder < Builder
68
+ ACCEPTABLE_STYLES = {
69
+ :balloon_content => [:template],
70
+ :hint_content => [:template],
71
+ :icon => [:href, :offset, :shadow, :size, :template],
72
+ :icon_content => [:template],
73
+ :line => [:stroke_color, :stroke_width],
74
+ :polygon => [:fill, :fill_color, :outline, :stroke_color, :stroke_width],
75
+ }
76
+
59
77
  def view(options = {})
60
78
  View {
61
79
  if options[:type]
@@ -65,12 +83,28 @@ module YMaps
65
83
  }
66
84
  end
67
85
 
86
+ # Add style definition
87
+ # @param [Symbol, String] id style name
88
+ # @param [Hash] options style options
68
89
  def style(id, options = {})
90
+ options[:hasBalloon] = options.delete(:balloon) if options.key?(:balloon)
91
+ options[:hasHint] = options.delete(:hint) if options.key?(:hint)
92
+ parent = options.delete(:parent) { false }
69
93
  Style(options.merge('gml:id' => id.to_s)) {
94
+ link_to(:parentStyle, parent) if parent
70
95
  yield
71
96
  }
72
97
  end
73
98
 
99
+ ACCEPTABLE_STYLES.each do |name, values|
100
+ define_method(name) do |options|
101
+ tag_name = "#{ActiveSupport::Inflector.camelize(name.to_s, false)}Style"
102
+ send(tag_name) do
103
+ style_options(options, values)
104
+ end
105
+ end
106
+ end
107
+
74
108
  def template(id, template_text = nil)
75
109
  Template('gml:id' => id.to_s) do
76
110
  text do
@@ -79,10 +113,42 @@ module YMaps
79
113
  end
80
114
  end
81
115
 
82
- def balloon_content(template)
83
- balloonContentStyle {
84
- @xml.repr(:template, "\##{template}")
85
- }
116
+ protected
117
+
118
+ def style_options(options = {}, acceptable = nil)
119
+ if acceptable
120
+ options.assert_valid_keys(acceptable)
121
+ end
122
+ # Filling options
123
+ fill(options[:fill] ? 1 : 0) if options.key?(:fill)
124
+ fillColor(options[:fill_color]) if options.key?(:fill_color)
125
+
126
+ # Outline options
127
+ outline(options[:outline] ? 1 : 0) if options.key?(:outline)
128
+ strokeColor(options[:stroke_color]) if options.key?(:stroke_color)
129
+ strokeWidth(options[:stroke_width]) if options.key?(:stroke_width)
130
+
131
+ href(options[:href]) if options.key?(:href)
132
+ size(*Array(options[:size])) if options.key?(:size)
133
+ offset(*Array(options[:offset])) if options.key?(:offset)
134
+ link_to(:template, options[:template]) if options.key?(:template)
135
+ shadow do
136
+ style_options(options[:shadow], [:href, :size, :template, :offset])
137
+ end if options.key?(:shadow)
138
+ end
139
+
140
+ def size(x, y = nil)
141
+ if x.is_a?(Hash)
142
+ x, y = x[:x], x[:y]
143
+ end
144
+ prefixed_method(:size, :x => x, :y => y)
145
+ end
146
+
147
+ def offset(x, y = nil)
148
+ if x.is_a?(Hash)
149
+ x, y = x[:x], x[:y]
150
+ end
151
+ prefixed_method(:offset, :x => x, :y => y)
86
152
  end
87
153
  end
88
154
 
@@ -113,7 +179,7 @@ module YMaps
113
179
 
114
180
  def point(latlng)
115
181
  Point {
116
- pos(latlng.pos)
182
+ pos(latlng.gml_pos)
117
183
  }
118
184
  end
119
185
 
@@ -1,53 +1,52 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ymaps}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alexander Semyonov"]
12
- s.date = %q{2010-04-03}
12
+ s.date = %q{2011-01-27}
13
13
  s.description = %q{Different helpers for generating YMapsML, using YMaps widgets and geocoding via Yandex.Maps}
14
14
  s.email = %q{rotuka@rotuka.com}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.rdoc"
17
+ "README.rdoc"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
- ".gitignore",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION",
26
- "init.rb",
27
- "lib/geokit/geocoders/yandex_geocoder.rb",
28
- "lib/ymaps.rb",
29
- "lib/ymaps/action_view.rb",
30
- "lib/ymaps/action_view/html_helper.rb",
31
- "lib/ymaps/action_view/ymapsml_helper.rb",
32
- "test/helper.rb",
33
- "test/test_ymaps.rb",
34
- "ymaps.gemspec"
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "init.rb",
26
+ "lib/geokit/geocoders/yandex_geocoder.rb",
27
+ "lib/geokit/inflector.rb",
28
+ "lib/ymaps.rb",
29
+ "lib/ymaps/action_view.rb",
30
+ "lib/ymaps/action_view/html_helper.rb",
31
+ "lib/ymaps/action_view/ymapsml_helper.rb",
32
+ "test/helper.rb",
33
+ "test/test_ymaps.rb",
34
+ "ymaps.gemspec"
35
35
  ]
36
36
  s.homepage = %q{http://github.com/rotuka/ymaps}
37
- s.rdoc_options = ["--charset=UTF-8"]
38
37
  s.require_paths = ["lib"]
39
- s.rubygems_version = %q{1.3.6}
38
+ s.rubygems_version = %q{1.3.7}
40
39
  s.summary = %q{Helpers for using YMaps}
41
40
  s.test_files = [
42
41
  "test/helper.rb",
43
- "test/test_ymaps.rb"
42
+ "test/test_ymaps.rb"
44
43
  ]
45
44
 
46
45
  if s.respond_to? :specification_version then
47
46
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
47
  s.specification_version = 3
49
48
 
50
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
51
50
  s.add_development_dependency(%q<shoulda>, [">= 0"])
52
51
  s.add_development_dependency(%q<yard>, [">= 0"])
53
52
  s.add_runtime_dependency(%q<geokit>, ["= 1.5.0"])
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Alexander Semyonov
@@ -14,13 +14,14 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-03 00:00:00 +04:00
17
+ date: 2011-01-27 00:00:00 +03:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: shoulda
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
24
25
  requirements:
25
26
  - - ">="
26
27
  - !ruby/object:Gem::Version
@@ -33,6 +34,7 @@ dependencies:
33
34
  name: yard
34
35
  prerelease: false
35
36
  requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
36
38
  requirements:
37
39
  - - ">="
38
40
  - !ruby/object:Gem::Version
@@ -45,6 +47,7 @@ dependencies:
45
47
  name: geokit
46
48
  prerelease: false
47
49
  requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
48
51
  requirements:
49
52
  - - "="
50
53
  - !ruby/object:Gem::Version
@@ -66,13 +69,13 @@ extra_rdoc_files:
66
69
  - README.rdoc
67
70
  files:
68
71
  - .document
69
- - .gitignore
70
72
  - LICENSE
71
73
  - README.rdoc
72
74
  - Rakefile
73
75
  - VERSION
74
76
  - init.rb
75
77
  - lib/geokit/geocoders/yandex_geocoder.rb
78
+ - lib/geokit/inflector.rb
76
79
  - lib/ymaps.rb
77
80
  - lib/ymaps/action_view.rb
78
81
  - lib/ymaps/action_view/html_helper.rb
@@ -85,11 +88,12 @@ homepage: http://github.com/rotuka/ymaps
85
88
  licenses: []
86
89
 
87
90
  post_install_message:
88
- rdoc_options:
89
- - --charset=UTF-8
91
+ rdoc_options: []
92
+
90
93
  require_paths:
91
94
  - lib
92
95
  required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
93
97
  requirements:
94
98
  - - ">="
95
99
  - !ruby/object:Gem::Version
@@ -97,6 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
101
  - 0
98
102
  version: "0"
99
103
  required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
100
105
  requirements:
101
106
  - - ">="
102
107
  - !ruby/object:Gem::Version
@@ -106,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
111
  requirements: []
107
112
 
108
113
  rubyforge_project:
109
- rubygems_version: 1.3.6
114
+ rubygems_version: 1.3.7
110
115
  signing_key:
111
116
  specification_version: 3
112
117
  summary: Helpers for using YMaps
data/.gitignore DELETED
@@ -1,23 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- doc
20
- pkg
21
- .yardoc
22
-
23
- ## PROJECT::SPECIFIC