text: "use strict";
  
  var _classProps = function (child, staticProps, instanceProps) {
    if (staticProps) Object.defineProperties(child, staticProps);
    if (instanceProps) Object.defineProperties(child.prototype, instanceProps);
  };
  
  // Recursivly clone objects
  var clone = function (obj, parent) {
    if (typeof (obj) != "object") return obj;
    var cloned = new obj.constructor();
  
    for (var name in obj) {
      if (!obj.hasOwnProperty(name)) continue;
      var value = obj[name];
  
      if (name == "parent" && typeof (value) == "object") {
        if (parent) cloned[name] = parent;
      } else if (name == "source") {
        cloned[name] = value;
      } else if (value instanceof Array) {
        cloned[name] = value.map(function (i) {
          return clone(i, cloned);
        });
      } else {
        cloned[name] = clone(value, cloned);
      }
    }
  
    return cloned;
  };
  
  var Node = (function () {
    var Node = function Node(defaults) {
      if (defaults === undefined) defaults = {};
      for (var name in defaults) {
        this[name] = defaults[name];
      }
    };
  
    _classProps(Node, null, {
      removeSelf: {
        writable: true,
  
  
        // Remove this node from parent
        //
        //   decl.removeSelf();
        //
        // Note, that removing by index is faster:
        //
        //   rule.each( (decl, i) => rule.remove(i) );
        value: function () {
          if (this.parent) {
            this.parent.remove(this);
          }
          return this;
        }
      },
      replace: {
        writable: true,
  
  
        // Shortcut to insert nodes before and remove self.
        //
        //   importNode.replace( loadedRoot );
        value: function (nodes) {
          this.parent.insertBefore(this, nodes);
          this.parent.remove(this);
          return this;
        }
      },
      toString: {
        writable: true,
  
  
        // Return CSS string of current node
        //
        //   decl.toString(); //=> "  color: black"
        value: function () {
          var result = "";
          var builder = function (str) {
            return result += str;
          };
          this.stringify(builder);
          return result;
        }
      },
      clone: {
        writable: true,
  
  
        // Clone current node
        //
        //   rule.append( decl.clone() );
        //
        // You can override properties while cloning:
        //
        //   rule.append( decl.clone({ value: '0' }) );
        value: function (overrides) {
          if (overrides === undefined) overrides = {};
          var cloned = clone(this);
          for (var name in overrides) {
            cloned[name] = overrides[name];
          }
          return cloned;
        }
      },
      toJSON: {
        writable: true,
  
  
        // Remove `parent` node on cloning to fix circular structures
        value: function () {
          var fixed = {};
  
          for (var name in this) {
            if (!this.hasOwnProperty(name)) continue;
            if (name == "parent") continue;
            var value = this[name];
  
            if (value instanceof Array) {
              fixed[name] = value.map(function (i) {
                return (typeof (i) == "object" && i.toJSON) ? i.toJSON() : i;
              });
            } else if (typeof (value) == "object" && value.toJSON) {
              fixed[name] = value.toJSON();
            } else {
              fixed[name] = value;
            }
          }
  
          return fixed;
        }
      },
      styleMap: {
        writable: true,
        value: function () {
          return {};
        }
      },
      style: {
        writable: true,
  
  
        // Copy code style from first node with same type
        value: function (name) {
          // Already had
          var value = this.styleMap()[name];
          if (typeof (value) != "undefined") return value;
  
          var parent = this.parent;
  
          // Hack for first rule in CSS
          if (!parent && (name == "beforeRule" || name == "beforeDecl")) {
            return "";
          }
          if (name == "beforeRule" && !parent.parent && parent.first == this) {
            return "";
          }
  
          // Floating child without parent
          if (!parent) return this.defaultStyle[name];
  
          // Detect style by other nodes
          var root = parent;
          while (root.parent) root = root.parent;
  
          if (!root.styleCache) root.styleCache = {};
          if (typeof (root.styleCache[name]) != "undefined") {
            return root.styleCache[name];
          }
  
          root.eachInside(function (other) {
            value = other.styleMap()[name];
            if (typeof (value) != "undefined") return false;
          });
          if (typeof (value) == "undefined") value = this.defaultStyle[name];
  
          root.styleCache[name] = value;
          return value;
        }
      },
      stringifyRaw: {
        writable: true,
  
  
        // Use raw value if origin was not changed
        value: function (prop) {
          var value = this[prop];
          var raw = this["_" + prop];
          if (raw && raw.value === value) {
            return raw.raw;
          } else {
            return value;
          }
        }
      }
    });
  
    return Node;
  })();
  
  // Default code style
  Node.prototype.defaultStyle = {
    colon: ": ",
    beforeDecl: "\n    ",
    commentLeft: " ",
    commentRight: " ",
    beforeRule: "\n",
    beforeOpen: " ",
    beforeClose: "\n",
    emptyBody: ""
  };
  
  module.exports = Node;