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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +16 -0
  3. data/lib/nanoc.rb +4 -2
  4. data/lib/nanoc/data_sources/filesystem.rb +9 -3
  5. data/lib/nanoc/extra.rb +1 -0
  6. data/lib/nanoc/extra/core_ext.rb +0 -1
  7. data/lib/nanoc/extra/srcset_parser.rb +79 -0
  8. data/lib/nanoc/filters/erb.rb +1 -5
  9. data/lib/nanoc/filters/relativize_paths.rb +62 -10
  10. data/lib/nanoc/helpers/rendering.rb +5 -4
  11. data/lib/nanoc/orig_cli.rb +0 -5
  12. data/lib/nanoc/rule_dsl.rb +1 -0
  13. data/lib/nanoc/rule_dsl/action_provider.rb +1 -1
  14. data/lib/nanoc/rule_dsl/compiler_dsl.rb +1 -1
  15. data/lib/nanoc/rule_dsl/errors.rb +25 -0
  16. data/lib/nanoc/rule_dsl/rules_loader.rb +1 -1
  17. data/lib/nanoc/version.rb +1 -1
  18. metadata +37 -33
  19. data/lib/nanoc/base.rb +0 -13
  20. data/lib/nanoc/base/changes_stream.rb +0 -53
  21. data/lib/nanoc/base/errors.rb +0 -65
  22. data/lib/nanoc/checking.rb +0 -14
  23. data/lib/nanoc/checking/check.rb +0 -93
  24. data/lib/nanoc/checking/checks.rb +0 -14
  25. data/lib/nanoc/checking/checks/css.rb +0 -16
  26. data/lib/nanoc/checking/checks/external_links.rb +0 -151
  27. data/lib/nanoc/checking/checks/html.rb +0 -16
  28. data/lib/nanoc/checking/checks/internal_links.rb +0 -95
  29. data/lib/nanoc/checking/checks/mixed_content.rb +0 -37
  30. data/lib/nanoc/checking/checks/stale.rb +0 -41
  31. data/lib/nanoc/checking/checks/w3c_validator.rb +0 -31
  32. data/lib/nanoc/checking/dsl.rb +0 -27
  33. data/lib/nanoc/checking/issue.rb +0 -16
  34. data/lib/nanoc/checking/loader.rb +0 -50
  35. data/lib/nanoc/checking/runner.rb +0 -136
  36. data/lib/nanoc/deploying.rb +0 -10
  37. data/lib/nanoc/deploying/deployer.rb +0 -45
  38. data/lib/nanoc/deploying/deployers.rb +0 -11
  39. data/lib/nanoc/deploying/deployers/fog.rb +0 -220
  40. data/lib/nanoc/deploying/deployers/git.rb +0 -112
  41. data/lib/nanoc/deploying/deployers/rsync.rb +0 -68
  42. data/lib/nanoc/extra/core_ext/pathname.rb +0 -27
  43. data/lib/nanoc/orig_cli/commands/check.rb +0 -43
  44. data/lib/nanoc/orig_cli/commands/deploy.rb +0 -126
data/lib/nanoc/base.rb DELETED
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # @api private
4
- module Nanoc
5
- module Int
6
- end
7
-
8
- module Base
9
- end
10
- end
11
-
12
- require_relative 'base/errors'
13
- require_relative 'base/changes_stream'
@@ -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
@@ -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
@@ -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
@@ -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