nanoc 1.3.1 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,12 @@
1
+ == 1.4
2
+
3
+ * nanoc now supports ERB (as well as Erubis); Erubis no longer is a dependency
4
+ * meta.yaml can now have haml_options property, which is passed to Haml
5
+ * Pages can now have a 'filename' property, which defaults to 'index' [Dennis
6
+ Sutch]
7
+ * Pages now know in what order they should be compiled, eliminating the need
8
+ for custom page ordering [Dennis Sutch]
9
+
1
10
  == 1.3.1
2
11
 
3
12
  * The contents of the 'assets' directory are now copied into the output
@@ -16,9 +25,9 @@
16
25
  == 1.2
17
26
 
18
27
  * Sites now have an 'assets' directory, whose contents are copied to the
19
- 'output' directory when compiling
28
+ 'output' directory when compiling [Soryu]
20
29
  * Added support for non-eRuby layouts (Markaby, Haml, Liquid, ...)
21
- * Added many more filters
30
+ * Added more filters (Markaby, Haml, Liquid, RDoc [Dmitry Bilunov])
22
31
  * Improved error reporting
23
32
  * Accessing page attributes using instance variables, and not through @page,
24
33
  is no longer possible
data/Rakefile CHANGED
@@ -29,7 +29,6 @@ spec = Gem::Specification.new do |s|
29
29
  s.homepage = HOMEPAGE
30
30
  s.email = EMAIL
31
31
 
32
- s.add_dependency('erubis')
33
32
  s.required_ruby_version = '>= 1.8.2'
34
33
 
35
34
  s.has_rdoc = false
data/bin/nanoc CHANGED
@@ -26,7 +26,7 @@ Description:
26
26
  The 'nanoc' command is used for creating nanoc-powered sites, as well as
27
27
  managing them: creating pages and templates and compiling the site.
28
28
 
29
- Read more about nanoc on the site: <http://stoneship.org/software/nanoc/>
29
+ Read more about nanoc on the site: <http://nanoc.stoneship.org/>
30
30
  EOT
31
31
 
32
32
  # Parse options
data/lib/compiler.rb CHANGED
@@ -13,11 +13,11 @@ module Nanoc
13
13
 
14
14
  PAGE_DEFAULTS = {
15
15
  :custom_path => nil,
16
+ :filename => 'index',
16
17
  :extension => 'html',
17
18
  :filters => [],
18
19
  :is_draft => false,
19
- :layout => 'default',
20
- :order => 0
20
+ :layout => 'default'
21
21
  }
22
22
 
23
23
  def initialize
@@ -31,6 +31,9 @@ module Nanoc
31
31
  # Require all Ruby source files in lib/
32
32
  Dir['lib/*.rb'].each { |f| require f }
33
33
 
34
+ # Create output assets directory if necessary
35
+ FileUtils.mkdir_p(@config[:output_dir])
36
+
34
37
  # Copy assets to output directory
35
38
  copy_assets
36
39
 
@@ -49,28 +52,27 @@ module Nanoc
49
52
  # Write page with layout
50
53
  FileManager.create_file(path_for_page(page)) { content }
51
54
  rescue => exception
52
- $stderr.puts "Exception occured while layouting page " +
53
- "'#{page[:_content_filename]}' in layout '#{page[:layout]}':" unless $quiet
54
- $stderr.puts exception unless $quiet
55
- $stderr.puts exception.backtrace.join("\n") unless $quiet
56
- exit
55
+ p = page[:_content_filename]
56
+ l = page[:layout]
57
+ handle_exception(exception, "layouting page '#{p}' in layout '#{l}'")
57
58
  end
58
59
 
59
60
  end
60
61
  end
61
62
 
62
- private
63
+ private
63
64
 
64
65
  # Copies the contents of the assets directory into the output directory
65
66
  def copy_assets
66
- # Create output assets directory if necessary
67
- FileUtils.mkdir_p(@config[:output_dir])
68
-
69
67
  # Remove existing assets
70
- Dir['assets/*'].each { |f| FileUtils.remove_entry_secure(f.sub('assets/', @config[:output_dir] + '/'), true) }
68
+ Dir['assets/*'].each do |f|
69
+ FileUtils.remove_entry_secure(f.sub('assets/', @config[:output_dir] + '/'), true)
70
+ end
71
71
 
72
72
  # Copy assets
73
- FileUtils.cp_r(Dir['assets/*'], @config[:output_dir]) if File.directory?('assets') and !Dir['assets/*'].empty?
73
+ if File.directory?('assets') and !Dir['assets/*'].empty?
74
+ FileUtils.cp_r(Dir['assets/*'], @config[:output_dir])
75
+ end
74
76
  end
75
77
 
76
78
  # Returns a list of uncompiled pages
@@ -84,7 +86,8 @@ module Nanoc
84
86
  page[:path] = filename.sub(/^content/, '').sub('meta.yaml', '')
85
87
 
86
88
  # Get the content filename
87
- content_filenames = Dir[filename.sub('meta.yaml', File.basename(File.dirname(filename)) + '.*')].reject { |f| f =~ /~$/ }
89
+ content_filenames = Dir[filename.sub('meta.yaml', File.basename(File.dirname(filename)) + '.*')]
90
+ content_filenames.reject! { |f| f =~ /~$/ }
88
91
  content_filenames += Dir["#{File.dirname(filename)}/index.*"] # fallback for nanoc 1.0
89
92
  content_filenames.ensure_single('content files', File.dirname(filename))
90
93
  page[:_content_filename] = content_filenames[0]
@@ -95,15 +98,6 @@ module Nanoc
95
98
  # Ignore drafts
96
99
  pages.reject! { |page| page[:is_draft] }
97
100
 
98
- # Sort pages by order and by path
99
- pages.sort! do |x,y|
100
- if x[:order].to_i == y[:order].to_i
101
- x[:path] <=> y[:path]
102
- else
103
- x[:order].to_i <=> y[:order].to_i
104
- end
105
- end
106
-
107
101
  pages
108
102
  end
109
103
 
@@ -123,66 +117,46 @@ module Nanoc
123
117
  # Returns the path for the given page
124
118
  def path_for_page(a_page)
125
119
  if a_page[:custom_path].nil?
126
- @config[:output_dir] + a_page[:path] + 'index.' + a_page[:extension]
120
+ @config[:output_dir] + a_page[:path] + a_page[:filename] + '.' + a_page[:extension]
127
121
  else
128
122
  @config[:output_dir] + a_page[:custom_path]
129
123
  end
130
124
  end
131
125
 
132
126
  # Compiles the given pages and returns the compiled pages
133
- def compile_pages(a_pages)
127
+ def compile_pages(pages)
134
128
  # Create page objects from given pages
135
- given_pages = []
136
- a_pages.each { |page| given_pages << Page.new(page) }
129
+ given_pages = []
130
+ pages.each { |page| given_pages << Page.new(page) }
137
131
 
138
- # Create arrays for two kinds of pages
139
- compiled_pages = []
140
- uncompiled_pages = []
141
- given_pages.each { |page| uncompiled_pages << page }
132
+ # Compile pages
133
+ Page.compile(given_pages)
142
134
 
143
- # Compile all pages
144
- given_pages.each do |page|
145
- # Read page
146
- content = File.read(page._content_filename)
147
-
148
- # Compile page
149
- begin
150
- content = content.filter(page.filters, :assigns => { :page => page, :pages => uncompiled_pages + compiled_pages })
151
- rescue Exception => exception
152
- $stderr.puts "Exception occured while compiling page " +
153
- "'#{page[:_content_filename]}':" unless $quiet
154
- $stderr.puts exception unless $quiet
155
- $stderr.puts exception.backtrace.join("\n") unless $quiet
156
- exit
157
- end
158
-
159
- # Move from uncompiled to compiled
160
- uncompiled_pages -= [ page ]
161
- compiled_pages += [ page ]
162
-
163
- # Create compiled page
164
- page[:content] = content
165
- end
166
-
167
- # Return all pages
168
- compiled_pages
135
+ given_pages
169
136
  end
170
137
 
171
138
  # Layouts the page
172
139
  def layouted_page(a_page, a_pages)
173
- context = { :page => a_page.merge(:_content_filename => nil), :pages => a_pages }
140
+ # Find layout
174
141
  layout = layout_for_page(a_page)
175
142
 
176
- content = nil
143
+ # Build params
144
+ assigns = { :page => a_page.merge(:_content_filename => nil), :pages => a_pages }
145
+ params = { :assigns => assigns }
146
+ params[:haml_options] = (a_page[:haml_options] || {}).symbolize_keys
147
+
148
+ # Layout
177
149
  case layout[:type]
178
150
  when :eruby
179
- content = layout[:content].eruby(context)
151
+ content = layout[:content].eruby(params)
180
152
  when :haml
181
- content = layout[:content].haml(context)
153
+ content = layout[:content].haml(params)
182
154
  when :markaby
183
- content = layout[:content].markaby(context)
155
+ content = layout[:content].markaby(params)
184
156
  when :liquid
185
- content = layout[:content].liquid(context)
157
+ content = layout[:content].liquid(params)
158
+ else
159
+ content = nil
186
160
  end
187
161
 
188
162
  content
data/lib/creator.rb CHANGED
@@ -3,12 +3,7 @@ module Nanoc
3
3
  class Creator
4
4
 
5
5
  def self.create_site(a_sitename)
6
- # Make sure we're not accidentally overwriting anything
7
- if File.exist?(a_sitename)
8
- $stderr.puts 'ERROR: A file or directory named ' + a_sitename +
9
- ' already exists.' unless $quiet
10
- exit
11
- end
6
+ ensure_nonexistant(a_sitename)
12
7
 
13
8
  FileManager.create_dir a_sitename do
14
9
  FileManager.create_dir 'assets'
@@ -24,8 +19,8 @@ module Nanoc
24
19
  "\n" +
25
20
  "# Built-in\n" +
26
21
  "layout: \"default\"\n" +
27
- "order: 0\n" +
28
22
  "filters: []\n" +
23
+ "filename: \"index\"\n" +
29
24
  "extension: \"html\"\n" +
30
25
  "\n" +
31
26
  "# Custom\n"
@@ -102,13 +97,7 @@ module Nanoc
102
97
 
103
98
  def self.create_page(a_pagename, a_params={})
104
99
  Nanoc.ensure_in_site
105
-
106
- # Make sure we're not accidentally overwriting anything
107
- if File.exist?(File.join(['content', a_pagename]))
108
- $stderr.puts 'ERROR: A file or directory named ' + a_pagename +
109
- ' already exists.' unless $quiet
110
- exit
111
- end
100
+ ensure_nonexistant(File.join(['content', a_pagename]))
112
101
 
113
102
  # Sanitize page name
114
103
  if a_pagename =~ /^[\/\.]+/
@@ -117,9 +106,6 @@ module Nanoc
117
106
  end
118
107
 
119
108
  # Read template
120
- template_index = nil
121
- template_meta = nil
122
- template_content_filename = nil
123
109
  template = a_params[:template] || 'default'
124
110
  begin
125
111
  template_meta = File.read("templates/#{template}/meta.yaml")
@@ -137,7 +123,9 @@ module Nanoc
137
123
  # Create index and yaml file
138
124
  FileManager.create_dir 'content' do
139
125
  FileManager.create_dir a_pagename do
140
- FileManager.create_file "#{a_pagename.sub(/.*\/([^\/]+)/, '\1')}#{File.extname(template_content_filename)}" do
126
+ page_name = a_pagename.sub(/.*\/([^\/]+)/, '\1')
127
+ extension = File.extname(template_content_filename)
128
+ FileManager.create_file "#{page_name}#{extension}" do
141
129
  template_index
142
130
  end
143
131
  FileManager.create_file 'meta.yaml' do
@@ -149,13 +137,7 @@ module Nanoc
149
137
 
150
138
  def self.create_template(a_templatename)
151
139
  Nanoc.ensure_in_site
152
-
153
- # Make sure we're not accidentally overwriting anything
154
- if File.exist?(File.join(['templates', a_templatename]))
155
- $stderr.puts 'ERROR: A file or directory named ' + a_templatename +
156
- ' already exists.' unless $quiet
157
- exit
158
- end
140
+ ensure_nonexistant(File.join(['templates', a_templatename]))
159
141
 
160
142
  FileManager.create_dir 'templates' do
161
143
  FileManager.create_dir a_templatename do
@@ -172,5 +154,14 @@ module Nanoc
172
154
  end
173
155
  end
174
156
 
157
+ private
158
+
159
+ def self.ensure_nonexistant(filename)
160
+ if File.exist?(filename)
161
+ $stderr.puts "ERROR: A file or directory named #{filename} already exists." unless $quiet
162
+ exit
163
+ end
164
+ end
165
+
175
166
  end
176
167
  end
data/lib/enhancements.rb CHANGED
@@ -2,11 +2,12 @@ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
2
 
3
3
  try_require 'rubygems'
4
4
 
5
- require 'erubis'
5
+ require 'erb'
6
6
  require 'fileutils'
7
7
  require 'yaml'
8
8
 
9
9
  try_require 'bluecloth'
10
+ try_require 'erubis'
10
11
  try_require 'redcloth'
11
12
  try_require 'rubypants'
12
13
  try_require 'markaby'
@@ -15,6 +16,15 @@ try_require 'haml'
15
16
  try_require 'rdoc/markup/simple_markup'
16
17
  try_require 'rdoc/markup/simple_markup/to_html'
17
18
 
19
+ def handle_exception(exception, text)
20
+ unless $quiet or exception.class == SystemExit
21
+ $stderr.puts "ERROR: Exception occured while #{text}:\n"
22
+ $stderr.puts exception
23
+ $stderr.puts exception.backtrace.join("\n")
24
+ end
25
+ exit
26
+ end
27
+
18
28
  class Array
19
29
  # Ensures that the array contains only one element
20
30
  def ensure_single(a_noun, a_context)
@@ -54,6 +64,13 @@ class Hash
54
64
  end
55
65
  end
56
66
 
67
+ def symbolize_keys
68
+ inject({}) do |hash, (key, value)|
69
+ hash[key.intern] = value
70
+ hash
71
+ end
72
+ end
73
+
57
74
  def stringify_keys
58
75
  inject({}) do |hash, (key, value)|
59
76
  hash[key.to_s] = value
@@ -62,20 +79,33 @@ class Hash
62
79
  end
63
80
  end
64
81
 
82
+ class ERBContext
83
+ def initialize(hash)
84
+ hash.each_pair do |key, value|
85
+ instance_variable_set('@' + key.to_s, value)
86
+ end
87
+ end
88
+
89
+ def get_binding
90
+ binding
91
+ end
92
+ end
93
+
65
94
  class String
66
95
  # Runs the string through the filters as given by the array of
67
96
  # filter names. Available filters include 'markdown', 'smartypants' and 'eruby'.
68
97
  def filter(a_filters, a_params={})
98
+ assigns = a_params[:assigns]
69
99
  a_filters.inject(self) do |result, filter|
70
100
  case filter
71
101
  when 'eruby'
72
- result.replace(result.eruby(a_params[:assigns]))
102
+ result.replace(result.eruby(:assigns => assigns))
73
103
  when 'haml'
74
- result.replace(result.haml(a_params[:assigns]))
104
+ result.replace(result.haml(:assigns => assigns))
75
105
  when 'liquid'
76
- result.replace(result.liquid(a_params[:assigns]))
106
+ result.replace(result.liquid(:assigns => assigns))
77
107
  when 'markaby'
78
- result.replace(result.markaby(a_params[:assigns]))
108
+ result.replace(result.markaby(:assigns => assigns))
79
109
  when 'markdown', 'bluecloth'
80
110
  result.replace(result.markdown)
81
111
  when 'rdoc'
@@ -90,22 +120,36 @@ class String
90
120
  end
91
121
  end
92
122
 
93
- # Converts the string using eRuby.
94
- def eruby(a_assigns={})
95
- Erubis::Eruby.new(self).evaluate(a_assigns)
123
+ # Converts the string using eRuby
124
+ def eruby(a_params={})
125
+ erubis(a_params)
126
+ rescue NameError
127
+ erb(a_params)
128
+ end
129
+
130
+ # Converts the string using Erubis
131
+ def erubis(a_params={})
132
+ Erubis::Eruby.new(self).evaluate(a_params[:assigns] || {})
133
+ end
134
+
135
+ # Converts the string using ERB
136
+ def erb(a_params={})
137
+ ERB.new(self).result(ERBContext.new(a_params[:assigns] || {}).get_binding)
96
138
  end
97
139
 
98
140
  # Converts the string using Haml
99
- def haml(a_assigns={})
100
- Haml::Engine.new(self, :locals => a_assigns).to_html
141
+ def haml(a_params={})
142
+ options = (a_params[:haml_options] || {})
143
+ options[:locals] = a_params[:assigns] unless a_params[:assigns].nil?
144
+ Haml::Engine.new(self, options).to_html
101
145
  rescue NameError
102
146
  $stderr.puts 'ERROR: String#haml failed (Haml not installed?)' unless $quiet
103
147
  exit
104
148
  end
105
149
 
106
150
  # Converts the string using Liquid
107
- def liquid(a_assigns={})
108
- Liquid::Template.parse(self).render(a_assigns.stringify_keys)
151
+ def liquid(a_params={})
152
+ Liquid::Template.parse(self).render((a_params[:assigns] || {}).stringify_keys)
109
153
  rescue NameError
110
154
  $stderr.puts 'ERROR: String#liquid failed (Liquid not installed?)' unless $quiet
111
155
  exit
@@ -113,8 +157,8 @@ class String
113
157
 
114
158
  # Converts the string using Markaby
115
159
  # TODO perhaps add support for helpers
116
- def markaby(a_assigns={})
117
- Markaby::Builder.new(a_assigns).instance_eval(self).to_s
160
+ def markaby(a_params={})
161
+ Markaby::Builder.new((a_params[:assigns] || {})).instance_eval(self).to_s
118
162
  rescue NameError
119
163
  $stderr.puts 'ERROR: String#markaby failed (Markaby not installed?)' unless $quiet
120
164
  exit
@@ -228,5 +272,6 @@ class FileManager
228
272
  end
229
273
 
230
274
  def render(a_name, a_context={})
231
- File.read('layouts/' + a_name.to_s + '.erb').eruby(a_context.merge({ :page => @page, :pages => @pages }))
275
+ assigns = a_context.merge({ :page => @page, :pages => @pages })
276
+ File.read('layouts/' + a_name.to_s + '.erb').eruby(:assigns => assigns)
232
277
  end
data/lib/nanoc.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Nanoc
2
- VERSION = '1.3.1'
2
+ VERSION = '1.4'
3
3
 
4
4
  def self.ensure_in_site
5
5
  unless in_site?
@@ -15,7 +15,6 @@ module Nanoc
15
15
  return false unless File.directory?('content')
16
16
  return false unless File.directory?('layouts')
17
17
  return false unless File.directory?('lib')
18
- return false unless File.directory?('output')
19
18
  return false unless File.directory?('tasks')
20
19
  return false unless File.directory?('templates')
21
20
  return false unless File.exist?('config.yaml')
data/lib/page.rb CHANGED
@@ -1,20 +1,14 @@
1
1
  module Nanoc
2
2
  class Page
3
3
 
4
- def initialize(a_hash={})
5
- @attributes = a_hash
6
- end
7
-
8
- def [](a_key)
9
- @attributes[a_key]
10
- end
4
+ @@compilation_stack = []
11
5
 
12
- def []=(a_key, a_value)
13
- @attributes[a_key] = a_value
6
+ def initialize(hash={})
7
+ @attributes = hash
14
8
  end
15
9
 
16
- def merge(a_other)
17
- @attributes.merge(a_other.to_hash)
10
+ def merge(other)
11
+ @attributes.merge(other.to_hash)
18
12
  self
19
13
  end
20
14
 
@@ -22,8 +16,75 @@ module Nanoc
22
16
  @attributes
23
17
  end
24
18
 
25
- def method_missing(a_method, *a_args)
26
- @attributes[a_method.to_sym]
19
+ # Accessing data
20
+
21
+ def [](key)
22
+ @attributes[key]
23
+ end
24
+
25
+ def []=(key, value)
26
+ @attributes[key] = value
27
+ end
28
+
29
+ def method_missing(method, *args)
30
+ @attributes[method.to_sym]
31
+ end
32
+
33
+ def content
34
+ compile!
35
+ @attributes[:content]
36
+ end
37
+
38
+ # Compiling
39
+
40
+ def self.compile(pages)
41
+ @@pages = pages
42
+
43
+ # Compile all pages
44
+ pages.each do |page|
45
+ page.compile!
46
+ end
47
+ end
48
+
49
+ def compile!
50
+ # Check for recursive call
51
+ if @@compilation_stack.include?(self)
52
+ # Print compilation stack
53
+ unless $quiet
54
+ $stderr.puts 'ERROR: Recursive call to page content. Page compilation stack:'
55
+
56
+ # Determine relevant part of compilation stack
57
+ stack_begin = @@compilation_stack.index(self)
58
+ stack_end = @@compilation_stack.size
59
+ relevant_stack_part = @@compilation_stack.last(stack_end - stack_begin)
60
+
61
+ # Print relevant part of compilation stack
62
+ relevant_stack_part.each_with_index do |page, i|
63
+ $stderr.puts "#{i} #{page._content_filename}"
64
+ end
65
+ end
66
+ exit
67
+ # Compile if not yet compiled
68
+ elsif self[:content].nil?
69
+ # Add to stack
70
+ @@compilation_stack.push(self)
71
+
72
+ # Read page
73
+ content = File.read(self._content_filename)
74
+
75
+ # Compile page
76
+ begin
77
+ assigns = { :page => self, :pages => @@pages }
78
+ # TODO set more custom options
79
+ params = { :assigns => assigns }
80
+ params[:haml_options] = (self[:haml_options] || {}).symbolize_keys
81
+ content = content.filter(self.filters, params)
82
+ rescue Exception => exception
83
+ handle_exception(exception, "compiling page '#{self[:_content_filename]}'")
84
+ end
85
+ @attributes[:content] = content
86
+ @@compilation_stack.pop
87
+ end
27
88
  end
28
89
 
29
90
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: nanoc
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.3.1
7
- date: 2007-06-30 00:00:00 +02:00
6
+ version: "1.4"
7
+ date: 2007-07-06 00:00:00 +02:00
8
8
  summary: a CMS that doesn't run on your server
9
9
  require_paths:
10
10
  - lib
@@ -51,13 +51,5 @@ extensions: []
51
51
 
52
52
  requirements: []
53
53
 
54
- dependencies:
55
- - !ruby/object:Gem::Dependency
56
- name: erubis
57
- version_requirement:
58
- version_requirements: !ruby/object:Gem::Version::Requirement
59
- requirements:
60
- - - ">"
61
- - !ruby/object:Gem::Version
62
- version: 0.0.0
63
- version:
54
+ dependencies: []
55
+