Class: Nanoc2::DataSources::FilesystemCombined

Inherits:
Nanoc2::DataSource show all
Defined in:
lib/nanoc2/data_sources/filesystem_combined.rb

Overview

Pages

The filesystem data source stores its pages in nested directories. A page is represented by a single file. The root directory is the ‘content’ directory.

The metadata for a page is embedded into the file itself. It is stored at the top of the file, between ‘—–’ (five dashes) separators. For example:

-----
filters_pre: [ 'redcloth' ]
-----
h1. Hello!

The path of a page is determined as follows. A file with an ‘index.*’ filename, such as ‘index.txt’, will have the filesystem path with the ‘index.*’ part stripped as a path. For example, ‘foo/bar/index.html’ will have ‘/foo/bar/’ as path.

A file with a filename not starting with ‘index.’, such as ‘foo.html’, will have a path ending in ‘foo/’. For example, ‘foo/bar.html’ will have ‘/foo/bar/’ as path.

Note that it is possible for two different, separate files to have the same path. It is therefore recommended to avoid such situations.

Some more examples:

content/index.html          --> /
content/foo.html            --> /foo/
content/foo/index.html      --> /foo/
content/foo/bar.html        --> /foo/bar/
content/foo/bar/index.html  --> /foo/bar/

File extensions are ignored by nanoc. The file extension does not determine the filters to run on it; the metadata in the file defines the list of filters.

Page defaults

The page defaults are loaded from a YAML-formatted file named ‘page_defaults.yaml’ at the top level of the nanoc site directory. For backward compatibility, the file can also be named ‘meta.yaml’.

Assets

Assets are stored in a way similar to pages. The attributes are merged into the asset. This does mean, however, that only textual assets are supported, as there is no way to embed attributes in binary assets.

Asset defaults

The asset defaults are stored similar to the way page defaults are stored, except that the asset defaults file is named ‘asset_defaults.yaml’ instead.

Layouts

Layouts are stored as files in the ‘layouts’ directory. Similar to pages, each layout consists of a metadata part and a content part, separated by ‘—–’.

Templates

Templates are located in the ‘templates’ directory. Templates are, just like pages, files consisting of a metadata part and a content part, separated by ‘—–’.

Code

Code is stored in ‘.rb’ files in the ‘lib’ directory. Code can reside in sub-directories.

Constant Summary collapse

PAGE_DEFAULTS_FILENAME =
'page_defaults.yaml'
PAGE_DEFAULTS_FILENAME_OLD =
'meta.yaml'
ASSET_DEFAULTS_FILENAME =
'asset_defaults.yaml'

Constants inherited from Plugin

Plugin::MAP

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Nanoc2::DataSource

#initialize, #loading, #update

Methods inherited from Plugin

identifier, identifiers, named, register

Constructor Details

This class inherits a constructor from Nanoc2::DataSource

Instance Attribute Details

#vcsObject

VCSes ##########



88
89
90
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 88

def vcs
  @vcs
end

Instance Method Details

#asset_defaultsObject

Asset defaults ##########



278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 278

def asset_defaults # :nodoc:
  if File.file?(ASSET_DEFAULTS_FILENAME)
    # Get attributes
    attributes = YAML.load_file(ASSET_DEFAULTS_FILENAME) || {}

    # Get mtime
    mtime = File.stat(ASSET_DEFAULTS_FILENAME).mtime

    # Build asset defaults
    Nanoc2::AssetDefaults.new(attributes, mtime)
  else
    Nanoc2::AssetDefaults.new({})
  end
end

#assetsObject

Assets ##########



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 199

def assets # :nodoc:
  files('assets', true).map do |filename|
    # Read and parse data
    meta, content = *parse_file(filename, 'asset')

    # Skip drafts
    return nil if meta[:is_draft]

    # Get attributes
    attributes = { 'extension' => File.extname(filename)[1..-1] }.merge(meta)

    # Get actual path
    if filename =~ /\/index\.[^\/]+$/
      path = filename.sub(/^assets/, '').sub(/index\.[^\/]+$/, '') + '/'
    else
      path = filename.sub(/^assets/, '').sub(/\.[^\/]+$/, '') + '/'
    end

    # Get mtime
    mtime = File.stat(filename).mtime

    # Build asset
    Nanoc2::Asset.new(StringIO.new(content), attributes, path, mtime)
  end.compact
end

#codeObject

Code ##########



425
426
427
428
429
430
431
432
433
434
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 425

def code # :nodoc:
  # Get data
  data = Dir['lib/**/*.rb'].sort.map { |filename| File.read(filename) + "\n" }.join('')

  # Get modification time
  mtime = Dir['lib/**/*.rb'].map { |filename| File.stat(filename).mtime }.inject { |memo, mtime| memo > mtime ? mtime : memo}

  # Build code
  Nanoc2::Code.new(data, mtime)
end

#delete_asset(asset) ⇒ Object

:nodoc:



233
234
235
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 233

def delete_asset(asset) # :nodoc:
  # TODO implement
end

#delete_layout(layout) ⇒ Object

:nodoc:



369
370
371
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 369

def delete_layout(layout) # :nodoc:
  # TODO implement
end

#delete_page(page) ⇒ Object

:nodoc:



193
194
195
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 193

def delete_page(page) # :nodoc:
  # TODO implement
end

#delete_template(template) ⇒ Object

:nodoc:



419
420
421
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 419

def delete_template(template) # :nodoc:
  # TODO implement
end

#destroyObject

:nodoc:



110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 110

def destroy # :nodoc:
  # Remove files
  vcs.remove(ASSET_DEFAULTS_FILENAME)    if File.file?(ASSET_DEFAULTS_FILENAME)
  vcs.remove(PAGE_DEFAULTS_FILENAME)     if File.file?(PAGE_DEFAULTS_FILENAME)
  vcs.remove(PAGE_DEFAULTS_FILENAME_OLD) if File.file?(PAGE_DEFAULTS_FILENAME_OLD)

  # Remove directories
  vcs.remove('assets')
  vcs.remove('content')
  vcs.remove('templates')
  vcs.remove('layouts')
  vcs.remove('lib')
end

#downObject

:nodoc:



99
100
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 99

def down # :nodoc:
end

#layoutsObject

Layouts ##########



314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 314

def layouts # :nodoc:
  files('layouts', true).map do |filename|
    # Read and parse data
    meta, content = *parse_file(filename, 'layout')

    # Get actual path
    if filename =~ /\/index\.[^\/]+$/
      path = filename.sub(/^layouts/, '').sub(/index\.[^\/]+$/, '') + '/'
    else
      path = filename.sub(/^layouts/, '').sub(/\.[^\/]+$/, '') + '/'
    end

    # Get mtime
    mtime = File.stat(filename).mtime

    # Build layout
    Nanoc2::Layout.new(content, meta, path, mtime)
  end.compact
end

#move_asset(asset, new_path) ⇒ Object

:nodoc:



229
230
231
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 229

def move_asset(asset, new_path) # :nodoc:
  # TODO implement
end

#move_layout(layout, new_path) ⇒ Object

:nodoc:



365
366
367
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 365

def move_layout(layout, new_path) # :nodoc:
  # TODO implement
end

#move_page(page, new_path) ⇒ Object

:nodoc:



189
190
191
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 189

def move_page(page, new_path) # :nodoc:
  # TODO implement
end

#move_template(template, new_name) ⇒ Object

:nodoc:



415
416
417
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 415

def move_template(template, new_name) # :nodoc:
  # TODO implement
end

#page_defaultsObject

Page Defaults ##########



239
240
241
242
243
244
245
246
247
248
249
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 239

def page_defaults # :nodoc:
  # Get attributes
  filename = File.file?(PAGE_DEFAULTS_FILENAME) ? PAGE_DEFAULTS_FILENAME : PAGE_DEFAULTS_FILENAME_OLD
  attributes = YAML.load_file(filename) || {}

  # Get mtime
  mtime = File.stat(filename).mtime

  # Build page defaults
  Nanoc2::PageDefaults.new(attributes, mtime)
end

#pagesObject

Pages ##########



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 126

def pages # :nodoc:
  files('content', true).map do |filename|
    # Read and parse data
    meta, content = *parse_file(filename, 'page')

    # Skip drafts
    return nil if meta[:is_draft]

    # Get attributes
    attributes = meta.merge(:file => Nanoc2::Extra::FileProxy.new(filename))

    # Get actual path
    if filename =~ /\/index\.[^\/]+$/
      path = filename.sub(/^content/, '').sub(/index\.[^\/]+$/, '') + '/'
    else
      path = filename.sub(/^content/, '').sub(/\.[^\/]+$/, '') + '/'
    end

    # Get mtime
    mtime = File.stat(filename).mtime

    # Build page
    Nanoc2::Page.new(content, attributes, path, mtime)
  end.compact
end

#save_asset(asset) ⇒ Object

:nodoc:



225
226
227
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 225

def save_asset(asset) # :nodoc:
  # TODO implement
end

#save_asset_defaults(asset_defaults) ⇒ Object

:nodoc:



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 293

def save_asset_defaults(asset_defaults) # :nodoc:
  # Notify
  if File.file?(ASSET_DEFAULTS_FILENAME)
    Nanoc2::NotificationCenter.post(:file_updated, ASSET_DEFAULTS_FILENAME)
    created  = false
  else
    Nanoc2::NotificationCenter.post(:file_created, ASSET_DEFAULTS_FILENAME)
    created  = true
  end

  # Write
  File.open(ASSET_DEFAULTS_FILENAME, 'w') do |io|
    io.write(asset_defaults.attributes.to_split_yaml)
  end

  # Add to working copy if possible
  vcs.add(ASSET_DEFAULTS_FILENAME) if created
end

#save_code(code) ⇒ Object

:nodoc:



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 436

def save_code(code) # :nodoc:
  # Check whether code existed
  existed = File.file?('lib/default.rb')

  # Remove all existing code files
  Dir['lib/**/*.rb'].each do |file|
    vcs.remove(file) unless file == 'lib/default.rb'
  end

  # Notify
  if existed
    Nanoc2::NotificationCenter.post(:file_updated, 'lib/default.rb')
  else
    Nanoc2::NotificationCenter.post(:file_created, 'lib/default.rb')
  end

  # Write new code
  File.open('lib/default.rb', 'w') do |io|
    io.write(code.data)
  end

  # Add to working copy if possible
  vcs.add('lib/default.rb') unless existed
end

#save_layout(layout) ⇒ Object

:nodoc:



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 334

def save_layout(layout) # :nodoc:
  # Find layout path
  last_path_component = layout.path.split('/')[-1]
  paths_best    = Dir['layouts' + layout.path[0..-2] + '.*']
  paths_worst   = Dir['layouts' + layout.path + 'index.*']
  path_default  = 'layouts' + layout.path[0..-2] + '.html'
  path          = paths_best[0] || paths_worst[0] || path_default
  parent_path   = '/' + File.join(layout.path.split('/')[0..-2])

  # Notify
  if File.file?(path)
    created = false
    Nanoc2::NotificationCenter.post(:file_updated, path)
  else
    created = true
    Nanoc2::NotificationCenter.post(:file_created, path)
  end

  # Write layout
  FileUtils.mkdir_p('layouts' + parent_path)
  File.open(path, 'w') do |io|
    io.write("-----\n")
    io.write(layout.attributes.to_split_yaml + "\n")
    io.write("-----\n")
    io.write(layout.content)
  end

  # Add to working copy if possible
  vcs.add(path) if created
end

#save_page(page) ⇒ Object

:nodoc:



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 152

def save_page(page) # :nodoc:
  # Find page path
  if page.path == '/'
    paths         = Dir['content/index.*']
    path          = paths[0] || 'content/index.html'
    parent_path   = '/'
  else
    last_path_component = page.path.split('/')[-1]
    paths_best    = Dir['content' + page.path[0..-2] + '.*']
    paths_worst   = Dir['content' + page.path + 'index.*']
    path_default  = 'content' + page.path[0..-2] + '.html'
    path          = paths_best[0] || paths_worst[0] || path_default
    parent_path   = '/' + File.join(page.path.split('/')[0..-2])
  end

  # Notify
  if File.file?(path)
    created = false
    Nanoc2::NotificationCenter.post(:file_updated, path)
  else
    created = true
    Nanoc2::NotificationCenter.post(:file_created, path)
  end

  # Write page
  FileUtils.mkdir_p('content' + parent_path)
  File.open(path, 'w') do |io|
    io.write("-----\n")
    io.write(page.attributes.to_split_yaml + "\n")
    io.write("-----\n")
    io.write(page.content)
  end

  # Add to working copy if possible
  vcs.add(path) if created
end

#save_page_defaults(page_defaults) ⇒ Object

:nodoc:



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 251

def save_page_defaults(page_defaults) # :nodoc:
  # Notify
  if File.file?(PAGE_DEFAULTS_FILENAME)
    filename = PAGE_DEFAULTS_FILENAME
    created  = false
    Nanoc2::NotificationCenter.post(:file_updated, filename)
  elsif File.file?(PAGE_DEFAULTS_FILENAME_OLD)
    filename = PAGE_DEFAULTS_FILENAME_OLD
    created  = false
    Nanoc2::NotificationCenter.post(:file_updated, filename)
  else
    filename = PAGE_DEFAULTS_FILENAME
    created  = true
    Nanoc2::NotificationCenter.post(:file_created, filename)
  end

  # Write
  File.open(filename, 'w') do |io|
    io.write(page_defaults.attributes.to_split_yaml)
  end

  # Add to working copy if possible
  vcs.add(filename) if created
end

#save_template(template) ⇒ Object

:nodoc:



388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 388

def save_template(template) # :nodoc:
  # Get template path
  paths         = Dir[File.join('templates', template.name) + '.*']
  path_default  = File.join('templates', template.name) + '.html'
  path          = paths[0] || path_default

  # Notify
  if File.file?(path)
    created = false
    Nanoc2::NotificationCenter.post(:file_updated, path)
  else
    created = true
    Nanoc2::NotificationCenter.post(:file_created, path)
  end

  # Write template
  File.open(path, 'w') do |io|
    io.write("-----\n")
    io.write(template.page_attributes.to_split_yaml + "\n")
    io.write("-----\n")
    io.write(template.page_content)
  end

  # Add to working copy if possible
  vcs.add(path) if created
end

#setupObject

:nodoc:



102
103
104
105
106
107
108
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 102

def setup # :nodoc:
  # Create directories
  %w( assets content templates layouts lib ).each do |dir|
    FileUtils.mkdir_p(dir)
    vcs.add(dir)
  end
end

#templatesObject

Templates ##########



375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 375

def templates # :nodoc:
  files('templates', false).map do |filename|
    # Read and parse data
    meta, content = *parse_file(filename, 'template')

    # Get name
    name = filename.sub(/^templates\//, '').sub(/\.[^\/]+$/, '')

    # Build template
    Nanoc2::Template.new(content, meta, name)
  end.compact
end

#upObject

Preparation ##########



96
97
# File 'lib/nanoc2/data_sources/filesystem_combined.rb', line 96

def up # :nodoc:
end