nanoc2 2.2.3
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 +3 -0
- data/LICENSE +19 -0
- data/README +75 -0
- data/Rakefile +76 -0
- data/bin/nanoc2 +26 -0
- data/lib/nanoc2.rb +73 -0
- data/lib/nanoc2/base.rb +26 -0
- data/lib/nanoc2/base/asset.rb +117 -0
- data/lib/nanoc2/base/asset_defaults.rb +21 -0
- data/lib/nanoc2/base/asset_rep.rb +282 -0
- data/lib/nanoc2/base/binary_filter.rb +44 -0
- data/lib/nanoc2/base/code.rb +41 -0
- data/lib/nanoc2/base/compiler.rb +67 -0
- data/lib/nanoc2/base/core_ext.rb +2 -0
- data/lib/nanoc2/base/core_ext/hash.rb +78 -0
- data/lib/nanoc2/base/core_ext/string.rb +8 -0
- data/lib/nanoc2/base/data_source.rb +286 -0
- data/lib/nanoc2/base/defaults.rb +30 -0
- data/lib/nanoc2/base/filter.rb +93 -0
- data/lib/nanoc2/base/layout.rb +91 -0
- data/lib/nanoc2/base/notification_center.rb +66 -0
- data/lib/nanoc2/base/page.rb +132 -0
- data/lib/nanoc2/base/page_defaults.rb +20 -0
- data/lib/nanoc2/base/page_rep.rb +324 -0
- data/lib/nanoc2/base/plugin.rb +71 -0
- data/lib/nanoc2/base/proxies.rb +5 -0
- data/lib/nanoc2/base/proxies/asset_proxy.rb +29 -0
- data/lib/nanoc2/base/proxies/asset_rep_proxy.rb +26 -0
- data/lib/nanoc2/base/proxies/layout_proxy.rb +25 -0
- data/lib/nanoc2/base/proxies/page_proxy.rb +35 -0
- data/lib/nanoc2/base/proxies/page_rep_proxy.rb +28 -0
- data/lib/nanoc2/base/proxy.rb +37 -0
- data/lib/nanoc2/base/router.rb +72 -0
- data/lib/nanoc2/base/site.rb +274 -0
- data/lib/nanoc2/base/template.rb +64 -0
- data/lib/nanoc2/binary_filters.rb +1 -0
- data/lib/nanoc2/binary_filters/image_science_thumbnail.rb +28 -0
- data/lib/nanoc2/cli.rb +9 -0
- data/lib/nanoc2/cli/base.rb +132 -0
- data/lib/nanoc2/cli/commands.rb +10 -0
- data/lib/nanoc2/cli/commands/autocompile.rb +80 -0
- data/lib/nanoc2/cli/commands/compile.rb +312 -0
- data/lib/nanoc2/cli/commands/create_layout.rb +85 -0
- data/lib/nanoc2/cli/commands/create_page.rb +85 -0
- data/lib/nanoc2/cli/commands/create_site.rb +323 -0
- data/lib/nanoc2/cli/commands/create_template.rb +76 -0
- data/lib/nanoc2/cli/commands/help.rb +69 -0
- data/lib/nanoc2/cli/commands/info.rb +125 -0
- data/lib/nanoc2/cli/commands/switch.rb +141 -0
- data/lib/nanoc2/cli/commands/update.rb +91 -0
- data/lib/nanoc2/cli/logger.rb +72 -0
- data/lib/nanoc2/data_sources.rb +2 -0
- data/lib/nanoc2/data_sources/filesystem.rb +707 -0
- data/lib/nanoc2/data_sources/filesystem_combined.rb +495 -0
- data/lib/nanoc2/extra.rb +6 -0
- data/lib/nanoc2/extra/auto_compiler.rb +285 -0
- data/lib/nanoc2/extra/context.rb +22 -0
- data/lib/nanoc2/extra/core_ext.rb +2 -0
- data/lib/nanoc2/extra/core_ext/hash.rb +54 -0
- data/lib/nanoc2/extra/core_ext/time.rb +13 -0
- data/lib/nanoc2/extra/file_proxy.rb +29 -0
- data/lib/nanoc2/extra/vcs.rb +48 -0
- data/lib/nanoc2/extra/vcses.rb +5 -0
- data/lib/nanoc2/extra/vcses/bazaar.rb +21 -0
- data/lib/nanoc2/extra/vcses/dummy.rb +20 -0
- data/lib/nanoc2/extra/vcses/git.rb +21 -0
- data/lib/nanoc2/extra/vcses/mercurial.rb +21 -0
- data/lib/nanoc2/extra/vcses/subversion.rb +21 -0
- data/lib/nanoc2/filters.rb +16 -0
- data/lib/nanoc2/filters/bluecloth.rb +13 -0
- data/lib/nanoc2/filters/erb.rb +19 -0
- data/lib/nanoc2/filters/erubis.rb +14 -0
- data/lib/nanoc2/filters/haml.rb +21 -0
- data/lib/nanoc2/filters/markaby.rb +14 -0
- data/lib/nanoc2/filters/maruku.rb +14 -0
- data/lib/nanoc2/filters/old.rb +19 -0
- data/lib/nanoc2/filters/rainpress.rb +13 -0
- data/lib/nanoc2/filters/rdiscount.rb +13 -0
- data/lib/nanoc2/filters/rdoc.rb +23 -0
- data/lib/nanoc2/filters/redcloth.rb +14 -0
- data/lib/nanoc2/filters/relativize_paths.rb +16 -0
- data/lib/nanoc2/filters/relativize_paths_in_css.rb +16 -0
- data/lib/nanoc2/filters/relativize_paths_in_html.rb +16 -0
- data/lib/nanoc2/filters/rubypants.rb +14 -0
- data/lib/nanoc2/filters/sass.rb +18 -0
- data/lib/nanoc2/helpers.rb +9 -0
- data/lib/nanoc2/helpers/blogging.rb +217 -0
- data/lib/nanoc2/helpers/capturing.rb +63 -0
- data/lib/nanoc2/helpers/filtering.rb +54 -0
- data/lib/nanoc2/helpers/html_escape.rb +25 -0
- data/lib/nanoc2/helpers/link_to.rb +113 -0
- data/lib/nanoc2/helpers/render.rb +49 -0
- data/lib/nanoc2/helpers/tagging.rb +56 -0
- data/lib/nanoc2/helpers/text.rb +38 -0
- data/lib/nanoc2/helpers/xml_sitemap.rb +63 -0
- data/lib/nanoc2/routers.rb +3 -0
- data/lib/nanoc2/routers/default.rb +54 -0
- data/lib/nanoc2/routers/no_dirs.rb +66 -0
- data/lib/nanoc2/routers/versioned.rb +79 -0
- metadata +185 -0
@@ -0,0 +1,495 @@
|
|
1
|
+
module Nanoc2::DataSources
|
2
|
+
|
3
|
+
# = Pages
|
4
|
+
#
|
5
|
+
# The filesystem data source stores its pages in nested directories. A page
|
6
|
+
# is represented by a single file. The root directory is the 'content'
|
7
|
+
# directory.
|
8
|
+
#
|
9
|
+
# The metadata for a page is embedded into the file itself. It is stored at
|
10
|
+
# the top of the file, between '-----' (five dashes) separators. For
|
11
|
+
# example:
|
12
|
+
#
|
13
|
+
# -----
|
14
|
+
# filters_pre: [ 'redcloth' ]
|
15
|
+
# -----
|
16
|
+
# h1. Hello!
|
17
|
+
#
|
18
|
+
# The path of a page is determined as follows. A file with an 'index.*'
|
19
|
+
# filename, such as 'index.txt', will have the filesystem path with the
|
20
|
+
# 'index.*' part stripped as a path. For example, 'foo/bar/index.html' will
|
21
|
+
# have '/foo/bar/' as path.
|
22
|
+
#
|
23
|
+
# A file with a filename not starting with 'index.', such as 'foo.html',
|
24
|
+
# will have a path ending in 'foo/'. For example, 'foo/bar.html' will have
|
25
|
+
# '/foo/bar/' as path.
|
26
|
+
#
|
27
|
+
# Note that it is possible for two different, separate files to have the
|
28
|
+
# same path. It is therefore recommended to avoid such situations.
|
29
|
+
#
|
30
|
+
# Some more examples:
|
31
|
+
#
|
32
|
+
# content/index.html --> /
|
33
|
+
# content/foo.html --> /foo/
|
34
|
+
# content/foo/index.html --> /foo/
|
35
|
+
# content/foo/bar.html --> /foo/bar/
|
36
|
+
# content/foo/bar/index.html --> /foo/bar/
|
37
|
+
#
|
38
|
+
# File extensions are ignored by nanoc. The file extension does not
|
39
|
+
# determine the filters to run on it; the metadata in the file defines the
|
40
|
+
# list of filters.
|
41
|
+
#
|
42
|
+
# = Page defaults
|
43
|
+
#
|
44
|
+
# The page defaults are loaded from a YAML-formatted file named
|
45
|
+
# 'page_defaults.yaml' at the top level of the nanoc site directory. For
|
46
|
+
# backward compatibility, the file can also be named 'meta.yaml'.
|
47
|
+
#
|
48
|
+
# = Assets
|
49
|
+
#
|
50
|
+
# Assets are stored in a way similar to pages. The attributes are merged
|
51
|
+
# into the asset. This does mean, however, that only textual assets are
|
52
|
+
# supported, as there is no way to embed attributes in binary assets.
|
53
|
+
#
|
54
|
+
# = Asset defaults
|
55
|
+
#
|
56
|
+
# The asset defaults are stored similar to the way page defaults are stored,
|
57
|
+
# except that the asset defaults file is named 'asset_defaults.yaml'
|
58
|
+
# instead.
|
59
|
+
#
|
60
|
+
# = Layouts
|
61
|
+
#
|
62
|
+
# Layouts are stored as files in the 'layouts' directory. Similar to pages,
|
63
|
+
# each layout consists of a metadata part and a content part, separated by
|
64
|
+
# '-----'.
|
65
|
+
#
|
66
|
+
# = Templates
|
67
|
+
#
|
68
|
+
# Templates are located in the 'templates' directory. Templates are, just
|
69
|
+
# like pages, files consisting of a metadata part and a content part,
|
70
|
+
# separated by '-----'.
|
71
|
+
#
|
72
|
+
# = Code
|
73
|
+
#
|
74
|
+
# Code is stored in '.rb' files in the 'lib' directory. Code can reside in
|
75
|
+
# sub-directories.
|
76
|
+
class FilesystemCombined < Nanoc2::DataSource
|
77
|
+
|
78
|
+
PAGE_DEFAULTS_FILENAME = 'page_defaults.yaml'
|
79
|
+
PAGE_DEFAULTS_FILENAME_OLD = 'meta.yaml'
|
80
|
+
ASSET_DEFAULTS_FILENAME = 'asset_defaults.yaml'
|
81
|
+
|
82
|
+
########## Attributes ##########
|
83
|
+
|
84
|
+
identifier :filesystem_combined
|
85
|
+
|
86
|
+
########## VCSes ##########
|
87
|
+
|
88
|
+
attr_accessor :vcs
|
89
|
+
|
90
|
+
def vcs
|
91
|
+
@vcs ||= Nanoc2::Extra::VCSes::Dummy.new
|
92
|
+
end
|
93
|
+
|
94
|
+
########## Preparation ##########
|
95
|
+
|
96
|
+
def up # :nodoc:
|
97
|
+
end
|
98
|
+
|
99
|
+
def down # :nodoc:
|
100
|
+
end
|
101
|
+
|
102
|
+
def setup # :nodoc:
|
103
|
+
# Create directories
|
104
|
+
%w( assets content templates layouts lib ).each do |dir|
|
105
|
+
FileUtils.mkdir_p(dir)
|
106
|
+
vcs.add(dir)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def destroy # :nodoc:
|
111
|
+
# Remove files
|
112
|
+
vcs.remove(ASSET_DEFAULTS_FILENAME) if File.file?(ASSET_DEFAULTS_FILENAME)
|
113
|
+
vcs.remove(PAGE_DEFAULTS_FILENAME) if File.file?(PAGE_DEFAULTS_FILENAME)
|
114
|
+
vcs.remove(PAGE_DEFAULTS_FILENAME_OLD) if File.file?(PAGE_DEFAULTS_FILENAME_OLD)
|
115
|
+
|
116
|
+
# Remove directories
|
117
|
+
vcs.remove('assets')
|
118
|
+
vcs.remove('content')
|
119
|
+
vcs.remove('templates')
|
120
|
+
vcs.remove('layouts')
|
121
|
+
vcs.remove('lib')
|
122
|
+
end
|
123
|
+
|
124
|
+
########## Pages ##########
|
125
|
+
|
126
|
+
def pages # :nodoc:
|
127
|
+
files('content', true).map do |filename|
|
128
|
+
# Read and parse data
|
129
|
+
meta, content = *parse_file(filename, 'page')
|
130
|
+
|
131
|
+
# Skip drafts
|
132
|
+
return nil if meta[:is_draft]
|
133
|
+
|
134
|
+
# Get attributes
|
135
|
+
attributes = meta.merge(:file => Nanoc2::Extra::FileProxy.new(filename))
|
136
|
+
|
137
|
+
# Get actual path
|
138
|
+
if filename =~ /\/index\.[^\/]+$/
|
139
|
+
path = filename.sub(/^content/, '').sub(/index\.[^\/]+$/, '') + '/'
|
140
|
+
else
|
141
|
+
path = filename.sub(/^content/, '').sub(/\.[^\/]+$/, '') + '/'
|
142
|
+
end
|
143
|
+
|
144
|
+
# Get mtime
|
145
|
+
mtime = File.stat(filename).mtime
|
146
|
+
|
147
|
+
# Build page
|
148
|
+
Nanoc2::Page.new(content, attributes, path, mtime)
|
149
|
+
end.compact
|
150
|
+
end
|
151
|
+
|
152
|
+
def save_page(page) # :nodoc:
|
153
|
+
# Find page path
|
154
|
+
if page.path == '/'
|
155
|
+
paths = Dir['content/index.*']
|
156
|
+
path = paths[0] || 'content/index.html'
|
157
|
+
parent_path = '/'
|
158
|
+
else
|
159
|
+
last_path_component = page.path.split('/')[-1]
|
160
|
+
paths_best = Dir['content' + page.path[0..-2] + '.*']
|
161
|
+
paths_worst = Dir['content' + page.path + 'index.*']
|
162
|
+
path_default = 'content' + page.path[0..-2] + '.html'
|
163
|
+
path = paths_best[0] || paths_worst[0] || path_default
|
164
|
+
parent_path = '/' + File.join(page.path.split('/')[0..-2])
|
165
|
+
end
|
166
|
+
|
167
|
+
# Notify
|
168
|
+
if File.file?(path)
|
169
|
+
created = false
|
170
|
+
Nanoc2::NotificationCenter.post(:file_updated, path)
|
171
|
+
else
|
172
|
+
created = true
|
173
|
+
Nanoc2::NotificationCenter.post(:file_created, path)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Write page
|
177
|
+
FileUtils.mkdir_p('content' + parent_path)
|
178
|
+
File.open(path, 'w') do |io|
|
179
|
+
io.write("-----\n")
|
180
|
+
io.write(page.attributes.to_split_yaml + "\n")
|
181
|
+
io.write("-----\n")
|
182
|
+
io.write(page.content)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Add to working copy if possible
|
186
|
+
vcs.add(path) if created
|
187
|
+
end
|
188
|
+
|
189
|
+
def move_page(page, new_path) # :nodoc:
|
190
|
+
# TODO implement
|
191
|
+
end
|
192
|
+
|
193
|
+
def delete_page(page) # :nodoc:
|
194
|
+
# TODO implement
|
195
|
+
end
|
196
|
+
|
197
|
+
########## Assets ##########
|
198
|
+
|
199
|
+
def assets # :nodoc:
|
200
|
+
files('assets', true).map do |filename|
|
201
|
+
# Read and parse data
|
202
|
+
meta, content = *parse_file(filename, 'asset')
|
203
|
+
|
204
|
+
# Skip drafts
|
205
|
+
return nil if meta[:is_draft]
|
206
|
+
|
207
|
+
# Get attributes
|
208
|
+
attributes = { 'extension' => File.extname(filename)[1..-1] }.merge(meta)
|
209
|
+
|
210
|
+
# Get actual path
|
211
|
+
if filename =~ /\/index\.[^\/]+$/
|
212
|
+
path = filename.sub(/^assets/, '').sub(/index\.[^\/]+$/, '') + '/'
|
213
|
+
else
|
214
|
+
path = filename.sub(/^assets/, '').sub(/\.[^\/]+$/, '') + '/'
|
215
|
+
end
|
216
|
+
|
217
|
+
# Get mtime
|
218
|
+
mtime = File.stat(filename).mtime
|
219
|
+
|
220
|
+
# Build asset
|
221
|
+
Nanoc2::Asset.new(StringIO.new(content), attributes, path, mtime)
|
222
|
+
end.compact
|
223
|
+
end
|
224
|
+
|
225
|
+
def save_asset(asset) # :nodoc:
|
226
|
+
# TODO implement
|
227
|
+
end
|
228
|
+
|
229
|
+
def move_asset(asset, new_path) # :nodoc:
|
230
|
+
# TODO implement
|
231
|
+
end
|
232
|
+
|
233
|
+
def delete_asset(asset) # :nodoc:
|
234
|
+
# TODO implement
|
235
|
+
end
|
236
|
+
|
237
|
+
########## Page Defaults ##########
|
238
|
+
|
239
|
+
def page_defaults # :nodoc:
|
240
|
+
# Get attributes
|
241
|
+
filename = File.file?(PAGE_DEFAULTS_FILENAME) ? PAGE_DEFAULTS_FILENAME : PAGE_DEFAULTS_FILENAME_OLD
|
242
|
+
attributes = YAML.load_file(filename) || {}
|
243
|
+
|
244
|
+
# Get mtime
|
245
|
+
mtime = File.stat(filename).mtime
|
246
|
+
|
247
|
+
# Build page defaults
|
248
|
+
Nanoc2::PageDefaults.new(attributes, mtime)
|
249
|
+
end
|
250
|
+
|
251
|
+
def save_page_defaults(page_defaults) # :nodoc:
|
252
|
+
# Notify
|
253
|
+
if File.file?(PAGE_DEFAULTS_FILENAME)
|
254
|
+
filename = PAGE_DEFAULTS_FILENAME
|
255
|
+
created = false
|
256
|
+
Nanoc2::NotificationCenter.post(:file_updated, filename)
|
257
|
+
elsif File.file?(PAGE_DEFAULTS_FILENAME_OLD)
|
258
|
+
filename = PAGE_DEFAULTS_FILENAME_OLD
|
259
|
+
created = false
|
260
|
+
Nanoc2::NotificationCenter.post(:file_updated, filename)
|
261
|
+
else
|
262
|
+
filename = PAGE_DEFAULTS_FILENAME
|
263
|
+
created = true
|
264
|
+
Nanoc2::NotificationCenter.post(:file_created, filename)
|
265
|
+
end
|
266
|
+
|
267
|
+
# Write
|
268
|
+
File.open(filename, 'w') do |io|
|
269
|
+
io.write(page_defaults.attributes.to_split_yaml)
|
270
|
+
end
|
271
|
+
|
272
|
+
# Add to working copy if possible
|
273
|
+
vcs.add(filename) if created
|
274
|
+
end
|
275
|
+
|
276
|
+
########## Asset defaults ##########
|
277
|
+
|
278
|
+
def asset_defaults # :nodoc:
|
279
|
+
if File.file?(ASSET_DEFAULTS_FILENAME)
|
280
|
+
# Get attributes
|
281
|
+
attributes = YAML.load_file(ASSET_DEFAULTS_FILENAME) || {}
|
282
|
+
|
283
|
+
# Get mtime
|
284
|
+
mtime = File.stat(ASSET_DEFAULTS_FILENAME).mtime
|
285
|
+
|
286
|
+
# Build asset defaults
|
287
|
+
Nanoc2::AssetDefaults.new(attributes, mtime)
|
288
|
+
else
|
289
|
+
Nanoc2::AssetDefaults.new({})
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def save_asset_defaults(asset_defaults) # :nodoc:
|
294
|
+
# Notify
|
295
|
+
if File.file?(ASSET_DEFAULTS_FILENAME)
|
296
|
+
Nanoc2::NotificationCenter.post(:file_updated, ASSET_DEFAULTS_FILENAME)
|
297
|
+
created = false
|
298
|
+
else
|
299
|
+
Nanoc2::NotificationCenter.post(:file_created, ASSET_DEFAULTS_FILENAME)
|
300
|
+
created = true
|
301
|
+
end
|
302
|
+
|
303
|
+
# Write
|
304
|
+
File.open(ASSET_DEFAULTS_FILENAME, 'w') do |io|
|
305
|
+
io.write(asset_defaults.attributes.to_split_yaml)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Add to working copy if possible
|
309
|
+
vcs.add(ASSET_DEFAULTS_FILENAME) if created
|
310
|
+
end
|
311
|
+
|
312
|
+
########## Layouts ##########
|
313
|
+
|
314
|
+
def layouts # :nodoc:
|
315
|
+
files('layouts', true).map do |filename|
|
316
|
+
# Read and parse data
|
317
|
+
meta, content = *parse_file(filename, 'layout')
|
318
|
+
|
319
|
+
# Get actual path
|
320
|
+
if filename =~ /\/index\.[^\/]+$/
|
321
|
+
path = filename.sub(/^layouts/, '').sub(/index\.[^\/]+$/, '') + '/'
|
322
|
+
else
|
323
|
+
path = filename.sub(/^layouts/, '').sub(/\.[^\/]+$/, '') + '/'
|
324
|
+
end
|
325
|
+
|
326
|
+
# Get mtime
|
327
|
+
mtime = File.stat(filename).mtime
|
328
|
+
|
329
|
+
# Build layout
|
330
|
+
Nanoc2::Layout.new(content, meta, path, mtime)
|
331
|
+
end.compact
|
332
|
+
end
|
333
|
+
|
334
|
+
def save_layout(layout) # :nodoc:
|
335
|
+
# Find layout path
|
336
|
+
last_path_component = layout.path.split('/')[-1]
|
337
|
+
paths_best = Dir['layouts' + layout.path[0..-2] + '.*']
|
338
|
+
paths_worst = Dir['layouts' + layout.path + 'index.*']
|
339
|
+
path_default = 'layouts' + layout.path[0..-2] + '.html'
|
340
|
+
path = paths_best[0] || paths_worst[0] || path_default
|
341
|
+
parent_path = '/' + File.join(layout.path.split('/')[0..-2])
|
342
|
+
|
343
|
+
# Notify
|
344
|
+
if File.file?(path)
|
345
|
+
created = false
|
346
|
+
Nanoc2::NotificationCenter.post(:file_updated, path)
|
347
|
+
else
|
348
|
+
created = true
|
349
|
+
Nanoc2::NotificationCenter.post(:file_created, path)
|
350
|
+
end
|
351
|
+
|
352
|
+
# Write layout
|
353
|
+
FileUtils.mkdir_p('layouts' + parent_path)
|
354
|
+
File.open(path, 'w') do |io|
|
355
|
+
io.write("-----\n")
|
356
|
+
io.write(layout.attributes.to_split_yaml + "\n")
|
357
|
+
io.write("-----\n")
|
358
|
+
io.write(layout.content)
|
359
|
+
end
|
360
|
+
|
361
|
+
# Add to working copy if possible
|
362
|
+
vcs.add(path) if created
|
363
|
+
end
|
364
|
+
|
365
|
+
def move_layout(layout, new_path) # :nodoc:
|
366
|
+
# TODO implement
|
367
|
+
end
|
368
|
+
|
369
|
+
def delete_layout(layout) # :nodoc:
|
370
|
+
# TODO implement
|
371
|
+
end
|
372
|
+
|
373
|
+
########## Templates ##########
|
374
|
+
|
375
|
+
def templates # :nodoc:
|
376
|
+
files('templates', false).map do |filename|
|
377
|
+
# Read and parse data
|
378
|
+
meta, content = *parse_file(filename, 'template')
|
379
|
+
|
380
|
+
# Get name
|
381
|
+
name = filename.sub(/^templates\//, '').sub(/\.[^\/]+$/, '')
|
382
|
+
|
383
|
+
# Build template
|
384
|
+
Nanoc2::Template.new(content, meta, name)
|
385
|
+
end.compact
|
386
|
+
end
|
387
|
+
|
388
|
+
def save_template(template) # :nodoc:
|
389
|
+
# Get template path
|
390
|
+
paths = Dir[File.join('templates', template.name) + '.*']
|
391
|
+
path_default = File.join('templates', template.name) + '.html'
|
392
|
+
path = paths[0] || path_default
|
393
|
+
|
394
|
+
# Notify
|
395
|
+
if File.file?(path)
|
396
|
+
created = false
|
397
|
+
Nanoc2::NotificationCenter.post(:file_updated, path)
|
398
|
+
else
|
399
|
+
created = true
|
400
|
+
Nanoc2::NotificationCenter.post(:file_created, path)
|
401
|
+
end
|
402
|
+
|
403
|
+
# Write template
|
404
|
+
File.open(path, 'w') do |io|
|
405
|
+
io.write("-----\n")
|
406
|
+
io.write(template.page_attributes.to_split_yaml + "\n")
|
407
|
+
io.write("-----\n")
|
408
|
+
io.write(template.page_content)
|
409
|
+
end
|
410
|
+
|
411
|
+
# Add to working copy if possible
|
412
|
+
vcs.add(path) if created
|
413
|
+
end
|
414
|
+
|
415
|
+
def move_template(template, new_name) # :nodoc:
|
416
|
+
# TODO implement
|
417
|
+
end
|
418
|
+
|
419
|
+
def delete_template(template) # :nodoc:
|
420
|
+
# TODO implement
|
421
|
+
end
|
422
|
+
|
423
|
+
########## Code ##########
|
424
|
+
|
425
|
+
def code # :nodoc:
|
426
|
+
# Get data
|
427
|
+
data = Dir['lib/**/*.rb'].sort.map { |filename| File.read(filename) + "\n" }.join('')
|
428
|
+
|
429
|
+
# Get modification time
|
430
|
+
mtime = Dir['lib/**/*.rb'].map { |filename| File.stat(filename).mtime }.inject { |memo, mtime| memo > mtime ? mtime : memo}
|
431
|
+
|
432
|
+
# Build code
|
433
|
+
Nanoc2::Code.new(data, mtime)
|
434
|
+
end
|
435
|
+
|
436
|
+
def save_code(code) # :nodoc:
|
437
|
+
# Check whether code existed
|
438
|
+
existed = File.file?('lib/default.rb')
|
439
|
+
|
440
|
+
# Remove all existing code files
|
441
|
+
Dir['lib/**/*.rb'].each do |file|
|
442
|
+
vcs.remove(file) unless file == 'lib/default.rb'
|
443
|
+
end
|
444
|
+
|
445
|
+
# Notify
|
446
|
+
if existed
|
447
|
+
Nanoc2::NotificationCenter.post(:file_updated, 'lib/default.rb')
|
448
|
+
else
|
449
|
+
Nanoc2::NotificationCenter.post(:file_created, 'lib/default.rb')
|
450
|
+
end
|
451
|
+
|
452
|
+
# Write new code
|
453
|
+
File.open('lib/default.rb', 'w') do |io|
|
454
|
+
io.write(code.data)
|
455
|
+
end
|
456
|
+
|
457
|
+
# Add to working copy if possible
|
458
|
+
vcs.add('lib/default.rb') unless existed
|
459
|
+
end
|
460
|
+
|
461
|
+
private
|
462
|
+
|
463
|
+
# Returns a list of all files in +dir+, ignoring any unwanted files (files
|
464
|
+
# that end with '~', '.orig', '.rej' or '.bak').
|
465
|
+
#
|
466
|
+
# +recursively+:: When +true+, finds files in +dir+ as well as its
|
467
|
+
# subdirectories; when +false+, only searches +dir+
|
468
|
+
# itself.
|
469
|
+
def files(dir, recursively)
|
470
|
+
glob = File.join([dir] + (recursively ? [ '**', '*' ] : [ '*' ]))
|
471
|
+
Dir[glob].reject { |f| File.directory?(f) or f =~ /(~|\.orig|\.rej|\.bak)$/ }
|
472
|
+
end
|
473
|
+
|
474
|
+
# Parses the file named +filename+ and returns an array with its first
|
475
|
+
# element a hash with the file's metadata, and with its second element the
|
476
|
+
# file content itself.
|
477
|
+
def parse_file(filename, kind)
|
478
|
+
# Split file
|
479
|
+
pieces = File.read(filename).split(/^-----/)
|
480
|
+
if pieces.size < 3
|
481
|
+
raise RuntimeError.new(
|
482
|
+
"The file '#{filename}' does not seem to be a nanoc #{kind}"
|
483
|
+
)
|
484
|
+
end
|
485
|
+
|
486
|
+
# Parse
|
487
|
+
meta = YAML.load(pieces[1]) || {}
|
488
|
+
content = pieces[2..-1].join.strip
|
489
|
+
|
490
|
+
[ meta, content ]
|
491
|
+
end
|
492
|
+
|
493
|
+
end
|
494
|
+
|
495
|
+
end
|