nanoc-checking 1.0.2 → 1.0.4
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 +12 -0
- data/README.md +2 -2
- data/lib/nanoc/checking/checks/external_links.rb +12 -4
- data/lib/nanoc/checking/checks/internal_links.rb +3 -3
- data/lib/nanoc/checking/checks/mixed_content.rb +1 -1
- data/lib/nanoc/checking/link_collector.rb +130 -0
- data/lib/nanoc/checking/version.rb +1 -1
- data/lib/nanoc/checking.rb +1 -0
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b380e10a13a38c13d712399af8308a0cb67b533094287649eb30283fceba9be3
|
4
|
+
data.tar.gz: bd6715348e5527f23bedf1812b56bc49d75e5827b5bb318a5165bf5cf689077f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61e31cc485a14e7a75199c65df33d172dd69caad7d00be40725ec55ca5203f052213846b974dd842be2a33d021d10be184a1266810f9fdcddf89db1a7def572d
|
7
|
+
data.tar.gz: 2472f804af1d3facea1b840d89280070042b27fc03d91475b91db5e41a6783261a84ac62f83d6ea25811112ee85ff045e5a9110bc8ca398f08b4650dcfbc65ae
|
data/NEWS.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# nanoc-checking news
|
2
2
|
|
3
|
+
## 1.0.4 (2024-04-19)
|
4
|
+
|
5
|
+
Enhancements:
|
6
|
+
|
7
|
+
- Added support for `javascript:` pseudo-URLs (#1698)
|
8
|
+
|
9
|
+
## 1.0.3 (2024-03-15)
|
10
|
+
|
11
|
+
Fixes:
|
12
|
+
|
13
|
+
- Restore compatibility with Nanoc 4.12.20
|
14
|
+
|
3
15
|
## 1.0.2 (2022-01-15)
|
4
16
|
|
5
17
|
Fixes:
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# nanoc-checking
|
2
2
|
|
3
|
-
This provides the `check` command and associated functionality for [Nanoc](https://nanoc.
|
3
|
+
This provides the `check` command and associated functionality for [Nanoc](https://nanoc.app).
|
4
4
|
|
5
|
-
For details, see the [Checking correctness of Nanoc sites](https://nanoc.
|
5
|
+
For details, see the [Checking correctness of Nanoc sites](https://nanoc.app/doc/testing/) chapter of the Nanoc documentation.
|
@@ -13,7 +13,7 @@ module Nanoc
|
|
13
13
|
# Find all broken external hrefs
|
14
14
|
# TODO: de-duplicate this (duplicated in internal links check)
|
15
15
|
filenames = output_html_filenames.reject { |f| excluded_file?(f) }
|
16
|
-
hrefs_with_filenames = ::Nanoc::
|
16
|
+
hrefs_with_filenames = ::Nanoc::Checking::LinkCollector.new(filenames, :external).filenames_per_href
|
17
17
|
results = select_invalid(hrefs_with_filenames.keys.shuffle)
|
18
18
|
|
19
19
|
# Report them
|
@@ -21,7 +21,7 @@ module Nanoc
|
|
21
21
|
filenames = hrefs_with_filenames[res.href]
|
22
22
|
filenames.each do |filename|
|
23
23
|
add_issue(
|
24
|
-
"broken reference to
|
24
|
+
"broken reference to <#{res.href}>: #{res.explanation}",
|
25
25
|
subject: filename,
|
26
26
|
)
|
27
27
|
end
|
@@ -43,6 +43,13 @@ module Nanoc
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def validate(href)
|
46
|
+
# Skip javascript: URLs
|
47
|
+
#
|
48
|
+
# This needs to be handled explicitly, because URI.parse does not
|
49
|
+
# like `javascript:` URLs -- presumably because those are not
|
50
|
+
# technically valid URLs.
|
51
|
+
return nil if href.start_with?('javascript:')
|
52
|
+
|
46
53
|
# Parse
|
47
54
|
url = nil
|
48
55
|
begin
|
@@ -71,7 +78,8 @@ module Nanoc
|
|
71
78
|
next
|
72
79
|
end
|
73
80
|
|
74
|
-
|
81
|
+
case res.code
|
82
|
+
when /^3..$/
|
75
83
|
if i == 4
|
76
84
|
return Result.new(href, 'too many redirects')
|
77
85
|
end
|
@@ -87,7 +95,7 @@ module Nanoc
|
|
87
95
|
end
|
88
96
|
|
89
97
|
url = URI.parse(location)
|
90
|
-
|
98
|
+
when '200'
|
91
99
|
return nil
|
92
100
|
else
|
93
101
|
return Result.new(href, res.code)
|
@@ -18,14 +18,14 @@ module Nanoc
|
|
18
18
|
def run
|
19
19
|
# TODO: de-duplicate this (duplicated in external links check)
|
20
20
|
filenames = output_html_filenames
|
21
|
-
uris = ::Nanoc::
|
21
|
+
uris = ::Nanoc::Checking::LinkCollector.new(filenames, :internal).filenames_per_href
|
22
22
|
|
23
23
|
uris.each_pair do |href, fns|
|
24
24
|
fns.each do |filename|
|
25
25
|
next if valid?(href, filename)
|
26
26
|
|
27
27
|
add_issue(
|
28
|
-
"broken reference to
|
28
|
+
"broken reference to <#{href}>",
|
29
29
|
subject: filename,
|
30
30
|
)
|
31
31
|
end
|
@@ -89,7 +89,7 @@ module Nanoc
|
|
89
89
|
# FIXME: do not depend on current working directory
|
90
90
|
origin = File.absolute_path(origin)
|
91
91
|
|
92
|
-
relative_origin = origin[@config.output_dir.size
|
92
|
+
relative_origin = origin[@config.output_dir.size..]
|
93
93
|
excludes = config.fetch(:exclude_origins, [])
|
94
94
|
excludes.any? { |pattern| Regexp.new(pattern).match(relative_origin) }
|
95
95
|
end
|
@@ -14,7 +14,7 @@ module Nanoc
|
|
14
14
|
|
15
15
|
def run
|
16
16
|
filenames = output_html_filenames
|
17
|
-
resource_uris_with_filenames = ::Nanoc::
|
17
|
+
resource_uris_with_filenames = ::Nanoc::Checking::LinkCollector.new(filenames).filenames_per_resource_uri
|
18
18
|
|
19
19
|
resource_uris_with_filenames.each_pair do |uri, fns|
|
20
20
|
next unless guaranteed_insecure?(uri)
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ::Nanoc
|
4
|
+
module Checking
|
5
|
+
class LinkCollector
|
6
|
+
# HTML5 element attributes
|
7
|
+
URI_ATTRS = {
|
8
|
+
'a' => %i[href ping],
|
9
|
+
'area' => %i[href ping],
|
10
|
+
'audio' => %i[src],
|
11
|
+
'base' => %i[href],
|
12
|
+
'blockquote' => %i[cite],
|
13
|
+
'form' => %i[action],
|
14
|
+
'iframe' => %i[src],
|
15
|
+
'img' => %i[src srcset],
|
16
|
+
'link' => %i[href],
|
17
|
+
'object' => %i[data],
|
18
|
+
'script' => %i[src],
|
19
|
+
'source' => %i[src srcset],
|
20
|
+
'video' => %i[poster src],
|
21
|
+
}.freeze
|
22
|
+
# HTML+RDFa global URI attributes
|
23
|
+
GLOBAL_ATTRS = %i[about resource].freeze
|
24
|
+
|
25
|
+
def initialize(filenames, mode = nil)
|
26
|
+
@filenames = filenames
|
27
|
+
@filter =
|
28
|
+
case mode
|
29
|
+
when nil
|
30
|
+
->(_h) { true }
|
31
|
+
when :external
|
32
|
+
->(h) { external_href?(h) }
|
33
|
+
when :internal
|
34
|
+
->(h) { internal_href?(h) }
|
35
|
+
else
|
36
|
+
raise ArgumentError, 'Expected mode argument to be :internal, :external or nil'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def filenames_per_href
|
41
|
+
grouped_filenames { |filename| hrefs_in_file(filename) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def filenames_per_resource_uri
|
45
|
+
grouped_filenames { |filename| resource_uris_in_file(filename) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def external_href?(href)
|
49
|
+
return false if internal_href?(href)
|
50
|
+
|
51
|
+
href =~ %r{^(//|[a-z-]+:)}
|
52
|
+
end
|
53
|
+
|
54
|
+
def internal_href?(href)
|
55
|
+
return false if href.nil?
|
56
|
+
|
57
|
+
href.start_with?('file:/')
|
58
|
+
end
|
59
|
+
|
60
|
+
# all links
|
61
|
+
def hrefs_in_file(filename)
|
62
|
+
uris_in_file filename, nil
|
63
|
+
end
|
64
|
+
|
65
|
+
# embedded resources, used by the mixed-content checker
|
66
|
+
def resource_uris_in_file(filename)
|
67
|
+
uris_in_file filename, %w[audio base form iframe img link object script source video]
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def grouped_filenames
|
73
|
+
require 'nokogiri'
|
74
|
+
grouped_filenames = {}
|
75
|
+
@filenames.each do |filename|
|
76
|
+
yield(filename).each do |resouce_uri|
|
77
|
+
grouped_filenames[resouce_uri] ||= Set.new
|
78
|
+
grouped_filenames[resouce_uri] << filename
|
79
|
+
end
|
80
|
+
end
|
81
|
+
grouped_filenames
|
82
|
+
end
|
83
|
+
|
84
|
+
def uris_in_file(filename, tag_names)
|
85
|
+
uris = Set.new
|
86
|
+
base_uri = URI("file://#{filename}")
|
87
|
+
doc = Nokogiri::HTML(::File.read(filename))
|
88
|
+
doc.traverse do |tag|
|
89
|
+
next unless tag_names.nil? || tag_names.include?(tag.name)
|
90
|
+
|
91
|
+
attrs = []
|
92
|
+
attrs += URI_ATTRS[tag.name] unless URI_ATTRS[tag.name].nil?
|
93
|
+
attrs += GLOBAL_ATTRS if tag_names.nil?
|
94
|
+
next if attrs.nil?
|
95
|
+
|
96
|
+
attrs.each do |attr_name|
|
97
|
+
next if tag[attr_name].nil?
|
98
|
+
|
99
|
+
if attr_name == :srcset
|
100
|
+
uris = uris.merge(tag[attr_name].split(',').map { |v| v.strip.split[0].strip }.compact)
|
101
|
+
elsif %i[about ping resource].include?(attr_name)
|
102
|
+
uris = uris.merge(tag[attr_name].split.map(&:strip).compact)
|
103
|
+
else
|
104
|
+
uris << tag[attr_name.to_s]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Strip fragment
|
110
|
+
uris.map! { |uri| uri.gsub(/#.*$/, '') }
|
111
|
+
|
112
|
+
# Resolve paths relative to the filename, return invalid URIs as-is
|
113
|
+
uris.map! do |uri|
|
114
|
+
if uri.start_with?('//')
|
115
|
+
# Don’t modify protocol-relative URLs. They’re absolute!
|
116
|
+
uri
|
117
|
+
else
|
118
|
+
begin
|
119
|
+
URI.join(base_uri, uri).to_s
|
120
|
+
rescue
|
121
|
+
uri
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
uris.select(&@filter)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/lib/nanoc/checking.rb
CHANGED
@@ -13,6 +13,7 @@ require_relative 'checking/check'
|
|
13
13
|
require_relative 'checking/checks'
|
14
14
|
require_relative 'checking/command_runners'
|
15
15
|
require_relative 'checking/dsl'
|
16
|
+
require_relative 'checking/link_collector'
|
16
17
|
require_relative 'checking/runner'
|
17
18
|
require_relative 'checking/loader'
|
18
19
|
require_relative 'checking/issue'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Defreyne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nanoc-cli
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '4.12'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 4.12.
|
22
|
+
version: 4.12.5
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '4.12'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 4.12.
|
32
|
+
version: 4.12.5
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: nanoc-core
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
version: '4.12'
|
40
40
|
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 4.12.
|
42
|
+
version: 4.12.5
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -49,7 +49,7 @@ dependencies:
|
|
49
49
|
version: '4.12'
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: 4.12.
|
52
|
+
version: 4.12.5
|
53
53
|
description: Provides checking functionality for Nanoc
|
54
54
|
email: denis+rubygems@denis.ws
|
55
55
|
executables: []
|
@@ -74,14 +74,16 @@ files:
|
|
74
74
|
- lib/nanoc/checking/commands/check.rb
|
75
75
|
- lib/nanoc/checking/dsl.rb
|
76
76
|
- lib/nanoc/checking/issue.rb
|
77
|
+
- lib/nanoc/checking/link_collector.rb
|
77
78
|
- lib/nanoc/checking/loader.rb
|
78
79
|
- lib/nanoc/checking/runner.rb
|
79
80
|
- lib/nanoc/checking/version.rb
|
80
|
-
homepage: https://nanoc.
|
81
|
+
homepage: https://nanoc.app/
|
81
82
|
licenses:
|
82
83
|
- MIT
|
83
84
|
metadata:
|
84
85
|
rubygems_mfa_required: 'true'
|
86
|
+
source_code_uri: https://github.com/nanoc/nanoc/tree/nanoc-checking-v1.0.4/nanoc-checking
|
85
87
|
post_install_message:
|
86
88
|
rdoc_options: []
|
87
89
|
require_paths:
|
@@ -90,14 +92,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
92
|
requirements:
|
91
93
|
- - ">="
|
92
94
|
- !ruby/object:Gem::Version
|
93
|
-
version: '2.
|
95
|
+
version: '2.7'
|
94
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
97
|
requirements:
|
96
98
|
- - ">="
|
97
99
|
- !ruby/object:Gem::Version
|
98
100
|
version: '0'
|
99
101
|
requirements: []
|
100
|
-
rubygems_version: 3.
|
102
|
+
rubygems_version: 3.5.9
|
101
103
|
signing_key:
|
102
104
|
specification_version: 4
|
103
105
|
summary: Checking support for Nanoc
|