nanoc 4.11.14 → 4.11.15

Sign up to get free protection for your applications and to get access to all the features.
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