sitemap_generator 1.5.2 → 2.0.0
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.
- data/Gemfile.lock +1 -1
- data/README.md +355 -186
- data/VERSION +1 -1
- data/lib/sitemap_generator.rb +15 -2
- data/lib/sitemap_generator/builder/sitemap_file.rb +17 -31
- data/lib/sitemap_generator/builder/sitemap_index_file.rb +14 -14
- data/lib/sitemap_generator/interpreter.rb +46 -18
- data/lib/sitemap_generator/link_set.rb +306 -126
- data/lib/sitemap_generator/sitemap_location.rb +60 -26
- data/lib/sitemap_generator/sitemap_namer.rb +41 -12
- data/tasks/sitemap_generator_tasks.rake +1 -2
- data/templates/sitemap.rb +10 -11
- metadata +5 -7
- data/README.md.orig +0 -374
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
data/lib/sitemap_generator.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'sitemap_generator/builder'
|
2
1
|
require 'sitemap_generator/sitemap_namer'
|
2
|
+
require 'sitemap_generator/builder'
|
3
3
|
require 'sitemap_generator/link_set'
|
4
4
|
require 'sitemap_generator/templates'
|
5
5
|
require 'sitemap_generator/utilities'
|
@@ -8,6 +8,8 @@ require 'sitemap_generator/sitemap_location'
|
|
8
8
|
require 'active_support/core_ext/numeric'
|
9
9
|
|
10
10
|
module SitemapGenerator
|
11
|
+
autoload(:Interpreter, 'sitemap_generator/interpreter')
|
12
|
+
|
11
13
|
SitemapError = Class.new(StandardError)
|
12
14
|
SitemapFullError = Class.new(SitemapError)
|
13
15
|
SitemapFinalizedError = Class.new(SitemapError)
|
@@ -22,13 +24,24 @@ module SitemapGenerator
|
|
22
24
|
# Lazy-initialize the LinkSet instance
|
23
25
|
Sitemap = (Class.new do
|
24
26
|
def method_missing(*args, &block)
|
25
|
-
(@link_set ||=
|
27
|
+
(@link_set ||= reset!).send(*args, &block)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Use a new LinkSet instance
|
31
|
+
def reset!
|
32
|
+
@link_set = LinkSet.new
|
26
33
|
end
|
27
34
|
end).new
|
28
35
|
end
|
29
36
|
|
30
37
|
class << self
|
31
38
|
attr_accessor :root, :app, :templates
|
39
|
+
attr_writer :yield_sitemap
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns true if we should yield the sitemap instance to the block, false otherwise.
|
43
|
+
def self.yield_sitemap?
|
44
|
+
!!@yeild_sitemap
|
32
45
|
end
|
33
46
|
|
34
47
|
self.root = File.expand_path(File.join(File.dirname(__FILE__), '../'))
|
@@ -14,21 +14,14 @@ module SitemapGenerator
|
|
14
14
|
class SitemapFile
|
15
15
|
include ActionView::Helpers::NumberHelper
|
16
16
|
include ActionView::Helpers::TextHelper # Rails 2.2.2 fails with missing 'pluralize' otherwise
|
17
|
-
attr_reader :link_count, :filesize, :
|
17
|
+
attr_reader :link_count, :filesize, :location
|
18
18
|
|
19
|
-
# Options
|
19
|
+
# === Options
|
20
20
|
#
|
21
|
-
# <tt>location</tt> a SitemapGenerator::SitemapLocation instance
|
22
|
-
#
|
23
|
-
# <tt>filename</tt> a symbol giving the base of the sitemap fileaname. Default: :sitemap
|
24
|
-
#
|
25
|
-
# <tt>namer</tt> (optional) if provided is used to get the next sitemap filename, overriding :filename
|
21
|
+
# * <tt>location</tt> - a SitemapGenerator::SitemapLocation instance or a Hash of options
|
22
|
+
# from which a SitemapLocation will be created for you.
|
26
23
|
def initialize(opts={})
|
27
|
-
SitemapGenerator::
|
28
|
-
|
29
|
-
@location = opts.delete(:location) || SitemapGenerator::SitemapLocation.new
|
30
|
-
@namer = opts.delete(:namer) || new_namer(opts.delete(:filename))
|
31
|
-
@filename = @location[:filename] = @namer.next
|
24
|
+
@location = opts.is_a?(Hash) ? SitemapGenerator::SitemapLocation.new(opts) : opts
|
32
25
|
@link_count = 0
|
33
26
|
@xml_content = '' # XML urlset content
|
34
27
|
@xml_wrapper_start = <<-HTML
|
@@ -102,20 +95,25 @@ module SitemapGenerator
|
|
102
95
|
|
103
96
|
# Ensure that the directory exists
|
104
97
|
dir = @location.directory
|
105
|
-
path = @location.path
|
106
98
|
if !File.exists?(dir)
|
107
99
|
FileUtils.mkdir_p(dir)
|
108
100
|
elsif !File.directory?(dir)
|
109
101
|
raise SitemapError.new("#{dir} should be a directory!")
|
110
102
|
end
|
111
103
|
|
112
|
-
|
104
|
+
# Write out the file
|
105
|
+
open(@location.path, 'wb') do |file|
|
113
106
|
gz = Zlib::GzipWriter.new(file)
|
114
107
|
gz.write @xml_wrapper_start
|
115
108
|
gz.write @xml_content
|
116
109
|
gz.write @xml_wrapper_end
|
117
110
|
gz.close
|
118
111
|
end
|
112
|
+
|
113
|
+
# Increment the namer (SitemapFile only)
|
114
|
+
@location.namer.next if @location.namer
|
115
|
+
|
116
|
+
# Cleanup and freeze the object
|
119
117
|
@xml_content = @xml_wrapper_start = @xml_wrapper_end = ''
|
120
118
|
freeze
|
121
119
|
end
|
@@ -125,8 +123,10 @@ module SitemapGenerator
|
|
125
123
|
end
|
126
124
|
|
127
125
|
# Return a new instance of the sitemap file with the same options, and the next name in the sequence.
|
128
|
-
def
|
129
|
-
|
126
|
+
def new
|
127
|
+
location = @location.dup
|
128
|
+
location.delete(:filename) if location.namer
|
129
|
+
self.class.new(location)
|
130
130
|
end
|
131
131
|
|
132
132
|
# Return a summary string
|
@@ -136,26 +136,12 @@ module SitemapGenerator
|
|
136
136
|
"+ #{'%-21s' % @location.path_in_public} #{'%13s' % @link_count} links / #{'%10s' % uncompressed_size} / #{'%10s' % compressed_size} gzipped"
|
137
137
|
end
|
138
138
|
|
139
|
-
# Create a new namer given a filename base and set the filename of this sitemap from it.
|
140
|
-
# It is a bit confusing because the setter takes a filename base whereas the getter
|
141
|
-
# returns a full filename including extension.
|
142
|
-
def filename=(base)
|
143
|
-
@namer = new_namer(base)
|
144
|
-
@filename = @location[:filename] = @namer.next
|
145
|
-
end
|
146
|
-
|
147
139
|
protected
|
148
140
|
|
149
|
-
# Return a new namer given a filename base and set the filename of this sitemap from it.
|
150
|
-
# Default filename base is 'sitemap'.
|
151
|
-
def new_namer(base=nil)
|
152
|
-
SitemapGenerator::SitemapNamer.new(base ||= :sitemap)
|
153
|
-
end
|
154
|
-
|
155
141
|
# Return the bytesize length of the string. Ruby 1.8.6 compatible.
|
156
142
|
def bytesize(string)
|
157
143
|
string.respond_to?(:bytesize) ? string.bytesize : string.length
|
158
144
|
end
|
159
145
|
end
|
160
146
|
end
|
161
|
-
end
|
147
|
+
end
|
@@ -1,16 +1,13 @@
|
|
1
1
|
module SitemapGenerator
|
2
2
|
module Builder
|
3
3
|
class SitemapIndexFile < SitemapFile
|
4
|
-
attr_accessor :sitemaps
|
5
4
|
|
5
|
+
# === Options
|
6
|
+
#
|
7
|
+
# * <tt>location</tt> - a SitemapGenerator::SitemapIndexLocation instance or a Hash of options
|
8
|
+
# from which a SitemapLocation will be created for you.
|
6
9
|
def initialize(opts={})
|
7
|
-
@
|
8
|
-
SitemapGenerator::Utilities.assert_valid_keys(opts, @options)
|
9
|
-
|
10
|
-
@location = opts.delete(:location) || SitemapGenerator::SitemapLocation.new
|
11
|
-
@filename = "#{opts.fetch(:filename, :sitemap_index)}.xml.gz"
|
12
|
-
@location[:filename] = @filename
|
13
|
-
|
10
|
+
@location = opts.is_a?(Hash) ? SitemapGenerator::SitemapIndexLocation.new(opts) : opts
|
14
11
|
@link_count = 0
|
15
12
|
@sitemaps_link_count = 0
|
16
13
|
@xml_content = '' # XML urlset content
|
@@ -37,16 +34,19 @@ module SitemapGenerator
|
|
37
34
|
super(SitemapGenerator::Builder::SitemapIndexUrl.new(link, options))
|
38
35
|
end
|
39
36
|
|
37
|
+
# Return a boolean indicating whether the sitemap file can fit another link
|
38
|
+
# of <tt>bytes</tt> bytes in size. You can also pass a string and the
|
39
|
+
# bytesize will be calculated for you.
|
40
|
+
def file_can_fit?(bytes)
|
41
|
+
bytes = bytes.is_a?(String) ? bytesize(bytes) : bytes
|
42
|
+
(@filesize + bytes) < SitemapGenerator::MAX_SITEMAP_FILESIZE && @link_count < SitemapGenerator::MAX_SITEMAP_FILES
|
43
|
+
end
|
44
|
+
|
40
45
|
# Return the total number of links in all sitemaps reference by this index file
|
41
46
|
def total_link_count
|
42
47
|
@sitemaps_link_count
|
43
48
|
end
|
44
49
|
|
45
|
-
# Set a new filename on the instance. Should not include any extensions e.g. :sitemap_index
|
46
|
-
def filename=(filename)
|
47
|
-
@filename = @location[:filename] = "#{filename}_index.xml.gz"
|
48
|
-
end
|
49
|
-
|
50
50
|
# Return a summary string
|
51
51
|
def summary(opts={})
|
52
52
|
uncompressed_size = number_to_human_size(@filesize) rescue "#{@filesize / 8} KB"
|
@@ -60,4 +60,4 @@ module SitemapGenerator
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
|
-
end
|
63
|
+
end
|
@@ -2,8 +2,8 @@ require 'sitemap_generator'
|
|
2
2
|
|
3
3
|
module SitemapGenerator
|
4
4
|
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# Provide a class for evaluating blocks, making the URL helpers from the framework
|
6
|
+
# and API methods available to it.
|
7
7
|
class Interpreter
|
8
8
|
|
9
9
|
if SitemapGenerator.app.rails3?
|
@@ -16,26 +16,54 @@ module SitemapGenerator
|
|
16
16
|
# Call with a block to evaluate a dynamic config. The only method exposed for you is
|
17
17
|
# `add` to add a link to the sitemap object attached to this interpreter.
|
18
18
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
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.reverse_merge!(:link_set => SitemapGenerator::Sitemap)
|
25
|
+
@linkset = opts.delete :link_set
|
26
|
+
@linkset.send(:set_options, opts)
|
27
|
+
eval(&block) if block_given?
|
29
28
|
end
|
30
29
|
|
31
30
|
def add(*args)
|
32
|
-
@
|
31
|
+
@linkset.add(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Start a new group of sitemaps. Any of the options to SitemapGenerator.new may
|
35
|
+
# be passed. Pass a block with calls to +add+ to add links to the sitemaps.
|
36
|
+
#
|
37
|
+
# All groups use the same sitemap index.
|
38
|
+
def group(*args, &block)
|
39
|
+
@linkset.group(*args, &block)
|
33
40
|
end
|
34
41
|
|
35
|
-
# Evaluate the
|
36
|
-
#
|
37
|
-
def
|
38
|
-
|
42
|
+
# Evaluate the block in the interpreter. Pass :yield_sitemap => true to
|
43
|
+
# yield the Interpreter instance to the block...for old-style calling.
|
44
|
+
def eval(opts={}, &block)
|
45
|
+
if block_given?
|
46
|
+
if opts[:yield_sitemap]
|
47
|
+
yield self
|
48
|
+
else
|
49
|
+
instance_eval(&block)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Run the interpreter on a config file using
|
55
|
+
# the default <tt>SitemapGenerator::Sitemap</tt> sitemap object.
|
56
|
+
#
|
57
|
+
# === Options
|
58
|
+
# * <tt>:config_file</tt> - full path to the config file to evaluate.
|
59
|
+
# Default is config/sitemap.rb in your application's root directory.
|
60
|
+
# All other options are passed to +new+.
|
61
|
+
def self.run(opts={}, &block)
|
62
|
+
config_file = opts.delete(:config_file)
|
63
|
+
config_file ||= SitemapGenerator.app.root + 'config/sitemap.rb'
|
64
|
+
interpreter = self.new(opts)
|
65
|
+
interpreter.instance_eval(File.read(config_file), config_file.to_s)
|
66
|
+
interpreter
|
39
67
|
end
|
40
68
|
end
|
41
|
-
end
|
69
|
+
end
|
@@ -4,100 +4,90 @@ require 'builder'
|
|
4
4
|
# which lists all the sitemap files written.
|
5
5
|
module SitemapGenerator
|
6
6
|
class LinkSet
|
7
|
+
@@requires_finalization_opts = [:filename, :sitemaps_path, :sitemaps_namer, :sitemaps_host]
|
8
|
+
@@new_location_opts = [:filename, :sitemaps_path, :sitemaps_namer]
|
7
9
|
|
8
|
-
attr_reader :default_host, :
|
9
|
-
attr_accessor :verbose, :yahoo_app_id, :include_root, :include_index
|
10
|
+
attr_reader :default_host, :sitemaps_path, :filename
|
11
|
+
attr_accessor :verbose, :yahoo_app_id, :include_root, :include_index, :sitemaps_host
|
10
12
|
|
11
|
-
#
|
13
|
+
# Add links to the link set by evaluating the block. The block should
|
14
|
+
# contains calls to sitemap methods like:
|
15
|
+
# * +add+ - Add a link to the current sitemap
|
16
|
+
# * +group+ - Start a new group of sitemaps
|
12
17
|
#
|
13
|
-
#
|
14
|
-
# that the block argument to `add_links` is evaluted within.
|
18
|
+
# == Options
|
15
19
|
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
# Any option supported by +new+ can be passed. The options will be
|
21
|
+
# set on the instance using the accessor methods. This is provided mostly
|
22
|
+
# as a convenience.
|
23
|
+
#
|
24
|
+
# In addition to the options to +new+, the following options are supported:
|
25
|
+
# * <tt>:finalize</tt> - The sitemaps are written as they get full and at the end
|
26
|
+
# of the block. Pass +false+ as the value to prevent the sitemap or sitemap index
|
27
|
+
# from being finalized. Default is +true+.
|
28
|
+
def create(opts={}, &block)
|
29
|
+
@sitemap_index = nil if @sitemap_index && @sitemap_index.finalized? && !@protect_index
|
30
|
+
@sitemap = nil if @sitemap && @sitemap.finalized?
|
31
|
+
set_options(opts)
|
32
|
+
start_time = Time.now if @verbose
|
33
|
+
interpreter.eval(:yield_sitemap => @yield_sitemap || SitemapGenerator.yield_sitemap?, &block)
|
34
|
+
finalize!
|
35
|
+
end_time = Time.now if @verbose
|
36
|
+
puts sitemap_index.stats_summary(:time_taken => end_time - start_time) if @verbose
|
37
|
+
self
|
38
|
+
end
|
29
39
|
|
30
|
-
|
40
|
+
# Dreprecated. Use create.
|
41
|
+
def add_links(&block)
|
42
|
+
@yield_sitemap = true
|
43
|
+
create(&block)
|
44
|
+
@yield_sitemap = false
|
31
45
|
end
|
32
46
|
|
33
47
|
# Constructor
|
34
48
|
#
|
35
|
-
#
|
49
|
+
# == Options:
|
50
|
+
# * <tt>:default_host</tt> - host including protocol to use in all sitemap links
|
51
|
+
# e.g. http://en.google.ca
|
36
52
|
#
|
37
|
-
# <tt
|
38
|
-
# Defaults to
|
53
|
+
# * <tt>:public_path</tt> - Full or relative path to the directory to write sitemaps into.
|
54
|
+
# Defaults to the <tt>public/</tt> directory in your application root directory or
|
55
|
+
# the current working directory.
|
39
56
|
#
|
40
|
-
# <tt
|
57
|
+
# * <tt>:sitemaps_host</tt> - host (including protocol) to use in links to the sitemaps. Useful if your sitemaps
|
58
|
+
# are hosted o different server e.g. 'http://amazon.aws.com/'
|
59
|
+
#
|
60
|
+
# * <tt>:sitemaps_path</tt> - path fragment within public to write sitemaps
|
41
61
|
# to e.g. 'en/'. Sitemaps are written to <tt>public_path</tt> + <tt>sitemaps_path</tt>
|
42
62
|
#
|
43
|
-
# <tt
|
44
|
-
#
|
63
|
+
# * <tt>:filename</tt> - symbol giving the base name for files (default <tt>:sitemap</tt>).
|
64
|
+
# The sitemap names are generated like "#{filename}1.xml.gz", "#{filename}2.xml.gz"
|
65
|
+
# and the index name is like "#{filename}_index.xml.gz".
|
45
66
|
#
|
46
|
-
# <tt
|
47
|
-
# The sitemap names are generated like "#{@filename}1.xml.gzip", "#{@filename}2.xml.gzip"
|
48
|
-
# and the index name is like "#{@filename}_index.xml.gzip".
|
67
|
+
# * <tt>:sitemaps_namer</tt> - A +SitemapNamer+ instance for generating the sitemap names.
|
49
68
|
#
|
50
|
-
# <tt
|
51
|
-
# Default is
|
69
|
+
# * <tt>:include_root</tt> - whether to include the root url i.e. '/' in each group of sitemaps.
|
70
|
+
# Default is true.
|
52
71
|
#
|
53
|
-
# <tt
|
54
|
-
# Default is
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
warn "Deprecated. Please call with an options hash instead."
|
60
|
-
[:public_path, :sitemaps_path, :default_host, :filename].each_with_index.inject({}) do |hash, arg|
|
61
|
-
hash[arg[0]] = args[arg[1]]
|
62
|
-
hash
|
63
|
-
end
|
64
|
-
else
|
65
|
-
args.first || {}
|
66
|
-
end
|
67
|
-
|
68
|
-
# Option defaults
|
72
|
+
# * <tt>:include_index</tt> - whether to include the sitemap index URL in each group of sitemaps.
|
73
|
+
# Default is true.
|
74
|
+
#
|
75
|
+
# * <tt>:verbose</tt> - If +true+, output a summary line for each sitemap and sitemap
|
76
|
+
# index that is created. Default is +false+.
|
77
|
+
def initialize(options={})
|
69
78
|
options.reverse_merge!({
|
70
79
|
:include_root => true,
|
71
80
|
:include_index => true,
|
72
81
|
:filename => :sitemap,
|
73
|
-
:
|
74
|
-
:sitemaps_path => nil
|
82
|
+
:verbose => false
|
75
83
|
})
|
76
84
|
options.each_pair { |k, v| instance_variable_set("@#{k}".to_sym, v) }
|
77
85
|
|
78
|
-
|
79
|
-
#
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
:host => @default_host
|
84
|
-
)
|
85
|
-
end
|
86
|
-
|
87
|
-
# Entry point for users.
|
88
|
-
#
|
89
|
-
# Called within the user's eval'ed sitemap config file. Add links to sitemap files
|
90
|
-
# passing a block. This instance is passed in as an argument. You can call
|
91
|
-
# `add` on it to add links.
|
92
|
-
#
|
93
|
-
# Example:
|
94
|
-
# add_links do |sitemap|
|
95
|
-
# sitemap.add '/'
|
96
|
-
# end
|
97
|
-
def add_links
|
98
|
-
sitemap.add('/', :lastmod => Time.now, :changefreq => 'always', :priority => 1.0, :host => @location.host) if include_root
|
99
|
-
sitemap.add(sitemap_index, :lastmod => Time.now, :changefreq => 'always', :priority => 1.0) if include_index
|
100
|
-
yield self
|
86
|
+
# If an index is passed in, protect it from modification.
|
87
|
+
# Sitemaps can be added to the index but nothing else can be changed.
|
88
|
+
if options[:sitemap_index]
|
89
|
+
@protect_index = true
|
90
|
+
end
|
101
91
|
end
|
102
92
|
|
103
93
|
# Add a link to a Sitemap. If a new Sitemap is required, one will be created for
|
@@ -107,15 +97,69 @@ module SitemapGenerator
|
|
107
97
|
# options - see README.
|
108
98
|
# host - host for the link, defaults to your <tt>default_host</tt>.
|
109
99
|
def add(link, options={})
|
110
|
-
|
100
|
+
add_default_links if !@added_default_links
|
101
|
+
sitemap.add(link, options.reverse_merge!(:host => @default_host))
|
111
102
|
rescue SitemapGenerator::SitemapFullError
|
112
|
-
finalize_sitemap
|
103
|
+
finalize_sitemap!
|
113
104
|
retry
|
114
105
|
rescue SitemapGenerator::SitemapFinalizedError
|
115
|
-
@sitemap = sitemap.
|
106
|
+
@sitemap = sitemap.new
|
116
107
|
retry
|
117
108
|
end
|
118
109
|
|
110
|
+
# Create a new group of sitemaps. Returns a new LinkSet instance with options set on it.
|
111
|
+
#
|
112
|
+
# All groups share this LinkSet's sitemap index, which is not modified by any of the options
|
113
|
+
# passed to +group+.
|
114
|
+
#
|
115
|
+
# === Options
|
116
|
+
# Any of the options to LinkSet.new. Except for <tt>:public_path</tt> which is shared
|
117
|
+
# by all groups.
|
118
|
+
#
|
119
|
+
# The current options are inherited by the new group of sitemaps. The only exceptions
|
120
|
+
# being <tt>:include_index</tt> and <tt>:include_root</tt> which default to +false+.
|
121
|
+
#
|
122
|
+
# Pass a block to add links to the new LinkSet. If you pass a block the sitemaps will
|
123
|
+
# be finalized when the block returns.
|
124
|
+
#
|
125
|
+
# If you are not changing any of the location settings like <tt>filename<tt>,
|
126
|
+
# <tt>sitemaps_path</tt>, <tt>sitemaps_host</tt> or <tt>sitemaps_namer</tt>
|
127
|
+
# the current sitemap will be used in the group. All of the options you have
|
128
|
+
# specified which affect the way the links are generated will still be applied
|
129
|
+
# for the duration of the group.
|
130
|
+
def group(opts={}, &block)
|
131
|
+
@created_group = true
|
132
|
+
original_opts = opts.dup
|
133
|
+
|
134
|
+
if (@@requires_finalization_opts & original_opts.keys).empty?
|
135
|
+
# If no new filename or path is specified reuse the default sitemap file.
|
136
|
+
# A new location object will be set on it for the duration of the group.
|
137
|
+
opts[:sitemap] = sitemap
|
138
|
+
elsif original_opts.key?(:sitemaps_host) && (@@new_location_opts & original_opts.keys).empty?
|
139
|
+
# If no location options are provided we are creating the next sitemap in the
|
140
|
+
# current series, so finalize and inherit the namer.
|
141
|
+
finalize_sitemap!
|
142
|
+
opts[:sitemaps_namer] = sitemaps_namer
|
143
|
+
end
|
144
|
+
|
145
|
+
opts = options_for_group(opts)
|
146
|
+
@group = SitemapGenerator::LinkSet.new(opts)
|
147
|
+
if opts.key?(:sitemap)
|
148
|
+
# If the group is sharing the current sitemap, set the
|
149
|
+
# new location options on the location object.
|
150
|
+
@original_location = @sitemap.location.dup
|
151
|
+
@sitemap.location.merge!(@group.sitemap_location)
|
152
|
+
if block_given?
|
153
|
+
@group.interpreter.eval(:yield_sitemap => @yield_sitemap || SitemapGenerator.yield_sitemap?, &block)
|
154
|
+
@sitemap.location.merge!(@original_location)
|
155
|
+
end
|
156
|
+
elsif block_given?
|
157
|
+
@group.interpreter.eval(:yield_sitemap => @yield_sitemap || SitemapGenerator.yield_sitemap?, &block)
|
158
|
+
@group.finalize_sitemap!
|
159
|
+
end
|
160
|
+
@group
|
161
|
+
end
|
162
|
+
|
119
163
|
# Ping search engines.
|
120
164
|
#
|
121
165
|
# @see http://en.wikipedia.org/wiki/Sitemap_index
|
@@ -135,7 +179,9 @@ module SitemapGenerator
|
|
135
179
|
search_engines.each do |engine, link|
|
136
180
|
next if engine == :yahoo && !self.yahoo_app_id
|
137
181
|
begin
|
138
|
-
|
182
|
+
Timeout::timeout(10) {
|
183
|
+
open(link)
|
184
|
+
}
|
139
185
|
puts "Successful ping of #{engine.to_s.titleize}" if verbose
|
140
186
|
rescue Timeout::Error, StandardError => e
|
141
187
|
puts "Ping failed for #{engine.to_s.titleize}: #{e.inspect} (URL #{link})" if verbose
|
@@ -159,84 +205,218 @@ module SitemapGenerator
|
|
159
205
|
sitemap_index.total_link_count
|
160
206
|
end
|
161
207
|
|
162
|
-
#
|
163
|
-
#
|
164
|
-
|
165
|
-
|
166
|
-
update_location_info(:host, value)
|
208
|
+
# Return the host to use in links to the sitemap files. This defaults to your
|
209
|
+
# +default_host+.
|
210
|
+
def sitemaps_host
|
211
|
+
@sitemaps_host || @default_host
|
167
212
|
end
|
168
213
|
|
169
|
-
#
|
170
|
-
|
171
|
-
|
172
|
-
#
|
173
|
-
# Example: 'tmp/' if you don't want to generate in public for some reason.
|
174
|
-
#
|
175
|
-
# Set to nil to use the current directory.
|
176
|
-
def public_path=(value)
|
177
|
-
update_location_info(:public_path, value)
|
214
|
+
# Lazy-initialize a sitemap instance when it's accessed
|
215
|
+
def sitemap
|
216
|
+
@sitemap ||= SitemapGenerator::Builder::SitemapFile.new(sitemap_location)
|
178
217
|
end
|
179
218
|
|
180
|
-
#
|
181
|
-
|
182
|
-
|
183
|
-
def sitemaps_path=(value)
|
184
|
-
update_location_info(:sitemaps_path, value)
|
219
|
+
# Lazy-initialize a sitemap index instance when it's accessed
|
220
|
+
def sitemap_index
|
221
|
+
@sitemap_index ||= SitemapGenerator::Builder::SitemapIndexFile.new(sitemap_index_location)
|
185
222
|
end
|
186
223
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
update_sitemap_info(:filename, value)
|
224
|
+
def finalize!
|
225
|
+
finalize_sitemap!
|
226
|
+
finalize_sitemap_index!
|
191
227
|
end
|
192
228
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
229
|
+
protected
|
230
|
+
|
231
|
+
# Set each option on this instance using accessor methods. This will affect
|
232
|
+
# both the sitemap and the sitemap index.
|
233
|
+
def set_options(opts={})
|
234
|
+
opts.each_pair do |key, value|
|
235
|
+
send("#{key}=", value)
|
236
|
+
end
|
199
237
|
end
|
200
238
|
|
201
|
-
#
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
239
|
+
# Given +opts+, return a hash of options prepped for creating a new group from this LinkSet.
|
240
|
+
# If <tt>:public_path</tt> is present in +opts+ it is removed because groups cannot
|
241
|
+
# change the public path.
|
242
|
+
def options_for_group(opts)
|
243
|
+
opts.delete(:public_path)
|
244
|
+
opts.reverse_merge!(
|
245
|
+
:include_index => false,
|
246
|
+
:include_root => false,
|
247
|
+
:sitemap_index => sitemap_index
|
206
248
|
)
|
249
|
+
|
250
|
+
# Reverse merge the current settings
|
251
|
+
current_settings = [
|
252
|
+
:include_root,
|
253
|
+
:include_index,
|
254
|
+
:sitemaps_path,
|
255
|
+
:public_path,
|
256
|
+
:sitemaps_host,
|
257
|
+
:verbose,
|
258
|
+
:default_host
|
259
|
+
].inject({}) do |hash, key|
|
260
|
+
if value = instance_variable_get(:"@#{key}")
|
261
|
+
hash[key] = value
|
262
|
+
end
|
263
|
+
hash
|
264
|
+
end
|
265
|
+
opts.reverse_merge!(current_settings)
|
266
|
+
opts
|
207
267
|
end
|
208
268
|
|
209
|
-
|
269
|
+
# Add default links if those options are turned on. Record the fact that we have done so
|
270
|
+
# in an instance variable.
|
271
|
+
def add_default_links
|
272
|
+
sitemap.add('/', :lastmod => Time.now, :changefreq => 'always', :priority => 1.0, :host => @default_host) if include_root
|
273
|
+
sitemap.add(sitemap_index, :lastmod => Time.now, :changefreq => 'always', :priority => 1.0) if include_index
|
274
|
+
@added_default_links = true
|
275
|
+
end
|
210
276
|
|
211
277
|
# Finalize a sitemap by including it in the index and outputting a summary line.
|
212
278
|
# Do nothing if it has already been finalized.
|
213
|
-
|
214
|
-
|
279
|
+
#
|
280
|
+
# Don't finalize if the sitemap is empty and a group has been created. The reason
|
281
|
+
# being that the group will have written out its sitemap.
|
282
|
+
#
|
283
|
+
# Add the default links if they have not been added yet and no groups have been created.
|
284
|
+
# If the default links haven't been added we know that the sitemap is empty,
|
285
|
+
# because they are added on the first call to add(). This ensure that if the
|
286
|
+
# block passed to create() is empty the default links are still included in the
|
287
|
+
# sitemap.
|
288
|
+
def finalize_sitemap!
|
289
|
+
add_default_links if !@added_default_links && !@created_group
|
290
|
+
return if sitemap.finalized? || sitemap.empty? && @created_group
|
215
291
|
sitemap_index.add(sitemap)
|
216
292
|
puts sitemap.summary if verbose
|
217
293
|
end
|
218
294
|
|
219
295
|
# Finalize a sitemap index and output a summary line. Do nothing if it has already
|
220
296
|
# been finalized.
|
221
|
-
def finalize_sitemap_index
|
222
|
-
return if sitemap_index.finalized?
|
297
|
+
def finalize_sitemap_index!
|
298
|
+
return if @protect_index || sitemap_index.finalized?
|
223
299
|
sitemap_index.finalize!
|
224
300
|
puts sitemap_index.summary if verbose
|
225
301
|
end
|
226
302
|
|
227
|
-
#
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
sitemap.send("#{attribute}=", value) if @sitemap && !@sitemap.finalized?
|
303
|
+
# Return the interpreter linked to this instance.
|
304
|
+
def interpreter
|
305
|
+
require 'sitemap_generator/interpreter'
|
306
|
+
@interpreter ||= SitemapGenerator::Interpreter.new(:link_set => self)
|
232
307
|
end
|
233
308
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
309
|
+
module LocationHelpers
|
310
|
+
public
|
311
|
+
|
312
|
+
# Set the host name, including protocol, that will be used by default on each
|
313
|
+
# of your sitemap links. You can pass a different host in your options to `add`
|
314
|
+
# if you need to change it on a per-link basis.
|
315
|
+
def default_host=(value)
|
316
|
+
@default_host = value
|
317
|
+
update_location_info(:host, value)
|
318
|
+
end
|
319
|
+
|
320
|
+
# Set the public_path. This path gives the location of your public directory.
|
321
|
+
# The default is the public/ directory in your Rails root. Or if Rails is not
|
322
|
+
# found, it defaults to public/ in the current directory (of the process).
|
323
|
+
#
|
324
|
+
# Example: 'tmp/' if you don't want to generate in public for some reason.
|
325
|
+
#
|
326
|
+
# Set to nil to use the current directory.
|
327
|
+
def public_path=(value)
|
328
|
+
@public_path = Pathname.new(value.to_s)
|
329
|
+
@public_path = SitemapGenerator.app.root + @public_path if @public_path.relative?
|
330
|
+
update_location_info(:public_path, @public_path)
|
331
|
+
@public_path
|
332
|
+
end
|
333
|
+
|
334
|
+
# Return a Pathname with the full path to the public directory
|
335
|
+
def public_path
|
336
|
+
@public_path ||= self.send(:public_path=, 'public/')
|
337
|
+
end
|
338
|
+
|
339
|
+
# Set the sitemaps_path. This path gives the location to write sitemaps to
|
340
|
+
# relative to your public_path.
|
341
|
+
# Example: 'sitemaps/' to generate your sitemaps in 'public/sitemaps/'.
|
342
|
+
def sitemaps_path=(value)
|
343
|
+
@sitemaps_path = value
|
344
|
+
update_location_info(:sitemaps_path, value)
|
345
|
+
end
|
346
|
+
|
347
|
+
# Set the host name, including protocol, that will be used on all links to your sitemap
|
348
|
+
# files. Useful when the server that hosts the sitemaps is not on the same host as
|
349
|
+
# the links in the sitemap.
|
350
|
+
def sitemaps_host=(value)
|
351
|
+
@sitemaps_host = value
|
352
|
+
update_location_info(:host, value)
|
353
|
+
end
|
354
|
+
|
355
|
+
# Set the filename base to use when generating sitemaps and sitemap indexes.
|
356
|
+
# The index name will be +value+ with <tt>_index.xml.gz</tt> appended.
|
357
|
+
# === Example
|
358
|
+
# <tt>filename = :sitemap</tt>
|
359
|
+
def filename=(value)
|
360
|
+
@filename = value
|
361
|
+
self.sitemaps_namer = SitemapGenerator::SitemapNamer.new(@filename)
|
362
|
+
self.sitemap_index_namer = SitemapGenerator::SitemapIndexNamer.new("#{@filename}_index")
|
363
|
+
end
|
364
|
+
|
365
|
+
# Set the namer to use when generating SitemapFiles (does not apply to the
|
366
|
+
# SitemapIndexFile)
|
367
|
+
def sitemaps_namer=(value)
|
368
|
+
@sitemaps_namer = value
|
369
|
+
@sitemap.location[:namer] = value if @sitemap && !@sitemap.finalized?
|
370
|
+
end
|
371
|
+
|
372
|
+
# Return the current sitemaps namer object. If it not set, looks for it on
|
373
|
+
# the current sitemap and if there is no sitemap, creates a new one using
|
374
|
+
# the current filename.
|
375
|
+
def sitemaps_namer
|
376
|
+
@sitemaps_namer ||= @sitemap && @sitemap.location.namer || SitemapGenerator::SitemapNamer.new(@filename)
|
377
|
+
end
|
378
|
+
|
379
|
+
# Set the namer to use when generating SitemapFiles (does not apply to the
|
380
|
+
# SitemapIndexFile)
|
381
|
+
def sitemap_index_namer=(value)
|
382
|
+
@sitemap_index_namer = value
|
383
|
+
@sitemap_index.location[:namer] = value if @sitemap_index && !@sitemap_index.finalized? && !@protect_index
|
384
|
+
end
|
385
|
+
|
386
|
+
def sitemap_index_namer
|
387
|
+
@sitemap_index_namer ||= @sitemap_index && @sitemap_index.location.namer || SitemapGenerator::SitemapIndexNamer.new("#{@filename}_index")
|
388
|
+
end
|
389
|
+
|
390
|
+
# Return a new +SitemapLocation+ instance with the current options included
|
391
|
+
def sitemap_location
|
392
|
+
SitemapGenerator::SitemapLocation.new(
|
393
|
+
:host => sitemaps_host,
|
394
|
+
:namer => sitemaps_namer,
|
395
|
+
:public_path => public_path,
|
396
|
+
:sitemaps_path => @sitemaps_path
|
397
|
+
)
|
398
|
+
end
|
399
|
+
|
400
|
+
# Return a new +SitemapIndexLocation+ instance with the current options included
|
401
|
+
def sitemap_index_location
|
402
|
+
SitemapGenerator::SitemapLocation.new(
|
403
|
+
:host => sitemaps_host,
|
404
|
+
:namer => sitemap_index_namer,
|
405
|
+
:public_path => public_path,
|
406
|
+
:sitemaps_path => @sitemaps_path
|
407
|
+
)
|
408
|
+
end
|
409
|
+
|
410
|
+
protected
|
411
|
+
|
412
|
+
# Update the given attribute on the current sitemap index and sitemap file location objects.
|
413
|
+
# But don't create the index or sitemap files yet if they are not already created.
|
414
|
+
def update_location_info(attribute, value, opts={})
|
415
|
+
opts.reverse_merge!(:include_index => !@protect_index)
|
416
|
+
@sitemap_index.location[attribute] = value if opts[:include_index] && @sitemap_index && !@sitemap_index.finalized?
|
417
|
+
@sitemap.location[attribute] = value if @sitemap && !@sitemap.finalized?
|
418
|
+
end
|
240
419
|
end
|
420
|
+
include LocationHelpers
|
241
421
|
end
|
242
|
-
end
|
422
|
+
end
|