class MaRuKu::MDElement

Rather than having a separate class for every possible element, Maruku has a single {MDElement} class that represents eveything in the document (paragraphs, headers, etc). The type of each element is available via {#node_type}.

Constants

INSPECT_FORMS

Attributes

al[RW]

An attribute list. May not be nil.

@return [AttributeList]

attributes[RW]

The processed attributes.

For the {Maruku document root}, this contains properties listed at the beginning of the document. The properties will be downcased and any spaces will be converted to underscores. For example, if you write in the source document:

!!!text
Title: test document
My property: value

content content

Then {#attributes} will return:

{:title => "test document", :my_property => "value"}

@return [{Symbol => String}]

children[RW]

The child nodes of this element.

@return [Array<String or MDElement>]

doc[RW]

The root element of the document to which this element belongs.

@return [Maruku]

meta_priv[RW]

@private

node_type[RW]

The type of this node (e.g. ‘:quote`, `:image`, `:abbr`). See {Helpers} for a list of possible values.

@return [Symbol]

Public Class Methods

new(node_type = :unset, children = [], meta = {}, al = nil) click to toggle source
# File lib/maruku/element.rb, line 51
def initialize(node_type = :unset, children = [], meta = {}, al = nil)
  self.children = children
  self.node_type = node_type
  self.attributes = {}

  # Define a new accessor on the singleton class for this instance
  # for each metadata key
  meta.each do |symbol, value|
    class << self
      self
    end.send(:attr_accessor, symbol)

    self.send("#{symbol}=", value)
  end

  self.al = al || AttributeList.new
  self.meta_priv = meta
end

Public Instance Methods

==(o) click to toggle source
# File lib/maruku/element.rb, line 73
def ==(o)
  o.is_a?(MDElement) &&
    self.node_type == o.node_type &&
    self.meta_priv == o.meta_priv &&
    self.children == o.children
end
children_to_s() click to toggle source
# File lib/maruku/output/to_s.rb, line 10
def children_to_s
  @children.join
end
each_element(e_node_type=nil) { |c| ... } click to toggle source

Iterates through each {MDElement} child node of this element. This includes deeply-nested child nodes. If ‘e_node_type` is specified, only yields nodes of that type.

# File lib/maruku/element.rb, line 83
def each_element(e_node_type=nil, &block)
  @children.each do |c|
    if c.is_a? MDElement then
      yield c if e_node_type.nil? || c.node_type == e_node_type
      c.each_element(e_node_type, &block)
    #
    # This handles the case where the children of an
    # element are arranged in a multi-dimensional array
    # (as in the case of a table)
    elsif c.is_a? Array then
      c.each do |cc|
        # A recursive call to each_element will ignore the current element
        # so we handle this case inline
        if cc.is_a? MDElement then
          yield cc if e_node_type.nil? || cc.node_type == e_node_type
          cc.each_element(e_node_type, &block)
        end
      end
    end

  end
end
generate_id() click to toggle source

Generate an id for headers. Assumes @children is set.

# File lib/maruku/toc.rb, line 180
def generate_id
  raise "generate_id only makes sense for headers" unless node_type == :header
  generated_id = children_to_s.tr(' ', '_').downcase.gsub(/\W/, '').strip
  num_occurs = (@doc.header_ids[generated_id] += 1)
  generated_id += "_#{num_occurs}" if num_occurs > 1
  generated_id
end
get_setting(sym) click to toggle source
# File lib/maruku/defaults.rb, line 39
def get_setting(sym)
  return attributes[sym] if attributes.has_key?(sym)
  return doc.attributes[sym] if doc && doc.attributes.has_key?(sym)
  return MaRuKu::Globals[sym] if MaRuKu::Globals.has_key?(sym)

  $stderr.puts "Bug: no default for #{sym.inspect}"
  nil
end
inspect() click to toggle source

Outputs the document AST as calls to document helpers. (this should be ‘eval`-able to get a copy of the original element).

# File lib/maruku/inspect_element.rb, line 24
def inspect
  if INSPECT_FORMS.has_key? @node_type
    name, *params = INSPECT_FORMS[@node_type]

    params = params.map do |p|
      if p == :children
        children_inspect
      else
        send(p).inspect
      end
    end
    params << @al.inspect if @al && !@al.empty?
  else
    name = 'el'
    params = [self.node_type.inspect, children_inspect]
    params << @meta_priv.inspect unless @meta_priv.empty? && self.al.empty?
    params << self.al.inspect unless self.al.empty?
  end

  "md_#{name}(#{params.join(', ')})"
end
md_div(children, al = nil) click to toggle source
# File lib/maruku/ext/div.rb, line 91
def md_div(children, al = nil)
  type = label = num = nil
  doc.refid2ref ||= {}
  if al
    al.each do |k, v|
      case k
      when :class; type = $1 if v =~ /^num_(\w*)/
      when :id; label = v
      end
    end
  end

  if type
    doc.refid2ref[type] ||= {}
    num = doc.refid2ref[type].length + 1
    if !label
      doc.id_counter += 1
            label =  "div_" + doc.id_counter.to_s
    end
  end

  e = self.md_el(:div, children, {:label => label, :type => type, :num => num}, al)
  doc.refid2ref[type].update(label => e) if type && label
  e
end
md_equation(math, label, numerate) click to toggle source
# File lib/maruku/ext/math/elements.rb, line 7
def md_equation(math, label, numerate)
  reglabel = /\\label\{(\w+)\}/
  math = math.gsub(reglabel, '') if label = math[reglabel, 1]
  num = nil
  if (label || numerate) && @doc # take number
    @doc.eqid2eq ||= {}
    num = @doc.eqid2eq.size + 1
    label = "eq#{num}" unless label # TODO do id for document
  end
  e = self.md_el(:equation, [], :math => math, :label => label, :num => num)
  @doc.eqid2eq[label] = e if label && @doc # take number
  e
end
md_inline_math(math) click to toggle source
# File lib/maruku/ext/math/elements.rb, line 3
def md_inline_math(math)
  self.md_el(:inline_math, [], :math => math)
end
replace_each_string() { |c| ... } click to toggle source

Iterates through each String child node of this element, replacing it with the result of the block. This includes deeply-nested child nodes.

This destructively modifies this node and its children.

@todo Make this non-destructive

# File lib/maruku/element.rb, line 113
def replace_each_string(&block)
  @children.map! do |c|
    next yield c if c.is_a?(String)
    c.replace_each_string(&block)
    c
  end
  @children.flatten! unless self.node_type == :table
end
to_s() click to toggle source

Strips all formatting from the string

# File lib/maruku/output/to_s.rb, line 6
def to_s
  children_to_s
end

Private Instance Methods

children_inspect() click to toggle source
# File lib/maruku/inspect_element.rb, line 48
def children_inspect
  kids = @children.map(&:inspect)
  return kids.first if kids.size == 1

  comma = kids.join(", ")
  if comma.size < 70
    "[#{comma}]"
  else
    "[\n\t#{kids.join(",\n\t")}\n]"
  end
end