hunk.code_window:           return this;
           }
           if (typeof value != 'object') {
             value = [value];
           }
           this.find('option').removeAttr('selected');
  
hunk.labels: keep keep replace keep keep keep
hunk.after_edit:         if (typeof value !== 'object') {
  
hunk.file_path: lib/api/attributes.js
hunk.type: replace
file: /**
   * Methods for modifying the DOM structure.
   *
   * @module cheerio/manipulation
   */
  
  var parse = require('../parse');
  var html = require('../static').html;
  var text = require('../static').text;
  var updateDOM = parse.update;
  var utils = require('../utils');
  var domEach = utils.domEach;
  var cloneDom = utils.cloneDom;
  var isHtml = utils.isHtml;
  var slice = Array.prototype.slice;
  var domhandler = require('domhandler');
  var DomUtils = require('htmlparser2').DomUtils;
  
  /**
   * Create an array of nodes, recursing into arrays and parsing strings if necessary.
   *
   * @private
   *
   * @param {Cheerio | string | Cheerio[] | string[]} [elem] - Elements to make an array of.
   * @param {boolean} [clone] - Optionally clone nodes.
   * @returns {Node[]} The array of nodes.
   */
  exports._makeDomArray = function makeDomArray(elem, clone) {
    if (elem == null) {
      return [];
    }
    if (elem.cheerio) {
      return clone ? cloneDom(elem.get()) : elem.get();
    }
    if (Array.isArray(elem)) {
      return elem.reduce(
        function (newElems, el) {
          return newElems.concat(this._makeDomArray(el, clone));
        }.bind(this),
        []
      );
    }
    if (typeof elem === 'string') {
      return parse(elem, this.options, false).children;
    }
    return clone ? cloneDom([elem]) : [elem];
  };
  
  function _insert(concatenator) {
    return function () {
      var elems = slice.call(arguments);
      var lastIdx = this.length - 1;
  
      return domEach(this, function (i, el) {
        var domSrc =
          typeof elems[0] === 'function'
            ? elems[0].call(el, i, html(el.children))
            : elems;
  
        var dom = this._makeDomArray(domSrc, i < lastIdx);
        concatenator(dom, el.children, el);
      });
    };
  }
  
  /**
   * Modify an array in-place, removing some number of elements and adding new
   * elements directly following them.
   *
   * @private
   *
   * @param {Node[]} array - Target array to splice.
   * @param {number} spliceIdx - Index at which to begin changing the array.
   * @param {number} spliceCount - Number of elements to remove from the array.
   * @param {Node[]} newElems - Elements to insert into the array.
   * @param {NodeWithChildren} parent - The parent of the node.
   * @returns {Node[]} The spliced array.
   */
  function uniqueSplice(array, spliceIdx, spliceCount, newElems, parent) {
    var spliceArgs = [spliceIdx, spliceCount].concat(newElems);
    var prev = array[spliceIdx - 1] || null;
    var next = array[spliceIdx + spliceCount] || null;
  
    // Before splicing in new elements, ensure they do not already appear in the
    // current array.
    for (var idx = 0; idx < newElems.length; ++idx) {
      var node = newElems[idx];
      var oldParent = node.parent;
      var prevIdx = oldParent && oldParent.children.indexOf(newElems[idx]);
  
      if (oldParent && prevIdx > -1) {
        oldParent.children.splice(prevIdx, 1);
        if (parent === oldParent && spliceIdx > prevIdx) {
          spliceArgs[0]--;
        }
      }
  
      node.parent = parent;
  
      if (node.prev) {
        node.prev.next = node.next || null;
      }
  
      if (node.next) {
        node.next.prev = node.prev || null;
      }
  
      node.prev = newElems[idx - 1] || prev;
      node.next = newElems[idx + 1] || next;
    }
  
    if (prev) {
      prev.next = newElems[0];
    }
    if (next) {
      next.prev = newElems[newElems.length - 1];
    }
    return array.splice.apply(array, spliceArgs);
  }
  
  /**
   * Insert every element in the set of matched elements to the end of the target.
   *
   * @example
   *   $('<li class="plum">Plum</li>').appendTo('#fruits');
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="apple">Apple</li>
   *   //      <li class="orange">Orange</li>
   *   //      <li class="pear">Pear</li>
   *   //      <li class="plum">Plum</li>
   *   //    </ul>
   *
   * @param {string | Cheerio} target - Element to append elements to.
   * @see {@link https://api.jquery.com/appendTo/}
   *
   * @returns {Cheerio} The instance itself.
   */
  exports.appendTo = function (target) {
    if (!target.cheerio) {
      target = this.constructor.call(
        this.constructor,
        target,
        null,
        this._originalRoot
      );
    }
  
    target.append(this);
  
    return this;
  };
  
  /**
   * Insert every element in the set of matched elements to the beginning of the target.
   *
   * @example
   *   $('<li class="plum">Plum</li>').prependTo('#fruits');
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="plum">Plum</li>
   *   //      <li class="apple">Apple</li>
   *   //      <li class="orange">Orange</li>
   *   //      <li class="pear">Pear</li>
   *   //    </ul>
   *
   * @param {string | Cheerio} target - Element to prepend elements to.
   * @see {@link https://api.jquery.com/prependTo/}
   *
   * @returns {Cheerio} The instance itself.
   */
  exports.prependTo = function (target) {
    if (!target.cheerio) {
      target = this.constructor.call(
        this.constructor,
        target,
        null,
        this._originalRoot
      );
    }
  
    target.prepend(this);
  
    return this;
  };
  
  /**
   * Inserts content as the *last* child of each of the selected elements.
   *
   * @example
   *   $('ul').append('<li class="plum">Plum</li>');
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="apple">Apple</li>
   *   //      <li class="orange">Orange</li>
   *   //      <li class="pear">Pear</li>
   *   //      <li class="plum">Plum</li>
   *   //    </ul>
   *
   * @function
   *
   * @see {@link https://api.jquery.com/append/}
   */
  exports.append = _insert(function (dom, children, parent) {
    uniqueSplice(children, children.length, 0, dom, parent);
  });
  
  /**
   * Inserts content as the *first* child of each of the selected elements.
   *
   * @example
   *   $('ul').prepend('<li class="plum">Plum</li>');
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="plum">Plum</li>
   *   //      <li class="apple">Apple</li>
   *   //      <li class="orange">Orange</li>
   *   //      <li class="pear">Pear</li>
   *   //    </ul>
   *
   * @function
   *
   * @see {@link https://api.jquery.com/prepend/}
   */
  exports.prepend = _insert(function (dom, children, parent) {
    uniqueSplice(children, 0, 0, dom, parent);
  });
  
  function _wrap(insert) {
    return function (wrapper) {
      var wrapperFn = typeof wrapper === 'function' && wrapper;
      var lastIdx = this.length - 1;
      var lastParent = this.parents().last();
  
      for (var i = 0; i < this.length; i++) {
        var el = this[i];
  
        if (wrapperFn) {
          wrapper = wrapperFn.call(el, i);
        }
  
        if (typeof wrapper === 'string' && !isHtml(wrapper)) {
          wrapper = lastParent.find(wrapper).clone();
        }
  
        var wrapperDom = this._makeDomArray(wrapper, i < lastIdx).slice(0, 1);
        var elInsertLocation = wrapperDom[0];
        // Find the deepest child. Only consider the first tag child of each node
        // (ignore text); stop if no children are found.
        var j = 0;
  
        while (
          elInsertLocation &&
          elInsertLocation.children &&
          j < elInsertLocation.children.length
        ) {
          if (elInsertLocation.children[j].type === 'tag') {
            elInsertLocation = elInsertLocation.children[j];
            j = 0;
          } else {
            j++;
          }
        }
  
        insert(el, elInsertLocation, wrapperDom);
      }
  
      return this;
    };
  }
  
  /**
   * The .wrap() function can take any string or object that could be passed to
   * the $() factory function to specify a DOM structure. This structure may be
   * nested several levels deep, but should contain only one inmost element. A
   * copy of this structure will be wrapped around each of the elements in the
   * set of matched elements. This method returns the original set of elements
   * for chaining purposes.
   *
   * @example
   *   const redFruit = $('<div class="red-fruit"></div>');
   *   $('.apple').wrap(redFruit);
   *
   *   //=> <ul id="fruits">
   *   //     <div class="red-fruit">
   *   //      <li class="apple">Apple</li>
   *   //     </div>
   *   //     <li class="orange">Orange</li>
   *   //     <li class="plum">Plum</li>
   *   //   </ul>
   *
   *   const healthy = $('<div class="healthy"></div>');
   *   $('li').wrap(healthy);
   *
   *   //=> <ul id="fruits">
   *   //     <div class="healthy">
   *   //       <li class="apple">Apple</li>
   *   //     </div>
   *   //     <div class="healthy">
   *   //       <li class="orange">Orange</li>
   *   //     </div>
   *   //     <div class="healthy">
   *   //        <li class="plum">Plum</li>
   *   //     </div>
   *   //   </ul>
   *
   * @param {Cheerio} wrapper - The DOM structure to wrap around each element in
   *     the selection.
   * @see {@link https://api.jquery.com/wrap/}
   */
  exports.wrap = _wrap(function (el, elInsertLocation, wrapperDom) {
    var parent = el.parent;
    var siblings = parent.children;
    var index = siblings.indexOf(el);
  
    updateDOM([el], elInsertLocation);
    // The previous operation removed the current element from the `siblings`
    // array, so the `dom` array can be inserted without removing any
    // additional elements.
    uniqueSplice(siblings, index, 0, wrapperDom, parent);
  });
  
  /**
   * The .wrapInner() function can take any string or object that could be passed
   * to the $() factory function to specify a DOM structure. This structure may
   * be nested several levels deep, but should contain only one inmost element.
   * The structure will be wrapped around the content of each of the elements in
   * the set of matched elements.
   *
   * @example
   *   const redFruit = $('<div class="red-fruit"></div>');
   *   $('.apple').wrapInner(redFruit);
   *
   *   //=> <ul id="fruits">
   *   //     <li class="apple">
   *   //       <div class="red-fruit">Apple</div>
   *   //     </li>
   *   //     <li class="orange">Orange</li>
   *   //     <li class="pear">Pear</li>
   *   //   </ul>
   *
   *   const healthy = $('<div class="healthy"></div>');
   *   $('li').wrapInner(healthy);
   *
   *   //=> <ul id="fruits">
   *   //     <li class="apple">
   *   //       <div class="healthy">Apple</div>
   *   //     </li>
   *   //     <li class="orange">
   *   //       <div class="healthy">Orange</div>
   *   //     </li>
   *   //     <li class="pear">
   *   //       <div class="healthy">Pear</div>
   *   //     </li>
   *   //   </ul>
   *
   * @param {Cheerio} wrapper - The DOM structure to wrap around the content of
   *     each element in the selection.
   * @see {@link https://api.jquery.com/wrapInner/}
   */
  exports.wrapInner = _wrap(function (el, elInsertLocation, wrapperDom) {
    updateDOM(el.children, elInsertLocation);
    updateDOM(wrapperDom, el);
  });
  
  /**
   * The .wrapAll() function can take any string or object that could be passed to
   * the $() function to specify a DOM structure. This structure may be nested
   * several levels deep, but should contain only one inmost element. The
   * structure will be wrapped around all of the elements in the set of matched
   * elements, as a single group.
   *
   * @example <caption>With markup passed to `wrapAll`</caption>
   *   const $ = cheerio.load(
   *     '<div class="container"><div class="inner">First</div><div class="inner">Second</div></div>'
   *   );
   *   $('.inner').wrapAll("<div class='new'></div>");
   *
   *   //=> <div class="container">
   *   //     <div class='new'>
   *   //       <div class="inner">First</div>
   *   //       <div class="inner">Second</div>
   *   //     </div>
   *   //   </div>
   *
   * @example <caption>With an existing cheerio instance</caption>
   *   const $ = cheerio.load(
   *     '<span>Span 1</span><strong>Strong</strong><span>Span 2</span>'
   *   );
   *   const wrap = $('<div><p><em><b></b></em></p></div>');
   *   $('span').wrapAll(wrap);
   *
   *   //=> <div>
   *   //     <p>
   *   //       <em>
   *   //         <b>
   *   //           <span>Span 1</span>
   *   //           <span>Span 2</span>
   *   //         </b>
   *   //       </em>
   *   //     </p>
   *   //   </div>
   *   //   <strong>Strong</strong>
   *
   * @param {Cheerio} wrapper - The DOM structure to wrap around all matched
   *     elements in the selection.
   * @see {@link https://api.jquery.com/wrapAll/}
   * @returns {Cheerio} The instance itself.
   */
  exports.wrapAll = function (wrapper) {
    if (this[0]) {
      if (typeof wrapper === 'function') {
        wrapper = wrapper.call(this[0]);
      }
  
      var wrap = this._make(wrapper);
  
      if (this[0].parent) {
        wrap = wrap.insertBefore(this[0]);
      }
  
      // if html is given as wrapper, wrap may contain text elements
      var elInsertLocation = { children: wrap };
      var j = 0;
  
      // Find the deepest child. Only consider the first tag child of each node
      // (ignore text); stop if no children are found.
      while (
        elInsertLocation &&
        elInsertLocation.children &&
        j < elInsertLocation.children.length
      ) {
        if (elInsertLocation.children[j].type === 'tag') {
          elInsertLocation = elInsertLocation.children[j];
          j = 0;
        } else {
          j++;
        }
      }
  
      this._make(elInsertLocation).append(this);
    }
    return this;
  };
  
  /**
   * Insert content next to each element in the set of matched elements.
   *
   * @example
   *   $('.apple').after('<li class="plum">Plum</li>');
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="apple">Apple</li>
   *   //      <li class="plum">Plum</li>
   *   //      <li class="orange">Orange</li>
   *   //      <li class="pear">Pear</li>
   *   //    </ul>
   *
   * @see {@link https://api.jquery.com/after/}
   *
   * @returns {Cheerio} The instance itself.
   */
  exports.after = function () {
    var elems = slice.call(arguments);
    var lastIdx = this.length - 1;
  
    return domEach(this, function (i, el) {
      var parent = el.parent;
      if (!parent) {
        return;
      }
  
      var siblings = parent.children;
      var index = siblings.indexOf(el);
  
      // If not found, move on
      if (index < 0) return;
  
      var domSrc =
        typeof elems[0] === 'function'
          ? elems[0].call(el, i, html(el.children))
          : elems;
  
      var dom = this._makeDomArray(domSrc, i < lastIdx);
  
      // Add element after `this` element
      uniqueSplice(siblings, index + 1, 0, dom, parent);
    });
  };
  
  /**
   * Insert every element in the set of matched elements after the target.
   *
   * @example
   *   $('<li class="plum">Plum</li>').insertAfter('.apple');
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="apple">Apple</li>
   *   //      <li class="plum">Plum</li>
   *   //      <li class="orange">Orange</li>
   *   //      <li class="pear">Pear</li>
   *   //    </ul>
   *
   * @param {string | Cheerio} target - Element to insert elements after.
   * @see {@link https://api.jquery.com/insertAfter/}
   *
   * @returns {Cheerio} The set of newly inserted elements.
   */
  exports.insertAfter = function (target) {
    var clones = [];
    var self = this;
    if (typeof target === 'string') {
      target = this.constructor.call(
        this.constructor,
        target,
        null,
        this._originalRoot
      );
    }
    target = this._makeDomArray(target);
    self.remove();
    domEach(target, function (i, el) {
      var clonedSelf = self._makeDomArray(self.clone());
      var parent = el.parent;
      if (!parent) {
        return;
      }
  
      var siblings = parent.children;
      var index = siblings.indexOf(el);
  
      // If not found, move on
      if (index < 0) return;
  
      // Add cloned `this` element(s) after target element
      uniqueSplice(siblings, index + 1, 0, clonedSelf, parent);
      clones.push(clonedSelf);
    });
    return this.constructor.call(this.constructor, this._makeDomArray(clones));
  };
  
  /**
   * Insert content previous to each element in the set of matched elements.
   *
   * @example
   *   $('.apple').before('<li class="plum">Plum</li>');
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="plum">Plum</li>
   *   //      <li class="apple">Apple</li>
   *   //      <li class="orange">Orange</li>
   *   //      <li class="pear">Pear</li>
   *   //    </ul>
   *
   * @see {@link https://api.jquery.com/before/}
   *
   * @returns {Cheerio} The instance itself.
   */
  exports.before = function () {
    var elems = slice.call(arguments);
    var lastIdx = this.length - 1;
  
    return domEach(this, function (i, el) {
      var parent = el.parent;
      if (!parent) {
        return;
      }
  
      var siblings = parent.children;
      var index = siblings.indexOf(el);
  
      // If not found, move on
      if (index < 0) return;
  
      var domSrc =
        typeof elems[0] === 'function'
          ? elems[0].call(el, i, html(el.children))
          : elems;
  
      var dom = this._makeDomArray(domSrc, i < lastIdx);
  
      // Add element before `el` element
      uniqueSplice(siblings, index, 0, dom, parent);
    });
  };
  
  /**
   * Insert every element in the set of matched elements before the target.
   *
   * @example
   *   $('<li class="plum">Plum</li>').insertBefore('.apple');
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="plum">Plum</li>
   *   //      <li class="apple">Apple</li>
   *   //      <li class="orange">Orange</li>
   *   //      <li class="pear">Pear</li>
   *   //    </ul>
   *
   * @param {string | Cheerio} target - Element to insert elements before.
   * @see {@link https://api.jquery.com/insertBefore/}
   *
   * @returns {Cheerio} The set of newly inserted elements.
   */
  exports.insertBefore = function (target) {
    var clones = [];
    var self = this;
    if (typeof target === 'string') {
      target = this.constructor.call(
        this.constructor,
        target,
        null,
        this._originalRoot
      );
    }
    target = this._makeDomArray(target);
    self.remove();
    domEach(target, function (_, el) {
      var clonedSelf = self._makeDomArray(self.clone());
      var parent = el.parent;
      if (!parent) {
        return;
      }
  
      var siblings = parent.children;
      var index = siblings.indexOf(el);
  
      // If not found, move on
      if (index < 0) return;
  
      // Add cloned `this` element(s) after target element
      uniqueSplice(siblings, index, 0, clonedSelf, parent);
      clones.push(clonedSelf);
    });
    return this.constructor.call(this.constructor, this._makeDomArray(clones));
  };
  
  /**
   * Removes the set of matched elements from the DOM and all their children.
   * `selector` filters the set of matched elements to be removed.
   *
   * @example
   *   $('.pear').remove();
   *   $.html();
   *   //=>  <ul id="fruits">
   *   //      <li class="apple">Apple</li>
   *   //      <li class="orange">Orange</li>
   *   //    </ul>
   *
   * @param {string} [selector] - Optional selector for elements to remove.
   * @see {@link https://api.jquery.com/remove/}
   *
   * @returns {Cheerio} The instance itself.
   */
  exports.remove = function (selector) {
    // Filter if we have selector
    var elems = selector ? this.filter(selector) : this;
  
    domEach(elems, function (_, el) {
      DomUtils.removeElement(el);
      el.prev = el.next = el.parent = null;
    });
  
    return this;
  };
  
  /**
   * Replaces matched elements with `content`.
   *
   * @example
   *   const plum = $('<li class="plum">Plum</li>');
   *   $('.pear').replaceWith(plum);
   *   $.html();
   *   //=> <ul id="fruits">
   *   //     <li class="apple">Apple</li>
   *   //     <li class="orange">Orange</li>
   *   //     <li class="plum">Plum</li>
   *   //   </ul>
   *
   * @param {Cheerio | Function} content - Replacement for matched elements.
   * @see {@link https://api.jquery.com/replaceWith/}
   *
   * @returns {Cheerio} The instance itself.
   */
  exports.replaceWith = function (content) {
    return domEach(this, function (i, el) {
      var parent = el.parent;
      if (!parent) {
        return;
      }
  
      var siblings = parent.children;
      var dom = this._makeDomArray(
        typeof content === 'function' ? content.call(el, i, el) : content
      );
  
      // In the case that `dom` contains nodes that already exist in other
      // structures, ensure those nodes are properly removed.
      updateDOM(dom, null);
  
      var index = siblings.indexOf(el);
  
      // Completely remove old element
      uniqueSplice(siblings, index, 1, dom, parent);
  
      if (dom.indexOf(el) < 0) {
        el.parent = el.prev = el.next = null;
      }
    });
  };
  
  /**
   * Empties an element, removing all its children.
   *
   * @example
   *   $('ul').empty();
   *   $.html();
   *   //=>  <ul id="fruits"></ul>
   *
   * @see {@link https://api.jquery.com/empty/}
   *
   * @returns {Cheerio} The instance itself.
   */
  exports.empty = function () {
    return domEach(this, function (_, el) {
      el.children.forEach(function (child) {
        child.next = child.prev = child.parent = null;
      });
  
      el.children.length = 0;
    });
  };
  
  /**
   * Gets an HTML content string from the first selected element. If `htmlString`
   * is specified, each selected element's content is replaced by the new content.
   *
   * @example
   *   $('.orange').html();
   *   //=> Orange
   *
   *   $('#fruits').html('<li class="mango">Mango</li>').html();
   *   //=> <li class="mango">Mango</li>
   *
   * @param {string | Cheerio} str - If specified used to replace selection's contents.
   * @see {@link https://api.jquery.com/html/}
   *
   * @returns {Cheerio} The instance itself.
   */
  exports.html = function (str) {
    if (str === undefined) {
      if (!this[0] || !this[0].children) return null;
      return html(this[0].children, this.options);
    }
  
    var opts = Object.apply({}, this.options); // keep main options
  
    return domEach(this, function (_, el) {
      el.children.forEach(function (child) {
        child.next = child.prev = child.parent = null;
      });
  
      opts.context = el;
  
      var content = str.cheerio
        ? str.clone().get()
        : parse('' + str, opts, false).children;
  
      updateDOM(content, el);
    });
  };
  
  /**
   * Turns the collection to a string. Alias for `.html()`.
   *
   * @returns {string} The rendered document.
   */
  exports.toString = function () {
    return html(this, this.options);
  };
  
  /**
   * Get the combined text contents of each element in the set of matched
   * elements, including their descendants. If `textString` is specified, each
   * selected element's content is replaced by the new text content.
   *
   * @example
   *   $('.orange').text();
   *   //=> Orange
   *
   *   $('ul').text();
   *   //=>  Apple
   *   //    Orange
   *   //    Pear
   *
   * @param {string | Function} [str] - If specified replacement for the selected
   *     element's contents.
   * @see {@link https://api.jquery.com/text/}
   * @returns {Cheerio | string} The instance itself when setting text, otherwise
   *     the rendered document.
   */
  exports.text = function (str) {
    // If `str` is undefined, act as a "getter"
    if (str === undefined) {
      return text(this);
    }
    if (typeof str === 'function') {
      // Function support
      return domEach(this, function (i, el) {
        return exports.text.call(this._make(el), str.call(el, i, text([el])));
      });
    }
  
    // Append text node to each selected elements
    return domEach(this, function (_, el) {
      el.children.forEach(function (child) {
        child.next = child.prev = child.parent = null;
      });
  
      var textNode = new domhandler.Text(str);
  
      updateDOM(textNode, el);
    });
  };
  
  /**
   * Clone the cheerio object.
   *
   * @example
   *   const moreFruit = $('#fruits').clone();
   *
   * @see {@link https://api.jquery.com/clone/}
   *
   * @returns {Cheerio} The cloned object.
   */
  exports.clone = function () {
    return this._make(cloneDom(this.get()));
  };
  