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
@@ -7,21 +7,27 @@ module Nanoc::CLI
7
7
  class Logger
8
8
 
9
9
  ACTION_COLORS = {
10
- :create => "\e[1m" + "\e[32m", # bold + green
11
- :update => "\e[1m" + "\e[33m", # bold + yellow
12
- :identical => "\e[1m", # bold
13
- :skip => "\e[1m" # bold
10
+ :create => "\e[1m" + "\e[32m", # bold + green
11
+ :update => "\e[1m" + "\e[33m", # bold + yellow
12
+ :identical => "\e[1m", # bold
13
+ :skip => "\e[1m", # bold
14
+ :'not written' => "\e[1m" # bold
14
15
  }
15
16
 
16
17
  include Singleton
17
18
 
18
- # The log leve, which can be :high, :low or :off (which will log all
19
+ # The log level, which can be :high, :low or :off (which will log all
19
20
  # messages, only high-priority messages, or no messages at all,
20
21
  # respectively).
21
22
  attr_accessor :level
22
23
 
24
+ # Whether to use color in log messages or not
25
+ attr_accessor :color
26
+ alias_method :color?, :color
27
+
23
28
  def initialize # :nodoc:
24
29
  @level = :high
30
+ @color = true
25
31
  end
26
32
 
27
33
  # Logs a file-related action.
@@ -36,9 +42,9 @@ module Nanoc::CLI
36
42
  log(
37
43
  level,
38
44
  '%s%12s%s %s%s' % [
39
- ACTION_COLORS[action.to_sym],
45
+ color? ? ACTION_COLORS[action.to_sym] : '',
40
46
  action,
41
- "\e[0m",
47
+ color? ? "\e[0m" : '',
42
48
  duration.nil? ? '' : "[%2.2fs] " % [ duration ],
43
49
  path
44
50
  ]
@@ -0,0 +1,2 @@
1
+ require 'nanoc/data_sources/filesystem'
2
+ require 'nanoc/data_sources/filesystem_combined'
@@ -120,7 +120,6 @@ module Nanoc::DataSources
120
120
  def update # :nodoc:
121
121
  update_page_defaults
122
122
  update_pages
123
- update_layouts
124
123
  update_templates
125
124
  end
126
125
 
@@ -368,8 +367,9 @@ module Nanoc::DataSources
368
367
  if is_old_school
369
368
  # Warn about deprecation
370
369
  warn(
371
- 'nanoc 2.1 changes the way layouts are stored. Future versions will not support these outdated sites. To update your site, issue \'nanoc update\'.',
372
- 'DEPRECATION WARNING'
370
+ 'DEPRECATION WARNING: nanoc 2.1 changes the way layouts are ' +
371
+ 'stored. Future versions will not support these outdated sites. ' +
372
+ 'To update your site, issue \'nanoc update\'.'
373
373
  )
374
374
 
375
375
  Dir[File.join('layouts', '*')].reject { |f| f =~ /~$/ }.map do |filename|
@@ -679,41 +679,6 @@ module Nanoc::DataSources
679
679
  end
680
680
  end
681
681
 
682
- # Updates outdated layouts.
683
- def update_layouts
684
- # layouts/abc.ext -> layouts/abc/abc.{html,yaml}
685
- Dir[File.join('layouts', '*')].select { |f| File.file?(f) }.each do |filename|
686
- # Get filter class
687
- filter_class = Nanoc::Filter.with_extension(File.extname(filename))
688
-
689
- # Get data
690
- content = File.read(filename)
691
- attributes = { :filter => filter_class.identifier.to_s }
692
- path = File.basename(filename, File.extname(filename))
693
-
694
- # Get layout
695
- tmp_layout = Nanoc::Layout.new(content, attributes, path)
696
-
697
- # Get filenames
698
- last_component = tmp_layout.path.split('/')[-1]
699
- dir_path = 'layouts' + tmp_layout.path
700
- meta_filename = dir_path + last_component + '.yaml'
701
- content_filename = dir_path + last_component + File.extname(filename)
702
-
703
- # Create new files
704
- FileUtils.mkdir_p(dir_path)
705
- File.open(meta_filename, 'w') { |io| io.write(tmp_layout.attributes.to_split_yaml) }
706
- File.open(content_filename, 'w') { |io| io.write(tmp_layout.content) }
707
-
708
- # Add
709
- vcs.add(meta_filename)
710
- vcs.add(content_filename)
711
-
712
- # Delete old files
713
- vcs.remove(filename)
714
- end
715
- end
716
-
717
682
  # Updates outdated templates (both content and meta file names).
718
683
  def update_templates
719
684
  # Update content files
@@ -0,0 +1,6 @@
1
+ require 'nanoc/extra/auto_compiler'
2
+ require 'nanoc/extra/context'
3
+ require 'nanoc/extra/core_ext'
4
+ require 'nanoc/extra/file_proxy'
5
+ require 'nanoc/extra/vcs'
6
+ require 'nanoc/extra/vcses'
@@ -0,0 +1,2 @@
1
+ require 'nanoc/extra/core_ext/hash'
2
+ require 'nanoc/extra/core_ext/time'
@@ -0,0 +1,5 @@
1
+ require 'nanoc/extra/vcses/bazaar'
2
+ require 'nanoc/extra/vcses/dummy'
3
+ require 'nanoc/extra/vcses/git'
4
+ require 'nanoc/extra/vcses/mercurial'
5
+ require 'nanoc/extra/vcses/subversion'
@@ -0,0 +1,14 @@
1
+ require 'nanoc/filters/bluecloth'
2
+ require 'nanoc/filters/erb'
3
+ require 'nanoc/filters/erubis'
4
+ require 'nanoc/filters/haml'
5
+ require 'nanoc/filters/markaby'
6
+ require 'nanoc/filters/maruku'
7
+ require 'nanoc/filters/old'
8
+ require 'nanoc/filters/rainpress'
9
+ require 'nanoc/filters/rdiscount'
10
+ require 'nanoc/filters/rdoc'
11
+ require 'nanoc/filters/redcloth'
12
+ require 'nanoc/filters/relativize_paths'
13
+ require 'nanoc/filters/rubypants'
14
+ require 'nanoc/filters/sass'
@@ -2,7 +2,6 @@ module Nanoc::Filters
2
2
  class ERB < Nanoc::Filter
3
3
 
4
4
  identifiers :erb
5
- extensions '.erb', '.rhtml'
6
5
 
7
6
  def run(content)
8
7
  require 'erb'
@@ -11,7 +10,9 @@ module Nanoc::Filters
11
10
  context = ::Nanoc::Extra::Context.new(assigns)
12
11
 
13
12
  # Get result
14
- ::ERB.new(content).result(context.get_binding)
13
+ erb = ::ERB.new(content)
14
+ erb.filename = filename
15
+ erb.result(context.get_binding)
15
16
  end
16
17
 
17
18
  end
@@ -2,13 +2,13 @@ module Nanoc::Filters
2
2
  class Haml < Nanoc::Filter
3
3
 
4
4
  identifiers :haml
5
- extensions '.haml'
6
5
 
7
6
  def run(content)
8
7
  require 'haml'
9
8
 
10
9
  # Get options
11
10
  options = @obj_rep.attribute_named(:haml_options) || {}
11
+ options[:filename] = filename
12
12
 
13
13
  # Create context
14
14
  context = ::Nanoc::Extra::Context.new(assigns)
@@ -2,7 +2,6 @@ module Nanoc::Filters
2
2
  class Markaby < Nanoc::Filter
3
3
 
4
4
  identifiers :markaby
5
- extensions '.mab'
6
5
 
7
6
  def run(content)
8
7
  require 'markaby'
@@ -0,0 +1,13 @@
1
+ module Nanoc::Filters
2
+ class Rainpress < Nanoc::Filter
3
+
4
+ identifier :rainpress
5
+
6
+ def run(content)
7
+ require 'rainpress'
8
+
9
+ ::Rainpress.compress(content)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module Nanoc::Filters
2
+ class RelativizePaths < Nanoc::Filter
3
+
4
+ identifier :relativize_paths
5
+
6
+ require 'nanoc/helpers/link_to'
7
+ include Nanoc::Helpers::LinkTo
8
+
9
+ def run(content, params={})
10
+ type = params[:type] || :html
11
+
12
+ case type
13
+ when :html
14
+ content.gsub(/(src|href)=(['"]?)(\/.+?)\2([ >])/) do
15
+ $1 + '=' + $2 + relative_path_to($3) + $2 + $4
16
+ end
17
+ when :css
18
+ content.gsub(/url\((['"]?)(\/.+?)\1\)/) do
19
+ 'url(' + $1 + relative_path_to($2) + $1 + ')'
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -8,6 +8,7 @@ module Nanoc::Filters
8
8
 
9
9
  # Get options
10
10
  options = @obj_rep.attribute_named(:sass_options) || {}
11
+ options[:filename] = filename
11
12
 
12
13
  # Get result
13
14
  ::Sass::Engine.new(content, options).render
@@ -0,0 +1,9 @@
1
+ require 'nanoc/helpers/blogging'
2
+ require 'nanoc/helpers/capturing'
3
+ require 'nanoc/helpers/filtering'
4
+ require 'nanoc/helpers/html_escape'
5
+ require 'nanoc/helpers/link_to'
6
+ require 'nanoc/helpers/render'
7
+ require 'nanoc/helpers/tagging'
8
+ require 'nanoc/helpers/text'
9
+ require 'nanoc/helpers/xml_sitemap'
@@ -21,14 +21,15 @@ module Nanoc::Helpers
21
21
  # include Nanoc::Helpers::Blogging
22
22
  module Blogging
23
23
 
24
- # Returns the list of articles, sorted by descending creation date (so
25
- # newer articles appear first).
24
+ # Returns an unsorted list of articles.
25
+ def articles
26
+ @pages.select { |page| page.kind == 'article' }
27
+ end
28
+
29
+ # Returns a list of articles, sorted by descending creation date (so newer
30
+ # articles appear first).
26
31
  def sorted_articles
27
- @pages.select do |page|
28
- page.kind == 'article'
29
- end.sort do |x,y|
30
- y.created_at <=> x.created_at
31
- end
32
+ articles.sort_by { |a| a.created_at }.reverse
32
33
  end
33
34
 
34
35
  # Returns a string representing the atom feed containing recent articles,
@@ -37,6 +38,19 @@ module Nanoc::Helpers
37
38
  #
38
39
  # +limit+:: The maximum number of articles to show. Defaults to 5.
39
40
  #
41
+ # +articles+:: A list of articles to include in the feed. Defaults to the
42
+ # list of articles returned by the articles function.
43
+ #
44
+ # +content_proc+:: A proc that returns the content of the given article,
45
+ # passed as a parameter. By default, given the argument
46
+ # +article+, this proc will return +article.content+.
47
+ # This function may not return nil.
48
+ #
49
+ # +excerpt_proc+:: A proc that returns the excerpt of the given article,
50
+ # passed as a parameter. By default, given the argument
51
+ # +article+, this proc will return +article.excerpt+.
52
+ # This function may return nil.
53
+ #
40
54
  # The following attributes must be set on blog articles:
41
55
  #
42
56
  # * 'title', containing the title of the blog post.
@@ -93,10 +107,38 @@ module Nanoc::Helpers
93
107
  require 'builder'
94
108
 
95
109
  # Extract parameters
96
- limit = params[:limit] || 5
110
+ limit = params[:limit] || 5
111
+ relevant_articles = params[:articles] || articles || []
112
+ content_proc = params[:content_proc] || lambda { |a| a.content }
113
+ excerpt_proc = params[:excerpt_proc] || lambda { |a| a.excerpt }
114
+
115
+ # Check feed page attributes
116
+ if @page.base_url.nil?
117
+ raise RuntimeError.new('Cannot build Atom feed: feed page has no base_url')
118
+ end
119
+ if @page.title.nil?
120
+ raise RuntimeError.new('Cannot build Atom feed: feed page has no title')
121
+ end
122
+ if @page.author_name.nil?
123
+ raise RuntimeError.new('Cannot build Atom feed: feed page has no author_name')
124
+ end
125
+ if @page.author_uri.nil?
126
+ raise RuntimeError.new('Cannot build Atom feed: feed page has no author_uri')
127
+ end
128
+
129
+ # Check article attributes
130
+ if relevant_articles.empty?
131
+ raise RuntimeError.new('Cannot build Atom feed: no articles')
132
+ end
133
+ if relevant_articles.any? { |a| a.created_at.nil? }
134
+ raise RuntimeError.new('Cannot build Atom feed: one or more articles lack created_at')
135
+ end
136
+
137
+ # Get sorted relevant articles
138
+ sorted_relevant_articles = relevant_articles.sort_by { |a| a.created_at }.reverse.first(limit)
97
139
 
98
140
  # Get most recent article
99
- last_article = sorted_articles.first
141
+ last_article = sorted_relevant_articles.first
100
142
 
101
143
  # Create builder
102
144
  buffer = ''
@@ -123,7 +165,7 @@ module Nanoc::Helpers
123
165
  end
124
166
 
125
167
  # Add articles
126
- sorted_articles.first(limit).each do |a|
168
+ sorted_relevant_articles.each do |a|
127
169
  xml.entry do
128
170
  # Add primary attributes
129
171
  xml.id atom_tag_for(a)
@@ -137,8 +179,9 @@ module Nanoc::Helpers
137
179
  xml.link(:rel => 'alternate', :href => url_for(a))
138
180
 
139
181
  # Add content
140
- xml.content a.content, :type => 'html'
141
- xml.summary a.excerpt, :type => 'html' unless a.excerpt.nil?
182
+ summary = excerpt_proc.call(a)
183
+ xml.content content_proc.call(a), :type => 'html'
184
+ xml.summary summary, :type => 'html' unless summary.nil?
142
185
  end
143
186
  end
144
187
  end
@@ -0,0 +1,54 @@
1
+ module Nanoc::Helpers
2
+
3
+ # Nanoc::Helpers::Filtering provides a filter method, which allows parts of
4
+ # a page to be filtered.
5
+ #
6
+ # For example, the following piece of code only runs the "rubypants" filter
7
+ # on the second paragraph:
8
+ #
9
+ # <p>Lorem ipsum dolor sit amet...</p>
10
+ # <% filter :rubypants do %>
11
+ # <p>Consectetur adipisicing elit...</p>
12
+ # <% end %>
13
+ #
14
+ # This helper likely only works with ERB (and perhaps Erubis).
15
+ #
16
+ # To activate this helper, +include+ it, like this:
17
+ #
18
+ # include Nanoc::Helpers::Filtering
19
+ module Filtering
20
+
21
+ # Filters the content in the given block and outputs it.
22
+ def filter(filter_name, &block)
23
+ # Capture block
24
+ data = capture(&block)
25
+
26
+ # Find filter
27
+ filter = Nanoc::Filter.named(filter_name).new(@_obj_rep)
28
+
29
+ # Filter captured data
30
+ filtered_data = filter.run(data)
31
+
32
+ # Append filtered data to buffer
33
+ buffer = eval('_erbout', block.binding)
34
+ buffer << filtered_data
35
+ end
36
+
37
+ private
38
+
39
+ def capture(*args, &block)
40
+ buffer = eval('_erbout', block.binding)
41
+
42
+ pos = buffer.length
43
+ block.call(*args)
44
+
45
+ data = buffer[pos..-1]
46
+
47
+ buffer[pos..-1] = ''
48
+
49
+ data
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -7,6 +7,7 @@ module Nanoc::Helpers
7
7
  # include Nanoc::Helpers::LinkTo
8
8
  module LinkTo
9
9
 
10
+ require 'nanoc/helpers/html_escape'
10
11
  include Nanoc::Helpers::HTMLEscape
11
12
 
12
13
  # Creates a HTML link to the given path or page/asset representation, and
@@ -68,6 +69,45 @@ module Nanoc::Helpers
68
69
  end
69
70
  end
70
71
 
72
+ # Returns the relative path from the current page to the given path or
73
+ # page/asset representation.
74
+ #
75
+ # +path_or_rep+:: the URL or path (a String) to where the relative should
76
+ # point, or the page or asset representation to which the
77
+ # relative should point.
78
+ #
79
+ # Example:
80
+ #
81
+ # # if the current item's path is /foo/bar/
82
+ # relative_path('/foo/qux/')
83
+ # # => '../qux/'
84
+ def relative_path_to(path_or_rep)
85
+ require 'pathname'
86
+
87
+ # Find path
88
+ path = path_or_rep.is_a?(String) ? path_or_rep : path_or_rep.path
89
+
90
+ # Get source and destination paths
91
+ dst_path = Pathname.new(path)
92
+ src_path = Pathname.new(@item.path)
93
+
94
+ # Calculate elative path (method depends on whether destination is a
95
+ # directory or not).
96
+ if src_path.to_s[-1,1] != '/'
97
+ relative_path = dst_path.relative_path_from(src_path.dirname).to_s
98
+ else
99
+ relative_path = dst_path.relative_path_from(src_path).to_s
100
+ end
101
+
102
+ # Add trailing slash if necessary
103
+ if dst_path.to_s[-1,1] == '/'
104
+ relative_path += '/'
105
+ end
106
+
107
+ # Done
108
+ relative_path
109
+ end
110
+
71
111
  end
72
112
 
73
113
  end