sitemap_generator 1.5.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|