nanoc 2.0 → 2.1
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 +54 -0
- data/LICENSE +1 -1
- data/README +63 -3
- data/Rakefile +61 -14
- data/bin/nanoc +7 -199
- data/lib/nanoc/base/asset.rb +113 -0
- data/lib/nanoc/base/asset_defaults.rb +21 -0
- data/lib/nanoc/base/asset_rep.rb +277 -0
- data/lib/nanoc/base/binary_filter.rb +44 -0
- data/lib/nanoc/base/code.rb +41 -0
- data/lib/nanoc/base/compiler.rb +46 -34
- data/lib/nanoc/base/core_ext/hash.rb +51 -7
- data/lib/nanoc/base/core_ext/string.rb +8 -0
- data/lib/nanoc/base/data_source.rb +253 -20
- data/lib/nanoc/base/defaults.rb +30 -0
- data/lib/nanoc/base/enhancements.rb +9 -84
- data/lib/nanoc/base/filter.rb +109 -6
- data/lib/nanoc/base/layout.rb +91 -0
- data/lib/nanoc/base/notification_center.rb +66 -0
- data/lib/nanoc/base/page.rb +94 -121
- data/lib/nanoc/base/page_defaults.rb +20 -0
- data/lib/nanoc/base/page_rep.rb +318 -0
- data/lib/nanoc/base/plugin.rb +57 -9
- data/lib/nanoc/base/proxies/asset_proxy.rb +29 -0
- data/lib/nanoc/base/proxies/asset_rep_proxy.rb +26 -0
- data/lib/nanoc/base/proxies/layout_proxy.rb +25 -0
- data/lib/nanoc/base/proxies/page_proxy.rb +35 -0
- data/lib/nanoc/base/proxies/page_rep_proxy.rb +28 -0
- data/lib/nanoc/base/proxy.rb +37 -0
- data/lib/nanoc/base/router.rb +72 -0
- data/lib/nanoc/base/site.rb +220 -91
- data/lib/nanoc/base/template.rb +64 -0
- data/lib/nanoc/binary_filters/image_science_thumbnail.rb +28 -0
- data/lib/nanoc/cli/base.rb +219 -0
- data/lib/nanoc/cli/cli.rb +16 -0
- data/lib/nanoc/cli/command.rb +105 -0
- data/lib/nanoc/cli/commands/autocompile.rb +80 -0
- data/lib/nanoc/cli/commands/compile.rb +273 -0
- data/lib/nanoc/cli/commands/create_layout.rb +85 -0
- data/lib/nanoc/cli/commands/create_page.rb +85 -0
- data/lib/nanoc/cli/commands/create_site.rb +327 -0
- data/lib/nanoc/cli/commands/create_template.rb +76 -0
- data/lib/nanoc/cli/commands/help.rb +69 -0
- data/lib/nanoc/cli/commands/info.rb +114 -0
- data/lib/nanoc/cli/commands/switch.rb +141 -0
- data/lib/nanoc/cli/commands/update.rb +91 -0
- data/lib/nanoc/cli/ext.rb +37 -0
- data/lib/nanoc/cli/logger.rb +66 -0
- data/lib/nanoc/cli/option_parser.rb +168 -0
- data/lib/nanoc/cli.rb +1 -0
- data/lib/nanoc/data_sources/filesystem.rb +650 -215
- data/lib/nanoc/data_sources/filesystem_combined.rb +495 -0
- data/lib/nanoc/extra/auto_compiler.rb +265 -0
- data/lib/nanoc/extra/context.rb +22 -0
- data/lib/nanoc/extra/core_ext/hash.rb +54 -0
- data/lib/nanoc/extra/core_ext/time.rb +13 -0
- data/lib/nanoc/extra/file_proxy.rb +29 -0
- data/lib/nanoc/extra/vcs.rb +48 -0
- data/lib/nanoc/extra/vcses/bazaar.rb +21 -0
- data/lib/nanoc/extra/vcses/dummy.rb +20 -0
- data/lib/nanoc/extra/vcses/git.rb +21 -0
- data/lib/nanoc/extra/vcses/mercurial.rb +21 -0
- data/lib/nanoc/extra/vcses/subversion.rb +21 -0
- data/lib/nanoc/filters/bluecloth.rb +13 -0
- data/lib/nanoc/filters/erb.rb +6 -22
- data/lib/nanoc/filters/erubis.rb +14 -0
- data/lib/nanoc/filters/haml.rb +11 -6
- data/lib/nanoc/filters/markaby.rb +5 -5
- data/lib/nanoc/filters/maruku.rb +14 -0
- data/lib/nanoc/filters/old.rb +19 -0
- data/lib/nanoc/filters/rdiscount.rb +13 -0
- data/lib/nanoc/filters/rdoc.rb +5 -4
- data/lib/nanoc/filters/redcloth.rb +14 -0
- data/lib/nanoc/filters/rubypants.rb +14 -0
- data/lib/nanoc/filters/sass.rb +13 -0
- data/lib/nanoc/helpers/blogging.rb +170 -0
- data/lib/nanoc/helpers/capturing.rb +59 -0
- data/lib/nanoc/helpers/html_escape.rb +23 -0
- data/lib/nanoc/helpers/link_to.rb +69 -0
- data/lib/nanoc/helpers/render.rb +47 -0
- data/lib/nanoc/helpers/tagging.rb +52 -0
- data/lib/nanoc/helpers/xml_sitemap.rb +58 -0
- data/lib/nanoc/routers/default.rb +54 -0
- data/lib/nanoc/routers/no_dirs.rb +66 -0
- data/lib/nanoc/routers/versioned.rb +79 -0
- data/lib/nanoc.rb +83 -12
- metadata +144 -47
- data/lib/nanoc/base/auto_compiler.rb +0 -124
- data/lib/nanoc/base/layout_processor.rb +0 -33
- data/lib/nanoc/base/page_proxy.rb +0 -31
- data/lib/nanoc/base/plugin_manager.rb +0 -33
- data/lib/nanoc/data_sources/database.rb +0 -259
- data/lib/nanoc/data_sources/trivial.rb +0 -145
- data/lib/nanoc/filters/markdown.rb +0 -13
- data/lib/nanoc/filters/smartypants.rb +0 -13
- data/lib/nanoc/filters/textile.rb +0 -13
- data/lib/nanoc/layout_processors/erb.rb +0 -35
- data/lib/nanoc/layout_processors/haml.rb +0 -18
- data/lib/nanoc/layout_processors/markaby.rb +0 -16
data/lib/nanoc/base/site.rb
CHANGED
|
@@ -1,143 +1,272 @@
|
|
|
1
1
|
module Nanoc
|
|
2
|
+
|
|
3
|
+
# A Nanoc::Site is the in-memory representation of a nanoc site. It holds
|
|
4
|
+
# references to the following site data:
|
|
5
|
+
#
|
|
6
|
+
# * +pages+ is a list of Nanoc::Page instances representing pages
|
|
7
|
+
# * +assets+ is a list of Nanoc::Asset instances representing assets
|
|
8
|
+
# * +page_defaults+ is a Nanoc::PageDefaults instance representing page
|
|
9
|
+
# defaults
|
|
10
|
+
# * +asset_defaults+ is a Nanoc::AssetDefaults instance representing asset
|
|
11
|
+
# defaults
|
|
12
|
+
# * +layouts+ is a list of Nanoc::Layout instances representing layouts
|
|
13
|
+
# * +templates+ is a list of Nanoc::Template representing templates
|
|
14
|
+
# * +code+ is a Nanoc::Code instance representing custom site code
|
|
15
|
+
#
|
|
16
|
+
# In addition, each site has a +config+ hash which stores the site
|
|
17
|
+
# configuration. This configuration hash can have the following keys:
|
|
18
|
+
#
|
|
19
|
+
# +output_dir+:: The directory to which compiled pages and assets will be
|
|
20
|
+
# written. This path is relative to the current working
|
|
21
|
+
# directory, but can also be an absolute path.
|
|
22
|
+
#
|
|
23
|
+
# +data_source+:: The identifier of the data source that will be used for
|
|
24
|
+
# loading site data.
|
|
25
|
+
#
|
|
26
|
+
# +router+:: The identifier of the router that will be used for determining
|
|
27
|
+
# page and asset representation paths.
|
|
28
|
+
#
|
|
29
|
+
# +index_filenames+:: A list of filenames that will be stripped off full
|
|
30
|
+
# page and asset paths to create cleaner URLs (for
|
|
31
|
+
# example, '/about/' will be used instead of
|
|
32
|
+
# '/about/index.html'). The default value should be okay
|
|
33
|
+
# in most cases.
|
|
34
|
+
#
|
|
35
|
+
# A site also has several helper classes:
|
|
36
|
+
#
|
|
37
|
+
# * +router+ is a Nanoc::Router subclass instance used for determining page
|
|
38
|
+
# and asset paths.
|
|
39
|
+
# * +data_source+ is a Nanoc::DataSource subclass instance used for managing
|
|
40
|
+
# site data.
|
|
41
|
+
# * +compiler+ is a Nanoc::Compiler instance that compiles page and asset
|
|
42
|
+
# representations.
|
|
43
|
+
#
|
|
44
|
+
# The physical representation of a Nanoc::Site is usually a directory that
|
|
45
|
+
# contains a configuration file, site data, and some rake tasks. However,
|
|
46
|
+
# different frontends may store data differently. For example, a web-based
|
|
47
|
+
# frontend would probably store the configuration and the site content in a
|
|
48
|
+
# database, and would not have rake tasks at all.
|
|
2
49
|
class Site
|
|
3
50
|
|
|
51
|
+
# The default configuration for a site. A site's configuration overrides
|
|
52
|
+
# these options: when a Nanoc::Site is created with a configuration that
|
|
53
|
+
# lacks some options, the default value will be taken from
|
|
54
|
+
# +DEFAULT_CONFIG+.
|
|
4
55
|
DEFAULT_CONFIG = {
|
|
5
|
-
:output_dir
|
|
6
|
-
:
|
|
7
|
-
:
|
|
56
|
+
:output_dir => 'output',
|
|
57
|
+
:data_source => 'filesystem',
|
|
58
|
+
:router => 'default',
|
|
59
|
+
:index_filenames => [ 'index.html' ]
|
|
8
60
|
}
|
|
9
61
|
|
|
10
62
|
attr_reader :config
|
|
11
|
-
attr_reader :compiler, :data_source
|
|
12
|
-
attr_reader :
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def initialize
|
|
63
|
+
attr_reader :compiler, :data_source, :router
|
|
64
|
+
attr_reader :page_defaults, :asset_defaults
|
|
65
|
+
attr_reader :pages, :assets, :layouts, :templates, :code
|
|
66
|
+
|
|
67
|
+
# Returns a Nanoc::Site object for the site specified by the given
|
|
68
|
+
# configuration hash +config+.
|
|
69
|
+
#
|
|
70
|
+
# +config+:: A hash containing the site configuration.
|
|
71
|
+
def initialize(config)
|
|
21
72
|
# Load configuration
|
|
22
|
-
@config = DEFAULT_CONFIG.merge(
|
|
73
|
+
@config = DEFAULT_CONFIG.merge(config.clean)
|
|
23
74
|
|
|
24
75
|
# Create data source
|
|
25
|
-
@data_source_class =
|
|
26
|
-
|
|
76
|
+
@data_source_class = Nanoc::DataSource.named(@config[:data_source])
|
|
77
|
+
raise Nanoc::Errors::UnknownDataSourceError.new(@config[:data_source]) if @data_source_class.nil?
|
|
27
78
|
@data_source = @data_source_class.new(self)
|
|
28
79
|
|
|
29
80
|
# Create compiler
|
|
30
|
-
@compiler
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
81
|
+
@compiler = Compiler.new(self)
|
|
82
|
+
|
|
83
|
+
# Load code (necessary for custom routers)
|
|
84
|
+
load_code
|
|
85
|
+
|
|
86
|
+
# Create router
|
|
87
|
+
@router_class = Nanoc::Router.named(@config[:router])
|
|
88
|
+
raise Nanoc::Errors::UnknownRouterError.new(@config[:router]) if @router_class.nil?
|
|
89
|
+
@router = @router_class.new(self)
|
|
90
|
+
|
|
91
|
+
# Initialize data
|
|
92
|
+
@page_defaults = PageDefaults.new({})
|
|
93
|
+
@page_defaults.site = self
|
|
94
|
+
@asset_defaults = AssetDefaults.new({})
|
|
95
|
+
@asset_defaults.site = self
|
|
96
|
+
@pages = []
|
|
97
|
+
@assets = []
|
|
98
|
+
@layouts = []
|
|
99
|
+
@templates = []
|
|
35
100
|
end
|
|
36
101
|
|
|
102
|
+
# Loads the site data. This will query the Nanoc::DataSource associated
|
|
103
|
+
# with the site and fetch all site data. The site data is cached, so
|
|
104
|
+
# calling this method will not have any effect the second time, unless
|
|
105
|
+
# +force+ is true.
|
|
106
|
+
#
|
|
107
|
+
# +force+:: If true, will force load the site data even if it has been
|
|
108
|
+
# loaded before, to circumvent caching issues.
|
|
37
109
|
def load_data(force=false)
|
|
110
|
+
# Don't load data twice
|
|
111
|
+
@data_loaded ||= false
|
|
38
112
|
return if @data_loaded and !force
|
|
39
113
|
|
|
40
|
-
# Load data
|
|
114
|
+
# Load all data
|
|
41
115
|
@data_source.loading do
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
116
|
+
load_code(force)
|
|
117
|
+
load_page_defaults
|
|
118
|
+
load_pages
|
|
119
|
+
load_asset_defaults
|
|
120
|
+
load_assets
|
|
121
|
+
load_layouts
|
|
122
|
+
load_templates
|
|
47
123
|
end
|
|
48
124
|
|
|
125
|
+
# Set loaded
|
|
126
|
+
@data_loaded = true
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private
|
|
130
|
+
|
|
131
|
+
# Loads this site's code and executes it.
|
|
132
|
+
def load_code(force=false)
|
|
133
|
+
# Don't load code twice
|
|
134
|
+
@code_loaded ||= false
|
|
135
|
+
return if @code_loaded and !force
|
|
136
|
+
|
|
137
|
+
# Get code
|
|
138
|
+
@code = @data_source.code
|
|
139
|
+
|
|
140
|
+
# Fix code if outdated
|
|
141
|
+
if @code.is_a? String
|
|
142
|
+
warn_data_source('Code', 'code', false)
|
|
143
|
+
@code = Code.new(code)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Set site
|
|
147
|
+
@code.site = self
|
|
148
|
+
|
|
149
|
+
# Execute code
|
|
150
|
+
# FIXME This could be dangerous when using nanoc as a framework
|
|
151
|
+
# (a separate ruby process should probably be forked, and the code
|
|
152
|
+
# should only be loaded in this forked process)
|
|
153
|
+
@code.load
|
|
154
|
+
|
|
155
|
+
# Set loaded
|
|
156
|
+
@code_loaded = true
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Loads this site's page defaults.
|
|
160
|
+
def load_page_defaults
|
|
161
|
+
# Get page defaults
|
|
162
|
+
@page_defaults = @data_source.page_defaults
|
|
163
|
+
|
|
164
|
+
# Fix page defaults if outdated
|
|
165
|
+
if @page_defaults.is_a? Hash
|
|
166
|
+
warn_data_source('PageDefaults', 'page_defaults', false)
|
|
167
|
+
@page_defaults = PageDefaults.new(@page_defaults)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Set site
|
|
171
|
+
@page_defaults.site = self
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Loads this site's pages, sets up page child-parent relationships and
|
|
175
|
+
# builds each page's list of page representations.
|
|
176
|
+
def load_pages
|
|
177
|
+
# Get pages
|
|
178
|
+
@pages = @data_source.pages
|
|
179
|
+
|
|
180
|
+
# Fix pages if outdated
|
|
181
|
+
if @pages.any? { |p| p.is_a? Hash }
|
|
182
|
+
warn_data_source('Page', 'pages', true)
|
|
183
|
+
@pages.map! { |p| Page.new(p[:uncompiled_content], p, p[:path]) }
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Set site
|
|
187
|
+
@pages.each { |p| p.site = self }
|
|
188
|
+
|
|
49
189
|
# Setup child-parent links
|
|
50
190
|
@pages.each do |page|
|
|
51
|
-
# Skip pages without parent
|
|
52
|
-
next if page.path == '/'
|
|
53
|
-
|
|
54
191
|
# Get parent
|
|
55
192
|
parent_path = page.path.sub(/[^\/]+\/$/, '')
|
|
56
193
|
parent = @pages.find { |p| p.path == parent_path }
|
|
194
|
+
next if parent.nil? or page.path == '/'
|
|
57
195
|
|
|
58
196
|
# Link
|
|
59
197
|
page.parent = parent
|
|
60
198
|
parent.children << page
|
|
61
199
|
end
|
|
62
200
|
|
|
63
|
-
#
|
|
64
|
-
@
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Creating a new site on disk
|
|
68
|
-
|
|
69
|
-
def self.create(sitename)
|
|
70
|
-
# Check whether site exists
|
|
71
|
-
error "A site named '#{sitename}' already exists." if File.exist?(sitename)
|
|
72
|
-
|
|
73
|
-
FileUtils.mkdir_p sitename
|
|
74
|
-
in_dir([sitename]) do
|
|
75
|
-
# Create output
|
|
76
|
-
FileManager.create_dir 'output'
|
|
77
|
-
|
|
78
|
-
# Create config
|
|
79
|
-
FileManager.create_file 'config.yaml' do
|
|
80
|
-
"output_dir: \"output\"\n" +
|
|
81
|
-
"data_source: \"filesystem\"\n"
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Create rakefile
|
|
85
|
-
FileManager.create_file 'Rakefile' do
|
|
86
|
-
"Dir['tasks/**/*.rake'].sort.each { |rakefile| load rakefile }\n" +
|
|
87
|
-
"\n" +
|
|
88
|
-
"task :default do\n" +
|
|
89
|
-
" puts 'This is an example rake task.'\n" +
|
|
90
|
-
"end\n"
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Create tasks
|
|
94
|
-
FileManager.create_file 'tasks/default.rake' do
|
|
95
|
-
"task :example do\n" +
|
|
96
|
-
" puts 'This is an example rake task in tasks/default.rake.'\n" +
|
|
97
|
-
"end\n"
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# Setup site
|
|
101
|
-
Site.from_cwd.setup
|
|
102
|
-
end
|
|
201
|
+
# Build page representations
|
|
202
|
+
@pages.each { |p| p.build_reps }
|
|
103
203
|
end
|
|
104
204
|
|
|
105
|
-
#
|
|
205
|
+
# Loads this site's asset defaults.
|
|
206
|
+
def load_asset_defaults
|
|
207
|
+
# Get page defaults
|
|
208
|
+
@asset_defaults = @data_source.asset_defaults
|
|
106
209
|
|
|
107
|
-
|
|
108
|
-
@
|
|
210
|
+
# Set site
|
|
211
|
+
@asset_defaults.site = self
|
|
212
|
+
rescue NotImplementedError
|
|
213
|
+
@asset_defaults = AssetDefaults.new({})
|
|
214
|
+
@asset_defaults.site = self
|
|
109
215
|
end
|
|
110
216
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
217
|
+
# Loads this site's assets and builds each asset's list of asset
|
|
218
|
+
# representations.
|
|
219
|
+
def load_assets
|
|
220
|
+
# Get assets
|
|
221
|
+
@assets = @data_source.assets
|
|
114
222
|
|
|
115
|
-
|
|
223
|
+
# Set site
|
|
224
|
+
@assets.each { |a| a.site = self }
|
|
116
225
|
|
|
117
|
-
|
|
118
|
-
@
|
|
226
|
+
# Build asset representations
|
|
227
|
+
@assets.each { |p| p.build_reps }
|
|
228
|
+
rescue NotImplementedError
|
|
229
|
+
@assets = []
|
|
119
230
|
end
|
|
120
231
|
|
|
121
|
-
|
|
122
|
-
|
|
232
|
+
# Loads this site's layouts.
|
|
233
|
+
def load_layouts
|
|
234
|
+
# Get layouts
|
|
235
|
+
@layouts = @data_source.layouts
|
|
123
236
|
|
|
124
|
-
|
|
125
|
-
|
|
237
|
+
# Fix layouts if outdated
|
|
238
|
+
if @layouts.any? { |l| l.is_a? Hash }
|
|
239
|
+
warn_data_source('Layout', 'layouts', true)
|
|
240
|
+
@layouts.map! { |l| Layout.new(l[:content], l, l[:path] || l[:name]) }
|
|
241
|
+
end
|
|
126
242
|
|
|
127
|
-
|
|
243
|
+
# Set site
|
|
244
|
+
@layouts.each { |l| l.site = self }
|
|
128
245
|
end
|
|
129
246
|
|
|
130
|
-
|
|
131
|
-
|
|
247
|
+
# Loads this site's templates.
|
|
248
|
+
def load_templates
|
|
249
|
+
# Get templates
|
|
250
|
+
@templates = @data_source.templates
|
|
132
251
|
|
|
133
|
-
|
|
134
|
-
|
|
252
|
+
# Fix templates if outdated
|
|
253
|
+
if @templates.any? { |t| t.is_a? Hash }
|
|
254
|
+
warn_data_source('Template', 'templates', true)
|
|
255
|
+
@templates.map! { |t| Template.new(t[:content], t[:meta].is_a?(String) ? YAML.load(t[:meta]) : t[:meta], t[:name]) }
|
|
256
|
+
end
|
|
135
257
|
|
|
136
|
-
|
|
137
|
-
|
|
258
|
+
# Set site
|
|
259
|
+
@templates.each { |t| t.site = self }
|
|
260
|
+
end
|
|
138
261
|
|
|
139
|
-
|
|
262
|
+
# Raises a warning about an outdated data source method.
|
|
263
|
+
def warn_data_source(class_name, method_name, is_array)
|
|
264
|
+
warn(
|
|
265
|
+
"In nanoc 2.1, DataSource##{method_name} should return #{is_array ? 'an array of' : 'a' } Nanoc::#{class_name} object#{is_array ? 's' : ''}. Future versions will not support these outdated data sources.",
|
|
266
|
+
'DEPRECATION WARNING'
|
|
267
|
+
)
|
|
140
268
|
end
|
|
141
269
|
|
|
142
270
|
end
|
|
271
|
+
|
|
143
272
|
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Nanoc
|
|
2
|
+
|
|
3
|
+
# A Nanoc::Template represents a template, which can be used for creating
|
|
4
|
+
# new pages. Pages don't necessary have to be created using templates, but
|
|
5
|
+
# they can be useful for generating pages where you only have to "fill in
|
|
6
|
+
# the blanks".
|
|
7
|
+
class Template
|
|
8
|
+
|
|
9
|
+
# The Nanoc::Site this template belongs to.
|
|
10
|
+
attr_accessor :site
|
|
11
|
+
|
|
12
|
+
# The name of this template.
|
|
13
|
+
attr_reader :name
|
|
14
|
+
|
|
15
|
+
# The raw content a page created using this template will have.
|
|
16
|
+
attr_reader :page_content
|
|
17
|
+
|
|
18
|
+
# A hash containing the attributes a page created using this template will
|
|
19
|
+
# have.
|
|
20
|
+
attr_reader :page_attributes
|
|
21
|
+
|
|
22
|
+
# Creates a new template.
|
|
23
|
+
#
|
|
24
|
+
# +name+:: The name of this template.
|
|
25
|
+
#
|
|
26
|
+
# +page_content+:: The raw content a page created using this template will
|
|
27
|
+
# have.
|
|
28
|
+
#
|
|
29
|
+
# +page_attributes+:: A hash containing the attributes a page created
|
|
30
|
+
# using this template will have.
|
|
31
|
+
def initialize(page_content, page_attributes, name)
|
|
32
|
+
@page_content = page_content
|
|
33
|
+
@page_attributes = page_attributes.clean
|
|
34
|
+
@name = name
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Saves the template in the database, creating it if it doesn't exist yet
|
|
38
|
+
# or updating it if it already exists. Tells the site's data source to
|
|
39
|
+
# save the template.
|
|
40
|
+
def save
|
|
41
|
+
@site.data_source.loading do
|
|
42
|
+
@site.data_source.save_template(self)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Renames the template. Tells the site's data source to rename the
|
|
47
|
+
# template.
|
|
48
|
+
def move_to(new_name)
|
|
49
|
+
@site.data_source.loading do
|
|
50
|
+
@site.data_source.move_template(self, new_name)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Deletes the template. Tells the site's data source to delete the
|
|
55
|
+
# template.
|
|
56
|
+
def delete
|
|
57
|
+
@site.data_source.loading do
|
|
58
|
+
@site.data_source.delete_template(self)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Nanoc::BinaryFilters
|
|
2
|
+
|
|
3
|
+
class ImageScienceThumbnail < Nanoc::BinaryFilter
|
|
4
|
+
|
|
5
|
+
identifier :image_science_thumbnail
|
|
6
|
+
|
|
7
|
+
def run(file)
|
|
8
|
+
require 'image_science'
|
|
9
|
+
|
|
10
|
+
# Get temporary file path
|
|
11
|
+
tmp_file = Tempfile.new('filter')
|
|
12
|
+
tmp_path = tmp_file.path
|
|
13
|
+
tmp_file.close
|
|
14
|
+
|
|
15
|
+
# Create thumbnail
|
|
16
|
+
ImageScience.with_image(file.path) do |img|
|
|
17
|
+
img.thumbnail(@asset_rep.thumbnail_size || 150) do |thumbnail|
|
|
18
|
+
thumbnail.save(tmp_path)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Return thumbnail file
|
|
23
|
+
File.open(tmp_path)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
module Nanoc::CLI
|
|
2
|
+
|
|
3
|
+
# Nanoc::CLI::Base is the central class representing a commandline nanoc
|
|
4
|
+
# tool. It has a list of commands, and is linked to a specific nanoc site.
|
|
5
|
+
class Base
|
|
6
|
+
|
|
7
|
+
attr_reader :commands, :site
|
|
8
|
+
|
|
9
|
+
# Creates a new instance of the commandline nanoc tool.
|
|
10
|
+
def initialize
|
|
11
|
+
create_commands
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Parses the given commandline arguments and executes the requested
|
|
15
|
+
# command.
|
|
16
|
+
def run(args)
|
|
17
|
+
# Check arguments
|
|
18
|
+
if args.length == 0
|
|
19
|
+
@help_command.run([], [])
|
|
20
|
+
exit 1
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Find version or help options
|
|
24
|
+
if args.length == 1
|
|
25
|
+
# Parse arguments
|
|
26
|
+
begin
|
|
27
|
+
parsed_arguments = Nanoc::CLI::OptionParser.parse(args[0..1], global_option_definitions)
|
|
28
|
+
rescue Nanoc::CLI::OptionParser::IllegalOptionError => e
|
|
29
|
+
$stderr.puts "illegal option -- #{e}"
|
|
30
|
+
exit 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Handle version option
|
|
34
|
+
if parsed_arguments[:options].has_key?(:version)
|
|
35
|
+
puts "nanoc #{Nanoc::VERSION} (c) 2007-2008 Denis Defreyne."
|
|
36
|
+
exit 1
|
|
37
|
+
# Handle help option
|
|
38
|
+
elsif parsed_arguments[:options].has_key?(:help)
|
|
39
|
+
show_help
|
|
40
|
+
exit 1
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Find command
|
|
45
|
+
command = command_named(args[0])
|
|
46
|
+
|
|
47
|
+
# Get extended option definitions (with help)
|
|
48
|
+
extended_option_definitions = command.option_definitions + [
|
|
49
|
+
# --help
|
|
50
|
+
{
|
|
51
|
+
:long => 'help', :short => 'h', :argument => :forbidden,
|
|
52
|
+
:desc => 'show this help message and quit'
|
|
53
|
+
},
|
|
54
|
+
# --verbose
|
|
55
|
+
{
|
|
56
|
+
:long => 'verbose', :short => 'V', :argument => :forbidden,
|
|
57
|
+
:desc => 'enable more detailed output'
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
# Parse arguments
|
|
62
|
+
begin
|
|
63
|
+
parsed_arguments = Nanoc::CLI::OptionParser.parse(args[1..-1], extended_option_definitions)
|
|
64
|
+
rescue Nanoc::CLI::OptionParser::IllegalOptionError => e
|
|
65
|
+
$stderr.puts "illegal option -- #{e}"
|
|
66
|
+
exit 1
|
|
67
|
+
rescue Nanoc::CLI::OptionParser::OptionRequiresAnArgumentError => e
|
|
68
|
+
$stderr.puts "option requires an argument -- #{e}"
|
|
69
|
+
exit 1
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Check help option
|
|
73
|
+
if parsed_arguments[:options].has_key?(:help)
|
|
74
|
+
show_help(command)
|
|
75
|
+
exit 1
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Check verbose option
|
|
79
|
+
if parsed_arguments[:options].has_key?(:verbose)
|
|
80
|
+
Nanoc::CLI::Logger.instance.level = :low
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Find and run command
|
|
84
|
+
command.run(parsed_arguments[:options], parsed_arguments[:arguments])
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Returns the command with the given name.
|
|
88
|
+
def command_named(name)
|
|
89
|
+
# Find by exact name or alias
|
|
90
|
+
command = @commands.find { |c| c.name == name or c.aliases.include?(name) }
|
|
91
|
+
return command unless command.nil?
|
|
92
|
+
|
|
93
|
+
# Find by approximation
|
|
94
|
+
commands = @commands.select { |c| c.name[0, name.length] == name }
|
|
95
|
+
if commands.length > 1
|
|
96
|
+
$stderr.puts "nanoc: '#{name}' is ambiguous:"
|
|
97
|
+
$stderr.puts " #{commands.map { |c| c.name }.join(' ') }"
|
|
98
|
+
exit 1
|
|
99
|
+
elsif commands.length == 0
|
|
100
|
+
$stderr.puts "nanoc: unknown command '#{name}'\n"
|
|
101
|
+
show_help
|
|
102
|
+
exit 1
|
|
103
|
+
else
|
|
104
|
+
return commands[0]
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Shows the help text for the given command, or shows the general help
|
|
109
|
+
# text if no command is given.
|
|
110
|
+
def show_help(command=nil)
|
|
111
|
+
if command.nil?
|
|
112
|
+
@help_command.run([], [])
|
|
113
|
+
else
|
|
114
|
+
@help_command.run([], [ command.name ])
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Helper function which can be called when a command is executed that
|
|
119
|
+
# requires a site, such as the compile command.
|
|
120
|
+
def require_site
|
|
121
|
+
if site.nil?
|
|
122
|
+
$stderr.puts 'The current working directory does not seem to be a ' +
|
|
123
|
+
'valid/complete nanoc site directory; aborting.'
|
|
124
|
+
exit 1
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Gets the site (Nanoc::Site) in the current directory and loads its data.
|
|
129
|
+
def site
|
|
130
|
+
# Load site if possible
|
|
131
|
+
if File.file?('config.yaml') and @site.nil?
|
|
132
|
+
begin
|
|
133
|
+
@site = Nanoc::Site.new(YAML.load_file('config.yaml'))
|
|
134
|
+
@site.load_data
|
|
135
|
+
rescue Nanoc::Errors::UnknownDataSourceError => e
|
|
136
|
+
$stderr.puts "Unknown data source: #{e}"
|
|
137
|
+
exit 1
|
|
138
|
+
rescue Nanoc::Errors::UnknownRouterError => e
|
|
139
|
+
$stderr.puts "Unknown router: #{e}"
|
|
140
|
+
exit 1
|
|
141
|
+
rescue Exception => e
|
|
142
|
+
$stderr.puts "ERROR: An exception occured while loading this site."
|
|
143
|
+
$stderr.puts
|
|
144
|
+
$stderr.puts "If you think this is a bug in nanoc, please do report it at " +
|
|
145
|
+
"<http://nanoc.stoneship.org/trac/newticket> -- thanks!"
|
|
146
|
+
$stderr.puts
|
|
147
|
+
$stderr.puts 'Message:'
|
|
148
|
+
$stderr.puts ' ' + e.message
|
|
149
|
+
$stderr.puts
|
|
150
|
+
$stderr.puts 'Backtrace:'
|
|
151
|
+
$stderr.puts e.backtrace.map { |t| ' - ' + t }.join("\n")
|
|
152
|
+
exit 1
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
@site
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Sets the data source's VCS to the VCS with the given name. Does nothing
|
|
160
|
+
# when the site's data source does not support VCSes (i.e. does not
|
|
161
|
+
# implement #vcs=).
|
|
162
|
+
def set_vcs(vcs_name)
|
|
163
|
+
# Skip if not possible
|
|
164
|
+
return if vcs_name.nil?
|
|
165
|
+
return if site.nil? or !site.data_source.respond_to?(:vcs=)
|
|
166
|
+
|
|
167
|
+
# Find VCS
|
|
168
|
+
vcs_class = Nanoc::Extra::VCS.named(vcs_name.to_sym)
|
|
169
|
+
if vcs_class.nil?
|
|
170
|
+
$stderr.puts "A VCS named #{vcs_name} was not found; aborting."
|
|
171
|
+
exit 1
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Set VCS
|
|
175
|
+
site.data_source.vcs = vcs_class.new
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Returns the list of global option definitionss.
|
|
179
|
+
def global_option_definitions
|
|
180
|
+
[
|
|
181
|
+
{
|
|
182
|
+
:long => 'help', :short => 'h', :argument => :forbidden,
|
|
183
|
+
:desc => 'show this help message and quit'
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
:long => 'version', :short => 'v', :argument => :forbidden,
|
|
187
|
+
:desc => 'show version information and quit'
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
protected
|
|
193
|
+
|
|
194
|
+
def create_commands
|
|
195
|
+
@commands = []
|
|
196
|
+
|
|
197
|
+
# Find all command classes
|
|
198
|
+
command_classes = []
|
|
199
|
+
ObjectSpace.each_object(Class) do |klass|
|
|
200
|
+
command_classes << klass if klass < Nanoc::CLI::Command
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Create commands
|
|
204
|
+
command_classes.each do |klass|
|
|
205
|
+
if klass.to_s == 'Nanoc::CLI::HelpCommand'
|
|
206
|
+
@help_command = HelpCommand.new
|
|
207
|
+
@commands << @help_command
|
|
208
|
+
else
|
|
209
|
+
@commands << klass.new
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Set base
|
|
214
|
+
@commands.each { |c| c.base = self }
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Nanoc::CLI # :nodoc:
|
|
2
|
+
end
|
|
3
|
+
|
|
4
|
+
# Load extensions
|
|
5
|
+
Nanoc.load('cli', 'ext.rb')
|
|
6
|
+
Nanoc.load('cli', 'option_parser.rb')
|
|
7
|
+
|
|
8
|
+
# Load logger
|
|
9
|
+
Nanoc.load('cli', 'logger.rb')
|
|
10
|
+
|
|
11
|
+
# Load commands
|
|
12
|
+
Nanoc.load('cli', 'command.rb')
|
|
13
|
+
Nanoc.load('cli', 'commands', '*.rb')
|
|
14
|
+
|
|
15
|
+
# Load base
|
|
16
|
+
Nanoc.load('cli', 'base.rb')
|