indexmap 0.3.0 → 0.4.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -3
- data/README.md +72 -15
- data/lib/indexmap/index_now_configuration.rb +4 -3
- data/lib/indexmap/path.rb +2 -1
- data/lib/indexmap/pinger/base.rb +4 -2
- data/lib/indexmap/pinger/google.rb +2 -1
- data/lib/indexmap/pinger/index_now.rb +33 -10
- data/lib/indexmap/task_runner.rb +17 -7
- data/lib/indexmap/version.rb +1 -1
- data/lib/tasks/indexmap_tasks.rake +29 -7
- data/test/indexmap/pinger/index_now_test.rb +40 -0
- data/test/indexmap/task_runner_test.rb +63 -0
- data/test/indexmap/validator_test.rb +12 -0
- data/test/test_helper.rb +7 -0
- metadata +16 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7a655a2fa64beda7c2724d6fb4f283a13a5baf47519863c489e982efa86f2c32
|
|
4
|
+
data.tar.gz: 42dac8a1312d05bba81df9534bba52eaa69d55c236688473757252a1038dae06
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d0615154aef9cf51613b73c46f834efb16c53b77dfb3611f8f980a8ae5c1e8eedaa653ca84ca5610a27b58377717e7c3acbd0fc1cdb162df90fd84d660912ed6
|
|
7
|
+
data.tar.gz: 796aeed197f26684ebbd74bb7b47d37c878fea855c02c4ec0636cd7ce28c44f32fb73a3c2a911955d194d175c8c80ce351c8b2f955e03707543a88e4ab740763
|
data/CHANGELOG.md
CHANGED
|
@@ -5,9 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [0.
|
|
8
|
+
## [0.4.0] - 2026-04-22
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
|
|
13
|
+
- improve the task messages (#4)
|
|
9
14
|
|
|
10
|
-
### <!-- 0 -->🚀 Features
|
|
11
|
-
- expand indexmap with sitemap parsing, validation, and search engine pinging
|
|
12
15
|
|
|
13
16
|
|
data/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://badge.fury.io/rb/indexmap)
|
|
4
4
|
[](https://github.com/ethos-link/indexmap/actions/workflows/ruby.yml)
|
|
5
5
|
|
|
6
|
-
`indexmap` is a small Ruby gem for generating XML
|
|
6
|
+
`indexmap` is a small Ruby gem for generating XML sitemaps from explicit Ruby data.
|
|
7
7
|
|
|
8
8
|
It is designed for Rails apps that want:
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ It is designed for Rails apps that want:
|
|
|
12
12
|
- first-party rake tasks instead of a large DSL
|
|
13
13
|
- easy extraction of sitemap logic into app-owned manifests
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
By default, `indexmap` writes a sitemap index plus one or more child sitemap files. For simpler sites, it also supports `:single_file` mode, which writes a single `urlset` directly to `sitemap.xml`.
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -34,7 +34,7 @@ Or install it directly:
|
|
|
34
34
|
gem install indexmap
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
## Ruby
|
|
37
|
+
## Ruby Usage
|
|
38
38
|
|
|
39
39
|
```ruby
|
|
40
40
|
require "indexmap"
|
|
@@ -56,7 +56,7 @@ Indexmap::Writer.new(
|
|
|
56
56
|
).write
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
## Rails
|
|
59
|
+
## Rails Usage
|
|
60
60
|
|
|
61
61
|
In an initializer:
|
|
62
62
|
|
|
@@ -77,14 +77,24 @@ Indexmap.configure do |config|
|
|
|
77
77
|
end
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
Then run:
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
83
|
bin/rails sitemap:create
|
|
84
84
|
bin/rails sitemap:format
|
|
85
|
+
bin/rails sitemap:validate
|
|
85
86
|
```
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
`sitemap:create` is the main task. It writes sitemap files, formats them, and validates the result.
|
|
89
|
+
|
|
90
|
+
### Default Index Mode
|
|
91
|
+
|
|
92
|
+
This is the default behavior. `indexmap` writes:
|
|
93
|
+
|
|
94
|
+
- `public/sitemap.xml` as a sitemap index
|
|
95
|
+
- one or more child sitemap files from `config.sections`
|
|
96
|
+
|
|
97
|
+
### Single-File Mode
|
|
88
98
|
|
|
89
99
|
For sites that only want one `public/sitemap.xml` file:
|
|
90
100
|
|
|
@@ -102,9 +112,9 @@ Indexmap.configure do |config|
|
|
|
102
112
|
end
|
|
103
113
|
```
|
|
104
114
|
|
|
105
|
-
In `:single_file` mode, `indexmap` writes a `urlset` directly to `sitemap.xml
|
|
115
|
+
In `:single_file` mode, `indexmap` writes a `urlset` directly to `sitemap.xml` and reads entries from `config.entries` instead of `config.sections`.
|
|
106
116
|
|
|
107
|
-
## Validation
|
|
117
|
+
## Validation And Parsing
|
|
108
118
|
|
|
109
119
|
`indexmap` also includes small utilities for working with generated sitemap files:
|
|
110
120
|
|
|
@@ -124,27 +134,72 @@ The built-in validator checks for:
|
|
|
124
134
|
|
|
125
135
|
## Search Engine Ping
|
|
126
136
|
|
|
127
|
-
|
|
137
|
+
`indexmap` can ping Google Search Console and IndexNow after sitemap generation.
|
|
138
|
+
|
|
139
|
+
Available rake tasks:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
bin/rails sitemap:validate
|
|
143
|
+
bin/rails sitemap:google:ping
|
|
144
|
+
bin/rails sitemap:index_now:ping
|
|
145
|
+
bin/rails sitemap:index_now:write_key
|
|
146
|
+
bin/rails sitemap:ping
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Google Search Console
|
|
150
|
+
|
|
151
|
+
Google pinging requires service account credentials:
|
|
152
|
+
|
|
153
|
+
```ruby
|
|
154
|
+
Indexmap.configure do |config|
|
|
155
|
+
config.google.credentials = -> { ENV["GOOGLE_SITEMAP"] }
|
|
156
|
+
end
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
If `config.google.credentials` is blank, `sitemap:google:ping` skips Google submission.
|
|
160
|
+
|
|
161
|
+
You can optionally override the Search Console property identifier:
|
|
128
162
|
|
|
129
163
|
```ruby
|
|
130
164
|
Indexmap.configure do |config|
|
|
131
165
|
config.google.credentials = -> { ENV["GOOGLE_SITEMAP"] }
|
|
166
|
+
config.google.property = -> { "sc-domain:example.com" }
|
|
167
|
+
end
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
If `config.google.property` is not set, `indexmap` defaults to `sc-domain:<host>`.
|
|
171
|
+
|
|
172
|
+
### IndexNow
|
|
173
|
+
|
|
174
|
+
IndexNow submission requires a key. `indexmap` supports two ways to provide it:
|
|
175
|
+
|
|
176
|
+
- set `config.index_now.key`
|
|
177
|
+
- or keep a valid verification file at `public/<key>.txt`
|
|
178
|
+
|
|
179
|
+
Configured-key example:
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
Indexmap.configure do |config|
|
|
132
183
|
config.index_now.key = -> { ENV["INDEXNOW_KEY"] }
|
|
133
184
|
end
|
|
134
185
|
```
|
|
135
186
|
|
|
136
|
-
|
|
187
|
+
If `config.index_now.key` is set, `sitemap:create` also writes the matching `public/<key>.txt` verification file automatically.
|
|
137
188
|
|
|
138
|
-
|
|
189
|
+
If you prefer the file-based flow, run:
|
|
139
190
|
|
|
140
191
|
```bash
|
|
141
|
-
bin/rails sitemap:validate
|
|
142
|
-
bin/rails sitemap:google:ping
|
|
143
|
-
bin/rails sitemap:index_now:ping
|
|
144
|
-
bin/rails sitemap:ping
|
|
145
192
|
bin/rails sitemap:index_now:write_key
|
|
146
193
|
```
|
|
147
194
|
|
|
195
|
+
That task:
|
|
196
|
+
|
|
197
|
+
- reuses an existing valid key file when present
|
|
198
|
+
- otherwise generates a new key in `public/<key>.txt`
|
|
199
|
+
- makes that key available to `sitemap:index_now:ping` without adding `config.index_now.key`
|
|
200
|
+
|
|
201
|
+
If neither a configured key nor a valid key file is present, `sitemap:index_now:ping` skips IndexNow submission.
|
|
202
|
+
|
|
148
203
|
## Development
|
|
149
204
|
|
|
150
205
|
Run tests:
|
|
@@ -165,6 +220,8 @@ Run the full default task:
|
|
|
165
220
|
bundle exec rake
|
|
166
221
|
```
|
|
167
222
|
|
|
223
|
+
Tests generate a coverage report automatically.
|
|
224
|
+
|
|
168
225
|
Note: `Gemfile.lock` is intentionally not tracked for this gem, following normal Ruby library conventions.
|
|
169
226
|
|
|
170
227
|
### Git hooks
|
|
@@ -13,16 +13,17 @@ module Indexmap
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def endpoint
|
|
16
|
-
resolve(@endpoint)
|
|
16
|
+
value = resolve(@endpoint)
|
|
17
|
+
value.to_s.strip.empty? ? DEFAULT_ENDPOINT : value
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def key
|
|
20
21
|
resolve(@key)
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
def key_path(public_path:)
|
|
24
|
+
def key_path(public_path:, key: self.key)
|
|
24
25
|
configured_path = resolve(@key_path)
|
|
25
|
-
return Pathname(configured_path)
|
|
26
|
+
return Pathname(configured_path) unless configured_path.to_s.strip.empty?
|
|
26
27
|
return if key.to_s.strip.empty?
|
|
27
28
|
|
|
28
29
|
Pathname(public_path).join("#{key}.txt")
|
data/lib/indexmap/path.rb
CHANGED
|
@@ -26,7 +26,8 @@ module Indexmap
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def default_index_filename
|
|
29
|
-
Indexmap.configuration.index_filename
|
|
29
|
+
configured = Indexmap.configuration.index_filename
|
|
30
|
+
configured.to_s.strip.empty? ? INDEX_FILENAME : configured
|
|
30
31
|
rescue
|
|
31
32
|
INDEX_FILENAME
|
|
32
33
|
end
|
data/lib/indexmap/pinger/base.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
3
|
+
require "logger"
|
|
4
4
|
require "uri"
|
|
5
5
|
|
|
6
6
|
module Indexmap
|
|
@@ -24,7 +24,9 @@ module Indexmap
|
|
|
24
24
|
@logger ||= if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
|
25
25
|
Rails.logger
|
|
26
26
|
else
|
|
27
|
-
|
|
27
|
+
Logger.new($stderr).tap do |logger|
|
|
28
|
+
logger.level = Logger::WARN
|
|
29
|
+
end
|
|
28
30
|
end
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -50,7 +50,8 @@ module Indexmap
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def property_identifier
|
|
53
|
-
google_configuration.property
|
|
53
|
+
property = google_configuration.property
|
|
54
|
+
property.to_s.strip.empty? ? "sc-domain:#{root_domain}" : property
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
def webmasters_service
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "faraday"
|
|
4
4
|
require "json"
|
|
5
|
+
require "securerandom"
|
|
5
6
|
require "time"
|
|
6
7
|
|
|
7
8
|
module Indexmap
|
|
@@ -37,16 +38,26 @@ module Indexmap
|
|
|
37
38
|
end
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
def write_key_file
|
|
41
|
-
key =
|
|
41
|
+
def write_key_file(key: index_now_configuration.key, path: nil)
|
|
42
|
+
key = key.to_s.strip
|
|
42
43
|
return if key.empty?
|
|
43
44
|
|
|
44
|
-
path
|
|
45
|
+
path ||= index_now_configuration.key_path(public_path: configuration.public_path, key: key)
|
|
45
46
|
FileUtils.mkdir_p(path.dirname)
|
|
46
47
|
File.write(path, "#{key}\n")
|
|
47
48
|
path
|
|
48
49
|
end
|
|
49
50
|
|
|
51
|
+
def ensure_key_file
|
|
52
|
+
configured_key = index_now_configuration.key.to_s.strip
|
|
53
|
+
return write_key_file(key: configured_key) unless configured_key.empty?
|
|
54
|
+
|
|
55
|
+
return existing_key_file if existing_key_file
|
|
56
|
+
|
|
57
|
+
key = generated_key
|
|
58
|
+
write_key_file(key: key, path: configuration.public_path.join("#{key}.txt"))
|
|
59
|
+
end
|
|
60
|
+
|
|
50
61
|
private
|
|
51
62
|
|
|
52
63
|
attr_reader :connection
|
|
@@ -158,15 +169,27 @@ module Indexmap
|
|
|
158
169
|
configured_key = index_now_configuration.key.to_s.strip
|
|
159
170
|
return configured_key unless configured_key.empty?
|
|
160
171
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
next unless filename.match?(/\A[a-zA-Z0-9-]{8,128}\z/)
|
|
172
|
+
existing_key_file&.read&.strip
|
|
173
|
+
end
|
|
164
174
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return
|
|
175
|
+
def existing_key_file
|
|
176
|
+
configured_path = index_now_configuration.key_path(public_path: configuration.public_path)
|
|
177
|
+
return configured_path if valid_key_file?(configured_path)
|
|
178
|
+
|
|
179
|
+
configuration.public_path.glob("*.txt").find { |file| valid_key_file?(file) }
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def valid_key_file?(path)
|
|
183
|
+
return false unless path&.file?
|
|
184
|
+
|
|
185
|
+
filename = path.basename(".txt").to_s
|
|
186
|
+
return false unless filename.match?(/\A[a-zA-Z0-9-]{8,128}\z/)
|
|
187
|
+
|
|
188
|
+
path.read.strip == filename
|
|
189
|
+
end
|
|
168
190
|
|
|
169
|
-
|
|
191
|
+
def generated_key
|
|
192
|
+
SecureRandom.uuid
|
|
170
193
|
end
|
|
171
194
|
end
|
|
172
195
|
end
|
data/lib/indexmap/task_runner.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Indexmap
|
|
|
11
11
|
def create
|
|
12
12
|
remove_existing_sitemap_files
|
|
13
13
|
configuration.writer.write
|
|
14
|
-
write_index_now_key
|
|
14
|
+
{files: sitemap_files, index_now_key_path: write_index_now_key}
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def format
|
|
@@ -27,28 +27,38 @@ module Indexmap
|
|
|
27
27
|
|
|
28
28
|
File.write(file_path, document.to_xml(indent: 2, save_with: save_options))
|
|
29
29
|
end
|
|
30
|
+
|
|
31
|
+
sitemap_files
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
def validate
|
|
33
35
|
Validator.new(configuration: configuration).validate!
|
|
36
|
+
sitemap_files
|
|
34
37
|
end
|
|
35
38
|
|
|
36
|
-
def write_index_now_key
|
|
37
|
-
Pinger::IndexNow.new(configuration: configuration)
|
|
39
|
+
def write_index_now_key(generate_if_missing: false)
|
|
40
|
+
pinger = Pinger::IndexNow.new(configuration: configuration)
|
|
41
|
+
return pinger.ensure_key_file if generate_if_missing
|
|
42
|
+
|
|
43
|
+
pinger.write_key_file
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def public_path
|
|
47
|
+
configuration.public_path
|
|
38
48
|
end
|
|
39
49
|
|
|
40
50
|
private
|
|
41
51
|
|
|
42
52
|
attr_reader :configuration
|
|
43
53
|
|
|
44
|
-
def sitemap_files
|
|
45
|
-
Dir.glob(configuration.public_path.join("sitemap*.xml"))
|
|
46
|
-
end
|
|
47
|
-
|
|
48
54
|
def remove_existing_sitemap_files
|
|
49
55
|
Dir.glob(configuration.public_path.join("sitemap*.xml*")).each do |file_path|
|
|
50
56
|
File.delete(file_path)
|
|
51
57
|
end
|
|
52
58
|
end
|
|
59
|
+
|
|
60
|
+
def sitemap_files
|
|
61
|
+
Dir.glob(configuration.public_path.join("sitemap*.xml")).sort
|
|
62
|
+
end
|
|
53
63
|
end
|
|
54
64
|
end
|
data/lib/indexmap/version.rb
CHANGED
|
@@ -2,19 +2,28 @@ namespace :sitemap do
|
|
|
2
2
|
desc "Create sitemap files"
|
|
3
3
|
task create: :environment do
|
|
4
4
|
runner = Indexmap::TaskRunner.new
|
|
5
|
-
runner.create
|
|
5
|
+
create_result = runner.create
|
|
6
6
|
runner.format
|
|
7
|
-
runner.validate
|
|
7
|
+
validated_files = runner.validate
|
|
8
|
+
|
|
9
|
+
puts "Created, formatted, and validated #{file_count(validated_files)} in #{public_directory(runner)}."
|
|
10
|
+
puts "IndexNow key file: #{create_result[:index_now_key_path]}" if create_result[:index_now_key_path]
|
|
8
11
|
end
|
|
9
12
|
|
|
10
13
|
desc "Format sitemap files for better readability"
|
|
11
14
|
task format: :environment do
|
|
12
|
-
Indexmap::TaskRunner.new
|
|
15
|
+
runner = Indexmap::TaskRunner.new
|
|
16
|
+
formatted_files = runner.format
|
|
17
|
+
|
|
18
|
+
puts "Formatted #{file_count(formatted_files)} in #{public_directory(runner)}."
|
|
13
19
|
end
|
|
14
20
|
|
|
15
21
|
desc "Validate sitemap shape and URL hygiene"
|
|
16
22
|
task validate: :environment do
|
|
17
|
-
Indexmap::TaskRunner.new
|
|
23
|
+
runner = Indexmap::TaskRunner.new
|
|
24
|
+
validated_files = runner.validate
|
|
25
|
+
|
|
26
|
+
puts "Validated #{file_count(validated_files)} for sitemap shape and URL hygiene."
|
|
18
27
|
end
|
|
19
28
|
|
|
20
29
|
desc "Ping all configured search engines"
|
|
@@ -36,10 +45,23 @@ namespace :sitemap do
|
|
|
36
45
|
Indexmap::Pinger::IndexNow.new.ping
|
|
37
46
|
end
|
|
38
47
|
|
|
39
|
-
desc "
|
|
48
|
+
desc "Ensure the IndexNow key file exists in public/"
|
|
40
49
|
task write_key: :environment do
|
|
41
|
-
path = Indexmap::TaskRunner.new.write_index_now_key
|
|
42
|
-
|
|
50
|
+
path = Indexmap::TaskRunner.new.write_index_now_key(generate_if_missing: true)
|
|
51
|
+
if path
|
|
52
|
+
puts "IndexNow key file available at #{path}."
|
|
53
|
+
else
|
|
54
|
+
puts "IndexNow key is not configured; skipped key file write."
|
|
55
|
+
end
|
|
43
56
|
end
|
|
44
57
|
end
|
|
58
|
+
|
|
59
|
+
def file_count(files)
|
|
60
|
+
count = Array(files).size
|
|
61
|
+
"#{count} sitemap #{(count == 1) ? "file" : "files"}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def public_directory(runner)
|
|
65
|
+
runner.public_path
|
|
66
|
+
end
|
|
45
67
|
end
|
|
@@ -17,6 +17,46 @@ class IndexmapPingerIndexNowTest < Minitest::Test
|
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def test_ensure_key_file_generates_a_key_when_configuration_is_missing
|
|
21
|
+
Dir.mktmpdir do |dir|
|
|
22
|
+
configuration = Indexmap::Configuration.new
|
|
23
|
+
configuration.base_url = "https://www.example.com"
|
|
24
|
+
configuration.public_path = Pathname(dir)
|
|
25
|
+
|
|
26
|
+
path = Indexmap::Pinger::IndexNow.new(configuration: configuration).ensure_key_file
|
|
27
|
+
|
|
28
|
+
assert_match(/\A[a-z0-9-]{8,128}\.txt\z/, path.basename.to_s)
|
|
29
|
+
assert_equal "#{path.basename(".txt")}\n", path.read
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_pings_using_existing_key_file_when_key_is_not_configured
|
|
34
|
+
Dir.mktmpdir do |dir|
|
|
35
|
+
public_path = Pathname(dir)
|
|
36
|
+
key_path = public_path.join("test-key-123.txt")
|
|
37
|
+
key_path.write("test-key-123\n")
|
|
38
|
+
write_sitemap_files(
|
|
39
|
+
public_path,
|
|
40
|
+
marketing_lastmod: "2026-04-18T00:00:00Z",
|
|
41
|
+
insights_lastmod: "2026-04-10T00:00:00Z"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
configuration = Indexmap::Configuration.new
|
|
45
|
+
configuration.base_url = "https://www.example.com"
|
|
46
|
+
configuration.public_path = public_path
|
|
47
|
+
|
|
48
|
+
indexnow_url = "https://api.indexnow.org/indexnow"
|
|
49
|
+
stub_request(:post, indexnow_url).to_return(status: 200, body: "", headers: {})
|
|
50
|
+
|
|
51
|
+
Indexmap::Pinger::IndexNow.new(configuration: configuration).ping
|
|
52
|
+
|
|
53
|
+
assert_requested(:post, indexnow_url, times: 1) do |request|
|
|
54
|
+
payload = JSON.parse(request.body)
|
|
55
|
+
assert_equal "test-key-123", payload.fetch("key")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
20
60
|
def test_pings_all_sitemap_urls_when_no_cutoff_is_provided
|
|
21
61
|
Dir.mktmpdir do |dir|
|
|
22
62
|
public_path = Pathname(dir)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class IndexmapTaskRunnerTest < Minitest::Test
|
|
6
|
+
def test_create_removes_existing_sitemap_files_writes_new_sitemap_and_key_file
|
|
7
|
+
Dir.mktmpdir do |dir|
|
|
8
|
+
public_path = Pathname(dir)
|
|
9
|
+
public_path.join("sitemap.xml").write("old")
|
|
10
|
+
public_path.join("sitemap-pages.xml.gz").write("old")
|
|
11
|
+
|
|
12
|
+
configuration = Indexmap::Configuration.new
|
|
13
|
+
configuration.base_url = "https://example.com"
|
|
14
|
+
configuration.public_path = public_path
|
|
15
|
+
configuration.sections = [
|
|
16
|
+
Indexmap::Section.new(
|
|
17
|
+
filename: "sitemap-pages.xml",
|
|
18
|
+
entries: [Indexmap::Entry.new(loc: "https://example.com/about")]
|
|
19
|
+
)
|
|
20
|
+
]
|
|
21
|
+
configuration.index_now.key = "test-key"
|
|
22
|
+
|
|
23
|
+
result = Indexmap::TaskRunner.new(configuration: configuration).create
|
|
24
|
+
|
|
25
|
+
assert_equal false, public_path.join("sitemap-pages.xml.gz").exist?
|
|
26
|
+
assert_includes public_path.join("sitemap.xml").read, "<sitemapindex"
|
|
27
|
+
assert_equal "test-key\n", public_path.join("test-key.txt").read
|
|
28
|
+
assert_equal [public_path.join("sitemap-pages.xml").to_s, public_path.join("sitemap.xml").to_s], result[:files]
|
|
29
|
+
assert_equal public_path.join("test-key.txt"), result[:index_now_key_path]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_write_index_now_key_returns_nil_when_key_is_not_configured
|
|
34
|
+
Dir.mktmpdir do |dir|
|
|
35
|
+
configuration = Indexmap::Configuration.new
|
|
36
|
+
configuration.base_url = "https://example.com"
|
|
37
|
+
configuration.public_path = Pathname(dir)
|
|
38
|
+
configuration.sections = [
|
|
39
|
+
Indexmap::Section.new(
|
|
40
|
+
filename: "sitemap-pages.xml",
|
|
41
|
+
entries: [Indexmap::Entry.new(loc: "https://example.com/about")]
|
|
42
|
+
)
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
result = Indexmap::TaskRunner.new(configuration: configuration).write_index_now_key
|
|
46
|
+
|
|
47
|
+
assert_nil result
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_write_index_now_key_can_generate_a_key_when_requested
|
|
52
|
+
Dir.mktmpdir do |dir|
|
|
53
|
+
configuration = Indexmap::Configuration.new
|
|
54
|
+
configuration.base_url = "https://example.com"
|
|
55
|
+
configuration.public_path = Pathname(dir)
|
|
56
|
+
|
|
57
|
+
result = Indexmap::TaskRunner.new(configuration: configuration).write_index_now_key(generate_if_missing: true)
|
|
58
|
+
|
|
59
|
+
assert_match(/\A[a-z0-9-]{8,128}\.txt\z/, result.basename.to_s)
|
|
60
|
+
assert_equal "#{result.basename(".txt")}\n", result.read
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
require "test_helper"
|
|
4
4
|
|
|
5
5
|
class IndexmapValidatorTest < Minitest::Test
|
|
6
|
+
def test_validate_raises_for_missing_sitemap
|
|
7
|
+
Dir.mktmpdir do |directory|
|
|
8
|
+
path = Pathname(directory).join("missing.xml")
|
|
9
|
+
|
|
10
|
+
error = assert_raises(Indexmap::ValidationError) do
|
|
11
|
+
Indexmap::Validator.new(path: path).validate!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
assert_equal "Missing sitemap file: #{path}", error.message
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
6
18
|
def test_validate_raises_for_duplicate_urls
|
|
7
19
|
Dir.mktmpdir do |directory|
|
|
8
20
|
path = Pathname(directory).join("sitemap.xml")
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: indexmap
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Paulo Fidalgo
|
|
@@ -122,6 +122,20 @@ dependencies:
|
|
|
122
122
|
- - "~>"
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '13.0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: simplecov
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0.22'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0.22'
|
|
125
139
|
- !ruby/object:Gem::Dependency
|
|
126
140
|
name: standard
|
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -183,6 +197,7 @@ files:
|
|
|
183
197
|
- test/indexmap/path_test.rb
|
|
184
198
|
- test/indexmap/pinger/google_test.rb
|
|
185
199
|
- test/indexmap/pinger/index_now_test.rb
|
|
200
|
+
- test/indexmap/task_runner_test.rb
|
|
186
201
|
- test/indexmap/validator_test.rb
|
|
187
202
|
- test/indexmap/writer_test.rb
|
|
188
203
|
- test/test_helper.rb
|