ignitionworks/draftjs_exporter

View on GitHub
lib/draftjs_exporter/entity_state.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true
require 'draftjs_exporter/entities/null'
require 'draftjs_exporter/error'

module DraftjsExporter
  class InvalidEntity < DraftjsExporter::Error; end

  class EntityState
    attr_reader :entity_decorators, :entity_map, :entity_stack, :root_element

    def initialize(root_element, entity_decorators, entity_map)
      @entity_decorators = entity_decorators
      @entity_map = entity_map
      @entity_stack = [[Entities::Null.new.call(root_element, nil), nil]]
    end

    def apply(command)
      case command.name
      when :start_entity
        start_command(command)
      when :stop_entity
        stop_command(command)
      end
    end

    def current_parent
      element, _data = entity_stack.last
      element
    end

    private

    def start_command(command)
      entity_details = entity_for(command.data)

      decorator = entity_decorators.fetch(entity_details.fetch(:type))
      parent_element = entity_stack.last.first
      new_element = decorator.call(parent_element, entity_details)
      entity_stack.push([new_element, entity_details])
    end

    def stop_command(command)
      entity_details = entity_for(command.data)
      _element, expected_entity_details = entity_stack.last

      if expected_entity_details != entity_details
        raise InvalidEntity, "Expected #{expected_entity_details.inspect} got #{entity_details.inspect}"
      end

      entity_stack.pop
    end

    def entity_for(key)
      entity_keys = [key.to_s, key.to_s.to_sym]
      entity_keys.map { |key| entity_map.fetch(key, nil) }.compact.first
    end
  end
end