crawlscope 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb1ed58c5dc558d7d7efcb357870fc4764a1d6d5caeb5ddc30e466334c986421
4
- data.tar.gz: 9e90845271e781a0586c30c5c3f2c770b4a0c837474d78e8a19afa89c5b2fb6d
3
+ metadata.gz: 34b82022958c0d4bbc782e95ee899e555932d764050bb20f940c6ffaeb754cc1
4
+ data.tar.gz: 2587fd40b220f51d9752196323953abd2af194c95e480e52aa432259ec9f263b
5
5
  SHA512:
6
- metadata.gz: cd645a628045089499e213491a08157e5268b2238007c86e20eeff996dcb0246037915dce0019554995ade10c57eae31ffc79d1b256a123160f728a7f6e74722
7
- data.tar.gz: d12723425911cc2c6184f6f2f31f8d0dbe6fde8bc021c3c45c0b5490e500906be6f49da74c3457e04778bb6ed0c50438489fd1875191090de702cf6d0ed494f0
6
+ metadata.gz: 589b924f5f5a627e988156a77ca280c7f8a8ae4a8602bb0ff9fb4d59b449b18c546eab14fbbeb22ad02aee1d2ccfb79a9e5e2e5af870d06c15e057a30c404187
7
+ data.tar.gz: 327e346ca6a0702ae37b37cdf413443b578042f06a43306b87d14d8fc0d165480c952da6ba36ef483d1cec76125bbc1226d6e8ae3acf3c836dc737e3970330e1
data/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ 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-07-21
9
+
10
+
11
+ ### Added
12
+
13
+ - add lazy install generator
14
+
15
+
16
+
17
+ ## [0.7.0] - 2026-07-21
18
+
19
+
20
+ ### Added
21
+
22
+ - add commitlint and lefthook
23
+
24
+ - add lazy Rails task entrypoint
25
+
26
+
27
+
8
28
  ## [0.6.0] - 2026-06-01
9
29
 
10
30
 
data/README.md CHANGED
@@ -37,9 +37,13 @@ Crawlscope requires Ruby 3.3 or newer.
37
37
  Add this line to your application's Gemfile:
38
38
 
39
39
  ```ruby
40
- gem "crawlscope"
40
+ gem "crawlscope", require: false
41
41
  ```
42
42
 
43
+ `require: false` keeps Crawlscope and its crawl stack out of normal Rails web
44
+ and job process boot. Require `crawlscope` at the application boundary that
45
+ runs an audit, or use the task setup below.
46
+
43
47
  And then execute:
44
48
 
45
49
  ```bash
@@ -142,7 +146,18 @@ puts result.issues.to_a.map(&:message)
142
146
 
143
147
  ## Rails Usage
144
148
 
145
- In an initializer:
149
+ Run the install generator after adding the gem:
150
+
151
+ ```bash
152
+ bin/rails generate crawlscope:install
153
+ ```
154
+
155
+ The generator creates `config/initializers/crawlscope.rb` with an idempotent
156
+ `CrawlscopeConfiguration.apply` loader and adds conditional `crawlscope/tasks`
157
+ loading to the application's `Rakefile`. This preserves `bin/rails --tasks` and
158
+ the `crawlscope:*` tasks without loading Crawlscope during normal Rails boot.
159
+
160
+ Customize the `Crawlscope.configure` block inside the generated initializer:
146
161
 
147
162
  ```ruby
148
163
  Crawlscope.configure do |config|
@@ -153,6 +168,17 @@ Crawlscope.configure do |config|
153
168
  end
154
169
  ```
155
170
 
171
+ Runtime callers must apply the generated configuration before using
172
+ Crawlscope:
173
+
174
+ ```ruby
175
+ CrawlscopeConfiguration.apply
176
+ Crawlscope.configuration.audit
177
+ ```
178
+
179
+ Rake tasks apply it automatically because `crawlscope/tasks` loads the gem
180
+ before Rails evaluates the initializer.
181
+
156
182
  Then run:
157
183
 
158
184
  ```bash
@@ -3,7 +3,7 @@
3
3
  module Crawlscope
4
4
  class Railtie < Rails::Railtie
5
5
  rake_tasks do
6
- load File.expand_path("../tasks/crawlscope_tasks.rake", __dir__)
6
+ require "crawlscope/tasks"
7
7
  end
8
8
  end
9
9
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "crawlscope"
4
+ require "rake"
5
+
6
+ unless Rake::Task.task_defined?("crawlscope:validate")
7
+ load File.expand_path("../tasks/crawlscope_tasks.rake", __dir__)
8
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Crawlscope
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.1"
5
5
  end
data/lib/crawlscope.rb CHANGED
@@ -27,8 +27,10 @@ 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")
33
+ Crawlscope.loader.ignore("#{__dir__}/crawlscope/tasks.rb")
32
34
  Crawlscope.loader.setup
33
35
 
34
36
  require "crawlscope/railtie" if defined?(Rails::Railtie)
@@ -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
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "test_helper"
4
+ require "open3"
5
+ require "rbconfig"
4
6
 
5
7
  class CrawlscopeLoaderTest < Minitest::Test
6
8
  def test_eager_loads_cleanly
@@ -8,4 +10,39 @@ class CrawlscopeLoaderTest < Minitest::Test
8
10
  Crawlscope.loader.eager_load
9
11
  end
10
12
  end
13
+
14
+ def test_entrypoint_does_not_load_crawl_dependencies
15
+ script = <<~RUBY
16
+ require "crawlscope"
17
+
18
+ loaded = $LOADED_FEATURES.grep(%r{/(?:async|faraday|json-schema|nokogiri)(?:/|\\.rb)})
19
+ abort loaded.join("\\n") unless loaded.empty?
20
+ RUBY
21
+
22
+ _stdout, stderr, status = Open3.capture3(
23
+ RbConfig.ruby,
24
+ "-I#{File.expand_path("../../lib", __dir__)}",
25
+ "-e",
26
+ script
27
+ )
28
+
29
+ assert status.success?, stderr
30
+ end
31
+
32
+ def test_task_entrypoint_registers_tasks
33
+ script = <<~RUBY
34
+ require "crawlscope/tasks"
35
+
36
+ abort "task missing" unless Rake::Task.task_defined?("crawlscope:validate")
37
+ RUBY
38
+
39
+ _stdout, stderr, status = Open3.capture3(
40
+ RbConfig.ruby,
41
+ "-I#{File.expand_path("../../lib", __dir__)}",
42
+ "-e",
43
+ script
44
+ )
45
+
46
+ assert status.success?, stderr
47
+ end
11
48
  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.6.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo Fidalgo
@@ -256,8 +256,11 @@ files:
256
256
  - lib/crawlscope/structured_data/report.rb
257
257
  - lib/crawlscope/structured_data/reporter.rb
258
258
  - lib/crawlscope/structured_data/writer.rb
259
+ - lib/crawlscope/tasks.rb
259
260
  - lib/crawlscope/url.rb
260
261
  - lib/crawlscope/version.rb
262
+ - lib/generators/crawlscope/install_generator.rb
263
+ - lib/generators/crawlscope/templates/initializer.rb.tt
261
264
  - lib/tasks/crawlscope_tasks.rake
262
265
  - test/crawlscope/browser_test.rb
263
266
  - test/crawlscope/cli_test.rb
@@ -268,6 +271,7 @@ files:
268
271
  - test/crawlscope/fetch_executor_test.rb
269
272
  - test/crawlscope/http_test.rb
270
273
  - test/crawlscope/indexability_rule_test.rb
274
+ - test/crawlscope/install_generator_test.rb
271
275
  - test/crawlscope/links_rule_test.rb
272
276
  - test/crawlscope/loader_test.rb
273
277
  - test/crawlscope/metadata_rule_test.rb
@@ -318,7 +322,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
318
322
  - !ruby/object:Gem::Version
319
323
  version: '0'
320
324
  requirements: []
321
- rubygems_version: 4.0.10
325
+ rubygems_version: 4.0.16
322
326
  specification_version: 4
323
327
  summary: Audit sitemap URLs for metadata, structured data, uniqueness, and links
324
328
  test_files: []