generateCSSRuleset = function generateCSSRuleset(selector
/* : string */
, declarations
/* : OrderedElements */
, stringHandlers
/* : StringHandlers */
, useImportant
/* : boolean */
, selectorHandlers
/* : SelectorHandler[] */
)
/* : string */
{
  // Mutates declarations
  runStringHandlers(declarations, stringHandlers, selectorHandlers);
  var originalElements = Object.keys(declarations.elements).reduce(arrayToObjectKeysReducer, Object.create(null)); // NOTE(emily): This mutates handledDeclarations.elements.

  var prefixedElements = prefixAll(declarations.elements);
  var elementNames = Object.keys(prefixedElements);

  if (elementNames.length !== declarations.keyOrder.length) {
    // There are some prefixed values, so we need to figure out how to sort
    // them.
    //
    // Loop through prefixedElements, looking for anything that is not in
    // sortOrder, which means it was added by prefixAll. This means that we
    // need to figure out where it should appear in the sortOrder.
    for (var i = 0; i < elementNames.length; i++) {
      if (!originalElements[elementNames[i]]) {
        // This element is not in the sortOrder, which means it is a prefixed
        // value that was added by prefixAll. Let's try to figure out where it
        // goes.
        var originalStyle = void 0;

        if (elementNames[i][0] === 'W') {
          // This is a Webkit-prefixed style, like "WebkitTransition". Let's
          // find its original style's sort order.
          originalStyle = elementNames[i][6].toLowerCase() + elementNames[i].slice(7);
        } else if (elementNames[i][1] === 'o') {
          // This is a Moz-prefixed style, like "MozTransition". We check
          // the second character to avoid colliding with Ms-prefixed
          // styles. Let's find its original style's sort order.
          originalStyle = elementNames[i][3].toLowerCase() + elementNames[i].slice(4);
        } else {
          // if (elementNames[i][1] === 's') {
          // This is a Ms-prefixed style, like "MsTransition".
          originalStyle = elementNames[i][2].toLowerCase() + elementNames[i].slice(3);
        }

        if (originalStyle && originalElements[originalStyle]) {
          var originalIndex = declarations.keyOrder.indexOf(originalStyle);
          declarations.keyOrder.splice(originalIndex, 0, elementNames[i]);
        } else {
          // We don't know what the original style was, so sort it to
          // top. This can happen for styles that are added that don't
          // have the same base name as the original style.
          declarations.keyOrder.unshift(elementNames[i]);
        }
      }
    }
  }

  var transformValue = useImportant === false ? stringifyValue : stringifyAndImportantifyValue;
  var rules = [];

  for (var _i = 0; _i < declarations.keyOrder.length; _i++) {
    var key = declarations.keyOrder[_i];
    var value = prefixedElements[key];

    if (Array.isArray(value)) {
      // inline-style-prefixer returns an array when there should be
      // multiple rules for the same key. Here we flatten to multiple
      // pairs with the same key.
      for (var j = 0; j < value.length; j++) {
        rules.push(transformRule(key, value[j], transformValue));
      }
    } else {
      rules.push(transformRule(key, value, transformValue));
    }
  }

  if (rules.length) {
    return "".concat(selector, "{").concat(rules.join(""), "}");
  } else {
    return "";
  }
}
Generate a CSS ruleset with the selector and containing the declarations.

This function assumes that the given declarations don't contain any special
children (such as media queries, pseudo-selectors, or descendant styles).

Note that this method does not deal with nesting used for e.g.
psuedo-selectors or media queries. That responsibility is left to  the
`generateCSS` function.

@param {string} selector: the selector associated with the ruleset
@param {Object} declarations: a map from camelCased CSS property name to CSS
    property value.
@param {Object.<string, function>} stringHandlers: a map from camelCased CSS
    property name to a function which will map the given value to the value
    that is output.
@param {bool} useImportant: A boolean saying whether to append "!important"
    to each of the CSS declarations.
@returns {string} A string of raw CSS.

Examples:

   generateCSSRuleset(".blah", { color: "red" })
   -> ".blah{color: red !important;}"
   generateCSSRuleset(".blah", { color: "red" }, {}, false)
   -> ".blah{color: red}"
   generateCSSRuleset(".blah", { color: "red" }, {color: c => c.toUpperCase})
   -> ".blah{color: RED}"
   generateCSSRuleset(".blah:hover", { color: "red" })
   -> ".blah:hover{color: red}"