define(["exports", "core/pubsubhub", "deps/marked"], function (exports, _pubsubhub, _marked) {
  "use strict";

  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.ISODate = exports.name = undefined;
  exports.markdownToHtml = markdownToHtml;
  exports.makeOwnerSwapper = makeOwnerSwapper;
  exports.calculateLeftPad = calculateLeftPad;
  exports.createResourceHint = createResourceHint;
  exports.normalizePadding = normalizePadding;
  exports.removeReSpec = removeReSpec;
  exports.joinAnd = joinAnd;
  exports.xmlEscape = xmlEscape;
  exports.norm = norm;
  exports.concatDate = concatDate;
  exports.toShortIsoDate = toShortIsoDate;
  exports.lead0 = lead0;
  exports.parseSimpleDate = parseSimpleDate;
  exports.parseLastModified = parseLastModified;
  exports.humanDate = humanDate;
  exports.isoDate = isoDate;
  exports.toKeyValuePairs = toKeyValuePairs;
  exports.linkCSS = linkCSS;
  exports.runTransforms = runTransforms;

  var _marked2 = _interopRequireDefault(_marked);

  function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
      default: obj
    };
  }

  var _slicedToArray = function () {
    function sliceIterator(arr, i) {
      var _arr = [];
      var _n = true;
      var _d = false;
      var _e = undefined;

      try {
        for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
          _arr.push(_s.value);

          if (i && _arr.length === i) break;
        }
      } catch (err) {
        _d = true;
        _e = err;
      } finally {
        try {
          if (!_n && _i["return"]) _i["return"]();
        } finally {
          if (_d) throw _e;
        }
      }

      return _arr;
    }

    return function (arr, i) {
      if (Array.isArray(arr)) {
        return arr;
      } else if (Symbol.iterator in Object(arr)) {
        return sliceIterator(arr, i);
      } else {
        throw new TypeError("Invalid attempt to destructure non-iterable instance");
      }
    };
  }();

  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 name = exports.name = "core/utils";

  _marked2.default.setOptions({
    sanitize: false,
    gfm: true
  });

  var spaceOrTab = /^[\ |\t]*/;
  var endsWithSpace = /\s+$/gm;
  var dashes = /\-/g;
  var gtEntity = /&gt;/gm;
  var ampEntity = /&amp;/gm;

  function markdownToHtml(text) {
    var normalizedLeftPad = normalizePadding(text);
    // As markdown is pulled from HTML, > and & are already escaped and
    // so blockquotes aren't picked up by the parser. This fixes it.
    var potentialMarkdown = normalizedLeftPad.replace(gtEntity, ">").replace(ampEntity, "&");
    var result = (0, _marked2.default)(potentialMarkdown);
    return result;
  }

  var ISODate = exports.ISODate = new Intl.DateTimeFormat(["en-ca-iso8601"], {
    timeZone: "UTC",
    year: "numeric",
    month: "2-digit",
    day: "2-digit"
  });

  var inlineElems = new Set(["a", "abbr", "acronym", "b", "bdo", "big", "br", "button", "cite", "code", "dfn", "em", "i", "img", "input", "kbd", "label", "map", "object", "q", "samp", "script", "select", "small", "span", "strong", "sub", "sup", "textarea", "time", "tt", "var"]);

  var resourceHints = new Set(["dns-prefetch", "preconnect", "preload", "prerender"]);

  var fetchDestinations = new Set(["document", "embed", "font", "image", "manifest", "media", "object", "report", "script", "serviceworker", "sharedworker", "style", "worker", "xslt", ""]);

  /**
   * Allows a node to be swapped into a different document at
   * some insertion point(Element). This function is useful for
   * opportunistic insertion of DOM nodes into a document, without
   * first knowing if that is the final document where the node will
   * reside.
   *
   * @param  {Node} node The node to be swapped.
   * @return {Function} A function that takes a new
   *                    insertion point (Node). When called,
   *                    node gets inserted into doc at before a given
   *                    insertion point (Node) - or just appended, if
   *                    the element has no children.
   */
  function makeOwnerSwapper(node) {
    if (!node) {
      throw new TypeError("Expected instance of Node.");
    }
    return function (insertionPoint) {
      insertionPoint.ownerDocument.adoptNode(node);
      if (insertionPoint.firstElementChild) {
        return insertionPoint.insertBefore(node, insertionPoint.firstElementChild);
      }
      insertionPoint.appendChild(node);
    };
  }

  function calculateLeftPad(text) {
    if (typeof text !== "string") {
      throw new TypeError("Invalid input");
    }
    // Find smallest padding value
    var leftPad = text.split("\n").filter(function (item) {
      return item;
    }).reduce(function (smallest, item) {
      // can't go smaller than 0
      if (smallest === 0) {
        return smallest;
      }
      var match = item.match(spaceOrTab)[0] || "";
      return Math.min(match.length, smallest);
    }, +Infinity);
    return leftPad === +Infinity ? 0 : leftPad;
  }
  /**
   * Creates a link element that represents a resource hint.
   *
   * @param {Object} opts Configure the resource hint.
   * @param {String} opts.hint The type of hint (see resourceHints).
   * @param {URL|String} opts.href The URL for the resource or origin.
   * @param {String} [opts.corsMode] Optional, the CORS mode to use (see HTML spec).
   * @param {String} [opts.as] Optional, fetch destination type (see fetchDestinations).
   * @param {Bool} [opts.dontRemove] If the hint should remain in the spec after processing.
   * @return {HTMLLinkElement} A link element ready to use.
   */
  function createResourceHint(opts) {
    if (!opts || (typeof opts === "undefined" ? "undefined" : _typeof(opts)) !== "object") {
      throw new TypeError("Missing options");
    }
    if (!resourceHints.has(opts.hint)) {
      throw new TypeError("Invalid resources hint");
    }
    var url = new URL(opts.href, document.location);
    var linkElem = document.createElement("link");
    var href = url.href;
    linkElem.rel = opts.hint;
    switch (linkElem.rel) {
      case "dns-prefetch":
      case "preconnect":
        href = url.origin;
        if (opts.corsMode || url.origin !== document.location.origin) {
          linkElem.crossOrigin = opts.corsMode || "anonymous";
        }
        break;
      case "preload":
        if ("as" in opts && typeof opts.as === "string") {
          if (!fetchDestinations.has(opts.as)) {
            console.warn("Unknown request destination: " + opts.as);
          }
          linkElem.setAttribute("as", opts.as);
        }
        break;
    }
    linkElem.href = href;
    if (!opts.dontRemove) {
      linkElem.classList.add("removeOnSave");
    }
    return linkElem;
  }

  function normalizePadding() {
    var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";

    if (!text) {
      return "";
    }
    if (typeof text !== "string") {
      throw TypeError("Invalid input");
    }
    if (text === "\n") {
      return "\n";
    }

    function isTextNode(node) {
      return node !== null && node.nodeType === Node.TEXT_NODE;
    }
    // Force into body
    var parserInput = "<body>" + text;
    var doc = new DOMParser().parseFromString(parserInput, "text/html");
    // Normalize block level elements children first
    Array.from(doc.body.children).filter(function (elem) {
      return !inlineElems.has(elem.localName);
    }).filter(function (elem) {
      return elem.localName !== "pre";
    }).filter(function (elem) {
      return elem.localName !== "table";
    }).forEach(function (elem) {
      elem.innerHTML = normalizePadding(elem.innerHTML);
    });
    // Normalize root level now
    Array.from(doc.body.childNodes).filter(function (node) {
      return isTextNode(node) && node.textContent.trim() === "";
    }).forEach(function (node) {
      return node.parentElement.replaceChild(doc.createTextNode("\n"), node);
    });
    // Normalize text node
    if (!isTextNode(doc.body.firstChild)) {
      Array.from(doc.body.firstChild.children).filter(function (child) {
        return child.localName !== "table";
      }).forEach(function (child) {
        child.innerHTML = normalizePadding(child.innerHTML);
      });
    }
    doc.normalize();
    // use the first space as an indicator of how much to chop off the front
    var firstSpace = doc.body.innerText.replace(/^\ *\n/, "").split("\n").filter(function (item) {
      return item && item.startsWith(" ");
    })[0];
    var chop = firstSpace ? firstSpace.match(/\ +/)[0].length : 0;
    if (chop) {
      // Chop chop from start, but leave pre elem alone
      Array.from(doc.body.childNodes).filter(function (node) {
        return node.localName !== "pre";
      }).filter(isTextNode).filter(function (node) {
        // we care about text next to a block level element
        var prevSib = node.previousElementSibling;
        var nextTo = prevSib ? prevSib.localName : node.parentElement.localName;
        // and we care about text elements that finish on a new line
        return !inlineElems.has(nextTo) || node.textContent.trim().includes("\n");
      }).reduce(function (replacer, node) {
        // We need to retain white space if the text Node is next to an in-line element
        var padding = "";
        var prevSib = node.previousElementSibling;
        var nextTo = prevSib ? prevSib.localName : node.parentElement.localName;
        if (/^[\t\ ]/.test(node.textContent) && inlineElems.has(nextTo)) {
          padding = node.textContent.match(/^\s+/)[0];
        }
        node.textContent = padding + node.textContent.replace(replacer, "");
        return replacer;
      }, new RegExp("^ {1," + chop + "}", "gm"));
      // deal with pre elements... we can chop whitespace from their siblings
      var _endsWithSpace = new RegExp("\\ {" + chop + "}$", "gm");
      Array.from(doc.body.querySelectorAll("pre")).map(function (elem) {
        return elem.previousSibling;
      }).filter(isTextNode).reduce(function (chop, node) {
        if (_endsWithSpace.test(node.textContent)) {
          node.textContent = node.textContent.substr(0, node.textContent.length - chop);
        }
        return chop;
      }, chop);
    }
    var result = endsWithSpace.test(doc.body.innerHTML) ? doc.body.innerHTML.trimRight() + "\n" : doc.body.innerHTML;
    return result;
  }

  // RESPEC STUFF
  function removeReSpec(doc) {
    Array.from(doc.querySelectorAll(".remove, script[data-requiremodule]")).forEach(function (elem) {
      elem.remove();
    });
  }

  // STRING HELPERS
  // Takes an array and returns a string that separates each of its items with the proper commas and
  // "and". The second argument is a mapping function that can convert the items before they are
  // joined
  function joinAnd() {
    var array = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    var mapper = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function (item) {
      return item;
    };

    var items = array.map(mapper);
    switch (items.length) {
      case 0:
      case 1:
        // "x"
        return items.toString();
      case 2:
        // x and y
        return items.join(" and ");
      default:
        // x, y, and z
        var str = items.join(", ");
        var lastComma = str.lastIndexOf(",");
        return str.substr(0, lastComma + 1) + " and " + str.slice(lastComma + 2);
    }
  }

  // Takes a string, applies some XML escapes, and returns the escaped string.
  // Note that overall using either Handlebars' escaped output or jQuery is much
  // preferred to operating on strings directly.
  function xmlEscape(s) {
    return s.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
  }

  // Trims string at both ends and replaces all other white space with a single space
  function norm(str) {
    return str.trim().replace(/\s+/g, " ");
  }

  // --- DATE HELPERS -------------------------------------------------------------------------------
  // Takes a Date object and an optional separator and returns the year,month,day representation with
  // the custom separator (defaulting to none) and proper 0-padding
  function concatDate(date) {
    var sep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";

    return ISODate.format(date).replace(dashes, sep);
  }

  // formats a date to "yyyy-mm-dd"
  function toShortIsoDate(date) {
    return ISODate.format(date);
  }

  // takes a string, prepends a "0" if it is of length 1, does nothing otherwise
  function lead0(str) {
    return String(str).length === 1 ? "0" + str : str;
  }

  // takes a YYYY-MM-DD date and returns a Date object for it
  function parseSimpleDate(str) {
    return new Date(str);
  }

  // takes what document.lastModified returns and produces a Date object for it
  function parseLastModified(str) {
    if (!str) return new Date();
    return new Date(Date.parse(str));
  }

  // given either a Date object or a date in YYYY-MM-DD format,
  // return a human-formatted date suitable for use in a W3C specification
  function humanDate() {
    var date = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Date();
    var lang = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document.documentElement.lang || "en";

    if (!(date instanceof Date)) date = new Date(date);
    var langs = [lang, "en"];
    var day = date.toLocaleString(langs, {
      day: "2-digit",
      timeZone: "UTC"
    });
    var month = date.toLocaleString(langs, {
      month: "long",
      timeZone: "UTC"
    });
    var year = date.toLocaleString(langs, {
      year: "numeric",
      timeZone: "UTC"
    });
    //date month year
    return day + " " + month + " " + year;
  }
  // given either a Date object or a date in YYYY-MM-DD format,
  // return an ISO formatted date suitable for use in a xsd:datetime item
  function isoDate(date) {
    return (date instanceof Date ? date : new Date(date)).toISOString();
  }

  // Given an object, it converts it to a key value pair separated by
  // ("=", configurable) and a delimiter (" ," configurable).
  // for example, {"foo": "bar", "baz": 1} becomes "foo=bar, baz=1"
  function toKeyValuePairs(obj) {
    var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ", ";
    var separator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "=";

    return Array.from(Object.entries(obj)).map(function (_ref) {
      var _ref2 = _slicedToArray(_ref, 2),
          key = _ref2[0],
          value = _ref2[1];

      return "" + key + separator + JSON.stringify(value);
    }).join(delimiter);
  }

  // STYLE HELPERS
  // take a document and either a link or an array of links to CSS and appends
  // a <link/> element to the head pointing to each
  function linkCSS(doc, styles) {
    var stylesArray = [].concat(styles);
    var frag = stylesArray.map(function (url) {
      var link = doc.createElement("link");
      link.rel = "stylesheet";
      link.href = url;
      return link;
    }).reduce(function (elem, nextLink) {
      elem.appendChild(nextLink);
      return elem;
    }, doc.createDocumentFragment());
    doc.head.appendChild(frag);
  }

  // TRANSFORMATIONS
  // Run list of transforms over content and return result.
  // Please note that this is a legacy method that is only kept in order
  // to maintain compatibility
  // with RSv1. It is therefore not tested and not actively supported.
  function runTransforms(content, flist) {
    var args = [this, content];
    var funcArgs = Array.from(arguments);
    funcArgs.shift();
    funcArgs.shift();
    args = args.concat(funcArgs);
    if (flist) {
      var methods = flist.split(/\s+/);
      for (var j = 0; j < methods.length; j++) {
        var meth = methods[j];
        if (window[meth]) {
          // the initial call passed |this| directly, so we keep it that way
          try {
            content = window[meth].apply(this, args);
          } catch (e) {
            (0, _pubsubhub.pub)("warn", "call to `" + meth + "()` failed with: " + e + ". See error console for stack trace.");
            console.error(e);
          }
        }
      }
    }
    return content;
  }
});
//# sourceMappingURL=utils.js.map