ftbpro_sitemap_generator 5.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +35 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1139 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/lib/capistrano/sitemap_generator.rb +1 -0
- data/lib/capistrano/tasks/sitemap_generator.cap +36 -0
- data/lib/sitemap_generator.rb +85 -0
- data/lib/sitemap_generator/adapters.rb +0 -0
- data/lib/sitemap_generator/adapters/file_adapter.rb +43 -0
- data/lib/sitemap_generator/adapters/fog_adapter.rb +28 -0
- data/lib/sitemap_generator/adapters/s3_adapter.rb +41 -0
- data/lib/sitemap_generator/adapters/wave_adapter.rb +21 -0
- data/lib/sitemap_generator/application.rb +49 -0
- data/lib/sitemap_generator/builder.rb +8 -0
- data/lib/sitemap_generator/builder/sitemap_file.rb +172 -0
- data/lib/sitemap_generator/builder/sitemap_index_file.rb +149 -0
- data/lib/sitemap_generator/builder/sitemap_index_url.rb +28 -0
- data/lib/sitemap_generator/builder/sitemap_url.rb +250 -0
- data/lib/sitemap_generator/core_ext.rb +3 -0
- data/lib/sitemap_generator/core_ext/big_decimal.rb +45 -0
- data/lib/sitemap_generator/core_ext/numeric.rb +48 -0
- data/lib/sitemap_generator/helpers/number_helper.rb +237 -0
- data/lib/sitemap_generator/interpreter.rb +80 -0
- data/lib/sitemap_generator/link_set.rb +677 -0
- data/lib/sitemap_generator/railtie.rb +7 -0
- data/lib/sitemap_generator/sitemap_location.rb +192 -0
- data/lib/sitemap_generator/sitemap_namer.rb +75 -0
- data/lib/sitemap_generator/tasks.rb +53 -0
- data/lib/sitemap_generator/templates.rb +41 -0
- data/lib/sitemap_generator/utilities.rb +181 -0
- data/lib/tasks/sitemap_generator_tasks.rake +1 -0
- data/rails/install.rb +2 -0
- data/rails/uninstall.rb +2 -0
- data/spec/blueprint.rb +15 -0
- data/spec/files/sitemap.create.rb +12 -0
- data/spec/files/sitemap.groups.rb +49 -0
- data/spec/sitemap_generator/adapters/s3_adapter_spec.rb +23 -0
- data/spec/sitemap_generator/alternate_sitemap_spec.rb +79 -0
- data/spec/sitemap_generator/application_spec.rb +69 -0
- data/spec/sitemap_generator/builder/sitemap_file_spec.rb +110 -0
- data/spec/sitemap_generator/builder/sitemap_index_file_spec.rb +124 -0
- data/spec/sitemap_generator/builder/sitemap_index_url_spec.rb +28 -0
- data/spec/sitemap_generator/builder/sitemap_url_spec.rb +186 -0
- data/spec/sitemap_generator/core_ext/bigdecimal_spec.rb +20 -0
- data/spec/sitemap_generator/core_ext/numeric_spec.rb +43 -0
- data/spec/sitemap_generator/file_adaptor_spec.rb +20 -0
- data/spec/sitemap_generator/geo_sitemap_spec.rb +30 -0
- data/spec/sitemap_generator/helpers/number_helper_spec.rb +196 -0
- data/spec/sitemap_generator/interpreter_spec.rb +90 -0
- data/spec/sitemap_generator/link_set_spec.rb +864 -0
- data/spec/sitemap_generator/mobile_sitemap_spec.rb +27 -0
- data/spec/sitemap_generator/news_sitemap_spec.rb +42 -0
- data/spec/sitemap_generator/pagemap_sitemap_spec.rb +57 -0
- data/spec/sitemap_generator/sitemap_generator_spec.rb +582 -0
- data/spec/sitemap_generator/sitemap_groups_spec.rb +144 -0
- data/spec/sitemap_generator/sitemap_location_spec.rb +210 -0
- data/spec/sitemap_generator/sitemap_namer_spec.rb +96 -0
- data/spec/sitemap_generator/templates_spec.rb +24 -0
- data/spec/sitemap_generator/utilities/existence_spec.rb +26 -0
- data/spec/sitemap_generator/utilities/hash_spec.rb +57 -0
- data/spec/sitemap_generator/utilities/rounding_spec.rb +31 -0
- data/spec/sitemap_generator/utilities_spec.rb +101 -0
- data/spec/sitemap_generator/video_sitemap_spec.rb +117 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/file_macros.rb +39 -0
- data/spec/support/schemas/siteindex.xsd +73 -0
- data/spec/support/schemas/sitemap-geo.xsd +41 -0
- data/spec/support/schemas/sitemap-mobile.xsd +32 -0
- data/spec/support/schemas/sitemap-news.xsd +159 -0
- data/spec/support/schemas/sitemap-pagemap.xsd +97 -0
- data/spec/support/schemas/sitemap-video.xsd +643 -0
- data/spec/support/schemas/sitemap.xsd +115 -0
- data/spec/support/xml_macros.rb +67 -0
- data/templates/sitemap.rb +27 -0
- metadata +226 -0
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.require
|
3
|
+
|
4
|
+
desc 'Default: run spec tests.'
|
5
|
+
task :default => :spec
|
6
|
+
|
7
|
+
require "rspec/core/rake_task"
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
+
spec.pattern = Dir.glob(['spec/sitemap_generator/**/*'])
|
10
|
+
spec.rspec_opts = ['--backtrace']
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# Helpers
|
15
|
+
#
|
16
|
+
|
17
|
+
def name; @name ||= Dir['*.gemspec'].first.split('.').first end
|
18
|
+
def version; File.read('VERSION').chomp end
|
19
|
+
def gemspec_file; "#{name}.gemspec" end
|
20
|
+
def gem_file; "#{name}-#{version}.gem" end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Release Tasks
|
24
|
+
# @see https://github.com/mojombo/rakegem
|
25
|
+
#
|
26
|
+
|
27
|
+
desc "Create tag v#{version}, build the gem and push to Git"
|
28
|
+
task :release => :build do
|
29
|
+
unless `git branch` =~ /^\* master$/
|
30
|
+
puts "You must be on the master branch to release!"
|
31
|
+
exit!
|
32
|
+
end
|
33
|
+
sh "git tag v#{version}"
|
34
|
+
sh "git push origin master --tags"
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Build #{gem_file} into the pkg/ directory"
|
38
|
+
task :build do
|
39
|
+
sh "mkdir -p pkg"
|
40
|
+
sh "gem build #{gemspec_file}"
|
41
|
+
sh "mv #{gem_file} pkg"
|
42
|
+
sh "bundle --local"
|
43
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
5.0.8
|
@@ -0,0 +1 @@
|
|
1
|
+
load File.expand_path(File.join('..', 'tasks', 'sitemap_generator.cap'), __FILE__)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
namespace :deploy do
|
2
|
+
namespace :sitemap do
|
3
|
+
desc 'Create sitemap and ping search engines'
|
4
|
+
task :refresh do
|
5
|
+
on roles :web do
|
6
|
+
within release_path do
|
7
|
+
with rails_env: fetch(:rails_env) do
|
8
|
+
execute :rake, "sitemap:refresh"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Create sitemap without pinging search engines'
|
15
|
+
task :create do
|
16
|
+
on roles :web do
|
17
|
+
within release_path do
|
18
|
+
with rails_env: fetch(:rails_env) do
|
19
|
+
execute :rake, "sitemap:create"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'Clean up sitemaps in sitemap_generator path'
|
26
|
+
task :clean do
|
27
|
+
on roles :web do
|
28
|
+
within release_path do
|
29
|
+
with rails_env: fetch(:rails_env) do
|
30
|
+
execute :rake, "sitemap:clean"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'sitemap_generator/sitemap_namer'
|
2
|
+
require 'sitemap_generator/builder'
|
3
|
+
require 'sitemap_generator/link_set'
|
4
|
+
require 'sitemap_generator/templates'
|
5
|
+
require 'sitemap_generator/utilities'
|
6
|
+
require 'sitemap_generator/application'
|
7
|
+
require 'sitemap_generator/adapters'
|
8
|
+
require 'sitemap_generator/sitemap_location'
|
9
|
+
|
10
|
+
module SitemapGenerator
|
11
|
+
autoload(:Interpreter, 'sitemap_generator/interpreter')
|
12
|
+
autoload(:FileAdapter, 'sitemap_generator/adapters/file_adapter')
|
13
|
+
autoload(:S3Adapter, 'sitemap_generator/adapters/s3_adapter')
|
14
|
+
autoload(:WaveAdapter, 'sitemap_generator/adapters/wave_adapter')
|
15
|
+
autoload(:FogAdapter, 'sitemap_generator/adapters/fog_adapter')
|
16
|
+
autoload(:BigDecimal, 'sitemap_generator/core_ext/big_decimal')
|
17
|
+
autoload(:Numeric, 'sitemap_generator/core_ext/numeric')
|
18
|
+
|
19
|
+
SitemapError = Class.new(StandardError)
|
20
|
+
SitemapFullError = Class.new(SitemapError)
|
21
|
+
SitemapFinalizedError = Class.new(SitemapError)
|
22
|
+
|
23
|
+
Utilities.with_warnings(nil) do
|
24
|
+
VERSION = File.read(File.dirname(__FILE__) + "/../VERSION").strip
|
25
|
+
MAX_SITEMAP_FILES = 50_000 # max sitemap links per index file
|
26
|
+
MAX_SITEMAP_LINKS = 50_000 # max links per sitemap
|
27
|
+
MAX_SITEMAP_IMAGES = 1_000 # max images per url
|
28
|
+
MAX_SITEMAP_NEWS = 1_000 # max news sitemap per index_file
|
29
|
+
MAX_SITEMAP_FILESIZE = 10_000_000 # bytes
|
30
|
+
SCHEMAS = {
|
31
|
+
'geo' => 'http://www.google.com/geo/schemas/sitemap/1.0',
|
32
|
+
'image' => 'http://www.google.com/schemas/sitemap-image/1.1',
|
33
|
+
'mobile' => 'http://www.google.com/schemas/sitemap-mobile/1.0',
|
34
|
+
'news' => 'http://www.google.com/schemas/sitemap-news/0.9',
|
35
|
+
'pagemap' => 'http://www.google.com/schemas/sitemap-pagemap/1.0',
|
36
|
+
'video' => 'http://www.google.com/schemas/sitemap-video/1.1'
|
37
|
+
}
|
38
|
+
SCHEMA_LOCATION = "http://www.sitemaps.org/schemas/sitemap/0.9
|
39
|
+
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
|
40
|
+
|
41
|
+
# Lazy-initialize the LinkSet instance
|
42
|
+
Sitemap = (Class.new do
|
43
|
+
def method_missing(*args, &block)
|
44
|
+
(@link_set ||= reset!).send(*args, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Use a new LinkSet instance
|
48
|
+
def reset!
|
49
|
+
@link_set = LinkSet.new
|
50
|
+
end
|
51
|
+
end).new
|
52
|
+
end
|
53
|
+
|
54
|
+
class << self
|
55
|
+
attr_accessor :root, :app, :templates
|
56
|
+
attr_writer :yield_sitemap, :verbose
|
57
|
+
end
|
58
|
+
|
59
|
+
# Global default for the verbose setting.
|
60
|
+
def self.verbose
|
61
|
+
if @verbose.nil?
|
62
|
+
@verbose = if SitemapGenerator::Utilities.truthy?(ENV['VERBOSE'])
|
63
|
+
true
|
64
|
+
elsif SitemapGenerator::Utilities.falsy?(ENV['VERBOSE'])
|
65
|
+
false
|
66
|
+
else
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
else
|
70
|
+
@verbose
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns true if we should yield the sitemap instance to the block, false otherwise.
|
75
|
+
def self.yield_sitemap?
|
76
|
+
!!@yield_sitemap
|
77
|
+
end
|
78
|
+
|
79
|
+
self.root = File.expand_path(File.join(File.dirname(__FILE__), '../')) # Root of the install dir, not the Rails app
|
80
|
+
self.templates = SitemapGenerator::Templates.new(self.root)
|
81
|
+
self.app = SitemapGenerator::Application.new
|
82
|
+
end
|
83
|
+
|
84
|
+
require 'sitemap_generator/railtie' if SitemapGenerator.app.rails3?
|
85
|
+
|
File without changes
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module SitemapGenerator
|
2
|
+
# Class for writing out data to a file.
|
3
|
+
class FileAdapter
|
4
|
+
|
5
|
+
# Write data to a file.
|
6
|
+
# @param location - File object giving the full path and file name of the file.
|
7
|
+
# If the location specifies a directory(ies) which does not exist, the directory(ies)
|
8
|
+
# will be created for you. If the location path ends with `.gz` the data will be
|
9
|
+
# compressed prior to being written out. Otherwise the data will be written out
|
10
|
+
# unchanged.
|
11
|
+
# @param raw_data - data to write to the file.
|
12
|
+
def write(location, raw_data)
|
13
|
+
# Ensure that the directory exists
|
14
|
+
dir = location.directory
|
15
|
+
if !File.exists?(dir)
|
16
|
+
FileUtils.mkdir_p(dir)
|
17
|
+
elsif !File.directory?(dir)
|
18
|
+
raise SitemapError.new("#{dir} should be a directory!")
|
19
|
+
end
|
20
|
+
|
21
|
+
stream = open(location.path, 'wb')
|
22
|
+
if location.path.to_s =~ /.gz$/
|
23
|
+
gzip(stream, raw_data)
|
24
|
+
else
|
25
|
+
plain(stream, raw_data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Write `data` to a stream, passing the data through a GzipWriter
|
30
|
+
# to compress it.
|
31
|
+
def gzip(stream, data)
|
32
|
+
gz = Zlib::GzipWriter.new(stream)
|
33
|
+
gz.write data
|
34
|
+
gz.close
|
35
|
+
end
|
36
|
+
|
37
|
+
# Write `data` to a stream as is.
|
38
|
+
def plain(stream, data)
|
39
|
+
stream.write data
|
40
|
+
stream.close
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
begin
|
2
|
+
require 'fog'
|
3
|
+
rescue LoadError
|
4
|
+
raise LoadError.new("Missing required 'fog'. Please 'gem install fog' and require it in your application.")
|
5
|
+
end
|
6
|
+
|
7
|
+
module SitemapGenerator
|
8
|
+
class FogAdapter
|
9
|
+
|
10
|
+
def initialize(opts = {})
|
11
|
+
@fog_credentials = opts[:fog_credentials]
|
12
|
+
@fog_directory = opts[:fog_directory]
|
13
|
+
end
|
14
|
+
|
15
|
+
# Call with a SitemapLocation and string data
|
16
|
+
def write(location, raw_data)
|
17
|
+
SitemapGenerator::FileAdapter.new.write(location, raw_data)
|
18
|
+
|
19
|
+
storage = Fog::Storage.new(@fog_credentials)
|
20
|
+
directory = storage.directories.new(:key => @fog_directory)
|
21
|
+
directory.files.create(
|
22
|
+
:key => location.path_in_public,
|
23
|
+
:body => File.open(location.path),
|
24
|
+
:public => true
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
begin
|
2
|
+
require 'fog'
|
3
|
+
rescue LoadError
|
4
|
+
raise LoadError.new("Missing required 'fog'. Please 'gem install fog' and require it in your application.")
|
5
|
+
end
|
6
|
+
|
7
|
+
module SitemapGenerator
|
8
|
+
class S3Adapter
|
9
|
+
|
10
|
+
def initialize(opts = {})
|
11
|
+
@aws_access_key_id = opts[:aws_access_key_id] || ENV['AWS_ACCESS_KEY_ID']
|
12
|
+
@aws_secret_access_key = opts[:aws_secret_access_key] || ENV['AWS_SECRET_ACCESS_KEY']
|
13
|
+
@fog_provider = opts[:fog_provider] || ENV['FOG_PROVIDER']
|
14
|
+
@fog_directory = opts[:fog_directory] || ENV['FOG_DIRECTORY']
|
15
|
+
@fog_region = opts[:fog_region] || ENV['FOG_REGION']
|
16
|
+
@fog_path_style = opts[:fog_path_style] || ENV['FOG_PATH_STYLE']
|
17
|
+
end
|
18
|
+
|
19
|
+
# Call with a SitemapLocation and string data
|
20
|
+
def write(location, raw_data)
|
21
|
+
SitemapGenerator::FileAdapter.new.write(location, raw_data)
|
22
|
+
|
23
|
+
credentials = {
|
24
|
+
:aws_access_key_id => @aws_access_key_id,
|
25
|
+
:aws_secret_access_key => @aws_secret_access_key,
|
26
|
+
:provider => @fog_provider,
|
27
|
+
}
|
28
|
+
credentials[:region] = @fog_region if @fog_region
|
29
|
+
credentials[:path_style] = @fog_path_style if @fog_path_style
|
30
|
+
|
31
|
+
storage = Fog::Storage.new(credentials)
|
32
|
+
directory = storage.directories.new(:key => @fog_directory)
|
33
|
+
directory.files.create(
|
34
|
+
:key => location.path_in_public,
|
35
|
+
:body => File.open(location.path),
|
36
|
+
:public => true
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'carrierwave'
|
3
|
+
rescue LoadError
|
4
|
+
raise LoadError.new("Missing required 'carrierwave'. Please 'gem install carrierwave' and require it in your application.")
|
5
|
+
end
|
6
|
+
|
7
|
+
module SitemapGenerator
|
8
|
+
class WaveAdapter < ::CarrierWave::Uploader::Base
|
9
|
+
attr_accessor :store_dir
|
10
|
+
|
11
|
+
# Call with a SitemapLocation and string data
|
12
|
+
def write(location, raw_data)
|
13
|
+
SitemapGenerator::FileAdapter.new.write(location, raw_data)
|
14
|
+
directory = File.dirname(location.path_in_public)
|
15
|
+
if directory != '.'
|
16
|
+
self.store_dir = directory
|
17
|
+
end
|
18
|
+
store!(open(location.path, 'rb'))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module SitemapGenerator
|
4
|
+
class Application
|
5
|
+
def rails?
|
6
|
+
defined?(Rails)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns a boolean indicating whether this environment is Rails 3
|
10
|
+
#
|
11
|
+
# @return [Boolean]
|
12
|
+
def rails3?
|
13
|
+
rails? && Rails.version.to_f >= 3
|
14
|
+
rescue
|
15
|
+
false # Rails.version defined in 2.1.0
|
16
|
+
end
|
17
|
+
|
18
|
+
def root
|
19
|
+
Pathname.new(rails_root || Dir.getwd)
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
# Returns the root of the Rails application,
|
25
|
+
# if this is running in a Rails context.
|
26
|
+
# Returns `nil` if no such root is defined.
|
27
|
+
#
|
28
|
+
# @return [String, nil]
|
29
|
+
def rails_root
|
30
|
+
if defined?(::Rails.root)
|
31
|
+
return ::Rails.root.to_s if ::Rails.root
|
32
|
+
raise "ERROR: Rails.root is nil!"
|
33
|
+
end
|
34
|
+
return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
|
35
|
+
return nil
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the environment of the Rails application,
|
39
|
+
# if this is running in a Rails context.
|
40
|
+
# Returns `nil` if no such environment is defined.
|
41
|
+
#
|
42
|
+
# @return [String, nil]
|
43
|
+
def rails_env
|
44
|
+
return ::Rails.env.to_s if defined?(::Rails.env)
|
45
|
+
return RAILS_ENV.to_s if defined?(RAILS_ENV)
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'sitemap_generator/builder/sitemap_file'
|
2
|
+
require 'sitemap_generator/builder/sitemap_index_file'
|
3
|
+
require 'sitemap_generator/builder/sitemap_url'
|
4
|
+
require 'sitemap_generator/builder/sitemap_index_url'
|
5
|
+
|
6
|
+
module SitemapGenerator::Builder
|
7
|
+
LinkHolder = Struct.new(:link, :options)
|
8
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'sitemap_generator/helpers/number_helper'
|
4
|
+
|
5
|
+
module SitemapGenerator
|
6
|
+
module Builder
|
7
|
+
#
|
8
|
+
# General Usage:
|
9
|
+
#
|
10
|
+
# sitemap = SitemapFile.new(:location => SitemapLocation.new(...))
|
11
|
+
# sitemap.add('/', { ... }) <- add a link to the sitemap
|
12
|
+
# sitemap.finalize! <- write the sitemap file and freeze the object to protect it from further modification
|
13
|
+
#
|
14
|
+
class SitemapFile
|
15
|
+
include SitemapGenerator::Helpers::NumberHelper
|
16
|
+
attr_reader :link_count, :filesize, :location, :news_count
|
17
|
+
|
18
|
+
# === Options
|
19
|
+
#
|
20
|
+
# * <tt>location</tt> - a SitemapGenerator::SitemapLocation instance or a Hash of options
|
21
|
+
# from which a SitemapLocation will be created for you.
|
22
|
+
def initialize(opts={}, schemas, schema_location)
|
23
|
+
@location = opts.is_a?(Hash) ? SitemapGenerator::SitemapLocation.new(opts) : opts
|
24
|
+
@link_count = 0
|
25
|
+
@news_count = 0
|
26
|
+
@xml_content = '' # XML urlset content
|
27
|
+
@schemas = schemas
|
28
|
+
@schema_location = schema_location
|
29
|
+
@xml_wrapper_start = xml_wrapper_start.gsub(/\s+/, ' ').gsub(/ *> */, '>').strip.slice(1..-2)
|
30
|
+
@xml_wrapper_end = %q[</urlset>]
|
31
|
+
@filesize = SitemapGenerator::Utilities.bytesize(@xml_wrapper_start) + SitemapGenerator::Utilities.bytesize(@xml_wrapper_end)
|
32
|
+
@written = false
|
33
|
+
@reserved_name = nil # holds the name reserved from the namer
|
34
|
+
@frozen = false # rather than actually freeze, use this boolean
|
35
|
+
end
|
36
|
+
|
37
|
+
def xml_wrapper_start
|
38
|
+
wrapper_start = '<?xml version="1.0" encoding="UTF-8"?>
|
39
|
+
<urlset
|
40
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
|
41
|
+
schema_location = "xsi:schemaLocation=\"#{@schema_location}\""
|
42
|
+
general_schema = 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"'
|
43
|
+
customized_schemas = @schemas.collect do |schema, content|
|
44
|
+
"xmlns:#{schema}=\"#{content}\""
|
45
|
+
end
|
46
|
+
wrapper_end = 'xmlns:xhtml="http://www.w3.org/1999/xhtml">'
|
47
|
+
xml_start = [wrapper_start, schema_location, general_schema, customized_schemas, wrapper_end].join(" ")
|
48
|
+
return <<-HTML
|
49
|
+
"#{xml_start}"
|
50
|
+
HTML
|
51
|
+
end
|
52
|
+
|
53
|
+
# If a name has been reserved, use the last modified time from the file.
|
54
|
+
# Otherwise return nil. We don't want to prematurely assign a name
|
55
|
+
# for this sitemap if one has not yet been reserved, because we may
|
56
|
+
# mess up the name-assignment sequence.
|
57
|
+
def lastmod
|
58
|
+
File.mtime(location.path) if location.reserved_name?
|
59
|
+
rescue
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def empty?
|
64
|
+
@link_count == 0
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return a boolean indicating whether the sitemap file can fit another link
|
68
|
+
# of <tt>bytes</tt> bytes in size. You can also pass a string and the
|
69
|
+
# bytesize will be calculated for you.
|
70
|
+
def file_can_fit?(bytes)
|
71
|
+
bytes = bytes.is_a?(String) ? SitemapGenerator::Utilities.bytesize(bytes) : bytes
|
72
|
+
(@filesize + bytes) < SitemapGenerator::MAX_SITEMAP_FILESIZE && @link_count < SitemapGenerator::MAX_SITEMAP_LINKS && @news_count < SitemapGenerator::MAX_SITEMAP_NEWS
|
73
|
+
end
|
74
|
+
|
75
|
+
# Add a link to the sitemap file.
|
76
|
+
#
|
77
|
+
# If a link cannot be added, for example if the file is too large or the link
|
78
|
+
# limit has been reached, a SitemapGenerator::SitemapFullError exception is raised
|
79
|
+
# and the sitemap is finalized.
|
80
|
+
#
|
81
|
+
# If the Sitemap has already been finalized a SitemapGenerator::SitemapFinalizedError
|
82
|
+
# exception is raised.
|
83
|
+
#
|
84
|
+
# Return the new link count.
|
85
|
+
#
|
86
|
+
# Call with:
|
87
|
+
# sitemap_url - a SitemapUrl instance
|
88
|
+
# sitemap, options - a Sitemap instance and options hash
|
89
|
+
# path, options - a path for the URL and options hash. For supported options
|
90
|
+
# see the SitemapGenerator::Builder::SitemapUrl class.
|
91
|
+
#
|
92
|
+
# The link added to the sitemap will use the host from its location object
|
93
|
+
# if no host has been specified.
|
94
|
+
def add(link, options={})
|
95
|
+
raise SitemapGenerator::SitemapFinalizedError if finalized?
|
96
|
+
|
97
|
+
sitemap_url = if link.is_a?(SitemapUrl)
|
98
|
+
link
|
99
|
+
else
|
100
|
+
options[:host] ||= @location.host
|
101
|
+
SitemapUrl.new(link, options)
|
102
|
+
end
|
103
|
+
|
104
|
+
xml = sitemap_url.to_xml
|
105
|
+
raise SitemapGenerator::SitemapFullError if !file_can_fit?(xml)
|
106
|
+
|
107
|
+
if sitemap_url.news?
|
108
|
+
@news_count += 1
|
109
|
+
end
|
110
|
+
|
111
|
+
# Add the XML to the sitemap
|
112
|
+
@xml_content << xml
|
113
|
+
@filesize += SitemapGenerator::Utilities.bytesize(xml)
|
114
|
+
@link_count += 1
|
115
|
+
end
|
116
|
+
|
117
|
+
# "Freeze" this object. Actually just flags it as frozen.
|
118
|
+
#
|
119
|
+
# A SitemapGenerator::SitemapFinalizedError exception is raised if the Sitemap
|
120
|
+
# has already been finalized.
|
121
|
+
def finalize!
|
122
|
+
raise SitemapGenerator::SitemapFinalizedError if finalized?
|
123
|
+
@frozen = true
|
124
|
+
end
|
125
|
+
|
126
|
+
def finalized?
|
127
|
+
@frozen
|
128
|
+
end
|
129
|
+
|
130
|
+
# Write out the sitemap and free up memory.
|
131
|
+
#
|
132
|
+
# All the xml content in the instance is cleared, but attributes like
|
133
|
+
# <tt>filesize</tt> are still available.
|
134
|
+
#
|
135
|
+
# A SitemapGenerator::SitemapError exception is raised if the file has
|
136
|
+
# already been written.
|
137
|
+
def write
|
138
|
+
raise SitemapGenerator::SitemapError.new("Sitemap already written!") if written?
|
139
|
+
finalize! unless finalized?
|
140
|
+
reserve_name
|
141
|
+
@location.write(@xml_wrapper_start + @xml_content + @xml_wrapper_end, link_count)
|
142
|
+
@xml_content = @xml_wrapper_start = @xml_wrapper_end = ''
|
143
|
+
@written = true
|
144
|
+
end
|
145
|
+
|
146
|
+
# Return true if this file has been written out to disk
|
147
|
+
def written?
|
148
|
+
@written
|
149
|
+
end
|
150
|
+
|
151
|
+
# Reserve a name from the namer unless one has already been reserved.
|
152
|
+
# Safe to call more than once.
|
153
|
+
def reserve_name
|
154
|
+
@reserved_name ||= @location.reserve_name
|
155
|
+
end
|
156
|
+
|
157
|
+
# Return a boolean indicating whether a name has been reserved
|
158
|
+
def reserved_name?
|
159
|
+
!!@reserved_name
|
160
|
+
end
|
161
|
+
|
162
|
+
# Return a new instance of the sitemap file with the same options,
|
163
|
+
# and the next name in the sequence.
|
164
|
+
def new
|
165
|
+
location = @location.dup
|
166
|
+
location.delete(:filename) if location.namer
|
167
|
+
self.class.new(location, @schemas, @schema_location)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|