content: import PropTypes from 'prop-types';
  import withSideEffect from 'react-side-effect';
  import isEqual from 'react-fast-compare';
  import React from 'react';
  import objectAssign from 'object-assign';
  
  var ATTRIBUTE_NAMES = {
      BODY: "bodyAttributes",
      HTML: "htmlAttributes",
      TITLE: "titleAttributes"
  };
  
  var TAG_NAMES = {
      BASE: "base",
      BODY: "body",
      HEAD: "head",
      HTML: "html",
      LINK: "link",
      META: "meta",
      NOSCRIPT: "noscript",
      SCRIPT: "script",
      STYLE: "style",
      TITLE: "title"
  };
  
  var VALID_TAG_NAMES = Object.keys(TAG_NAMES).map(function (name) {
      return TAG_NAMES[name];
  });
  
  var TAG_PROPERTIES = {
      CHARSET: "charset",
      CSS_TEXT: "cssText",
      HREF: "href",
      HTTPEQUIV: "http-equiv",
      INNER_HTML: "innerHTML",
      ITEM_PROP: "itemprop",
      NAME: "name",
      PROPERTY: "property",
      REL: "rel",
      SRC: "src"
  };
  
  var REACT_TAG_MAP = {
      accesskey: "accessKey",
      charset: "charSet",
      class: "className",
      contenteditable: "contentEditable",
      contextmenu: "contextMenu",
      "http-equiv": "httpEquiv",
      itemprop: "itemProp",
      tabindex: "tabIndex"
  };
  
  var HELMET_PROPS = {
      DEFAULT_TITLE: "defaultTitle",
      DEFER: "defer",
      ENCODE_SPECIAL_CHARACTERS: "encodeSpecialCharacters",
      ON_CHANGE_CLIENT_STATE: "onChangeClientState",
      TITLE_TEMPLATE: "titleTemplate"
  };
  
  var HTML_TAG_MAP = Object.keys(REACT_TAG_MAP).reduce(function (obj, key) {
      obj[REACT_TAG_MAP[key]] = key;
      return obj;
  }, {});
  
  var SELF_CLOSING_TAGS = [TAG_NAMES.NOSCRIPT, TAG_NAMES.SCRIPT, TAG_NAMES.STYLE];
  
  var HELMET_ATTRIBUTE = "data-react-helmet";
  
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  };
  
  var classCallCheck = function (instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  };
  
  var createClass = function () {
    function defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
      }
    }
  
    return function (Constructor, protoProps, staticProps) {
      if (protoProps) defineProperties(Constructor.prototype, protoProps);
      if (staticProps) defineProperties(Constructor, staticProps);
      return Constructor;
    };
  }();
  
  var _extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];
  
      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }
  
    return target;
  };
  
  var inherits = function (subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
  
    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  };
  
  var objectWithoutProperties = function (obj, keys) {
    var target = {};
  
    for (var i in obj) {
      if (keys.indexOf(i) >= 0) continue;
      if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
      target[i] = obj[i];
    }
  
    return target;
  };
  
  var possibleConstructorReturn = function (self, call) {
    if (!self) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
  
    return call && (typeof call === "object" || typeof call === "function") ? call : self;
  };
  
  var encodeSpecialCharacters = function encodeSpecialCharacters(str) {
      var encode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
  
      if (encode === false) {
          return String(str);
      }
  
      return String(str).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
  };
  
  var getTitleFromPropsList = function getTitleFromPropsList(propsList) {
      var innermostTitle = getInnermostProperty(propsList, TAG_NAMES.TITLE);
      var innermostTemplate = getInnermostProperty(propsList, HELMET_PROPS.TITLE_TEMPLATE);
  
      if (innermostTemplate && innermostTitle) {
          // use function arg to avoid need to escape $ characters
          return innermostTemplate.replace(/%s/g, function () {
              return Array.isArray(innermostTitle) ? innermostTitle.join("") : innermostTitle;
          });
      }
  
      var innermostDefaultTitle = getInnermostProperty(propsList, HELMET_PROPS.DEFAULT_TITLE);
  
      return innermostTitle || innermostDefaultTitle || undefined;
  };
  
  var getOnChangeClientState = function getOnChangeClientState(propsList) {
      return getInnermostProperty(propsList, HELMET_PROPS.ON_CHANGE_CLIENT_STATE) || function () {};
  };
  
  var getAttributesFromPropsList = function getAttributesFromPropsList(tagType, propsList) {
      return propsList.filter(function (props) {
          return typeof props[tagType] !== "undefined";
      }).map(function (props) {
          return props[tagType];
      }).reduce(function (tagAttrs, current) {
          return _extends({}, tagAttrs, current);
      }, {});
  };
  
  var getBaseTagFromPropsList = function getBaseTagFromPropsList(primaryAttributes, propsList) {
      return propsList.filter(function (props) {
          return typeof props[TAG_NAMES.BASE] !== "undefined";
      }).map(function (props) {
          return props[TAG_NAMES.BASE];
      }).reverse().reduce(function (innermostBaseTag, tag) {
          if (!innermostBaseTag.length) {
              var keys = Object.keys(tag);
  
              for (var i = 0; i < keys.length; i++) {
                  var attributeKey = keys[i];
                  var lowerCaseAttributeKey = attributeKey.toLowerCase();
  
                  if (primaryAttributes.indexOf(lowerCaseAttributeKey) !== -1 && tag[lowerCaseAttributeKey]) {
                      return innermostBaseTag.concat(tag);
                  }
              }
          }
  
          return innermostBaseTag;
      }, []);
  };
  
  var getTagsFromPropsList = function getTagsFromPropsList(tagName, primaryAttributes, propsList) {
      // Calculate list of tags, giving priority innermost component (end of the propslist)
      var approvedSeenTags = {};
  
      return propsList.filter(function (props) {
          if (Array.isArray(props[tagName])) {
              return true;
          }
          if (typeof props[tagName] !== "undefined") {
              warn("Helmet: " + tagName + " should be of type \"Array\". Instead found type \"" + _typeof(props[tagName]) + "\"");
          }
          return false;
      }).map(function (props) {
          return props[tagName];
      }).reverse().reduce(function (approvedTags, instanceTags) {
          var instanceSeenTags = {};
  
          instanceTags.filter(function (tag) {
              var primaryAttributeKey = void 0;
              var keys = Object.keys(tag);
              for (var i = 0; i < keys.length; i++) {
                  var attributeKey = keys[i];
                  var lowerCaseAttributeKey = attributeKey.toLowerCase();
  
                  // Special rule with link tags, since rel and href are both primary tags, rel takes priority
                  if (primaryAttributes.indexOf(lowerCaseAttributeKey) !== -1 && !(primaryAttributeKey === TAG_PROPERTIES.REL && tag[primaryAttributeKey].toLowerCase() === "canonical") && !(lowerCaseAttributeKey === TAG_PROPERTIES.REL && tag[lowerCaseAttributeKey].toLowerCase() === "stylesheet")) {
                      primaryAttributeKey = lowerCaseAttributeKey;
                  }
                  // Special case for innerHTML which doesn't work lowercased
                  if (primaryAttributes.indexOf(attributeKey) !== -1 && (attributeKey === TAG_PROPERTIES.INNER_HTML || attributeKey === TAG_PROPERTIES.CSS_TEXT || attributeKey === TAG_PROPERTIES.ITEM_PROP)) {
                      primaryAttributeKey = attributeKey;
                  }
              }
  
              if (!primaryAttributeKey || !tag[primaryAttributeKey]) {
                  return false;
              }
  
              var value = tag[primaryAttributeKey].toLowerCase();
  
              if (!approvedSeenTags[primaryAttributeKey]) {
                  approvedSeenTags[primaryAttributeKey] = {};
              }
  
              if (!instanceSeenTags[primaryAttributeKey]) {
                  instanceSeenTags[primaryAttributeKey] = {};
              }
  
              if (!approvedSeenTags[primaryAttributeKey][value]) {
                  instanceSeenTags[primaryAttributeKey][value] = true;
                  return true;
              }
  
              return false;
          }).reverse().forEach(function (tag) {
              return approvedTags.push(tag);
          });
  
          // Update seen tags with tags from this instance
          var keys = Object.keys(instanceSeenTags);
          for (var i = 0; i < keys.length; i++) {
              var attributeKey = keys[i];
              var tagUnion = objectAssign({}, approvedSeenTags[attributeKey], instanceSeenTags[attributeKey]);
  
              approvedSeenTags[attributeKey] = tagUnion;
          }
  
          return approvedTags;
      }, []).reverse();
  };
  
  var getInnermostProperty = function getInnermostProperty(propsList, property) {
      for (var i = propsList.length - 1; i >= 0; i--) {
          var props = propsList[i];
  
          if (props.hasOwnProperty(property)) {
              return props[property];
          }
      }
  
      return null;
  };
  
  var reducePropsToState = function reducePropsToState(propsList) {
      return {
          baseTag: getBaseTagFromPropsList([TAG_PROPERTIES.HREF], propsList),
          bodyAttributes: getAttributesFromPropsList(ATTRIBUTE_NAMES.BODY, propsList),
          defer: getInnermostProperty(propsList, HELMET_PROPS.DEFER),
          encode: getInnermostProperty(propsList, HELMET_PROPS.ENCODE_SPECIAL_CHARACTERS),
          htmlAttributes: getAttributesFromPropsList(ATTRIBUTE_NAMES.HTML, propsList),
          linkTags: getTagsFromPropsList(TAG_NAMES.LINK, [TAG_PROPERTIES.REL, TAG_PROPERTIES.HREF], propsList),
          metaTags: getTagsFromPropsList(TAG_NAMES.META, [TAG_PROPERTIES.NAME, TAG_PROPERTIES.CHARSET, TAG_PROPERTIES.HTTPEQUIV, TAG_PROPERTIES.PROPERTY, TAG_PROPERTIES.ITEM_PROP], propsList),
          noscriptTags: getTagsFromPropsList(TAG_NAMES.NOSCRIPT, [TAG_PROPERTIES.INNER_HTML], propsList),
          onChangeClientState: getOnChangeClientState(propsList),
          scriptTags: getTagsFromPropsList(TAG_NAMES.SCRIPT, [TAG_PROPERTIES.SRC, TAG_PROPERTIES.INNER_HTML], propsList),
          styleTags: getTagsFromPropsList(TAG_NAMES.STYLE, [TAG_PROPERTIES.CSS_TEXT], propsList),
          title: getTitleFromPropsList(propsList),
          titleAttributes: getAttributesFromPropsList(ATTRIBUTE_NAMES.TITLE, propsList)
      };
  };
  
  var rafPolyfill = function () {
      var clock = Date.now();
  
      return function (callback) {
          var currentTime = Date.now();
  
          if (currentTime - clock > 16) {
              clock = currentTime;
              callback(currentTime);
          } else {
              setTimeout(function () {
                  rafPolyfill(callback);
              }, 0);
          }
      };
  }();
  
  var cafPolyfill = function cafPolyfill(id) {
      return clearTimeout(id);
  };
  
  var requestAnimationFrame = typeof window !== "undefined" ? window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || rafPolyfill : global.requestAnimationFrame || rafPolyfill;
  
  var cancelAnimationFrame = typeof window !== "undefined" ? window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || cafPolyfill : global.cancelAnimationFrame || cafPolyfill;
  
  var warn = function warn(msg) {
      return console && typeof console.warn === "function" && console.warn(msg);
  };
  
  var _helmetCallback = null;
  
  var handleClientStateChange = function handleClientStateChange(newState) {
      if (_helmetCallback) {
          cancelAnimationFrame(_helmetCallback);
      }
  
      if (newState.defer) {
          _helmetCallback = requestAnimationFrame(function () {
              commitTagChanges(newState, function () {
                  _helmetCallback = null;
              });
          });
      } else {
          commitTagChanges(newState);
          _helmetCallback = null;
      }
  };
  
  var commitTagChanges = function commitTagChanges(newState, cb) {
      var baseTag = newState.baseTag,
          bodyAttributes = newState.bodyAttributes,
          htmlAttributes = newState.htmlAttributes,
          linkTags = newState.linkTags,
          metaTags = newState.metaTags,
          noscriptTags = newState.noscriptTags,
          onChangeClientState = newState.onChangeClientState,
          scriptTags = newState.scriptTags,
          styleTags = newState.styleTags,
          title = newState.title,
          titleAttributes = newState.titleAttributes;
  
      updateAttributes(TAG_NAMES.BODY, bodyAttributes);
      updateAttributes(TAG_NAMES.HTML, htmlAttributes);
  
      updateTitle(title, titleAttributes);
  
      var tagUpdates = {
          baseTag: updateTags(TAG_NAMES.BASE, baseTag),
          linkTags: updateTags(TAG_NAMES.LINK, linkTags),
          metaTags: updateTags(TAG_NAMES.META, metaTags),
          noscriptTags: updateTags(TAG_NAMES.NOSCRIPT, noscriptTags),
          scriptTags: updateTags(TAG_NAMES.SCRIPT, scriptTags),
          styleTags: updateTags(TAG_NAMES.STYLE, styleTags)
      };
  
      var addedTags = {};
      var removedTags = {};
  
      Object.keys(tagUpdates).forEach(function (tagType) {
          var _tagUpdates$tagType = tagUpdates[tagType],
              newTags = _tagUpdates$tagType.newTags,
              oldTags = _tagUpdates$tagType.oldTags;
  
  
          if (newTags.length) {
              addedTags[tagType] = newTags;
          }
          if (oldTags.length) {
              removedTags[tagType] = tagUpdates[tagType].oldTags;
          }
      });
  
      cb && cb();
  
      onChangeClientState(newState, addedTags, removedTags);
  };
  
  var flattenArray = function flattenArray(possibleArray) {
      return Array.isArray(possibleArray) ? possibleArray.join("") : possibleArray;
  };
  
  var updateTitle = function updateTitle(title, attributes) {
      if (typeof title !== "undefined" && document.title !== title) {
          document.title = flattenArray(title);
      }
  
      updateAttributes(TAG_NAMES.TITLE, attributes);
  };
  
  var updateAttributes = function updateAttributes(tagName, attributes) {
      var elementTag = document.getElementsByTagName(tagName)[0];
  
      if (!elementTag) {
          return;
      }
  
      var helmetAttributeString = elementTag.getAttribute(HELMET_ATTRIBUTE);
      var helmetAttributes = helmetAttributeString ? helmetAttributeString.split(",") : [];
      var attributesToRemove = [].concat(helmetAttributes);
      var attributeKeys = Object.keys(attributes);
  
      for (var i = 0; i < attributeKeys.length; i++) {
          var attribute = attributeKeys[i];
          var value = attributes[attribute] || "";
  
          if (elementTag.getAttribute(attribute) !== value) {
              elementTag.setAttribute(attribute, value);
          }
  
          if (helmetAttributes.indexOf(attribute) === -1) {
              helmetAttributes.push(attribute);
          }
  
          var indexToSave = attributesToRemove.indexOf(attribute);
          if (indexToSave !== -1) {
              attributesToRemove.splice(indexToSave, 1);
          }
      }
  
      for (var _i = attributesToRemove.length - 1; _i >= 0; _i--) {
          elementTag.removeAttribute(attributesToRemove[_i]);
      }
  
      if (helmetAttributes.length === attributesToRemove.length) {
          elementTag.removeAttribute(HELMET_ATTRIBUTE);
      } else if (elementTag.getAttribute(HELMET_ATTRIBUTE) !== attributeKeys.join(",")) {
          elementTag.setAttribute(HELMET_ATTRIBUTE, attributeKeys.join(","));
      }
  };
  
  var updateTags = function updateTags(type, tags) {
      var headElement = document.head || document.querySelector(TAG_NAMES.HEAD);
      var tagNodes = headElement.querySelectorAll(type + "[" + HELMET_ATTRIBUTE + "]");
      var oldTags = Array.prototype.slice.call(tagNodes);
      var newTags = [];
      var indexToDelete = void 0;
  
      if (tags && tags.length) {
          tags.forEach(function (tag) {
              var newElement = document.createElement(type);
  
              for (var attribute in tag) {
                  if (tag.hasOwnProperty(attribute)) {
                      if (attribute === TAG_PROPERTIES.INNER_HTML) {
                          newElement.innerHTML = tag.innerHTML;
                      } else if (attribute === TAG_PROPERTIES.CSS_TEXT) {
                          if (newElement.styleSheet) {
                              newElement.styleSheet.cssText = tag.cssText;
                          } else {
                              newElement.appendChild(document.createTextNode(tag.cssText));
                          }
                      } else {
                          var value = typeof tag[attribute] === "undefined" ? "" : tag[attribute];
                          newElement.setAttribute(attribute, value);
                      }
                  }
              }
  
              newElement.setAttribute(HELMET_ATTRIBUTE, "true");
  
              // Remove a duplicate tag from domTagstoRemove, so it isn't cleared.
              if (oldTags.some(function (existingTag, index) {
                  indexToDelete = index;
                  return newElement.isEqualNode(existingTag);
              })) {
                  oldTags.splice(indexToDelete, 1);
              } else {
                  newTags.push(newElement);
              }
          });
      }
  
      oldTags.forEach(function (tag) {
          return tag.parentNode.removeChild(tag);
      });
      newTags.forEach(function (tag) {
          return headElement.appendChild(tag);
      });
  
      return {
          oldTags: oldTags,
          newTags: newTags
      };
  };
  
  var generateElementAttributesAsString = function generateElementAttributesAsString(attributes) {
      return Object.keys(attributes).reduce(function (str, key) {
          var attr = typeof attributes[key] !== "undefined" ? key + "=\"" + attributes[key] + "\"" : "" + key;
          return str ? str + " " + attr : attr;
      }, "");
  };
  
  var generateTitleAsString = function generateTitleAsString(type, title, attributes, encode) {
      var attributeString = generateElementAttributesAsString(attributes);
      var flattenedTitle = flattenArray(title);
      return attributeString ? "<" + type + " " + HELMET_ATTRIBUTE + "=\"true\" " + attributeString + ">" + encodeSpecialCharacters(flattenedTitle, encode) + "</" + type + ">" : "<" + type + " " + HELMET_ATTRIBUTE + "=\"true\">" + encodeSpecialCharacters(flattenedTitle, encode) + "</" + type + ">";
  };
  
  var generateTagsAsString = function generateTagsAsString(type, tags, encode) {
      return tags.reduce(function (str, tag) {
          var attributeHtml = Object.keys(tag).filter(function (attribute) {
              return !(attribute === TAG_PROPERTIES.INNER_HTML || attribute === TAG_PROPERTIES.CSS_TEXT);
          }).reduce(function (string, attribute) {
              var attr = typeof tag[attribute] === "undefined" ? attribute : attribute + "=\"" + encodeSpecialCharacters(tag[attribute], encode) + "\"";
              return string ? string + " " + attr : attr;
          }, "");
  
          var tagContent = tag.innerHTML || tag.cssText || "";
  
          var isSelfClosing = SELF_CLOSING_TAGS.indexOf(type) === -1;
  
          return str + "<" + type + " " + HELMET_ATTRIBUTE + "=\"true\" " + attributeHtml + (isSelfClosing ? "/>" : ">" + tagContent + "</" + type + ">");
      }, "");
  };
  
  var convertElementAttributestoReactProps = function convertElementAttributestoReactProps(attributes) {
      var initProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
      return Object.keys(attributes).reduce(function (obj, key) {
          obj[REACT_TAG_MAP[key] || key] = attributes[key];
          return obj;
      }, initProps);
  };
  
  var convertReactPropstoHtmlAttributes = function convertReactPropstoHtmlAttributes(props) {
      var initAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
      return Object.keys(props).reduce(function (obj, key) {
          obj[HTML_TAG_MAP[key] || key] = props[key];
          return obj;
      }, initAttributes);
  };
  
  var generateTitleAsReactComponent = function generateTitleAsReactComponent(type, title, attributes) {
      var _initProps;
  
      // assigning into an array to define toString function on it
      var initProps = (_initProps = {
          key: title
      }, _initProps[HELMET_ATTRIBUTE] = true, _initProps);
      var props = convertElementAttributestoReactProps(attributes, initProps);
  
      return [React.createElement(TAG_NAMES.TITLE, props, title)];
  };
  
  var generateTagsAsReactComponent = function generateTagsAsReactComponent(type, tags) {
      return tags.map(function (tag, i) {
          var _mappedTag;
  
          var mappedTag = (_mappedTag = {
              key: i
          }, _mappedTag[HELMET_ATTRIBUTE] = true, _mappedTag);
  
          Object.keys(tag).forEach(function (attribute) {
              var mappedAttribute = REACT_TAG_MAP[attribute] || attribute;
  
              if (mappedAttribute === TAG_PROPERTIES.INNER_HTML || mappedAttribute === TAG_PROPERTIES.CSS_TEXT) {
                  var content = tag.innerHTML || tag.cssText;
                  mappedTag.dangerouslySetInnerHTML = { __html: content };
              } else {
                  mappedTag[mappedAttribute] = tag[attribute];
              }
          });
  
          return React.createElement(type, mappedTag);
      });
  };
  
  var getMethodsForTag = function getMethodsForTag(type, tags, encode) {
      switch (type) {
          case TAG_NAMES.TITLE:
              return {
                  toComponent: function toComponent() {
                      return generateTitleAsReactComponent(type, tags.title, tags.titleAttributes, encode);
                  },
                  toString: function toString() {
                      return generateTitleAsString(type, tags.title, tags.titleAttributes, encode);
                  }
              };
          case ATTRIBUTE_NAMES.BODY:
          case ATTRIBUTE_NAMES.HTML:
              return {
                  toComponent: function toComponent() {
                      return convertElementAttributestoReactProps(tags);
                  },
                  toString: function toString() {
                      return generateElementAttributesAsString(tags);
                  }
              };
          default:
              return {
                  toComponent: function toComponent() {
                      return generateTagsAsReactComponent(type, tags);
                  },
                  toString: function toString() {
                      return generateTagsAsString(type, tags, encode);
                  }
              };
      }
  };
  
  var mapStateOnServer = function mapStateOnServer(_ref) {
      var baseTag = _ref.baseTag,
          bodyAttributes = _ref.bodyAttributes,
          encode = _ref.encode,
          htmlAttributes = _ref.htmlAttributes,
          linkTags = _ref.linkTags,
          metaTags = _ref.metaTags,
          noscriptTags = _ref.noscriptTags,
          scriptTags = _ref.scriptTags,
          styleTags = _ref.styleTags,
          _ref$title = _ref.title,
          title = _ref$title === undefined ? "" : _ref$title,
          titleAttributes = _ref.titleAttributes;
      return {
          base: getMethodsForTag(TAG_NAMES.BASE, baseTag, encode),
          bodyAttributes: getMethodsForTag(ATTRIBUTE_NAMES.BODY, bodyAttributes, encode),
          htmlAttributes: getMethodsForTag(ATTRIBUTE_NAMES.HTML, htmlAttributes, encode),
          link: getMethodsForTag(TAG_NAMES.LINK, linkTags, encode),
          meta: getMethodsForTag(TAG_NAMES.META, metaTags, encode),
          noscript: getMethodsForTag(TAG_NAMES.NOSCRIPT, noscriptTags, encode),
          script: getMethodsForTag(TAG_NAMES.SCRIPT, scriptTags, encode),
          style: getMethodsForTag(TAG_NAMES.STYLE, styleTags, encode),
          title: getMethodsForTag(TAG_NAMES.TITLE, { title: title, titleAttributes: titleAttributes }, encode)
      };
  };
  
  var Helmet = function Helmet(Component) {
      var _class, _temp;
  
      return _temp = _class = function (_React$Component) {
          inherits(HelmetWrapper, _React$Component);
  
          function HelmetWrapper() {
              classCallCheck(this, HelmetWrapper);
              return possibleConstructorReturn(this, _React$Component.apply(this, arguments));
          }
  
          HelmetWrapper.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
              return !isEqual(this.props, nextProps);
          };
  
          HelmetWrapper.prototype.mapNestedChildrenToProps = function mapNestedChildrenToProps(child, nestedChildren) {
              if (!nestedChildren) {
                  return null;
              }
  
              switch (child.type) {
                  case TAG_NAMES.SCRIPT:
                  case TAG_NAMES.NOSCRIPT:
                      return {
                          innerHTML: nestedChildren
                      };
  
                  case TAG_NAMES.STYLE:
                      return {
                          cssText: nestedChildren
                      };
              }
  
              throw new Error("<" + child.type + " /> elements are self-closing and can not contain children. Refer to our API for more information.");
          };
  
          HelmetWrapper.prototype.flattenArrayTypeChildren = function flattenArrayTypeChildren(_ref) {
              var _babelHelpers$extends;
  
              var child = _ref.child,
                  arrayTypeChildren = _ref.arrayTypeChildren,
                  newChildProps = _ref.newChildProps,
                  nestedChildren = _ref.nestedChildren;
  
              return _extends({}, arrayTypeChildren, (_babelHelpers$extends = {}, _babelHelpers$extends[child.type] = [].concat(arrayTypeChildren[child.type] || [], [_extends({}, newChildProps, this.mapNestedChildrenToProps(child, nestedChildren))]), _babelHelpers$extends));
          };
  
          HelmetWrapper.prototype.mapObjectTypeChildren = function mapObjectTypeChildren(_ref2) {
              var _babelHelpers$extends2, _babelHelpers$extends3;
  
              var child = _ref2.child,
                  newProps = _ref2.newProps,
                  newChildProps = _ref2.newChildProps,
                  nestedChildren = _ref2.nestedChildren;
  
              switch (child.type) {
                  case TAG_NAMES.TITLE:
                      return _extends({}, newProps, (_babelHelpers$extends2 = {}, _babelHelpers$extends2[child.type] = nestedChildren, _babelHelpers$extends2.titleAttributes = _extends({}, newChildProps), _babelHelpers$extends2));
  
                  case TAG_NAMES.BODY:
                      return _extends({}, newProps, {
                          bodyAttributes: _extends({}, newChildProps)
                      });
  
                  case TAG_NAMES.HTML:
                      return _extends({}, newProps, {
                          htmlAttributes: _extends({}, newChildProps)
                      });
              }
  
              return _extends({}, newProps, (_babelHelpers$extends3 = {}, _babelHelpers$extends3[child.type] = _extends({}, newChildProps), _babelHelpers$extends3));
          };
  
          HelmetWrapper.prototype.mapArrayTypeChildrenToProps = function mapArrayTypeChildrenToProps(arrayTypeChildren, newProps) {
              var newFlattenedProps = _extends({}, newProps);
  
              Object.keys(arrayTypeChildren).forEach(function (arrayChildName) {
                  var _babelHelpers$extends4;
  
                  newFlattenedProps = _extends({}, newFlattenedProps, (_babelHelpers$extends4 = {}, _babelHelpers$extends4[arrayChildName] = arrayTypeChildren[arrayChildName], _babelHelpers$extends4));
              });
  
              return newFlattenedProps;
          };
  
          HelmetWrapper.prototype.warnOnInvalidChildren = function warnOnInvalidChildren(child, nestedChildren) {
              if (process.env.NODE_ENV !== "production") {
                  if (!VALID_TAG_NAMES.some(function (name) {
                      return child.type === name;
                  })) {
                      if (typeof child.type === "function") {
                          return warn("You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.");
                      }
  
                      return warn("Only elements types " + VALID_TAG_NAMES.join(", ") + " are allowed. Helmet does not support rendering <" + child.type + "> elements. Refer to our API for more information.");
                  }
  
                  if (nestedChildren && typeof nestedChildren !== "string" && (!Array.isArray(nestedChildren) || nestedChildren.some(function (nestedChild) {
                      return typeof nestedChild !== "string";
                  }))) {
                      throw new Error("Helmet expects a string as a child of <" + child.type + ">. Did you forget to wrap your children in braces? ( <" + child.type + ">{``}</" + child.type + "> ) Refer to our API for more information.");
                  }
              }
  
              return true;
          };
  
          HelmetWrapper.prototype.mapChildrenToProps = function mapChildrenToProps(children, newProps) {
              var _this2 = this;
  
              var arrayTypeChildren = {};
  
              React.Children.forEach(children, function (child) {
                  if (!child || !child.props) {
                      return;
                  }
  
                  var _child$props = child.props,
                      nestedChildren = _child$props.children,
                      childProps = objectWithoutProperties(_child$props, ["children"]);
  
                  var newChildProps = convertReactPropstoHtmlAttributes(childProps);
  
                  _this2.warnOnInvalidChildren(child, nestedChildren);
  
                  switch (child.type) {
                      case TAG_NAMES.LINK:
                      case TAG_NAMES.META:
                      case TAG_NAMES.NOSCRIPT:
                      case TAG_NAMES.SCRIPT:
                      case TAG_NAMES.STYLE:
                          arrayTypeChildren = _this2.flattenArrayTypeChildren({
                              child: child,
                              arrayTypeChildren: arrayTypeChildren,
                              newChildProps: newChildProps,
                              nestedChildren: nestedChildren
                          });
                          break;
  
                      default:
                          newProps = _this2.mapObjectTypeChildren({
                              child: child,
                              newProps: newProps,
                              newChildProps: newChildProps,
                              nestedChildren: nestedChildren
                          });
                          break;
                  }
              });
  
              newProps = this.mapArrayTypeChildrenToProps(arrayTypeChildren, newProps);
              return newProps;
          };
  
          HelmetWrapper.prototype.render = function render() {
              var _props = this.props,
                  children = _props.children,
                  props = objectWithoutProperties(_props, ["children"]);
  
              var newProps = _extends({}, props);
  
              if (children) {
                  newProps = this.mapChildrenToProps(children, newProps);
              }
  
              return React.createElement(Component, newProps);
          };
  
          createClass(HelmetWrapper, null, [{
              key: "canUseDOM",
  
  
              // Component.peek comes from react-side-effect:
              // For testing, you may use a static peek() method available on the returned component.
              // It lets you get the current state without resetting the mounted instance stack.
              // Don’t use it for anything other than testing.
  
              /**
              * @param {Object} base: {"target": "_blank", "href": "http://mysite.com/"}
              * @param {Object} bodyAttributes: {"className": "root"}
              * @param {String} defaultTitle: "Default Title"
              * @param {Boolean} defer: true
              * @param {Boolean} encodeSpecialCharacters: true
              * @param {Object} htmlAttributes: {"lang": "en", "amp": undefined}
              * @param {Array} link: [{"rel": "canonical", "href": "http://mysite.com/example"}]
              * @param {Array} meta: [{"name": "description", "content": "Test description"}]
              * @param {Array} noscript: [{"innerHTML": "<img src='http://mysite.com/js/test.js'"}]
              * @param {Function} onChangeClientState: "(newState) => console.log(newState)"
              * @param {Array} script: [{"type": "text/javascript", "src": "http://mysite.com/js/test.js"}]
              * @param {Array} style: [{"type": "text/css", "cssText": "div { display: block; color: blue; }"}]
              * @param {String} title: "Title"
              * @param {Object} titleAttributes: {"itemprop": "name"}
              * @param {String} titleTemplate: "MySite.com - %s"
              */
              set: function set$$1(canUseDOM) {
                  Component.canUseDOM = canUseDOM;
              }
          }]);
          return HelmetWrapper;
      }(React.Component), _class.propTypes = {
          base: PropTypes.object,
          bodyAttributes: PropTypes.object,
          children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
          defaultTitle: PropTypes.string,
          defer: PropTypes.bool,
          encodeSpecialCharacters: PropTypes.bool,
          htmlAttributes: PropTypes.object,
          link: PropTypes.arrayOf(PropTypes.object),
          meta: PropTypes.arrayOf(PropTypes.object),
          noscript: PropTypes.arrayOf(PropTypes.object),
          onChangeClientState: PropTypes.func,
          script: PropTypes.arrayOf(PropTypes.object),
          style: PropTypes.arrayOf(PropTypes.object),
          title: PropTypes.string,
          titleAttributes: PropTypes.object,
          titleTemplate: PropTypes.string
      }, _class.defaultProps = {
          defer: true,
          encodeSpecialCharacters: true
      }, _class.peek = Component.peek, _class.rewind = function () {
          var mappedState = Component.rewind();
          if (!mappedState) {
              // provide fallback if mappedState is undefined
              mappedState = mapStateOnServer({
                  baseTag: [],
                  bodyAttributes: {},
                  encodeSpecialCharacters: true,
                  htmlAttributes: {},
                  linkTags: [],
                  metaTags: [],
                  noscriptTags: [],
                  scriptTags: [],
                  styleTags: [],
                  title: "",
                  titleAttributes: {}
              });
          }
  
          return mappedState;
      }, _temp;
  };
  
  var NullComponent = function NullComponent() {
      return null;
  };
  
  var HelmetSideEffects = withSideEffect(reducePropsToState, handleClientStateChange, mapStateOnServer)(NullComponent);
  
  var HelmetExport = Helmet(HelmetSideEffects);
  HelmetExport.renderStatic = HelmetExport.rewind;
  
  export { HelmetExport as Helmet };
  