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,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Deploying
4
- # Represents a deployer, an object that allows uploading the compiled site
5
- # to a specific (remote) location.
6
- #
7
- # @abstract Subclass and override {#run} to implement a custom filter.
8
- #
9
- # @api private
10
- class Deployer
11
- extend DDPlugin::Plugin
12
-
13
- # @return [String] The path to the directory that contains the files to
14
- # upload. It should not have a trailing slash.
15
- attr_reader :source_path
16
-
17
- # @return [Hash] The deployer configuration
18
- attr_reader :config
19
-
20
- # @return [Boolean] true if the deployer should only show what would be
21
- # deployed instead of doing the actual deployment
22
- attr_reader :dry_run
23
- alias dry_run? dry_run
24
-
25
- # @param [String] source_path The path to the directory that contains the
26
- # files to upload. It should not have a trailing slash.
27
- #
28
- # @return [Hash] config The deployer configuration
29
- #
30
- # @param [Boolean] dry_run true if the deployer should
31
- # only show what would be deployed instead actually deploying
32
- def initialize(source_path, config, dry_run: false)
33
- @source_path = source_path
34
- @config = config
35
- @dry_run = dry_run
36
- end
37
-
38
- # Performs the actual deployment.
39
- #
40
- # @abstract
41
- def run
42
- raise NotImplementedError.new('Nanoc::Deploying::Deployer subclasses must implement #run')
43
- end
44
- end
45
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'tty-command'
4
-
5
- # @api private
6
- module Nanoc::Deploying::Deployers
7
- end
8
-
9
- require_relative 'deployers/fog'
10
- require_relative 'deployers/git'
11
- require_relative 'deployers/rsync'
@@ -1,220 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Deploying::Deployers
4
- # A deployer that deploys a site using [fog](https://github.com/fog/fog).
5
- #
6
- # @example A deployment configuration with public and staging configurations
7
- #
8
- # deploy:
9
- # public:
10
- # kind: fog
11
- # bucket: nanoc-site
12
- # cdn_id: XXXXXX
13
- # preprod:
14
- # kind: fog
15
- # provider: local
16
- # local_root: ~/myCloud
17
- # bucket: nanoc-site
18
- # staging:
19
- # kind: fog
20
- # provider: local
21
- # local_root: ~/myCloud
22
- # bucket: nanoc-site-staging
23
- #
24
- # @api private
25
- class Fog < ::Nanoc::Deploying::Deployer
26
- identifier :fog
27
-
28
- class FogWrapper
29
- def initialize(directory, is_dry_run)
30
- @directory = directory
31
- @is_dry_run = is_dry_run
32
- end
33
-
34
- def upload(source_filename, destination_key)
35
- log_effectful("uploading #{source_filename} -> #{destination_key}")
36
-
37
- unless dry_run?
38
- File.open(source_filename) do |io|
39
- @directory.files.create(
40
- key: destination_key,
41
- body: io,
42
- public: true,
43
- )
44
- end
45
- end
46
- end
47
-
48
- def remove(keys)
49
- keys.each do |key|
50
- log_effectful("removing #{key}")
51
-
52
- unless dry_run?
53
- @directory.files.get(key).destroy
54
- end
55
- end
56
- end
57
-
58
- def invalidate(keys, cdn, distribution)
59
- keys.each_slice(1000) do |keys_slice|
60
- keys_slice.each do |key|
61
- log_effectful("invalidating #{key}")
62
- end
63
-
64
- unless dry_run?
65
- cdn.post_invalidation(distribution, keys_slice)
66
- end
67
- end
68
- end
69
-
70
- def dry_run?
71
- @is_dry_run
72
- end
73
-
74
- def log_effectful(str)
75
- if @is_dry_run
76
- puts "[dry run] #{str}"
77
- else
78
- puts str
79
- end
80
- end
81
- end
82
-
83
- # @see Nanoc::Deploying::Deployer#run
84
- def run
85
- require 'fog/core'
86
-
87
- src = File.expand_path(source_path)
88
- bucket = config[:bucket] || config[:bucket_name]
89
- path = config[:path]
90
- cdn_id = config[:cdn_id]
91
-
92
- if path&.end_with?('/')
93
- raise "The path `#{path}` is not supposed to have a trailing slash"
94
- end
95
-
96
- connection = connect
97
- directory = get_or_create_bucket(connection, bucket, path)
98
- wrapper = FogWrapper.new(directory, dry_run?)
99
-
100
- remote_files = list_remote_files(directory)
101
- etags = read_etags(remote_files)
102
-
103
- modified_keys, retained_keys = upload_all(src, path, etags, wrapper)
104
-
105
- removed_keys = remote_files.map(&:key) - retained_keys - modified_keys
106
- wrapper.remove(removed_keys)
107
-
108
- if cdn_id
109
- cdn = ::Fog::CDN.new(config_for_fog)
110
- distribution = cdn.get_distribution(cdn_id)
111
- wrapper.invalidate(modified_keys + removed_keys, cdn, distribution)
112
- end
113
- end
114
-
115
- private
116
-
117
- def config_for_fog
118
- config.dup.tap do |c|
119
- c.delete(:bucket)
120
- c.delete(:bucket_name)
121
- c.delete(:path)
122
- c.delete(:cdn_id)
123
- c.delete(:kind)
124
- end
125
- end
126
-
127
- def connect
128
- ::Fog::Storage.new(config_for_fog)
129
- rescue ArgumentError
130
- require "fog/#{config[:provider]}"
131
- ::Fog::Storage.new(config_for_fog)
132
- end
133
-
134
- def get_or_create_bucket(connection, bucket, path)
135
- directory =
136
- begin
137
- connection.directories.get(bucket, prefix: path)
138
- rescue ::Excon::Errors::NotFound
139
- nil
140
- end
141
-
142
- if directory
143
- directory
144
- elsif dry_run?
145
- puts '[dry run] creating bucket'
146
- else
147
- puts 'creating bucket'
148
- connection.directories.create(key: bucket, prefix: path)
149
- end
150
- end
151
-
152
- def remote_key_for_local_filename(local_filename, src, path)
153
- relative_local_filename = local_filename.sub(/\A#{src}\//, '')
154
-
155
- if path
156
- File.join(path, relative_local_filename)
157
- else
158
- relative_local_filename
159
- end
160
- end
161
-
162
- def list_remote_files(directory)
163
- if directory
164
- [].tap do |files|
165
- directory.files.each { |file| files << file }
166
- end
167
- else
168
- []
169
- end
170
- end
171
-
172
- def list_local_files(src)
173
- Dir[src + '/**/*'].select { |f| File.file?(f) }
174
- end
175
-
176
- def upload_all(src, path, etags, wrapper)
177
- modified_keys = []
178
- retained_keys = []
179
-
180
- local_files = list_local_files(src)
181
- local_files.each do |file_path|
182
- key = remote_key_for_local_filename(file_path, src, path)
183
- if needs_upload?(key, file_path, etags)
184
- wrapper.upload(file_path, key)
185
- modified_keys.push(key)
186
- else
187
- retained_keys.push(key)
188
- end
189
- end
190
-
191
- [modified_keys, retained_keys]
192
- end
193
-
194
- def needs_upload?(key, file_path, etags)
195
- remote_etag = etags[key]
196
- return true if remote_etag.nil?
197
-
198
- local_etag = calc_local_etag(file_path)
199
- remote_etag != local_etag
200
- end
201
-
202
- def read_etags(files)
203
- case config[:provider]
204
- when 'aws'
205
- files.each_with_object({}) do |file, etags|
206
- etags[file.key] = file.etag
207
- end
208
- else
209
- {}
210
- end
211
- end
212
-
213
- def calc_local_etag(file_path)
214
- case config[:provider]
215
- when 'aws'
216
- Digest::MD5.file(file_path).hexdigest
217
- end
218
- end
219
- end
220
- end
@@ -1,112 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Deploying::Deployers
4
- # A deployer that deploys a site using [Git](https://git-scm.com).
5
- #
6
- # @example A deployment configuration for GitHub Pages:
7
- #
8
- # deploy:
9
- # default:
10
- # kind: git
11
- # remote: git@github.com:myself/myproject.git
12
- # branch: gh-pages
13
- # forced: true
14
- #
15
- class Git < ::Nanoc::Deploying::Deployer
16
- identifier :git
17
-
18
- module Errors
19
- class Generic < ::Nanoc::Core::Error
20
- end
21
-
22
- class OutputDirDoesNotExist < Generic
23
- def initialize(path)
24
- super("The directory to deploy, #{path}, does not exist.")
25
- end
26
- end
27
-
28
- class OutputDirIsNotAGitRepo < Generic
29
- def initialize(path)
30
- super("The directory to deploy, #{path}, is not a Git repository.")
31
- end
32
- end
33
-
34
- class RemoteDoesNotExist < Generic
35
- def initialize(remote)
36
- super("The remote to deploy to, #{remote}, does not exist.")
37
- end
38
- end
39
-
40
- class BranchDoesNotExist < Generic
41
- def initialize(branch)
42
- super("The branch to deploy, #{branch}, does not exist.")
43
- end
44
- end
45
- end
46
-
47
- def run
48
- unless File.exist?(source_path)
49
- raise Errors::OutputDirDoesNotExist.new(source_path)
50
- end
51
-
52
- remote = config.fetch(:remote, 'origin')
53
- branch = config.fetch(:branch, 'master')
54
- forced = config.fetch(:forced, false)
55
-
56
- puts "Deploying via Git to branch “#{branch}” on remote “#{remote}”…"
57
-
58
- Dir.chdir(source_path) do
59
- unless File.exist?('.git')
60
- raise Errors::OutputDirIsNotAGitRepo.new(source_path)
61
- end
62
-
63
- # Verify existence of remote, if remote is not a URL
64
- if remote_is_name?(remote)
65
- begin
66
- run_cmd(%W[git config --get remote.#{remote}.url])
67
- rescue TTY::Command::ExitError
68
- raise Errors::RemoteDoesNotExist.new(remote)
69
- end
70
- end
71
-
72
- # If the branch exists then switch to it, otherwise prompt the user to create one.
73
- begin
74
- run_cmd_unless_dry(%W[git checkout #{branch}])
75
- rescue TTY::Command::ExitError
76
- raise Errors::BranchDoesNotExist.new(branch)
77
- end
78
-
79
- return if clean_repo?
80
-
81
- msg = "Automated commit at #{Time.now.utc} by Nanoc #{Nanoc::VERSION}"
82
- author = 'Nanoc <>'
83
- run_cmd_unless_dry(%w[git add -A])
84
- run_cmd_unless_dry(%W[git commit -a --author #{author} -m #{msg}])
85
-
86
- if forced
87
- run_cmd_unless_dry(%W[git push -f #{remote} #{branch}])
88
- else
89
- run_cmd_unless_dry(%W[git push #{remote} #{branch}])
90
- end
91
- end
92
- end
93
-
94
- private
95
-
96
- def remote_is_name?(remote)
97
- remote !~ /:\/\/|@.+:/
98
- end
99
-
100
- def run_cmd(cmd, dry_run: false)
101
- TTY::Command.new(printer: :null).run(*cmd, dry_run: dry_run)
102
- end
103
-
104
- def run_cmd_unless_dry(cmd)
105
- run_cmd(cmd, dry_run: dry_run)
106
- end
107
-
108
- def clean_repo?
109
- TTY::Command.new(printer: :null).run('git status --porcelain').out.empty?
110
- end
111
- end
112
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc::Deploying::Deployers
4
- # A deployer that deploys a site using rsync.
5
- #
6
- # The configuration has should include a `:dst` value, a string containing
7
- # the destination to where rsync should upload its data. It will likely be
8
- # in `host:path` format. It should not end with a slash. For example,
9
- # `"example.com:/var/www/sites/mysite/html"`.
10
- #
11
- # @example A deployment configuration with public and staging configurations
12
- #
13
- # deploy:
14
- # public:
15
- # kind: rsync
16
- # dst: "ectype:sites/stoneship/public"
17
- # staging:
18
- # kind: rsync
19
- # dst: "ectype:sites/stoneship-staging/public"
20
- # options: [ "-glpPrtvz" ]
21
- #
22
- # @api private
23
- class Rsync < ::Nanoc::Deploying::Deployer
24
- identifier :rsync
25
-
26
- # Default rsync options
27
- DEFAULT_OPTIONS = [
28
- '--group',
29
- '--links',
30
- '--perms',
31
- '--partial',
32
- '--progress',
33
- '--recursive',
34
- '--times',
35
- '--verbose',
36
- '--compress',
37
- '--exclude=".hg"',
38
- '--exclude=".svn"',
39
- '--exclude=".git"',
40
- ].freeze
41
-
42
- # @see Nanoc::Deploying::Deployer#run
43
- def run
44
- # Get params
45
- src = source_path + '/'
46
- dst = config[:dst]
47
- options = config[:options] || DEFAULT_OPTIONS
48
-
49
- # Validate
50
- raise 'No dst found in deployment configuration' if dst.nil?
51
- raise 'dst requires no trailing slash' if dst[-1, 1] == '/'
52
-
53
- # Run
54
- if dry_run
55
- warn 'Performing a dry-run; no actions will actually be performed'
56
- run_shell_cmd(['echo', 'rsync', options, src, dst].flatten)
57
- else
58
- run_shell_cmd(['rsync', options, src, dst].flatten)
59
- end
60
- end
61
-
62
- private
63
-
64
- def run_shell_cmd(cmd)
65
- TTY::Command.new(printer: :null).run(*cmd)
66
- end
67
- end
68
- end