"use strict";

RB.LinkifyUtils = {
  URL_RE: new RegExp('\\b((' + ['https://', 'http://', 'ftp://', 'ftps://', 'gopher://', 'mailto:', 'news:', 'sms:'].join('|') + ')[\\-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*([\\-A-Za-z0-9+@#\/%=~_();|]|))', 'g'),
  /**
   * Linkify all URLs within some text.
   *
   * This will turn things that look like URLs into clickable links.
   *
   * Args:
   *     text (string):
   *         The text to linkify.
   *
   * Returns:
   *     string:
   *     The given text with all URLs replaced by <a> tags.
   */
  linkifyURLs(text) {
    return text.replace(RB.LinkifyUtils.URL_RE, function (url) {
      /*
       * We might catch an entity at the end of the URL. This is hard
       * to avoid, since we can't rely on advanced RegExp techniques
       * in all browsers. So, we'll now search for it and prevent it
       * from being part of the URL if it exists. However, a URL with
       * an open bracket will not have its close bracket removed. This
       * was a modification to the original bug fix.
       *
       * See bug 1069.
       */
      const parts = url.match(/^(.*)(&[a-z]+;|\))$/);
      const openParen = url.match(/.*\(.*/);
      let extra = '';
      if (parts !== null && openParen === null) {
        /* We caught an entity. Set it free. */
        url = parts[1];
        extra = parts[2];
      }
      return `<a target="_blank" href="${url}">${url}</a>${extra}`;
    });
  },
  /**
   * Linkify /r/# review request numbers.
   *
   * This will turn things that look like references to other review requests
   * into clickable links.
   *
   * Args:
   *     text (string):
   *         The text to linkify.
   *
   * Returns:
   *     string:
   *     The given text with all "/r/#" text replaced by <a> tags.
   */
  linkifyReviewRequests(text) {
    return text.replace(/(^|\s|&lt;|\(|\[|{)\/(r\/\d+(\/[\-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|]*)?)/g, function (text, m1, m2) {
      const parts = m2.match(/^(.*)(&[a-z]+;|\))$/);
      let extra = '';
      let url = m2;
      if (parts !== null) {
        /* We caught an entity. Set it free. */
        url = parts[1];
        extra = parts[2];
      }
      const href = SITE_ROOT + url + (url.substr(-1) === '/' ? '' : '/');
      return `${m1}<a target="_blank" href="${href}" class="review-request-link">/${url}</a>${extra}`;
    });
  },
  /**
   * Linkify bug numbers.
   *
   * This will turn things that look like references to bugs (such as
   * "bug 408") into clickable links.
   *
   * Args:
   *     text (string):
   *         The text to linkify.
   *
   *     bugTrackerURL (string):
   *         The URL to use when formatting the bug number. This is expected
   *         to have the literal ``--bug_id--`` in it, which will be replaced
   *         by the captured bug ID.
   *
   * Returns:
   *     string:
   *     The given text with all bug references replaced by <a> tags.
   */
  linkifyBugs(text, bugTrackerURL) {
    if (bugTrackerURL) {
      return text.replace(/\b(bug|issue) (#([^.,)\]\s]+)|#?(\d+))/gi, function (text, m2, m3, bugnum1, bugnum2) {
        /*
         * The bug number can appear in either of those groups,
         * depending on how this was typed, so try both.
         */
        const bugnum = bugnum1 || bugnum2;
        const href = bugTrackerURL.replace("--bug_id--", bugnum);
        return `<a target="_blank" href="${href}">${text}</a>`;
      });
    } else {
      return text;
    }
  },
  /**
   * Linkify text using all available methods.
   *
   * Linkifies a block of text, turning URLs, /r/#/ paths, and bug numbers
   * into clickable links.
   *
   * Args:
   *     text (string):
   *         The text to linkify.
   *
   *     bugTrackerURL (string):
   *         The URL to use when formatting the bug number. This is expected
   *         to have the literal ``--bug_id--`` in it, which will be replaced
   *         by the captured bug ID.
   *
   *     isHTMLEncoded (boolean):
   *         Whether or not the given text has already had dangerous
   *         characters (like < or >) replaced by their HTML entities. If
   *         this is false, the text will first be encoded.
   *
   * Returns:
   *     string:
   *     The given text with all linkifyable items replaced by <a> tags.
   */
  linkifyText(text, bugTrackerURL, isHTMLEncoded) {
    if (!isHTMLEncoded) {
      text = _.escape(text);
    }
    text = RB.LinkifyUtils.linkifyURLs(text);
    text = RB.LinkifyUtils.linkifyReviewRequests(text);
    text = RB.LinkifyUtils.linkifyBugs(text, bugTrackerURL);
    return text;
  },
  /**
   * Linkify text within a pre-established DOM tree.
   *
   * This iterates through a tree of nodes, linkifying any text nodes that
   * reference bug URLs, review requests, or contain unlinked plain-text
   * URLs.
   *
   * This will avoid linking anything within a <pre> tag, to avoid messing
   * with code blocks, and <a> tags, to avoid linkifying existing links.
   *
   * Args:
   *     el (Element):
   *         The element to linkify.
   *
   *     bugTrackerURL (string):
   *         The URL to use when formatting the bug number. This is expected
   *         to have the literal ``--bug_id--`` in it, which will be replaced
   *         by the captured bug ID.
   */
  linkifyChildren(el, bugTrackerURL) {
    for (let i = 0; i < el.childNodes.length; i++) {
      const node = el.childNodes[i];
      if (node.nodeType === node.TEXT_NODE) {
        if (node.textContent) {
          const newText = RB.LinkifyUtils.linkifyText(node.textContent, bugTrackerURL);
          if (newText !== node.textContent) {
            $(node).replaceWith(newText);
          }
        }
      } else if (node.nodeType === node.ELEMENT_NODE) {
        if (node.nodeName !== 'PRE' && node.nodeName !== 'A') {
          RB.LinkifyUtils.linkifyChildren(node, bugTrackerURL);
        }
      }
    }
  }
};

//# sourceMappingURL=linkifyUtils.js.map