xml-sitemap 1.3.1 → 1.3.2
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/.travis.yml +0 -1
- data/README.md +2 -2
- data/lib/xml-sitemap/index.rb +1 -1
- data/lib/xml-sitemap/item.rb +83 -10
- data/lib/xml-sitemap/map.rb +25 -25
- data/lib/xml-sitemap/options.rb +1 -0
- data/lib/xml-sitemap/render_engine.rb +95 -18
- data/lib/xml-sitemap/version.rb +1 -1
- data/spec/fixtures/encoded_image_map.xml +0 -13
- data/spec/fixtures/encoded_map.xml +0 -3
- data/spec/fixtures/encoded_video_map.xml +53 -0
- data/spec/fixtures/saved_map.xml +0 -7
- data/spec/fixtures/simple_map.xml +1 -1
- data/spec/index_spec.rb +1 -1
- data/spec/map_spec.rb +68 -16
- metadata +5 -4
data/README.md
CHANGED
@@ -38,7 +38,7 @@ map = XmlSitemap::Map.new('domain.com') do |m|
|
|
38
38
|
# You can drop leading slash, it will be automatically added
|
39
39
|
m.add 'page2'
|
40
40
|
|
41
|
-
# Set the page priority
|
41
|
+
# Set the page priority
|
42
42
|
m.add 'page3', :priority => 0.2
|
43
43
|
|
44
44
|
# Specify last modification date and update frequiency
|
@@ -73,7 +73,7 @@ map = XmlSitemap.map('foobar.com')
|
|
73
73
|
|
74
74
|
By default XmlSitemap creates a map with link to homepage of your domain.
|
75
75
|
|
76
|
-
Homepage priority is `1.0`.
|
76
|
+
Homepage priority is `1.0`.
|
77
77
|
|
78
78
|
List of available update periods:
|
79
79
|
|
data/lib/xml-sitemap/index.rb
CHANGED
@@ -21,7 +21,7 @@ module XmlSitemap
|
|
21
21
|
# map - XmlSitemap::Map instance
|
22
22
|
#
|
23
23
|
def add(map)
|
24
|
-
raise ArgumentError, 'XmlSitemap::Map object
|
24
|
+
raise ArgumentError, 'XmlSitemap::Map object required!' unless map.kind_of?(XmlSitemap::Map)
|
25
25
|
raise ArgumentError, 'Map is empty!' if map.empty?
|
26
26
|
|
27
27
|
@maps << {
|
data/lib/xml-sitemap/item.rb
CHANGED
@@ -5,13 +5,16 @@ module XmlSitemap
|
|
5
5
|
# ISO8601 regex from here: http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
|
6
6
|
ISO8601_REGEX = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/
|
7
7
|
|
8
|
-
attr_reader :target, :updated, :priority, :changefreq, :validate_time, :image_location, :image_caption, :image_geolocation, :image_title, :image_license
|
9
|
-
|
8
|
+
attr_reader :target, :updated, :priority, :changefreq, :validate_time, :image_location, :image_caption, :image_geolocation, :image_title, :image_license,
|
9
|
+
:video_thumbnail_location, :video_title, :video_description, :video_content_location, :video_player_location,
|
10
|
+
:video_duration, :video_expiration_date, :video_rating, :video_view_count, :video_publication_date, :video_family_friendly, :video_category,
|
11
|
+
:video_restriction, :video_gallery_location, :video_price, :video_requires_subscription, :video_uploader, :video_platform, :video_live
|
12
|
+
|
10
13
|
def initialize(target, opts={})
|
11
14
|
@target = target.to_s.strip
|
12
15
|
@updated = opts[:updated] || Time.now
|
13
|
-
@priority = opts[:priority]
|
14
|
-
@changefreq = opts[:period]
|
16
|
+
@priority = opts[:priority]
|
17
|
+
@changefreq = opts[:period]
|
15
18
|
@validate_time = (opts[:validate_time] != false)
|
16
19
|
|
17
20
|
# Refer to http://support.google.com/webmasters/bin/answer.py?hl=en&answer=178636 for requirement to support images in sitemap
|
@@ -21,6 +24,35 @@ module XmlSitemap
|
|
21
24
|
@image_title = opts[:image_title]
|
22
25
|
@image_license = opts[:image_license]
|
23
26
|
|
27
|
+
# Refer to http://support.google.com/webmasters/bin/answer.py?hl=en&answer=80472&topic=10079&ctx=topic#2 for requirement to support videos in sitemap
|
28
|
+
@video_thumbnail_location = opts[:video_thumbnail_location]
|
29
|
+
@video_title = opts[:video_title]
|
30
|
+
@video_description = opts[:video_description]
|
31
|
+
@video_content_location = opts[:video_content_location]
|
32
|
+
@video_player_location = opts[:video_player_location]
|
33
|
+
@video_duration = opts[:video_duration]
|
34
|
+
@video_expiration_date = opts[:video_expiration_date]
|
35
|
+
@video_rating = opts[:video_rating]
|
36
|
+
@video_view_count = opts[:video_view_count]
|
37
|
+
@video_publication_date = opts[:video_publication_date]
|
38
|
+
@video_family_friendly = opts[:video_family_friendly]
|
39
|
+
# tag
|
40
|
+
@video_category = opts[:video_category]
|
41
|
+
@video_restriction = opts[:video_restriction]
|
42
|
+
@video_gallery_location = opts[:video_gallery_location]
|
43
|
+
@video_price = opts[:video_price]
|
44
|
+
@video_requires_subscription = opts[:video_requires_subscription]
|
45
|
+
@video_uploader = opts[:video_uploader]
|
46
|
+
@video_platform = opts[:video_platform]
|
47
|
+
@video_live = opts[:video_live]
|
48
|
+
|
49
|
+
if @changefreq
|
50
|
+
@changefreq = @changefreq.to_sym
|
51
|
+
unless XmlSitemap::PERIODS.include?(@changefreq)
|
52
|
+
raise ArgumentError, "Invalid :period value '#{@changefreq}'"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
24
56
|
unless @updated.kind_of?(Time) || @updated.kind_of?(Date) || @updated.kind_of?(String)
|
25
57
|
raise ArgumentError, "Time, Date, or ISO8601 String required for :updated!"
|
26
58
|
end
|
@@ -29,15 +61,36 @@ module XmlSitemap
|
|
29
61
|
raise ArgumentError, "String provided to :updated did not match ISO8601 standard!"
|
30
62
|
end
|
31
63
|
|
32
|
-
@
|
33
|
-
|
34
|
-
|
64
|
+
@updated = @updated.to_time if @updated.kind_of?(Date)
|
65
|
+
|
66
|
+
##############################################################################################
|
67
|
+
##############################################################################################
|
68
|
+
|
69
|
+
unless @video_expiration_date.kind_of?(Time) || @video_expiration_date.kind_of?(Date) || @video_expiration_date.kind_of?(String)
|
70
|
+
raise ArgumentError, "Time, Date, or ISO8601 String required for :video_expiration_date!" unless @video_expiration_date.nil?
|
35
71
|
end
|
36
72
|
|
37
|
-
|
73
|
+
if @validate_time && @video_expiration_date.kind_of?(String) && !(@video_expiration_date =~ ISO8601_REGEX)
|
74
|
+
raise ArgumentError, "String provided to :video_expiration_date did not match ISO8601 standard!"
|
75
|
+
end
|
76
|
+
|
77
|
+
@video_expiration_date = @video_expiration_date.to_time if @video_expiration_date.kind_of?(Date)
|
78
|
+
|
79
|
+
##############################################################################################
|
80
|
+
##############################################################################################
|
81
|
+
|
82
|
+
unless @video_publication_date.kind_of?(Time) || @video_publication_date.kind_of?(Date) || @video_publication_date.kind_of?(String)
|
83
|
+
raise ArgumentError, "Time, Date, or ISO8601 String required for :video_publication_date!" unless @video_publication_date.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
if @validate_time && @video_publication_date.kind_of?(String) && !(@video_publication_date =~ ISO8601_REGEX)
|
87
|
+
raise ArgumentError, "String provided to :video_publication_date did not match ISO8601 standard!"
|
88
|
+
end
|
89
|
+
|
90
|
+
@video_publication_date = @video_publication_date.to_time if @video_publication_date.kind_of?(Date)
|
38
91
|
end
|
39
92
|
|
40
|
-
# Returns the timestamp value for
|
93
|
+
# Returns the timestamp value of lastmod for renderer
|
41
94
|
#
|
42
95
|
def lastmod_value
|
43
96
|
if @updated.kind_of?(Time)
|
@@ -46,5 +99,25 @@ module XmlSitemap
|
|
46
99
|
@updated.to_s
|
47
100
|
end
|
48
101
|
end
|
102
|
+
|
103
|
+
# Returns the timestamp value of video:expiration_date for renderer
|
104
|
+
#
|
105
|
+
def video_expiration_date_value
|
106
|
+
if @video_expiration_date.kind_of?(Time)
|
107
|
+
@video_expiration_date.utc.iso8601
|
108
|
+
else
|
109
|
+
@video_expiration_date.to_s
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Returns the timestamp value of video:publication_date for renderer
|
114
|
+
#
|
115
|
+
def video_publication_date_value
|
116
|
+
if @video_publication_date.kind_of?(Time)
|
117
|
+
@video_publication_date.utc.iso8601
|
118
|
+
else
|
119
|
+
@video_publication_date.to_s
|
120
|
+
end
|
121
|
+
end
|
49
122
|
end
|
50
|
-
end
|
123
|
+
end
|
data/lib/xml-sitemap/map.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
module XmlSitemap
|
1
|
+
module XmlSitemap
|
2
2
|
class Map
|
3
3
|
include XmlSitemap::RenderEngine
|
4
|
-
|
4
|
+
|
5
5
|
attr_reader :domain, :items
|
6
6
|
attr_reader :buffer
|
7
7
|
attr_reader :created_at
|
8
8
|
attr_reader :root
|
9
9
|
attr_reader :group
|
10
|
-
|
10
|
+
|
11
11
|
# Initializa a new Map instance
|
12
12
|
#
|
13
13
|
# domain - Primary domain for the map (required)
|
@@ -23,70 +23,70 @@ module XmlSitemap
|
|
23
23
|
def initialize(domain, opts={})
|
24
24
|
@domain = domain.to_s.strip
|
25
25
|
raise ArgumentError, 'Domain required!' if @domain.empty?
|
26
|
-
|
26
|
+
|
27
27
|
@created_at = opts[:time] || Time.now.utc
|
28
28
|
@secure = opts[:secure] || false
|
29
29
|
@home = opts.key?(:home) ? opts[:home] : true
|
30
30
|
@root = opts.key?(:root) ? opts[:root] : true
|
31
31
|
@group = opts[:group] || "sitemap"
|
32
32
|
@items = []
|
33
|
-
|
33
|
+
|
34
34
|
self.add('/', :priority => 1.0) if @home === true
|
35
|
-
|
35
|
+
|
36
36
|
yield self if block_given?
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Adds a new item to the map
|
40
40
|
#
|
41
41
|
# target - Path or url
|
42
42
|
# opts - Item options
|
43
43
|
#
|
44
44
|
# opts[:updated] - Lastmod property of the item
|
45
|
-
# opts[:period] - Update frequency.
|
46
|
-
# opts[:priority] - Item priority.
|
45
|
+
# opts[:period] - Update frequency.
|
46
|
+
# opts[:priority] - Item priority.
|
47
47
|
# opts[:validate_time] - Skip time validation if want to insert raw strings.
|
48
|
-
#
|
48
|
+
#
|
49
49
|
def add(target, opts={})
|
50
50
|
raise RuntimeError, 'Only up to 50k records allowed!' if @items.size > 50000
|
51
51
|
raise ArgumentError, 'Target required!' if target.nil?
|
52
52
|
raise ArgumentError, 'Target is empty!' if target.to_s.strip.empty?
|
53
|
-
|
53
|
+
|
54
54
|
url = process_target(target)
|
55
|
-
|
55
|
+
|
56
56
|
if url.length > 2048
|
57
57
|
raise ArgumentError, "Target can't be longer than 2,048 characters!"
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
opts[:updated] = @created_at unless opts.key?(:updated)
|
61
61
|
item = XmlSitemap::Item.new(url, opts)
|
62
62
|
@items << item
|
63
63
|
item
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
# Get map items count
|
67
67
|
#
|
68
68
|
def size
|
69
69
|
@items.size
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# Returns true if sitemap does not have any items
|
73
73
|
#
|
74
74
|
def empty?
|
75
75
|
@items.empty?
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
# Generate full url for path
|
79
79
|
#
|
80
80
|
def url(path='')
|
81
81
|
"#{@secure ? 'https' : 'http'}://#{@domain}#{path}"
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
# Get full url for index
|
85
85
|
#
|
86
86
|
def index_url(offset, secure)
|
87
87
|
"#{secure ? 'https' : 'http'}://#{@domain}/#{@group}-#{offset}.xml"
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
# Render XML
|
91
91
|
#
|
92
92
|
# method - Pick a render engine (:builder, :nokogiri, :string).
|
@@ -102,7 +102,7 @@ module XmlSitemap
|
|
102
102
|
render_string
|
103
103
|
end
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
# Render XML sitemap into the file
|
107
107
|
#
|
108
108
|
# path - Output filename
|
@@ -114,15 +114,15 @@ module XmlSitemap
|
|
114
114
|
def render_to(path, options={})
|
115
115
|
overwrite = options[:overwrite] == true || true
|
116
116
|
compress = options[:gzip] == true || false
|
117
|
-
|
117
|
+
|
118
118
|
path = File.expand_path(path)
|
119
119
|
path << ".gz" unless path =~ /\.gz\z/i if compress
|
120
|
-
|
120
|
+
|
121
121
|
if File.exists?(path) && !overwrite
|
122
122
|
raise RuntimeError, "File already exists and not overwritable!"
|
123
123
|
end
|
124
|
-
|
125
|
-
File.open(path, '
|
124
|
+
|
125
|
+
File.open(path, 'wb') do |f|
|
126
126
|
unless compress
|
127
127
|
f.write(self.render)
|
128
128
|
else
|
@@ -132,9 +132,9 @@ module XmlSitemap
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
end
|
135
|
-
|
135
|
+
|
136
136
|
protected
|
137
|
-
|
137
|
+
|
138
138
|
# Process target path or url
|
139
139
|
#
|
140
140
|
def process_target(str)
|
data/lib/xml-sitemap/options.rb
CHANGED
@@ -14,6 +14,7 @@ module XmlSitemap
|
|
14
14
|
'xsi:schemaLocation' => "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd",
|
15
15
|
'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
|
16
16
|
'xmlns:image' => "http://www.google.com/schemas/sitemap-image/1.1",
|
17
|
+
'xmlns:video' => "http://www.google.com/schemas/sitemap-video/1.1",
|
17
18
|
'xmlns' => "http://www.sitemaps.org/schemas/sitemap/0.9"
|
18
19
|
}.freeze
|
19
20
|
|
@@ -15,19 +15,45 @@ module XmlSitemap
|
|
15
15
|
s.url do |u|
|
16
16
|
u.loc item.target
|
17
17
|
|
18
|
+
# Format and image tag specifications found at http://support.google.com/webmasters/bin/answer.py?hl=en&answer=178636
|
18
19
|
if item.image_location
|
19
20
|
u["image"].image do |a|
|
20
|
-
a["image"].loc
|
21
|
-
a["image"].caption
|
22
|
-
a["image"].title
|
23
|
-
a["image"].license
|
24
|
-
a["image"].geo_location
|
21
|
+
a["image"].loc item.image_location
|
22
|
+
a["image"].caption item.image_caption if item.image_caption
|
23
|
+
a["image"].title item.image_title if item.image_title
|
24
|
+
a["image"].license item.image_license if item.image_license
|
25
|
+
a["image"].geo_location item.image_geolocation if item.image_geolocation
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Format and video tag specifications found at http://support.google.com/webmasters/bin/answer.py?hl=en&answer=80472&topic=10079&ctx=topic#2
|
30
|
+
if item.video_thumbnail_location && item.video_title && item.video_description && (item.video_content_location || item.video_player_location)
|
31
|
+
u["video"].video do |a|
|
32
|
+
a["video"].thumbnail_loc item.video_thumbnail_location
|
33
|
+
a["video"].title item.video_title
|
34
|
+
a["video"].description item.video_description
|
35
|
+
a["video"].content_loc item.video_content_location if item.video_content_location
|
36
|
+
a["video"].player_loc item.video_player_location if item.video_player_location
|
37
|
+
a["video"].duration item.video_duration.to_s if item.video_duration
|
38
|
+
a["video"].expiration_date item.video_expiration_date_value if item.video_expiration_date
|
39
|
+
a["video"].rating item.video_rating.to_s if item.video_rating
|
40
|
+
a["video"].view_count item.video_view_count.to_s if item.video_view_count
|
41
|
+
a["video"].publication_date item.video_publication_date_value if item.video_publication_date
|
42
|
+
a["video"].family_friendly item.video_family_friendly if item.video_family_friendly
|
43
|
+
a["video"].category item.video_category if item.video_category
|
44
|
+
a["video"].restriction item.video_restriction, :relationship => "allow" if item.video_restriction
|
45
|
+
a["video"].gallery_loc item.video_gallery_location if item.video_gallery_location
|
46
|
+
a["video"].price item.video_price.to_s, :currency => "USD" if item.video_price
|
47
|
+
a["video"].requires_subscription item.video_requires_subscription if item.video_requires_subscription
|
48
|
+
a["video"].uploader item.video_uploader if item.video_uploader
|
49
|
+
a["video"].platform item.video_platform, :relationship => "allow" if item.video_platform
|
50
|
+
a["video"].live item.video_live if item.video_live
|
25
51
|
end
|
26
52
|
end
|
27
53
|
|
28
54
|
u.lastmod item.lastmod_value
|
29
|
-
u.changefreq item.changefreq.to_s
|
30
|
-
u.priority item.priority.to_s
|
55
|
+
u.changefreq item.changefreq.to_s if item.changefreq
|
56
|
+
u.priority item.priority.to_s if item.priority
|
31
57
|
end
|
32
58
|
end
|
33
59
|
}
|
@@ -46,19 +72,45 @@ module XmlSitemap
|
|
46
72
|
s.url do |u|
|
47
73
|
u.loc item.target
|
48
74
|
|
75
|
+
# Format and image tag specifications found at http://support.google.com/webmasters/bin/answer.py?hl=en&answer=178636
|
49
76
|
if item.image_location
|
50
77
|
u.image :image do |a|
|
51
|
-
a.tag!
|
52
|
-
a.tag!
|
53
|
-
a.tag!
|
54
|
-
a.tag!
|
55
|
-
a.tag!
|
78
|
+
a.tag! "image:loc", CGI::escapeHTML(item.image_location)
|
79
|
+
a.tag! "image:caption", CGI::escapeHTML(item.image_caption) if item.image_caption
|
80
|
+
a.tag! "image:title", CGI::escapeHTML(item.image_title) if item.image_title
|
81
|
+
a.tag! "image:license", CGI::escapeHTML(item.image_license) if item.image_license
|
82
|
+
a.tag! "image:geo_location", CGI::escapeHTML(item.image_geolocation) if item.image_geolocation
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Format and video tag specifications found at http://support.google.com/webmasters/bin/answer.py?hl=en&answer=80472&topic=10079&ctx=topic#2
|
87
|
+
if item.video_thumbnail_location && item.video_title && item.video_description && (item.video_content_location || item.video_player_location)
|
88
|
+
u.video :video do |a|
|
89
|
+
a.tag! "video:thumbnail_loc", CGI::escapeHTML(item.video_thumbnail_location)
|
90
|
+
a.tag! "video:title", CGI::escapeHTML(item.video_title)
|
91
|
+
a.tag! "video:description", CGI::escapeHTML(item.video_description)
|
92
|
+
a.tag! "video:content_loc", CGI::escapeHTML(item.video_content_location) if item.video_content_location
|
93
|
+
a.tag! "video:player_loc", CGI::escapeHTML(item.video_player_location) if item.video_player_location
|
94
|
+
a.tag! "video:duration", CGI::escapeHTML(item.video_duration.to_s) if item.video_duration
|
95
|
+
a.tag! "video:expiration_date", CGI::escapeHTML(item.video_expiration_date_value) if item.video_expiration_date
|
96
|
+
a.tag! "video:rating", CGI::escapeHTML(item.video_rating.to_s) if item.video_rating
|
97
|
+
a.tag! "video:view_count", CGI::escapeHTML(item.video_view_count.to_s) if item.video_view_count
|
98
|
+
a.tag! "video:publication_date", CGI::escapeHTML(item.video_publication_date_value) if item.video_publication_date
|
99
|
+
a.tag! "video:family_friendly", CGI::escapeHTML(item.video_family_friendly) if item.video_family_friendly
|
100
|
+
a.tag! "video:category", CGI::escapeHTML(item.video_category) if item.video_category
|
101
|
+
a.tag! "video:restriction", CGI::escapeHTML(item.video_restriction), :relationship => "allow" if item.video_restriction
|
102
|
+
a.tag! "video:gallery_loc", CGI::escapeHTML(item.video_gallery_location) if item.video_gallery_location
|
103
|
+
a.tag! "video:price", CGI::escapeHTML(item.video_price.to_s), :currency => "USD" if item.video_price
|
104
|
+
a.tag! "video:requires_subscription", CGI::escapeHTML(item.video_requires_subscription) if item.video_requires_subscription
|
105
|
+
a.tag! "video:uploader", CGI::escapeHTML(item.video_uploader) if item.video_uploader
|
106
|
+
a.tag! "video:platform", CGI::escapeHTML(item.video_platform), :relationship => "allow" if item.video_platform
|
107
|
+
a.tag! "video:live", CGI::escapeHTML(item.video_live) if item.video_live
|
56
108
|
end
|
57
109
|
end
|
58
110
|
|
59
111
|
u.lastmod item.lastmod_value
|
60
|
-
u.changefreq item.changefreq.to_s
|
61
|
-
u.priority item.priority.to_s
|
112
|
+
u.changefreq item.changefreq.to_s if item.changefreq
|
113
|
+
u.priority item.priority.to_s if item.priority
|
62
114
|
end
|
63
115
|
end
|
64
116
|
}.to_s
|
@@ -80,7 +132,7 @@ module XmlSitemap
|
|
80
132
|
item_string = " <url>\n"
|
81
133
|
item_string << " <loc>#{CGI::escapeHTML(item.target)}</loc>\n"
|
82
134
|
|
83
|
-
# Format and image tag specifications found
|
135
|
+
# Format and image tag specifications found at http://support.google.com/webmasters/bin/answer.py?hl=en&answer=178636
|
84
136
|
if item.image_location
|
85
137
|
item_string << " <image:image>\n"
|
86
138
|
item_string << " <image:loc>#{CGI::escapeHTML(item.image_location)}</image:loc>\n"
|
@@ -91,9 +143,34 @@ module XmlSitemap
|
|
91
143
|
item_string << " </image:image>\n"
|
92
144
|
end
|
93
145
|
|
146
|
+
# Format and video tag specifications found at http://support.google.com/webmasters/bin/answer.py?hl=en&answer=80472&topic=10079&ctx=topic#2
|
147
|
+
if item.video_thumbnail_location && item.video_title && item.video_description && (item.video_content_location || item.video_player_location)
|
148
|
+
item_string << " <video:video>\n"
|
149
|
+
item_string << " <video:thumbnail_loc>#{CGI::escapeHTML(item.video_thumbnail_location)}</video:thumbnail_loc>\n"
|
150
|
+
item_string << " <video:title>#{CGI::escapeHTML(item.video_title)}</video:title>\n"
|
151
|
+
item_string << " <video:description>#{CGI::escapeHTML(item.video_description)}</video:description>\n"
|
152
|
+
item_string << " <video:content_loc>#{CGI::escapeHTML(item.video_content_location)}</video:content_loc>\n" if item.video_content_location
|
153
|
+
item_string << " <video:player_loc>#{CGI::escapeHTML(item.video_player_location)}</video:player_loc>\n" if item.video_player_location
|
154
|
+
item_string << " <video:duration>#{CGI::escapeHTML(item.video_duration.to_s)}</video:duration>\n" if item.video_duration
|
155
|
+
item_string << " <video:expiration_date>#{item.video_expiration_date_value}</video:expiration_date>\n" if item.video_expiration_date
|
156
|
+
item_string << " <video:rating>#{CGI::escapeHTML(item.video_rating.to_s)}</video:rating>\n" if item.video_rating
|
157
|
+
item_string << " <video:view_count>#{CGI::escapeHTML(item.video_view_count.to_s)}</video:view_count>\n" if item.video_view_count
|
158
|
+
item_string << " <video:publication_date>#{item.video_publication_date_value}</video:publication_date>\n" if item.video_publication_date
|
159
|
+
item_string << " <video:family_friendly>#{CGI::escapeHTML(item.video_family_friendly)}</video:family_friendly>\n" if item.video_family_friendly
|
160
|
+
item_string << " <video:category>#{CGI::escapeHTML(item.video_category)}</video:category>\n" if item.video_category
|
161
|
+
item_string << " <video:restriction relationship=\"allow\">#{CGI::escapeHTML(item.video_restriction)}</video:restriction>\n" if item.video_restriction
|
162
|
+
item_string << " <video:gallery_loc>#{CGI::escapeHTML(item.video_gallery_location)}</video:gallery_loc>\n" if item.video_gallery_location
|
163
|
+
item_string << " <video:price currency=\"USD\">#{CGI::escapeHTML(item.video_price.to_s)}</video:price>\n" if item.video_price
|
164
|
+
item_string << " <video:requires_subscription>#{CGI::escapeHTML(item.video_requires_subscription)}</video:requires_subscription>\n" if item.video_requires_subscription
|
165
|
+
item_string << " <video:uploader>#{CGI::escapeHTML(item.video_uploader)}</video:uploader>\n" if item.video_uploader
|
166
|
+
item_string << " <video:platform relationship=\"allow\">#{CGI::escapeHTML(item.video_platform)}</video:platform>\n" if item.video_platform
|
167
|
+
item_string << " <video:live>#{CGI::escapeHTML(item.video_live)}</video:live>\n" if item.video_live
|
168
|
+
item_string << " </video:video>\n"
|
169
|
+
end
|
170
|
+
|
94
171
|
item_string << " <lastmod>#{item.lastmod_value}</lastmod>\n"
|
95
|
-
item_string << " <changefreq>#{item.changefreq}</changefreq>\n"
|
96
|
-
item_string << " <priority>#{item.priority}</priority>\n"
|
172
|
+
item_string << " <changefreq>#{item.changefreq}</changefreq>\n" if item.changefreq
|
173
|
+
item_string << " <priority>#{item.priority}</priority>\n" if item.priority
|
97
174
|
item_string << " </url>\n"
|
98
175
|
|
99
176
|
item_results << item_string
|
@@ -101,7 +178,7 @@ module XmlSitemap
|
|
101
178
|
|
102
179
|
result << item_results.join("")
|
103
180
|
result << "</urlset>\n"
|
104
|
-
|
181
|
+
|
105
182
|
result
|
106
183
|
end
|
107
184
|
end
|
data/lib/xml-sitemap/version.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
<url>
|
4
4
|
<loc>http://foobar.com/</loc>
|
5
5
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
6
|
-
<changefreq>weekly</changefreq>
|
7
6
|
<priority>1.0</priority>
|
8
7
|
</url>
|
9
8
|
<url>
|
@@ -12,8 +11,6 @@
|
|
12
11
|
<image:loc>http://foobar.com/foo.gif</image:loc>
|
13
12
|
</image:image>
|
14
13
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
15
|
-
<changefreq>weekly</changefreq>
|
16
|
-
<priority>0.5</priority>
|
17
14
|
</url>
|
18
15
|
<url>
|
19
16
|
<loc>http://foobar.com/path?a=b&c=d&e=image support string</loc>
|
@@ -22,8 +19,6 @@
|
|
22
19
|
<image:title>Image Title</image:title>
|
23
20
|
</image:image>
|
24
21
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
25
|
-
<changefreq>weekly</changefreq>
|
26
|
-
<priority>0.5</priority>
|
27
22
|
</url>
|
28
23
|
<url>
|
29
24
|
<loc>http://foobar.com/path?a=b&c=d&e=image support string</loc>
|
@@ -32,8 +27,6 @@
|
|
32
27
|
<image:caption>Image Caption</image:caption>
|
33
28
|
</image:image>
|
34
29
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
35
|
-
<changefreq>weekly</changefreq>
|
36
|
-
<priority>0.5</priority>
|
37
30
|
</url>
|
38
31
|
<url>
|
39
32
|
<loc>http://foobar.com/path?a=b&c=d&e=image support string</loc>
|
@@ -42,8 +35,6 @@
|
|
42
35
|
<image:license>Image License</image:license>
|
43
36
|
</image:image>
|
44
37
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
45
|
-
<changefreq>weekly</changefreq>
|
46
|
-
<priority>0.5</priority>
|
47
38
|
</url>
|
48
39
|
<url>
|
49
40
|
<loc>http://foobar.com/path?a=b&c=d&e=image support string</loc>
|
@@ -52,8 +43,6 @@
|
|
52
43
|
<image:geo_location>Image GeoLocation</image:geo_location>
|
53
44
|
</image:image>
|
54
45
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
55
|
-
<changefreq>weekly</changefreq>
|
56
|
-
<priority>0.5</priority>
|
57
46
|
</url>
|
58
47
|
<url>
|
59
48
|
<loc>http://foobar.com/path?a=b&c=d&e=image support string</loc>
|
@@ -65,7 +54,5 @@
|
|
65
54
|
<image:geo_location>Image GeoLocation</image:geo_location>
|
66
55
|
</image:image>
|
67
56
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
68
|
-
<changefreq>weekly</changefreq>
|
69
|
-
<priority>0.5</priority>
|
70
57
|
</url>
|
71
58
|
</urlset>
|
@@ -3,13 +3,10 @@
|
|
3
3
|
<url>
|
4
4
|
<loc>http://foobar.com/</loc>
|
5
5
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
6
|
-
<changefreq>weekly</changefreq>
|
7
6
|
<priority>1.0</priority>
|
8
7
|
</url>
|
9
8
|
<url>
|
10
9
|
<loc>http://foobar.com/path?a=b&c=d&e=sample string</loc>
|
11
10
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
12
|
-
<changefreq>weekly</changefreq>
|
13
|
-
<priority>0.5</priority>
|
14
11
|
</url>
|
15
12
|
</urlset>
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<urlset xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
3
|
+
<url>
|
4
|
+
<loc>http://foobar.com/</loc>
|
5
|
+
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
6
|
+
<priority>1.0</priority>
|
7
|
+
</url>
|
8
|
+
<url>
|
9
|
+
<loc>http://foobar.com/path?a=b&c=d&e=video</loc>
|
10
|
+
<video:video>
|
11
|
+
<video:thumbnail_loc>http://foobar.com/foo.jpg</video:thumbnail_loc>
|
12
|
+
<video:title>Video Title</video:title>
|
13
|
+
<video:description>Video Description</video:description>
|
14
|
+
<video:content_loc>http://foobar.com/foo.mp4</video:content_loc>
|
15
|
+
</video:video>
|
16
|
+
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
17
|
+
</url>
|
18
|
+
<url>
|
19
|
+
<loc>http://foobar.com/path?a=b&c=d&e=video</loc>
|
20
|
+
<video:video>
|
21
|
+
<video:thumbnail_loc>http://foobar.com/foo.jpg</video:thumbnail_loc>
|
22
|
+
<video:title>Video Title</video:title>
|
23
|
+
<video:description>Video Description</video:description>
|
24
|
+
<video:player_loc>http://foobar.com/foo.swf</video:player_loc>
|
25
|
+
</video:video>
|
26
|
+
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
27
|
+
</url>
|
28
|
+
<url>
|
29
|
+
<loc>http://foobar.com/path?a=b&c=d&e=video</loc>
|
30
|
+
<video:video>
|
31
|
+
<video:thumbnail_loc>http://foobar.com/foo.jpg</video:thumbnail_loc>
|
32
|
+
<video:title>Video Title</video:title>
|
33
|
+
<video:description>Video Description</video:description>
|
34
|
+
<video:content_loc>http://foobar.com/foo.mp4</video:content_loc>
|
35
|
+
<video:player_loc>http://foobar.com/foo.swf</video:player_loc>
|
36
|
+
<video:duration>180</video:duration>
|
37
|
+
<video:expiration_date>2012-06-01T00:00:01Z</video:expiration_date>
|
38
|
+
<video:rating>3.5</video:rating>
|
39
|
+
<video:view_count>2500</video:view_count>
|
40
|
+
<video:publication_date>2011-06-01T00:00:01Z</video:publication_date>
|
41
|
+
<video:family_friendly>no</video:family_friendly>
|
42
|
+
<video:category>Video Category</video:category>
|
43
|
+
<video:restriction relationship="allow">IT</video:restriction>
|
44
|
+
<video:gallery_loc>http://foobar.com/foo.mpu</video:gallery_loc>
|
45
|
+
<video:price currency="USD">20</video:price>
|
46
|
+
<video:requires_subscription>no</video:requires_subscription>
|
47
|
+
<video:uploader>Video Uploader</video:uploader>
|
48
|
+
<video:platform relationship="allow">web</video:platform>
|
49
|
+
<video:live>no</video:live>
|
50
|
+
</video:video>
|
51
|
+
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
52
|
+
</url>
|
53
|
+
</urlset>
|
data/spec/fixtures/saved_map.xml
CHANGED
@@ -3,25 +3,18 @@
|
|
3
3
|
<url>
|
4
4
|
<loc>http://foobar.com/</loc>
|
5
5
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
6
|
-
<changefreq>weekly</changefreq>
|
7
6
|
<priority>1.0</priority>
|
8
7
|
</url>
|
9
8
|
<url>
|
10
9
|
<loc>http://foobar.com/about</loc>
|
11
10
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
12
|
-
<changefreq>weekly</changefreq>
|
13
|
-
<priority>0.5</priority>
|
14
11
|
</url>
|
15
12
|
<url>
|
16
13
|
<loc>http://foobar.com/terms</loc>
|
17
14
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
18
|
-
<changefreq>weekly</changefreq>
|
19
|
-
<priority>0.5</priority>
|
20
15
|
</url>
|
21
16
|
<url>
|
22
17
|
<loc>http://foobar.com/privacy</loc>
|
23
18
|
<lastmod>2011-06-01T00:00:01Z</lastmod>
|
24
|
-
<changefreq>weekly</changefreq>
|
25
|
-
<priority>0.5</priority>
|
26
19
|
</url>
|
27
20
|
</urlset>
|
data/spec/index_spec.rb
CHANGED
@@ -11,7 +11,7 @@ describe XmlSitemap::Index do
|
|
11
11
|
|
12
12
|
it 'should raise error if passing a wrong object' do
|
13
13
|
index = XmlSitemap::Index.new
|
14
|
-
expect { index.add(nil) }.to raise_error ArgumentError, 'XmlSitemap::Map object
|
14
|
+
expect { index.add(nil) }.to raise_error ArgumentError, 'XmlSitemap::Map object required!'
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'should raise error if passing an empty sitemap' do
|
data/spec/map_spec.rb
CHANGED
@@ -100,24 +100,56 @@ describe XmlSitemap::Map do
|
|
100
100
|
describe '#render' do
|
101
101
|
|
102
102
|
before do
|
103
|
-
opts1 = { :image_location => "http://foobar.com/foo.gif"}
|
104
|
-
opts2 = { :image_location => "http://foobar.com/foo.gif", :image_title => "Image Title"}
|
105
|
-
opts3 = { :image_location => "http://foobar.com/foo.gif", :image_caption => "Image Caption"}
|
106
|
-
opts4 = { :image_location => "http://foobar.com/foo.gif", :image_license => "Image License"}
|
107
|
-
opts5 = { :image_location => "http://foobar.com/foo.gif", :image_geolocation => "Image GeoLocation"}
|
103
|
+
opts1 = { :image_location => "http://foobar.com/foo.gif" }
|
104
|
+
opts2 = { :image_location => "http://foobar.com/foo.gif", :image_title => "Image Title" }
|
105
|
+
opts3 = { :image_location => "http://foobar.com/foo.gif", :image_caption => "Image Caption" }
|
106
|
+
opts4 = { :image_location => "http://foobar.com/foo.gif", :image_license => "Image License" }
|
107
|
+
opts5 = { :image_location => "http://foobar.com/foo.gif", :image_geolocation => "Image GeoLocation" }
|
108
108
|
opts6 = { :image_location => "http://foobar.com/foo.gif",
|
109
109
|
:image_title => "Image Title",
|
110
110
|
:image_caption => "Image Caption",
|
111
111
|
:image_license => "Image License",
|
112
|
-
:image_geolocation => "Image GeoLocation"}
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
112
|
+
:image_geolocation => "Image GeoLocation" }
|
113
|
+
opts7 = { :video_thumbnail_location => "http://foobar.com/foo.jpg",
|
114
|
+
:video_title => "Video Title",
|
115
|
+
:video_description => "Video Description",
|
116
|
+
:video_content_location => "http://foobar.com/foo.mp4" }
|
117
|
+
opts8 = { :video_thumbnail_location => "http://foobar.com/foo.jpg",
|
118
|
+
:video_title => "Video Title",
|
119
|
+
:video_description => "Video Description",
|
120
|
+
:video_player_location => "http://foobar.com/foo.swf" }
|
121
|
+
opts9 = { :video_thumbnail_location => "http://foobar.com/foo.jpg",
|
122
|
+
:video_title => "Video Title",
|
123
|
+
:video_description => "Video Description",
|
124
|
+
:video_content_location => "http://foobar.com/foo.mp4",
|
125
|
+
:video_player_location => "http://foobar.com/foo.swf",
|
126
|
+
:video_duration => 180,
|
127
|
+
:video_expiration_date => Time.gm(2012, 6, 1, 0, 0, 1),
|
128
|
+
:video_rating => 3.5,
|
129
|
+
:video_view_count => 2500,
|
130
|
+
:video_publication_date => base_time,
|
131
|
+
:video_family_friendly => "no",
|
132
|
+
:video_category => "Video Category",
|
133
|
+
:video_restriction => "IT",
|
134
|
+
:video_gallery_location => "http://foobar.com/foo.mpu",
|
135
|
+
:video_price => 20,
|
136
|
+
:video_requires_subscription => "no",
|
137
|
+
:video_uploader => "Video Uploader",
|
138
|
+
:video_platform => "web",
|
139
|
+
:video_live => "no" }
|
140
|
+
|
141
|
+
@image_map = XmlSitemap::Map.new('foobar.com', :time => base_time)
|
142
|
+
@image_map.add('/path?a=b&c=d&e=image support string', opts1)
|
143
|
+
@image_map.add('/path?a=b&c=d&e=image support string', opts2)
|
144
|
+
@image_map.add('/path?a=b&c=d&e=image support string', opts3)
|
145
|
+
@image_map.add('/path?a=b&c=d&e=image support string', opts4)
|
146
|
+
@image_map.add('/path?a=b&c=d&e=image support string', opts5)
|
147
|
+
@image_map.add('/path?a=b&c=d&e=image support string', opts6)
|
148
|
+
|
149
|
+
@video_map = XmlSitemap::Map.new('foobar.com', :time => base_time)
|
150
|
+
@video_map.add('/path?a=b&c=d&e=video', opts7)
|
151
|
+
@video_map.add('/path?a=b&c=d&e=video', opts8)
|
152
|
+
@video_map.add('/path?a=b&c=d&e=video', opts9)
|
121
153
|
end
|
122
154
|
|
123
155
|
it 'should have properly encoded entities' do
|
@@ -134,6 +166,16 @@ describe XmlSitemap::Map do
|
|
134
166
|
# ignore ordering of urlset attributes by dropping first two lines
|
135
167
|
s.split("\n")[2..-1].join("\n").should == fixture('encoded_map.xml').split("\n")[2..-1].join("\n")
|
136
168
|
end
|
169
|
+
|
170
|
+
it 'should have properly encoded entities with image support' do
|
171
|
+
s = @image_map.render(:builder)
|
172
|
+
s.split("\n")[2..-1].join("\n").should == fixture('encoded_image_map.xml').split("\n")[2..-1].join("\n")
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'should have properly encoded entities with video support' do
|
176
|
+
s = @video_map.render(:builder)
|
177
|
+
s.split("\n")[2..-1].join("\n").should == fixture('encoded_video_map.xml').split("\n")[2..-1].join("\n")
|
178
|
+
end
|
137
179
|
end
|
138
180
|
|
139
181
|
context 'with nokogiri engine' do
|
@@ -146,9 +188,14 @@ describe XmlSitemap::Map do
|
|
146
188
|
end
|
147
189
|
|
148
190
|
it 'should have properly encoded entities with image support' do
|
149
|
-
s = @
|
191
|
+
s = @image_map.render(:nokogiri)
|
150
192
|
s.split("\n")[2..-1].join("\n").should == fixture('encoded_image_map.xml').split("\n")[2..-1].join("\n")
|
151
193
|
end
|
194
|
+
|
195
|
+
it 'should have properly encoded entities with video support' do
|
196
|
+
s = @video_map.render(:nokogiri)
|
197
|
+
s.split("\n")[2..-1].join("\n").should == fixture('encoded_video_map.xml').split("\n")[2..-1].join("\n")
|
198
|
+
end
|
152
199
|
end
|
153
200
|
|
154
201
|
context 'with string engine' do
|
@@ -161,9 +208,14 @@ describe XmlSitemap::Map do
|
|
161
208
|
end
|
162
209
|
|
163
210
|
it 'should have properly encoded entities with image support' do
|
164
|
-
s = @
|
211
|
+
s = @image_map.render(:string)
|
165
212
|
s.split("\n")[2..-1].join("\n").should == fixture('encoded_image_map.xml').split("\n")[2..-1].join("\n")
|
166
213
|
end
|
214
|
+
|
215
|
+
it 'should have properly encoded entities with video support' do
|
216
|
+
s = @video_map.render(:string)
|
217
|
+
s.split("\n")[2..-1].join("\n").should == fixture('encoded_video_map.xml').split("\n")[2..-1].join("\n")
|
218
|
+
end
|
167
219
|
end
|
168
220
|
end
|
169
221
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xml-sitemap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -115,6 +115,7 @@ files:
|
|
115
115
|
- spec/fixtures/empty_index.xml
|
116
116
|
- spec/fixtures/encoded_image_map.xml
|
117
117
|
- spec/fixtures/encoded_map.xml
|
118
|
+
- spec/fixtures/encoded_video_map.xml
|
118
119
|
- spec/fixtures/group_index.xml
|
119
120
|
- spec/fixtures/sample_index.xml
|
120
121
|
- spec/fixtures/sample_index_secure.xml
|
@@ -146,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
147
|
version: '0'
|
147
148
|
requirements: []
|
148
149
|
rubyforge_project:
|
149
|
-
rubygems_version: 1.8.
|
150
|
+
rubygems_version: 1.8.25
|
150
151
|
signing_key:
|
151
152
|
specification_version: 3
|
152
153
|
summary: Simple XML sitemap generator for Ruby/Rails applications.
|
@@ -154,6 +155,7 @@ test_files:
|
|
154
155
|
- spec/fixtures/empty_index.xml
|
155
156
|
- spec/fixtures/encoded_image_map.xml
|
156
157
|
- spec/fixtures/encoded_map.xml
|
158
|
+
- spec/fixtures/encoded_video_map.xml
|
157
159
|
- spec/fixtures/group_index.xml
|
158
160
|
- spec/fixtures/sample_index.xml
|
159
161
|
- spec/fixtures/sample_index_secure.xml
|
@@ -164,4 +166,3 @@ test_files:
|
|
164
166
|
- spec/map_spec.rb
|
165
167
|
- spec/spec_helper.rb
|
166
168
|
- spec/xmlsitemap_spec.rb
|
167
|
-
has_rdoc:
|