nanoc 4.11.14 → 4.11.15
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.rb +4 -2
- data/lib/nanoc/data_sources/filesystem.rb +9 -3
- data/lib/nanoc/extra.rb +1 -0
- data/lib/nanoc/extra/core_ext.rb +0 -1
- data/lib/nanoc/extra/srcset_parser.rb +79 -0
- data/lib/nanoc/filters/erb.rb +1 -5
- data/lib/nanoc/filters/relativize_paths.rb +62 -10
- data/lib/nanoc/helpers/rendering.rb +5 -4
- data/lib/nanoc/orig_cli.rb +0 -5
- data/lib/nanoc/rule_dsl.rb +1 -0
- data/lib/nanoc/rule_dsl/action_provider.rb +1 -1
- data/lib/nanoc/rule_dsl/compiler_dsl.rb +1 -1
- data/lib/nanoc/rule_dsl/errors.rb +25 -0
- data/lib/nanoc/rule_dsl/rules_loader.rb +1 -1
- data/lib/nanoc/version.rb +1 -1
- metadata +37 -33
- data/lib/nanoc/base.rb +0 -13
- data/lib/nanoc/base/changes_stream.rb +0 -53
- data/lib/nanoc/base/errors.rb +0 -65
- data/lib/nanoc/checking.rb +0 -14
- data/lib/nanoc/checking/check.rb +0 -93
- data/lib/nanoc/checking/checks.rb +0 -14
- data/lib/nanoc/checking/checks/css.rb +0 -16
- data/lib/nanoc/checking/checks/external_links.rb +0 -151
- data/lib/nanoc/checking/checks/html.rb +0 -16
- data/lib/nanoc/checking/checks/internal_links.rb +0 -95
- data/lib/nanoc/checking/checks/mixed_content.rb +0 -37
- data/lib/nanoc/checking/checks/stale.rb +0 -41
- data/lib/nanoc/checking/checks/w3c_validator.rb +0 -31
- data/lib/nanoc/checking/dsl.rb +0 -27
- data/lib/nanoc/checking/issue.rb +0 -16
- data/lib/nanoc/checking/loader.rb +0 -50
- data/lib/nanoc/checking/runner.rb +0 -136
- data/lib/nanoc/deploying.rb +0 -10
- data/lib/nanoc/deploying/deployer.rb +0 -45
- data/lib/nanoc/deploying/deployers.rb +0 -11
- data/lib/nanoc/deploying/deployers/fog.rb +0 -220
- data/lib/nanoc/deploying/deployers/git.rb +0 -112
- data/lib/nanoc/deploying/deployers/rsync.rb +0 -68
- data/lib/nanoc/extra/core_ext/pathname.rb +0 -27
- data/lib/nanoc/orig_cli/commands/check.rb +0 -43
- data/lib/nanoc/orig_cli/commands/deploy.rb +0 -126
data/lib/nanoc/base.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
class ChangesStream
|
5
|
-
class ChangesListener
|
6
|
-
def initialize(y)
|
7
|
-
@y = y
|
8
|
-
end
|
9
|
-
|
10
|
-
def unknown
|
11
|
-
@y << :unknown
|
12
|
-
end
|
13
|
-
|
14
|
-
def lib
|
15
|
-
@y << :lib
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_stop(&block)
|
19
|
-
if block_given?
|
20
|
-
@to_stop = block
|
21
|
-
else
|
22
|
-
@to_stop
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def initialize(enum: nil)
|
28
|
-
@enum = enum
|
29
|
-
@enum ||=
|
30
|
-
Enumerator.new do |y|
|
31
|
-
@listener = ChangesListener.new(y)
|
32
|
-
yield(@listener)
|
33
|
-
end.lazy
|
34
|
-
end
|
35
|
-
|
36
|
-
def stop
|
37
|
-
@listener&.to_stop&.call
|
38
|
-
end
|
39
|
-
|
40
|
-
def map
|
41
|
-
self.class.new(enum: @enum.map { |e| yield(e) })
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_enum
|
45
|
-
@enum
|
46
|
-
end
|
47
|
-
|
48
|
-
def each
|
49
|
-
@enum.each { |e| yield(e) }
|
50
|
-
nil
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
data/lib/nanoc/base/errors.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc
|
4
|
-
module Int
|
5
|
-
# Module that contains all Nanoc-specific errors.
|
6
|
-
#
|
7
|
-
# @api private
|
8
|
-
module Errors
|
9
|
-
Generic = ::Nanoc::Core::Error
|
10
|
-
|
11
|
-
NoSuchSnapshot = ::Nanoc::Core::Errors::NoSuchSnapshot
|
12
|
-
CannotGetCompiledContentOfBinaryItem = ::Nanoc::Core::Errors::CannotGetCompiledContentOfBinaryItem
|
13
|
-
CannotGetParentOrChildrenOfNonLegacyItem = ::Nanoc::Core::Errors::CannotGetParentOrChildrenOfNonLegacyItem
|
14
|
-
CannotLayoutBinaryItem = ::Nanoc::Core::Errors::CannotLayoutBinaryItem
|
15
|
-
UnknownLayout = ::Nanoc::Core::Errors::UnknownLayout
|
16
|
-
CannotUseBinaryFilter = ::Nanoc::Core::Errors::CannotUseBinaryFilter
|
17
|
-
CannotUseTextualFilter = ::Nanoc::Core::Errors::CannotUseTextualFilter
|
18
|
-
|
19
|
-
# Error that is raised during site compilation when a layout is compiled
|
20
|
-
# for which the filter cannot be determined. This is similar to the
|
21
|
-
# {UnknownFilter} error, but specific for filters for layouts.
|
22
|
-
class CannotDetermineFilter < Generic
|
23
|
-
# @param [String] layout_identifier The identifier of the layout for
|
24
|
-
# which the filter could not be determined
|
25
|
-
def initialize(layout_identifier)
|
26
|
-
super("The filter to be used for the “#{layout_identifier}” layout could not be determined. Make sure the layout does have a filter.")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Error that is raised when no rules file can be found in the current
|
31
|
-
# working directory.
|
32
|
-
class NoRulesFileFound < Generic
|
33
|
-
def initialize
|
34
|
-
super('This site does not have a rules file, which is required for Nanoc sites.')
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Error that is raised when no compilation rule that can be applied to the
|
39
|
-
# current item can be found.
|
40
|
-
class NoMatchingCompilationRuleFound < Generic
|
41
|
-
# @param [Nanoc::Core::Item] item The item for which no compilation rule
|
42
|
-
# could be found
|
43
|
-
def initialize(item)
|
44
|
-
super("No compilation rules were found for the “#{item.identifier}” item.")
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Error that is raised when no routing rule that can be applied to the
|
49
|
-
# current item can be found.
|
50
|
-
class NoMatchingRoutingRuleFound < Generic
|
51
|
-
# @param [Nanoc::Core::ItemRep] rep The item repiresentation for which no
|
52
|
-
# routing rule could be found
|
53
|
-
def initialize(rep)
|
54
|
-
super("No routing rules were found for the “#{rep.item.identifier}” item (rep “#{rep.name}”).")
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
class AmbiguousMetadataAssociation < Generic
|
59
|
-
def initialize(content_filenames, meta_filename)
|
60
|
-
super("There are multiple content files (#{content_filenames.sort.join(', ')}) that could match the file containing metadata (#{meta_filename}).")
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
data/lib/nanoc/checking.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# @api private
|
4
|
-
module Nanoc::Checking
|
5
|
-
end
|
6
|
-
|
7
|
-
require_relative 'checking/check'
|
8
|
-
require_relative 'checking/checks'
|
9
|
-
require_relative 'checking/dsl'
|
10
|
-
require_relative 'checking/runner'
|
11
|
-
require_relative 'checking/loader'
|
12
|
-
require_relative 'checking/issue'
|
13
|
-
|
14
|
-
Nanoc::Check = Nanoc::Checking::Check
|
data/lib/nanoc/checking/check.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nanoc::Checking
|
4
|
-
# @api private
|
5
|
-
class OutputDirNotFoundError < ::Nanoc::Core::Error
|
6
|
-
def initialize(directory_path)
|
7
|
-
super("Unable to run check against output directory at “#{directory_path}”: directory does not exist.")
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
# @api private
|
12
|
-
class Check < Nanoc::Core::Context
|
13
|
-
extend DDPlugin::Plugin
|
14
|
-
|
15
|
-
DDMemoize.activate(self)
|
16
|
-
|
17
|
-
attr_reader :issues
|
18
|
-
|
19
|
-
def self.define(ident, &block)
|
20
|
-
klass = Class.new(::Nanoc::Checking::Check) { identifier(ident) }
|
21
|
-
klass.send(:define_method, :run) do
|
22
|
-
instance_exec(&block)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.create(site)
|
27
|
-
output_dir = site.config.output_dir
|
28
|
-
unless File.exist?(output_dir)
|
29
|
-
raise Nanoc::Checking::OutputDirNotFoundError.new(output_dir)
|
30
|
-
end
|
31
|
-
|
32
|
-
output_filenames = Dir[output_dir + '/**/*'].select { |f| File.file?(f) }
|
33
|
-
|
34
|
-
# FIXME: ugly
|
35
|
-
compiler = Nanoc::Core::Compiler.new_for(site)
|
36
|
-
res = compiler.run_until_reps_built
|
37
|
-
reps = res.fetch(:reps)
|
38
|
-
view_context =
|
39
|
-
Nanoc::Core::ViewContextForShell.new(
|
40
|
-
items: site.items,
|
41
|
-
reps: reps,
|
42
|
-
)
|
43
|
-
|
44
|
-
context = {
|
45
|
-
items: Nanoc::Core::PostCompileItemCollectionView.new(site.items, view_context),
|
46
|
-
layouts: Nanoc::Core::LayoutCollectionView.new(site.layouts, view_context),
|
47
|
-
config: Nanoc::Core::ConfigView.new(site.config, view_context),
|
48
|
-
output_filenames: output_filenames,
|
49
|
-
}
|
50
|
-
|
51
|
-
new(context)
|
52
|
-
end
|
53
|
-
|
54
|
-
def initialize(context)
|
55
|
-
super(context)
|
56
|
-
|
57
|
-
@issues = Set.new
|
58
|
-
end
|
59
|
-
|
60
|
-
def run
|
61
|
-
raise NotImplementedError.new('Nanoc::Checking::Check subclasses must implement #run')
|
62
|
-
end
|
63
|
-
|
64
|
-
def add_issue(desc, subject: nil)
|
65
|
-
# Simplify subject
|
66
|
-
# FIXME: do not depend on working directory
|
67
|
-
if subject&.start_with?(Dir.getwd)
|
68
|
-
subject = subject[(Dir.getwd.size + 1)..subject.size]
|
69
|
-
end
|
70
|
-
|
71
|
-
@issues << Issue.new(desc, subject, self.class)
|
72
|
-
end
|
73
|
-
|
74
|
-
# @private
|
75
|
-
def output_filenames
|
76
|
-
super.reject { |f| excluded_patterns.any? { |pat| pat.match?(f) } }
|
77
|
-
end
|
78
|
-
|
79
|
-
# @private
|
80
|
-
memoized def excluded_patterns
|
81
|
-
@config
|
82
|
-
.fetch(:checks, {})
|
83
|
-
.fetch(:all, {})
|
84
|
-
.fetch(:exclude_files, [])
|
85
|
-
.map { |pattern| Regexp.new(pattern) }
|
86
|
-
end
|
87
|
-
|
88
|
-
# @private
|
89
|
-
def output_html_filenames
|
90
|
-
output_filenames.select { |f| File.extname(f) =~ /\A\.x?html?\z/ }
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# @api private
|
4
|
-
module Nanoc::Checking::Checks
|
5
|
-
end
|
6
|
-
|
7
|
-
require_relative 'checks/w3c_validator'
|
8
|
-
|
9
|
-
require_relative 'checks/css'
|
10
|
-
require_relative 'checks/external_links'
|
11
|
-
require_relative 'checks/html'
|
12
|
-
require_relative 'checks/internal_links'
|
13
|
-
require_relative 'checks/mixed_content'
|
14
|
-
require_relative 'checks/stale'
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ::Nanoc::Checking::Checks
|
4
|
-
# @api private
|
5
|
-
class CSS < ::Nanoc::Checking::Checks::W3CValidator
|
6
|
-
identifier :css
|
7
|
-
|
8
|
-
def extension
|
9
|
-
'css'
|
10
|
-
end
|
11
|
-
|
12
|
-
def validator_class
|
13
|
-
::W3CValidators::CSSValidator
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,151 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ::Nanoc::Checking::Checks
|
4
|
-
# A validator that verifies that all external links point to a location that exists.
|
5
|
-
#
|
6
|
-
# @api private
|
7
|
-
class ExternalLinks < ::Nanoc::Checking::Check
|
8
|
-
identifiers :external_links, :elinks
|
9
|
-
|
10
|
-
def run
|
11
|
-
# Find all broken external hrefs
|
12
|
-
# TODO: de-duplicate this (duplicated in internal links check)
|
13
|
-
filenames = output_html_filenames.reject { |f| excluded_file?(f) }
|
14
|
-
hrefs_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames, :external).filenames_per_href
|
15
|
-
results = select_invalid(hrefs_with_filenames.keys.shuffle)
|
16
|
-
|
17
|
-
# Report them
|
18
|
-
results.each do |res|
|
19
|
-
filenames = hrefs_with_filenames[res.href]
|
20
|
-
filenames.each do |filename|
|
21
|
-
add_issue(
|
22
|
-
"broken reference to #{res.href}: #{res.explanation}",
|
23
|
-
subject: filename,
|
24
|
-
)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class Result
|
30
|
-
attr_reader :href
|
31
|
-
attr_reader :explanation
|
32
|
-
|
33
|
-
def initialize(href, explanation)
|
34
|
-
@href = href
|
35
|
-
@explanation = explanation
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def select_invalid(hrefs)
|
40
|
-
::Parallel.map(hrefs, in_threads: 10) { |href| validate(href) }.compact
|
41
|
-
end
|
42
|
-
|
43
|
-
def validate(href)
|
44
|
-
# Parse
|
45
|
-
url = nil
|
46
|
-
begin
|
47
|
-
url = URI.parse(href)
|
48
|
-
rescue URI::Error
|
49
|
-
return Result.new(href, 'invalid URI')
|
50
|
-
end
|
51
|
-
|
52
|
-
# Skip excluded URLs
|
53
|
-
return nil if excluded?(href)
|
54
|
-
|
55
|
-
# Skip non-HTTP URLs
|
56
|
-
return nil if url.scheme !~ /^https?$/
|
57
|
-
|
58
|
-
# Get status
|
59
|
-
res = nil
|
60
|
-
last_err = nil
|
61
|
-
timeouts = [3, 5, 10, 30, 60]
|
62
|
-
5.times do |i|
|
63
|
-
begin
|
64
|
-
Timeout.timeout(timeouts[i]) do
|
65
|
-
res = request_url_once(url)
|
66
|
-
end
|
67
|
-
rescue => e
|
68
|
-
last_err = e
|
69
|
-
next
|
70
|
-
end
|
71
|
-
|
72
|
-
if /^3..$/.match?(res.code)
|
73
|
-
if i == 4
|
74
|
-
return Result.new(href, 'too many redirects')
|
75
|
-
end
|
76
|
-
|
77
|
-
location = extract_location(res, url)
|
78
|
-
return Result.new(href, 'redirection without a target location') if location.nil?
|
79
|
-
|
80
|
-
if /^30[18]$/.match?(res.code)
|
81
|
-
return Result.new(href, "link has moved permanently to '#{location}'")
|
82
|
-
end
|
83
|
-
|
84
|
-
url = URI.parse(location)
|
85
|
-
elsif res.code == '200'
|
86
|
-
return nil
|
87
|
-
else
|
88
|
-
return Result.new(href, res.code)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
if last_err
|
92
|
-
return Result.new(href, last_err.message)
|
93
|
-
else
|
94
|
-
raise Nanoc::Core::Errors::InternalInconsistency, 'last_err cannot be nil'
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def extract_location(res, url)
|
99
|
-
location = res['Location']
|
100
|
-
|
101
|
-
case location
|
102
|
-
when nil
|
103
|
-
nil
|
104
|
-
when /^https?:\/\//
|
105
|
-
location
|
106
|
-
else
|
107
|
-
base_url = url.dup
|
108
|
-
base_url.path = (/^\//.match?(location) ? '' : '/')
|
109
|
-
base_url.query = nil
|
110
|
-
base_url.fragment = nil
|
111
|
-
base_url.to_s + location
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def path_for_url(url)
|
116
|
-
path =
|
117
|
-
if url.path.nil? || url.path.empty?
|
118
|
-
'/'
|
119
|
-
else
|
120
|
-
url.path
|
121
|
-
end
|
122
|
-
|
123
|
-
if url.query
|
124
|
-
path = path + '?' + url.query
|
125
|
-
end
|
126
|
-
|
127
|
-
path
|
128
|
-
end
|
129
|
-
|
130
|
-
def request_url_once(url)
|
131
|
-
req = Net::HTTP::Get.new(path_for_url(url))
|
132
|
-
req['User-Agent'] = "Mozilla/5.0 Nanoc/#{Nanoc::VERSION} (link rot checker)"
|
133
|
-
http = Net::HTTP.new(url.host, url.port)
|
134
|
-
if url.instance_of? URI::HTTPS
|
135
|
-
http.use_ssl = true
|
136
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
137
|
-
end
|
138
|
-
http.request(req)
|
139
|
-
end
|
140
|
-
|
141
|
-
def excluded?(href)
|
142
|
-
excludes = @config.fetch(:checks, {}).fetch(:external_links, {}).fetch(:exclude, [])
|
143
|
-
excludes.any? { |pattern| Regexp.new(pattern).match(href) }
|
144
|
-
end
|
145
|
-
|
146
|
-
def excluded_file?(file)
|
147
|
-
excludes = @config.fetch(:checks, {}).fetch(:external_links, {}).fetch(:exclude_files, [])
|
148
|
-
excludes.any? { |pattern| Regexp.new(pattern).match(file) }
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ::Nanoc::Checking::Checks
|
4
|
-
# @api private
|
5
|
-
class HTML < ::Nanoc::Checking::Checks::W3CValidator
|
6
|
-
identifier :html
|
7
|
-
|
8
|
-
def extension
|
9
|
-
'{htm,html}'
|
10
|
-
end
|
11
|
-
|
12
|
-
def validator_class
|
13
|
-
::W3CValidators::NuValidator
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|