class Webby::Resources::MetaFile
The MetaFile class is used to read meta-data and content from files. The meta-data is in a YAML block located at the top of the file. The content is the remainder of the file (everything after the YAML block).
The meta-data data must be found between two YAML block separators “—”, each on their own line.
Example:
--- layout: blog filter: markdown tags: - ruby - web development --- This is a blog entry formatted using MarkDown and tagged as "ruby" and "web development". The layout being used is the "blog" format.
Public Class Methods
Opens the file identified by filename and returns the meta-data
located at the top of the file. If the file contains no meta-data, then
nil
is returned.
# File lib/webby/resources/meta_file.rb, line 50 def self.meta_data( name ) ::File.open(name, 'r') {|fd| MetaFile.new(fd).meta_data} end
Opens the file identified by filename and returns true if there is a meta-data block at the top of the file, and returns false if there is not a meta-data block at the top of the file.
# File lib/webby/resources/meta_file.rb, line 61 def self.meta_data?( name ) ::File.open(name, 'r') {|fd| MetaFile.new(fd).meta_data?} end
Creates a new MetaFile parser that will read from the given io stream.
# File lib/webby/resources/meta_file.rb, line 67 def initialize( io ) raise ArgumentError, "expecting an IO stream" unless io.respond_to? :gets @io = io @meta_count = 0 end
Opens the file identified by filename and returns the contents of the file as a string. Any meta-data at the top of the file is skipped and is not included in the returned string. If the file contains no meta-data, then this method behaves the same as File#read.
# File lib/webby/resources/meta_file.rb, line 39 def self.read( name ) ::File.open(name, 'r') {|fd| MetaFile.new(fd).read} end
Public Instance Methods
Reads in each meta-data section and yields it to the given block. The first meta-data section is yielded “as is”, but subsequent meta-data sections are merged with this first section and then yielded. This allows the user to define common items in the first meta-data section and only include items that are different in the subsequent sections.
Example:
--- title: First Title author: me directory: foo/bar/baz --- title: Second Title author: you --- title: Third Title author: them ---
and parsing the meta-data above yields …
meta_file.each do |hash| pp hash end
the following output
{ 'title' => 'First Title', 'author' => 'me', 'directory' => 'foo/bar/baz' } { 'title' => 'Second Title', 'author' => 'you', 'directory' => 'foo/bar/baz' } { 'title' => 'Third Title', 'author' => 'them', 'directory' => 'foo/bar/baz' }
Even though the “directory” item only appears in the first meta-data block, it is copied to all the subsequent blocks.
# File lib/webby/resources/meta_file.rb, line 126 def each return unless meta_data? first, count = nil, 0 @io.seek 0 buffer = @io.gets while count < @meta_count while (line = @io.gets) !~ META_SEP buffer << line end h = YAML.load(buffer) raise Error, ERR_MSG unless h.instance_of?(Hash) if first then h = first.merge(h) else first = h.dup end buffer = line count += 1 yield h end rescue ArgumentError => err msg = ERR_MSG.dup << "\n\t-- " << err.message raise Error, msg end
Returns the number of meta-data blocks at the top of the file.
# File lib/webby/resources/meta_file.rb, line 176 def meta_count meta_end @meta_count end
Returns the meta-data defined at the top of the file. Returns
nil
if no meta-data is defined. The meta-data is returned as
Ruby objects
Meta-data is stored in YAML format between two YAML separators “—” on their own lines.
# File lib/webby/resources/meta_file.rb, line 160 def meta_data return if meta_end.nil? @io.seek 0 return YAML.load(@io) end
Returns true if the IO stream contains meta-data. Returns false if the IO stream does not contain meta-data.
# File lib/webby/resources/meta_file.rb, line 170 def meta_data? meta_end.nil? ? false : true end
Returns the position in the IO stream where the meta-data ends and the
regular data begins. If there is no meta-data in the stream, returns
nil
.
# File lib/webby/resources/meta_file.rb, line 184 def meta_end return @meta_end if defined? @meta_end @meta_end = nil @io.seek 0 line = @io.read(4) return unless META_SEP =~ line @io.seek 0 @io.gets pos, count = nil, 1 while line = @io.gets count += 1 if META_SEP =~ line pos = count @meta_count += 1 end end return if pos.nil? @meta_end = pos end
Returns the entire contents of the IO stream exluding any meta-data found at the beginning of the stream.
# File lib/webby/resources/meta_file.rb, line 76 def read count = meta_end @io.seek 0 count.times {@io.gets} unless count.nil? @io.read end