content: import ReactDOM from 'react-dom';
  import React from 'react';
  import _ from 'lodash';
  import {toCamelCase} from './case-convert';
  
  const components = {},
    mountedComponents = {},
    config = {
      camelCase: true,
      unmountRemovedComponents: true,
      defaultProps: {}
    };
  
  export function _configure(newConfig) {
    _.extend(config, newConfig);
  }
  
  export function registerComponent(name, component) {
    if (typeof component === 'undefined' && typeof name === 'function') {
      component = name;
      name = component.name;
    }
  
    components[name] = component;
  }
  
  function mount(component, props, rootNode, config) {
    const element = React.createElement(
      component,
      parseProps(_.extend({}, props, config.defaultProps), {camelCase: config.camelCase}),
      null
    );
    return ReactDOM.render(
      element, rootNode
    );
  }
  
  function parseProps(props, {camelCase = true}) {
    props = _.mapValues(props, (value, key, object) => {
      if (_.isObject(value) && _.isEqual(_.keys(value), ['$component']))
        return () => mountedComponents[value.$component];
      if (_.isObject(value) && _.isEqual(_.keys(value), ['$window']))
        return window[value.$window];
      return value;
    });
    if (camelCase) props = toCamelCase(props);
    return props;
  }
  
  function getRootNode(scriptNode) {
    let rootNode = document.getElementById(scriptNode.id + '-root');
    if (rootNode) return rootNode;
    rootNode = document.createElement(scriptNode.dataset.rootType || 'div');
    rootNode.id = scriptNode.id + '-root';
    if (scriptNode.dataset.rootClass)
      rootNode.className = scriptNode.dataset.rootClass;
    scriptNode.parentNode.insertBefore(rootNode, scriptNode);
    return rootNode;
  }
  
  export function getMountedComponent(component) {
    return mountedComponents[component];
  }
  
  function inDocument(node) {
    return document.contains(node);
  }
  
  function unmountComponent(component) {
    const root = ReactDOM.findDOMNode(component);
    if (root)
      ReactDOM.unmountComponentAtNode(root.parentNode);
  }
  
  function isRemoved(component) {
    const root = ReactDOM.findDOMNode(component);
    if (!root)
      return true;
    return !inDocument(root.parentNode);
  }
  
  function unmountRemovedComponents() {
    const previouslyMountedComponents = _.extend({}, mountedComponents);
    for (const componentId in previouslyMountedComponents) {
      if (!previouslyMountedComponents.hasOwnProperty(componentId)) continue;
      if (isRemoved(previouslyMountedComponents[componentId])) {
        unmountComponent(previouslyMountedComponents[componentId]);
        delete previouslyMountedComponents[componentId];
      }
    }
  }
  
  export function mountAll() {
    // Set defaults
    if (config.unmountRemovedComponents) unmountRemovedComponents();
  
    // Get all scripts
    const scripts = document.querySelectorAll('script[data-component]');
    for (let i = 0; i < scripts.length; i++) {
      const script = scripts[i];
      // Ensure script has an id
      if (typeof script.id === 'undefined') {
        console.error('Auntomount scripts need to have an id');
        continue;
      }
  
      // Ensure component is not already mounted
      if (typeof mountedComponents[script.id] !== 'undefined') continue;
  
      // Ensure component is registered
      if (typeof components[script.dataset.component] === 'undefined') {
        console.error(script.dataset.component, 'is not registered with automount');
        continue;
      }
  
      // Create root for element
      const root = getRootNode(script);
  
      let props;
      try {
        props = JSON.parse(script.innerHTML.trim());
      } catch (error) {
        props = {};
      }
  
      // Mount component
      mountedComponents[script.id] = mount(
        components[script.dataset.component],
        props,
        root,
        config
      );
  
      // Link to original script for external usage
      script.__component = mountedComponents[script.id];
    }
  }
  