Class: RichText::Op
- Inherits:
-
Object
- Object
- RichText::Op
- Defined in:
- lib/rich-text/op.rb
Overview
Operations are the immutable units of rich-text deltas and documents. As such, we have a class that wraps these values and provides convenient methods for querying type and contents, and for subdividing as needed by Delta#slice.
Constant Summary collapse
- TYPES =
[:insert, :retain, :delete].freeze
Instance Attribute Summary collapse
- #attributes ⇒ Hash readonly
-
#type ⇒ Symbol
readonly
One of TYPES.
-
#value ⇒ String, ...
readonly
Value depends on type.
Class Method Summary collapse
-
.parse(data) ⇒ Op
Creates a new Op object from a Hash.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
(also: #eql?)
An Op is equal to another if type, value, and attributes all match.
-
#attributes? ⇒ Boolean
Whether any attributes are present;
falsewhen attributes is empty,trueotherwise. -
#delete? ⇒ Boolean
Returns whether type is
:deleteor not. -
#initialize(type, value, attributes = nil) ⇒ Op
constructor
Creates a new Op object, based on a type, value, and attributes.
-
#insert?(kind = Object) ⇒ Boolean
Returns whether type is
:insert, and value is an instance ofkind. -
#inspect(wrap = true) ⇒ String
A string useful for debugging, that includes type, value, and attributes.
-
#length ⇒ Integer
Returns a number indicating the length of this op, depending of the type:.
-
#retain? ⇒ Boolean
Returns whether type is
:retainor not. -
#slice(start = 0, len = length) ⇒ Op
Returns a copy of the op with a subset of the value, measured in number of characters.
-
#to_h ⇒ Hash
The Hash representation of this object, the inverse of Op.parse.
-
#to_json(*args) ⇒ String
The JSON representation of this object, by delegating to #to_h.
Constructor Details
#initialize(type, value, attributes = nil) ⇒ Op
Creates a new Op object, based on a type, value, and attributes. No sanity checking is performed on the arguments; please use parse for dealing with untrusted user input.
51 52 53 54 55 |
# File 'lib/rich-text/op.rb', line 51 def initialize(type, value, attributes = nil) @type = type.to_sym @value = value.freeze @attributes = (attributes || {}).freeze end |
Instance Attribute Details
#attributes ⇒ Hash (readonly)
13 14 15 |
# File 'lib/rich-text/op.rb', line 13 def attributes @attributes end |
#type ⇒ Symbol (readonly)
Returns one of TYPES.
9 10 11 |
# File 'lib/rich-text/op.rb', line 9 def type @type end |
#value ⇒ String, ... (readonly)
Returns value depends on type.
11 12 13 |
# File 'lib/rich-text/op.rb', line 11 def value @value end |
Class Method Details
.parse(data) ⇒ Op
Creates a new Op object from a Hash. Used by Delta#initialize to parse raw data into a convenient form.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/rich-text/op.rb', line 25 def self.parse(data) data = data.to_h.with_indifferent_access type_keys = (data.keys & TYPES.map(&:to_s)) if type_keys.length != 1 raise ArgumentError.new("must be a Hash containing exactly one of the following keys: #{TYPES.inspect}") end type = type_keys.first.to_sym value = data[type] if [:retain, :delete].include?(type) && !value.is_a?(Integer) raise ArgumentError.new("value must be an Integer when type is #{type.inspect}") end attributes = data[:attributes] if attributes && !attributes.is_a?(Hash) raise ArgumentError.new("attributes must be a Hash") end self.new(type, value, attributes) end |
Instance Method Details
#==(other) ⇒ Boolean Also known as: eql?
An Op is equal to another if type, value, and attributes all match
148 149 150 |
# File 'lib/rich-text/op.rb', line 148 def ==(other) other.is_a?(Op) && type == other.type && value == other.value && attributes == other.attributes end |
#attributes? ⇒ Boolean
Returns whether any attributes are present; false when attributes is empty, true otherwise.
62 63 64 |
# File 'lib/rich-text/op.rb', line 62 def attributes? !attributes.empty? end |
#delete? ⇒ Boolean
Returns whether type is :delete or not
85 86 87 |
# File 'lib/rich-text/op.rb', line 85 def delete? type == :delete end |
#insert?(kind = Object) ⇒ Boolean
Returns whether type is :insert, and value is an instance of kind
73 74 75 |
# File 'lib/rich-text/op.rb', line 73 def insert?(kind = Object) type == :insert && value.is_a?(kind) end |
#inspect(wrap = true) ⇒ String
A string useful for debugging, that includes type, value, and attributes.
139 140 141 142 143 |
# File 'lib/rich-text/op.rb', line 139 def inspect(wrap = true) str = "#{type}=#{value.inspect}" str << " #{attributes.inspect}" if attributes? wrap ? "#<#{self.class.name} #{str}>" : str end |
#length ⇒ Integer
Returns a number indicating the length of this op, depending of the type:
- for
:insert, returnsvalue.lengthif a String, 1 otherwise - for
:retainand:delete, returns value
94 95 96 97 98 99 100 101 |
# File 'lib/rich-text/op.rb', line 94 def length case type when :insert value.is_a?(String) ? value.length : 1 when :retain, :delete value end end |
#retain? ⇒ Boolean
Returns whether type is :retain or not
79 80 81 |
# File 'lib/rich-text/op.rb', line 79 def retain? type == :retain end |
#slice(start = 0, len = length) ⇒ Op
Returns a copy of the op with a subset of the value, measured in number of characters. An op may be subdivided if needed to return at most the requested length. Non-string inserts cannot be subdivided (naturally, as they have length 1).
108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/rich-text/op.rb', line 108 def slice(start = 0, len = length) if insert?(String) Op.new(:insert, value.slice(start, len), attributes) elsif insert? unless start == 0 && len == 1 raise ArgumentError.new("cannot subdivide a non-string insert") end dup else Op.new(type, [value - start, len].min, attributes) end end |
#to_h ⇒ Hash
Returns the Hash representation of this object, the inverse of parse.
122 123 124 125 126 |
# File 'lib/rich-text/op.rb', line 122 def to_h { type => value }.tap do |json| json[:attributes] = attributes if attributes? end end |
#to_json(*args) ⇒ String
Returns the JSON representation of this object, by delegating to #to_h.
129 130 131 |
# File 'lib/rich-text/op.rb', line 129 def to_json(*args) to_h.to_json(*args) end |