nanoc 1.4 → 1.5
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.
- 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
|