nanoc 1.5 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,11 +1,25 @@
1
- == 1.5
1
+ nanoc Release Notes
2
+ ===================
3
+
4
+ 1.6
5
+ ---
6
+
7
+ * Added support for post-layout filters
8
+ * Added support for getting a File object for the page, so you can now e.g.
9
+ easily get the modification time for a given page (`@page.file.mtime`).
10
+ * Cleaned up the source code a lot
11
+ * Removed deprecated asset-copying functionality
12
+
13
+ 1.5
14
+ ---
2
15
 
3
16
  * Added support for custom filters
4
17
  * Improved Liquid support -- Liquid is now a first-class nanoc citizen
5
18
  * Deprecated assets -- use something like rsync instead
6
19
  * Added eruby_engine option, which can be 'erb' or 'erubis'
7
20
 
8
- == 1.4
21
+ 1.4
22
+ ---
9
23
 
10
24
  * nanoc now supports ERB (as well as Erubis); Erubis no longer is a dependency
11
25
  * meta.yaml can now have haml_options property, which is passed to Haml
@@ -14,12 +28,14 @@
14
28
  * Pages now know in what order they should be compiled, eliminating the need
15
29
  for custom page ordering [Dennis Sutch]
16
30
 
17
- == 1.3.1
31
+ 1.3.1
32
+ -----
18
33
 
19
34
  * The contents of the 'assets' directory are now copied into the output
20
35
  directory specified in 'config.yaml'
21
36
 
22
- == 1.3
37
+ 1.3
38
+ ---
23
39
 
24
40
  * The @pages array now also contains uncompiled pages
25
41
  * Pages with 'skip_output' set to true will not be outputted
@@ -29,9 +45,10 @@
29
45
  * nanoc now warns before overwriting in create_site, create_page and
30
46
  create_template (but not in compile)
31
47
 
32
- == 1.2
48
+ 1.2
49
+ ---
33
50
 
34
- * Sites now have an 'assets' directory, whose contents are copied to the
51
+ * Sites now have an 'assets' directory, whose contents are copied to the
35
52
  'output' directory when compiling [Soryu]
36
53
  * Added support for non-eRuby layouts (Markaby, Haml, Liquid, ...)
37
54
  * Added more filters (Markaby, Haml, Liquid, RDoc [Dmitry Bilunov])
@@ -41,16 +58,19 @@
41
58
  * Page attributes can now be accessed using dot notation, i.e. @page.title as
42
59
  well as @page[:title]
43
60
 
44
- == 1.1.3
61
+ 1.1.3
62
+ -----
45
63
 
46
64
  * Fixed bug which would cause layoutless pages to be outputted incorrectly
47
65
 
48
- == 1.1.2
66
+ 1.1.2
67
+ -----
49
68
 
50
69
  * Backup files (files ending with a “~”) are now ignored
51
70
  * Fixed bug which would cause subpages not to be generated correctly
52
71
 
53
- == 1.1
72
+ 1.1
73
+ ---
54
74
 
55
75
  * Added support for nested layouts
56
76
  * Added coloured logging
@@ -59,12 +79,14 @@
59
79
  directory they are in [Colin Barrett]
60
80
  * It is now possible to access @page in the page’s content file
61
81
 
62
- == 1.0.1
82
+ 1.0.1
83
+ -----
63
84
 
64
85
  * Fixed a bug which would cause a “no such template” error to be displayed
65
86
  when the template existed but compiling it would raise an exception
66
87
  * Fixed bug which would cause pages not to be sorted by order before compiling
67
88
 
68
- == 1.0
89
+ 1.0
90
+ ---
69
91
 
70
92
  * Initial release
@@ -23,6 +23,8 @@ module Nanoc
23
23
  :layout => 'default'
24
24
  }
25
25
 
26
+ attr_reader :config, :stack, :pages
27
+
26
28
  def initialize
27
29
  @filters = {}
28
30
  end
@@ -38,17 +40,23 @@ module Nanoc
38
40
  # Require all Ruby source files in lib/
39
41
  Dir['lib/*.rb'].each { |f| require f }
40
42
 
41
- # Create output assets directory if necessary
43
+ # Create output directory if necessary
42
44
  FileUtils.mkdir_p(@config[:output_dir])
43
45
 
44
- # Copy assets to output directory
45
- copy_assets
46
+ # Get all pages
47
+ @pages = find_uncompiled_pages
48
+
49
+ # Filter, layout, and filter again
50
+ filter(:pre)
51
+ layout
52
+ filter(:post)
46
53
 
47
- # Compile and layout pages
48
- pages = find_uncompiled_pages
49
- pages = layout(compile(pages))
54
+ # Save pages
55
+ save_pages
50
56
  end
51
57
 
58
+ # Filter management
59
+
52
60
  def register_filter(name, &block)
53
61
  @filters[name.to_sym] = block
54
62
  end
@@ -57,137 +65,81 @@ module Nanoc
57
65
  @filters[name.to_sym]
58
66
  end
59
67
 
60
- def config
61
- @config
62
- end
63
-
64
68
  private
65
69
 
66
- # Returns the path for the given page
67
- def path_for_page(page)
68
- if page.attributes[:custom_path].nil?
69
- @config[:output_dir] + page.attributes[:path] +
70
- page.attributes[:filename] + '.' + page.attributes[:extension]
71
- else
72
- @config[:output_dir] + page.attributes[:custom_path]
73
- end
74
- end
75
-
76
- # Returns the layout for the given page
77
- def layout_for_page(page)
78
- if page.attributes[:layout].nil?
79
- { :type => :eruby, :content => "<%= @page.content %>" }
80
- else
81
- filenames = Dir["layouts/#{page.attributes[:layout]}.*"]
82
- filenames.ensure_single('layout files', page.attributes[:layout])
83
- filename = filenames[0]
84
-
85
- { :type => FILE_TYPES[File.extname(filename)], :content => File.read(filename) }
86
- end
87
- end
88
-
89
- def copy_assets
90
- # Check for assets
91
- if Dir['assets/*'].size > 0
92
- deprecate 'Asset-copying functionality is deprecated as of nanoc 1.5,' +
93
- 'and will be removed in nanoc 1.6. Please use a Rake task that' +
94
- 'copies assets using something like rsync instead.'
95
- end
96
-
97
- # Remove existing assets
98
- Dir['assets/*'].each do |f|
99
- FileUtils.remove_entry_secure(f.sub('assets/', @config[:output_dir] + '/'), true)
100
- end
101
-
102
- # Copy assets
103
- if File.directory?('assets') and !Dir['assets/*'].empty?
104
- FileUtils.cp_r(Dir['assets/*'], @config[:output_dir])
105
- end
106
- end
70
+ # Main methods
107
71
 
108
72
  def find_uncompiled_pages
109
73
  # Read all meta files
110
- pages = Dir['content/**/meta.yaml'].collect do |filename|
74
+ Dir['content/**/meta.yaml'].inject([]) do |pages, filename|
111
75
  # Read the meta file
112
- page = @global_page.merge(YAML.load_file_and_clean(filename))
76
+ hash = @global_page.merge(YAML.load_file_and_clean(filename))
113
77
 
114
78
  # Fix the path
115
- page[:path] = filename.sub(/^content/, '').sub('meta.yaml', '')
79
+ hash[:path] = filename.sub(/^content/, '').sub('meta.yaml', '')
80
+
81
+ # Convert to a Page instance
82
+ page = Page.new(hash, self)
116
83
 
117
84
  # Get the content filename
118
- content_filenames = Dir[filename.sub('meta.yaml', File.basename(File.dirname(filename)) + '.*')]
119
- content_filenames.reject! { |f| f =~ /~$/ }
120
- content_filenames += Dir["#{File.dirname(filename)}/index.*"] # fallback for nanoc 1.0
121
- content_filenames.ensure_single('content files', File.dirname(filename))
122
- page[:_content_filename] = content_filenames[0]
85
+ page.content_filename = content_filename_for_meta_filename(filename)
123
86
 
124
- page
87
+ # Skip drafts
88
+ hash[:is_draft] ? pages : pages + [ page ]
125
89
  end
126
-
127
- # Ignore drafts
128
- pages.reject! { |page| page[:is_draft] }
129
-
130
- pages
131
90
  end
132
91
 
133
- def compile(pages)
134
- # Create page objects from given pages
135
- given_pages = []
136
- pages.each { |page| given_pages << Page.new(page) }
92
+ def filter(stage)
93
+ # Reset filter stack
94
+ @stack = []
137
95
 
138
- # Compile pages
139
- Page.compile(given_pages)
140
-
141
- given_pages
142
- end
143
-
144
- def layouted_page(page, pages)
145
- # Find layout
146
- layout = layout_for_page(page)
147
-
148
- # Build params
149
- if layout[:type] == :liquid
150
- public_page = page.to_liquid
151
- public_pages = pages.map { |p| p.to_liquid }
152
- else
153
- public_page = page.to_proxy
154
- public_pages = pages.map { |p| p.to_proxy }
155
- end
156
- params = { :assigns => { :page => public_page, :pages => public_pages } }
157
- params[:haml_options] = (page.attributes[:haml_options] || {}).symbolize_keys
158
-
159
- # Layout
160
- case layout[:type]
161
- when :eruby
162
- content = layout[:content].eruby(params)
163
- when :haml
164
- content = layout[:content].haml(params)
165
- when :markaby
166
- content = layout[:content].markaby(params)
167
- when :liquid
168
- content = layout[:content].liquid(params)
169
- else
170
- content = nil
96
+ # Prepare pages
97
+ @pages.each do |page|
98
+ page.stage = stage
99
+ page.is_filtered = false
171
100
  end
172
101
 
173
- content
102
+ # Filter pages
103
+ @pages.each { |page| page.filter! }
174
104
  end
175
105
 
176
- def layout(pages)
177
- pages.reject { |page| page.attributes[:skip_output] }.each do |page|
106
+ def layout
107
+ # For each page (ignoring drafts)
108
+ @pages.reject { |page| page.attributes[:skip_output] }.each do |page|
178
109
  begin
179
- # Prepare layout content
180
- content = layouted_page(page, pages)
181
-
182
- # Write page with layout
183
- FileManager.create_file(path_for_page(page)) { content }
110
+ # Layout the page
111
+ page.layout!
184
112
  rescue => exception
185
- p = page.attributes[:_content_filename]
186
- l = page.attributes[:layout]
187
- handle_exception(exception, "layouting page '#{p}' in layout '#{l}'")
113
+ handle_exception(exception, "layouting page '#{page.content_filename}' in layout '#{page.attributes[:layout]}'")
188
114
  end
189
115
  end
190
116
  end
191
117
 
118
+ def save_pages
119
+ @pages.reject { |page| page.attributes[:skip_output] }.each do |page|
120
+ # Write page with layout
121
+ FileManager.create_file(page.path) { page.content }
122
+ end
123
+ end
124
+
125
+ # Helper methods
126
+
127
+ def content_filename_for_meta_filename(filename)
128
+ # Find all files with base name of parent directory
129
+ content_filenames = Dir[filename.sub('meta.yaml', File.basename(File.dirname(filename)) + '.*')]
130
+
131
+ # Find all index.* files (used to be a fallback for nanoc 1.0, kinda...)
132
+ content_filenames += Dir["#{File.dirname(filename)}/index.*"]
133
+
134
+ # Reject backups
135
+ content_filenames.reject! { |f| f =~ /~$/ }
136
+
137
+ # Make sure there is only one content file
138
+ content_filenames.ensure_single('content files', File.dirname(filename))
139
+
140
+ # Return the first (and only one)
141
+ content_filenames[0]
142
+ end
143
+
192
144
  end
193
145
  end
@@ -1,5 +1,7 @@
1
1
  class Hash
2
- # Cleans up the hash by performing the following operations:
2
+ # Cleans up the hash and returns the result. It performs the following
3
+ # operations:
4
+ #
3
5
  # * Values with keys ending in _at and _on are converted into Times and
4
6
  # Dates, respectively
5
7
  # * All keys are converted to symbols
@@ -1,8 +1,10 @@
1
1
  require 'yaml'
2
2
 
3
3
  module YAML
4
+
4
5
  # Loads a YAML file, cleans it using Hash#clean, and returns the result
5
6
  def self.load_file_and_clean(a_filename)
6
7
  (YAML.load_file(a_filename) || {}).clean
7
8
  end
9
+
8
10
  end
data/lib/nanoc/creator.rb CHANGED
@@ -6,7 +6,6 @@ module Nanoc
6
6
  ensure_nonexistant(a_sitename)
7
7
 
8
8
  FileManager.create_dir a_sitename do
9
- FileManager.create_dir 'assets'
10
9
  FileManager.create_dir 'output'
11
10
 
12
11
  FileManager.create_file 'config.yaml' do
@@ -20,7 +19,7 @@ module Nanoc
20
19
  "# Built-in\n" +
21
20
  "layout: \"default\"\n" +
22
21
  "filters: []\n" +
23
- "filename: \"index\"\n" +
22
+ "filename: \"index\"\n" +
24
23
  "extension: \"html\"\n" +
25
24
  "\n" +
26
25
  "# Custom\n"
@@ -101,7 +100,7 @@ module Nanoc
101
100
 
102
101
  # Sanitize page name
103
102
  if a_pagename =~ /^[\/\.]+/
104
- $stderr.puts 'ERROR: page name starts with dots and/or slashes, aborting' unless $quiet == true
103
+ $stderr.puts 'ERROR: page name starts with dots and/or slashes, aborting' unless $quiet
105
104
  return
106
105
  end
107
106
 
@@ -109,12 +108,26 @@ module Nanoc
109
108
  template = a_params[:template] || 'default'
110
109
  begin
111
110
  template_meta = File.read("templates/#{template}/meta.yaml")
111
+
112
+ # Find all files
112
113
  template_content_filenames = Dir["templates/#{template}/#{template}.*"]
114
+
115
+ # Find all index.* files (used to be a fallback for nanoc 1.0, kinda...)
113
116
  template_content_filenames += Dir["templates/#{template}/index.*"]
117
+
118
+ # Reject backups
119
+ template_content_filenames.reject! { |f| f =~ /~$/ }
120
+
121
+ # Make sure there is only one content file
122
+ template_content_filenames.ensure_single('template files', template)
123
+
124
+ # Get the first (and only one)
114
125
  template_content_filename = template_content_filenames[0]
126
+
115
127
  template_index = File.read(template_content_filename)
116
- rescue
117
- $stderr.puts 'ERROR: no such template' unless $quiet == true
128
+ rescue => e
129
+ puts e.inspect
130
+ $stderr.puts 'ERROR: no such template' unless $quiet
118
131
  exit
119
132
  end
120
133
  template_meta = template_meta.eruby
@@ -1,4 +1,16 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
1
+ def try_require(s)
2
+ require s
3
+ rescue LoadError
4
+ end
5
+
6
+ def nanoc_require(s)
7
+ require s
8
+ rescue LoadError
9
+ $stderr.puts "ERROR: You need '#{s}' to compile this site." unless $quiet
10
+ exit
11
+ end
12
+
13
+ try_require 'rubygems'
2
14
 
3
15
  require 'fileutils'
4
16
 
@@ -8,11 +20,7 @@ def handle_exception(exception, text)
8
20
  $stderr.puts exception
9
21
  $stderr.puts exception.backtrace.join("\n")
10
22
  end
11
- exit
12
- end
13
-
14
- def deprecate(str)
15
- $stderr.puts 'DEPRECATION WARNING: ' + str unless $quiet
23
+ exit(1)
16
24
  end
17
25
 
18
26
  class FileLogger
@@ -1,10 +1,3 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- require 'erb'
6
- try_require 'erubis'
7
-
8
1
  class ERBContext
9
2
 
10
3
  def initialize(hash)
@@ -28,11 +21,13 @@ class String
28
21
 
29
22
  # Converts the string using Erubis
30
23
  def erubis(params={})
24
+ nanoc_require 'erubis'
31
25
  Erubis::Eruby.new(self).evaluate(params[:assigns] || {})
32
26
  end
33
27
 
34
28
  # Converts the string using ERB
35
29
  def erb(params={})
30
+ nanoc_require 'erb'
36
31
  ERB.new(self).result(ERBContext.new(params[:assigns] || {}).get_binding)
37
32
  end
38
33
 
@@ -1,19 +1,13 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- try_require 'haml'
6
-
7
1
  class String
8
2
 
9
3
  # Converts the string using Haml
10
4
  def haml(params={})
5
+ nanoc_require 'haml'
6
+
11
7
  options = (params[:haml_options] || {})
12
8
  options[:locals] = params[:assigns] unless params[:assigns].nil?
9
+
13
10
  Haml::Engine.new(self, options).to_html
14
- rescue NameError
15
- $stderr.puts 'ERROR: String#haml failed (Haml not installed?)' unless $quiet
16
- exit
17
11
  end
18
12
 
19
13
  end
@@ -1,21 +1,22 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- try_require 'liquid'
1
+ # Filter
6
2
 
7
3
  class String
8
4
 
9
- # Converts the string using Liquid
10
5
  def liquid(params={})
6
+ nanoc_require 'liquid'
7
+
11
8
  Liquid::Template.parse(self).render((params[:assigns] || {}).stringify_keys)
12
- rescue NameError
13
- $stderr.puts 'ERROR: String#liquid failed (Liquid not installed?)' unless $quiet
14
- exit
15
9
  end
16
10
 
17
11
  end
18
12
 
13
+ register_filter 'liquid' do |page, pages, config|
14
+ assigns = { :page => page, :pages => pages }
15
+ page.content.liquid(:assigns => assigns)
16
+ end
17
+
18
+ # Render tag
19
+
19
20
  begin
20
21
  class Nanoc::LiquidRenderTag < ::Liquid::Tag
21
22
  Syntax = /(['"])([^'"]+)\1/
@@ -44,8 +45,3 @@ begin
44
45
  Liquid::Template.register_tag('render', Nanoc::LiquidRenderTag)
45
46
  rescue NameError
46
47
  end
47
-
48
- register_filter 'liquid' do |page, pages, config|
49
- assigns = { :page => page, :pages => pages }
50
- page.content.liquid(:assigns => assigns)
51
- end
@@ -1,20 +1,10 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- require 'erb'
6
-
7
- try_require 'markaby'
8
-
9
1
  class String
10
2
 
11
3
  # Converts the string using Markaby
12
4
  # TODO perhaps add support for helpers
13
5
  def markaby(params={})
6
+ nanoc_require 'markaby'
14
7
  Markaby::Builder.new((params[:assigns] || {})).instance_eval(self).to_s
15
- rescue NameError
16
- $stderr.puts 'ERROR: String#markaby failed (Markaby not installed?)' unless $quiet
17
- exit
18
8
  end
19
9
 
20
10
  end
@@ -1,17 +1,9 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- try_require 'bluecloth'
6
-
7
1
  class String
8
2
 
9
- # Converts the string to HTML using BlueCloth/Markdown.
3
+ # Converts the string using Markdown
10
4
  def markdown
5
+ nanoc_require 'bluecloth'
11
6
  BlueCloth.new(self).to_html
12
- rescue NameError
13
- $stderr.puts 'ERROR: String#markdown failed: BlueCloth not installed' unless $quiet
14
- exit
15
7
  end
16
8
 
17
9
  end
@@ -1,14 +1,10 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- try_require 'rdoc/markup/simple_markup'
6
- try_require 'rdoc/markup/simple_markup/to_html'
7
-
8
1
  class String
9
2
 
10
3
  # Converts the string using RDoc
11
4
  def rdoc
5
+ nanoc_require 'rdoc/markup/simple_markup'
6
+ nanoc_require 'rdoc/markup/simple_markup/to_html'
7
+
12
8
  SM::SimpleMarkup.new.convert(self, SM::ToHtml.new)
13
9
  end
14
10
 
@@ -1,13 +1,8 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- try_require 'haml'
6
-
7
1
  class String
8
2
 
9
3
  # Converts the string using Sass
10
4
  def sass
5
+ nanoc_require 'haml'
11
6
  Sass::Engine.new(self).render
12
7
  end
13
8
 
@@ -1,17 +1,9 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- try_require 'rubypants'
6
-
7
1
  class String
8
2
 
9
3
  # Converts the string using RubyPants/SmartyPants
10
4
  def smartypants
5
+ nanoc_require 'rubypants'
11
6
  RubyPants.new(self).to_html
12
- rescue NameError
13
- $stderr.puts 'ERROR: String#smartypants failed (RubyPants not installed?)' unless $quiet
14
- exit
15
7
  end
16
8
 
17
9
  end
@@ -1,17 +1,9 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
-
5
- try_require 'redcloth'
6
-
7
1
  class String
8
2
 
9
3
  # Converts the string using RedCloth/Textile
10
4
  def textile
5
+ nanoc_require 'redcloth'
11
6
  RedCloth.new(self).to_html
12
- rescue NameError
13
- $stderr.puts 'ERROR: String#textile failed (RedCloth not installed?)' unless $quiet
14
- exit
15
7
  end
16
8
 
17
9
  end
data/lib/nanoc/page.rb CHANGED
@@ -1,64 +1,13 @@
1
- def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
-
3
- try_require 'rubygems'
4
- try_require 'liquid'
5
-
6
1
  module Nanoc
7
2
 
8
- # Page drop
9
-
10
- begin
11
- class PageDrop < ::Liquid::Drop
12
- def initialize(page)
13
- @page = page
14
- end
15
-
16
- def before_method(name)
17
- name == 'content' ? @page.content : @page.attributes[name.to_sym]
18
- end
19
- end
20
- rescue NameError
21
- class PageDrop
22
- def initialize(*args)
23
- $stderr.puts 'ERROR: Liquid not installed; cannot use Liquid in layouts.'
24
- exit
25
- end
26
- end
27
- end
28
-
29
- # Page proxy
30
-
31
- class PageProxy
32
- def initialize(page, params={})
33
- @page = page
34
- @do_compile = (params[:compile] != false)
35
- end
36
-
37
- def [](key)
38
- if key.to_sym == :content and @do_compile
39
- @page.content
40
- else
41
- if key.to_s.starts_with?('_')
42
- nil
43
- elsif key.to_s.ends_with?('?')
44
- @page.attributes[key.to_s[0..-2].to_sym]
45
- else
46
- @page.attributes[key]
47
- end
48
- end
49
- end
50
-
51
- def method_missing(method, *args)
52
- self[method]
53
- end
54
- end
55
-
56
- # Page
57
-
58
3
  class Page
59
4
 
60
- def initialize(hash={})
5
+ attr_accessor :stage, :is_filtered, :content_filename
6
+
7
+ def initialize(hash, compiler)
61
8
  @attributes = hash
9
+ @compiler = compiler
10
+ @stage = nil
62
11
  end
63
12
 
64
13
  def attributes
@@ -66,79 +15,159 @@ module Nanoc
66
15
  end
67
16
 
68
17
  def content
69
- compile
18
+ filter!
70
19
  @attributes[:content]
71
20
  end
72
21
 
22
+ def stage=(s) ; @stage = s ; puts 'NEW STAGE = ' + s.to_s ; end
23
+
73
24
  # Proxy/Liquid support
74
25
 
75
26
  def to_proxy(params={})
76
- PageProxy.new(self, :compile => params[:compile])
27
+ PageProxy.new(self, :filter => params[:filter])
77
28
  end
78
29
 
79
30
  def to_liquid
31
+ nanoc_require 'liquid'
80
32
  PageDrop.new(self)
81
33
  end
82
34
 
83
- # Compiling
35
+ # Helper methods
84
36
 
85
- def self.compile(pages)
86
- @@compilation_stack = []
87
- @@pages = pages
37
+ def path
38
+ if @attributes[:custom_path].nil?
39
+ @compiler.config[:output_dir] + @attributes[:path] +
40
+ @attributes[:filename] + '.' + @attributes[:extension]
41
+ else
42
+ @compiler.config[:output_dir] + @attributes[:custom_path]
43
+ end
44
+ end
88
45
 
89
- # Compile all pages
90
- pages.each { |page| page.compile }
46
+ def file
47
+ File.new(@content_filename)
91
48
  end
92
49
 
93
- def compile
50
+ def find_layout
51
+ if @attributes[:layout].nil?
52
+ { :type => :eruby, :content => "<%= @page.content %>" }
53
+ else
54
+ # Find all layouts
55
+ filenames = Dir["layouts/#{@attributes[:layout]}.*"]
56
+
57
+ # Reject backups
58
+ filenames.reject! { |f| f =~ /~$/ }
59
+
60
+ # Make sure there is only one content file
61
+ filenames.ensure_single('layout files', @attributes[:layout])
62
+
63
+ # Get the first (and only one)
64
+ filename = filenames[0]
65
+
66
+ { :type => Nanoc::Compiler::FILE_TYPES[File.extname(filename)], :content => File.read(filename) }
67
+ end
68
+ end
69
+
70
+ # Filtering
71
+
72
+ def filter!
73
+ # Get stack and list of other pages
74
+ stack = @compiler.stack
75
+ other_pages = @compiler.pages
76
+
94
77
  # Check for recursive call
95
- if @@compilation_stack.include?(self)
96
- # Print compilation stack
78
+ if stack.include?(self)
79
+ # Print stack
97
80
  unless $quiet
98
81
  $stderr.puts 'ERROR: Recursive call to page content.'
99
- print_compilation_stack
82
+ print_stack
100
83
  end
101
84
 
102
85
  exit
103
- # Compile if not yet compiled
104
- elsif @attributes[:content].nil?
105
- @@compilation_stack.pushing(self) do
86
+ end
87
+
88
+ # Get filters
89
+ if @stage == :pre
90
+ filters = @attributes[:filters_pre] || @attributes[:filters] || []
91
+ elsif @stage == :post
92
+ filters = @attributes[:filters_post] || []
93
+ else
94
+ puts '?????!!!!!!!!'
95
+ puts `pwd`
96
+ end
97
+
98
+ # Filter if not yet filtered
99
+ unless @is_filtered
100
+ stack.pushing(self) do
106
101
  # Read page
107
- content = File.read(@attributes[:_content_filename])
102
+ content = @attributes[:content] || File.read(@content_filename)
108
103
 
109
104
  begin
110
105
  # Get params
111
- page = self.to_proxy(:compile => false)
112
- pages = @@pages.map { |p| p.to_proxy }
106
+ page = self.to_proxy(:filter => false)
107
+ pages = other_pages.map { |p| p.to_proxy }
113
108
  config = $nanoc_compiler.config
114
109
 
115
110
  # Filter page
116
111
  @attributes[:content] = content
117
- @attributes[:filters].each do |filter_name|
112
+ filters.each do |filter_name|
118
113
  filter = $nanoc_compiler.filter_named(filter_name)
119
114
  if filter.nil?
120
115
  $stderr.puts 'WARNING: Unknown filter: ' + filter_name unless $quiet
121
116
  else
122
117
  @attributes[:content] = filter.call(page, pages, config)
118
+ @is_filtered = true
123
119
  end
124
120
  end
125
121
  rescue Exception => exception
126
- handle_exception(exception, "compiling page '#{@attributes[:_content_filename]}'")
122
+ handle_exception(exception, "filter page '#{@content_filename}'")
127
123
  end
128
124
  end
129
125
  end
130
126
  end
131
127
 
132
- def print_compilation_stack
133
- # Determine relevant part of compilation stack
134
- stack_begin = @@compilation_stack.index(self)
135
- stack_end = @@compilation_stack.size
136
- relevant_stack_part = @@compilation_stack.last(stack_end - stack_begin)
128
+ def layout!
129
+ # Get list of other pages
130
+ other_pages = @compiler.pages
131
+
132
+ # Find layout
133
+ layout = self.find_layout
134
+
135
+ # Build params
136
+ if layout[:type] == :liquid
137
+ public_page = self.to_liquid
138
+ public_pages = other_pages.map { |p| p.to_liquid }
139
+ else
140
+ public_page = self.to_proxy
141
+ public_pages = other_pages.map { |p| p.to_proxy }
142
+ end
143
+ params = { :assigns => { :page => public_page, :pages => public_pages } }
144
+ params[:haml_options] = (@attributes[:haml_options] || {}).symbolize_keys
145
+
146
+ # Layout
147
+ case layout[:type]
148
+ when :eruby
149
+ @attributes[:content] = layout[:content].eruby(params)
150
+ when :haml
151
+ @attributes[:content] = layout[:content].haml(params)
152
+ when :markaby
153
+ @attributes[:content] = layout[:content].markaby(params)
154
+ when :liquid
155
+ @attributes[:content] = layout[:content].liquid(params)
156
+ else
157
+ @attributes[:content] = nil
158
+ end
159
+ end
160
+
161
+ def print_stack
162
+ # Determine relevant part of stack
163
+ stack_begin = @compiler.stack.index(self)
164
+ stack_end = @compiler.stack.size
165
+ relevant_stack_part = @compiler.stack.last(stack_end - stack_begin)
137
166
 
138
- # Print relevant part of compilation stack
139
- $stderr.puts 'Page compilation stack:'
167
+ # Print relevant part of stack
168
+ $stderr.puts 'Page filter stack:'
140
169
  relevant_stack_part.each_with_index do |page, i|
141
- $stderr.puts "#{i} #{page.attributes[:_content_filename]}"
170
+ $stderr.puts "#{i} #{page.content_filename}"
142
171
  end
143
172
  end
144
173
 
@@ -0,0 +1,18 @@
1
+ try_require 'liquid'
2
+
3
+ module Nanoc
4
+
5
+ begin
6
+ class PageDrop < ::Liquid::Drop
7
+ def initialize(page)
8
+ @page = page
9
+ end
10
+
11
+ def before_method(name)
12
+ name == 'content' ? @page.content : @page.attributes[name.to_sym]
13
+ end
14
+ end
15
+ rescue NameError
16
+ end
17
+
18
+ end
@@ -0,0 +1,26 @@
1
+ module Nanoc
2
+ class PageProxy
3
+
4
+ def initialize(page, params={})
5
+ @page = page
6
+ @do_filter = (params[:filter] != false)
7
+ end
8
+
9
+ def [](key)
10
+ if key.to_sym == :content and @do_filter
11
+ @page.content
12
+ elsif key.to_sym == :file
13
+ @page.file
14
+ elsif key.to_s.ends_with?('?')
15
+ @page.attributes[key.to_s[0..-2].to_sym]
16
+ else
17
+ @page.attributes[key]
18
+ end
19
+ end
20
+
21
+ def method_missing(method, *args)
22
+ self[method]
23
+ end
24
+
25
+ end
26
+ end
data/lib/nanoc.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Nanoc
2
2
 
3
- VERSION = '1.5'
3
+ VERSION = '1.6'
4
4
 
5
5
  def self.ensure_in_site
6
6
  unless in_site?
@@ -27,6 +27,8 @@ module Nanoc
27
27
 
28
28
  end
29
29
 
30
+ require File.dirname(__FILE__) + '/nanoc/enhancements.rb'
31
+
30
32
  require File.dirname(__FILE__) + '/nanoc/creator.rb'
31
33
  require File.dirname(__FILE__) + '/nanoc/compiler.rb'
32
34
 
@@ -34,6 +36,7 @@ $nanoc_creator = Nanoc::Creator.new
34
36
  $nanoc_compiler = Nanoc::Compiler.new
35
37
 
36
38
  require File.dirname(__FILE__) + '/nanoc/core_ext.rb'
37
- require File.dirname(__FILE__) + '/nanoc/enhancements.rb'
38
39
  require File.dirname(__FILE__) + '/nanoc/filters.rb'
39
40
  require File.dirname(__FILE__) + '/nanoc/page.rb'
41
+ require File.dirname(__FILE__) + '/nanoc/page_drop.rb'
42
+ require File.dirname(__FILE__) + '/nanoc/page_proxy.rb'
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.5"
7
- date: 2007-09-10 00:00:00 +02:00
6
+ version: "1.6"
7
+ date: 2007-10-13 00:00:00 +02:00
8
8
  summary: a CMS that doesn't run on your server
9
9
  require_paths:
10
10
  - lib
@@ -56,6 +56,8 @@ files:
56
56
  - lib/nanoc/filters/textile_filter.rb
57
57
  - lib/nanoc/filters.rb
58
58
  - lib/nanoc/page.rb
59
+ - lib/nanoc/page_drop.rb
60
+ - lib/nanoc/page_proxy.rb
59
61
  - lib/nanoc.rb
60
62
  test_files: []
61
63