class Markaby::Builder
The Markaby::Builder class is the central gear in the system. When using from Ruby code, this is the only class you need to instantiate directly.
mab = Markaby::Builder.new mab.html do head { title "Boats.com" } body do h1 "Boats.com has great deals" ul do li "$49 for a canoe" li "$39 for a raft" li "$29 for a huge boot that floats and can fit 5 people" end end end puts mab.to_s
Constants
- DEFAULT_OPTIONS
- HTML5_OPTIONS
Attributes
Public Class Methods
# File lib/markaby/builder.rb, line 65 def self.get(option) @@options[option] end
# File lib/markaby/builder.rb, line 73 def self.ignore_helpers(*helpers) ignored_helpers.concat helpers end
# File lib/markaby/builder.rb, line 69 def self.ignored_helpers @@ignored_helpers ||= [] end
Create a Markaby builder object. Pass in a
hash of variable assignments to assigns
which will be
available as instance variables inside tag construction blocks. If an
object is passed in to helper
, its methods will be available
from those same blocks.
Pass in a block
to new and the block will be evaluated.
mab = Markaby::Builder.new { html do body do h1 "Matching Mole" end end }
# File lib/markaby/builder.rb, line 94 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 if helper helper.instance_variables.each do |iv| instance_variable_set(iv, helper.instance_variable_get(iv)) end end @builder = XmlMarkup.new(:indent => @indent, :target => @streams.last) text(capture(&block)) if block end
# File lib/markaby/builder.rb, line 53 def self.restore_defaults! @@options = DEFAULT_OPTIONS.dup end
# File lib/markaby/builder.rb, line 61 def self.set(option, value) @@options[option] = value end
# File lib/markaby/builder.rb, line 57 def self.set_html5_options! @@options = HTML5_OPTIONS.dup end
Public Instance Methods
Captures the HTML code built inside the block
. This is done
by creating a new stream for the builder object, running the block and
passing back its stream as a string.
>> Markaby::Builder.new.capture { h1 "TEST"; h2 "CAPTURE ME" } => "<h1>TEST</h1><h2>CAPTURE ME</h2>"
# File lib/markaby/builder.rb, line 159 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
# File lib/markaby/builder.rb, line 119 def helper=(helper) @_helper = helper end
# File lib/markaby/builder.rb, line 130 def locals=(locals) locals.each do |key, value| metaclass do define_method key do value end end end end
Create a tag named tag
. Other than the first argument which is
the tag name, the arguments are the same as the tags implemented via
method_missing.
# File lib/markaby/builder.rb, line 172 def tag!(tag, *args, &block) ele_id = nil if @auto_validation && @tagset if !@tagset.tagset.has_key?(tag) raise InvalidXhtmlError, "no element `#{tag}' for #{tagset.doctype}" elsif args.last.respond_to?(:to_hash) attrs = args.last.to_hash if @tagset.forms.include?(tag) && attrs[:id] attrs[:name] ||= attrs[:id] end attrs.each do |k, v| atname = k.to_s.downcase.intern unless k =~ /:/ or @tagset.tagset[tag].include? atname raise InvalidXhtmlError, "no attribute `#{k}' on #{tag} elements" end if atname == :id ele_id = v.to_s if @used_ids.has_key? ele_id raise InvalidXhtmlError, "id `#{ele_id}' already used (id's must be unique)." end end if AttrsBoolean.include? atname if v attrs[k] = atname.to_s else attrs.delete k end end end end end if block str = capture(&block) block = proc { text(str) } end f = fragment { @builder.tag!(tag, *args, &block) } @used_ids[ele_id] = f if ele_id f end
Write a string
to the HTML stream without escaping it.
# File lib/markaby/builder.rb, line 146 def text(string) @builder << string.to_s nil end
Returns a string containing the HTML stream. Internally, the stream is stored as an Array.
# File lib/markaby/builder.rb, line 141 def to_s @streams.last.to_s end
Private Instance Methods
# File lib/markaby/builder.rb, line 276 def fragment stream = @streams.last start = stream.length yield length = stream.length - start Fragment.new(stream, start, length) end
# File lib/markaby/builder.rb, line 263 def instance_methods_for(obj) obj.instance_methods end
# File lib/markaby/builder.rb, line 259 def instance_variables_for(obj) obj.instance_variables end
# File lib/markaby/builder.rb, line 123 def metaclass(&block) metaclass = class << self; self; end metaclass.class_eval(&block) end
This method is used to intercept calls to helper methods and instance variables. Here is the order of interception:
-
If
sym
is a helper method, the helper method is called and output to the stream. -
If
sym
is a Builder::XmlMarkup method, it is passed on to the builder object. -
If
sym
is also the name of an instance variable, the value of the instance variable is returned. -
If
sym
has come this far and notagset
is found,sym
and its arguments are passed to tag! -
If a tagset is found, though,
NoMethodError
is raised.
#method_missing used to be the lynchpin in Markaby, but it's no longer used to handle HTML tags. See html_tag for that.
# File lib/markaby/builder.rb, line 231 def method_missing(sym, *args, &block) if @_helper.respond_to?(sym, true) && !self.class.ignored_helpers.include?(sym) r = @_helper.send(sym, *args, &block) if @output_helpers && r.respond_to?(:to_str) fragment { @builder << r } else r end elsif @assigns.has_key?(sym) @assigns[sym] elsif @assigns.has_key?(stringy_key = sym.to_s) # Rails' ActionView assigns hash has string keys for # instance variables that are defined in the controller. @assigns[stringy_key] elsif instance_variables_for(self).include?(ivar = "@#{sym}".to_sym) instance_variable_get(ivar) elsif @_helper && instance_variables_for(@_helper).include?(ivar) @_helper.instance_variable_get(ivar) elsif instance_methods_for(::Builder::XmlMarkup).include?(sym) @builder.__send__(sym, *args, &block) elsif !@tagset tag!(sym, *args, &block) else super end end