xml-sitemap 1.3.1 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|