nanoc-checking 1.0.4 → 1.0.6
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/NEWS.md +16 -0
- data/lib/nanoc/checking/check.rb +3 -3
- data/lib/nanoc/checking/checks/external_links.rb +15 -1
- data/lib/nanoc/checking/checks/internal_links.rb +2 -1
- data/lib/nanoc/checking/checks/mixed_content.rb +1 -1
- data/lib/nanoc/checking/checks/stale.rb +7 -5
- data/lib/nanoc/checking/checks/w3c_validator.rb +0 -1
- data/lib/nanoc/checking/command_runners/check.rb +1 -1
- data/lib/nanoc/checking/dsl.rb +3 -3
- data/lib/nanoc/checking/link_collector.rb +4 -2
- data/lib/nanoc/checking/loader.rb +1 -1
- data/lib/nanoc/checking/runner.rb +71 -15
- data/lib/nanoc/checking/version.rb +1 -1
- metadata +5 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ab6cbdc1bae780d9287e543d5462a6a6683141c0b0d79ec1d5f1f26e4ed228a
|
4
|
+
data.tar.gz: bb4437776e9720dc53935e96d920d2c74cd46b37c6aa020d10203fb64d59212f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3efba36b203db266dec8769472a02dd8c8a08922f003cc1a408ae7d9799f2bf61f2a64c5b278507b36cbe70b13018b5a221ac91f3d31ef9b06485bfca65befc7
|
7
|
+
data.tar.gz: 894aebf4ae02cfccff5a0b37795781f8ffb1c0a0e46d3f4fb3afc46632717279b8a22691da702040000bc4df6c91c3ce12d1a5660058abcfa9063fe04bcfe7af
|
data/NEWS.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# nanoc-checking news
|
2
2
|
|
3
|
+
## 1.0.6 (2025-04-20)
|
4
|
+
|
5
|
+
Enhancements:
|
6
|
+
|
7
|
+
- Made checks be run in parallel (#1735) [Jan M. Faber]
|
8
|
+
|
9
|
+
Fixes:
|
10
|
+
|
11
|
+
- Restored compatibility with Nanoc 4.13.4
|
12
|
+
|
13
|
+
## 1.0.5 (2024-04-21)
|
14
|
+
|
15
|
+
Fixes:
|
16
|
+
|
17
|
+
- Fixed support for paths with spaces in internal_links check (#1702)
|
18
|
+
|
3
19
|
## 1.0.4 (2024-04-19)
|
4
20
|
|
5
21
|
Enhancements:
|
data/lib/nanoc/checking/check.rb
CHANGED
@@ -39,21 +39,21 @@ module Nanoc
|
|
39
39
|
view_context =
|
40
40
|
Nanoc::Core::ViewContextForShell.new(
|
41
41
|
items: site.items,
|
42
|
-
reps
|
42
|
+
reps:,
|
43
43
|
)
|
44
44
|
|
45
45
|
context = {
|
46
46
|
items: Nanoc::Core::PostCompileItemCollectionView.new(site.items, view_context),
|
47
47
|
layouts: Nanoc::Core::LayoutCollectionView.new(site.layouts, view_context),
|
48
48
|
config: Nanoc::Core::ConfigView.new(site.config, view_context),
|
49
|
-
output_filenames
|
49
|
+
output_filenames:,
|
50
50
|
}
|
51
51
|
|
52
52
|
new(context)
|
53
53
|
end
|
54
54
|
|
55
55
|
def initialize(context)
|
56
|
-
super
|
56
|
+
super
|
57
57
|
|
58
58
|
@issues = Set.new
|
59
59
|
end
|
@@ -143,7 +143,7 @@ module Nanoc
|
|
143
143
|
|
144
144
|
def request_url_once(url)
|
145
145
|
req = Net::HTTP::Get.new(path_for_url(url))
|
146
|
-
req['User-Agent'] =
|
146
|
+
req['User-Agent'] = user_agent
|
147
147
|
http = Net::HTTP.new(url.host, url.port)
|
148
148
|
if url.instance_of? URI::HTTPS
|
149
149
|
http.use_ssl = true
|
@@ -161,6 +161,20 @@ module Nanoc
|
|
161
161
|
excludes = @config.fetch(:checks, {}).fetch(:external_links, {}).fetch(:exclude_files, [])
|
162
162
|
excludes.any? { |pattern| Regexp.new(pattern).match(file) }
|
163
163
|
end
|
164
|
+
|
165
|
+
def user_agent
|
166
|
+
@_user_agent ||= custom_user_agent || default_user_agent
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
def custom_user_agent
|
172
|
+
@config.dig(:checks, :external_links, :user_agent)
|
173
|
+
end
|
174
|
+
|
175
|
+
def default_user_agent
|
176
|
+
"Mozilla/5.0 Nanoc/#{Nanoc::VERSION} (link rot checker)"
|
177
|
+
end
|
164
178
|
end
|
165
179
|
end
|
166
180
|
end
|
@@ -43,7 +43,8 @@ module Nanoc
|
|
43
43
|
|
44
44
|
output_dir = @config.output_dir
|
45
45
|
output_dir += '/' unless output_dir.end_with?('/')
|
46
|
-
|
46
|
+
# FIXME: escape is hacky
|
47
|
+
base_uri = URI("file://#{output_dir.gsub(' ', '%20')}")
|
47
48
|
path = href.sub(/#{base_uri}/, '').sub(/file:\/{1,3}/, '')
|
48
49
|
|
49
50
|
path = "/#{path}" unless path.start_with?('/')
|
@@ -22,7 +22,7 @@ module Nanoc
|
|
22
22
|
protected
|
23
23
|
|
24
24
|
def item_rep_paths
|
25
|
-
@
|
25
|
+
@_item_rep_paths ||=
|
26
26
|
Set.new(
|
27
27
|
@items
|
28
28
|
.flat_map(&:reps)
|
@@ -34,10 +34,12 @@ module Nanoc
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def pruner
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
@_pruner ||= begin
|
38
|
+
exclude_config = @config.fetch(:prune, {}).fetch(:exclude, [])
|
39
|
+
# FIXME: specifying reps this way is icky
|
40
|
+
reps = Nanoc::Core::ItemRepRepo.new
|
41
|
+
Nanoc::Core::Pruner.new(@config._unwrap, reps, exclude: exclude_config)
|
42
|
+
end
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
data/lib/nanoc/checking/dsl.rb
CHANGED
@@ -5,7 +5,7 @@ module Nanoc
|
|
5
5
|
# @api private
|
6
6
|
class DSL
|
7
7
|
def self.from_file(filename, enabled_checks:)
|
8
|
-
dsl = new(enabled_checks:
|
8
|
+
dsl = new(enabled_checks:)
|
9
9
|
absolute_filename = File.expand_path(filename)
|
10
10
|
dsl.instance_eval(File.read(filename), absolute_filename)
|
11
11
|
dsl
|
@@ -15,9 +15,9 @@ module Nanoc
|
|
15
15
|
@enabled_checks = enabled_checks
|
16
16
|
end
|
17
17
|
|
18
|
-
def check(identifier, &
|
18
|
+
def check(identifier, &)
|
19
19
|
klass = Class.new(::Nanoc::Checking::Check)
|
20
|
-
klass.send(:define_method, :run, &
|
20
|
+
klass.send(:define_method, :run, &)
|
21
21
|
klass.send(:identifier, identifier)
|
22
22
|
end
|
23
23
|
|
@@ -83,7 +83,8 @@ module ::Nanoc
|
|
83
83
|
|
84
84
|
def uris_in_file(filename, tag_names)
|
85
85
|
uris = Set.new
|
86
|
-
|
86
|
+
# FIXME: escape is hacky
|
87
|
+
base_uri = URI("file://#{filename.gsub(' ', '%20')}")
|
87
88
|
doc = Nokogiri::HTML(::File.read(filename))
|
88
89
|
doc.traverse do |tag|
|
89
90
|
next unless tag_names.nil? || tag_names.include?(tag.name)
|
@@ -116,7 +117,8 @@ module ::Nanoc
|
|
116
117
|
uri
|
117
118
|
else
|
118
119
|
begin
|
119
|
-
|
120
|
+
# FIXME: escape is hacky
|
121
|
+
URI.join(base_uri, uri.gsub(' ', '%20')).to_s
|
120
122
|
rescue
|
121
123
|
uri
|
122
124
|
end
|
@@ -6,13 +6,18 @@ module Nanoc
|
|
6
6
|
#
|
7
7
|
# @api private
|
8
8
|
class Runner
|
9
|
+
# Number of threads to use for running checks.
|
10
|
+
NUM_THREADS = 5
|
11
|
+
|
9
12
|
# @param [Nanoc::Core::Site] site The Nanoc site this runner is for
|
10
13
|
def initialize(site)
|
11
14
|
@site = site
|
15
|
+
|
16
|
+
@log_mutex = Thread::Mutex.new
|
12
17
|
end
|
13
18
|
|
14
19
|
def any_enabled_checks?
|
15
|
-
enabled_checks.
|
20
|
+
!enabled_checks.empty?
|
16
21
|
end
|
17
22
|
|
18
23
|
# Lists all available checks on stdout.
|
@@ -56,7 +61,7 @@ module Nanoc
|
|
56
61
|
private
|
57
62
|
|
58
63
|
def loader
|
59
|
-
@
|
64
|
+
@_loader ||= Nanoc::Checking::Loader.new(config: @site.config)
|
60
65
|
end
|
61
66
|
|
62
67
|
def load_all
|
@@ -93,32 +98,83 @@ module Nanoc
|
|
93
98
|
# TODO: remove me
|
94
99
|
Nanoc::Core::Compiler.new_for(@site).run_until_reps_built
|
95
100
|
|
96
|
-
checks =
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
+
checks = classes.map { _1.create(@site) }
|
102
|
+
length = classes.map { _1.identifier.to_s.length }.max
|
103
|
+
|
104
|
+
puts 'Running checks…'
|
105
|
+
|
106
|
+
# Create space in terminal to print status of all checks
|
107
|
+
classes.count.times { puts }
|
108
|
+
cursor_up($stdout, classes.count)
|
109
|
+
|
110
|
+
# Print all checks (all “pending” for now)
|
111
|
+
checks.each_with_index do |check, index|
|
112
|
+
log_check(index:, topic: format(" %-#{length}s", check.class.identifier.to_s), state: 'pending')
|
113
|
+
end
|
114
|
+
|
115
|
+
# Run checks in parallel
|
116
|
+
Parallel.each_with_index(checks, in_threads: NUM_THREADS) do |check, index|
|
117
|
+
log_check(index:, topic: format(" %-#{length}s", check.class.identifier.to_s), state: colorizer.c('running', :blue))
|
101
118
|
|
102
|
-
check = klass.create(@site)
|
103
119
|
check.run
|
104
120
|
|
105
|
-
|
106
|
-
|
121
|
+
state = check.issues.empty? ? colorizer.c('ok', :green) : colorizer.c('error', :red)
|
122
|
+
log_check(index:, topic: format(" %-#{length}s", check.class.identifier.to_s), state:)
|
123
|
+
end
|
107
124
|
|
108
|
-
|
125
|
+
# Move cursor to below list
|
126
|
+
cursor_down($stdout, checks.count)
|
109
127
|
|
110
|
-
|
128
|
+
# Collect issues
|
129
|
+
issues = Set.new
|
130
|
+
checks.each do |check|
|
131
|
+
issues.merge(check.issues)
|
111
132
|
end
|
133
|
+
|
112
134
|
issues
|
113
135
|
end
|
114
136
|
|
137
|
+
def log_check(index:, topic:, state:)
|
138
|
+
@log_mutex.synchronize do
|
139
|
+
cursor_down($stdout, index)
|
140
|
+
|
141
|
+
$stdout << "#{topic} #{state}"
|
142
|
+
erase_rest_of_line($stdout)
|
143
|
+
|
144
|
+
cursor_up($stdout, index)
|
145
|
+
go_to_start_of_line($stdout)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def cursor_up(io, count)
|
150
|
+
return if count.zero?
|
151
|
+
|
152
|
+
io << "\e[#{count}A"
|
153
|
+
end
|
154
|
+
|
155
|
+
def cursor_down(io, count)
|
156
|
+
return if count.zero?
|
157
|
+
|
158
|
+
io << "\e[#{count}B"
|
159
|
+
end
|
160
|
+
|
161
|
+
def go_to_start_of_line(io)
|
162
|
+
io << "\r"
|
163
|
+
end
|
164
|
+
|
165
|
+
def erase_rest_of_line(io)
|
166
|
+
io << "\e[K"
|
167
|
+
end
|
168
|
+
|
115
169
|
def subject_to_s(str)
|
116
170
|
str || '(global)'
|
117
171
|
end
|
118
172
|
|
119
|
-
def
|
120
|
-
|
173
|
+
def colorizer
|
174
|
+
@_colorizer ||= Nanoc::CLI::ANSIStringColorizer.new($stdout)
|
175
|
+
end
|
121
176
|
|
177
|
+
def print_issues(issues)
|
122
178
|
return if issues.empty?
|
123
179
|
|
124
180
|
puts 'Issues found!'
|
@@ -129,7 +185,7 @@ module Nanoc
|
|
129
185
|
|
130
186
|
puts " #{subject_to_s(subject)}:"
|
131
187
|
issues.each do |i|
|
132
|
-
puts " [ #{'ERROR'
|
188
|
+
puts " [ #{colorizer.c('ERROR', :red)} ] #{i.check_class.identifier} - #{i.description}"
|
133
189
|
end
|
134
190
|
end
|
135
191
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nanoc-checking
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Defreyne
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: nanoc-cli
|
@@ -83,8 +82,7 @@ licenses:
|
|
83
82
|
- MIT
|
84
83
|
metadata:
|
85
84
|
rubygems_mfa_required: 'true'
|
86
|
-
source_code_uri: https://github.com/nanoc/nanoc/tree/nanoc-checking-v1.0.
|
87
|
-
post_install_message:
|
85
|
+
source_code_uri: https://github.com/nanoc/nanoc/tree/nanoc-checking-v1.0.6/nanoc-checking
|
88
86
|
rdoc_options: []
|
89
87
|
require_paths:
|
90
88
|
- lib
|
@@ -92,15 +90,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
90
|
requirements:
|
93
91
|
- - ">="
|
94
92
|
- !ruby/object:Gem::Version
|
95
|
-
version: '
|
93
|
+
version: '3.1'
|
96
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
95
|
requirements:
|
98
96
|
- - ">="
|
99
97
|
- !ruby/object:Gem::Version
|
100
98
|
version: '0'
|
101
99
|
requirements: []
|
102
|
-
rubygems_version: 3.
|
103
|
-
signing_key:
|
100
|
+
rubygems_version: 3.6.7
|
104
101
|
specification_version: 4
|
105
102
|
summary: Checking support for Nanoc
|
106
103
|
test_files: []
|