class Utopia::Content::Document

A single request through content middleware. We use a struct to hide instance varibles since we instance_exec within this context.

Attributes

attributes[R]

Per-document global attributes.

current[R]

The current state, represents a list from outer to inner most tag by traversing {State#parent}. At any point in parsing markup, this is a list of the inner most tag, then the next outer tag, etc.

end_tags[R]

End tags represents a list of execution order. This is the order that end tags have appeared when evaluating nodes.

first[R]

The first {State} generated by rendering this document. It contains useful information regarding the node and uri used to access the resource.

request[R]

The Rack::Request for this document.

Public Class Methods

new(request, attributes = {}) click to toggle source
Calls superclass method
# File lib/utopia/content/document.rb, line 46
def initialize(request, attributes = {})
        @request = request
        
        @attributes = attributes
        
        @first = nil
        @current = nil
        @end_tags = []
        
        super()
end
render(node, request, attributes) click to toggle source
# File lib/utopia/content/document.rb, line 42
def self.render(node, request, attributes)
        self.new(request, attributes).render!(node, attributes)
end

Public Instance Methods

[](key) click to toggle source
# File lib/utopia/content/document.rb, line 58
def [] key
        @attributes[key]
end
[]=(key, value) click to toggle source
# File lib/utopia/content/document.rb, line 62
def []= key, value
        @attributes[key] = value
end
cdata(string)
Alias for: write
content() click to toggle source

The content of the node

# File lib/utopia/content/document.rb, line 219
def content
        @end_tags.last.content
end
controller() click to toggle source

A helper method for accessing controller variables from view:

# File lib/utopia/content/document.rb, line 73
def controller
        @controller ||= Utopia::Controller[request]
end
localization() click to toggle source
# File lib/utopia/content/document.rb, line 77
def localization
        @localization ||= Utopia::Localization[request]
end
lookup_node(path) click to toggle source

Lookup a node with the given path relative to the current node. @return [Node] The node if could be found.

# File lib/utopia/content/document.rb, line 212
def lookup_node(path)
        @end_tags.reverse_each do |state|
                return state.node.lookup_node(path) if state.node.respond_to?(:lookup_node)
        end
end
lookup_tag(tag) click to toggle source

Maps a tag to a node instance by asking the current node to lookup the tag name. This function is called for each tag and thus heavily affects performance. @return [Node] The node for the given tag.

# File lib/utopia/content/document.rb, line 192
def lookup_tag(tag)
        # result = tag
        #
        # # This loop works from inner to outer tags, and updates the tag we are currently searching for based on any overrides:
        # @begin_tags.reverse_each do |state|
        #   result = state.lookup(result)
        #
        #   return result if result.is_a?(Node)
        # end
        
        # This loop looks up a tag by asking the most embedded node to look it up based on tag name. This almost always only evaluates the top state:
        @end_tags.reverse_each do |state|
                return state.node.lookup_tag(tag) if state.node.respond_to?(:lookup_tag)
        end
        
        return nil
end
parent() click to toggle source
# File lib/utopia/content/document.rb, line 223
def parent
        @end_tags[-2]
end
parse_markup(markup) click to toggle source
# File lib/utopia/content/document.rb, line 81
def parse_markup(markup)
        MarkupParser.parse(markup, self)
end
render!(node, attributes) click to toggle source
# File lib/utopia/content/document.rb, line 66
def render!(node, attributes)
        @body << render_node(node, attributes)
        
        return self
end
render_node(node, attributes = {}) click to toggle source
# File lib/utopia/content/document.rb, line 180
def render_node(node, attributes = {})
        @current = State.new(@current, nil, node, attributes)
        
        # We keep track of the first thing rendered by this document.
        @first ||= @current
        
        # This returns the content of rendering the tag:
        return tag_end
end
tag(name, attributes = {}) { |node| ... } click to toggle source
# File lib/utopia/content/document.rb, line 104
def tag(name, attributes = {})
        # If we provide a block which can give inner data, we are not self-closing.
        tag = Tag.new(name, !block_given?, attributes)

        if block_given?
                node = tag_begin(tag)
                yield node
                tag_end(tag)
        else
                tag_complete(tag, node)
        end
end
tag_begin(tag, node = nil) click to toggle source
# File lib/utopia/content/document.rb, line 128
def tag_begin(tag, node = nil)
        node ||= lookup_tag(tag)

        if node
                @current = State.new(@current, tag, node)

                node.tag_begin(self, state) if node.respond_to?(:tag_begin)

                return node
        end

        # raise ArgumentError.new("tag_begin: #{tag} is tag.self_closed?") if tag.self_closed?

        @current.tag_begin(tag)

        return nil
end
tag_complete(tag, node = nil) click to toggle source
# File lib/utopia/content/document.rb, line 117
def tag_complete(tag, node = nil)
        node ||= lookup_tag(tag)

        if node
                tag_begin(tag, node)
                tag_end(tag)
        else
                @current.tag_complete(tag)
        end
end
tag_end(tag = nil) click to toggle source
# File lib/utopia/content/document.rb, line 156
def tag_end(tag = nil)
        # Determine if the current state contains tags that need to be completed, or if the state itself is finished.
        if @current.empty?
                if node = @current.node
                        node.tag_end(self, @current) if node.respond_to?(:tag_end)
                end

                @end_tags << @current
                buffer = @current.call(self)

                @current = @current.parent
                @end_tags.pop

                @current.write(buffer) if @current

                return buffer
        else
                # raise ArgumentError.new("tag_begin: #{tag} is tag.self_closed?") if tag.self_closed?
                @current.tag_end(tag)
        end

        return nil
end
text(string) click to toggle source
# File lib/utopia/content/document.rb, line 152
def text(string)
        @current.text(string)
end
write(string) click to toggle source
# File lib/utopia/content/document.rb, line 146
def write(string)
        @current.write(string)
end
Also aliased as: cdata