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
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Checking::Checks
4
- # A check that verifies that all internal links point to a location that exists.
5
- #
6
- # @api private
7
- class InternalLinks < ::Nanoc::Checking::Check
8
- identifiers :internal_links, :ilinks
9
-
10
- # Starts the validator. The results will be printed to stdout.
11
- #
12
- # Internal links that match a regexp pattern in `@config[:checks][:internal_links][:exclude]` will
13
- # be skipped.
14
- #
15
- # @return [void]
16
- def run
17
- # TODO: de-duplicate this (duplicated in external links check)
18
- filenames = output_html_filenames
19
- uris = ::Nanoc::Extra::LinkCollector.new(filenames, :internal).filenames_per_href
20
-
21
- uris.each_pair do |href, fns|
22
- fns.each do |filename|
23
- next if valid?(href, filename)
24
-
25
- add_issue(
26
- "broken reference to #{href}",
27
- subject: filename,
28
- )
29
- end
30
- end
31
- end
32
-
33
- protected
34
-
35
- def valid?(href, origin)
36
- # Skip hrefs that point to self
37
- # FIXME: this is ugly and won’t always be correct
38
- return true if href == '.'
39
-
40
- # Turn file: into output_dir-as-root relative paths
41
-
42
- output_dir = @config.output_dir
43
- output_dir += '/' unless output_dir.end_with?('/')
44
- base_uri = URI("file://#{output_dir}")
45
- path = href.sub(/#{base_uri}/, '').sub(/file:\/{1,3}/, '')
46
-
47
- path = "/#{path}" unless path.start_with?('/')
48
-
49
- # Skip hrefs that are specified in the exclude configuration
50
- return true if excluded?(path, origin)
51
-
52
- # Make an absolute path
53
- path = ::File.join(output_dir, path[1..path.length])
54
-
55
- # Remove fragment
56
- path = path.sub(/#.*$/, '')
57
- return true if path.empty?
58
-
59
- # Remove query string
60
- path = path.sub(/\?.*$/, '')
61
- return true if path.empty?
62
-
63
- # Decode URL (e.g. '%20' -> ' ')
64
- path = CGI.unescape(path)
65
-
66
- # Check whether file exists
67
- return true if File.file?(path)
68
-
69
- # Check whether directory with index file exists
70
- return true if File.directory?(path) && @config[:index_filenames].any? { |fn| File.file?(File.join(path, fn)) }
71
-
72
- # Nope :(
73
- false
74
- end
75
-
76
- def excluded?(href, origin)
77
- config = @config.fetch(:checks, {}).fetch(:internal_links, {})
78
- excluded_target?(href, config) || excluded_origin?(origin, config)
79
- end
80
-
81
- def excluded_target?(href, config)
82
- excludes = config.fetch(:exclude_targets, config.fetch(:exclude, []))
83
- excludes.any? { |pattern| Regexp.new(pattern).match(href) }
84
- end
85
-
86
- def excluded_origin?(origin, config)
87
- # FIXME: do not depend on current working directory
88
- origin = File.absolute_path(origin)
89
-
90
- relative_origin = origin[@config.output_dir.size..-1]
91
- excludes = config.fetch(:exclude_origins, [])
92
- excludes.any? { |pattern| Regexp.new(pattern).match(relative_origin) }
93
- end
94
- end
95
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Checking::Checks
4
- # A check that verifies HTML files do not reference external resources with
5
- # URLs that would trigger "mixed content" warnings.
6
- #
7
- # @api private
8
- class MixedContent < ::Nanoc::Checking::Check
9
- identifier :mixed_content
10
-
11
- PROTOCOL_PATTERN = /^(\w+):\/\//.freeze
12
-
13
- def run
14
- filenames = output_html_filenames
15
- resource_uris_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames).filenames_per_resource_uri
16
-
17
- resource_uris_with_filenames.each_pair do |uri, fns|
18
- next unless guaranteed_insecure?(uri)
19
-
20
- fns.each do |filename|
21
- add_issue(
22
- "mixed content include: #{uri}",
23
- subject: filename,
24
- )
25
- end
26
- end
27
- end
28
-
29
- private
30
-
31
- def guaranteed_insecure?(href)
32
- protocol = PROTOCOL_PATTERN.match(href)
33
-
34
- protocol && protocol[1].casecmp('http').zero?
35
- end
36
- end
37
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Checking::Checks
4
- # @api private
5
- class Stale < ::Nanoc::Checking::Check
6
- identifier :stale
7
-
8
- def run
9
- output_filenames.each do |f|
10
- next if pruner.filename_excluded?(f)
11
- next if item_rep_paths.include?(f)
12
-
13
- add_issue(
14
- 'file without matching item',
15
- subject: f,
16
- )
17
- end
18
- end
19
-
20
- protected
21
-
22
- def item_rep_paths
23
- @item_rep_paths ||=
24
- Set.new(
25
- @items
26
- .flat_map(&:reps)
27
- .map(&:_unwrap)
28
- .flat_map(&:raw_paths)
29
- .flat_map(&:values)
30
- .flatten,
31
- )
32
- end
33
-
34
- def pruner
35
- exclude_config = @config.fetch(:prune, {}).fetch(:exclude, [])
36
- # FIXME: specifying reps this way is icky
37
- reps = Nanoc::Core::ItemRepRepo.new
38
- @pruner ||= Nanoc::Core::Pruner.new(@config._unwrap, reps, exclude: exclude_config)
39
- end
40
- end
41
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ::Nanoc::Checking::Checks
4
- # @api private
5
- class W3CValidator < ::Nanoc::Checking::Check
6
- def run
7
- require 'w3c_validators'
8
- require 'resolv-replace'
9
-
10
- Dir[@config.output_dir + '/**/*.' + extension].each do |filename|
11
- results = validator_class.new.validate_file(filename)
12
- lines = File.readlines(filename)
13
- results.errors.each do |e|
14
- line_num = e.line.to_i - 1
15
- line = lines[line_num]
16
- message = e.message.gsub(%r{\s+}, ' ').strip.sub(/\s+:$/, '')
17
- desc = "line #{line_num + 1}: #{message}: #{line}"
18
- add_issue(desc, subject: filename)
19
- end
20
- end
21
- end
22
-
23
- def extension
24
- raise NotImplementedError
25
- end
26
-
27
- def validator_class
28
- raise NotImplementedError
29
- end
30
- end
31
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Checking
4
- # @api private
5
- class DSL
6
- def self.from_file(filename, enabled_checks:)
7
- dsl = new(enabled_checks: enabled_checks)
8
- absolute_filename = File.expand_path(filename)
9
- dsl.instance_eval(File.read(filename), absolute_filename)
10
- dsl
11
- end
12
-
13
- def initialize(enabled_checks:)
14
- @enabled_checks = enabled_checks
15
- end
16
-
17
- def check(identifier, &block)
18
- klass = Class.new(::Nanoc::Checking::Check)
19
- klass.send(:define_method, :run, &block)
20
- klass.send(:identifier, identifier)
21
- end
22
-
23
- def deploy_check(*identifiers)
24
- identifiers.each { |i| @enabled_checks << i }
25
- end
26
- end
27
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Checking
4
- # @api private
5
- class Issue
6
- attr_reader :description
7
- attr_reader :subject
8
- attr_reader :check_class
9
-
10
- def initialize(desc, subject, check_class)
11
- @description = desc
12
- @subject = subject
13
- @check_class = check_class
14
- end
15
- end
16
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Checking
4
- # @api private
5
- class Loader
6
- CHECKS_FILENAMES = ['Checks', 'Checks.rb', 'checks', 'checks.rb'].freeze
7
-
8
- def initialize(config:)
9
- @config = config
10
- end
11
-
12
- def run
13
- dsl
14
- end
15
-
16
- def enabled_checks
17
- (enabled_checks_from_dsl + enabled_checks_from_config).uniq
18
- end
19
-
20
- private
21
-
22
- def dsl_present?
23
- checks_filename && File.file?(checks_filename)
24
- end
25
-
26
- def enabled_checks_from_dsl
27
- dsl
28
- @enabled_checks_from_dsl
29
- end
30
-
31
- def enabled_checks_from_config
32
- @config.fetch(:checking, {}).fetch(:enabled_checks, []).map(&:to_sym)
33
- end
34
-
35
- def dsl
36
- @enabled_checks_from_dsl ||= []
37
-
38
- @dsl ||=
39
- if dsl_present?
40
- Nanoc::Checking::DSL.from_file(checks_filename, enabled_checks: @enabled_checks_from_dsl)
41
- else
42
- Nanoc::Checking::DSL.new(enabled_checks: @enabled_checks_from_dsl)
43
- end
44
- end
45
-
46
- def checks_filename
47
- @_checks_filename ||= CHECKS_FILENAMES.find { |f| File.file?(f) }
48
- end
49
- end
50
- end
@@ -1,136 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Checking
4
- # Runner is reponsible for running issue checks.
5
- #
6
- # @api private
7
- class Runner
8
- # @param [Nanoc::Core::Site] site The Nanoc site this runner is for
9
- def initialize(site)
10
- @site = site
11
- end
12
-
13
- def any_enabled_checks?
14
- enabled_checks.any?
15
- end
16
-
17
- # Lists all available checks on stdout.
18
- #
19
- # @return [void]
20
- def list_checks
21
- load_all
22
-
23
- puts 'Available checks:'
24
- puts
25
- puts all_check_classes.map { |i| ' ' + i.identifier.to_s }.sort.join("\n")
26
- end
27
-
28
- # Runs all checks.
29
- #
30
- # @return [Boolean] true if successful, false otherwise
31
- def run_all
32
- load_all
33
- run_check_classes(all_check_classes)
34
- end
35
-
36
- # Runs the checks marked for deployment.
37
- #
38
- # @return [Boolean] true if successful, false otherwise
39
- def run_for_deploy
40
- # TODO: rename to #run_enabled
41
- load_all
42
- run_check_classes(check_classes_named(enabled_checks))
43
- end
44
-
45
- # Runs the checks with the given names.
46
- #
47
- # @param [Array<Symbol>] check_class_names The names of the checks
48
- #
49
- # @return [Boolean] true if successful, false otherwise
50
- def run_specific(check_class_names)
51
- load_all
52
- run_check_classes(check_classes_named(check_class_names))
53
- end
54
-
55
- private
56
-
57
- def loader
58
- @loader ||= Nanoc::Checking::Loader.new(config: @site.config)
59
- end
60
-
61
- def load_all
62
- loader.run
63
- end
64
-
65
- def enabled_checks
66
- loader.enabled_checks
67
- end
68
-
69
- def run_check_classes(classes)
70
- issues = run_checks(classes)
71
- print_issues(issues)
72
- issues.empty? ? true : false
73
- end
74
-
75
- def all_check_classes
76
- Nanoc::Checking::Check.all
77
- end
78
-
79
- def check_classes_named(names)
80
- names.map do |name|
81
- name = name.to_s.tr('-', '_').to_sym
82
- klass = Nanoc::Checking::Check.named(name)
83
- raise Nanoc::Core::TrivialError, "Unknown check: #{name}" if klass.nil?
84
-
85
- klass
86
- end
87
- end
88
-
89
- def run_checks(classes)
90
- return [] if classes.empty?
91
-
92
- # TODO: remove me
93
- Nanoc::Core::Compiler.new_for(@site).run_until_reps_built
94
-
95
- checks = []
96
- issues = Set.new
97
- length = classes.map { |c| c.identifier.to_s.length }.max + 18
98
- classes.each do |klass|
99
- print format(" %-#{length}s", "Running check #{klass.identifier}… ")
100
-
101
- check = klass.create(@site)
102
- check.run
103
-
104
- checks << check
105
- issues.merge(check.issues)
106
-
107
- # TODO: report progress
108
-
109
- puts check.issues.empty? ? 'ok'.green : 'error'.red
110
- end
111
- issues
112
- end
113
-
114
- def subject_to_s(str)
115
- str || '(global)'
116
- end
117
-
118
- def print_issues(issues)
119
- require 'colored'
120
-
121
- return if issues.empty?
122
-
123
- puts 'Issues found!'
124
- issues.group_by(&:subject).to_a.sort_by { |s| subject_to_s(s.first) }.each do |pair|
125
- subject = pair.first
126
- issues = pair.last
127
- next if issues.empty?
128
-
129
- puts " #{subject_to_s(subject)}:"
130
- issues.each do |i|
131
- puts " [ #{'ERROR'.red} ] #{i.check_class.identifier} - #{i.description}"
132
- end
133
- end
134
- end
135
- end
136
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- # @api private
5
- module Deploying
6
- end
7
- end
8
-
9
- require 'nanoc/deploying/deployer'
10
- require 'nanoc/deploying/deployers'