class Markaby::Builder
puts mab.to_s
end
end
end
li “$29 for a huge boot that floats and can fit 5 people”
li “$39 for a raft”
li “$49 for a canoe”
ul do
h1 “Boats.com has great deals”
body do
head { title “Boats.com” }
mab.html do
mab = Markaby::Builder.new
from Ruby code, this is the only class you need to instantiate directly.
The Markaby::Builder class is the central gear in the system. When using
def self.get(option)
def self.get(option) @@options[option] end
def self.restore_defaults!
def self.restore_defaults! @@options = DEFAULT_OPTIONS.dup end
def self.set(option, value)
def self.set(option, value) @@options[option] = value end
def capture(&block)
=> "
TEST
CAPTURE ME
">> Markaby::Builder.new.capture { h1 "TEST"; h2 "CAPTURE ME" }
stream for the builder object, running the block and passing back its stream as a string.
Captures the HTML code built inside the +block+. This is done by creating a new
def capture(&block) @streams.push(@builder.target = Stream.new) @builder.level += 1 str = instance_eval(&block) str = @streams.last.join if @streams.last.any? @streams.pop @builder.level -= 1 @builder.target = @streams.last str end
def fragment
def fragment stream = @streams.last start = stream.length yield length = stream.length - start Fragment.new(stream, start, length) end
def helper=(helper)
def helper=(helper) @_helper = helper end
def initialize(assigns = {}, helper = nil, &block)
}
end
end
h1 "Matching Mole"
body do
html do
mab = Markaby::Builder.new {
Pass in a +block+ to new and the block will be evaluated.
from those same blocks.
blocks. If an object is passed in to +helper+, its methods will be available
+assigns+ which will be available as instance variables inside tag construction
Create a Markaby builder object. Pass in a hash of variable assignments to
def initialize(assigns = {}, helper = nil, &block) @streams = [Stream.new] @assigns = assigns.dup @_helper = helper @used_ids = {} @@options.each do |k, v| instance_variable_set("@#{k}", @assigns.delete(k) || v) end @assigns.each do |k, v| instance_variable_set("@#{k}", v) end helper&.instance_variables&.each do |iv| instance_variable_set(iv, helper.instance_variable_get(iv)) end @builder = XmlMarkup.new(indent: @indent, target: @streams.last) text(capture(&block)) if block end
def instance_methods_for(obj)
def instance_methods_for(obj) obj.instance_methods end
def instance_methods_for(obj)
def instance_methods_for(obj) obj.instance_methods.map { |m| m.to_sym } end
def instance_variables_for(obj)
def instance_variables_for(obj) obj.instance_variables end
def instance_variables_for(obj)
def instance_variables_for(obj) obj.instance_variables.map { |var| var.to_sym } end
def locals=(locals)
def locals=(locals) locals.each do |key, value| define_singleton_method(key) { value } end end
def method_missing(sym, *args, &block)
method_missing used to be the lynchpin in Markaby, but it's no longer used to handle
* If a tagset is found, the tagset is tole to handle +sym+
* If +sym+ has come this far and no +tagset+ is found, +sym+ and its arguments are passed to tag!
value of the instance variable is returned.
* If +sym+ is also the name of an instance variable, the
* If +sym+ is a Builder::XmlMarkup method, it is passed on to the builder object.
and output to the stream.
* If +sym+ is a helper method, the helper method is called
variables. Here is the order of interception:
This method is used to intercept calls to helper methods and instance
def method_missing(sym, *args, &block) case response_for(sym) when :helper then @_helper.send(sym, *args, &block) when :assigns then @assigns[sym] when :stringy_assigns then @assigns[sym.to_s] when :ivar then instance_variable_get(ivar) when :helper_ivar then @_helper.instance_variable_get(ivar) when :xml_markup then @builder.__send__(sym, *args, &block) when :tag then tag!(sym, *args, &block) when :tagset then @tagset.handle_tag sym, self, *args, &block else super end end
def respond_to_missing? sym, include_private = false
def respond_to_missing? sym, include_private = false !response_for(sym).nil? end
def response_for sym
def response_for sym return :helper if @_helper.respond_to?(sym, true) return :assigns if @assigns.has_key?(sym) return :stringy_assigns if @assigns.has_key?(sym.to_s) return :ivar if instance_variables_for(self).include?(ivar = "@#{sym}".to_sym) return :helper_ivar if @_helper && instance_variables_for(@_helper).include?(ivar) return :xml_markup if instance_methods_for(::Builder::XmlMarkup).include?(sym) return :tag if @tagset.nil? return :tagset if @tagset.can_handle? sym nil end
def tag!(tag, *args, &block)
Create a tag named +tag+. Other than the first argument which is the tag name,
def tag!(tag, *args, &block) attributes = {} if @auto_validation && @tagset attributes = @tagset.validate_and_transform_attributes!(tag, *args) tag = @tagset.validate_and_transform_tag_name! tag end element_id = attributes[:id].to_s raise InvalidXhtmlError, "id `#{element_id}' already used (id's must be unique)." if @used_ids.has_key?(element_id) if block str = capture(&block) block = proc { text(str) } end f = fragment { @builder.tag!(tag, *args, &block) } @used_ids[element_id] = f unless element_id.empty? f end
def tagset=(tagset)
def tagset=(tagset) @tagset = tagset tagset.default_options.each do |k, v| instance_variable_set("@#{k}".to_sym, v) end end
def text(string)
def text(string) @builder << string.to_s nil end
def to_s
def to_s @streams.last.to_s end