nanoc 4.0.2 → 4.1.0a1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +17 -0
  3. data/Gemfile +50 -46
  4. data/Gemfile.lock +365 -0
  5. data/Guardfile +3 -0
  6. data/NEWS.md +21 -0
  7. data/README.md +1 -1
  8. data/lib/nanoc/base.rb +3 -15
  9. data/lib/nanoc/base/checksummer.rb +3 -14
  10. data/lib/nanoc/base/compilation/compiler.rb +112 -283
  11. data/lib/nanoc/base/compilation/compiler_dsl.rb +29 -37
  12. data/lib/nanoc/base/compilation/dependency_tracker.rb +25 -170
  13. data/lib/nanoc/base/compilation/filter.rb +3 -4
  14. data/lib/nanoc/base/compilation/item_rep_repo.rb +33 -0
  15. data/lib/nanoc/base/compilation/outdatedness_checker.rb +39 -53
  16. data/lib/nanoc/base/compilation/rule.rb +13 -24
  17. data/lib/nanoc/base/compilation/rule_context.rb +29 -15
  18. data/lib/nanoc/base/entities.rb +10 -0
  19. data/lib/nanoc/base/{source_data → entities}/code_snippet.rb +1 -4
  20. data/lib/nanoc/base/{source_data → entities}/configuration.rb +1 -1
  21. data/lib/nanoc/base/entities/content.rb +8 -9
  22. data/lib/nanoc/base/{identifiable_collection.rb → entities/identifiable_collection.rb} +0 -0
  23. data/lib/nanoc/base/entities/identifier.rb +11 -2
  24. data/lib/nanoc/base/{source_data → entities}/item.rb +0 -18
  25. data/lib/nanoc/base/{result_data → entities}/item_rep.rb +15 -13
  26. data/lib/nanoc/base/entities/rule_memory.rb +54 -0
  27. data/lib/nanoc/base/entities/rule_memory_action.rb +19 -0
  28. data/lib/nanoc/base/entities/rule_memory_actions.rb +3 -0
  29. data/lib/nanoc/base/entities/rule_memory_actions/filter.rb +22 -0
  30. data/lib/nanoc/base/entities/rule_memory_actions/layout.rb +22 -0
  31. data/lib/nanoc/base/entities/rule_memory_actions/snapshot.rb +26 -0
  32. data/lib/nanoc/base/entities/rules_collection.rb +120 -0
  33. data/lib/nanoc/base/{source_data → entities}/site.rb +11 -10
  34. data/lib/nanoc/base/repos.rb +2 -0
  35. data/lib/nanoc/base/repos/checksum_store.rb +3 -9
  36. data/lib/nanoc/base/repos/compiled_content_cache.rb +0 -5
  37. data/lib/nanoc/base/{source_data → repos}/data_source.rb +3 -6
  38. data/lib/nanoc/base/repos/dependency_store.rb +118 -0
  39. data/lib/nanoc/base/repos/rule_memory_store.rb +1 -5
  40. data/lib/nanoc/base/repos/site_loader.rb +0 -28
  41. data/lib/nanoc/base/repos/store.rb +0 -12
  42. data/lib/nanoc/base/services.rb +8 -0
  43. data/lib/nanoc/base/services/compiler_loader.rb +49 -0
  44. data/lib/nanoc/base/services/executor.rb +4 -4
  45. data/lib/nanoc/base/services/item_rep_builder.rb +30 -0
  46. data/lib/nanoc/base/services/item_rep_router.rb +55 -0
  47. data/lib/nanoc/base/services/item_rep_selector.rb +39 -0
  48. data/lib/nanoc/base/services/item_rep_writer.rb +2 -0
  49. data/lib/nanoc/base/services/postprocessor.rb +26 -0
  50. data/lib/nanoc/base/services/preprocessor.rb +26 -0
  51. data/lib/nanoc/base/services/recording_executor.rb +36 -22
  52. data/lib/nanoc/base/services/rule_memory_calculator.rb +84 -0
  53. data/lib/nanoc/base/services/rules_loader.rb +29 -0
  54. data/lib/nanoc/base/views.rb +6 -0
  55. data/lib/nanoc/base/views/config_view.rb +8 -2
  56. data/lib/nanoc/base/views/identifiable_collection_view.rb +5 -4
  57. data/lib/nanoc/base/views/item_rep_collection_view.rb +7 -6
  58. data/lib/nanoc/base/views/item_rep_view.rb +13 -12
  59. data/lib/nanoc/base/views/item_view.rb +18 -12
  60. data/lib/nanoc/base/views/layout_view.rb +1 -1
  61. data/lib/nanoc/base/views/mixins/document_view_mixin.rb +2 -1
  62. data/lib/nanoc/base/views/mutable_identifiable_collection_view.rb +1 -1
  63. data/lib/nanoc/base/views/mutable_item_collection_view.rb +4 -7
  64. data/lib/nanoc/base/views/post_compile_item_collection_view.rb +8 -0
  65. data/lib/nanoc/base/views/post_compile_item_view.rb +7 -0
  66. data/lib/nanoc/base/views/site_view.rb +3 -2
  67. data/lib/nanoc/base/views/view.rb +12 -0
  68. data/lib/nanoc/base/views/view_context.rb +12 -0
  69. data/lib/nanoc/cli/commands/compile.rb +13 -15
  70. data/lib/nanoc/cli/commands/create-site.rb +15 -0
  71. data/lib/nanoc/cli/commands/prune.rb +1 -1
  72. data/lib/nanoc/cli/commands/shell.rb +3 -3
  73. data/lib/nanoc/cli/commands/show-data.rb +5 -5
  74. data/lib/nanoc/cli/commands/show-rules.rb +2 -1
  75. data/lib/nanoc/cli/error_handler.rb +28 -30
  76. data/lib/nanoc/cli/stream_cleaners/ansi_colors.rb +1 -1
  77. data/lib/nanoc/data_sources/filesystem.rb +1 -1
  78. data/lib/nanoc/extra/checking/check.rb +8 -7
  79. data/lib/nanoc/extra/checking/checks/external_links.rb +14 -1
  80. data/lib/nanoc/extra/checking/runner.rb +1 -1
  81. data/lib/nanoc/extra/deployer.rb +3 -3
  82. data/lib/nanoc/extra/piper.rb +5 -5
  83. data/lib/nanoc/extra/pruner.rb +8 -7
  84. data/lib/nanoc/filters/relativize_paths.rb +48 -32
  85. data/lib/nanoc/filters/sass/sass_filesystem_importer.rb +0 -1
  86. data/lib/nanoc/helpers/blogging.rb +15 -7
  87. data/lib/nanoc/helpers/capturing.rb +56 -13
  88. data/lib/nanoc/helpers/link_to.rb +2 -2
  89. data/lib/nanoc/helpers/tagging.rb +5 -10
  90. data/lib/nanoc/helpers/text.rb +9 -11
  91. data/lib/nanoc/version.rb +1 -1
  92. data/nanoc-4.0.2.gem +0 -0
  93. data/tags +1175 -0
  94. data/test/base/test_compiler.rb +48 -98
  95. data/test/base/test_compiler_dsl.rb +113 -39
  96. data/test/base/test_dependency_tracker.rb +80 -79
  97. data/test/base/test_outdatedness_checker.rb +39 -26
  98. data/test/base/test_site.rb +0 -97
  99. data/test/cli/commands/test_compile.rb +2 -3
  100. data/test/extra/checking/checks/test_external_links.rb +25 -0
  101. data/test/extra/deployers/test_fog.rb +12 -6
  102. data/test/filters/test_erb.rb +1 -1
  103. data/test/filters/test_erubis.rb +1 -1
  104. data/test/filters/test_haml.rb +1 -1
  105. data/test/filters/test_less.rb +4 -4
  106. data/test/filters/test_sass.rb +1 -0
  107. data/test/filters/test_xsl.rb +7 -8
  108. data/test/helper.rb +0 -2
  109. data/test/helpers/test_blogging.rb +26 -23
  110. data/test/helpers/test_capturing.rb +131 -12
  111. data/test/helpers/test_filtering.rb +6 -6
  112. data/test/helpers/test_link_to.rb +1 -1
  113. data/test/helpers/test_rendering.rb +16 -24
  114. data/test/helpers/test_tagging.rb +13 -10
  115. data/test/helpers/test_xml_sitemap.rb +25 -21
  116. metadata +36 -14
  117. data/lib/nanoc/base/compilation/rule_memory_calculator.rb +0 -35
  118. data/lib/nanoc/base/compilation/rules_collection.rb +0 -245
  119. data/test/base/test_rule_context.rb +0 -78
@@ -91,6 +91,21 @@ checks:
91
91
  # E.g.:
92
92
  # exclude: ['^/server_status']
93
93
  exclude: []
94
+
95
+ # Configuration for the “external_links” checker, which checks whether all
96
+ # external links are valid.
97
+ external_links:
98
+ # A list of patterns, specified as regular expressions, to exclude from the check.
99
+ # If an external link matches this pattern, the validity check will be skipped.
100
+ # E.g.:
101
+ # exclude: ['^http://example.com$']
102
+ exclude: []
103
+
104
+ # A list of file patterns, specified as regular expressions, to exclude from the check.
105
+ # If a file matches this pattern, the links from this file will not be checked.
106
+ # E.g.:
107
+ # exclude_files: ['blog/page']
108
+ exclude_files: []
94
109
  EOS
95
110
 
96
111
  DEFAULT_RULES = <<EOS unless defined? DEFAULT_RULES
@@ -16,7 +16,7 @@ module Nanoc::CLI::Commands
16
16
  class Prune < ::Nanoc::CLI::CommandRunner
17
17
  def run
18
18
  load_site
19
- site.compiler.load
19
+ site.compiler.build_reps
20
20
 
21
21
  if options.key?(:yes)
22
22
  Nanoc::Extra::Pruner.new(site, exclude: prune_config_exclude).run
@@ -23,9 +23,9 @@ module Nanoc::CLI::Commands
23
23
 
24
24
  def self.env_for_site(site)
25
25
  {
26
- items: Nanoc::ItemCollectionView.new(site.items),
27
- layouts: Nanoc::LayoutCollectionView.new(site.layouts),
28
- config: Nanoc::ConfigView.new(site.config),
26
+ items: Nanoc::ItemCollectionView.new(site.items, nil),
27
+ layouts: Nanoc::LayoutCollectionView.new(site.layouts, nil),
28
+ config: Nanoc::ConfigView.new(site.config, nil),
29
29
  }
30
30
  end
31
31
  end
@@ -17,11 +17,11 @@ module Nanoc::CLI::Commands
17
17
 
18
18
  # Get dependency tracker
19
19
  compiler = site.compiler
20
- compiler.load
21
- dependency_tracker = compiler.dependency_tracker
20
+ compiler.load_stores
21
+ dependency_store = compiler.dependency_store
22
22
 
23
23
  # Print data
24
- print_item_dependencies(items, dependency_tracker)
24
+ print_item_dependencies(items, dependency_store)
25
25
  print_item_rep_paths(items)
26
26
  print_item_rep_outdatedness(items, compiler)
27
27
  print_layouts(layouts, compiler)
@@ -56,13 +56,13 @@ module Nanoc::CLI::Commands
56
56
  puts
57
57
  end
58
58
 
59
- def print_item_dependencies(items, dependency_tracker)
59
+ def print_item_dependencies(items, dependency_store)
60
60
  print_header('Item dependencies')
61
61
 
62
62
  sorted_with_prev(items) do |item, prev|
63
63
  puts if prev
64
64
  puts "item #{item.identifier} depends on:"
65
- predecessors = dependency_tracker.objects_causing_outdatedness_of(item).sort_by { |i| i ? i.identifier : '' }
65
+ predecessors = dependency_store.objects_causing_outdatedness_of(item).sort_by { |i| i ? i.identifier : '' }
66
66
  predecessors.each do |pred|
67
67
  type =
68
68
  case pred
@@ -12,6 +12,7 @@ module Nanoc::CLI::Commands
12
12
 
13
13
  @c = Nanoc::CLI::ANSIStringColorizer
14
14
  @rules = site.compiler.rules_collection
15
+ @reps = site.compiler.reps
15
16
 
16
17
  site.items.sort_by(&:identifier).each { |e| explain_item(e) }
17
18
  site.layouts.sort_by(&:identifier).each { |e| explain_layout(e) }
@@ -20,7 +21,7 @@ module Nanoc::CLI::Commands
20
21
  def explain_item(item)
21
22
  puts "#{@c.c('Item ' + item.identifier, :bold, :yellow)}:"
22
23
 
23
- item.reps.each do |rep|
24
+ @reps[item].each do |rep|
24
25
  rule = @rules.compilation_rule_for(rep)
25
26
  puts " Rep #{rep.name}: #{rule ? rule.pattern : '(none)'}"
26
27
  end
@@ -3,23 +3,23 @@ module Nanoc::CLI
3
3
  #
4
4
  # @api private
5
5
  class ErrorHandler
6
- # @option params [Nanoc::CLI::Command, nil] command The command that is
6
+ # @param [Nanoc::CLI::Command, nil] command The command that is
7
7
  # currently being executed, or nil if there is none
8
- def initialize(params = {})
9
- @command = params[:command]
8
+ def initialize(command: nil)
9
+ @command = command
10
10
  end
11
11
 
12
12
  # Enables error handling in the given block.
13
13
  #
14
- # @option params [Nanoc::CLI::Command, nil] command The command that is
14
+ # @param [Nanoc::CLI::Command, nil] command The command that is
15
15
  # currently being executed, or nil if there is none
16
16
  #
17
17
  # @return [void]
18
- def self.handle_while(params = {}, &block)
18
+ def self.handle_while(command: nil, &block)
19
19
  if @disabled
20
20
  yield
21
21
  else
22
- new(params).handle_while(&block)
22
+ new(command: command).handle_while(&block)
23
23
  end
24
24
  end
25
25
 
@@ -247,9 +247,9 @@ module Nanoc::CLI
247
247
  defined?(Bundler) && Bundler::SharedHelpers.in_bundle?
248
248
  end
249
249
 
250
- def write_section_header(stream, title, params = {})
250
+ def write_section_header(stream, title, verbose: false)
251
251
  stream.puts
252
- if params[:verbose]
252
+ if verbose
253
253
  stream.puts '===== ' + title.upcase + ':'
254
254
  else
255
255
  stream.puts "\e[1m\e[31m" + title + ':' + "\e[0m"
@@ -257,16 +257,16 @@ module Nanoc::CLI
257
257
  stream.puts
258
258
  end
259
259
 
260
- def write_error_message(stream, error, params = {})
261
- write_section_header(stream, 'Message', params)
260
+ def write_error_message(stream, error, verbose: false)
261
+ write_section_header(stream, 'Message', verbose: verbose)
262
262
 
263
263
  stream.puts "#{error.class}: #{error.message}"
264
264
  resolution = resolution_for(error)
265
265
  stream.puts "#{resolution}" if resolution
266
266
  end
267
267
 
268
- def write_compilation_stack(stream, _error, params = {})
269
- write_section_header(stream, 'Compilation stack', params)
268
+ def write_compilation_stack(stream, _error, verbose: false)
269
+ write_section_header(stream, 'Compilation stack', verbose: verbose)
270
270
 
271
271
  if stack.empty?
272
272
  stream.puts ' (empty)'
@@ -281,16 +281,14 @@ module Nanoc::CLI
281
281
  end
282
282
  end
283
283
 
284
- def write_stack_trace(stream, error, params = {})
285
- is_verbose = params.fetch(:verbose, false)
284
+ def write_stack_trace(stream, error, verbose: false)
285
+ write_section_header(stream, 'Stack trace', verbose: verbose)
286
286
 
287
- write_section_header(stream, 'Stack trace', params)
288
-
289
- count = is_verbose ? -1 : 10
287
+ count = verbose ? -1 : 10
290
288
  error.backtrace[0...count].each_with_index do |item, index|
291
289
  stream.puts " #{index}. #{item}"
292
290
  end
293
- if !is_verbose && error.backtrace.size > count
291
+ if !verbose && error.backtrace.size > count
294
292
  stream.puts " ... #{error.backtrace.size - count} more lines omitted. See full crash log for details."
295
293
  end
296
294
  end
@@ -303,41 +301,41 @@ module Nanoc::CLI
303
301
  stream.puts 'A detailed crash log has been written to ./crash.log.'
304
302
  end
305
303
 
306
- def write_version_information(stream, params = {})
307
- write_section_header(stream, 'Version information', params)
304
+ def write_version_information(stream, verbose: false)
305
+ write_section_header(stream, 'Version information', verbose: verbose)
308
306
  stream.puts Nanoc.version_information
309
307
  end
310
308
 
311
- def write_system_information(stream, params = {})
309
+ def write_system_information(stream, verbose: false)
312
310
  uname = `uname -a`
313
- write_section_header(stream, 'System information', params)
311
+ write_section_header(stream, 'System information', verbose: verbose)
314
312
  stream.puts uname
315
313
  rescue Errno::ENOENT
316
314
  end
317
315
 
318
- def write_installed_gems(stream, params = {})
319
- write_section_header(stream, 'Installed gems', params)
316
+ def write_installed_gems(stream, verbose: false)
317
+ write_section_header(stream, 'Installed gems', verbose: verbose)
320
318
  gems_and_versions.each do |g|
321
319
  stream.puts " #{g.first} #{g.last.join(', ')}"
322
320
  end
323
321
  end
324
322
 
325
- def write_environment(stream, params = {})
326
- write_section_header(stream, 'Environment', params)
323
+ def write_environment(stream, verbose: false)
324
+ write_section_header(stream, 'Environment', verbose: verbose)
327
325
  ENV.sort.each do |e|
328
326
  stream.puts "#{e.first} => #{e.last.inspect}"
329
327
  end
330
328
  end
331
329
 
332
- def write_gemfile_lock(stream, params = {})
330
+ def write_gemfile_lock(stream, verbose: false)
333
331
  if File.exist?('Gemfile.lock')
334
- write_section_header(stream, 'Gemfile.lock', params)
332
+ write_section_header(stream, 'Gemfile.lock', verbose: verbose)
335
333
  stream.puts File.read('Gemfile.lock')
336
334
  end
337
335
  end
338
336
 
339
- def write_load_paths(stream, params = {})
340
- write_section_header(stream, 'Load paths', params)
337
+ def write_load_paths(stream, verbose: false)
338
+ write_section_header(stream, 'Load paths', verbose: verbose)
341
339
  $LOAD_PATH.each_with_index do |i, index|
342
340
  stream.puts " #{index}. #{i}"
343
341
  end
@@ -5,7 +5,7 @@ module Nanoc::CLI::StreamCleaners
5
5
  class ANSIColors < Abstract
6
6
  # @see Nanoc::CLI::StreamCleaners::Abstract#clean
7
7
  def clean(s)
8
- s.gsub(/\e\[.+?m/, '')
8
+ s.is_a?(String) ? s.gsub(/\e\[.+?m/, '') : s
9
9
  end
10
10
  end
11
11
  end
@@ -192,7 +192,7 @@ module Nanoc::DataSources
192
192
  # Returns the extension(s) of filename. Supports multiple extensions.
193
193
  # Includes the leading period.
194
194
  def ext_of(filename)
195
- filename =~ extension_regex ? $1 : ''
195
+ filename =~ extension_regex ? Regexp.last_match[1] : ''
196
196
  end
197
197
 
198
198
  # Returns a regex that is used for determining the extension of a file
@@ -19,11 +19,14 @@ module Nanoc::Extra::Checking
19
19
  end
20
20
  output_filenames = Dir[output_dir + '/**/*'].select { |f| File.file?(f) }
21
21
 
22
+ # FIXME: ugly
23
+ view_context = site.compiler.create_view_context
24
+
22
25
  context = {
23
- items: Nanoc::ItemCollectionView.new(site.items),
24
- layouts: Nanoc::LayoutCollectionView.new(site.layouts),
25
- config: Nanoc::ConfigView.new(site.config),
26
- site: Nanoc::SiteView.new(site), # TODO: remove me
26
+ items: Nanoc::ItemCollectionView.new(site.items, view_context),
27
+ layouts: Nanoc::LayoutCollectionView.new(site.layouts, view_context),
28
+ config: Nanoc::ConfigView.new(site.config, view_context),
29
+ site: Nanoc::SiteView.new(site, view_context), # TODO: remove me
27
30
  output_filenames: output_filenames,
28
31
  }
29
32
 
@@ -40,9 +43,7 @@ module Nanoc::Extra::Checking
40
43
  raise NotImplementedError.new('Nanoc::Extra::Checking::Check subclasses must implement #run')
41
44
  end
42
45
 
43
- def add_issue(desc, params = {})
44
- subject = params.fetch(:subject, nil)
45
-
46
+ def add_issue(desc, subject: nil)
46
47
  @issues << Issue.new(desc, subject, self.class)
47
48
  end
48
49
  end
@@ -14,7 +14,7 @@ module ::Nanoc::Extra::Checking::Checks
14
14
  def run
15
15
  # Find all broken external hrefs
16
16
  # TODO: de-duplicate this (duplicated in internal links check)
17
- filenames = output_filenames.select { |f| File.extname(f) == '.html' }
17
+ filenames = output_filenames.select { |f| File.extname(f) == '.html' && !excluded_file?(f) }
18
18
  hrefs_with_filenames = ::Nanoc::Extra::LinkCollector.new(filenames, :external).filenames_per_href
19
19
  results = select_invalid(hrefs_with_filenames.keys)
20
20
 
@@ -89,6 +89,9 @@ module ::Nanoc::Extra::Checking::Checks
89
89
  return Result.new(href, 'invalid URI')
90
90
  end
91
91
 
92
+ # Skip excluded URLs
93
+ return nil if self.excluded?(href)
94
+
92
95
  # Skip non-HTTP URLs
93
96
  return nil if url.scheme !~ /^https?$/
94
97
 
@@ -161,5 +164,15 @@ module ::Nanoc::Extra::Checking::Checks
161
164
  end
162
165
  http.request(req)
163
166
  end
167
+
168
+ def excluded?(href)
169
+ excludes = @config.fetch(:checks, {}).fetch(:external_links, {}).fetch(:exclude, [])
170
+ excludes.any? { |pattern| Regexp.new(pattern).match(href) }
171
+ end
172
+
173
+ def excluded_file?(file)
174
+ excludes = @config.fetch(:checks, {}).fetch(:external_links, {}).fetch(:exclude_files, [])
175
+ excludes.any? { |pattern| Regexp.new(pattern).match(file) }
176
+ end
164
177
  end
165
178
  end
@@ -107,7 +107,7 @@ module Nanoc::Extra::Checking
107
107
  return [] if classes.empty?
108
108
 
109
109
  # TODO: remove me
110
- @site.compiler.load
110
+ @site.compiler.build_reps
111
111
 
112
112
  checks = []
113
113
  issues = Set.new
@@ -25,12 +25,12 @@ module Nanoc::Extra
25
25
  #
26
26
  # @return [Hash] config The deployer configuration
27
27
  #
28
- # @option params [Boolean] :dry_run (false) true if the deployer should
28
+ # @param [Boolean] dry_run true if the deployer should
29
29
  # only show what would be deployed instead actually deploying
30
- def initialize(source_path, config, params = {})
30
+ def initialize(source_path, config, dry_run: false)
31
31
  @source_path = source_path
32
32
  @config = config
33
- @dry_run = params.fetch(:dry_run) { false }
33
+ @dry_run = dry_run
34
34
  end
35
35
 
36
36
  # Performs the actual deployment.
@@ -14,11 +14,11 @@ module Nanoc::Extra
14
14
  end
15
15
  end
16
16
 
17
- # @option [IO] :stdout ($stdout)
18
- # @option [IO] :stderr ($stderr)
19
- def initialize(params = {})
20
- @stdout = params.fetch(:stdout, $stdout)
21
- @stderr = params.fetch(:stderr, $stderr)
17
+ # @param [IO] stdout
18
+ # @param [IO] stderr
19
+ def initialize(stdout: $stdout, stderr: $stderr)
20
+ @stdout = stdout
21
+ @stderr = stderr
22
22
  end
23
23
 
24
24
  # @param [Array<String>] cmd
@@ -9,13 +9,15 @@ module Nanoc::Extra
9
9
 
10
10
  # @param [Nanoc::Int::Site] site The site for which a pruner is created
11
11
  #
12
- # @option params [Boolean] :dry_run (false) true if the files to be deleted
12
+ # @param [Boolean] dry_run true if the files to be deleted
13
13
  # should only be printed instead of actually deleted, false if the files
14
14
  # should actually be deleted.
15
- def initialize(site, params = {})
15
+ #
16
+ # @param [Enumerable<String>] exclude
17
+ def initialize(site, dry_run: false, exclude: [])
16
18
  @site = site
17
- @dry_run = params.fetch(:dry_run) { false }
18
- @exclude = params.fetch(:exclude) { [] }
19
+ @dry_run = dry_run
20
+ @exclude = exclude
19
21
  end
20
22
 
21
23
  # Prunes all output files not managed by Nanoc.
@@ -25,9 +27,8 @@ module Nanoc::Extra
25
27
  require 'find'
26
28
 
27
29
  # Get compiled files
28
- all_raw_paths = site.items.map do |item|
29
- item.reps.map(&:raw_path)
30
- end
30
+ # FIXME: requires #build_reps to have been called
31
+ all_raw_paths = site.compiler.reps.map(&:raw_path)
31
32
  compiled_files = all_raw_paths.flatten.compact.select { |f| File.file?(f) }
32
33
 
33
34
  # Get present files and dirs
@@ -35,30 +35,9 @@ module Nanoc::Filters
35
35
  # Filter
36
36
  case params[:type]
37
37
  when :css
38
- # FIXME: parse CSS the proper way using csspool or something
39
- content.gsub(/url\((['"]?)(\/(?:[^\/].*?)?)\1\)/) do
40
- 'url(' + $1 + relative_path_to($2) + $1 + ')'
41
- end
38
+ relativize_css(content)
42
39
  when :html, :xml, :xhtml
43
- selectors = params.fetch(:select) { SELECTORS }
44
- namespaces = params[:namespaces] || {}
45
-
46
- require 'nokogiri'
47
- case params[:type]
48
- when :html
49
- klass = ::Nokogiri::HTML
50
- when :xml
51
- klass = ::Nokogiri::XML
52
- when :xhtml
53
- klass = ::Nokogiri::XML
54
- # FIXME: cleanup because it is ugly
55
- # this cleans the XHTML namespace to process fragments and full
56
- # documents in the same way. At least, Nokogiri adds this namespace
57
- # if detects the `html` element.
58
- content = content.sub(%r{(<html[^>]+)xmlns="http://www.w3.org/1999/xhtml"}, '\1')
59
- end
60
-
61
- nokogiri_process(content, selectors, namespaces, klass, params[:type])
40
+ relativize_html_like(content, params)
62
41
  else
63
42
  raise RuntimeError.new(
64
43
  'The relativize_paths needs to know the type of content to ' \
@@ -69,6 +48,38 @@ module Nanoc::Filters
69
48
 
70
49
  protected
71
50
 
51
+ def relativize_css(content)
52
+ # FIXME: parse CSS the proper way using csspool or something
53
+ content.gsub(/url\((['"]?)(\/(?:[^\/].*?)?)\1\)/) do
54
+ quote = Regexp.last_match[1]
55
+ path = Regexp.last_match[2]
56
+ 'url(' + quote + relative_path_to(path) + quote + ')'
57
+ end
58
+ end
59
+
60
+ def relativize_html_like(content, params)
61
+ selectors = params.fetch(:select, SELECTORS)
62
+ namespaces = params.fetch(:namespaces, {})
63
+ type = params.fetch(:type)
64
+
65
+ require 'nokogiri'
66
+ case type
67
+ when :html
68
+ klass = ::Nokogiri::HTML
69
+ when :xml
70
+ klass = ::Nokogiri::XML
71
+ when :xhtml
72
+ klass = ::Nokogiri::XML
73
+ # FIXME: cleanup because it is ugly
74
+ # this cleans the XHTML namespace to process fragments and full
75
+ # documents in the same way. At least, Nokogiri adds this namespace
76
+ # if detects the `html` element.
77
+ content = content.sub(%r{(<html[^>]+)xmlns="http://www.w3.org/1999/xhtml"}, '\1')
78
+ end
79
+
80
+ nokogiri_process(content, selectors, namespaces, klass, type)
81
+ end
82
+
72
83
  def nokogiri_process(content, selectors, namespaces, klass, type)
73
84
  # Ensure that all prefixes are strings
74
85
  namespaces = namespaces.reduce({}) { |new, (prefix, uri)| new.merge(prefix.to_s => uri) }
@@ -77,14 +88,7 @@ module Nanoc::Filters
77
88
  selectors.map { |sel| "descendant-or-self::#{sel}" }.each do |selector|
78
89
  doc.xpath(selector, namespaces).each do |node|
79
90
  if node.name == 'comment'
80
- content = node.content.dup
81
- content = content.sub(%r{^(\s*\[.+?\]>\s*)(.+?)(\s*<!\[endif\])}m) do |_m|
82
- fragment = nokogiri_process($2, selectors, namespaces, klass, type)
83
- $1 + fragment + $3
84
- end
85
- comment = Nokogiri::XML::Comment.new(doc, content)
86
- # Works w/ Nokogiri 1.5.5 but fails w/ Nokogiri 1.5.2
87
- node.replace(comment)
91
+ nokogiri_process_comment(node, doc, selectors, namespaces, klass, type)
88
92
  elsif self.path_is_relativizable?(node.content)
89
93
  node.content = relative_path_to(node.content)
90
94
  end
@@ -93,8 +97,20 @@ module Nanoc::Filters
93
97
  doc.send("to_#{type}")
94
98
  end
95
99
 
100
+ def nokogiri_process_comment(node, doc, selectors, namespaces, klass, type)
101
+ content = node.content.dup.sub(%r{^(\s*\[.+?\]>\s*)(.+?)(\s*<!\[endif\])}m) do |_m|
102
+ beginning = Regexp.last_match[1]
103
+ body = Regexp.last_match[2]
104
+ ending = Regexp.last_match[3]
105
+
106
+ beginning + nokogiri_process(body, selectors, namespaces, klass, type) + ending
107
+ end
108
+
109
+ node.replace(Nokogiri::XML::Comment.new(doc, content))
110
+ end
111
+
96
112
  def path_is_relativizable?(s)
97
- s[0, 1] == '/'
113
+ s.start_with?('/')
98
114
  end
99
115
  end
100
116
  end