nanoc 2.1.6 → 2.2

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 (65) hide show
  1. data/ChangeLog +3 -221
  2. data/Rakefile +9 -51
  3. data/bin/nanoc +5 -2
  4. data/lib/nanoc.rb +9 -31
  5. data/lib/nanoc/base.rb +26 -0
  6. data/lib/nanoc/base/core_ext.rb +2 -0
  7. data/lib/nanoc/base/filter.rb +11 -41
  8. data/lib/nanoc/base/layout.rb +1 -5
  9. data/lib/nanoc/base/page_rep.rb +1 -1
  10. data/lib/nanoc/base/proxies.rb +5 -0
  11. data/lib/nanoc/base/site.rb +4 -2
  12. data/lib/nanoc/binary_filters.rb +1 -0
  13. data/lib/nanoc/cli.rb +9 -1
  14. data/lib/nanoc/cli/base.rb +41 -129
  15. data/lib/nanoc/cli/commands.rb +10 -0
  16. data/lib/nanoc/cli/commands/autocompile.rb +1 -1
  17. data/lib/nanoc/cli/commands/compile.rb +51 -13
  18. data/lib/nanoc/cli/commands/create_layout.rb +1 -1
  19. data/lib/nanoc/cli/commands/create_page.rb +1 -1
  20. data/lib/nanoc/cli/commands/create_site.rb +1 -1
  21. data/lib/nanoc/cli/commands/create_template.rb +1 -1
  22. data/lib/nanoc/cli/commands/help.rb +1 -1
  23. data/lib/nanoc/cli/commands/info.rb +1 -1
  24. data/lib/nanoc/cli/commands/switch.rb +1 -1
  25. data/lib/nanoc/cli/commands/update.rb +1 -1
  26. data/lib/nanoc/cli/logger.rb +13 -7
  27. data/lib/nanoc/data_sources.rb +2 -0
  28. data/lib/nanoc/data_sources/filesystem.rb +3 -38
  29. data/lib/nanoc/extra.rb +6 -0
  30. data/lib/nanoc/extra/core_ext.rb +2 -0
  31. data/lib/nanoc/extra/vcses.rb +5 -0
  32. data/lib/nanoc/filters.rb +14 -0
  33. data/lib/nanoc/filters/erb.rb +3 -2
  34. data/lib/nanoc/filters/haml.rb +1 -1
  35. data/lib/nanoc/filters/markaby.rb +0 -1
  36. data/lib/nanoc/filters/rainpress.rb +13 -0
  37. data/lib/nanoc/filters/relativize_paths.rb +25 -0
  38. data/lib/nanoc/filters/sass.rb +1 -0
  39. data/lib/nanoc/helpers.rb +9 -0
  40. data/lib/nanoc/helpers/blogging.rb +55 -12
  41. data/lib/nanoc/helpers/filtering.rb +54 -0
  42. data/lib/nanoc/helpers/link_to.rb +40 -0
  43. data/lib/nanoc/helpers/text.rb +38 -0
  44. data/lib/nanoc/helpers/xml_sitemap.rb +3 -2
  45. data/lib/nanoc/routers.rb +3 -0
  46. data/vendor/cri/ChangeLog +0 -0
  47. data/vendor/cri/LICENSE +19 -0
  48. data/vendor/cri/NEWS +0 -0
  49. data/vendor/cri/README +4 -0
  50. data/vendor/cri/Rakefile +25 -0
  51. data/vendor/cri/lib/cri.rb +12 -0
  52. data/vendor/cri/lib/cri/base.rb +153 -0
  53. data/{lib/nanoc/cli → vendor/cri/lib/cri}/command.rb +5 -6
  54. data/vendor/cri/lib/cri/core_ext.rb +8 -0
  55. data/vendor/cri/lib/cri/core_ext/string.rb +41 -0
  56. data/{lib/nanoc/cli → vendor/cri/lib/cri}/option_parser.rb +35 -17
  57. data/vendor/cri/test/test_base.rb +6 -0
  58. data/vendor/cri/test/test_command.rb +6 -0
  59. data/vendor/cri/test/test_core_ext.rb +21 -0
  60. data/vendor/cri/test/test_option_parser.rb +279 -0
  61. data/vendor/mime-types/lib/mime/types.rb +1558 -0
  62. metadata +45 -9
  63. data/lib/nanoc/base/enhancements.rb +0 -14
  64. data/lib/nanoc/cli/cli.rb +0 -16
  65. data/lib/nanoc/cli/ext.rb +0 -37
@@ -0,0 +1,38 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::Helpers::Text contains several useful text-related helper functions.
4
+ module Text
5
+
6
+ # Returns an excerpt for the given string. HTML tags are ignored, so if
7
+ # you don't want them to turn up, they should be stripped from the string
8
+ # before passing it to the excerpt function.
9
+ #
10
+ # +params+ is a hash where the following keys can be set:
11
+ #
12
+ # +length+:: The maximum number of characters this excerpt can contain,
13
+ # including the omission. Defaults to 25.
14
+ #
15
+ # +omission+:: The string to append to the excerpt when the excerpt is
16
+ # shorter than the original string. Defaults to '...' (but in
17
+ # HTML, you may want to use something more fancy, like
18
+ # '…').
19
+ def excerptize(string, params={})
20
+ # Initialize params
21
+ params[:length] ||= 25
22
+ params[:omission] ||= '...'
23
+
24
+ # Get excerpt
25
+ length = params[:length] - params[:omission].length
26
+ length = 0 if length < 0
27
+ (string.length > params[:length] ? string[0...length] + params[:omission] : string)
28
+ end
29
+
30
+ # Strips all HTML tags out of the given string.
31
+ def strip_html(string)
32
+ # FIXME will need something more sophisticated than this, because it sucks
33
+ string.gsub(/<[^>]*(>+|\s*\z)/m, '').strip
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -43,9 +43,10 @@ module Nanoc::Helpers
43
43
  xml.instruct!
44
44
  xml.urlset(:xmlns => 'http://www.google.com/schemas/sitemap/0.84') do
45
45
  # Add page
46
- @pages.reject { |p| p.is_hidden }.each do |page|
46
+ @pages.reject { |p| p.is_hidden || p.skip_output }.each do |page|
47
47
  xml.url do
48
- xml.loc @page.base_url + page.path
48
+ loc = (@site.config[:base_url] || @page.base_url) + page.path
49
+ xml.loc loc
49
50
  xml.lastmod page.mtime.to_iso8601_date unless page.mtime.nil?
50
51
  xml.changefreq page.changefreq unless page.changefreq.nil?
51
52
  xml.priority page.priority unless page.priority.nil?
@@ -0,0 +1,3 @@
1
+ require 'nanoc/routers/default'
2
+ require 'nanoc/routers/no_dirs'
3
+ require 'nanoc/routers/versioned'
File without changes
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Denis Defreyne and contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
File without changes
@@ -0,0 +1,4 @@
1
+ Cri
2
+ ===
3
+
4
+ Cri is a library for building easy-to-use commandline tools.
@@ -0,0 +1,25 @@
1
+ ##### Requirements
2
+
3
+ # Rake etc
4
+ require 'rake'
5
+ require 'minitest/unit'
6
+
7
+ # Cri itself
8
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/lib'))
9
+ require 'cri'
10
+
11
+ ##### Testing
12
+
13
+ desc 'Runs all tests'
14
+ task :test do
15
+ ENV['QUIET'] ||= 'true'
16
+
17
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/..'))
18
+
19
+ MiniTest::Unit.autorun
20
+
21
+ test_files = Dir['test/test_*.rb']
22
+ test_files.each { |f| require f }
23
+ end
24
+
25
+ task :default => :test
@@ -0,0 +1,12 @@
1
+ module Cri
2
+
3
+ # The current Cri version.
4
+ VERSION = '1.0'
5
+
6
+ end
7
+
8
+ # Load Cri
9
+ require 'cri/base'
10
+ require 'cri/command'
11
+ require 'cri/core_ext'
12
+ require 'cri/option_parser'
@@ -0,0 +1,153 @@
1
+ module Cri
2
+
3
+ # Cri::Base is the central class representing a commandline tool. It has a
4
+ # list of commands.
5
+ class Base
6
+
7
+ # The CLI's list of commands (should also contain the help command)
8
+ attr_reader :commands
9
+
10
+ # The CLI's help command (required)
11
+ attr_accessor :help_command
12
+
13
+ # Creates a new instance of the commandline tool.
14
+ def initialize(tool_name)
15
+ @tool_name = tool_name
16
+
17
+ @commands = []
18
+ end
19
+
20
+ # Parses the given commandline arguments and executes the requested
21
+ # command.
22
+ def run(args)
23
+ # Check arguments
24
+ if args.length == 0
25
+ @help_command.run([], [])
26
+ exit 1
27
+ end
28
+
29
+ # Partition options
30
+ opts_before_command = []
31
+ command_name = nil
32
+ opts_and_args_after_command = []
33
+ stage = 0
34
+ args.each do |arg|
35
+ # Update stage if necessary
36
+ stage = 1 if stage == 0 && !is_option?(arg)
37
+
38
+ # Add
39
+ opts_before_command << arg if stage == 0
40
+ command_name = arg if stage == 1
41
+ opts_and_args_after_command << arg if stage == 2
42
+
43
+ # Update stage if necessary
44
+ stage = 2 if stage == 1
45
+ end
46
+
47
+ # Handle options before command
48
+ begin
49
+ parsed_arguments = Cri::OptionParser.parse(opts_before_command, global_option_definitions)
50
+ rescue Cri::OptionParser::IllegalOptionError => e
51
+ $stderr.puts "illegal option -- #{e}"
52
+ exit 1
53
+ end
54
+ parsed_arguments[:options].keys.each do |option|
55
+ handle_option(option)
56
+ end
57
+
58
+ # Get command
59
+ if command_name.nil?
60
+ $stderr.puts "no command given"
61
+ exit 1
62
+ end
63
+ command = command_named(command_name)
64
+ if command.nil?
65
+ $stderr.puts "no such command: #{command_name}"
66
+ exit 1
67
+ end
68
+
69
+ # Parse arguments
70
+ option_definitions = command.option_definitions + global_option_definitions
71
+ begin
72
+ parsed_arguments = Cri::OptionParser.parse(opts_and_args_after_command, option_definitions)
73
+ rescue Cri::OptionParser::IllegalOptionError => e
74
+ $stderr.puts "illegal option -- #{e}"
75
+ exit 1
76
+ rescue Cri::OptionParser::OptionRequiresAnArgumentError => e
77
+ $stderr.puts "option requires an argument -- #{e}"
78
+ exit 1
79
+ end
80
+
81
+ # Handle global options
82
+ global_options = global_option_definitions.map { |o| o[:long] }
83
+ global_options.delete_if { |o| !parsed_arguments[:options].keys.include?(o.to_sym) }
84
+ global_options.each { |o| handle_option(o.to_sym) }
85
+
86
+ if parsed_arguments[:options].has_key?(:help)
87
+ # Show help for this command
88
+ show_help(command)
89
+ else
90
+ # Run command
91
+ command.run(parsed_arguments[:options], parsed_arguments[:arguments])
92
+ end
93
+ end
94
+
95
+ # Returns the command with the given name.
96
+ def command_named(name)
97
+ # Find by exact name or alias
98
+ command = @commands.find { |c| c.name == name or c.aliases.include?(name) }
99
+ return command unless command.nil?
100
+
101
+ # Find by approximation
102
+ commands = @commands.select { |c| c.name[0, name.length] == name }
103
+ if commands.length > 1
104
+ $stderr.puts "#{@tool_name}: '#{name}' is ambiguous:"
105
+ $stderr.puts " #{commands.map { |c| c.name }.join(' ') }"
106
+ exit 1
107
+ elsif commands.length == 0
108
+ $stderr.puts "#{@tool_name}: unknown command '#{name}'\n"
109
+ show_help
110
+ exit 1
111
+ else
112
+ return commands[0]
113
+ end
114
+ end
115
+
116
+ # Shows the help text for the given command, or shows the general help
117
+ # text if no command is given.
118
+ def show_help(command=nil)
119
+ if command.nil?
120
+ @help_command.run([], [])
121
+ else
122
+ @help_command.run([], [ command.name ])
123
+ end
124
+ end
125
+
126
+ # Returns the list of global option definitionss.
127
+ def global_option_definitions
128
+ []
129
+ end
130
+
131
+ # Adds the given command to the list of commands. Adding a command will
132
+ # also cause the command's +base+ to be set to this instance.
133
+ def add_command(command)
134
+ @commands << command
135
+ command.base = self
136
+ end
137
+
138
+ # Handles the given optio
139
+ def handle_option(option)
140
+ false
141
+ end
142
+
143
+ private
144
+
145
+ # Returns true if the given string is an option (i.e. -foo or --foo),
146
+ # false otherwise.
147
+ def is_option?(string)
148
+ string =~ /^-/
149
+ end
150
+
151
+ end
152
+
153
+ end
@@ -1,7 +1,7 @@
1
- module Nanoc::CLI
1
+ module Cri
2
2
 
3
- # Nanoc::CLI::Command represents a command that can be executed on the
4
- # commandline. It is an abstract superclass for all commands.
3
+ # Cri::Command represents a command that can be executed on the commandline.
4
+ # It is an abstract superclass for all commands.
5
5
  class Command
6
6
 
7
7
  attr_accessor :base
@@ -39,7 +39,7 @@ module Nanoc::CLI
39
39
  end
40
40
 
41
41
  # Returns an array containing this command's option definitions. See the
42
- # documentation for Nanoc::CLI::OptionParser for details on what option
42
+ # documentation for Cri::OptionParser for details on what option
43
43
  # definitions look like. Subclasses may implement this method if the
44
44
  # command has options.
45
45
  def option_definitions
@@ -51,8 +51,7 @@ module Nanoc::CLI
51
51
  #
52
52
  # +options+:: A hash containing the parsed commandline options. For
53
53
  # example, '--foo=bar' will be converted into { :foo => 'bar'
54
- # }. See the Nanoc::CLI::OptionParser documentation for
55
- # details.
54
+ # }. See the Cri::OptionParser documentation for details.
56
55
  #
57
56
  # +arguments+:: An array of strings representing the commandline arguments
58
57
  # given to this command.
@@ -0,0 +1,8 @@
1
+ module Cri::CoreExtensions
2
+ end
3
+
4
+ require 'cri/core_ext/string'
5
+
6
+ class String
7
+ include Cri::CoreExtensions::String
8
+ end
@@ -0,0 +1,41 @@
1
+ module Cri::CoreExtensions
2
+
3
+ module String
4
+
5
+ # Word-wraps and indents the string.
6
+ #
7
+ # +width+:: The maximal width of each line. This also includes indentation,
8
+ # i.e. the actual maximal width of the text is width-indentation.
9
+ #
10
+ # +indentation+:: The number of spaces to indent each wrapped line.
11
+ def wrap_and_indent(width, indentation)
12
+ # Split into paragraphs
13
+ paragraphs = self.split("\n").map { |p| p.strip }.reject { |p| p == '' }
14
+
15
+ # Wrap and indent each paragraph
16
+ paragraphs.map do |paragraph|
17
+ # Initialize
18
+ lines = []
19
+ line = ''
20
+
21
+ # Split into words
22
+ paragraph.split(/\s/).each do |word|
23
+ # Begin new line if it's too long
24
+ if (line + ' ' + word).length >= width
25
+ lines << line
26
+ line = ''
27
+ end
28
+
29
+ # Add word to line
30
+ line += (line == '' ? '' : ' ' ) + word
31
+ end
32
+ lines << line
33
+
34
+ # Join lines
35
+ lines.map { |l| ' '*indentation + l }.join("\n")
36
+ end.join("\n\n")
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -1,6 +1,6 @@
1
- module Nanoc::CLI
1
+ module Cri
2
2
 
3
- # Nanoc::CLI::OptionParser is used for parsing commandline options.
3
+ # Cri::OptionParser is used for parsing commandline options.
4
4
  class OptionParser
5
5
 
6
6
  # Error that will be raised when an unknown option is encountered.
@@ -25,8 +25,8 @@ module Nanoc::CLI
25
25
  # :long:: The long name of the option, e.g. +all+. Do not include the '--'
26
26
  # prefix.
27
27
  #
28
- # :argument:: Whether this option's argument is required (:required) or
29
- # forbidden (:forbidden).
28
+ # :argument:: Whether this option's argument is required (:required),
29
+ # optional (:optional) or forbidden (:forbidden).
30
30
  #
31
31
  # A sample array of definition hashes could look like this:
32
32
  #
@@ -53,7 +53,7 @@ module Nanoc::CLI
53
53
  # For example, the following commandline options (which should not be
54
54
  # passed as a string, but as an array of strings):
55
55
  #
56
- # foo bar -xyz -a hiss --level 50 --father=ani -n luke squeak
56
+ # foo -xyz -a hiss -s -m please --level 50 --father=ani -n luke squeak
57
57
  #
58
58
  # with the following option definitions:
59
59
  #
@@ -62,6 +62,8 @@ module Nanoc::CLI
62
62
  # { :short => 'y', :long => 'yyy', :argument => :forbidden },
63
63
  # { :short => 'z', :long => 'zzz', :argument => :forbidden },
64
64
  # { :short => 'a', :long => 'all', :argument => :forbidden },
65
+ # { :short => 's', :long => 'stuff', :argument => :optional },
66
+ # { :short => 'm', :long => 'more', :argument => :optional },
65
67
  # { :short => 'l', :long => 'level', :argument => :required },
66
68
  # { :short => 'f', :long => 'father', :argument => :required },
67
69
  # { :short => 'n', :long => 'name', :argument => :required }
@@ -70,12 +72,14 @@ module Nanoc::CLI
70
72
  # will be translated into:
71
73
  #
72
74
  # {
73
- # :arguments => [ 'foo', 'bar', 'hiss', 'squeak' ],
75
+ # :arguments => [ 'foo', 'hiss', 'squeak' ],
74
76
  # :options => {
75
- # :xxx => nil,
76
- # :yyy => nil,
77
- # :zzz => nil,
78
- # :all => nil,
77
+ # :xxx => true,
78
+ # :yyy => true,
79
+ # :zzz => true,
80
+ # :all => true,
81
+ # :stuff => true,
82
+ # :more => 'please',
79
83
  # :level => '50',
80
84
  # :father => 'ani',
81
85
  # :name => 'luke'
@@ -115,18 +119,25 @@ module Nanoc::CLI
115
119
  definition = definitions.find { |d| d[:long] == option_key }
116
120
  raise IllegalOptionError.new(option_key) if definition.nil?
117
121
 
118
- if definition[:argument] == :required
122
+ if [ :required, :optional ].include?(definition[:argument])
119
123
  # Get option value if necessary
120
124
  if option_value.nil?
121
125
  option_value = unprocessed_arguments_and_options.shift
122
- raise OptionRequiresAnArgumentError.new(option_key) if option_value.nil?
126
+ if option_value.nil? || option_value =~ /^-/
127
+ if definition[:argument] == :required
128
+ raise OptionRequiresAnArgumentError.new(option_key)
129
+ else
130
+ unprocessed_arguments_and_options.unshift(option_value)
131
+ option_value = true
132
+ end
133
+ end
123
134
  end
124
135
 
125
136
  # Store option
126
137
  options[definition[:long].to_sym] = option_value
127
138
  else
128
139
  # Store option
129
- options[definition[:long].to_sym] = nil
140
+ options[definition[:long].to_sym] = true
130
141
  end
131
142
  # Handle -xyz options
132
143
  elsif e =~ /^-./ and !no_more_options
@@ -141,17 +152,24 @@ module Nanoc::CLI
141
152
 
142
153
  if option_keys.length > 1 and definition[:argument] == :required
143
154
  # This is a combined option and it requires an argument, so complain
144
- raise OptionRequiresAnArgumentError.new(option_key) if option_value.nil?
145
- elsif definition[:argument] == :required
155
+ raise OptionRequiresAnArgumentError.new(option_key)
156
+ elsif [ :required, :optional ].include?(definition[:argument])
146
157
  # Get option value
147
158
  option_value = unprocessed_arguments_and_options.shift
148
- raise OptionRequiresAnArgumentError.new(option_key) if option_value.nil?
159
+ if option_value.nil? || option_value =~ /^-/
160
+ if definition[:argument] == :required
161
+ raise OptionRequiresAnArgumentError.new(option_key)
162
+ else
163
+ unprocessed_arguments_and_options.unshift(option_value)
164
+ option_value = true
165
+ end
166
+ end
149
167
 
150
168
  # Store option
151
169
  options[definition[:long].to_sym] = option_value
152
170
  else
153
171
  # Store option
154
- options[definition[:long].to_sym] = nil
172
+ options[definition[:long].to_sym] = true
155
173
  end
156
174
  end
157
175
  # Handle normal arguments