ftbpro_sitemap_generator 5.0.8

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.
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
+