nanoc2 2.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/ChangeLog +3 -0
  2. data/LICENSE +19 -0
  3. data/README +75 -0
  4. data/Rakefile +76 -0
  5. data/bin/nanoc2 +26 -0
  6. data/lib/nanoc2.rb +73 -0
  7. data/lib/nanoc2/base.rb +26 -0
  8. data/lib/nanoc2/base/asset.rb +117 -0
  9. data/lib/nanoc2/base/asset_defaults.rb +21 -0
  10. data/lib/nanoc2/base/asset_rep.rb +282 -0
  11. data/lib/nanoc2/base/binary_filter.rb +44 -0
  12. data/lib/nanoc2/base/code.rb +41 -0
  13. data/lib/nanoc2/base/compiler.rb +67 -0
  14. data/lib/nanoc2/base/core_ext.rb +2 -0
  15. data/lib/nanoc2/base/core_ext/hash.rb +78 -0
  16. data/lib/nanoc2/base/core_ext/string.rb +8 -0
  17. data/lib/nanoc2/base/data_source.rb +286 -0
  18. data/lib/nanoc2/base/defaults.rb +30 -0
  19. data/lib/nanoc2/base/filter.rb +93 -0
  20. data/lib/nanoc2/base/layout.rb +91 -0
  21. data/lib/nanoc2/base/notification_center.rb +66 -0
  22. data/lib/nanoc2/base/page.rb +132 -0
  23. data/lib/nanoc2/base/page_defaults.rb +20 -0
  24. data/lib/nanoc2/base/page_rep.rb +324 -0
  25. data/lib/nanoc2/base/plugin.rb +71 -0
  26. data/lib/nanoc2/base/proxies.rb +5 -0
  27. data/lib/nanoc2/base/proxies/asset_proxy.rb +29 -0
  28. data/lib/nanoc2/base/proxies/asset_rep_proxy.rb +26 -0
  29. data/lib/nanoc2/base/proxies/layout_proxy.rb +25 -0
  30. data/lib/nanoc2/base/proxies/page_proxy.rb +35 -0
  31. data/lib/nanoc2/base/proxies/page_rep_proxy.rb +28 -0
  32. data/lib/nanoc2/base/proxy.rb +37 -0
  33. data/lib/nanoc2/base/router.rb +72 -0
  34. data/lib/nanoc2/base/site.rb +274 -0
  35. data/lib/nanoc2/base/template.rb +64 -0
  36. data/lib/nanoc2/binary_filters.rb +1 -0
  37. data/lib/nanoc2/binary_filters/image_science_thumbnail.rb +28 -0
  38. data/lib/nanoc2/cli.rb +9 -0
  39. data/lib/nanoc2/cli/base.rb +132 -0
  40. data/lib/nanoc2/cli/commands.rb +10 -0
  41. data/lib/nanoc2/cli/commands/autocompile.rb +80 -0
  42. data/lib/nanoc2/cli/commands/compile.rb +312 -0
  43. data/lib/nanoc2/cli/commands/create_layout.rb +85 -0
  44. data/lib/nanoc2/cli/commands/create_page.rb +85 -0
  45. data/lib/nanoc2/cli/commands/create_site.rb +323 -0
  46. data/lib/nanoc2/cli/commands/create_template.rb +76 -0
  47. data/lib/nanoc2/cli/commands/help.rb +69 -0
  48. data/lib/nanoc2/cli/commands/info.rb +125 -0
  49. data/lib/nanoc2/cli/commands/switch.rb +141 -0
  50. data/lib/nanoc2/cli/commands/update.rb +91 -0
  51. data/lib/nanoc2/cli/logger.rb +72 -0
  52. data/lib/nanoc2/data_sources.rb +2 -0
  53. data/lib/nanoc2/data_sources/filesystem.rb +707 -0
  54. data/lib/nanoc2/data_sources/filesystem_combined.rb +495 -0
  55. data/lib/nanoc2/extra.rb +6 -0
  56. data/lib/nanoc2/extra/auto_compiler.rb +285 -0
  57. data/lib/nanoc2/extra/context.rb +22 -0
  58. data/lib/nanoc2/extra/core_ext.rb +2 -0
  59. data/lib/nanoc2/extra/core_ext/hash.rb +54 -0
  60. data/lib/nanoc2/extra/core_ext/time.rb +13 -0
  61. data/lib/nanoc2/extra/file_proxy.rb +29 -0
  62. data/lib/nanoc2/extra/vcs.rb +48 -0
  63. data/lib/nanoc2/extra/vcses.rb +5 -0
  64. data/lib/nanoc2/extra/vcses/bazaar.rb +21 -0
  65. data/lib/nanoc2/extra/vcses/dummy.rb +20 -0
  66. data/lib/nanoc2/extra/vcses/git.rb +21 -0
  67. data/lib/nanoc2/extra/vcses/mercurial.rb +21 -0
  68. data/lib/nanoc2/extra/vcses/subversion.rb +21 -0
  69. data/lib/nanoc2/filters.rb +16 -0
  70. data/lib/nanoc2/filters/bluecloth.rb +13 -0
  71. data/lib/nanoc2/filters/erb.rb +19 -0
  72. data/lib/nanoc2/filters/erubis.rb +14 -0
  73. data/lib/nanoc2/filters/haml.rb +21 -0
  74. data/lib/nanoc2/filters/markaby.rb +14 -0
  75. data/lib/nanoc2/filters/maruku.rb +14 -0
  76. data/lib/nanoc2/filters/old.rb +19 -0
  77. data/lib/nanoc2/filters/rainpress.rb +13 -0
  78. data/lib/nanoc2/filters/rdiscount.rb +13 -0
  79. data/lib/nanoc2/filters/rdoc.rb +23 -0
  80. data/lib/nanoc2/filters/redcloth.rb +14 -0
  81. data/lib/nanoc2/filters/relativize_paths.rb +16 -0
  82. data/lib/nanoc2/filters/relativize_paths_in_css.rb +16 -0
  83. data/lib/nanoc2/filters/relativize_paths_in_html.rb +16 -0
  84. data/lib/nanoc2/filters/rubypants.rb +14 -0
  85. data/lib/nanoc2/filters/sass.rb +18 -0
  86. data/lib/nanoc2/helpers.rb +9 -0
  87. data/lib/nanoc2/helpers/blogging.rb +217 -0
  88. data/lib/nanoc2/helpers/capturing.rb +63 -0
  89. data/lib/nanoc2/helpers/filtering.rb +54 -0
  90. data/lib/nanoc2/helpers/html_escape.rb +25 -0
  91. data/lib/nanoc2/helpers/link_to.rb +113 -0
  92. data/lib/nanoc2/helpers/render.rb +49 -0
  93. data/lib/nanoc2/helpers/tagging.rb +56 -0
  94. data/lib/nanoc2/helpers/text.rb +38 -0
  95. data/lib/nanoc2/helpers/xml_sitemap.rb +63 -0
  96. data/lib/nanoc2/routers.rb +3 -0
  97. data/lib/nanoc2/routers/default.rb +54 -0
  98. data/lib/nanoc2/routers/no_dirs.rb +66 -0
  99. data/lib/nanoc2/routers/versioned.rb +79 -0
  100. 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