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
Per-document global attributes.
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.
The first {State} generated by rendering this document. It contains useful information regarding the node and uri used to access the resource.
The Rack::Request for this document.
Public Class Methods
# File lib/utopia/content/document.rb, line 46 def initialize(request, attributes = {}) @request = request @attributes = attributes @first = nil @current = nil @end_tags = [] super() end
# 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
# File lib/utopia/content/document.rb, line 58 def [] key @attributes[key] end
# File lib/utopia/content/document.rb, line 62 def []= key, value @attributes[key] = value end
The content of the node
# File lib/utopia/content/document.rb, line 219 def content @end_tags.last.content end
A helper method for accessing controller variables from view:
# File lib/utopia/content/document.rb, line 73 def controller @controller ||= Utopia::Controller[request] end
# File lib/utopia/content/document.rb, line 77 def localization @localization ||= Utopia::Localization[request] end
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
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
# File lib/utopia/content/document.rb, line 223 def parent @end_tags[-2] end
# File lib/utopia/content/document.rb, line 81 def parse_markup(markup) MarkupParser.parse(markup, self) end
# File lib/utopia/content/document.rb, line 66 def render!(node, attributes) @body << render_node(node, attributes) return self end
# 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
# 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
# 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
# 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
# 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
# File lib/utopia/content/document.rb, line 152 def text(string) @current.text(string) end
# File lib/utopia/content/document.rb, line 146 def write(string) @current.write(string) end