ftbpro_sitemap_generator 5.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +35 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +1139 -0
  6. data/Rakefile +43 -0
  7. data/VERSION +1 -0
  8. data/lib/capistrano/sitemap_generator.rb +1 -0
  9. data/lib/capistrano/tasks/sitemap_generator.cap +36 -0
  10. data/lib/sitemap_generator.rb +85 -0
  11. data/lib/sitemap_generator/adapters.rb +0 -0
  12. data/lib/sitemap_generator/adapters/file_adapter.rb +43 -0
  13. data/lib/sitemap_generator/adapters/fog_adapter.rb +28 -0
  14. data/lib/sitemap_generator/adapters/s3_adapter.rb +41 -0
  15. data/lib/sitemap_generator/adapters/wave_adapter.rb +21 -0
  16. data/lib/sitemap_generator/application.rb +49 -0
  17. data/lib/sitemap_generator/builder.rb +8 -0
  18. data/lib/sitemap_generator/builder/sitemap_file.rb +172 -0
  19. data/lib/sitemap_generator/builder/sitemap_index_file.rb +149 -0
  20. data/lib/sitemap_generator/builder/sitemap_index_url.rb +28 -0
  21. data/lib/sitemap_generator/builder/sitemap_url.rb +250 -0
  22. data/lib/sitemap_generator/core_ext.rb +3 -0
  23. data/lib/sitemap_generator/core_ext/big_decimal.rb +45 -0
  24. data/lib/sitemap_generator/core_ext/numeric.rb +48 -0
  25. data/lib/sitemap_generator/helpers/number_helper.rb +237 -0
  26. data/lib/sitemap_generator/interpreter.rb +80 -0
  27. data/lib/sitemap_generator/link_set.rb +677 -0
  28. data/lib/sitemap_generator/railtie.rb +7 -0
  29. data/lib/sitemap_generator/sitemap_location.rb +192 -0
  30. data/lib/sitemap_generator/sitemap_namer.rb +75 -0
  31. data/lib/sitemap_generator/tasks.rb +53 -0
  32. data/lib/sitemap_generator/templates.rb +41 -0
  33. data/lib/sitemap_generator/utilities.rb +181 -0
  34. data/lib/tasks/sitemap_generator_tasks.rake +1 -0
  35. data/rails/install.rb +2 -0
  36. data/rails/uninstall.rb +2 -0
  37. data/spec/blueprint.rb +15 -0
  38. data/spec/files/sitemap.create.rb +12 -0
  39. data/spec/files/sitemap.groups.rb +49 -0
  40. data/spec/sitemap_generator/adapters/s3_adapter_spec.rb +23 -0
  41. data/spec/sitemap_generator/alternate_sitemap_spec.rb +79 -0
  42. data/spec/sitemap_generator/application_spec.rb +69 -0
  43. data/spec/sitemap_generator/builder/sitemap_file_spec.rb +110 -0
  44. data/spec/sitemap_generator/builder/sitemap_index_file_spec.rb +124 -0
  45. data/spec/sitemap_generator/builder/sitemap_index_url_spec.rb +28 -0
  46. data/spec/sitemap_generator/builder/sitemap_url_spec.rb +186 -0
  47. data/spec/sitemap_generator/core_ext/bigdecimal_spec.rb +20 -0
  48. data/spec/sitemap_generator/core_ext/numeric_spec.rb +43 -0
  49. data/spec/sitemap_generator/file_adaptor_spec.rb +20 -0
  50. data/spec/sitemap_generator/geo_sitemap_spec.rb +30 -0
  51. data/spec/sitemap_generator/helpers/number_helper_spec.rb +196 -0
  52. data/spec/sitemap_generator/interpreter_spec.rb +90 -0
  53. data/spec/sitemap_generator/link_set_spec.rb +864 -0
  54. data/spec/sitemap_generator/mobile_sitemap_spec.rb +27 -0
  55. data/spec/sitemap_generator/news_sitemap_spec.rb +42 -0
  56. data/spec/sitemap_generator/pagemap_sitemap_spec.rb +57 -0
  57. data/spec/sitemap_generator/sitemap_generator_spec.rb +582 -0
  58. data/spec/sitemap_generator/sitemap_groups_spec.rb +144 -0
  59. data/spec/sitemap_generator/sitemap_location_spec.rb +210 -0
  60. data/spec/sitemap_generator/sitemap_namer_spec.rb +96 -0
  61. data/spec/sitemap_generator/templates_spec.rb +24 -0
  62. data/spec/sitemap_generator/utilities/existence_spec.rb +26 -0
  63. data/spec/sitemap_generator/utilities/hash_spec.rb +57 -0
  64. data/spec/sitemap_generator/utilities/rounding_spec.rb +31 -0
  65. data/spec/sitemap_generator/utilities_spec.rb +101 -0
  66. data/spec/sitemap_generator/video_sitemap_spec.rb +117 -0
  67. data/spec/spec_helper.rb +24 -0
  68. data/spec/support/file_macros.rb +39 -0
  69. data/spec/support/schemas/siteindex.xsd +73 -0
  70. data/spec/support/schemas/sitemap-geo.xsd +41 -0
  71. data/spec/support/schemas/sitemap-mobile.xsd +32 -0
  72. data/spec/support/schemas/sitemap-news.xsd +159 -0
  73. data/spec/support/schemas/sitemap-pagemap.xsd +97 -0
  74. data/spec/support/schemas/sitemap-video.xsd +643 -0
  75. data/spec/support/schemas/sitemap.xsd +115 -0
  76. data/spec/support/xml_macros.rb +67 -0
  77. data/templates/sitemap.rb +27 -0
  78. metadata +226 -0
@@ -0,0 +1,48 @@
1
+ class SitemapGenerator::Numeric
2
+ KILOBYTE = 1024
3
+ MEGABYTE = KILOBYTE * 1024
4
+ GIGABYTE = MEGABYTE * 1024
5
+ TERABYTE = GIGABYTE * 1024
6
+ PETABYTE = TERABYTE * 1024
7
+ EXABYTE = PETABYTE * 1024
8
+
9
+ def initialize(number)
10
+ @number = number
11
+ end
12
+
13
+ # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes
14
+ def bytes
15
+ @number
16
+ end
17
+ alias :byte :bytes
18
+
19
+ def kilobytes
20
+ @number * KILOBYTE
21
+ end
22
+ alias :kilobyte :kilobytes
23
+
24
+ def megabytes
25
+ @number * MEGABYTE
26
+ end
27
+ alias :megabyte :megabytes
28
+
29
+ def gigabytes
30
+ @number * GIGABYTE
31
+ end
32
+ alias :gigabyte :gigabytes
33
+
34
+ def terabytes
35
+ @number * TERABYTE
36
+ end
37
+ alias :terabyte :terabytes
38
+
39
+ def petabytes
40
+ @number * PETABYTE
41
+ end
42
+ alias :petabyte :petabytes
43
+
44
+ def exabytes
45
+ @number * EXABYTE
46
+ end
47
+ alias :exabyte :exabytes
48
+ end
@@ -0,0 +1,237 @@
1
+ # require "sitemap_generator/core_ext/big_decimal/conversions"
2
+ require "sitemap_generator/utilities"
3
+
4
+ module SitemapGenerator
5
+ # = SitemapGenerator Number Helpers
6
+ module Helpers #:nodoc:
7
+
8
+ # Provides methods for converting numbers into formatted strings.
9
+ # Methods are provided for precision, positional notation and file size
10
+ # and pretty printing.
11
+ #
12
+ # Most methods expect a +number+ argument, and will return it
13
+ # unchanged if can't be converted into a valid number.
14
+ module NumberHelper
15
+
16
+ # Raised when argument +number+ param given to the helpers is invalid and
17
+ # the option :raise is set to +true+.
18
+ class InvalidNumberError < StandardError
19
+ attr_accessor :number
20
+ def initialize(number)
21
+ @number = number
22
+ end
23
+ end
24
+
25
+ # Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You can
26
+ # customize the format in the +options+ hash.
27
+ #
28
+ # ==== Options
29
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale).
30
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
31
+ # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
32
+ #
33
+ # ==== Examples
34
+ # number_with_delimiter(12345678) # => 12,345,678
35
+ # number_with_delimiter(12345678.05) # => 12,345,678.05
36
+ # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
37
+ # number_with_delimiter(12345678, :separator => ",") # => 12,345,678
38
+ # number_with_delimiter(12345678.05, :locale => :fr) # => 12 345 678,05
39
+ # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
40
+ # # => 98 765 432,98
41
+ def number_with_delimiter(number, options = {})
42
+ SitemapGenerator::Utilities.symbolize_keys!(options)
43
+
44
+ begin
45
+ Float(number)
46
+ rescue ArgumentError, TypeError
47
+ if options[:raise]
48
+ raise InvalidNumberError, number
49
+ else
50
+ return number
51
+ end
52
+ end
53
+
54
+ defaults = {
55
+ :separator => ".",
56
+ :delimiter => ",",
57
+ :precision => 3,
58
+ :significant => false,
59
+ :strip_insignificant_zeros => false
60
+ }
61
+ options = SitemapGenerator::Utilities.reverse_merge(options, defaults)
62
+
63
+ parts = number.to_s.to_str.split('.')
64
+ parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
65
+ parts.join(options[:separator])
66
+ end
67
+
68
+ # Formats a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision
69
+ # of 2 if +:significant+ is +false+, and 5 if +:significant+ is +true+).
70
+ # You can customize the format in the +options+ hash.
71
+ #
72
+ # ==== Options
73
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale).
74
+ # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3).
75
+ # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +false+)
76
+ # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
77
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
78
+ # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +false+)
79
+ #
80
+ # ==== Examples
81
+ # number_with_precision(111.2345) # => 111.235
82
+ # number_with_precision(111.2345, :precision => 2) # => 111.23
83
+ # number_with_precision(13, :precision => 5) # => 13.00000
84
+ # number_with_precision(389.32314, :precision => 0) # => 389
85
+ # number_with_precision(111.2345, :significant => true) # => 111
86
+ # number_with_precision(111.2345, :precision => 1, :significant => true) # => 100
87
+ # number_with_precision(13, :precision => 5, :significant => true) # => 13.000
88
+ # number_with_precision(111.234, :locale => :fr) # => 111,234
89
+ # number_with_precision(13, :precision => 5, :significant => true, strip_insignificant_zeros => true)
90
+ # # => 13
91
+ # number_with_precision(389.32314, :precision => 4, :significant => true) # => 389.3
92
+ # number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
93
+ # # => 1.111,23
94
+ def number_with_precision(number, options = {})
95
+ SitemapGenerator::Utilities.symbolize_keys!(options)
96
+
97
+ number = begin
98
+ Float(number)
99
+ rescue ArgumentError, TypeError
100
+ if options[:raise]
101
+ raise InvalidNumberError, number
102
+ else
103
+ return number
104
+ end
105
+ end
106
+
107
+ defaults = {
108
+ :separator => ".",
109
+ :delimiter => ",",
110
+ :precision => 3,
111
+ :significant => false,
112
+ :strip_insignificant_zeros => false
113
+ }
114
+ precision_defaults = {
115
+ :delimiter => ""
116
+ }
117
+ defaults = defaults.merge(precision_defaults)
118
+
119
+ options = SitemapGenerator::Utilities.reverse_merge(options, defaults) # Allow the user to unset default values: Eg.: :significant => false
120
+ precision = options.delete :precision
121
+ significant = options.delete :significant
122
+ strip_insignificant_zeros = options.delete :strip_insignificant_zeros
123
+
124
+ if significant and precision > 0
125
+ if number == 0
126
+ digits, rounded_number = 1, 0
127
+ else
128
+ digits = (Math.log10(number.abs) + 1).floor
129
+ rounded_number = (SitemapGenerator::BigDecimal.new(number.to_s) / SitemapGenerator::BigDecimal.new((10 ** (digits - precision)).to_f.to_s)).round.to_f * 10 ** (digits - precision)
130
+ digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed
131
+ end
132
+ precision = precision - digits
133
+ precision = precision > 0 ? precision : 0 #don't let it be negative
134
+ else
135
+ rounded_number = SitemapGenerator::Utilities.round(SitemapGenerator::BigDecimal.new(number.to_s), precision).to_f
136
+ end
137
+ formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options)
138
+ if strip_insignificant_zeros
139
+ escaped_separator = Regexp.escape(options[:separator])
140
+ formatted_number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
141
+ else
142
+ formatted_number
143
+ end
144
+
145
+ end
146
+
147
+ STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb].freeze
148
+ DECIMAL_UNITS = {0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
149
+ -1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto}.freeze
150
+
151
+ # Formats the bytes in +number+ into a more understandable representation
152
+ # (e.g., giving it 1500 yields 1.5 KB). This method is useful for
153
+ # reporting file sizes to users. You can customize the
154
+ # format in the +options+ hash.
155
+ #
156
+ # See <tt>number_to_human</tt> if you want to pretty-print a generic number.
157
+ #
158
+ # ==== Options
159
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale).
160
+ # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3).
161
+ # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +true+)
162
+ # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
163
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
164
+ # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +true+)
165
+ # ==== Examples
166
+ # number_to_human_size(123) # => 123 Bytes
167
+ # number_to_human_size(1234) # => 1.21 KB
168
+ # number_to_human_size(12345) # => 12.1 KB
169
+ # number_to_human_size(1234567) # => 1.18 MB
170
+ # number_to_human_size(1234567890) # => 1.15 GB
171
+ # number_to_human_size(1234567890123) # => 1.12 TB
172
+ # number_to_human_size(1234567, :precision => 2) # => 1.2 MB
173
+ # number_to_human_size(483989, :precision => 2) # => 470 KB
174
+ # number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,2 MB
175
+ #
176
+ # Non-significant zeros after the fractional separator are stripped out by default (set
177
+ # <tt>:strip_insignificant_zeros</tt> to +false+ to change that):
178
+ # number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB"
179
+ # number_to_human_size(524288000, :precision=>5) # => "500 MB"
180
+ def number_to_human_size(number, options = {})
181
+ SitemapGenerator::Utilities.symbolize_keys!(options)
182
+
183
+ number = begin
184
+ Float(number)
185
+ rescue ArgumentError, TypeError
186
+ if options[:raise]
187
+ raise InvalidNumberError, number
188
+ else
189
+ return number
190
+ end
191
+ end
192
+
193
+ defaults = {
194
+ :separator => ".",
195
+ :delimiter => ",",
196
+ :precision => 3,
197
+ :significant => false,
198
+ :strip_insignificant_zeros => false
199
+ }
200
+ human = {
201
+ :delimiter => "",
202
+ :precision => 3,
203
+ :significant => true,
204
+ :strip_insignificant_zeros => true
205
+ }
206
+ defaults = defaults.merge(human)
207
+ options = SitemapGenerator::Utilities.reverse_merge(options, defaults)
208
+ #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
209
+ options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
210
+
211
+ storage_units_format = "%n %u"
212
+
213
+ if number.to_i < 1024
214
+ unit = number.to_i > 1 || number.to_i == 0 ? 'Bytes' : 'Byte'
215
+ storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit)
216
+ else
217
+ max_exp = STORAGE_UNITS.size - 1
218
+ exponent = (Math.log(number) / Math.log(1024)).to_i # Convert to base 1024
219
+ exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
220
+ number /= 1024 ** exponent
221
+
222
+ unit_key = STORAGE_UNITS[exponent]
223
+ units = {
224
+ :byte => "Bytes",
225
+ :kb => "KB",
226
+ :mb => "MB",
227
+ :gb => "GB",
228
+ :tb => "TB"
229
+ }
230
+ unit = units[unit_key]
231
+ formatted_number = number_with_precision(number, options)
232
+ storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit)
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,80 @@
1
+ require 'sitemap_generator'
2
+
3
+ module SitemapGenerator
4
+
5
+ # Provide a class for evaluating blocks, making the URL helpers from the framework
6
+ # and API methods available to it.
7
+ class Interpreter
8
+
9
+ if SitemapGenerator.app.rails3?
10
+ include ::Rails.application.routes.url_helpers
11
+ elsif SitemapGenerator.app.rails?
12
+ require 'action_controller'
13
+ include ActionController::UrlWriter
14
+ end
15
+
16
+ # Call with a block to evaluate a dynamic config. The only method exposed for you is
17
+ # `add` to add a link to the sitemap object attached to this interpreter.
18
+ #
19
+ # === Options
20
+ # * <tt>link_set</tt> - a LinkSet instance to use. Default is SitemapGenerator::Sitemap.
21
+ #
22
+ # All other options are passed to the LinkSet by setting them using accessor methods.
23
+ def initialize(opts={}, &block)
24
+ opts = SitemapGenerator::Utilities.reverse_merge(opts, :link_set => SitemapGenerator::Sitemap)
25
+ @linkset = opts.delete :link_set
26
+ @linkset.send(:set_options, opts)
27
+ eval(&block) if block_given?
28
+ end
29
+
30
+ def add(*args)
31
+ @linkset.add(*args)
32
+ end
33
+
34
+ def add_to_index(*args)
35
+ @linkset.add_to_index(*args)
36
+ end
37
+
38
+ # Start a new group of sitemaps. Any of the options to SitemapGenerator.new may
39
+ # be passed. Pass a block with calls to +add+ to add links to the sitemaps.
40
+ #
41
+ # All groups use the same sitemap index.
42
+ def group(*args, &block)
43
+ @linkset.group(*args, &block)
44
+ end
45
+
46
+ # Return the LinkSet instance so that you can access it from within the `create` block
47
+ # without having to use the yield_sitemap option.
48
+ def sitemap
49
+ @linkset
50
+ end
51
+
52
+ # Evaluate the block in the interpreter. Pass :yield_sitemap => true to
53
+ # yield the Interpreter instance to the block...for old-style calling.
54
+ def eval(opts={}, &block)
55
+ if block_given?
56
+ if opts[:yield_sitemap]
57
+ yield @linkset
58
+ else
59
+ instance_eval(&block)
60
+ end
61
+ end
62
+ end
63
+
64
+ # Run the interpreter on a config file using
65
+ # the default <tt>SitemapGenerator::Sitemap</tt> sitemap object.
66
+ #
67
+ # === Options
68
+ # * <tt>:config_file</tt> - full path to the config file to evaluate.
69
+ # Default is config/sitemap.rb in your application's root directory.
70
+ # All other options are passed to +new+.
71
+ def self.run(opts={}, &block)
72
+ opts = opts.dup
73
+ config_file = opts.delete(:config_file)
74
+ config_file ||= SitemapGenerator.app.root + 'config/sitemap.rb'
75
+ interpreter = self.new(opts)
76
+ interpreter.instance_eval(File.read(config_file), config_file.to_s)
77
+ interpreter
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,677 @@
1
+ require 'builder'
2
+
3
+ # A LinkSet provisions a bunch of links to sitemap files. It also writes the index file
4
+ # which lists all the sitemap files written.
5
+ module SitemapGenerator
6
+ class LinkSet
7
+ @@requires_finalization_opts = [:filename, :sitemaps_path, :sitemaps_host, :namer]
8
+ @@new_location_opts = [:filename, :sitemaps_path, :namer]
9
+
10
+ attr_reader :default_host, :sitemaps_path, :filename, :create_index
11
+ attr_accessor :include_root, :include_index, :adapter, :yield_sitemap
12
+ attr_writer :verbose
13
+
14
+ # Create a new sitemap index and sitemap files. Pass a block with calls to the following
15
+ # methods:
16
+ # * +add+ - Add a link to the current sitemap
17
+ # * +group+ - Start a new group of sitemaps
18
+ #
19
+ # == Options
20
+ #
21
+ # Any option supported by +new+ can be passed. The options will be
22
+ # set on the instance using the accessor methods. This is provided mostly
23
+ # as a convenience.
24
+ #
25
+ # In addition to the options to +new+, the following options are supported:
26
+ # * <tt>:finalize</tt> - The sitemaps are written as they get full and at the end
27
+ # of the block. Pass +false+ as the value to prevent the sitemap or sitemap index
28
+ # from being finalized. Default is +true+.
29
+ #
30
+ # If you are calling +create+ more than once in your sitemap configuration file,
31
+ # make sure that you set a different +sitemaps_path+ or +filename+ for each call otherwise
32
+ # the sitemaps may be overwritten.
33
+ def create(opts={}, &block)
34
+ reset!
35
+ set_customized_schemas(opts)
36
+ set_options(opts)
37
+ if verbose
38
+ start_time = Time.now
39
+ puts "In '#{sitemap_index.location.public_path}':"
40
+ end
41
+ interpreter.eval(:yield_sitemap => yield_sitemap?, &block)
42
+ finalize!
43
+ end_time = Time.now if verbose
44
+ output(sitemap_index.stats_summary(:time_taken => end_time - start_time)) if verbose
45
+ self
46
+ end
47
+
48
+ # Constructor
49
+ #
50
+ # == Options:
51
+ # * <tt>:adapter</tt> - instance of a class with a write method which takes a SitemapGenerator::Location
52
+ # and raw XML data and persists it. The default adapter is a SitemapGenerator::FileAdapter
53
+ # which simply writes files to the filesystem. You can use a SitemapGenerator::WaveAdapter
54
+ # for uploading sitemaps to remote servers - useful for read-only hosts such as Heroku. Or
55
+ # you can provide an instance of your own class to provide custom behavior.
56
+ #
57
+ # * <tt>:default_host</tt> - host including protocol to use in all sitemap links
58
+ # e.g. http://en.google.ca
59
+ #
60
+ # * <tt>:public_path</tt> - Full or relative path to the directory to write sitemaps into.
61
+ # Defaults to the <tt>public/</tt> directory in your application root directory or
62
+ # the current working directory.
63
+ #
64
+ # * <tt>:sitemaps_host</tt> - String. <b>Host including protocol</b> to use when generating
65
+ # a link to a sitemap file i.e. the hostname of the server where the sitemaps are hosted.
66
+ # The value will differ from the hostname in your sitemap links.
67
+ # For example: `'http://amazon.aws.com/'`.
68
+ #
69
+ # Note that `include_index` is automatically turned off when the `sitemaps_host` does
70
+ # not match `default_host`. Because the link to the sitemap index file that would
71
+ # otherwise be added would point to a different host than the rest of the links in
72
+ # the sitemap. Something that the sitemap rules forbid.
73
+ #
74
+ # * <tt>:sitemaps_path</tt> - path fragment within public to write sitemaps
75
+ # to e.g. 'en/'. Sitemaps are written to <tt>public_path</tt> + <tt>sitemaps_path</tt>
76
+ #
77
+ # * <tt>:filename</tt> - symbol giving the base name for files (default <tt>:sitemap</tt>).
78
+ # The names are generated like "#{filename}.xml.gz", "#{filename}1.xml.gz", "#{filename}2.xml.gz"
79
+ # with the first file being the index if you have more than one sitemap file.
80
+ #
81
+ # * <tt>:include_index</tt> - Boolean. Whether to <b>add a link pointing to the sitemap index<b>
82
+ # to the current sitemap. This points search engines to your Sitemap Index to
83
+ # include it in the indexing of your site. Default is `false`. Turned off when
84
+ # `sitemaps_host` is set or within a `group()` block. Turned off because Google can complain
85
+ # about nested indexing and because if a robot is already reading your sitemap, they
86
+ # probably know about the index.
87
+ #
88
+ # * <tt>:include_root</tt> - Boolean. Whether to **add the root** url i.e. '/' to the
89
+ # current sitemap. Default is `true`. Turned off within a `group()` block.
90
+ #
91
+ # * <tt>:search_engines</tt> - Hash. A hash of search engine names mapped to
92
+ # ping URLs. See ping_search_engines.
93
+ #
94
+ # * <tt>:verbose</tt> - If +true+, output a summary line for each sitemap and sitemap
95
+ # index that is created. Default is +false+.
96
+ #
97
+ # * <tt>:create_index</tt> - Supported values: `true`, `false`, `:auto`. Default: `:auto`.
98
+ # Whether to create a sitemap index file. If `true` an index file is always created,
99
+ # regardless of how many links are in your sitemap. If `false` an index file is never
100
+ # created. If `:auto` an index file is created only if your sitemap has more than
101
+ # one sitemap file.
102
+ #
103
+ # * <tt>:namer</tt> - A <tt>SitemapGenerator::SimpleNamer</tt> instance for generating the sitemap
104
+ # and index file names. See <tt>:filename</tt> if you don't need to do anything fancy, and can
105
+ # accept the default naming conventions.
106
+ #
107
+ # * <tt>:compress</tt> - Specifies which files to compress with gzip. Default is `true`. Accepted values:
108
+ # * `true` - Boolean; compress all files.
109
+ # * `false` - Boolean; write out only uncompressed files.
110
+ # * `:all_but_first` - Symbol; leave the first file uncompressed but compress any remaining files.
111
+ #
112
+ # The compression setting applies to groups too. So :all_but_first will have the same effect (the first
113
+ # file in the group will not be compressed, the rest will). So if you require different behaviour for your
114
+ # groups, pass in a `:compress` option e.g. <tt>group(:compress => false) { add('/link') }</tt>
115
+ #
116
+ # KJV: When adding a new option be sure to include it in `options_for_group()` if
117
+ # the option should be inherited by groups.
118
+ def initialize(options={})
119
+ options = SitemapGenerator::Utilities.reverse_merge(options,
120
+ :include_root => true,
121
+ :include_index => false,
122
+ :filename => :sitemap,
123
+ :search_engines => {
124
+ :google => "http://www.google.com/webmasters/tools/ping?sitemap=%s",
125
+ :bing => "http://www.bing.com/webmaster/ping.aspx?siteMap=%s"
126
+ },
127
+ :create_index => :auto,
128
+ :compress => true
129
+ )
130
+ options.each_pair { |k, v| instance_variable_set("@#{k}".to_sym, v) }
131
+
132
+ # If an index is passed in, protect it from modification.
133
+ # Sitemaps can be added to the index but nothing else can be changed.
134
+ if options[:sitemap_index]
135
+ @protect_index = true
136
+ end
137
+ end
138
+
139
+ # Add a link to a Sitemap. If a new Sitemap is required, one will be created for
140
+ # you.
141
+ #
142
+ # link - string link e.g. '/merchant', '/article/1' or whatever.
143
+ # options - see README.
144
+ # host - host for the link, defaults to your <tt>default_host</tt>.
145
+ def add(link, options={})
146
+ add_default_links if !@added_default_links
147
+ sitemap.add(link, SitemapGenerator::Utilities.reverse_merge(options, :host => @default_host))
148
+ rescue SitemapGenerator::SitemapFullError
149
+ finalize_sitemap!
150
+ retry
151
+ rescue SitemapGenerator::SitemapFinalizedError
152
+ @sitemap = sitemap.new
153
+ retry
154
+ end
155
+
156
+ # Add a link to the Sitemap Index.
157
+ # * link - A string link e.g. '/sitemaps/sitemap1.xml.gz' or a SitemapFile instance.
158
+ # * options - A hash of options including `:lastmod`, ':priority`, ':changefreq` and `:host`
159
+ #
160
+ # The `:host` option defaults to the value of `sitemaps_host` which is the host where your
161
+ # sitemaps reside. If no `sitemaps_host` is set, the `default_host` is used.
162
+ def add_to_index(link, options={})
163
+ sitemap_index.add(link, SitemapGenerator::Utilities.reverse_merge(options, :host => sitemaps_host))
164
+ end
165
+
166
+ # Create a new group of sitemap files.
167
+ #
168
+ # Returns a new LinkSet instance with the options passed in set on it. All groups
169
+ # share the sitemap index, which is not affected by any of the options passed here.
170
+ #
171
+ # === Options
172
+ # Any of the options to LinkSet.new. Except for <tt>:public_path</tt> which is shared
173
+ # by all groups.
174
+ #
175
+ # The current options are inherited by the new group of sitemaps. The only exceptions
176
+ # being <tt>:include_index</tt> and <tt>:include_root</tt> which default to +false+.
177
+ #
178
+ # Pass a block to add links to the new LinkSet. If you pass a block the sitemaps will
179
+ # be finalized when the block returns.
180
+ #
181
+ # If you are not changing any of the location settings like <tt>filename<tt>,
182
+ # <tt>sitemaps_path</tt>, <tt>sitemaps_host</tt> or <tt>namer</tt>,
183
+ # links you add within the group will be added to the current sitemap.
184
+ # Otherwise the current sitemap file is finalized and a new sitemap file started,
185
+ # using the options you specified.
186
+ #
187
+ # Most commonly, you'll want to give the group's files a distinct name using
188
+ # the <tt>filename</tt> option.
189
+ #
190
+ # Options like <tt>:default_host</tt> can be used and it will only affect the links
191
+ # within the group. Links added outside of the group will revert to the previous
192
+ # +default_host+.
193
+ def group(opts={}, &block)
194
+ @created_group = true
195
+ original_opts = opts.dup
196
+
197
+ if (@@requires_finalization_opts & original_opts.keys).empty?
198
+ # If no new filename or path is specified reuse the default sitemap file.
199
+ # A new location object will be set on it for the duration of the group.
200
+ original_opts[:sitemap] = sitemap
201
+ elsif original_opts.key?(:sitemaps_host) && (@@new_location_opts & original_opts.keys).empty?
202
+ # If no location options are provided we are creating the next sitemap in the
203
+ # current series, so finalize and inherit the namer.
204
+ finalize_sitemap!
205
+ original_opts[:namer] = namer
206
+ end
207
+
208
+ opts = options_for_group(original_opts)
209
+ @group = SitemapGenerator::LinkSet.new(opts)
210
+ if opts.key?(:sitemap)
211
+ # If the group is sharing the current sitemap, set the
212
+ # new location options on the location object.
213
+ @original_location = @sitemap.location.dup
214
+ @sitemap.location.merge!(@group.sitemap_location)
215
+ if block_given?
216
+ @group.interpreter.eval(:yield_sitemap => @yield_sitemap || SitemapGenerator.yield_sitemap?, &block)
217
+ @sitemap.location.merge!(@original_location)
218
+ end
219
+ else
220
+ # Handle the case where a user only has one group, and it's being written
221
+ # to a new sitemap file. They would expect there to be an index. So force
222
+ # index creation. If there is more than one group, we would have an index anyways,
223
+ # so it's safe to force index creation in these other cases. In the case that
224
+ # the groups reuse the current sitemap, don't force index creation because
225
+ # we want the default behaviour i.e. only an index if more than one sitemap file.
226
+ # Don't force index creation if the user specifically requested no index. This
227
+ # unfortunately means that if they set it to :auto they may be getting an index
228
+ # when they didn't expect one, but you shouldn't be using groups if you only have
229
+ # one sitemap and don't want an index. Rather, just add the links directly in the create()
230
+ # block.
231
+ @group.send(:create_index=, true, true) if @group.create_index != false
232
+
233
+ if block_given?
234
+ @group.interpreter.eval(:yield_sitemap => @yield_sitemap || SitemapGenerator.yield_sitemap?, &block)
235
+ @group.finalize_sitemap!
236
+ end
237
+ end
238
+ @group
239
+ end
240
+
241
+ # Ping search engines to notify them of updated sitemaps.
242
+ #
243
+ # Search engines are already notified for you if you run `rake sitemap:refresh`.
244
+ # If you want to ping search engines separately to your sitemap generation, run
245
+ # `rake sitemap:refresh:no_ping` and then run a rake task or script
246
+ # which calls this method as in the example below.
247
+ #
248
+ # == Arguments
249
+ # * sitemap_index_url - The full URL to your sitemap index file.
250
+ # If not provided the location is based on the `host` you have
251
+ # set and any other options like your `sitemaps_path`. The URL
252
+ # will be CGI escaped for you when included as part of the
253
+ # search engine ping URL.
254
+ #
255
+ # == Options
256
+ # A hash of one or more search engines to ping in addition to the
257
+ # default search engines. The key is the name of the search engine
258
+ # as a string or symbol and the value is the full URL to ping with
259
+ # a string interpolation that will be replaced by the CGI escaped sitemap
260
+ # index URL. If you have any literal percent characters in your URL you
261
+ # need to escape them with `%%`. For example if your sitemap index URL
262
+ # is `http://example.com/sitemap.xml.gz` and your
263
+ # ping url is `http://example.com/100%%/ping?url=%s`
264
+ # then the final URL that is pinged will be `http://example.com/100%/ping?url=http%3A%2F%2Fexample.com%2Fsitemap.xml.gz`
265
+ #
266
+ # == Examples
267
+ #
268
+ # Both of these examples will ping the default search engines in addition to `http://superengine.com/ping?url=http%3A%2F%2Fexample.com%2Fsitemap.xml.gz`
269
+ #
270
+ # SitemapGenerator::Sitemap.host('http://example.com/')
271
+ # SitemapGenerator::Sitemap.ping_search_engines(:super_engine => 'http://superengine.com/ping?url=%s')
272
+ #
273
+ # Is equivalent to:
274
+ #
275
+ # SitemapGenerator::Sitemap.ping_search_engines('http://example.com/sitemap.xml.gz', :super_engine => 'http://superengine.com/ping?url=%s')
276
+ def ping_search_engines(*args)
277
+ require 'cgi/session'
278
+ require 'open-uri'
279
+ require 'timeout'
280
+
281
+ engines = args.last.is_a?(Hash) ? args.pop : {}
282
+ unescaped_url = args.shift || sitemap_index_url
283
+ index_url = CGI.escape(unescaped_url)
284
+
285
+ output("\n")
286
+ output("Pinging with URL '#{unescaped_url}':")
287
+ search_engines.merge(engines).each do |engine, link|
288
+ link = link % index_url
289
+ name = Utilities.titleize(engine.to_s)
290
+ begin
291
+ Timeout::timeout(10) {
292
+ open(link)
293
+ }
294
+ output(" Successful ping of #{name}")
295
+ rescue Timeout::Error, StandardError => e
296
+ output("Ping failed for #{name}: #{e.inspect} (URL #{link})")
297
+ end
298
+ end
299
+ end
300
+
301
+ # Return a count of the total number of links in all sitemaps
302
+ def link_count
303
+ sitemap_index.total_link_count
304
+ end
305
+
306
+ # Return the host to use in links to the sitemap files. This defaults to your
307
+ # +default_host+.
308
+ def sitemaps_host
309
+ @sitemaps_host || @default_host
310
+ end
311
+
312
+ # Lazy-initialize a sitemap instance and return it.
313
+ def sitemap
314
+ @sitemap ||= SitemapGenerator::Builder::SitemapFile.new(sitemap_location,
315
+ schemas,
316
+ schema_location)
317
+ end
318
+
319
+ # Lazy-initialize a sitemap index instance and return it.
320
+ def sitemap_index
321
+ @sitemap_index ||= SitemapGenerator::Builder::SitemapIndexFile.new(sitemap_index_location)
322
+ end
323
+
324
+ # Return the full url to the sitemap index file. When `create_index` is `false`
325
+ # the first sitemap is technically the index, so this will be its URL. It's important
326
+ # to use this method to get the index url because `sitemap_index.location.url` will
327
+ # not be correct in such situations.
328
+ #
329
+ # KJV: This is somewhat confusing.
330
+ def sitemap_index_url
331
+ sitemap_index.index_url
332
+ end
333
+
334
+ # All done. Write out remaining files.
335
+ def finalize!
336
+ finalize_sitemap!
337
+ finalize_sitemap_index!
338
+ end
339
+
340
+ # Return a boolean indicating hether to add a link to the sitemap index file
341
+ # to the current sitemap. This points search engines to your Sitemap Index so
342
+ # they include it in the indexing of your site, but is not strictly neccessary.
343
+ # Default is `true`. Turned off when `sitemaps_host` is set or within a `group()` block.
344
+ def include_index?
345
+ if default_host && sitemaps_host && sitemaps_host != default_host
346
+ false
347
+ else
348
+ @include_index
349
+ end
350
+ end
351
+
352
+ # Return a boolean indicating whether to automatically add the root url i.e. '/' to the
353
+ # current sitemap. Default is `true`. Turned off within a `group()` block.
354
+ def include_root?
355
+ !!@include_root
356
+ end
357
+
358
+ # Set verbose on the instance or by setting ENV['VERBOSE'] to true or false.
359
+ # By default verbose is true. When running rake tasks, pass the <tt>-s</tt>
360
+ # option to rake to turn verbose off.
361
+ def verbose
362
+ if @verbose.nil?
363
+ @verbose = SitemapGenerator.verbose.nil? ? true : SitemapGenerator.verbose
364
+ end
365
+ @verbose
366
+ end
367
+
368
+ def schemas
369
+ @schemas || SCHEMAS
370
+ end
371
+
372
+ def schema_location
373
+ @schema_location || SCHEMA_LOCATION
374
+ end
375
+
376
+ # Return a boolean indicating whether or not to yield the sitemap.
377
+ def yield_sitemap?
378
+ @yield_sitemap.nil? ? SitemapGenerator.yield_sitemap? : !!@yield_sitemap
379
+ end
380
+
381
+ protected
382
+
383
+ def set_customized_schemas(opts)
384
+ exclude_keys = opts.delete(:exclude_keys) || []
385
+ @schemas= SitemapGenerator::SCHEMAS.reject{ |k, v| exclude_keys.include? k }
386
+ @schema_location = [SitemapGenerator::SCHEMA_LOCATION,
387
+ opts.delete(:schema_location).to_s].join(" ").strip()
388
+ end
389
+
390
+ # Set each option on this instance using accessor methods. This will affect
391
+ # both the sitemap and the sitemap index.
392
+ #
393
+ # If both `filename` and `namer` are passed, set filename first so it
394
+ # doesn't override the latter.
395
+ def set_options(opts={})
396
+ opts = opts.dup
397
+ %w(filename namer).each do |key|
398
+ if value = opts.delete(key.to_sym)
399
+ send("#{key}=", value)
400
+ end
401
+ end
402
+ opts.each_pair do |key, value|
403
+ send("#{key}=", value)
404
+ end
405
+ end
406
+
407
+ # Given +opts+, modify it and return it prepped for creating a new group from this LinkSet.
408
+ # If <tt>:public_path</tt> is present in +opts+ it is removed because groups cannot
409
+ # change the public path.
410
+ def options_for_group(opts)
411
+ opts = SitemapGenerator::Utilities.reverse_merge(opts,
412
+ :include_index => false,
413
+ :include_root => false,
414
+ :sitemap_index => sitemap_index
415
+ )
416
+ opts.delete(:public_path)
417
+
418
+ # Reverse merge the current settings
419
+ # KJV: This hash could be a problem because it needs to be maintained
420
+ # when new options are added, but can easily be missed. We really could
421
+ # do with a separate SitemapOptions class.
422
+ current_settings = [
423
+ :include_root,
424
+ :include_index,
425
+ :sitemaps_path,
426
+ :public_path,
427
+ :sitemaps_host,
428
+ :verbose,
429
+ :default_host,
430
+ :adapter,
431
+ :create_index,
432
+ :compress,
433
+ :schemas,
434
+ :schema_location
435
+ ].inject({}) do |hash, key|
436
+ if !(value = instance_variable_get(:"@#{key}")).nil?
437
+ hash[key] = value
438
+ end
439
+ hash
440
+ end
441
+ SitemapGenerator::Utilities.reverse_merge!(opts, current_settings)
442
+ opts
443
+ end
444
+
445
+ # Add default links if those options are turned on. Record the fact that we have done so
446
+ # in an instance variable.
447
+ def add_default_links
448
+ if include_root?
449
+ sitemap.add('/', :lastmod => Time.now, :changefreq => 'always', :priority => 1.0, :host => @default_host)
450
+ end
451
+ if include_index?
452
+ sitemap.add(sitemap_index, :lastmod => Time.now, :changefreq => 'always', :priority => 1.0)
453
+ end
454
+ @added_default_links = true
455
+ end
456
+
457
+ # Finalize a sitemap by including it in the index and outputting a summary line.
458
+ # Do nothing if it has already been finalized.
459
+ #
460
+ # Don't finalize if the sitemap is empty.
461
+ #
462
+ # Add the default links if they have not been added yet and no groups have been created.
463
+ # If the default links haven't been added we know that the sitemap is empty,
464
+ # because they are added on the first call to add(). This ensure that if the
465
+ # block passed to create() is empty the default links are still included in the
466
+ # sitemap.
467
+ def finalize_sitemap!
468
+ return if sitemap.finalized? || sitemap.empty? && @created_group
469
+ add_default_links if !@added_default_links && !@created_group
470
+ # This will finalize it. We add to the index even if not creating an index because
471
+ # the index keeps track of how many links are in our sitemaps and we need this info
472
+ # for the summary line. Also the index determines which file gets the first name
473
+ # so everything has to go via the index.
474
+ add_to_index(sitemap) unless sitemap.empty?
475
+ end
476
+
477
+ # Finalize a sitemap index and output a summary line. Do nothing if it has already
478
+ # been finalized.
479
+ def finalize_sitemap_index!
480
+ return if @protect_index || sitemap_index.finalized?
481
+ sitemap_index.finalize!
482
+ sitemap_index.write
483
+ end
484
+
485
+ # Return the interpreter linked to this instance.
486
+ def interpreter
487
+ require 'sitemap_generator/interpreter'
488
+ @interpreter ||= SitemapGenerator::Interpreter.new(:link_set => self)
489
+ end
490
+
491
+ # Reset this instance. Keep the same options, but return to the same state
492
+ # as before any sitemaps were created.
493
+ def reset!
494
+ @sitemap_index = nil if @sitemap_index && @sitemap_index.finalized? && !@protect_index
495
+ @sitemap = nil if @sitemap && @sitemap.finalized?
496
+ self.namer.reset
497
+ @added_default_links = false
498
+ end
499
+
500
+ # Write the given string to STDOUT. Used so that the sitemap config can be
501
+ # evaluated and some info output to STDOUT in a lazy fasion.
502
+ def output(string)
503
+ return unless verbose
504
+ puts string
505
+ end
506
+
507
+ module LocationHelpers
508
+ public
509
+
510
+ # Set the host name, including protocol, that will be used by default on each
511
+ # of your sitemap links. You can pass a different host in your options to `add`
512
+ # if you need to change it on a per-link basis.
513
+ def default_host=(value)
514
+ @default_host = value
515
+ update_location_info(:host, value)
516
+ end
517
+
518
+ # Set the public_path. This path gives the location of your public directory.
519
+ # The default is the public/ directory in your Rails root. Or if Rails is not
520
+ # found, it defaults to public/ in the current directory (of the process).
521
+ #
522
+ # Example: 'tmp/' if you don't want to generate in public for some reason.
523
+ #
524
+ # Set to nil to use the current directory.
525
+ def public_path=(value)
526
+ @public_path = Pathname.new(SitemapGenerator::Utilities.append_slash(value))
527
+ if @public_path.relative?
528
+ @public_path = SitemapGenerator.app.root + @public_path
529
+ end
530
+ update_location_info(:public_path, @public_path)
531
+ @public_path
532
+ end
533
+
534
+ # Return a Pathname with the full path to the public directory
535
+ def public_path
536
+ @public_path ||= self.send(:public_path=, 'public/')
537
+ end
538
+
539
+ # Set the sitemaps_path. This path gives the location to write sitemaps to
540
+ # relative to your public_path.
541
+ # Example: 'sitemaps/' to generate your sitemaps in 'public/sitemaps/'.
542
+ def sitemaps_path=(value)
543
+ @sitemaps_path = value
544
+ update_location_info(:sitemaps_path, value)
545
+ end
546
+
547
+ # Set the host name, including protocol, that will be used on all links to your sitemap
548
+ # files. Useful when the server that hosts the sitemaps is not on the same host as
549
+ # the links in the sitemap.
550
+ #
551
+ # Note that `include_index` will be turned off to avoid adding a link to a sitemap with
552
+ # a different host than the other links.
553
+ def sitemaps_host=(value)
554
+ @sitemaps_host = value
555
+ update_location_info(:host, value)
556
+ end
557
+
558
+ # Set the filename base to use when generating sitemaps (and the sitemap index).
559
+ #
560
+ # === Example
561
+ # <tt>filename = :sitemap</tt>
562
+ #
563
+ # === Generates
564
+ # <tt>sitemap.xml.gz, sitemap1.xml.gz, sitemap2.xml.gz, ...</tt>
565
+ def filename=(value)
566
+ @filename = value
567
+ self.namer = SitemapGenerator::SimpleNamer.new(@filename)
568
+ end
569
+
570
+ # Set the search engines hash to a new hash of search engine names mapped to
571
+ # ping URLs (see ping_search_engines). If the value is nil it is converted
572
+ # to an empty hash.
573
+ # === Example
574
+ # <tt>search_engines = { :google => "http://www.google.com/webmasters/sitemaps/ping?sitemap=%s" }</tt>
575
+ def search_engines=(value)
576
+ @search_engines = value || {}
577
+ end
578
+
579
+ # Return the hash of search engines.
580
+ def search_engines
581
+ @search_engines || {}
582
+ end
583
+
584
+ # Return a new +SitemapLocation+ instance with the current options included
585
+ def sitemap_location
586
+ SitemapGenerator::SitemapLocation.new(
587
+ :host => sitemaps_host,
588
+ :namer => namer,
589
+ :public_path => public_path,
590
+ :sitemaps_path => @sitemaps_path,
591
+ :adapter => @adapter,
592
+ :verbose => verbose,
593
+ :compress => @compress
594
+ )
595
+ end
596
+
597
+ # Return a new +SitemapIndexLocation+ instance with the current options included
598
+ def sitemap_index_location
599
+ SitemapGenerator::SitemapLocation.new(
600
+ :host => sitemaps_host,
601
+ :namer => namer,
602
+ :public_path => public_path,
603
+ :sitemaps_path => @sitemaps_path,
604
+ :adapter => @adapter,
605
+ :verbose => verbose,
606
+ :create_index => @create_index,
607
+ :compress => @compress
608
+ )
609
+ end
610
+
611
+ # Set the value of +create_index+ on the SitemapIndexLocation object of the
612
+ # SitemapIndexFile.
613
+ #
614
+ # Whether to create a sitemap index file. Supported values: `true`, `false`, `:auto`.
615
+ # If `true` an index file is always created, regardless of how many links
616
+ # are in your sitemap. If `false` an index file is never created.
617
+ # If `:auto` an index file is created only if your sitemap has more than
618
+ # one sitemap file.
619
+ def create_index=(value, force=false)
620
+ @create_index = value
621
+ # Allow overriding the protected status of the index when we are creating a group.
622
+ # Because sometimes we need to force an index in that case. But generally we don't
623
+ # want to allow people to mess with this value if the index is protected.
624
+ @sitemap_index.location[:create_index] = value if @sitemap_index && ((!@sitemap_index.finalized? && !@protect_index) || force)
625
+ end
626
+
627
+ # Set the namer to use to generate the sitemap (and index) file names.
628
+ # This should be an instance of <tt>SitemapGenerator::SimpleNamer</tt>
629
+ def namer=(value)
630
+ @namer = value
631
+ @sitemap.location[:namer] = value if @sitemap && !@sitemap.finalized?
632
+ @sitemap_index.location[:namer] = value if @sitemap_index && !@sitemap_index.finalized? && !@protect_index
633
+ end
634
+
635
+ # Return the namer object. If it is not set, looks for it on
636
+ # the current sitemap and if there is no sitemap, creates a new one using
637
+ # the current filename.
638
+ def namer
639
+ @namer ||= @sitemap && @sitemap.location.namer || SitemapGenerator::SimpleNamer.new(@filename)
640
+ end
641
+
642
+ # Set the value of the compress setting.
643
+ #
644
+ # Values:
645
+ # * `true` - Boolean; compress all files
646
+ # * `false` - Boolean; write out only uncompressed files
647
+ # * `:all_but_first` - Symbol; leave the first file uncompressed but compress any remaining files.
648
+ #
649
+ # The compression setting applies to groups too. So :all_but_first will have the same effect (the first
650
+ # file in the group will not be compressed, the rest will). So if you require different behaviour for your
651
+ # groups, pass in a `:compress` option e.g. <tt>group(:compress => false) { add('/link') }</tt>
652
+ def compress=(value)
653
+ @compress = value
654
+ @sitemap_index.location[:compress] = @compress if @sitemap_index
655
+ @sitemap.location[:compress] = @compress if @sitemap
656
+ end
657
+
658
+ # Return the current compression setting. Its value determines which files will be gzip'ed.
659
+ # See the setter for documentation of its values.
660
+ def compress
661
+ @compress
662
+ end
663
+
664
+ protected
665
+
666
+ # Update the given attribute on the current sitemap index and sitemap file location objects.
667
+ # But don't create the index or sitemap files yet if they are not already created.
668
+ def update_location_info(attribute, value, opts={})
669
+ opts = SitemapGenerator::Utilities.reverse_merge(opts, :include_index => !@protect_index)
670
+ @sitemap_index.location[attribute] = value if opts[:include_index] && @sitemap_index && !@sitemap_index.finalized?
671
+ @sitemap.location[attribute] = value if @sitemap && !@sitemap.finalized?
672
+ end
673
+ end
674
+ include LocationHelpers
675
+ end
676
+ end
677
+