crawlscope 0.7.0 → 0.7.2
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 +18 -0
- data/README.md +30 -12
- data/lib/crawlscope/rake_tasks.rb +2 -2
- data/lib/crawlscope/version.rb +1 -1
- data/lib/crawlscope.rb +1 -0
- data/lib/generators/crawlscope/install_generator.rb +37 -0
- data/lib/generators/crawlscope/templates/initializer.rb.tt +27 -0
- data/test/crawlscope/install_generator_test.rb +58 -0
- data/test/crawlscope/rake_tasks_test.rb +34 -2
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 18717d5f025a5e0dc10b3f5a231b52d788a7ad09fe017b803815dc1cf22b7f11
|
|
4
|
+
data.tar.gz: 25f80cac563922d3c34d069c34b6c5521064fb4a74dd98cc54f6bb04e6de283a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 322dacf831bfa19dd16a6ebf3917e8d8bcaab462b440468945e4e9e07768a42955afe7f418b217594f9654c22490d32124f6fdb95004a20f23508f76bca6d7db
|
|
7
|
+
data.tar.gz: b301ad0f2c7c92dd3dc436f7019c62d7958bdd402eb8a887626d938a9bfd085d8d21bdab76a5243f3e2d9684d94ffce554e5108db26995d67b63140fcadbb9e2
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ 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.2] - 2026-07-23
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- preserve host configuration
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## [0.7.1] - 2026-07-21
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- add lazy install generator
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
8
26
|
## [0.7.0] - 2026-07-21
|
|
9
27
|
|
|
10
28
|
|
data/README.md
CHANGED
|
@@ -142,24 +142,23 @@ puts result.issues.to_a.map(&:message)
|
|
|
142
142
|
- `pages`: fetched page snapshots
|
|
143
143
|
- `issues`: structured issues with `code`, `severity`, `category`, `url`, and `message`
|
|
144
144
|
|
|
145
|
-
`result.ok?` returns `false`
|
|
145
|
+
`result.ok?` returns `false` when an error is present. Warnings and notices
|
|
146
|
+
remain available through `result.issues` without making the result fail.
|
|
146
147
|
|
|
147
148
|
## Rails Usage
|
|
148
149
|
|
|
149
|
-
|
|
150
|
-
only when a Crawlscope task is requested. In the application's `Rakefile`,
|
|
151
|
-
before `require_relative "config/application"`:
|
|
150
|
+
Run the install generator after adding the gem:
|
|
152
151
|
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
require "crawlscope/tasks" if list_tasks || ARGV.any? { |argument| argument.start_with?("crawlscope:") }
|
|
152
|
+
```bash
|
|
153
|
+
bin/rails generate crawlscope:install
|
|
156
154
|
```
|
|
157
155
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
156
|
+
The generator creates `config/initializers/crawlscope.rb` with an idempotent
|
|
157
|
+
`CrawlscopeConfiguration.apply` loader and adds conditional `crawlscope/tasks`
|
|
158
|
+
loading to the application's `Rakefile`. This preserves `bin/rails --tasks` and
|
|
159
|
+
the `crawlscope:*` tasks without loading Crawlscope during normal Rails boot.
|
|
161
160
|
|
|
162
|
-
|
|
161
|
+
Customize the `Crawlscope.configure` block inside the generated initializer:
|
|
163
162
|
|
|
164
163
|
```ruby
|
|
165
164
|
Crawlscope.configure do |config|
|
|
@@ -170,6 +169,20 @@ Crawlscope.configure do |config|
|
|
|
170
169
|
end
|
|
171
170
|
```
|
|
172
171
|
|
|
172
|
+
Runtime callers must apply the generated configuration before using
|
|
173
|
+
Crawlscope:
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
CrawlscopeConfiguration.apply
|
|
177
|
+
Crawlscope.configuration.audit
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Rake tasks apply it automatically because `crawlscope/tasks` loads the gem
|
|
181
|
+
before Rails evaluates the initializer. Each Rake entry point passes the shared
|
|
182
|
+
`Crawlscope.configuration` object to the CLI, so configured base URLs, sitemap
|
|
183
|
+
paths, registries, and runtime settings are preserved unless a task argument or
|
|
184
|
+
environment override replaces them.
|
|
185
|
+
|
|
173
186
|
Then run:
|
|
174
187
|
|
|
175
188
|
```bash
|
|
@@ -211,7 +224,12 @@ bundle exec rake crawlscope:validate:ldjson URL=https://example.com/article
|
|
|
211
224
|
bundle exec rake 'crawlscope:validate:ldjson[https://example.com/article]'
|
|
212
225
|
```
|
|
213
226
|
|
|
214
|
-
`crawlscope:validate` runs all default sitemap rules: indexability, metadata,
|
|
227
|
+
`crawlscope:validate` runs all default sitemap rules: indexability, metadata,
|
|
228
|
+
structured data, uniqueness, content quality, and links. `URL` is the site
|
|
229
|
+
base. Without `SITEMAP`, Crawlscope uses the configured sitemap path, then
|
|
230
|
+
falls back to `/sitemap.xml`. With `SITEMAP`, Crawlscope uses `URL` as the site
|
|
231
|
+
base and validates URLs from that sitemap. `SITEMAP` may be a full URL or a
|
|
232
|
+
local file path.
|
|
215
233
|
|
|
216
234
|
Plain `rake` does not pass `--url` style flags to tasks. Use `URL=...` or the
|
|
217
235
|
task-argument form above instead.
|
|
@@ -16,8 +16,8 @@ module Crawlscope
|
|
|
16
16
|
validate(url: url, sitemap_path: sitemap_path, rule_names: rule)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def run(command, argv: [])
|
|
20
|
-
status = Cli.start([command, *argv], out: $stdout, err: $stderr)
|
|
19
|
+
def run(command, argv: [], configuration: Crawlscope.configuration)
|
|
20
|
+
status = Cli.start([command, *argv], out: $stdout, err: $stderr, configuration: configuration)
|
|
21
21
|
exit(status) unless status.zero?
|
|
22
22
|
end
|
|
23
23
|
|
data/lib/crawlscope/version.rb
CHANGED
data/lib/crawlscope.rb
CHANGED
|
@@ -27,6 +27,7 @@ module Crawlscope
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
Crawlscope.instance_variable_set(:@loader, Zeitwerk::Loader.for_gem)
|
|
30
|
+
Crawlscope.loader.ignore("#{__dir__}/generators")
|
|
30
31
|
Crawlscope.loader.ignore("#{__dir__}/tasks")
|
|
31
32
|
Crawlscope.loader.ignore("#{__dir__}/crawlscope/railtie.rb")
|
|
32
33
|
Crawlscope.loader.ignore("#{__dir__}/crawlscope/tasks.rb")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module Crawlscope
|
|
6
|
+
module Generators
|
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
|
9
|
+
|
|
10
|
+
desc "Create a lazy-safe Crawlscope initializer and task loader"
|
|
11
|
+
|
|
12
|
+
def create_initializer
|
|
13
|
+
template "initializer.rb.tt", "config/initializers/crawlscope.rb"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def configure_rakefile
|
|
17
|
+
rakefile = File.join(destination_root, "Rakefile")
|
|
18
|
+
return unless File.exist?(rakefile)
|
|
19
|
+
return if File.read(rakefile).include?('require "crawlscope/tasks"')
|
|
20
|
+
|
|
21
|
+
inject_into_file "Rakefile", rakefile_setup, before: /^require_relative ["']config\/application["']/
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def rakefile_setup
|
|
27
|
+
<<~RUBY
|
|
28
|
+
crawlscope_tasks_requested = Rake.application.options.show_tasks ||
|
|
29
|
+
ARGV.any? { |argument| ["-T", "--tasks"].include?(argument) }
|
|
30
|
+
require "crawlscope/tasks" if crawlscope_tasks_requested ||
|
|
31
|
+
ARGV.any? { |argument| argument.start_with?("crawlscope:") }
|
|
32
|
+
|
|
33
|
+
RUBY
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CrawlscopeConfiguration
|
|
4
|
+
MUTEX = Mutex.new
|
|
5
|
+
|
|
6
|
+
def self.apply
|
|
7
|
+
return if @applied
|
|
8
|
+
|
|
9
|
+
MUTEX.synchronize do
|
|
10
|
+
return if @applied
|
|
11
|
+
|
|
12
|
+
require "crawlscope"
|
|
13
|
+
|
|
14
|
+
Crawlscope.configure do |config|
|
|
15
|
+
config.base_url = -> { ENV.fetch("CRAWLSCOPE_BASE_URL", "http://localhost:3000") }
|
|
16
|
+
config.sitemap_path = lambda {
|
|
17
|
+
ENV.fetch("SITEMAP", Rails.public_path.join("sitemap.xml").to_s)
|
|
18
|
+
}
|
|
19
|
+
config.site_name = ENV.fetch("CRAWLSCOPE_SITE_NAME", "Application")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
@applied = true
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
CrawlscopeConfiguration.apply if defined?(Crawlscope)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
require "generators/crawlscope/install_generator"
|
|
5
|
+
require "open3"
|
|
6
|
+
require "rbconfig"
|
|
7
|
+
|
|
8
|
+
class CrawlscopeInstallGeneratorTest < Minitest::Test
|
|
9
|
+
def test_generates_lazy_initializer_and_task_loader
|
|
10
|
+
Dir.mktmpdir do |destination|
|
|
11
|
+
File.write(File.join(destination, "Rakefile"), <<~RUBY)
|
|
12
|
+
require_relative "config/application"
|
|
13
|
+
Rails.application.load_tasks
|
|
14
|
+
RUBY
|
|
15
|
+
|
|
16
|
+
Crawlscope::Generators::InstallGenerator.start([], destination_root: destination)
|
|
17
|
+
|
|
18
|
+
initializer = File.join(destination, "config/initializers/crawlscope.rb")
|
|
19
|
+
rakefile = File.read(File.join(destination, "Rakefile"))
|
|
20
|
+
|
|
21
|
+
assert File.exist?(initializer)
|
|
22
|
+
assert_includes File.read(initializer), "module CrawlscopeConfiguration"
|
|
23
|
+
assert_includes File.read(initializer), "CrawlscopeConfiguration.apply if defined?(Crawlscope)"
|
|
24
|
+
assert_includes rakefile, 'require "crawlscope/tasks"'
|
|
25
|
+
assert_operator rakefile.index('require "crawlscope/tasks"'), :<, rakefile.index('require_relative "config/application"')
|
|
26
|
+
|
|
27
|
+
_stdout, stderr, status = Open3.capture3(RbConfig.ruby, initializer)
|
|
28
|
+
assert status.success?, stderr
|
|
29
|
+
|
|
30
|
+
script = <<~RUBY
|
|
31
|
+
require "pathname"
|
|
32
|
+
|
|
33
|
+
module Rails
|
|
34
|
+
def self.public_path
|
|
35
|
+
Pathname.new("public")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
require "crawlscope"
|
|
40
|
+
load ARGV.fetch(0)
|
|
41
|
+
|
|
42
|
+
configuration = Crawlscope.configuration
|
|
43
|
+
CrawlscopeConfiguration.apply
|
|
44
|
+
abort "configuration replaced" unless Crawlscope.configuration.equal?(configuration)
|
|
45
|
+
abort "base URL missing" unless configuration.base_url == "http://localhost:3000"
|
|
46
|
+
abort "sitemap missing" unless configuration.sitemap_path == "public/sitemap.xml"
|
|
47
|
+
RUBY
|
|
48
|
+
_stdout, stderr, status = Open3.capture3(
|
|
49
|
+
RbConfig.ruby,
|
|
50
|
+
"-I#{File.expand_path("../../lib", __dir__)}",
|
|
51
|
+
"-e",
|
|
52
|
+
script,
|
|
53
|
+
initializer
|
|
54
|
+
)
|
|
55
|
+
assert status.success?, stderr
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require "test_helper"
|
|
4
4
|
|
|
5
5
|
class CrawlscopeRakeTasksTest < Minitest::Test
|
|
6
|
+
Rule = Data.define(:code)
|
|
7
|
+
|
|
6
8
|
def setup
|
|
7
9
|
@original_start = Crawlscope::Cli.method(:start)
|
|
8
10
|
end
|
|
@@ -13,6 +15,7 @@ class CrawlscopeRakeTasksTest < Minitest::Test
|
|
|
13
15
|
singleton_class.define_method(:start) do |*args, **kwargs|
|
|
14
16
|
original_start.call(*args, **kwargs)
|
|
15
17
|
end
|
|
18
|
+
Crawlscope.reset!
|
|
16
19
|
end
|
|
17
20
|
|
|
18
21
|
def test_validate_passes_rake_arguments_to_cli
|
|
@@ -56,14 +59,43 @@ class CrawlscopeRakeTasksTest < Minitest::Test
|
|
|
56
59
|
)
|
|
57
60
|
end
|
|
58
61
|
|
|
62
|
+
def test_run_passes_the_shared_configuration_to_cli
|
|
63
|
+
calls = capture_cli_calls
|
|
64
|
+
configuration = Crawlscope.configuration
|
|
65
|
+
|
|
66
|
+
Crawlscope::RakeTasks.run("validate")
|
|
67
|
+
|
|
68
|
+
assert_same configuration, calls.fetch(0).fetch(:kwargs).fetch(:configuration)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_validate_passes_the_host_rule_registry_to_cli
|
|
72
|
+
registry = Crawlscope::RuleRegistry.new(rules: [Rule.new(:host)], default_codes: [:host])
|
|
73
|
+
Crawlscope.configure { |configuration| configuration.rule_registry = registry }
|
|
74
|
+
calls = capture_cli_calls
|
|
75
|
+
|
|
76
|
+
Crawlscope::RakeTasks.validate
|
|
77
|
+
|
|
78
|
+
call = calls.fetch(0)
|
|
79
|
+
assert_equal "validate", call.fetch(:argv).first
|
|
80
|
+
assert_same registry, call.fetch(:kwargs).fetch(:configuration).rule_registry
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_run_exits_with_a_nonzero_cli_status
|
|
84
|
+
capture_cli_calls(status: 2)
|
|
85
|
+
|
|
86
|
+
error = assert_raises(SystemExit) { Crawlscope::RakeTasks.run("validate") }
|
|
87
|
+
|
|
88
|
+
assert_equal 2, error.status
|
|
89
|
+
end
|
|
90
|
+
|
|
59
91
|
private
|
|
60
92
|
|
|
61
|
-
def capture_cli_calls
|
|
93
|
+
def capture_cli_calls(status: 0)
|
|
62
94
|
calls = []
|
|
63
95
|
singleton_class = class << Crawlscope::Cli; self; end
|
|
64
96
|
singleton_class.define_method(:start) do |argv, **kwargs|
|
|
65
97
|
calls << {argv: argv, kwargs: kwargs}
|
|
66
|
-
|
|
98
|
+
status
|
|
67
99
|
end
|
|
68
100
|
calls
|
|
69
101
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: crawlscope
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Paulo Fidalgo
|
|
@@ -259,6 +259,8 @@ files:
|
|
|
259
259
|
- lib/crawlscope/tasks.rb
|
|
260
260
|
- lib/crawlscope/url.rb
|
|
261
261
|
- lib/crawlscope/version.rb
|
|
262
|
+
- lib/generators/crawlscope/install_generator.rb
|
|
263
|
+
- lib/generators/crawlscope/templates/initializer.rb.tt
|
|
262
264
|
- lib/tasks/crawlscope_tasks.rake
|
|
263
265
|
- test/crawlscope/browser_test.rb
|
|
264
266
|
- test/crawlscope/cli_test.rb
|
|
@@ -269,6 +271,7 @@ files:
|
|
|
269
271
|
- test/crawlscope/fetch_executor_test.rb
|
|
270
272
|
- test/crawlscope/http_test.rb
|
|
271
273
|
- test/crawlscope/indexability_rule_test.rb
|
|
274
|
+
- test/crawlscope/install_generator_test.rb
|
|
272
275
|
- test/crawlscope/links_rule_test.rb
|
|
273
276
|
- test/crawlscope/loader_test.rb
|
|
274
277
|
- test/crawlscope/metadata_rule_test.rb
|