class Strelka::CMS::Page

An abstraction of a page with markup. This class provides rendering and introspection facilities for page files on disk. A page file is a plain file with a .page extension that contains some content to be rendered for the docs site, and is of the form:

---                                     | - YAML document separator
title: My Brilliant Document            | - An optional YAML header, see
filters:                                |
  - apilinks                            |
  - links                               |
  - syntax                              |
  - editorial                           |
  - textile                             |
                                        |
---                                     | - Document separator
h1. My Brilliant Document               | - Document contents which will
                                        |   will be transformed by the
This is a document with some stuff in   |   configured filters.
it. It rules you. Like my teeth.        |
                                        |

Constants

DEFAULT_OPTIONS

The default page options.

PAGE_WITH_YAML_HEADER

Pattern to match a source page with a YAML header

Attributes

catalog[RW]

The page's catalog (if it was loaded via one)

content[RW]

The page's content

created[R]

The Time the page object was instantiated

filters[R]

The Array of filter names that will be applied to the rendered output, in the order they will be applied.

options[R]

Any additional options in the header

path[R]

The path to the page (if loaded from a file, nil otherwise)

template[R]

The path to the Inversion template to wrap the page content in

title[RW]

The page title given in the page config

Public Class Methods

load( path, catalog=nil ) click to toggle source

Read page source from the file at the given path and return a new Page object.

# File lib/strelka/cms/page.rb, line 63
def self::load( path, catalog=nil )
        page = File.open( path, 'r', encoding: 'utf-8' ) do |io|
                self.read( io, catalog )
        end

        page.path = path

        return page
end
new( content, catalog=nil, options={} ) click to toggle source

Create a new Page with the specified content and options.

# File lib/strelka/cms/page.rb, line 105
def initialize( content, catalog=nil, options={} )
        # If there's no catalog, the options might be in its place
        if catalog.is_a?( Hash )
                options = catalog
                catalog = nil
        end

        @content  = content
        @catalog  = catalog

        options   = DEFAULT_OPTIONS.merge( options )
        @tags     = options.delete( 'tags' ) || options.delete( 'keywords' )
        @title    = options.delete( 'title' )
        @filters  = options.delete( 'filters' )
        @template = options.delete( 'template' )
        @options  = options
        @created  = Time.now

        @article  = nil

        @path     = nil
end
parse( source, catalog=nil ) click to toggle source

Parse the given source and return a new Page object.

# File lib/strelka/cms/page.rb, line 83
def self::parse( source, catalog=nil )
        options = nil

        if source =~ PAGE_WITH_YAML_HEADER
                self.log.debug "Parsing page with YAML header..."
                options = YAML.load( $1 )
                source = $2
                self.log.debug "  YAML header options: %p" % [ options ]
        else
                self.log.debug "Parsing page with no header."
                options = {}
        end

        return new( source, catalog, options )
end
read( io, catalog=nil ) click to toggle source

Read page source from the given io and return a new Page object.

# File lib/strelka/cms/page.rb, line 75
def self::read( io, catalog=nil )
        source = io.read
        self.log.debug "Read %d bytes from %p" % [ source.length, io ]
        page = self.parse( source, catalog )
end

Public Instance Methods

apply_filters( content ) click to toggle source

Apply the filters corresponding to the given filter_names and return the modified content.

# File lib/strelka/cms/page.rb, line 183
def apply_filters( content )
        filters = self.filter_objects
        self.log.debug "Applying %d filters to %d bytes of content: %p" %
                [ filters.length, content.length, content[0,100] ]

        return filters.inject( self.content.dup ) do |filtered_content, filter|
                begin
                        filter.process( filtered_content, self )
                rescue => err
                        self.log.error "%s while applying the %s filter: %s" %
                                [ err.class.name, filter.class.factory_type, err.message ]
                        self.log.debug "  " + err.backtrace.join("\n  ")
                        filtered_content
                end
        end
end
date()
Alias for: modified
filter_objects() click to toggle source

Return the page's filters as instances of Strelka::CMS::PageFilter.

# File lib/strelka/cms/page.rb, line 202
def filter_objects
        return self.filters.map do |filter_name|
                filter_name.untaint
                Strelka::CMS::PageFilter.create( filter_name )
        end
end
first_heading() click to toggle source

Return the contents of the first heading from the rendered page.

# File lib/strelka/cms/page.rb, line 211
def first_heading
        self.log.debug "Fetching page title from rendered page"
        doc = Nokogiri::HTML( self.to_s )
        if heading = doc.css( 'h1,h2,h3' ).first
                self.log.debug "  got first heading: %s" % [ heading ]
                return heading.content
        else
                self.log.debug "  couldn't find a heading."
                return nil
        end
end
index_fields() click to toggle source

Extract a Hash of fields to be indexed from the page and return it.

# File lib/strelka/cms/page.rb, line 253
def index_fields
        return {
            :title         => self.title,
            :first_heading => self.first_heading,
                :tags          => self.tags.join( ', ' ),
            :content       => self.stripped_content,
                :modified      => self.modified,
                :created       => self.created,
        }
end
inspect() click to toggle source

Return a human-readable representation of the receiving object.

# File lib/strelka/cms/page.rb, line 305
def inspect
        return %|#<%s:%#0x %p %p [%s] {filters: %s}>| % [
                self.class.name,
                self.object_id / 2,
                self.path,
                self.title,
                self.tags.join(', '),
                self.filters.join('+'),
        ]
end
keywords()
Alias for: tags
modified() click to toggle source

Return the Time the page was last modified. This is derived from its 'date' header if it has one, or its mtime if it was loaded from a file, or its created date if neither of those are available.

# File lib/strelka/cms/page.rb, line 268
def modified
        if headerdate = self.options['date']
                headerdate = headerdate.to_time if headerdate.respond_to?( :to_time )
                headerdate = Time.parse( headerdate ) unless headerdate.is_a?( Time )
                return headerdate
        elsif self.path
                return self.path.mtime
        else
                return self.created
        end
end
Also aliased as: date
path=( newpath ) click to toggle source

Set the path to the page.

# File lib/strelka/cms/page.rb, line 160
def path=( newpath )
        @path = Pathname( newpath )
end
relative_html_path() click to toggle source

Return the page's HTML path.

# File lib/strelka/cms/page.rb, line 175
def relative_html_path
        pagepath = self.relative_path or return nil
        return pagepath.to_s.sub(/\.page$/, '.html')
end
relative_path() click to toggle source

Return the page's path relative to its catalog.

# File lib/strelka/cms/page.rb, line 166
def relative_path
        catalog = self.catalog or return nil
        path = self.path or return nil

        return path.relative_path_from( catalog.basedir )
end
render( * ) click to toggle source

Return the page rendered as HTML after applying filters and wrapping it in its configured template if it has one.

# File lib/strelka/cms/page.rb, line 226
def render( * )
        if path = self.template
                self.log.debug "Wrapping %p in template at %p" % [ self, path ]
                tmpl = Inversion::Template.load( path )
                tmpl.page = self
                return tmpl
        else
                return self.to_s
        end
end
stripped_content() click to toggle source

Return the page content with tags stripped.

# File lib/strelka/cms/page.rb, line 247
def stripped_content
        return self.content.gsub( /<.*?>/, '' )
end
summary() click to toggle source

Return a summary of the page.

# File lib/strelka/cms/page.rb, line 283
def summary
        summary = self.article.summarize( sentences: 1 ).first
        return summary[:sentence].strip
end
summary_topics() click to toggle source

Return an Array of topics for the page.

# File lib/strelka/cms/page.rb, line 290
def summary_topics
        return self.article.topics
end
tags() click to toggle source

Return the Array of tags/keywords set in the header, or derived from the content if not specified explicitly.

# File lib/strelka/cms/page.rb, line 297
def tags
        @tags ||= self.article.keywords
        return @tags
end
Also aliased as: keywords
to_html()
Alias for: to_s
to_s() click to toggle source

Render the page content, filtering it with its configured filters. Note that this does not wrap it in its template.

# File lib/strelka/cms/page.rb, line 240
def to_s
        return self.apply_filters( self.content )
end
Also aliased as: to_html

Protected Instance Methods

article() click to toggle source

Derive a summary and topics from the stripped contents of the page. This populates summary and summary_topics.

# File lib/strelka/cms/page.rb, line 323
def article
        @article ||= OTS.parse( self.stripped_content )
        return @article
end