middleman-sitemap-xml-generator 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 39126624d004b40536c5f31beb3f23fa8fe821ad
4
+ data.tar.gz: 0b9325923fc546edb658fdc6bd2b0a3bf14346d3
5
+ SHA512:
6
+ metadata.gz: 82829eda0cd378195d7cb5e5df2ce21a5c61502803c9f682c6cb0772c3b90d2b21d95b95a9df7ebde0fbeab4c39c82465b06581a55e032a38ad3aee0cfba4dc0
7
+ data.tar.gz: 57e007bebf44470378ca5af854e2b810136d15221b64285b037389860be421120ef8d87a541103316c5c62bc83c5feadb39762f346bb13f959c81dccebd2d6fe
@@ -0,0 +1,10 @@
1
+ # Ignore bundler lock file
2
+ Gemfile.lock
3
+
4
+ # Ignore pkg folder
5
+ pkg
6
+
7
+ .bundle
8
+ tmp
9
+ spec/reports
10
+ vendor
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in middleman-search_engine_sitemap.gemspec
4
+ gemspec
@@ -0,0 +1,24 @@
1
+ The MIT License (MIT)
2
+
3
+ (c) 2016 AT-AT
4
+
5
+ Original:
6
+ Copyright (c) 2014 Pete Nicholls
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
@@ -0,0 +1,197 @@
1
+ # Middleman-Sitemap-Xml-Generator
2
+
3
+
4
+ This extension is a forked and slightly extended version of [Middleman Search Engine Sitemap by Pete Nicholls](https://github.com/Aupajo/middleman-search_engine_sitemap).
5
+
6
+ Note that this extension has been forked from the release [tagged as v1.3.0](https://github.com/Aupajo/middleman-search_engine_sitemap/releases/tag/v1.3.0) to support Middleman-v3.
7
+
8
+ Please refer to [the original](https://github.com/Aupajo/middleman-search_engine_sitemap) if you want to get the latest release or a version for Middleman-v4.
9
+
10
+
11
+ ### Why forked from v1.3.0?
12
+
13
+ Because I'm not be planning to use Middleman-v4 yet. 8-)
14
+
15
+
16
+ ## Installation
17
+
18
+ Add the following line to the Gemfile of your Middleman project:
19
+
20
+ ```ruby
21
+ gem 'middleman-sitemap-xml-generator'
22
+ ```
23
+
24
+ Then as usual, run:
25
+
26
+ ```sh
27
+ bundle install
28
+ ```
29
+
30
+
31
+ ## Usage
32
+
33
+ To activate and configure this extension, add the following configuration block to Middleman's config.rb:
34
+
35
+ ```ruby
36
+ set :url_root, 'http://example.com'
37
+ activate :sitemap_xml_generator
38
+ ```
39
+
40
+
41
+ ### Options
42
+
43
+ | Option | Default | Description
44
+ | --- | --- | ---
45
+ | default_changefreq | 'monthly' | Default page priority
46
+ | default_priority | 0.5 | Default page priority
47
+ | sitemap_xml_path | 'sitemap.xml' | Path to the sitemap.xml
48
+ | exclude_attr | 'hide_from_sitemap' | Attribute in `Frontmatter` to exclude from the sitemap
49
+ | process_url | nil | Callable object(responds to #call) to process a URL
50
+ | process_changefreq | nil | Callable object to determine a changefreq
51
+ | process_priority | nil | Callable object to determine a priority
52
+ | exclude_if | ->(resource) { false } | Callable object to exclude from the sitemap
53
+ | extra_ext | [] | Extensions allowed to be in the sitemap<br>(needed prefixed "dot")
54
+ | discard_ext | [] | Extensions removed from "loc" tag<br>(needed prefixed "dot")
55
+
56
+
57
+ ## Determination of "changefreq" and "priority"
58
+
59
+ A value of `changefreq` and `priority` in the sitemap.xml is determined in the following priority.
60
+
61
+ 1. **(Higher)** `Frontmatter` attributes in each file
62
+
63
+ ```yaml
64
+ ---
65
+ changefreq: daily
66
+ priority: 1.0
67
+ ---
68
+ ```
69
+
70
+ 1. Processing in a `process_changefreq` and a `process_priority` option
71
+
72
+ ```ruby
73
+ activate :sitemap_xml_generator do |f|
74
+ f.process_changefreq = ->(path, default) {
75
+ path.end_with?('.foo') ? 'yearly' : default
76
+ }
77
+ f.process_priority = ->(path, default) {
78
+ path.end_with?('.foo') ? 0.9 : default
79
+ }
80
+ end
81
+ ```
82
+
83
+ | Argument | Description
84
+ | --- | ---
85
+ | path | A path prefixed "/" from **Web** root. e.g. `/foo.html`
86
+ | default | The same value as `default_changefreq` or `default_priority`
87
+
88
+ 1. **(Lower)** A value in a `default_changefreq` and a `default_priority` option
89
+
90
+
91
+ ## Excluding pages
92
+
93
+
94
+ ### Specify in Frontmatter
95
+
96
+ You can add a `hide_from_sitemap` attribute to `Frontmatter` in the page which is omitted from the sitemap.xml:
97
+
98
+ ```yaml
99
+ ---
100
+ hide_from_sitemap: true
101
+ ---
102
+ ```
103
+
104
+ If you would like to use a different `Frontmatter` attribute, you can specify it in a `exclude_attr` option:
105
+
106
+ ```ruby
107
+ activate :sitemap_xml_generator do |f|
108
+ f.exclude_attr = 'invisible'
109
+ end
110
+ ```
111
+
112
+ Then you can omit a page the following way:
113
+
114
+ ```yaml
115
+ ---
116
+ invisible: true
117
+ ---
118
+ ```
119
+
120
+
121
+ ### Use custom processor
122
+
123
+ You can also use a `exclude_if` option to exclude pages based on conditions you want:
124
+
125
+ ```ruby
126
+ # Exclude all pages which have a date that's after today
127
+ activate :sitemap_xml_generator do |f|
128
+ f.exclude_if = ->(resource) {
129
+ resource.data.date && resource.data.date > Date.today
130
+ }
131
+ end
132
+ ```
133
+
134
+ | Argument | Description
135
+ | --- | ---
136
+ | resource | A resource object (`Middleman::Sitemap::Resource`)
137
+
138
+
139
+ ## Processing a URL in "loc" tag
140
+
141
+ You can use a `process_url` option to process a URL in "loc" tag in each page in the sitemap.xml:
142
+
143
+ ```ruby
144
+ # This Proc removes a trailing slash from a URL in all "loc" tag.
145
+ activate :sitemap_xml_generator do |f|
146
+ f.process_url = ->(url) { url.chomp('/') }
147
+ end
148
+ ```
149
+
150
+ | Argument | Description
151
+ | --- | ---
152
+ | url | The URL of each page
153
+
154
+
155
+ ## Adding file in addition to HTML
156
+
157
+ Only HTML file is added to the sitemap.xml with the default setting.
158
+
159
+ You can use a `extra_ext` option to add any file to the sitemap.xml:
160
+
161
+ ```ruby
162
+ # This setting adds every file suffixed ".foo" to the sitemap.xml.
163
+ activate :sitemap_xml_generator do |f|
164
+ f.extra_ext = ['.foo'] # prefixed dot is required.
165
+ end
166
+ ```
167
+
168
+
169
+ ## Excluding a content extension
170
+
171
+ You can use a `discard_ext` option to exclude a content extension from a address in "loc" tag in the sitemap.xml:
172
+
173
+ ```ruby
174
+ # This setting removes suffixed ".foo" from "loc" tag in the sitemap.xml.
175
+ activate :sitemap_xml_generator do |f|
176
+ f.discard_ext = ['.foo'] # prefixed dot is required.
177
+ end
178
+ ```
179
+
180
+ Note that this process is executed before the process designated in a `process_url` option.
181
+
182
+
183
+ ## Workaround for the template reference issue
184
+
185
+ This extension deals with that [issue](https://github.com/Aupajo/middleman-search_engine_sitemap/issues/5) by [this workaround](https://github.com/Aupajo/middleman-search_engine_sitemap/issues/2#issuecomment-46701165).
186
+
187
+
188
+ ## Thanks
189
+
190
+ All ideas, logics, hints and prizes belong to the original author, Pete Nicholls.
191
+
192
+ And all mistakes belong to me.
193
+
194
+
195
+ ## License
196
+
197
+ (c) 2016 AT-AT. MIT Licensed, see [LICENSE](LICENSE.md) for details.
@@ -0,0 +1,7 @@
1
+ require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,6 @@
1
+ require 'middleman-core'
2
+
3
+ ::Middleman::Extensions.register(:sitemap_xml_generator) do
4
+ require 'middleman-sitemap-xml-generator/extension'
5
+ ::Middleman::SitemapXmlGenerator::Extension
6
+ end
@@ -0,0 +1,168 @@
1
+ module Middleman
2
+ module SitemapXmlGenerator
3
+ class Extension < ::Middleman::Extension
4
+ option :default_changefreq, 'monthly', 'Default page priority'
5
+ option :default_priority, 0.5, 'Default page priority'
6
+ option :sitemap_xml_path, 'sitemap.xml', 'Path to the sitemap.xml'
7
+ option :exclude_attr, 'hide_from_sitemap', 'Attribute in Frontmatter to exclude from sitemap'
8
+ option :process_url, nil, 'Callable object(responds to #call) to process a URL'
9
+ option :process_changefreq, nil, 'Callable object to determine a changefreq'
10
+ option :process_priority, nil, 'Callable object to determine a priority'
11
+ option :exclude_if, ->(resource) { false }, 'Callable object to exclude from the sitemap'
12
+ option :extra_ext, [], 'Extensions allowed to be in the sitemap(needed prefixed "dot")'
13
+ option :discard_ext, [], 'Extensions removed from "loc" in the sitemap(needed prefixed "dot")'
14
+
15
+ TEMPLATES_DIR = File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
16
+
17
+
18
+ def initialize(app, options_hash={}, &block)
19
+ super
20
+
21
+ require 'builder'
22
+ end
23
+
24
+
25
+ public
26
+
27
+
28
+ #
29
+ # Hooks
30
+ #
31
+
32
+ def after_configuration
33
+ register_extension_templates
34
+ prepare_extra_ext_opt
35
+ prepare_discard_ext_opt
36
+ watch_vendor_directory
37
+ end
38
+
39
+ def manipulate_resource_list(resources)
40
+ resources << sitemap_resource
41
+ end
42
+
43
+
44
+ #
45
+ # Helpers
46
+ #
47
+
48
+ def resource_in_sitemap?(resource)
49
+ is_page?(resource) && not_excluded?(resource)
50
+ end
51
+
52
+ def process_changefreq(path)
53
+ default = options.default_changefreq
54
+ options.process_changefreq ? options.process_changefreq.call(path, default) : default
55
+ end
56
+
57
+ def process_priority(path)
58
+ default = options.default_priority
59
+ options.process_priority ? options.process_priority.call(path, default) : default
60
+ end
61
+
62
+ def process_url(path)
63
+ path = process_extension path
64
+ options.process_url ? options.process_url.call(path) : path
65
+ end
66
+
67
+ helpers do
68
+ def resources_for_sitemap
69
+ sitemap.resources.select do |resource|
70
+ extensions[:sitemap_xml_generator].resource_in_sitemap?(resource)
71
+ end
72
+ end
73
+ end
74
+
75
+
76
+ #
77
+ # Internals
78
+ #
79
+
80
+ private
81
+
82
+ def allowed_ext?(resource)
83
+ options.extra_ext.include? File.extname(resource.path)
84
+ end
85
+
86
+ def filter_valid_extension(value)
87
+ [value].flatten.select { |ext| ext.match /^\.[^.]+/ }
88
+ end
89
+
90
+ def generate_processor(method_name)
91
+ self.class.instance_method(method_name.to_sym).bind(self)
92
+ end
93
+
94
+ def is_page?(resource)
95
+ resource.path.end_with?(page_ext) || allowed_ext?(resource)
96
+ end
97
+
98
+ def not_excluded?(resource)
99
+ !resource.ignored? \
100
+ && !resource.data[options.exclude_attr] && !options.exclude_if.call(resource)
101
+ end
102
+
103
+ def page_ext
104
+ File.extname(app.index_file)
105
+ end
106
+
107
+ def prepare_extra_ext_opt
108
+ options.extra_ext = filter_valid_extension options.extra_ext
109
+ end
110
+
111
+ def prepare_discard_ext_opt
112
+ options.discard_ext = filter_valid_extension options.discard_ext
113
+ end
114
+
115
+ def process_extension(path)
116
+ target_ext = File.extname path
117
+ if options.discard_ext.include?(target_ext)
118
+ path = File.join(File.dirname(path), File.basename(path, target_ext))
119
+ end
120
+ path
121
+ end
122
+
123
+ def register_extension_templates
124
+ # We call reload_path to register the templates directory with Middleman.
125
+ # The path given to app.files must be relative to the Middleman site's root.
126
+ templates_dir_relative_from_root = \
127
+ Pathname(TEMPLATES_DIR).relative_path_from(Pathname(app.root))
128
+ app.files.reload_path(templates_dir_relative_from_root)
129
+ end
130
+
131
+ def sitemap_locals
132
+ {
133
+ url_proc: generate_processor(:process_url),
134
+ changefreq_proc: generate_processor(:process_changefreq),
135
+ priority_proc: generate_processor(:process_priority)
136
+ }
137
+ end
138
+
139
+ def sitemap_resource
140
+ source_file = template('sitemap.xml.builder')
141
+
142
+ ::Middleman::Sitemap::Resource.new(app.sitemap, sitemap_xml_path, source_file).tap do |res|
143
+ res.add_metadata(options: { layout: false }, locals: sitemap_locals)
144
+ end
145
+ end
146
+
147
+ def sitemap_xml_path
148
+ options.sitemap_xml_path
149
+ end
150
+
151
+ def template(path)
152
+ full_path = File.join(TEMPLATES_DIR, path)
153
+ raise "Template #{full_path} not found" if !File.exist?(full_path)
154
+ full_path
155
+ end
156
+
157
+ # Workaround for the template reference issue. See below:
158
+ # https://github.com/Aupajo/middleman-search_engine_sitemap/issues/5
159
+ # https://github.com/Aupajo/middleman-search_engine_sitemap/issues/2#issuecomment-46701165
160
+ def watch_vendor_directory
161
+ app.config[:file_watcher_ignore] = (app.config[:file_watcher_ignore].reject do |regexp|
162
+ regexp == /^vendor(\/|$)/
163
+ end)
164
+ end
165
+
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,11 @@
1
+ xml.instruct!
2
+ xml.urlset 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9' do
3
+ resources_for_sitemap.each do |page|
4
+ xml.url do
5
+ xml.loc url_proc.call(File.join(url_root, page.url))
6
+ xml.lastmod(File.mtime(page.source_file).iso8601) if page.source_file
7
+ xml.changefreq page.data.changefreq || changefreq_proc.call(page.url)
8
+ xml.priority page.data.priority || priority_proc.call(page.url)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module Middleman
2
+ module SitemapXmlGenerator
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require 'middleman-sitemap-xml-generator'
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $:.unshift(lib) unless $:.include?(lib)
4
+ require 'middleman-sitemap-xml-generator/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'middleman-sitemap-xml-generator'
8
+ s.version = Middleman::SitemapXmlGenerator::VERSION
9
+ s.authors = ['AT-AT']
10
+ s.email = ['dec.alpha21264@gmail.com']
11
+ s.homepage = 'https://github.com/AT-AT/middleman-sitemap-xml-generator'
12
+ s.summary = %q{Adds a sitemap.xml file to your Middleman site for search engines.}
13
+ s.description = %q{Adds a sitemap.xml file to your Middleman site for search engines.}
14
+ s.license = 'MIT'
15
+ s.files = `git ls-files -z`.split("\0")
16
+ s.test_files = `git ls-files -- {test,spec,features,fixtures}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ['lib']
19
+
20
+ # The version of middleman-core your extension depends on
21
+ s.add_runtime_dependency 'middleman-core', '~> 3.4.1'
22
+ s.add_runtime_dependency 'builder'
23
+
24
+ # Additional dependencies
25
+ s.add_development_dependency 'bundler', '~> 1.5'
26
+ s.add_development_dependency 'rake'
27
+ s.add_development_dependency 'rspec'
28
+ s.add_development_dependency 'nokogiri', '1.6.3'
29
+ end
@@ -0,0 +1,116 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
3
+ targetNamespace="http://www.sitemaps.org/schemas/sitemap/0.9"
4
+ xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
5
+ elementFormDefault="qualified">
6
+ <xsd:annotation>
7
+ <xsd:documentation>
8
+ XML Schema for Sitemap files.
9
+ Last Modifed 2008-03-26
10
+ </xsd:documentation>
11
+ </xsd:annotation>
12
+
13
+ <xsd:element name="urlset">
14
+ <xsd:annotation>
15
+ <xsd:documentation>
16
+ Container for a set of up to 50,000 document elements.
17
+ This is the root element of the XML file.
18
+ </xsd:documentation>
19
+ </xsd:annotation>
20
+ <xsd:complexType>
21
+ <xsd:sequence>
22
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
23
+ <xsd:element name="url" type="tUrl" maxOccurs="unbounded"/>
24
+ </xsd:sequence>
25
+ </xsd:complexType>
26
+ </xsd:element>
27
+
28
+ <xsd:complexType name="tUrl">
29
+ <xsd:annotation>
30
+ <xsd:documentation>
31
+ Container for the data needed to describe a document to crawl.
32
+ </xsd:documentation>
33
+ </xsd:annotation>
34
+ <xsd:sequence>
35
+ <xsd:element name="loc" type="tLoc"/>
36
+ <xsd:element name="lastmod" type="tLastmod" minOccurs="0"/>
37
+ <xsd:element name="changefreq" type="tChangeFreq" minOccurs="0"/>
38
+ <xsd:element name="priority" type="tPriority" minOccurs="0"/>
39
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
40
+ </xsd:sequence>
41
+ </xsd:complexType>
42
+
43
+ <xsd:simpleType name="tLoc">
44
+ <xsd:annotation>
45
+ <xsd:documentation>
46
+ REQUIRED: The location URI of a document.
47
+ The URI must conform to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt).
48
+ </xsd:documentation>
49
+ </xsd:annotation>
50
+ <xsd:restriction base="xsd:anyURI">
51
+ <xsd:minLength value="12"/>
52
+ <xsd:maxLength value="2048"/>
53
+ </xsd:restriction>
54
+ </xsd:simpleType>
55
+
56
+ <xsd:simpleType name="tLastmod">
57
+ <xsd:annotation>
58
+ <xsd:documentation>
59
+ OPTIONAL: The date the document was last modified. The date must conform
60
+ to the W3C DATETIME format (http://www.w3.org/TR/NOTE-datetime).
61
+ Example: 2005-05-10
62
+ Lastmod may also contain a timestamp.
63
+ Example: 2005-05-10T17:33:30+08:00
64
+ </xsd:documentation>
65
+ </xsd:annotation>
66
+ <xsd:union>
67
+ <xsd:simpleType>
68
+ <xsd:restriction base="xsd:date"/>
69
+ </xsd:simpleType>
70
+ <xsd:simpleType>
71
+ <xsd:restriction base="xsd:dateTime"/>
72
+ </xsd:simpleType>
73
+ </xsd:union>
74
+ </xsd:simpleType>
75
+
76
+ <xsd:simpleType name="tChangeFreq">
77
+ <xsd:annotation>
78
+ <xsd:documentation>
79
+ OPTIONAL: Indicates how frequently the content at a particular URL is
80
+ likely to change. The value "always" should be used to describe
81
+ documents that change each time they are accessed. The value "never"
82
+ should be used to describe archived URLs. Please note that web
83
+ crawlers may not necessarily crawl pages marked "always" more often.
84
+ Consider this element as a friendly suggestion and not a command.
85
+ </xsd:documentation>
86
+ </xsd:annotation>
87
+ <xsd:restriction base="xsd:string">
88
+ <xsd:enumeration value="always"/>
89
+ <xsd:enumeration value="hourly"/>
90
+ <xsd:enumeration value="daily"/>
91
+ <xsd:enumeration value="weekly"/>
92
+ <xsd:enumeration value="monthly"/>
93
+ <xsd:enumeration value="yearly"/>
94
+ <xsd:enumeration value="never"/>
95
+ </xsd:restriction>
96
+ </xsd:simpleType>
97
+
98
+ <xsd:simpleType name="tPriority">
99
+ <xsd:annotation>
100
+ <xsd:documentation>
101
+ OPTIONAL: The priority of a particular URL relative to other pages
102
+ on the same site. The value for this element is a number between
103
+ 0.0 and 1.0 where 0.0 identifies the lowest priority page(s).
104
+ The default priority of a page is 0.5. Priority is used to select
105
+ between pages on your site. Setting a priority of 1.0 for all URLs
106
+ will not help you, as the relative priority of pages on your site
107
+ is what will be considered.
108
+ </xsd:documentation>
109
+ </xsd:annotation>
110
+ <xsd:restriction base="xsd:decimal">
111
+ <xsd:minInclusive value="0.0"/>
112
+ <xsd:maxInclusive value="1.0"/>
113
+ </xsd:restriction>
114
+ </xsd:simpleType>
115
+
116
+ </xsd:schema>
@@ -0,0 +1,3 @@
1
+ ---
2
+ priority: 0.2
3
+ ---
@@ -0,0 +1,2 @@
1
+ ---
2
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ changefreq: daily
3
+ priority: 0.2
4
+ ---
@@ -0,0 +1,3 @@
1
+ ---
2
+ changefreq: daily
3
+ ---
File without changes
@@ -0,0 +1,3 @@
1
+ ---
2
+ ignored_by_proc: true
3
+ ---
@@ -0,0 +1,3 @@
1
+ ---
2
+ hide_from_sitemap: true
3
+ ---
File without changes
@@ -0,0 +1 @@
1
+ Layout
@@ -0,0 +1,4 @@
1
+ ---
2
+ changefreq: daily
3
+ priority: 0.2
4
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ changefreq: daily
3
+ priority: 0.2
4
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ changefreq: daily
3
+ priority: 0.2
4
+ ---
@@ -0,0 +1,2 @@
1
+ ---
2
+ ---
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+ require 'nokogiri'
3
+ require 'pathname'
4
+
5
+ describe "Generate sitemap.xml", :feature do
6
+ include XmlHelpers
7
+
8
+ it "produces a valid sitemap" do
9
+ run_site 'dummy' do
10
+ set :url_root, 'http://example.com'
11
+ activate :sitemap_xml_generator
12
+
13
+ ignore '/ignored.html'
14
+ end
15
+
16
+ visit '/sitemap.xml'
17
+
18
+ schema = Pathname(__dir__) + '../../sitemap.xsd'
19
+ doc = Nokogiri::XML(last_response.body)
20
+ expect(doc).to validate_against_schema(schema)
21
+
22
+ expect(doc).to contain_node('url').with_children(
23
+ 'loc' => 'http://example.com/home.html',
24
+ 'priority' => '0.5',
25
+ 'changefreq' => 'monthly'
26
+ )
27
+
28
+ expect(doc).to contain_node('url').with_children(
29
+ 'loc' => 'http://example.com/about.html',
30
+ 'priority' => '0.2',
31
+ 'changefreq' => 'monthly'
32
+ )
33
+
34
+ expect(doc).to contain_node('url').with_children(
35
+ 'loc' => 'http://example.com/blog.html',
36
+ 'priority' => '0.5',
37
+ 'changefreq' => 'daily'
38
+ )
39
+
40
+ expect(doc.to_s).not_to include('http://example.com/ignored.html')
41
+ expect(doc.to_s).not_to include('http://example.com/ignored-in-frontmatter.html')
42
+ end
43
+
44
+ it "works with directory indexes" do
45
+ run_site 'dummy' do
46
+ set :url_root, 'http://example.com'
47
+ activate :directory_indexes
48
+ activate :sitemap_xml_generator
49
+
50
+ ignore '/ignored.html'
51
+ end
52
+
53
+ visit '/sitemap.xml'
54
+ doc = Nokogiri::XML(last_response.body)
55
+
56
+ expect(doc).to contain_node('url').with_children(
57
+ 'loc' => 'http://example.com/home/',
58
+ 'priority' => '0.5',
59
+ 'changefreq' => 'monthly'
60
+ )
61
+
62
+ expect(doc).to contain_node('url').with_children(
63
+ 'loc' => 'http://example.com/about/',
64
+ 'priority' => '0.2',
65
+ 'changefreq' => 'monthly'
66
+ )
67
+
68
+ expect(doc).to contain_node('url').with_children(
69
+ 'loc' => 'http://example.com/blog/',
70
+ 'priority' => '0.5',
71
+ 'changefreq' => 'daily'
72
+ )
73
+
74
+ expect(doc.to_s).not_to include('http://example.com/ignored/')
75
+ expect(doc.to_s).not_to include('http://example.com/ignored-in-frontmatter/')
76
+ end
77
+
78
+ it "supports custom URL processing" do
79
+ run_site 'dummy' do
80
+ set :url_root, 'http://example.com'
81
+ activate :directory_indexes
82
+ activate :sitemap_xml_generator, process_url: ->(url) { url.upcase }
83
+ end
84
+
85
+ visit '/sitemap.xml'
86
+ doc = Nokogiri::XML(last_response.body)
87
+
88
+ expect(doc).to contain_node('url').with_children(
89
+ 'loc' => 'HTTP://EXAMPLE.COM/HOME/',
90
+ 'priority' => '0.5',
91
+ 'changefreq' => 'monthly'
92
+ )
93
+ end
94
+
95
+ it "ignores resources based on exclude_if result" do
96
+ run_site 'dummy' do
97
+ set :url_root, 'http://example.com'
98
+ activate :sitemap_xml_generator,
99
+ exclude_if: ->(resource) { resource.data.ignored_by_proc }
100
+
101
+ ignore '/ignored.html'
102
+ end
103
+
104
+ visit '/sitemap.xml'
105
+ doc = Nokogiri::XML(last_response.body)
106
+
107
+ expect(doc.to_s).not_to include('http://example.com/ignored-by-proc.html')
108
+ end
109
+
110
+ it "allows resources having a extension which is designated in the option" do
111
+ run_site 'dummy' do
112
+ set :url_root, 'http://example.com'
113
+ activate :sitemap_xml_generator,
114
+ extra_ext: ['.foo', 'bar']
115
+ end
116
+
117
+ visit '/sitemap.xml'
118
+ doc = Nokogiri::XML(last_response.body)
119
+
120
+ expect(doc).to contain_node('url').with_children(
121
+ 'loc' => 'http://example.com/allowed-extra-ext.foo',
122
+ 'priority' => '0.2',
123
+ 'changefreq' => 'daily'
124
+ )
125
+
126
+ expect(doc.to_s).not_to include('http://example.com/allowed-extra-ext.bar')
127
+ end
128
+
129
+ it "removes designated extention from resources" do
130
+ run_site 'dummy' do
131
+ set :url_root, 'http://example.com'
132
+ activate :sitemap_xml_generator,
133
+ extra_ext: ['.foo', '.bar'],
134
+ discard_ext: ['.html', '.foo', 'bar']
135
+ end
136
+
137
+ visit '/sitemap.xml'
138
+ doc = Nokogiri::XML(last_response.body)
139
+
140
+ expect(doc).to contain_node('url').with_children(
141
+ 'loc' => 'http://example.com/removed-ext',
142
+ 'priority' => '0.2',
143
+ 'changefreq' => 'daily'
144
+ )
145
+
146
+ expect(doc).to contain_node('url').with_children(
147
+ 'loc' => 'http://example.com/removed-extra-ext',
148
+ 'priority' => '0.2',
149
+ 'changefreq' => 'daily'
150
+ )
151
+
152
+ expect(doc).to contain_node('url').with_children(
153
+ 'loc' => 'http://example.com/removed-ext-remained.bar',
154
+ 'priority' => '0.2',
155
+ 'changefreq' => 'daily'
156
+ )
157
+ end
158
+
159
+ it "set values by procs" do
160
+ run_site 'dummy' do
161
+ set :url_root, 'http://example.com'
162
+ activate :sitemap_xml_generator,
163
+ extra_ext: ['.foo'],
164
+ process_changefreq: ->(path, default){
165
+ path.end_with?('.foo') ? 'yearly' : default
166
+ },
167
+ process_priority: ->(path, default){
168
+ path.end_with?('.foo') ? 0.9 : default
169
+ }
170
+ end
171
+
172
+ visit '/sitemap.xml'
173
+ doc = Nokogiri::XML(last_response.body)
174
+
175
+ expect(doc).to contain_node('url').with_children(
176
+ 'loc' => 'http://example.com/values_by_proc.foo',
177
+ 'priority' => '0.9',
178
+ 'changefreq' => 'yearly'
179
+ )
180
+ end
181
+
182
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec'
2
+
3
+ $LOAD_PATH << File.expand_path("../../lib", __FILE__)
4
+
5
+ # Include support files
6
+ support_files_pattern = File.expand_path('../support/**/*.rb', __FILE__)
7
+ Dir.glob(support_files_pattern).each { |f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.include MiddlemanServerHelpers, :feature
11
+ end
@@ -0,0 +1,41 @@
1
+ require 'middleman/rack'
2
+ require 'rack/test'
3
+
4
+ module MiddlemanServerHelpers
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ @app.call
9
+ end
10
+
11
+ def visit(path)
12
+ get(path)
13
+ raise last_response.errors if !last_response.errors.empty?
14
+ end
15
+
16
+ def find_on_page(string)
17
+ expect(last_response.body).to include(string)
18
+ end
19
+
20
+ def run_site(path, &block)
21
+ setup_environment(path)
22
+
23
+ @app = lambda do
24
+ instance = Middleman::Application.server.inst do
25
+ # Require the extension after the server has booted, as would typically happen.
26
+ require File.expand_path('../../../lib/middleman_extension', __FILE__)
27
+
28
+ instance_exec(&block)
29
+ end
30
+
31
+ instance.class.to_rack_app
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def setup_environment(path)
38
+ ENV['MM_ROOT'] = File.expand_path("../../#{path}", __FILE__)
39
+ ENV['TEST'] = "true"
40
+ end
41
+ end
@@ -0,0 +1,49 @@
1
+ module XmlHelpers
2
+ extend RSpec::Matchers::DSL
3
+
4
+ matcher :validate_against_schema do |schema|
5
+ match do |actual|
6
+ xsd = Nokogiri::XML::Schema(schema.read)
7
+ @validation_errors = xsd.validate(actual)
8
+ @validation_errors.empty?
9
+ end
10
+
11
+ failure_message do |actual|
12
+ num_errors = @validation_errors.length
13
+ error_count = "#{num_errors} error#{'s' if num_errors > 1}"
14
+
15
+ "expected XML to validate against #{schema}, got #{error_count}:\n" +
16
+ @validation_errors.each_with_index.map do |error, i|
17
+ " #{i + 1}. #{error}"
18
+ end.join("\n")
19
+ end
20
+ end
21
+
22
+ matcher :contain_node do |name|
23
+ match do |doc|
24
+ if @attributes
25
+ doc.css(name).detect do |node|
26
+ @attributes.all? { |k, v| node.css(k).text == v }
27
+ end
28
+ else
29
+ doc.at_css(name)
30
+ end
31
+ end
32
+
33
+ chain :with_children do |attributes|
34
+ @attributes = attributes
35
+ end
36
+
37
+ failure_message do |doc|
38
+ expected_xml = "<#{name}>\n"
39
+
40
+ if @attributes
41
+ @attributes.each { |k,v| expected_xml << " <#{k}>#{v}</#{k}>\n" }
42
+ end
43
+
44
+ expected_xml << "</#{name}>"
45
+
46
+ "expected XML to contain:\n\n#{expected_xml}\n\ninstead got:\n\n#{doc.to_s}"
47
+ end
48
+ end
49
+ end
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-sitemap-xml-generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - AT-AT
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: middleman-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.4.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.4.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: builder
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: nokogiri
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 1.6.3
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 1.6.3
97
+ description: Adds a sitemap.xml file to your Middleman site for search engines.
98
+ email:
99
+ - dec.alpha21264@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - Gemfile
106
+ - LICENSE.md
107
+ - README.md
108
+ - Rakefile
109
+ - lib/middleman-sitemap-xml-generator.rb
110
+ - lib/middleman-sitemap-xml-generator/extension.rb
111
+ - lib/middleman-sitemap-xml-generator/templates/sitemap.xml.builder
112
+ - lib/middleman-sitemap-xml-generator/version.rb
113
+ - lib/middleman_extension.rb
114
+ - middleman-sitemap-xml-generator.gemspec
115
+ - sitemap.xsd
116
+ - spec/dummy/source/about.html
117
+ - spec/dummy/source/allowed-extra-ext.bar
118
+ - spec/dummy/source/allowed-extra-ext.foo
119
+ - spec/dummy/source/blog.html
120
+ - spec/dummy/source/home.html
121
+ - spec/dummy/source/ignored-by-proc.html
122
+ - spec/dummy/source/ignored-in-frontmatter.html
123
+ - spec/dummy/source/ignored.html
124
+ - spec/dummy/source/layouts/layout.erb
125
+ - spec/dummy/source/removed-ext-remained.bar
126
+ - spec/dummy/source/removed-ext.html
127
+ - spec/dummy/source/removed-extra-ext.foo
128
+ - spec/dummy/source/values_by_proc.foo
129
+ - spec/features/sitemap_feature_spec.rb
130
+ - spec/spec_helper.rb
131
+ - spec/support/middleman_server_helpers.rb
132
+ - spec/support/xml_helpers.rb
133
+ homepage: https://github.com/AT-AT/middleman-sitemap-xml-generator
134
+ licenses:
135
+ - MIT
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.5.1
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: Adds a sitemap.xml file to your Middleman site for search engines.
157
+ test_files:
158
+ - spec/dummy/source/about.html
159
+ - spec/dummy/source/allowed-extra-ext.bar
160
+ - spec/dummy/source/allowed-extra-ext.foo
161
+ - spec/dummy/source/blog.html
162
+ - spec/dummy/source/home.html
163
+ - spec/dummy/source/ignored-by-proc.html
164
+ - spec/dummy/source/ignored-in-frontmatter.html
165
+ - spec/dummy/source/ignored.html
166
+ - spec/dummy/source/layouts/layout.erb
167
+ - spec/dummy/source/removed-ext-remained.bar
168
+ - spec/dummy/source/removed-ext.html
169
+ - spec/dummy/source/removed-extra-ext.foo
170
+ - spec/dummy/source/values_by_proc.foo
171
+ - spec/features/sitemap_feature_spec.rb
172
+ - spec/spec_helper.rb
173
+ - spec/support/middleman_server_helpers.rb
174
+ - spec/support/xml_helpers.rb