Class: RichText::Document::Entry

Inherits:
RootedTree::Node
  • Object
show all
Includes:
Styleable
Defined in:
lib/richtext/document/entry.rb

Overview

The Entry class extends the basic Node class and adds methods that make handling text a little nicer. Essentially the :text attribute is given special status by allowing it to a) be set during initialization, b) only visible in leaf nodes and c) copied over when adding children to leaf nodes.

Some attributes are also supported explicitly by the inclusion of special accesser methods. The attributes are are bold, italic, underline, color and font.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Styleable

#bold=, #bold?, #color, #color=, #font, #font=, #italic=, #italic?, #underlined=, #underlined?

Constructor Details

#initialize(text = nil, **attributes) ⇒ Entry

Extend the default Node initializer by also accepting a string. It will, if given, be stored as a text attribute.



25
26
27
28
# File 'lib/richtext/document/entry.rb', line 25

def initialize(text = nil, **attributes)
  @attributes = attributes
  super text
end

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



19
20
21
# File 'lib/richtext/document/entry.rb', line 19

def attributes
  @attributes
end

Instance Method Details

#[](key) ⇒ Object

Accessor for single attributes.

key - the attribute key

Returns the attribute value if it is set and nil otherwise.



45
46
47
# File 'lib/richtext/document/entry.rb', line 45

def [](key)
  attributes[key]
end

#[]=(key, v) ⇒ Object

Write a single attribute.

key - the attribute key v - the new value



54
55
56
# File 'lib/richtext/document/entry.rb', line 54

def []=(key, v)
  attributes[key] = v
end

#append_child(child_text = nil, **attributes) ⇒ Object Also known as: <<

Create and append a new child, initialized with the given text and attributes.

child_text - the text of the child or an Entry object. attributes - a hash of attributes to apply to the child if child_text is

not an Entry object.

Returns self to allow chaining.



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/richtext/document/entry.rb', line 83

def append_child(child_text = nil, **attributes)
  if leaf? && !text.empty?
    super self.class.new(value)
  end

  if child_text.is_a? self.class
    super child_text
  else
    super self.class.new(child_text, attributes)
  end
end

#freezeObject

Freeze the attributes hash, as well as the node structure.

Returns self.



34
35
36
37
# File 'lib/richtext/document/entry.rb', line 34

def freeze
  @attributes.freeze
  super
end

#inspect(*args, &block) ⇒ Object

Represents the Entry structure as a hierarchy, showing the attributes of each node as well as the text entries in the leafs.

If a block is given, it will be called once for each entry, and the returned string will be used to represent the object in the output graph.

Returns a string. Note that it will contain newline characters if the node has children.



168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/richtext/document/entry.rb', line 168

def inspect *args, &block
  unless block_given?
    block = proc do |entry|
      base_name = entry.leaf? ? %Q{"#{entry.text}"} : ''
      base_name + entry.attributes.reduce('') do |a, (k, v)|
        a + " #{k}=#{v.inspect}"
      end
    end
  end

  super(*args, &block)
end

#optimize(&block) ⇒ Object

Optimize a copy of the node tree based on the rules outlined for #optimize!.

Returns the root of the new optimized node structure.



133
134
135
# File 'lib/richtext/document/entry.rb', line 133

def optimize(&block)
  dup.optimize!(&block)
end

#optimize!(&block) ⇒ Object

Go through each child and merge any node that a) is not a lead node and b) only has one child, with its child. The attributes of the child will override those of the parent.

Returns self.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/richtext/document/entry.rb', line 103

def optimize!(&block)
  # If the node is a leaf it cannot be optimized further
  return self if leaf?

  block = proc { |e| e.leaf? && e.text.empty? } unless block_given?

  children.each do |child|
    child.delete if block.call child.optimize!(&block)
  end

  # If we only have one child it is superfluous and
  # should be merged. That means this node will inherrit
  # the children of the single child as well as its
  # attributes
  if degree == 1
    # Move the attributes over
    attributes.merge! child.attributes
    self.value = child.text
    # Get the children of the child and add them to self
    first_child.delete.each { |child| append_child child }
  end

  self
end

#textObject

Read the text of the node.

Returns the string stored in the node, if it is a leaf. Otherwise nil.



62
63
64
# File 'lib/richtext/document/entry.rb', line 62

def text
  value || '' if leaf?
end

#text=(new_text) ⇒ Object

Write the text of the node. The method will raise a RuntimeException if the node is not a leaf.



69
70
71
72
# File 'lib/richtext/document/entry.rb', line 69

def text=(new_text)
  raise 'Only leafs can have a text entry' unless leaf?
  self.value = new_text
end

#to_s(&block) ⇒ Object

Combine the text from all the leaf nodes in the tree, from left to right. If a block is given the node, along with its text will be passed as arguments. The block will be called recursivly, starting at the leaf nodes and propagating up until the entire tree has been “rendered” in this way.

block - a block that will be used to generate strings for each node.

Returns a string representation of the node structure.



147
148
149
150
151
152
153
154
155
156
# File 'lib/richtext/document/entry.rb', line 147

def to_s(&block)
  string =
    if leaf?
      text
    else
      children.reduce('') { |a, e| a + e.to_s(&block) }
    end

  block_given? ? yield(self, string) : string
end