nanoc 2.1.6 → 2.2

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