require 'securerandom'
module DraftjsHtml
module Draftjs
class RawBuilder
def self.build(&block)
instance = new
instance.instance_eval(&block)
instance.to_h
end
def initialize
@blocks = []
@entity_map = {}
end
def text_block(text, depth: 0)
typed_block('unstyled', text, depth: depth)
end
def typed_block(type, text, depth: 0)
@blocks << { 'key' => SecureRandom.urlsafe_base64(10), 'text' => text, 'type' => type, 'depth' => depth }
end
def inline_style(style_name, range)
(@blocks.last['inlineStyleRanges'] ||= []) << { 'style' => style_name, 'offset' => range.begin, 'length' => range.size }
end
def entity_range(key, range)
(@blocks.last['entityRanges'] ||= []) << { 'key' => key, 'offset' => range.begin, 'length' => range.size }
end
def apply_entity(type, range, data: {}, mutability: 'IMMUTABLE', key: SecureRandom.uuid)
@entity_map[key] = {
'type' => type,
'mutability' => mutability,
'data' => deep_stringify_keys(data),
}
entity_range(key, range)
end
def has_blocks?
@blocks.any?
end
def to_h
{
'blocks' => @blocks,
'entityMap' => @entity_map,
}
end
def to_s
draftjs = DraftjsHtml::Draftjs.parse(to_h)
draftjs.blocks.reduce('') do |acc, block|
acc << "typed_block '#{block.type}', '#{block.text}', depth: #{block.depth}\n"
block.inline_styles.each do |style|
acc << "inline_style '#{style.name}', #{style.range.begin}..#{style.range.end} # (#{style.offset} + #{style.length})\n"
end
block.entity_ranges.each do |entity_range|
entity = draftjs.entity_map[entity_range.name]
acc << "apply_entity '#{entity.type}', #{entity_range.range.begin}..#{entity_range.range.end}\n"
end
acc
end
end
private
def deep_stringify_keys(object)
case object
when Hash
object.each_with_object({}) do |(key, value), result|
result[key.to_s] = deep_stringify_keys(value)
end
when Array then object.map { |e| deep_stringify_keys(e) }
else
object
end
end
end
end
end