nanoc 3.3.7 → 3.4.0

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