indexmap 0.6.0 → 0.7.1
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 +112 -2
- data/README.md +100 -78
- data/lib/indexmap/configuration.rb +3 -6
- data/lib/indexmap/creator.rb +22 -35
- data/lib/indexmap/index_now_configuration.rb +12 -5
- data/lib/indexmap/output.rb +3 -5
- data/lib/indexmap/parser.rb +26 -14
- data/lib/indexmap/pinger/base.rb +5 -1
- data/lib/indexmap/pinger/google.rb +2 -2
- data/lib/indexmap/pinger/index_now.rb +21 -24
- data/lib/indexmap/storage/active_storage.rb +105 -0
- data/lib/indexmap/storage/file.rb +11 -0
- data/lib/indexmap/storage/filesystem.rb +77 -0
- data/lib/indexmap/storage/memory.rb +61 -0
- data/lib/indexmap/task_runner.rb +35 -8
- data/lib/indexmap/validator.rb +42 -30
- data/lib/indexmap/version.rb +1 -1
- data/lib/indexmap/writer.rb +2 -9
- data/lib/indexmap.rb +4 -1
- data/lib/tasks/indexmap_tasks.rake +13 -5
- data/test/indexmap/configuration_test.rb +98 -129
- data/test/indexmap/parser_test.rb +44 -3
- data/test/indexmap/pinger/google_test.rb +101 -123
- data/test/indexmap/pinger/index_now_test.rb +148 -179
- data/test/indexmap/storage_test.rb +123 -0
- data/test/indexmap/task_runner_test.rb +104 -63
- data/test/indexmap/validator_test.rb +96 -92
- data/test/indexmap/writer_test.rb +63 -74
- data/test/release_task_test.rb +86 -0
- metadata +8 -4
- data/lib/indexmap/path.rb +0 -42
- data/test/indexmap/path_test.rb +0 -28
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64a9d1c671519fea6ba6a46b7f67daed2784ad5aaccf2594dc3aa0a374f55854
|
|
4
|
+
data.tar.gz: 50f6bc13a8097194dec9736b96c8cc6baf0f76429edf0175372aee97991c63f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2ce92a1da076303265c03ff833585b069215c8417b134407850770c64ae04b3ab93fcf894484874e710e304c6b3c94f19247d70073aaa6ba5e170f70212e4992
|
|
7
|
+
data.tar.gz: 991f39cd9db707dd79e7a404e636aaea8c8a1db07ce5b59d2daf9d73c33a55d39c252d6edef2adf8fc98ea22e153f8619aee4f67f9fd11c3fccf56b473bb1ffa
|
data/CHANGELOG.md
CHANGED
|
@@ -5,14 +5,124 @@ 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.7.1] - 2026-05-31
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
|
|
13
|
+
- document google search console credentials
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- preserve release changelog history ([#13](https://github.com/ethos-link/indexmap/pull/13))
|
|
21
|
+
|
|
22
|
+
- improve sitemap create output ([#14](https://github.com/ethos-link/indexmap/pull/14))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## [0.7.0] - 2026-05-08
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- avoid rewriting existing IndexNow key files ([#11](https://github.com/ethos-link/indexmap/pull/11))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
8
35
|
## [0.6.0] - 2026-05-01
|
|
9
36
|
|
|
10
37
|
|
|
11
38
|
### Added
|
|
12
39
|
|
|
13
|
-
- add the url count to google ping output (#9)
|
|
40
|
+
- add the url count to google ping output ([#9](https://github.com/ethos-link/indexmap/pull/9))
|
|
41
|
+
|
|
42
|
+
- support named sitemap outputs ([#10](https://github.com/ethos-link/indexmap/pull/10))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## [0.5.0] - 2026-04-24
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- namespace rake tasks and harden sitemap validation ([#8](https://github.com/ethos-link/indexmap/pull/8))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## [0.4.2] - 2026-04-23
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- harden sitemap pinging and indexnow key handling ([#7](https://github.com/ethos-link/indexmap/pull/7))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## [0.4.1] - 2026-04-22
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
- add output to ping tasks ([#6](https://github.com/ethos-link/indexmap/pull/6))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## [0.4.0] - 2026-04-22
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
### Documentation
|
|
77
|
+
|
|
78
|
+
- improve the task messages ([#4](https://github.com/ethos-link/indexmap/pull/4))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
## [0.3.1] - 2026-04-22
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
|
|
87
|
+
- fix changelog generation ([#2](https://github.com/ethos-link/indexmap/pull/2))
|
|
88
|
+
|
|
89
|
+
- harden indexmap runtime defaults and test coverage ([#3](https://github.com/ethos-link/indexmap/pull/3))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
## [0.3.0] - 2026-04-22
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
- expand indexmap with sitemap parsing, validation, and search engine pinging
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
## [0.2.1] - 2026-04-21
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
### Fixed
|
|
106
|
+
|
|
107
|
+
- publish built gem in release workflow
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
## [0.2.0] - 2026-04-21
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
### Added
|
|
115
|
+
|
|
116
|
+
- add single-file sitemap mode
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
## [0.1.0] - 2026-04-21
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
### Added
|
|
14
124
|
|
|
15
|
-
-
|
|
125
|
+
- bootstrap indexmap gem
|
|
16
126
|
|
|
17
127
|
|
|
18
128
|
|
data/README.md
CHANGED
|
@@ -34,6 +34,17 @@ Or install it directly:
|
|
|
34
34
|
gem install indexmap
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
Upgrading an existing app? Read [UPGRADE.md](UPGRADE.md) before deploying,
|
|
38
|
+
especially if the app uses custom storage or stores sitemap files under a
|
|
39
|
+
directory prefix such as `sitemaps/`.
|
|
40
|
+
|
|
41
|
+
## Documentation
|
|
42
|
+
|
|
43
|
+
- [Search engine ping](docs/search-engine-ping.md): Google Search Console
|
|
44
|
+
credentials, Google property configuration, and IndexNow key setup.
|
|
45
|
+
- [UPGRADE.md](UPGRADE.md): host-app migration steps for public contract
|
|
46
|
+
changes.
|
|
47
|
+
|
|
37
48
|
## Ruby Usage
|
|
38
49
|
|
|
39
50
|
```ruby
|
|
@@ -51,7 +62,6 @@ sections = [
|
|
|
51
62
|
|
|
52
63
|
Indexmap::Writer.new(
|
|
53
64
|
sections: sections,
|
|
54
|
-
public_path: Pathname("public"),
|
|
55
65
|
base_url: "https://example.com"
|
|
56
66
|
).write
|
|
57
67
|
```
|
|
@@ -63,7 +73,12 @@ In an initializer:
|
|
|
63
73
|
```ruby
|
|
64
74
|
Indexmap.configure do |config|
|
|
65
75
|
config.base_url = -> { "https://example.com" }
|
|
66
|
-
config.
|
|
76
|
+
config.storage = -> do
|
|
77
|
+
Indexmap::Storage::Filesystem.new(
|
|
78
|
+
path: Rails.public_path,
|
|
79
|
+
public_url: config.base_url
|
|
80
|
+
)
|
|
81
|
+
end
|
|
67
82
|
config.sections = -> do
|
|
68
83
|
[
|
|
69
84
|
Indexmap::Section.new(
|
|
@@ -85,26 +100,26 @@ bin/rails indexmap:sitemap:format
|
|
|
85
100
|
bin/rails indexmap:sitemap:validate
|
|
86
101
|
```
|
|
87
102
|
|
|
88
|
-
`indexmap:sitemap:create` is the main task. It
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
fails.
|
|
103
|
+
`indexmap:sitemap:create` is the main task. It builds sitemap files in memory,
|
|
104
|
+
formats them, validates the result, then writes the final XML files to the
|
|
105
|
+
configured storage. Existing sitemap files are left untouched if generation or
|
|
106
|
+
validation fails.
|
|
92
107
|
|
|
93
108
|
### Default Index Mode
|
|
94
109
|
|
|
95
110
|
This is the default behavior. `indexmap` writes:
|
|
96
111
|
|
|
97
|
-
- `
|
|
112
|
+
- `sitemap.xml` as a sitemap index
|
|
98
113
|
- one or more child sitemap files from `config.sections`
|
|
99
114
|
|
|
100
115
|
### Single-File Mode
|
|
101
116
|
|
|
102
|
-
For sites that only want one `
|
|
117
|
+
For sites that only want one `sitemap.xml` file:
|
|
103
118
|
|
|
104
119
|
```ruby
|
|
105
120
|
Indexmap.configure do |config|
|
|
106
121
|
config.base_url = -> { "https://example.com" }
|
|
107
|
-
config.
|
|
122
|
+
config.storage = -> { Indexmap::Storage::Filesystem.new(path: Rails.public_path, public_url: config.base_url) }
|
|
108
123
|
config.format = :single_file
|
|
109
124
|
config.entries = -> do
|
|
110
125
|
[
|
|
@@ -122,13 +137,12 @@ In `:single_file` mode, `indexmap` writes a `urlset` directly to `sitemap.xml` a
|
|
|
122
137
|
Most apps only need the default output. Use named outputs when one part of the
|
|
123
138
|
sitemap must be generated separately, for example when static pages can be
|
|
124
139
|
generated during deploy but database-heavy pages should refresh later. Named
|
|
125
|
-
outputs
|
|
126
|
-
serving are application concerns.
|
|
140
|
+
outputs write through the same configured storage as the default output.
|
|
127
141
|
|
|
128
142
|
```ruby
|
|
129
143
|
Indexmap.configure do |config|
|
|
130
144
|
config.base_url = -> { "https://example.com" }
|
|
131
|
-
config.
|
|
145
|
+
config.storage = -> { Indexmap::Storage::Filesystem.new(path: Rails.root.join("storage/sitemaps"), public_url: config.base_url) }
|
|
132
146
|
config.sections = -> { Sitemap.sections }
|
|
133
147
|
|
|
134
148
|
config.output :insights_data do |output|
|
|
@@ -151,12 +165,57 @@ Generate only the named output:
|
|
|
151
165
|
Indexmap.create(:insights_data)
|
|
152
166
|
```
|
|
153
167
|
|
|
154
|
-
Named outputs inherit `base_url
|
|
155
|
-
|
|
168
|
+
Named outputs inherit `base_url` and `format` from the main configuration unless
|
|
169
|
+
you override them. Storage is configured once and shared by every output.
|
|
170
|
+
|
|
171
|
+
`Indexmap.create` uses the same safe publish flow as the rake task: build,
|
|
172
|
+
format, validate, and then write the final XML file or files to storage.
|
|
173
|
+
|
|
174
|
+
### Storage
|
|
175
|
+
|
|
176
|
+
Every `indexmap` operation reads and writes through `config.storage`. The storage
|
|
177
|
+
object is the source of truth for generation, validation, parsing, Google
|
|
178
|
+
submission, IndexNow submission, and IndexNow verification files.
|
|
179
|
+
|
|
180
|
+
The filesystem adapter stores files in a directory and exposes public URLs from
|
|
181
|
+
the same filenames:
|
|
182
|
+
|
|
183
|
+
```ruby
|
|
184
|
+
Indexmap.configure do |config|
|
|
185
|
+
config.base_url = "https://example.com"
|
|
186
|
+
config.storage = Indexmap::Storage::Filesystem.new(
|
|
187
|
+
path: Rails.public_path,
|
|
188
|
+
public_url: "https://example.com"
|
|
189
|
+
)
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Rails apps that store sitemap files in Active Storage can use the optional
|
|
194
|
+
adapter. `indexmap` does not depend on `activestorage`; this adapter only uses
|
|
195
|
+
the model and attachment object you pass in.
|
|
196
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
Indexmap.configure do |config|
|
|
199
|
+
config.base_url = "https://example.com"
|
|
200
|
+
config.storage = Indexmap::Storage::ActiveStorage.new(
|
|
201
|
+
model: SitemapArtifact,
|
|
202
|
+
filename_column: :filename,
|
|
203
|
+
attachment: :file,
|
|
204
|
+
public_url: "https://example.com"
|
|
205
|
+
)
|
|
206
|
+
end
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Custom storage backends can implement the same small interface:
|
|
156
210
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
211
|
+
```ruby
|
|
212
|
+
storage.write(filename, body, content_type:)
|
|
213
|
+
storage.read(filename)
|
|
214
|
+
storage.exist?(filename)
|
|
215
|
+
storage.list(prefix:, suffix:)
|
|
216
|
+
storage.delete(filename)
|
|
217
|
+
storage.public_url(filename)
|
|
218
|
+
```
|
|
160
219
|
|
|
161
220
|
### Deferred Dynamic Sections
|
|
162
221
|
|
|
@@ -168,7 +227,7 @@ replaced successfully.
|
|
|
168
227
|
```ruby
|
|
169
228
|
Indexmap.configure do |config|
|
|
170
229
|
config.base_url = -> { "https://example.com" }
|
|
171
|
-
config.
|
|
230
|
+
config.storage = -> { Indexmap::Storage::Filesystem.new(path: Rails.root.join("storage/sitemaps"), public_url: config.base_url) }
|
|
172
231
|
config.sections = -> { Sitemap.sections }
|
|
173
232
|
|
|
174
233
|
config.output :insights_data do |output|
|
|
@@ -201,7 +260,7 @@ while database-dependent output is refreshed by the job backend.
|
|
|
201
260
|
`indexmap` also includes small utilities for working with generated sitemap files:
|
|
202
261
|
|
|
203
262
|
```ruby
|
|
204
|
-
parser = Indexmap::Parser.new(
|
|
263
|
+
parser = Indexmap::Parser.new(source: "sitemap.xml")
|
|
205
264
|
parser.paths
|
|
206
265
|
# => ["/", "/about", "/articles/example"]
|
|
207
266
|
|
|
@@ -224,6 +283,8 @@ The built-in validator checks for:
|
|
|
224
283
|
## Search Engine Ping
|
|
225
284
|
|
|
226
285
|
`indexmap` can ping Google Search Console and IndexNow after sitemap generation.
|
|
286
|
+
See [Search engine ping](docs/search-engine-ping.md) for Google credential
|
|
287
|
+
setup, Search Console property configuration, and IndexNow key provisioning.
|
|
227
288
|
|
|
228
289
|
Available rake tasks:
|
|
229
290
|
|
|
@@ -235,59 +296,9 @@ bin/rails indexmap:index_now:write_key
|
|
|
235
296
|
bin/rails indexmap:ping
|
|
236
297
|
```
|
|
237
298
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
```ruby
|
|
243
|
-
Indexmap.configure do |config|
|
|
244
|
-
config.google.credentials = -> { ENV["GOOGLE_SITEMAP"] }
|
|
245
|
-
end
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
If `config.google.credentials` is blank, `indexmap:google:ping` skips Google submission.
|
|
249
|
-
|
|
250
|
-
You can optionally override the Search Console property identifier:
|
|
251
|
-
|
|
252
|
-
```ruby
|
|
253
|
-
Indexmap.configure do |config|
|
|
254
|
-
config.google.credentials = -> { ENV["GOOGLE_SITEMAP"] }
|
|
255
|
-
config.google.property = -> { "sc-domain:example.com" }
|
|
256
|
-
end
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
If `config.google.property` is not set, `indexmap` defaults to `sc-domain:<host>`.
|
|
260
|
-
|
|
261
|
-
### IndexNow
|
|
262
|
-
|
|
263
|
-
IndexNow submission requires a key. `indexmap` supports two ways to provide it:
|
|
264
|
-
|
|
265
|
-
- set `config.index_now.key`
|
|
266
|
-
- or keep a valid verification file at `public/<key>.txt`
|
|
267
|
-
|
|
268
|
-
Configured-key example:
|
|
269
|
-
|
|
270
|
-
```ruby
|
|
271
|
-
Indexmap.configure do |config|
|
|
272
|
-
config.index_now.key = -> { ENV["INDEXNOW_KEY"] }
|
|
273
|
-
end
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
If `config.index_now.key` is set, `indexmap:sitemap:create` also writes the matching `public/<key>.txt` verification file automatically.
|
|
277
|
-
|
|
278
|
-
If you prefer the file-based flow, run:
|
|
279
|
-
|
|
280
|
-
```bash
|
|
281
|
-
bin/rails indexmap:index_now:write_key
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
That task:
|
|
285
|
-
|
|
286
|
-
- reuses an existing valid key file when present
|
|
287
|
-
- otherwise generates a new key in `public/<key>.txt`
|
|
288
|
-
- makes that key available to `indexmap:index_now:ping` without adding `config.index_now.key`
|
|
289
|
-
|
|
290
|
-
If neither a configured key nor a valid key file is present, `indexmap:index_now:ping` skips IndexNow submission.
|
|
299
|
+
If Google credentials are blank, `indexmap:google:ping` skips Google
|
|
300
|
+
submission. If neither a configured IndexNow key nor a valid key file is
|
|
301
|
+
present, `indexmap:index_now:ping` skips IndexNow submission.
|
|
291
302
|
|
|
292
303
|
## Development
|
|
293
304
|
|
|
@@ -315,7 +326,12 @@ Note: `Gemfile.lock` is intentionally not tracked for this gem, following normal
|
|
|
315
326
|
|
|
316
327
|
### Git hooks
|
|
317
328
|
|
|
318
|
-
We use [lefthook](https://lefthook.dev/) with the Ruby
|
|
329
|
+
We use [lefthook](https://lefthook.dev/) with the Ruby
|
|
330
|
+
[commitlint](https://github.com/arandilopez/commitlint) gem to enforce
|
|
331
|
+
Conventional Commits on every commit. We also use
|
|
332
|
+
[Standard Ruby](https://standardrb.com/) to keep code style consistent. CI
|
|
333
|
+
validates commit messages, Standard Ruby, tests, and git-cliff changelog
|
|
334
|
+
generation on pull requests and pushes to main/master.
|
|
319
335
|
|
|
320
336
|
Run the hook installer once per clone:
|
|
321
337
|
|
|
@@ -325,11 +341,16 @@ bundle exec lefthook install
|
|
|
325
341
|
|
|
326
342
|
## Release
|
|
327
343
|
|
|
328
|
-
Releases are tag-driven and published by GitHub Actions to RubyGems.
|
|
344
|
+
Releases are tag-driven and published by GitHub Actions to RubyGems.
|
|
345
|
+
Local release commands never publish directly.
|
|
329
346
|
|
|
330
|
-
Install [git-cliff](https://git-cliff.org/) locally before preparing a
|
|
347
|
+
Install [git-cliff](https://git-cliff.org/) locally before preparing a
|
|
348
|
+
release. The release task prepends the next `CHANGELOG.md` section from
|
|
349
|
+
Conventional Commits.
|
|
331
350
|
|
|
332
|
-
Before preparing a release, make sure you are on `main` or `master` with a
|
|
351
|
+
Before preparing a release, make sure you are on `main` or `master` with a
|
|
352
|
+
clean worktree. If the release contains a breaking public-contract change,
|
|
353
|
+
update `UPGRADE.md` with the host-app migration steps first.
|
|
333
354
|
|
|
334
355
|
Then run one of:
|
|
335
356
|
|
|
@@ -342,12 +363,13 @@ bundle exec rake 'release:prepare[0.1.0]'
|
|
|
342
363
|
|
|
343
364
|
The task will:
|
|
344
365
|
|
|
345
|
-
1.
|
|
366
|
+
1. Prepend the next `CHANGELOG.md` section with `git-cliff`.
|
|
346
367
|
1. Update `lib/indexmap/version.rb`.
|
|
347
368
|
1. Commit the release changes.
|
|
348
369
|
1. Create and push the `vX.Y.Z` tag.
|
|
349
370
|
|
|
350
|
-
The `Release` workflow then runs tests, publishes the gem to RubyGems,
|
|
371
|
+
The `Release` workflow then runs tests, publishes the gem to RubyGems,
|
|
372
|
+
and creates the GitHub release from the changelog entry.
|
|
351
373
|
|
|
352
374
|
## License
|
|
353
375
|
|
|
@@ -4,7 +4,7 @@ module Indexmap
|
|
|
4
4
|
class Configuration
|
|
5
5
|
VALID_FORMATS = %i[index single_file].freeze
|
|
6
6
|
|
|
7
|
-
attr_writer :base_url, :entries, :format, :index_filename, :
|
|
7
|
+
attr_writer :base_url, :entries, :format, :index_filename, :sections, :storage
|
|
8
8
|
|
|
9
9
|
def initialize
|
|
10
10
|
@format = :index
|
|
@@ -38,11 +38,8 @@ module Indexmap
|
|
|
38
38
|
@index_now ||= IndexNowConfiguration.new
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def
|
|
42
|
-
|
|
43
|
-
return Pathname("public") if value.nil?
|
|
44
|
-
|
|
45
|
-
Pathname(value)
|
|
41
|
+
def storage
|
|
42
|
+
resolve(@storage) || Storage::Filesystem.new(path: "public", public_url: base_url)
|
|
46
43
|
end
|
|
47
44
|
|
|
48
45
|
def sections
|
data/lib/indexmap/creator.rb
CHANGED
|
@@ -1,74 +1,61 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "nokogiri"
|
|
4
|
-
require "tmpdir"
|
|
5
4
|
|
|
6
5
|
module Indexmap
|
|
7
6
|
class Creator
|
|
8
|
-
ValidationConfiguration = Struct.new(:base_url, keyword_init: true)
|
|
7
|
+
ValidationConfiguration = Struct.new(:base_url, :index_filename, :storage, keyword_init: true)
|
|
9
8
|
|
|
10
9
|
def initialize(output:)
|
|
11
10
|
@output = output
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def create
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
written_files = write_to(staging_path)
|
|
20
|
-
sitemap_files = sitemap_files_in(staging_path)
|
|
21
|
-
|
|
22
|
-
format(sitemap_files)
|
|
23
|
-
validate(staging_path.join(output.index_filename))
|
|
24
|
-
|
|
25
|
-
publish(sitemap_files)
|
|
26
|
-
written_files.map { |path| output.public_path.join(path.basename) }
|
|
27
|
-
end
|
|
14
|
+
files = format(write)
|
|
15
|
+
validate(files)
|
|
16
|
+
publish(files)
|
|
17
|
+
files.map(&:filename)
|
|
28
18
|
end
|
|
29
19
|
|
|
30
20
|
private
|
|
31
21
|
|
|
32
22
|
attr_reader :output
|
|
33
23
|
|
|
34
|
-
def
|
|
35
|
-
output.writer.
|
|
36
|
-
writer.public_path = staging_path
|
|
37
|
-
end.write
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def sitemap_files_in(path)
|
|
41
|
-
path.glob("sitemap*.xml").sort
|
|
24
|
+
def write
|
|
25
|
+
output.writer.write
|
|
42
26
|
end
|
|
43
27
|
|
|
44
28
|
def format(files)
|
|
45
|
-
files.
|
|
29
|
+
files.map do |file|
|
|
46
30
|
document = Nokogiri::XML(
|
|
47
|
-
|
|
31
|
+
file.body,
|
|
48
32
|
nil,
|
|
49
33
|
nil,
|
|
50
34
|
Nokogiri::XML::ParseOptions::DEFAULT_XML | Nokogiri::XML::ParseOptions::NOBLANKS
|
|
51
35
|
)
|
|
52
36
|
save_options = Nokogiri::XML::Node::SaveOptions::FORMAT | Nokogiri::XML::Node::SaveOptions::AS_XML
|
|
53
37
|
|
|
54
|
-
|
|
38
|
+
Storage::File.new(
|
|
39
|
+
filename: file.filename,
|
|
40
|
+
body: document.to_xml(indent: 2, save_with: save_options),
|
|
41
|
+
content_type: file.content_type
|
|
42
|
+
)
|
|
55
43
|
end
|
|
56
44
|
end
|
|
57
45
|
|
|
58
|
-
def validate(
|
|
46
|
+
def validate(files)
|
|
59
47
|
Validator.new(
|
|
60
|
-
configuration: ValidationConfiguration.new(
|
|
61
|
-
|
|
48
|
+
configuration: ValidationConfiguration.new(
|
|
49
|
+
base_url: output.base_url,
|
|
50
|
+
index_filename: output.index_filename,
|
|
51
|
+
storage: Storage::Memory.new(files)
|
|
52
|
+
)
|
|
62
53
|
).validate!
|
|
63
54
|
end
|
|
64
55
|
|
|
65
56
|
def publish(files)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
files.map do |file_path|
|
|
69
|
-
final_path = output.public_path.join(file_path.basename)
|
|
70
|
-
File.rename(file_path, final_path)
|
|
71
|
-
final_path
|
|
57
|
+
files.each do |file|
|
|
58
|
+
output.storage.write(file.filename, file.body, content_type: file.content_type)
|
|
72
59
|
end
|
|
73
60
|
end
|
|
74
61
|
end
|
|
@@ -5,7 +5,7 @@ module Indexmap
|
|
|
5
5
|
DEFAULT_ENDPOINT = "https://api.indexnow.org"
|
|
6
6
|
DEFAULT_MAX_URLS_PER_REQUEST = 500
|
|
7
7
|
|
|
8
|
-
attr_writer :dry_run, :endpoint, :key, :
|
|
8
|
+
attr_writer :dry_run, :endpoint, :key, :key_filename, :max_urls_per_request, :write_key_file
|
|
9
9
|
|
|
10
10
|
def dry_run?
|
|
11
11
|
value = resolve(@dry_run)
|
|
@@ -21,12 +21,19 @@ module Indexmap
|
|
|
21
21
|
resolve(@key)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
return
|
|
24
|
+
def write_key_file?
|
|
25
|
+
value = resolve(@write_key_file)
|
|
26
|
+
return !key.to_s.strip.empty? if value.nil?
|
|
27
|
+
|
|
28
|
+
value == true || value.to_s == "1"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def key_filename(key: self.key)
|
|
32
|
+
configured_filename = resolve(@key_filename)
|
|
33
|
+
return configured_filename unless configured_filename.to_s.strip.empty?
|
|
27
34
|
return if key.to_s.strip.empty?
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
"#{key}.txt"
|
|
30
37
|
end
|
|
31
38
|
|
|
32
39
|
def max_urls_per_request
|
data/lib/indexmap/output.rb
CHANGED
|
@@ -4,7 +4,7 @@ module Indexmap
|
|
|
4
4
|
class Output
|
|
5
5
|
VALID_FORMATS = %i[index single_file].freeze
|
|
6
6
|
|
|
7
|
-
attr_writer :base_url, :entries, :format, :index_filename, :
|
|
7
|
+
attr_writer :base_url, :entries, :format, :index_filename, :sections
|
|
8
8
|
|
|
9
9
|
def initialize(configuration:)
|
|
10
10
|
@configuration = configuration
|
|
@@ -29,9 +29,8 @@ module Indexmap
|
|
|
29
29
|
resolve(@index_filename) || configuration.index_filename
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def
|
|
33
|
-
|
|
34
|
-
Pathname(value)
|
|
32
|
+
def storage
|
|
33
|
+
configuration.storage
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
def sections
|
|
@@ -57,7 +56,6 @@ module Indexmap
|
|
|
57
56
|
entries: entries,
|
|
58
57
|
format: format,
|
|
59
58
|
sections: sections,
|
|
60
|
-
public_path: public_path,
|
|
61
59
|
base_url: base_url,
|
|
62
60
|
index_filename: index_filename
|
|
63
61
|
)
|