Class: MaRuKu::MDElement

Inherits:
Object
  • Object
show all
Includes:
MaRuKu, Errors, Helpers, Out::HTML, Out::Latex, Out::Markdown, Strings
Defined in:
lib/maruku/element.rb,
lib/maruku.rb,
lib/maruku/toc.rb,
lib/maruku/ext/div.rb,
lib/maruku/defaults.rb,
lib/maruku/output/to_s.rb,
lib/maruku/inspect_element.rb,
lib/maruku/ext/math/elements.rb

Overview

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.

Direct Known Subclasses

MDDocument, MDHTMLElement

Constant Summary collapse

INSPECT_FORMS =
{
  :paragraph          => ["par",      :children],
  :footnote_reference => ["foot_ref", :footnote_id],
  :entity             => ["entity",   :entity_name],
  :email_address      => ["email",    :email],
  :inline_code        => ["code",     :raw_code],
  :raw_html           => ["html",     :raw_html],
  :emphasis           => ["em",       :children],
  :strong             => ["strong",   :children],
  :immediate_link     => ["url",      :url],
  :image              => ["image",    :children, :ref_id],
  :im_image           => ["im_image", :children, :url, :title],
  :link               => ["link",     :children, :ref_id],
  :im_link            => ["im_link",  :children, :url, :title],
  :ref_definition     => ["ref_def",  :ref_id, :url, :title],
  :ial                => ["ial",      :ial],
  :li                 => ["li",       :children, :want_my_paragraph]
}

Constants included from Errors

Errors::FRAME_WIDTH

Constants included from Strings

Strings::TAB_SIZE

Constants included from Out::Latex

Out::Latex::LATEX_ADD_SLASH, Out::Latex::LATEX_TO_CHARCODE, Out::Latex::Latex_preamble_enc_cjk, Out::Latex::Latex_preamble_enc_utf8, Out::Latex::OtherGoodies, Out::Latex::SAFE_CHARS

Constants included from Out::HTML

Out::HTML::HTML4Attributes, Out::HTML::Xhtml11_mathml2_svg11

Constants included from Out::Markdown

Out::Markdown::DefaultLineLength

Constants included from MaRuKu

Abbreviation, AttributeDefinitionList, BLOCK_TAGS, Definition, EMailAddress, FootnoteText, Globals, HTML_INLINE_ELEMS, IncompleteLink, InlineAttributeList, LinkRegex, MARUKU_URL, MarukuURL, S5_Fancy, S5_external, TableSeparator, VERSION, Version

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Errors

#maruku_error, #maruku_recover, #raise_error, #tell_user

Methods included from Helpers

#md_abbr, #md_abbr_def, #md_ald, #md_br, #md_code, #md_codeblock, #md_el, #md_em, #md_email, #md_emstrong, #md_entity, #md_foot_ref, #md_footnote, #md_header, #md_hrule, #md_html, #md_ial, #md_im_image, #md_im_link, #md_image, #md_li, #md_link, #md_par, #md_quote, #md_ref_def, #md_strong, #md_url, #md_xml_instr

Methods included from Strings

#parse_email_headers, #sanitize_ref_id, #spaces_before_first_char, #split_lines, #strip_indent, #unquote

Methods included from Out::Latex

#array_to_latex, #children_to_latex, #latex_color, #latex_escape, #render_latex_signature, #string_to_latex, #to_latex, #to_latex_abbr, #to_latex_cell, #to_latex_citation, #to_latex_code, #to_latex_definition, #to_latex_definition_list, #to_latex_div, #to_latex_divref, #to_latex_document, #to_latex_email_address, #to_latex_emphasis, #to_latex_entity, #to_latex_eqref, #to_latex_equation, #to_latex_footnote_reference, #to_latex_head_cell, #to_latex_header, #to_latex_hrule, #to_latex_im_link, #to_latex_image, #to_latex_immediate_link, #to_latex_inline_code, #to_latex_inline_math, #to_latex_li, #to_latex_linebreak, #to_latex_link, #to_latex_ol, #to_latex_paragraph, #to_latex_quote, #to_latex_raw_html, #to_latex_strong, #to_latex_table, #to_latex_ul, #wrap_as_environment, #wrap_as_span

Methods included from Out::HTML

#add_class_to, #add_css_to, #add_ws, #adjust_png, #array_to_html, #children_to_html, #convert_to_mathml_blahtex, #convert_to_mathml_itex2mml, #convert_to_mathml_none, #convert_to_mathml_ritex, #convert_to_png_blahtex, #convert_to_png_none, #day_suffix, escapeHTML, #html_element, #maruku_html_signature, #nice_date, #obfuscate, #pixels_per_ex, #render_footnotes, #render_mathml, #render_png, #render_section_number, #section_number, #to_html, #to_html_abbr, #to_html_cell, #to_html_citation, #to_html_code, #to_html_code_using_pre, #to_html_definition, #to_html_definition_data, #to_html_definition_list, #to_html_definition_term, #to_html_div, #to_html_divref, #to_html_document, #to_html_document_tree, #to_html_email_address, #to_html_emphasis, #to_html_entity, #to_html_eqref, #to_html_equation, #to_html_footnote_reference, #to_html_head_cell, #to_html_header, #to_html_hrule, #to_html_im_image, #to_html_im_link, #to_html_image, #to_html_immediate_link, #to_html_inline_code, #to_html_inline_math, #to_html_li, #to_html_linebreak, #to_html_link, #to_html_ol, #to_html_paragraph, #to_html_quote, #to_html_raw_html, #to_html_ref_definition, #to_html_strong, #to_html_table, #to_html_ul, #to_html_xml_instr, #to_latex_ref_definition, #wrap_as_element, #xelem, #xml_newline, #xtext

Methods included from Out::Markdown

#add_indent, #array_to_md, #children_to_md, #mysplit, #to_md, #to_md_abbr_def, #to_md_code, #to_md_email_address, #to_md_emphasis, #to_md_entity, #to_md_header, #to_md_hrule, #to_md_im_image, #to_md_im_link, #to_md_image, #to_md_immediate_link, #to_md_inline_code, #to_md_linebreak, #to_md_link, #to_md_ol, #to_md_paragraph, #to_md_quote, #to_md_ref_definition, #to_md_strong, #to_md_ul, #wrap

Methods included from MaRuKu

#markdown_extra?, #new_meta_data?, textile2

Constructor Details

#initialize(node_type = :unset, children = [], meta = {}, al = nil) ⇒ MDElement

Returns a new instance of MDElement.


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 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

Instance Attribute Details

#alAttributeList

An attribute list. May not be nil.

Returns:


21
22
23
# File 'lib/maruku/element.rb', line 21

def al
  @al
end

#attributes{Symbol => String}

The processed attributes.

For the 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:

Title: test document
My property: value

content content

Then #attributes will return:

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

Returns:


43
44
45
# File 'lib/maruku/element.rb', line 43

def attributes
  @attributes
end

#childrenArray<String or MDElement>

The child nodes of this element.

Returns:


16
17
18
# File 'lib/maruku/element.rb', line 16

def children
  @children
end

#docMaruku

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

Returns:


49
50
51
# File 'lib/maruku/element.rb', line 49

def doc
  @doc
end

#meta_privObject


71
72
73
# File 'lib/maruku/element.rb', line 71

def meta_priv
  @meta_priv
end

#node_typeSymbol

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

Returns:

  • (Symbol)

11
12
13
# File 'lib/maruku/element.rb', line 11

def node_type
  @node_type
end

Instance Method Details

#==(o) ⇒ Object


73
74
75
76
77
78
# 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_sObject


10
11
12
# File 'lib/maruku/output/to_s.rb', line 10

def children_to_s
  @children.join
end

#each_element(e_node_type = nil, &block) ⇒ Object

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


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# 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_idObject

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


180
181
182
183
184
185
186
# 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) ⇒ Object


39
40
41
42
43
44
45
46
# 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

#inspectObject

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


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 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) ⇒ Object


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# 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) ⇒ Object


7
8
9
10
11
12
13
14
15
16
17
18
19
# 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) ⇒ Object


3
4
5
# 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(&block) ⇒ Object

TODO:

Make this non-destructive

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.


113
114
115
116
117
118
119
120
# 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_sObject

Strips all formatting from the string


6
7
8
# File 'lib/maruku/output/to_s.rb', line 6

def to_s
  children_to_s
end