nanoc 1.4 → 1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +7 -0
- data/README +2 -24
- data/Rakefile +1 -1
- data/bin/nanoc +4 -4
- data/lib/nanoc.rb +13 -5
- data/lib/{compiler.rb → nanoc/compiler.rb} +80 -53
- data/lib/nanoc/core_ext.rb +1 -0
- data/lib/nanoc/core_ext/array.rb +17 -0
- data/lib/nanoc/core_ext/hash.rb +41 -0
- data/lib/nanoc/core_ext/string.rb +13 -0
- data/lib/nanoc/core_ext/yaml.rb +8 -0
- data/lib/{creator.rb → nanoc/creator.rb} +7 -7
- data/lib/nanoc/enhancements.rb +93 -0
- data/lib/nanoc/filters.rb +7 -0
- data/lib/nanoc/filters/eruby_filter.rb +44 -0
- data/lib/nanoc/filters/haml_filter.rb +24 -0
- data/lib/nanoc/filters/liquid_filter.rb +51 -0
- data/lib/nanoc/filters/markaby_filter.rb +25 -0
- data/lib/nanoc/filters/markdown_filter.rb +21 -0
- data/lib/nanoc/filters/rdoc_filter.rb +19 -0
- data/lib/nanoc/filters/sass_filter.rb +18 -0
- data/lib/nanoc/filters/smartypants_filter.rb +21 -0
- data/lib/nanoc/filters/textile_filter.rb +21 -0
- data/lib/nanoc/page.rb +147 -0
- metadata +25 -7
- data/lib/enhancements.rb +0 -277
- data/lib/page.rb +0 -91
data/ChangeLog
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
== 1.5
|
2
|
+
|
3
|
+
* Added support for custom filters
|
4
|
+
* Improved Liquid support -- Liquid is now a first-class nanoc citizen
|
5
|
+
* Deprecated assets -- use something like rsync instead
|
6
|
+
* Added eruby_engine option, which can be 'erb' or 'erubis'
|
7
|
+
|
1
8
|
== 1.4
|
2
9
|
|
3
10
|
* nanoc now supports ERB (as well as Erubis); Erubis no longer is a dependency
|
data/README
CHANGED
@@ -7,31 +7,9 @@ Markdown, etc.
|
|
7
7
|
|
8
8
|
== Documentation
|
9
9
|
|
10
|
-
nanoc has a web site at <http://stoneship.org
|
11
|
-
|
10
|
+
nanoc has a web site at <http://nanoc.stoneship.org/>, which contains a
|
11
|
+
"Getting Started" guide as well as a reference for nanoc.
|
12
12
|
|
13
13
|
== Contact
|
14
14
|
|
15
15
|
You can reach me at <denis.defreyne@stoneship.org>.
|
16
|
-
|
17
|
-
== Copyright
|
18
|
-
|
19
|
-
Copyright (c) 2007 Denis Defreyne
|
20
|
-
|
21
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
22
|
-
of this software and associated documentation files (the "Software"), to deal
|
23
|
-
in the Software without restriction, including without limitation the rights
|
24
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
25
|
-
copies of the Software, and to permit persons to whom the Software is
|
26
|
-
furnished to do so, subject to the following conditions:
|
27
|
-
|
28
|
-
The above copyright notice and this permission notice shall be included in all
|
29
|
-
copies or substantial portions of the Software.
|
30
|
-
|
31
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
32
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
33
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
34
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
35
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
36
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
37
|
-
SOFTWARE.
|
data/Rakefile
CHANGED
data/bin/nanoc
CHANGED
@@ -69,7 +69,7 @@ case command
|
|
69
69
|
$stderr.puts 'Usage: nanoc create_site [site_name]'
|
70
70
|
exit
|
71
71
|
end
|
72
|
-
|
72
|
+
$nanoc_creator.create_site(ARGV[1])
|
73
73
|
|
74
74
|
# Create page
|
75
75
|
when 'create_page', 'cp'
|
@@ -77,7 +77,7 @@ case command
|
|
77
77
|
$stderr.puts 'Usage: nanoc create_page [page_name]'
|
78
78
|
exit
|
79
79
|
end
|
80
|
-
|
80
|
+
$nanoc_creator.create_page(ARGV[1], :template => unprocessed_opts['--template'])
|
81
81
|
|
82
82
|
# Create template
|
83
83
|
when 'create_template', 'ct'
|
@@ -85,7 +85,7 @@ case command
|
|
85
85
|
$stderr.puts 'Usage: nanoc create_template [template_name]'
|
86
86
|
exit
|
87
87
|
end
|
88
|
-
|
88
|
+
$nanoc_creator.create_template(ARGV[1])
|
89
89
|
|
90
90
|
# Process site and generate output
|
91
91
|
when 'compile', 'compile_site', 'co'
|
@@ -93,7 +93,7 @@ case command
|
|
93
93
|
$stderr.puts 'Usage: nanoc compile'
|
94
94
|
exit
|
95
95
|
end
|
96
|
-
|
96
|
+
$nanoc_compiler.run
|
97
97
|
|
98
98
|
else
|
99
99
|
puts 'Unrecognised command \'' + command + '\''
|
data/lib/nanoc.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Nanoc
|
2
|
-
|
2
|
+
|
3
|
+
VERSION = '1.5'
|
3
4
|
|
4
5
|
def self.ensure_in_site
|
5
6
|
unless in_site?
|
@@ -23,9 +24,16 @@ module Nanoc
|
|
23
24
|
|
24
25
|
true
|
25
26
|
end
|
27
|
+
|
26
28
|
end
|
27
29
|
|
28
|
-
require File.dirname(__FILE__) + '/
|
29
|
-
require File.dirname(__FILE__) + '/
|
30
|
-
|
31
|
-
|
30
|
+
require File.dirname(__FILE__) + '/nanoc/creator.rb'
|
31
|
+
require File.dirname(__FILE__) + '/nanoc/compiler.rb'
|
32
|
+
|
33
|
+
$nanoc_creator = Nanoc::Creator.new
|
34
|
+
$nanoc_compiler = Nanoc::Compiler.new
|
35
|
+
|
36
|
+
require File.dirname(__FILE__) + '/nanoc/core_ext.rb'
|
37
|
+
require File.dirname(__FILE__) + '/nanoc/enhancements.rb'
|
38
|
+
require File.dirname(__FILE__) + '/nanoc/filters.rb'
|
39
|
+
require File.dirname(__FILE__) + '/nanoc/page.rb'
|
@@ -1,7 +1,10 @@
|
|
1
1
|
module Nanoc
|
2
2
|
class Compiler
|
3
3
|
|
4
|
-
DEFAULT_CONFIG
|
4
|
+
DEFAULT_CONFIG = {
|
5
|
+
:output_dir => 'output',
|
6
|
+
:eruby_engine => 'erb'
|
7
|
+
}
|
5
8
|
|
6
9
|
FILE_TYPES = {
|
7
10
|
'.erb' => :eruby,
|
@@ -21,13 +24,17 @@ module Nanoc
|
|
21
24
|
}
|
22
25
|
|
23
26
|
def initialize
|
27
|
+
@filters = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
# Make sure we're in a nanoc site
|
24
32
|
Nanoc.ensure_in_site
|
25
33
|
|
34
|
+
# Load some configuration stuff
|
26
35
|
@config = DEFAULT_CONFIG.merge(YAML.load_file_and_clean('config.yaml'))
|
27
36
|
@global_page = PAGE_DEFAULTS.merge(YAML.load_file_and_clean('meta.yaml'))
|
28
|
-
end
|
29
37
|
|
30
|
-
def run
|
31
38
|
# Require all Ruby source files in lib/
|
32
39
|
Dir['lib/*.rb'].each { |f| require f }
|
33
40
|
|
@@ -37,33 +44,56 @@ module Nanoc
|
|
37
44
|
# Copy assets to output directory
|
38
45
|
copy_assets
|
39
46
|
|
40
|
-
# Compile
|
41
|
-
pages =
|
47
|
+
# Compile and layout pages
|
48
|
+
pages = find_uncompiled_pages
|
49
|
+
pages = layout(compile(pages))
|
50
|
+
end
|
42
51
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
next if page.skip_output
|
52
|
+
def register_filter(name, &block)
|
53
|
+
@filters[name.to_sym] = block
|
54
|
+
end
|
47
55
|
|
48
|
-
|
49
|
-
|
50
|
-
|
56
|
+
def filter_named(name)
|
57
|
+
@filters[name.to_sym]
|
58
|
+
end
|
51
59
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
handle_exception(exception, "layouting page '#{p}' in layout '#{l}'")
|
58
|
-
end
|
60
|
+
def config
|
61
|
+
@config
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
59
65
|
|
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]
|
60
73
|
end
|
61
74
|
end
|
62
75
|
|
63
|
-
|
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
|
64
88
|
|
65
|
-
# Copies the contents of the assets directory into the output directory
|
66
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
|
+
|
67
97
|
# Remove existing assets
|
68
98
|
Dir['assets/*'].each do |f|
|
69
99
|
FileUtils.remove_entry_secure(f.sub('assets/', @config[:output_dir] + '/'), true)
|
@@ -75,8 +105,7 @@ module Nanoc
|
|
75
105
|
end
|
76
106
|
end
|
77
107
|
|
78
|
-
|
79
|
-
def uncompiled_pages
|
108
|
+
def find_uncompiled_pages
|
80
109
|
# Read all meta files
|
81
110
|
pages = Dir['content/**/meta.yaml'].collect do |filename|
|
82
111
|
# Read the meta file
|
@@ -101,30 +130,7 @@ module Nanoc
|
|
101
130
|
pages
|
102
131
|
end
|
103
132
|
|
104
|
-
|
105
|
-
def layout_for_page(a_page)
|
106
|
-
if a_page[:layout].nil?
|
107
|
-
{ :type => :eruby, :content => "<%= @page[:content] %>" }
|
108
|
-
else
|
109
|
-
filenames = Dir["layouts/#{a_page[:layout]}.*"]
|
110
|
-
filenames.ensure_single('layout files', a_page[:layout])
|
111
|
-
filename = filenames[0]
|
112
|
-
|
113
|
-
{ :type => FILE_TYPES[File.extname(filename)], :content => File.read(filename) }
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# Returns the path for the given page
|
118
|
-
def path_for_page(a_page)
|
119
|
-
if a_page[:custom_path].nil?
|
120
|
-
@config[:output_dir] + a_page[:path] + a_page[:filename] + '.' + a_page[:extension]
|
121
|
-
else
|
122
|
-
@config[:output_dir] + a_page[:custom_path]
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Compiles the given pages and returns the compiled pages
|
127
|
-
def compile_pages(pages)
|
133
|
+
def compile(pages)
|
128
134
|
# Create page objects from given pages
|
129
135
|
given_pages = []
|
130
136
|
pages.each { |page| given_pages << Page.new(page) }
|
@@ -135,15 +141,20 @@ module Nanoc
|
|
135
141
|
given_pages
|
136
142
|
end
|
137
143
|
|
138
|
-
|
139
|
-
def layouted_page(a_page, a_pages)
|
144
|
+
def layouted_page(page, pages)
|
140
145
|
# Find layout
|
141
|
-
layout = layout_for_page(
|
146
|
+
layout = layout_for_page(page)
|
142
147
|
|
143
148
|
# Build params
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
147
158
|
|
148
159
|
# Layout
|
149
160
|
case layout[:type]
|
@@ -162,5 +173,21 @@ module Nanoc
|
|
162
173
|
content
|
163
174
|
end
|
164
175
|
|
176
|
+
def layout(pages)
|
177
|
+
pages.reject { |page| page.attributes[:skip_output] }.each do |page|
|
178
|
+
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 }
|
184
|
+
rescue => exception
|
185
|
+
p = page.attributes[:_content_filename]
|
186
|
+
l = page.attributes[:layout]
|
187
|
+
handle_exception(exception, "layouting page '#{p}' in layout '#{l}'")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
165
192
|
end
|
166
193
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.join(File.dirname(__FILE__), 'core_ext', '*.rb')].each { |f| require f }
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Array
|
2
|
+
# Ensures that the array contains only one element
|
3
|
+
def ensure_single(a_noun, a_context)
|
4
|
+
if self.size != 1
|
5
|
+
$stderr.puts "ERROR: expected 1 #{a_noun}, found #{self.size} (#{a_context})" unless $quiet
|
6
|
+
exit
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Pushes the object on the stack, yields, and pops stack
|
11
|
+
def pushing(obj)
|
12
|
+
push(obj)
|
13
|
+
yield
|
14
|
+
ensure
|
15
|
+
pop
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Hash
|
2
|
+
# Cleans up the hash by performing the following operations:
|
3
|
+
# * Values with keys ending in _at and _on are converted into Times and
|
4
|
+
# Dates, respectively
|
5
|
+
# * All keys are converted to symbols
|
6
|
+
# * Value strings 'true', 'false', and 'none' are converted into
|
7
|
+
# true, false, and nil, respectively
|
8
|
+
def clean
|
9
|
+
symbolize_keys.inject({}) do |hash, (key, value)|
|
10
|
+
if key.to_s =~ /_on$/
|
11
|
+
hash.merge(key => Date.parse(value))
|
12
|
+
elsif key.to_s =~ /_at$/
|
13
|
+
hash.merge(key => Time.parse(value))
|
14
|
+
elsif value == 'true'
|
15
|
+
hash.merge(key => true)
|
16
|
+
elsif value == 'false'
|
17
|
+
hash.merge(key => false)
|
18
|
+
elsif value == 'none'
|
19
|
+
hash.merge(key => nil)
|
20
|
+
else
|
21
|
+
hash.merge(key => value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Converts all keys in the hash to symbols and returns the result
|
27
|
+
def symbolize_keys
|
28
|
+
inject({}) do |hash, (key, value)|
|
29
|
+
new_value = value.respond_to?(:symbolize_keys) ? value.symbolize_keys : value
|
30
|
+
hash.merge({ key.to_sym => new_value })
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Converts all keys in the hash to strings and returns the result
|
35
|
+
def stringify_keys
|
36
|
+
inject({}) do |hash, (key, value)|
|
37
|
+
new_value = value.respond_to?(:stringify_keys) ? value.stringify_keys : value
|
38
|
+
hash.merge({ key.to_s => new_value })
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -2,7 +2,7 @@ module Nanoc
|
|
2
2
|
|
3
3
|
class Creator
|
4
4
|
|
5
|
-
def
|
5
|
+
def create_site(a_sitename)
|
6
6
|
ensure_nonexistant(a_sitename)
|
7
7
|
|
8
8
|
FileManager.create_dir a_sitename do
|
@@ -38,10 +38,10 @@ module Nanoc
|
|
38
38
|
FileManager.create_file 'default.erb' do
|
39
39
|
"<html>\n" +
|
40
40
|
" <head>\n" +
|
41
|
-
" <title><%= @page
|
41
|
+
" <title><%= @page.title %></title>\n" +
|
42
42
|
" </head>\n" +
|
43
43
|
" <body>\n" +
|
44
|
-
"<%= @page
|
44
|
+
"<%= @page.content %>\n" +
|
45
45
|
" </body>\n" +
|
46
46
|
"</html>\n"
|
47
47
|
end
|
@@ -53,7 +53,7 @@ module Nanoc
|
|
53
53
|
"\# before nanoc starts compiling.\n" +
|
54
54
|
"\n" +
|
55
55
|
"def html_escape(a_string)\n" +
|
56
|
-
" a_string.gsub('&', '&').gsub('<', '<').gsub('>', '>').gsub('
|
56
|
+
" a_string.gsub('&', '&').gsub('<', '<').gsub('>', '>').gsub('\"', '"')\n" +
|
57
57
|
"end\n" +
|
58
58
|
"alias h html_escape\n"
|
59
59
|
end
|
@@ -95,7 +95,7 @@ module Nanoc
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
def
|
98
|
+
def create_page(a_pagename, a_params={})
|
99
99
|
Nanoc.ensure_in_site
|
100
100
|
ensure_nonexistant(File.join(['content', a_pagename]))
|
101
101
|
|
@@ -135,7 +135,7 @@ module Nanoc
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
-
def
|
138
|
+
def create_template(a_templatename)
|
139
139
|
Nanoc.ensure_in_site
|
140
140
|
ensure_nonexistant(File.join(['templates', a_templatename]))
|
141
141
|
|
@@ -156,7 +156,7 @@ module Nanoc
|
|
156
156
|
|
157
157
|
private
|
158
158
|
|
159
|
-
def
|
159
|
+
def ensure_nonexistant(filename)
|
160
160
|
if File.exist?(filename)
|
161
161
|
$stderr.puts "ERROR: A file or directory named #{filename} already exists." unless $quiet
|
162
162
|
exit
|