site_maps 0.0.1.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +45 -0
  3. data/.gitignore +16 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +36 -0
  6. data/.tool-versions +1 -0
  7. data/CHANGELOG.md +8 -0
  8. data/Gemfile +18 -0
  9. data/Gemfile.lock +134 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +186 -0
  12. data/Rakefile +4 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +7 -0
  15. data/exec/site_maps +9 -0
  16. data/lib/site-maps.rb +3 -0
  17. data/lib/site_maps/adapters/adapter.rb +80 -0
  18. data/lib/site_maps/adapters/aws_sdk/config.rb +51 -0
  19. data/lib/site_maps/adapters/aws_sdk/location.rb +9 -0
  20. data/lib/site_maps/adapters/aws_sdk/storage.rb +52 -0
  21. data/lib/site_maps/adapters/aws_sdk.rb +31 -0
  22. data/lib/site_maps/adapters/file_system/config.rb +5 -0
  23. data/lib/site_maps/adapters/file_system/location.rb +35 -0
  24. data/lib/site_maps/adapters/file_system/storage.rb +61 -0
  25. data/lib/site_maps/adapters/file_system.rb +26 -0
  26. data/lib/site_maps/adapters/noop.rb +18 -0
  27. data/lib/site_maps/atomic_repository.rb +24 -0
  28. data/lib/site_maps/builder/link.rb +27 -0
  29. data/lib/site_maps/builder/normalizer.rb +48 -0
  30. data/lib/site_maps/builder/sitemap_index/item.rb +35 -0
  31. data/lib/site_maps/builder/sitemap_index.rb +40 -0
  32. data/lib/site_maps/builder/url.rb +152 -0
  33. data/lib/site_maps/builder/url_set.rb +92 -0
  34. data/lib/site_maps/cli.rb +68 -0
  35. data/lib/site_maps/configuration.rb +119 -0
  36. data/lib/site_maps/incremental_location.rb +62 -0
  37. data/lib/site_maps/notification/bus.rb +90 -0
  38. data/lib/site_maps/notification/event.rb +50 -0
  39. data/lib/site_maps/notification/publisher.rb +78 -0
  40. data/lib/site_maps/notification.rb +36 -0
  41. data/lib/site_maps/primitives/array.rb +15 -0
  42. data/lib/site_maps/primitives/output.rb +66 -0
  43. data/lib/site_maps/primitives/string.rb +43 -0
  44. data/lib/site_maps/process.rb +29 -0
  45. data/lib/site_maps/railtie.rb +18 -0
  46. data/lib/site_maps/runner/event_listener.rb +78 -0
  47. data/lib/site_maps/runner.rb +136 -0
  48. data/lib/site_maps/sitemap_builder.rb +75 -0
  49. data/lib/site_maps/sitemap_reader.rb +56 -0
  50. data/lib/site_maps/version.rb +5 -0
  51. data/lib/site_maps.rb +112 -0
  52. data/site_maps.gemspec +44 -0
  53. metadata +172 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 58b8a07d1b6a6b8774a2ee2d1dd0e3ae9ebea70095ebbf5b3c0abe4edfdece6b
4
+ data.tar.gz: 472ea2dcc6760eb0f072f9ffb30b8f31fbf4fcbc25041802f44daed83c81f27c
5
+ SHA512:
6
+ metadata.gz: f86928a65fb91dc0f655bf45d87c3b2eedcb1fdeb08a99f509346ec9e7d8388220386322069ba6a9ecc9fb7abab667e5683ea1be42816a8dca83462251f58f27
7
+ data.tar.gz: 4fafbd0e7da884694f13bf4cc6ff47db28ad8e6b04fcc0680eb671d45fbddafbec1f3d0f6420f5d6190ee439b3f9ecf74cc1307e593c8d11b97e230255788e2f
@@ -0,0 +1,45 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ rubocop:
11
+ name: "Rubocop"
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: "3.0"
18
+ bundler-cache: true
19
+ - name: Run rubocop
20
+ run: |
21
+ bundle exec rubocop --parallel
22
+ tests:
23
+ name: Tests
24
+ runs-on: ubuntu-latest
25
+ strategy:
26
+ fail-fast: false
27
+ matrix:
28
+ ruby-version:
29
+ - "3.0"
30
+ - "3.1"
31
+ - "3.2"
32
+ - "3.3"
33
+ steps:
34
+ - name: Checkout code
35
+ uses: actions/checkout@v4
36
+ - name: Setup Ruby and install gems
37
+ uses: ruby/setup-ruby@v1
38
+ with:
39
+ ruby-version: ${{ matrix.ruby-version }}
40
+ bundler-cache: true
41
+ - name: Install dependencies
42
+ run: bundle install --jobs 4 --retry 3
43
+ - name: Run tests
44
+ run: bundle exec rspec
45
+
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.env
3
+ /.rspec_status
4
+ /.yardoc
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.gem
12
+ /spec/dummy/db/*.sqlite3
13
+ /spec/dummy/db/*.sqlite3-*
14
+ /spec/dummy/log/*.log
15
+ /spec/dummy/storage/
16
+ /spec/dummy/tmp/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,36 @@
1
+ inherit_mode:
2
+ merge:
3
+ - Exclude
4
+
5
+ require:
6
+ - rubocop-performance
7
+ - rubocop-rspec
8
+ - standard/cop/block_single_line_braces
9
+
10
+ inherit_gem:
11
+ standard: config/base.yml
12
+
13
+ AllCops:
14
+ TargetRubyVersion: 2.5
15
+ SuggestExtensions: false
16
+ Exclude:
17
+ - "db/**/*"
18
+ - "tmp/**/*"
19
+ - "vendor/**/*"
20
+ - "spec/support/hooks/notification.rb" # I'll refactor this rspec matcher to allow use things like an_instance_of
21
+ NewCops: enable
22
+
23
+ RSpec/MultipleExpectations:
24
+ Enabled: false
25
+
26
+ RSpec/ExampleLength:
27
+ Enabled: false
28
+
29
+ RSpec/MultipleMemoizedHelpers:
30
+ Enabled: false
31
+
32
+ RSpec/MessageSpies:
33
+ Enabled: false
34
+
35
+ RSpec/StubbedMock:
36
+ Enabled: false
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.3.5
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## 0.0.1.beta1 - 2024-11-07
8
+ The first release of the gem
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "aws-sdk-s3"
6
+ gem "dotenv"
7
+ gem "nokogiri"
8
+ gem "pry"
9
+ gem "rspec"
10
+ gem "rubocop-performance"
11
+ gem "rubocop-rspec"
12
+ gem "rubocop"
13
+ gem "standard"
14
+ gem "timecop"
15
+ gem "webmock"
16
+
17
+ # Specify your gem's dependencies in site_maps.gemspec
18
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,134 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ site_maps (0.0.1.beta1)
5
+ builder (~> 3.0)
6
+ concurrent-ruby (>= 1.1)
7
+ rack (>= 2.0)
8
+ thor
9
+ zeitwerk
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ addressable (2.8.7)
15
+ public_suffix (>= 2.0.2, < 7.0)
16
+ ast (2.4.2)
17
+ aws-eventstream (1.3.0)
18
+ aws-partitions (1.1003.0)
19
+ aws-sdk-core (3.212.0)
20
+ aws-eventstream (~> 1, >= 1.3.0)
21
+ aws-partitions (~> 1, >= 1.992.0)
22
+ aws-sigv4 (~> 1.9)
23
+ jmespath (~> 1, >= 1.6.1)
24
+ aws-sdk-kms (1.95.0)
25
+ aws-sdk-core (~> 3, >= 3.210.0)
26
+ aws-sigv4 (~> 1.5)
27
+ aws-sdk-s3 (1.170.0)
28
+ aws-sdk-core (~> 3, >= 3.210.0)
29
+ aws-sdk-kms (~> 1)
30
+ aws-sigv4 (~> 1.5)
31
+ aws-sigv4 (1.10.1)
32
+ aws-eventstream (~> 1, >= 1.0.2)
33
+ bigdecimal (3.1.8)
34
+ builder (3.3.0)
35
+ coderay (1.1.3)
36
+ concurrent-ruby (1.3.4)
37
+ crack (1.0.0)
38
+ bigdecimal
39
+ rexml
40
+ diff-lcs (1.5.1)
41
+ dotenv (2.8.1)
42
+ hashdiff (1.1.1)
43
+ jmespath (1.6.2)
44
+ json (2.8.1)
45
+ language_server-protocol (3.17.0.3)
46
+ lint_roller (1.1.0)
47
+ method_source (1.1.0)
48
+ nokogiri (1.16.7-x86_64-linux)
49
+ racc (~> 1.4)
50
+ parallel (1.26.3)
51
+ parser (3.3.6.0)
52
+ ast (~> 2.4.1)
53
+ racc
54
+ pry (0.14.2)
55
+ coderay (~> 1.1)
56
+ method_source (~> 1.0)
57
+ public_suffix (5.1.1)
58
+ racc (1.8.1)
59
+ rack (3.1.8)
60
+ rainbow (3.1.1)
61
+ regexp_parser (2.9.2)
62
+ rexml (3.3.9)
63
+ rspec (3.13.0)
64
+ rspec-core (~> 3.13.0)
65
+ rspec-expectations (~> 3.13.0)
66
+ rspec-mocks (~> 3.13.0)
67
+ rspec-core (3.13.2)
68
+ rspec-support (~> 3.13.0)
69
+ rspec-expectations (3.13.3)
70
+ diff-lcs (>= 1.2.0, < 2.0)
71
+ rspec-support (~> 3.13.0)
72
+ rspec-mocks (3.13.2)
73
+ diff-lcs (>= 1.2.0, < 2.0)
74
+ rspec-support (~> 3.13.0)
75
+ rspec-support (3.13.1)
76
+ rubocop (1.64.1)
77
+ json (~> 2.3)
78
+ language_server-protocol (>= 3.17.0)
79
+ parallel (~> 1.10)
80
+ parser (>= 3.3.0.2)
81
+ rainbow (>= 2.2.2, < 4.0)
82
+ regexp_parser (>= 1.8, < 3.0)
83
+ rexml (>= 3.2.5, < 4.0)
84
+ rubocop-ast (>= 1.31.1, < 2.0)
85
+ ruby-progressbar (~> 1.7)
86
+ unicode-display_width (>= 2.4.0, < 3.0)
87
+ rubocop-ast (1.34.1)
88
+ parser (>= 3.3.1.0)
89
+ rubocop-performance (1.21.1)
90
+ rubocop (>= 1.48.1, < 2.0)
91
+ rubocop-ast (>= 1.31.1, < 2.0)
92
+ rubocop-rspec (3.2.0)
93
+ rubocop (~> 1.61)
94
+ ruby-progressbar (1.13.0)
95
+ standard (1.37.0)
96
+ language_server-protocol (~> 3.17.0.2)
97
+ lint_roller (~> 1.0)
98
+ rubocop (~> 1.64.0)
99
+ standard-custom (~> 1.0.0)
100
+ standard-performance (~> 1.4)
101
+ standard-custom (1.0.2)
102
+ lint_roller (~> 1.0)
103
+ rubocop (~> 1.50)
104
+ standard-performance (1.4.0)
105
+ lint_roller (~> 1.1)
106
+ rubocop-performance (~> 1.21.0)
107
+ thor (1.3.2)
108
+ timecop (0.9.10)
109
+ unicode-display_width (2.6.0)
110
+ webmock (3.24.0)
111
+ addressable (>= 2.8.0)
112
+ crack (>= 0.3.2)
113
+ hashdiff (>= 0.4.0, < 2.0.0)
114
+ zeitwerk (2.6.18)
115
+
116
+ PLATFORMS
117
+ x86_64-linux
118
+
119
+ DEPENDENCIES
120
+ aws-sdk-s3
121
+ dotenv
122
+ nokogiri
123
+ pry
124
+ rspec
125
+ rubocop
126
+ rubocop-performance
127
+ rubocop-rspec
128
+ site_maps!
129
+ standard
130
+ timecop
131
+ webmock
132
+
133
+ BUNDLED WITH
134
+ 2.3.22
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Marcos G. Zimmermann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # SiteMaps
2
+
3
+ SiteMaps is a gem that helps you to generate sitemaps for your Rails application.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'site_maps'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ bundle install
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ gem install site_maps
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ Create a configuration file where you will define the sitemap logic. You can use the following DSL to define the sitemap generation. Below is the minimum configuration required to generate a sitemap:
28
+
29
+ ```ruby
30
+ # config/sitemap.rb
31
+ SiteMaps.use(:file_system) do
32
+ configure do |config|
33
+ config.url = "https://example.com/sitemaps/sitemap.xml.gz" # Location of main sitemap index file
34
+ config.directory = "/home/www/public"
35
+ end
36
+ process do |s|
37
+ s.add('/', priority: 1.0, changefreq: "daily")
38
+ s.add('/about', priority: 0.9, changefreq: "weekly")
39
+ end
40
+ end
41
+ ```
42
+
43
+ After creating the configuration file, you can run the following command to generate the sitemap:
44
+
45
+ ```bash
46
+ SiteMaps.generate(config_file: "config/sitemap.rb")
47
+ .enqueue_all
48
+ .run
49
+ ```
50
+
51
+ Sitemap links are defined in the `process` block because the gem is designed to generate sitemaps for large websites in parallel. The `process` block will be executed in a separate thread for each process, which will improve the performance of the sitemap generation. Each process can have a unique name and a unique sitemap file location. By omitting the name and the file location, the process will use the `:default` value.
52
+
53
+ Bellows is an example of a configuration file with multiple processes:
54
+
55
+ ```ruby
56
+ # config/sitemap.rb
57
+ SiteMaps.use(:file_system) do
58
+ configure do |config|
59
+ config.url = "https://example.com/sitemaps/sitemap.xml.gz" # Location of main sitemap index file
60
+ config.directory = "/home/www/public"
61
+ end
62
+ process do |s|
63
+ s.add('/', priority: 1.0, changefreq: "daily")
64
+ s.add('/about', priority: 0.9, changefreq: "weekly")
65
+ end
66
+ process :categories, "categories/sitemap.xml" do |s|
67
+ Category.find_each do |category|
68
+ s.add(category_path(category), priority: 0.7)
69
+ end
70
+ end
71
+ process :posts, "posts/%{year}-%{month}/sitemap.xml", year: Date.today.year, month: Date.today.month do |s, year, month|
72
+ Post.where(year: year, month: month).find_each do |post|
73
+ s.add(post_path(post), priority: 0.8)
74
+ end
75
+ end
76
+ end
77
+ ```
78
+
79
+ The `process` block can receive a name and a file location as arguments. The file location can contain placeholders that will be replaced by the values passed to the process block. The `process` block can receive a hash with the values that will be used to replace the placeholders in the file location. It will allow you to incrementally generate sitemaps by year and month, for example.
80
+
81
+ ```ruby
82
+ SiteMaps.generate(config_file: "config/sitemap.rb")
83
+ .enqueue(:posts, year: 2021, month: 1)
84
+ .enqueue(:posts, year: 2021, month: 2)
85
+ .enqueue_remaining # Enqueue all remaining processes (default and categories)
86
+ .run
87
+ ```
88
+
89
+ If you are using Rails, you may want to add routes to the sitemap builder. You can use the `include_module` adapter method.
90
+
91
+ ```ruby
92
+ # config/sitemap.rb
93
+ SiteMaps.use(:file_system) do
94
+ include_module Rails.application.routes.url_helpers # It's the same of `extend Rails.application.routes.url_helpers`
95
+
96
+ configure do |config|
97
+ config.url = "https://example.com/sitemaps/sitemap.xml.gz" # Location of main sitemap index file
98
+ config.directory = "/home/www/public"
99
+ end
100
+ process do |s|
101
+ s.add(root_path, priority: 1.0, changefreq: "daily")
102
+ s.add(about_path, priority: 0.9, changefreq: "weekly")
103
+ end
104
+ end
105
+ ```
106
+
107
+ ### AWS S3
108
+
109
+ You can use the AWS S3 adapter to store the sitemaps in an S3 bucket. The configuration is similar to the file system adapter, but you need to provide the AWS SDK options.
110
+
111
+ ```ruby
112
+ aws_sdk_options = {
113
+ bucket: "my-bucket",
114
+ region: "us-east-1",
115
+ aws_access_key: ENV["AWS_ACCESS_KEY_ID"],
116
+ aws_secret_key: ENV["AWS_SECRET_ACCESS_KEY"],
117
+ # Optional parameters (default values)
118
+ acl: "public-read",
119
+ cache_control: "private, max-age=0, no-cache",
120
+ }
121
+
122
+ SiteMaps.use(:aws_sdk, **aws_sdk_options) do
123
+ configure do |config|
124
+ config.url = "https://my-bucket.s3.amazonaws.com/sitemaps/sitemap.xml.gz"
125
+ end
126
+ process do |s|
127
+ s.add('/', priority: 1.0, changefreq: "daily")
128
+ s.add('/about', priority: 0.9, changefreq: "weekly")
129
+ end
130
+ end
131
+ ```
132
+
133
+ ## CLI
134
+
135
+ You can use the CLI to generate the sitemap. The CLI will load the configuration file and run the sitemap generation.
136
+
137
+ ```bash
138
+ bundle exec site_maps generate --config-file config/sitemap.rb
139
+ ```
140
+
141
+ To enqueue dynamic processes, you can pass the process name with the context values.
142
+
143
+ ```bash
144
+ bundle exec site_maps generate monthly_posts --config-file config/sitemap.rb --context=year:2021,month:1
145
+ ```
146
+
147
+ ## Notification
148
+
149
+ You can subscribe to the internal events to receive notifications about the sitemap generation. The following events are available:
150
+
151
+ * `sitemaps.runner.enqueue_process` - Triggered when a process is enqueued.
152
+ * `sitemaps.runner.before_process_execution` - Triggered before a process starts execution
153
+ * `sitemaps.runner.process_execution` - Triggered when a process finishes execution.
154
+ * `sitemaps.builder.finalize_urlset` - Triggered when the sitemap builder finishes the URL set.
155
+
156
+ You can subscribe to the events using the following code:
157
+
158
+ ```ruby
159
+ SiteMaps::Notification.subscribe("sitemaps.runner.enqueue_process") do |event|
160
+ puts "Enqueueing process #{event.payload[:name]}"
161
+ end
162
+ ```
163
+
164
+ We have the standard event handler `SiteMaps::Runner::EventListener` that will print the events to the standard output. You can use it to view the progress of the sitemap generation.
165
+
166
+ ```ruby
167
+ SiteMaps::Notification.subscribe(SiteMaps::Runner::EventListener)
168
+ SiteMaps.generate(config_file: "config/sitemap.rb")
169
+ .enqueue_all
170
+ .run
171
+ ```
172
+
173
+ ## Development
174
+
175
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
176
+
177
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
178
+
179
+ ## Contributing
180
+
181
+ Bug reports and pull requests are welcome on GitHub at https://github.com/marcosgz/site_maps.
182
+
183
+
184
+ ## License
185
+
186
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "dotenv/load"
6
+ require "pry"
7
+ require "site_maps"
8
+
9
+ SiteMaps.configure do |config|
10
+ config.url = "https://example.com/site_maps/sitemap.xml"
11
+ config.directory = "/tmp/site_maps"
12
+ end
13
+
14
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+ find gemfiles -type f \( -iname "*.gemfile" ! -iname "*.lock" \) -exec bundle install --gemfile {} \;
data/exec/site_maps ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
5
+
6
+ require "site_maps"
7
+ require "site_maps/cli"
8
+
9
+ SiteMaps::CLI.start
data/lib/site-maps.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "site_maps"
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SiteMaps::Adapters
4
+ class Adapter
5
+ extend Forwardable
6
+
7
+ class << self
8
+ def config_class
9
+ return SiteMaps::Configuration unless defined?(self::Config)
10
+
11
+ self::Config
12
+ end
13
+ end
14
+
15
+ def_delegators :config, :fetch_sitemap_index_links
16
+ attr_reader :sitemap_index, :processes
17
+
18
+ def initialize(**options, &block)
19
+ @config = SiteMaps.config.becomes(self.class.config_class, **options)
20
+ @processes = Concurrent::Hash.new
21
+ reset!
22
+ instance_exec(&block) if block
23
+ end
24
+
25
+ # @abstract
26
+ # @param [String] url The remote URL to write to
27
+ # @param [String] raw_data The raw data to write
28
+ # @return [void]
29
+ # @raise [SiteMaps::Error] if the write operation fails
30
+ def write(_url, _raw_data, **_kwargs)
31
+ raise NotImplementedError
32
+ end
33
+
34
+ # @abstract
35
+ # @param [String] url The remote URL to read from
36
+ # @return [Array<String, Hash>] The raw data and metadata
37
+ # @raise [SiteMaps::FileNotFoundError] if the file does not exist
38
+ def read(_url)
39
+ raise NotImplementedError
40
+ end
41
+
42
+ # @abstract
43
+ # @param [String] url The remote URL to delete
44
+ # @return [void]
45
+ # @raise [SiteMaps::FileNotFoundError] if the file does not exist
46
+ def delete(_url)
47
+ raise NotImplementedError
48
+ end
49
+
50
+ def config
51
+ yield(@config) if block_given?
52
+ @config
53
+ end
54
+ alias_method :configure, :config
55
+
56
+ def process(name = :default, location = nil, **kwargs, &block)
57
+ name = name.to_sym
58
+ raise ArgumentError, "Process #{name} already defined" if @processes.key?(name)
59
+
60
+ @processes[name] = SiteMaps::Process.new(name, location, kwargs, block)
61
+ end
62
+
63
+ def maybe_inline_urlset?
64
+ @processes.size == 1 && @processes.first.last.static?
65
+ end
66
+
67
+ def repo
68
+ @repo ||= SiteMaps::AtomicRepository.new(config.url)
69
+ end
70
+
71
+ def include_module(mod)
72
+ extend(mod)
73
+ end
74
+
75
+ def reset!
76
+ @sitemap_index = SiteMaps::Builder::SitemapIndex.new
77
+ @repo = nil
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SiteMaps::Adapters::AwsSdk::Config < SiteMaps::Configuration
4
+ attribute :access_key_id, default: -> { ENV["AWS_ACCESS_KEY_ID"] }
5
+ attribute :secret_access_key, default: -> { ENV["AWS_SECRET_ACCESS_KEY"] }
6
+ attribute :region, default: -> { ENV.fetch("AWS_REGION", "us-east-1") }
7
+ attribute :bucket, default: -> { ENV["AWS_BUCKET"] }
8
+ attribute :acl, default: "public-read"
9
+ attribute :cache_control, default: "private, max-age=0, no-cache"
10
+
11
+ attr_reader :aws_extra_options
12
+
13
+ def initialize(**options)
14
+ defined_attrs = options.slice(*self.class.attributes.keys)
15
+ super(**defined_attrs)
16
+
17
+ @aws_extra_options = options.reject { |k, v| defined_attrs.key?(k) }
18
+ end
19
+
20
+ def s3_bucket
21
+ s3_resource.bucket(bucket)
22
+ end
23
+
24
+ def s3_resource
25
+ @s3_resource ||= begin
26
+ require "aws-sdk-s3"
27
+
28
+ ::Aws::S3::Resource.new(s3_resource_options)
29
+ end
30
+ end
31
+
32
+ def inspect
33
+ "#<#{self.class}:#{object_id} access_key_id=#{access_key_id.inspect} region=#{region.inspect} bucket=#{bucket.inspect}>"
34
+ end
35
+ alias_method :to_s, :inspect
36
+
37
+ private
38
+
39
+ def s3_resource_options
40
+ options = aws_extra_options.dup
41
+ options[:region] = region if region?
42
+ if access_key_id? && secret_access_key?
43
+ options[:credentials] = ::Aws::Credentials.new(
44
+ access_key_id,
45
+ secret_access_key
46
+ )
47
+ end
48
+
49
+ options
50
+ end
51
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SiteMaps::Adapters::AwsSdk::Location < SiteMaps::Adapters::FileSystem::Location
4
+ ROOT_RE = %r{^/}
5
+
6
+ def remote_path
7
+ make_relative(uri.path)
8
+ end
9
+ end