nanoc 3.3.7 → 3.4.0

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 (53) hide show
  1. data/Gemfile.lock +133 -0
  2. data/NEWS.md +15 -0
  3. data/lib/nanoc.rb +2 -2
  4. data/lib/nanoc/base/compilation/compiler.rb +1 -1
  5. data/lib/nanoc/base/compilation/item_rep_proxy.rb +3 -3
  6. data/lib/nanoc/base/core_ext/string.rb +0 -18
  7. data/lib/nanoc/base/errors.rb +24 -19
  8. data/lib/nanoc/base/plugin_registry.rb +1 -1
  9. data/lib/nanoc/base/result_data/item_rep.rb +1 -2
  10. data/lib/nanoc/base/source_data/site.rb +1 -1
  11. data/lib/nanoc/cli.rb +46 -4
  12. data/lib/nanoc/cli/ansi_string_colorizer.rb +30 -0
  13. data/lib/nanoc/cli/cleaning_stream.rb +91 -0
  14. data/lib/nanoc/cli/command_runner.rb +3 -11
  15. data/lib/nanoc/cli/commands/compile.rb +2 -2
  16. data/lib/nanoc/cli/commands/{create_item.rb → create-item.rb} +6 -7
  17. data/lib/nanoc/cli/commands/{create_layout.rb → create-layout.rb} +9 -10
  18. data/lib/nanoc/cli/commands/{create_site.rb → create-site.rb} +13 -14
  19. data/lib/nanoc/cli/commands/deploy.rb +4 -12
  20. data/lib/nanoc/cli/commands/nanoc.rb +4 -2
  21. data/lib/nanoc/cli/commands/prune.rb +1 -1
  22. data/lib/nanoc/cli/commands/{debug.rb → show-data.rb} +6 -5
  23. data/lib/nanoc/cli/commands/{info.rb → show-plugins.rb} +6 -6
  24. data/lib/nanoc/cli/commands/show-rules.rb +69 -0
  25. data/lib/nanoc/cli/commands/update.rb +1 -2
  26. data/lib/nanoc/cli/commands/validate-css.rb +24 -0
  27. data/lib/nanoc/cli/commands/validate-html.rb +24 -0
  28. data/lib/nanoc/cli/commands/validate-links.rb +35 -0
  29. data/lib/nanoc/cli/commands/watch.rb +3 -3
  30. data/lib/nanoc/cli/error_handler.rb +142 -26
  31. data/lib/nanoc/cli/logger.rb +4 -21
  32. data/lib/nanoc/cli/stream_cleaners.rb +14 -0
  33. data/lib/nanoc/cli/stream_cleaners/abstract.rb +23 -0
  34. data/lib/nanoc/cli/stream_cleaners/ansi_colors.rb +15 -0
  35. data/lib/nanoc/cli/stream_cleaners/utf8.rb +16 -0
  36. data/lib/nanoc/extra/deployers/rsync.rb +2 -7
  37. data/lib/nanoc/extra/pruner.rb +3 -3
  38. data/lib/nanoc/extra/validators/links.rb +14 -3
  39. data/lib/nanoc/filters.rb +4 -0
  40. data/lib/nanoc/filters/handlebars.rb +30 -0
  41. data/lib/nanoc/filters/mustache.rb +2 -2
  42. data/lib/nanoc/filters/pandoc.rb +20 -0
  43. data/lib/nanoc/helpers/filtering.rb +1 -1
  44. data/lib/nanoc/tasks/validate.rake +10 -68
  45. data/nanoc.gemspec +0 -16
  46. data/test/cli/commands/test_create_site.rb +1 -1
  47. data/test/cli/commands/test_deploy.rb +45 -0
  48. data/test/cli/test_cli.rb +1 -1
  49. data/test/extra/validators/test_links.rb +15 -5
  50. data/test/filters/test_handlebars.rb +42 -0
  51. data/test/filters/test_mustache.rb +19 -0
  52. data/test/filters/test_pandoc.rb +18 -0
  53. metadata +23 -33
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::CLI
4
+
5
+ # A simple ANSI colorizer for strings. When given a string and a list of
6
+ # attributes, it returns a colorized string.
7
+ module ANSIStringColorizer
8
+
9
+ # TODO complete mapping
10
+ MAPPING = {
11
+ :bold => "\e[1m",
12
+ :red => "\e[31m",
13
+ :green => "\e[32m",
14
+ :yellow => "\e[33m",
15
+ :blue => "\e[34m"
16
+ }
17
+
18
+ # @param [String] s The string to colorize
19
+ #
20
+ # @param [Array] as An array of attributes from `MAPPING` to colorize the
21
+ # string with
22
+ #
23
+ # @return [String] A string colorized using the given attributes
24
+ def self.c(s, *as)
25
+ as.map { |a| MAPPING[a] }.join('') + s + "\e[0m"
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::CLI
4
+
5
+ # An output stream that passes output through stream cleaners. This can be
6
+ # used to strip ANSI color sequences, for instance.
7
+ class CleaningStream
8
+
9
+ # @param [IO, StringIO] stream The stream to wrap
10
+ def initialize(stream)
11
+ @stream = stream
12
+ @stream_cleaners = []
13
+ end
14
+
15
+ # Adds a stream cleaner for the given class to this cleaning stream. If the
16
+ # cleaning stream already has the given stream cleaner, nothing happens.
17
+ #
18
+ # @param [Nanoc::CLI::StreamCleaners::Abstract] klass The class of the
19
+ # stream cleaner to add
20
+ #
21
+ # @return [void]
22
+ def add_stream_cleaner(klass)
23
+ unless @stream_cleaners.map { |c| c.class }.include?(klass)
24
+ @stream_cleaners << klass.new
25
+ end
26
+ end
27
+
28
+ # Removes the stream cleaner for the given class from this cleaning stream.
29
+ # If the cleaning stream does not have the given stream cleaner, nothing
30
+ # happens.
31
+ #
32
+ # @param [Nanoc::CLI::StreamCleaners::Abstract] klass The class of the
33
+ # stream cleaner to add
34
+ #
35
+ # @return [void]
36
+ def remove_stream_cleaner(klass)
37
+ @stream_cleaners.delete_if { |c| c.class == klass }
38
+ end
39
+
40
+ # @group IO proxy methods
41
+
42
+ # @see IO#write
43
+ def write(s)
44
+ @stream.write(self.clean(s))
45
+ end
46
+
47
+ # @see IO#<<
48
+ def <<(s)
49
+ @stream.<<(self.clean(s))
50
+ end
51
+
52
+ # @see IO#tty?
53
+ def tty?
54
+ @stream.tty?
55
+ end
56
+
57
+ # @see IO#flush
58
+ def flush
59
+ @stream.flush
60
+ end
61
+
62
+ # @see IO#tell
63
+ def tell
64
+ @stream.tell
65
+ end
66
+
67
+ # @see IO#print
68
+ def print(s)
69
+ @stream.print(self.clean(s))
70
+ end
71
+
72
+ # @see IO#puts
73
+ def puts(*s)
74
+ @stream.puts(*s.map { |ss| self.clean(ss) })
75
+ end
76
+
77
+ # @see StringIO#string
78
+ def string
79
+ @stream.string
80
+ end
81
+
82
+ protected
83
+
84
+ def clean(s)
85
+ @stream_cleaners.inject(s) { |m,c| c.clean(m) }
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
@@ -23,12 +23,7 @@ module Nanoc::CLI
23
23
  # Load site if possible
24
24
  @site ||= nil
25
25
  if File.file?('config.yaml') && @site.nil?
26
- begin
27
- @site = Nanoc::Site.new('.')
28
- rescue Nanoc::Errors::UnknownDataSource => e
29
- $stderr.puts "Unknown data source: #{e}"
30
- exit 1
31
- end
26
+ @site = Nanoc::Site.new('.')
32
27
  end
33
28
 
34
29
  @site
@@ -57,9 +52,7 @@ module Nanoc::CLI
57
52
  # @return [void]
58
53
  def require_site
59
54
  if site.nil?
60
- $stderr.puts 'The current working directory does not seem to be a ' +
61
- 'valid/complete nanoc site directory; aborting.'
62
- exit 1
55
+ raise ::Nanoc::Errors::GenericTrivial, "The current working directory does not seem to be a nanoc site."
63
56
  end
64
57
  end
65
58
 
@@ -77,8 +70,7 @@ module Nanoc::CLI
77
70
  # Find VCS
78
71
  vcs_class = Nanoc::Extra::VCS.named(vcs_name.to_sym)
79
72
  if vcs_class.nil?
80
- $stderr.puts "A VCS named #{vcs_name} was not found; aborting."
81
- exit 1
73
+ raise Nanoc::Errors::GenericTrivial, "A VCS named #{vcs_name} was not found"
82
74
  end
83
75
 
84
76
  site.data_sources.each do |data_source|
@@ -37,7 +37,7 @@ module Nanoc::CLI::Commands
37
37
  # Warn if trying to compile a single item
38
38
  if arguments.size == 1
39
39
  $stderr.puts '-' * 80
40
- $stderr.puts 'Note: As of nanoc 3.2, it is no longer possible to compile a single item. When invoking the “compile” command, all items in the site will be compiled.'.make_compatible_with_env
40
+ $stderr.puts 'Note: As of nanoc 3.2, it is no longer possible to compile a single item. When invoking the “compile” command, all items in the site will be compiled.'
41
41
  $stderr.puts '-' * 80
42
42
  end
43
43
 
@@ -221,7 +221,7 @@ module Nanoc::CLI::Commands
221
221
  delay = 1.0
222
222
  step = 0
223
223
 
224
- text = "Running #{filter_name} filter… ".make_compatible_with_env
224
+ text = "Running #{filter_name} filter… "
225
225
 
226
226
  while !Thread.current[:stopped]
227
227
  sleep 0.1
@@ -1,8 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- usage 'create_item [options] identifier'
3
+ usage 'create-item [options] identifier'
4
+ aliases :create_item, :ci
4
5
  summary 'create an item'
5
- aliases :ci
6
6
  description <<-EOS
7
7
  Create a new item in the current site. The first data source in the site
8
8
  configuration will be used.
@@ -17,8 +17,7 @@ module Nanoc::CLI::Commands
17
17
  def run
18
18
  # Check arguments
19
19
  if arguments.length != 1
20
- $stderr.puts "usage: #{command.usage}"
21
- exit 1
20
+ raise Nanoc::Errors::GenericTrivial, "usage: #{command.usage}"
22
21
  end
23
22
 
24
23
  # Extract arguments and options
@@ -32,9 +31,9 @@ module Nanoc::CLI::Commands
32
31
 
33
32
  # Check whether item is unique
34
33
  if !self.site.items.find { |i| i.identifier == identifier }.nil?
35
- $stderr.puts "An item already exists at #{identifier}. Please " +
36
- "pick a unique name for the item you are creating."
37
- exit 1
34
+ raise Nanoc::Errors::GenericTrivial,
35
+ "An item already exists at #{identifier}. Please " +
36
+ "pick a unique name for the item you are creating."
38
37
  end
39
38
 
40
39
  # Setup notifications
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
- usage 'create_layout [options] identifier'
4
- aliases 'cl'
3
+ usage 'create-layout [options] identifier'
4
+ aliases :create_layout, :cl
5
5
  summary 'create a layout'
6
6
  description <<-EOS
7
7
  Create a new layout in the current site. The first data source in the site
@@ -15,8 +15,7 @@ module Nanoc::CLI::Commands
15
15
  def run
16
16
  # Check arguments
17
17
  if arguments.length != 1
18
- $stderr.puts "usage: #{command.usage}"
19
- exit 1
18
+ raise Nanoc::Errors::GenericTrivial, "usage: #{command.usage}"
20
19
  end
21
20
 
22
21
  # Extract arguments
@@ -30,16 +29,16 @@ module Nanoc::CLI::Commands
30
29
 
31
30
  # Check whether layout is unique
32
31
  if !self.site.layouts.find { |l| l.identifier == identifier }.nil?
33
- $stderr.puts "A layout already exists at #{identifier}. Please " +
34
- "pick a unique name for the layout you are creating."
35
- exit 1
32
+ raise Nanoc::Errors::GenericTrivial,
33
+ "A layout already exists at #{identifier}. Please " +
34
+ "pick a unique name for the layout you are creating."
36
35
  end
37
36
 
38
37
  # Check whether layout is not at /
39
38
  if identifier == '/'
40
- $stderr.puts "There cannot be a layout with the identifier '/'; " +
41
- "please pick a different identifier for this layout."
42
- exit 1
39
+ raise Nanoc::Errors::GenericTrivial,
40
+ "There cannot be a layout with the identifier '/'; " +
41
+ "please pick a different identifier for this layout."
43
42
  end
44
43
 
45
44
  # Setup notifications
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
- usage 'create_site [options] path'
4
- aliases 'cs'
3
+ usage 'create-site [options] path'
4
+ aliases :create_site, :cs
5
5
  summary 'create a site'
6
6
  description <<-EOS
7
7
  Create a new site at the given path. The site will use the filesystem_unified data source by default, but this can be changed using the --datasource commandline option.
@@ -274,7 +274,9 @@ EOS
274
274
  <meta charset="utf-8">
275
275
  <title>A Brand New nanoc Site - <%= @item[:title] %></title>
276
276
  <link rel="stylesheet" type="text/css" href="/style.css" media="screen">
277
- <meta name="generator" content="nanoc #{Nanoc::VERSION}">
277
+
278
+ <!-- you don't need to keep this, but it's cool for stats! -->
279
+ <meta name="generator" content="nanoc <%= Nanoc::VERSION %>">
278
280
  </head>
279
281
  <body>
280
282
  <div id="main">
@@ -300,8 +302,7 @@ EOS
300
302
  def run
301
303
  # Check arguments
302
304
  if arguments.length != 1
303
- $stderr.puts "usage: #{command.usage}"
304
- exit 1
305
+ raise Nanoc::Errors::GenericTrivial, "usage: #{command.usage}"
305
306
  end
306
307
 
307
308
  # Extract arguments and options
@@ -310,14 +311,12 @@ EOS
310
311
 
311
312
  # Check whether site exists
312
313
  if File.exist?(path)
313
- $stderr.puts "A site at '#{path}' already exists."
314
- exit 1
314
+ raise Nanoc::Errors::GenericTrivial, "A site at '#{path}' already exists."
315
315
  end
316
316
 
317
317
  # Check whether data source exists
318
318
  if Nanoc::DataSource.named(data_source).nil?
319
- $stderr.puts "Unrecognised data source: #{data_source}"
320
- exit 1
319
+ raise Nanoc::Errors::GenericTrivial, "Unrecognised data source: #{data_source}"
321
320
  end
322
321
 
323
322
  # Setup notifications
@@ -345,12 +344,12 @@ EOS
345
344
  FileUtils.mkdir_p('output')
346
345
 
347
346
  # Create config
348
- File.open('config.yaml', 'w') { |io| io.write(DEFAULT_CONFIG.make_compatible_with_env) }
347
+ File.open('config.yaml', 'w') { |io| io.write(DEFAULT_CONFIG) }
349
348
  Nanoc::NotificationCenter.post(:file_created, 'config.yaml')
350
349
 
351
350
  # Create rules
352
351
  File.open('Rules', 'w') do |io|
353
- io.write DEFAULT_RULES.make_compatible_with_env
352
+ io.write DEFAULT_RULES
354
353
  end
355
354
  Nanoc::NotificationCenter.post(:file_created, 'Rules')
356
355
  end
@@ -376,14 +375,14 @@ EOS
376
375
 
377
376
  # Create home page
378
377
  data_source.create_item(
379
- DEFAULT_ITEM.make_compatible_with_env,
378
+ DEFAULT_ITEM,
380
379
  { :title => "Home" },
381
380
  '/'
382
381
  )
383
382
 
384
383
  # Create stylesheet
385
384
  data_source.create_item(
386
- DEFAULT_STYLESHEET.make_compatible_with_env,
385
+ DEFAULT_STYLESHEET,
387
386
  {},
388
387
  '/stylesheet/',
389
388
  :extension => '.css'
@@ -391,7 +390,7 @@ EOS
391
390
 
392
391
  # Create layout
393
392
  data_source.create_layout(
394
- DEFAULT_LAYOUT.make_compatible_with_env,
393
+ DEFAULT_LAYOUT,
395
394
  {},
396
395
  '/default/'
397
396
  )
@@ -28,8 +28,7 @@ module Nanoc::CLI::Commands
28
28
 
29
29
  # Get config
30
30
  deploy_configs = site.config.fetch(:deploy) do
31
- $stderr.puts "The site configuration has no deploy configuration."
32
- exit 1
31
+ raise Nanoc::Errors::GenericTrivial, "The site configuration has no deploy configuration."
33
32
  end
34
33
 
35
34
  # List
@@ -42,14 +41,9 @@ module Nanoc::CLI::Commands
42
41
  end
43
42
 
44
43
  # Get target
45
- target = options.fetch(:target) do
46
- $stderr.puts "The deploy command requires a --target option."
47
- exit 1
48
- end
49
- target = target.to_sym
44
+ target = options.fetch(:target, :default).to_sym
50
45
  config = deploy_configs.fetch(target) do
51
- $stderr.puts "The site configuration has no deploy configuration for #{target}."
52
- exit 1
46
+ raise Nanoc::Errors::GenericTrivial, "The site configuration has no deploy configuration for #{target}."
53
47
  end
54
48
 
55
49
  # Get deployer
@@ -60,9 +54,7 @@ module Nanoc::CLI::Commands
60
54
  end
61
55
  deployer_class = Nanoc::Extra::Deployer.named(name)
62
56
  if deployer_class.nil?
63
- $stderr.puts "The specified deploy target has an unrecognised kind (#{name})."
64
- $stderr.puts "(expected one of #{names.join(', ')})"
65
- exit 1
57
+ raise Nanoc::Errors::GenericTrivial, "The specified deploy target has an unrecognised kind “#{name}” (expected one of #{names.join(', ')})."
66
58
  end
67
59
 
68
60
  # Run
@@ -4,7 +4,8 @@ usage 'nanoc command [options] [arguments]'
4
4
  summary 'nanoc, a static site compiler written in Ruby'
5
5
 
6
6
  opt :l, :color, 'enable color' do
7
- Nanoc::CLI::Logger.instance.color = true
7
+ $stdout.remove_stream_cleaner(Nanoc::CLI::StreamCleaners::ANSIColors)
8
+ $stderr.remove_stream_cleaner(Nanoc::CLI::StreamCleaners::ANSIColors)
8
9
  end
9
10
 
10
11
  opt :d, :debug, 'enable debugging' do
@@ -17,7 +18,8 @@ opt :h, :help, 'show the help message and quit' do |value, cmd|
17
18
  end
18
19
 
19
20
  opt :C, :'no-color', 'disable color' do
20
- Nanoc::CLI::Logger.instance.color = false
21
+ $stdout.add_stream_cleaner(Nanoc::CLI::StreamCleaners::ANSIColors)
22
+ $stderr.add_stream_cleaner(Nanoc::CLI::StreamCleaners::ANSIColors)
21
23
  end
22
24
 
23
25
  opt :V, :verbose, 'make nanoc output more detailed' do
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  usage 'prune'
4
- summary 'removes files not managed by nanoc from the output directory'
4
+ summary 'remove files not managed by nanoc from the output directory'
5
5
  description <<-EOS
6
6
  Find all files in the output directory that do not correspond to an item
7
7
  managed by nanoc and remove them. Since this is a hazardous operation, an
@@ -1,15 +1,16 @@
1
1
  # encoding: utf-8
2
2
 
3
- usage 'debug'
4
- summary 'show debug information for this site'
3
+ usage 'show-data'
4
+ aliases :debug
5
+ summary 'show data in this site'
5
6
  description <<-EOS
6
7
  Show information about all items, item representations and layouts in the
7
- current site.
8
+ current site, along with dependency information.
8
9
  EOS
9
10
 
10
11
  module Nanoc::CLI::Commands
11
12
 
12
- class Debug < ::Nanoc::CLI::CommandRunner
13
+ class ShowData < ::Nanoc::CLI::CommandRunner
13
14
 
14
15
  def run
15
16
  # Make sure we are in a nanoc site directory
@@ -114,4 +115,4 @@ module Nanoc::CLI::Commands
114
115
 
115
116
  end
116
117
 
117
- runner Nanoc::CLI::Commands::Debug
118
+ runner Nanoc::CLI::Commands::ShowData
@@ -1,7 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- summary 'show info about available plugins'
4
- usage 'info [options]'
3
+ summary 'show all available plugins'
4
+ aliases :info
5
+ usage 'show-plugins [options]'
5
6
  description <<-EOS
6
7
  Show a list of available plugins, including filters, data sources and VCSes.
7
8
  If the current directory contains a nanoc web site, the plugins defined in this site will be shown as well.
@@ -9,13 +10,12 @@ EOS
9
10
 
10
11
  module Nanoc::CLI::Commands
11
12
 
12
- class Info < ::Nanoc::CLI::CommandRunner
13
+ class ShowPlugins < ::Nanoc::CLI::CommandRunner
13
14
 
14
15
  def run
15
16
  # Check arguments
16
17
  if arguments.size != 0
17
- $stderr.puts "usage: #{command.usage}"
18
- exit 1
18
+ raise Nanoc::Errors::GenericTrivial, "usage: #{command.usage}"
19
19
  end
20
20
 
21
21
  # Get list of plugins (before and after)
@@ -95,4 +95,4 @@ module Nanoc::CLI::Commands
95
95
 
96
96
  end
97
97
 
98
- runner Nanoc::CLI::Commands::Info
98
+ runner Nanoc::CLI::Commands::ShowPlugins