class Webby::Resources::MetaFile - webby-0.9.4 Documentation

# 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

meta_data( filename ) → object or nil click to toggle source

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

meta_data?( filename ) → true or false click to toggle source

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

new( io ) click to toggle source

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

read( filename ) → string click to toggle source

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

each() { |h| ... } click to toggle source

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

meta_count() click to toggle source

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

meta_data() click to toggle source

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

meta_data?() click to toggle source

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

meta_end() click to toggle source

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

read() click to toggle source

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