/*! markdown-it-sanitizer 0.4.3 https://github.com/svbergerem/markdown-it-sanitizer @license MIT */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.markdownitSanitizer = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
// Sanitizer

'use strict';

module.exports = function sanitizer_plugin(md, options) {

  var linkify = md.linkify,
      escapeHtml = md.utils.escapeHtml,
      // <a href="url" title="(optional)"></a>
      patternLinkOpen = '<a\\s([^<>]*href="[^"<>]*"[^<>]*)\\s?>',
      regexpLinkOpen = RegExp(patternLinkOpen, 'i'),
      // <img src="url" alt=""(optional) title=""(optional)>
      patternImage = '<img\\s([^<>]*src="[^"<>]*"[^<>]*)\\s?\\/?>',
      regexpImage = RegExp(patternImage, 'i'),
      regexpImageProtocols = /^(?:https?:)?\/\//i,
      regexpLinkProtocols = /^(?:https?:\/\/|ftp:\/\/|\/\/|mailto:|xmpp:)/i;

  options = options ? options : {};
  var removeUnknown = (typeof options.removeUnknown !== 'undefined') ? options.removeUnknown : false;
  var removeUnbalanced = (typeof options.removeUnbalanced !== 'undefined') ? options.removeUnbalanced : false;
  var imageClass = (typeof options.imageClass !== 'undefined') ? options.imageClass : '';
  var runBalancer = false;
  var j;


  var allowedTags = [ 'a', 'b', 'blockquote', 'code', 'em', 'h1', 'h2', 'h3', 'h4', 'h5',
                     'h6', 'li', 'ol', 'p', 'pre', 's', 'sub', 'sup', 'strong', 'ul' ];
  var openTagCount = new Array(allowedTags.length);
  var removeTag = new Array(allowedTags.length);
  for (j = 0; j < allowedTags.length; j++) { openTagCount[j] = 0; }
  for (j = 0; j < allowedTags.length; j++) { removeTag[j] = false; }

  function getUrl(link) {
    var match = linkify.match(link);
    if (match && match.length === 1 && match[0].index === 0 && match[0].lastIndex === link.length) {
      return match[0].url;
    }
    return null;
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  //          REPLACE UNKNOWN TAGS
  /////////////////////////////////////////////////////////////////////////////////////////////////

  function replaceUnknownTags(str) {
    /*
     * it starts with '<' and maybe ends with '>',
     * maybe has a '<' on the right
     * it doesnt have '<' or '>' in between
     * -> it's a tag!
     */
    str = str.replace(/<[^<>]*>?/gi, function (tag) {
      var match, attrs, url, alt, title, tagnameIndex;

      // '<->', '<- ' and '<3 ' look nice, they are harmless
      if (/(^<->|^<-\s|^<3\s)/.test(tag)) { return tag; }

      // images
      match = tag.match(regexpImage);
      if (match) {
        attrs = match[1];
        url   = getUrl(attrs.match(/src="([^"<>]*)"/i)[1]);
        alt   = attrs.match(/alt="([^"<>]*)"/i);
        alt   = (alt && typeof alt[1] !== 'undefined') ? alt[1] : '';
        title = attrs.match(/title="([^"<>]*)"/i);
        title = (title && typeof title[1] !== 'undefined') ? title[1] : '';

        // only http and https are allowed for images
        if (url && regexpImageProtocols.test(url)) {
          if (imageClass !== '') {
            return '<img src="' + url + '" alt="' + alt + '" title="' + title + '" class="' + imageClass + '">';
          }
          return '<img src="' + url + '" alt="' + alt + '" title="' + title + '">';
        }
      }

      // links
      tagnameIndex = allowedTags.indexOf('a');
      match = tag.match(regexpLinkOpen);
      if (match) {
        attrs = match[1];
        url   = getUrl(attrs.match(/href="([^"<>]*)"/i)[1]);
        title = attrs.match(/title="([^"<>]*)"/i);
        title = (title && typeof title[1] !== 'undefined') ? title[1] : '';
        // only http, https, ftp, mailto and xmpp are allowed for links
        if (url && regexpLinkProtocols.test(url)) {
          runBalancer = true;
          openTagCount[tagnameIndex] += 1;
          return '<a href="' + url + '" title="' + title + '" target="_blank">';
        }
      }
      match = /<\/a>/i.test(tag);
      if (match) {
        runBalancer = true;
        openTagCount[tagnameIndex] -= 1;
        if (openTagCount[tagnameIndex] < 0) {
          removeTag[tagnameIndex] = true;
        }
        return '</a>';
      }

      // standalone tags
      match = tag.match(/<(br|hr)\s?\/?>/i);
      if (match) {
        return '<' + match[1].toLowerCase() + '>';
      }

      // whitelisted tags
      match = tag.match(/<(\/?)(b|blockquote|code|em|h[1-6]|li|ol(?: start="\d+")?|p|pre|s|sub|sup|strong|ul)>/i);
      if (match && !/<\/ol start="\d+"/i.test(tag)) {
        runBalancer = true;
        tagnameIndex = allowedTags.indexOf(match[2].toLowerCase().split(' ')[0]);
        if (match[1] === '/') {
          openTagCount[tagnameIndex] -= 1;
        } else {
          openTagCount[tagnameIndex] += 1;
        }
        if (openTagCount[tagnameIndex] < 0) {
          removeTag[tagnameIndex] = true;
        }
        return '<' + match[1] + match[2].toLowerCase() + '>';
      }

      // other tags we don't recognize
      if (removeUnknown === true) {
        return '';
      }
      return escapeHtml(tag);
    });

    return str;
  }


  function sanitizeInlineAndBlock(state) {
    var i, blkIdx, inlineTokens;
    // reset counts
    for (j = 0; j < allowedTags.length; j++) { openTagCount[j] = 0; }
    for (j = 0; j < allowedTags.length; j++) { removeTag[j] = false; }
    runBalancer = false;


    for (blkIdx = 0; blkIdx < state.tokens.length; blkIdx++) {
      if (state.tokens[blkIdx].type === 'html_block') {
        state.tokens[blkIdx].content = replaceUnknownTags(state.tokens[blkIdx].content);
      }
      if (state.tokens[blkIdx].type !== 'inline') {
        continue;
      }

      inlineTokens = state.tokens[blkIdx].children;
      for (i = 0; i < inlineTokens.length; i++) {
        if (inlineTokens[i].type === 'html_inline') {
          inlineTokens[i].content = replaceUnknownTags(inlineTokens[i].content);
        }
      }
    }
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  //          REPLACE UNBALANCED TAGS
  /////////////////////////////////////////////////////////////////////////////////////////////////

  function balance(state) {
    if (runBalancer === false) { return; }
    var blkIdx, inlineTokens;

    function replaceUnbalancedTag(str, tagname) {
      var openingRegexp, closingRegexp;
      if (tagname === 'a') {
        openingRegexp = RegExp('<a href="[^"<>]*" title="[^"<>]*" target="_blank">', 'g');
      } else if (tagname === 'ol') {
        openingRegexp = /<ol(?: start="\d+")?>/g;
      } else {
        openingRegexp = RegExp('<' + tagname + '>', 'g');
      }
      closingRegexp = RegExp('</' + tagname + '>', 'g');
      if (removeUnbalanced === true) {
        str = str.replace(openingRegexp, '');
        str = str.replace(closingRegexp, '');
      } else {
        str = str.replace(openingRegexp, function (m) { return escapeHtml(m); });
        str = str.replace(closingRegexp, function (m) { return escapeHtml(m); });
      }
      return str;
    }

    function replaceAllUnbalancedTags(str) {
      var i;
      for (i = 0; i < allowedTags.length; i++) {
        if (removeTag[i] === true) {
          str = replaceUnbalancedTag(str, allowedTags[i]);
        }
      }
      return str;
    }

    for (j = 0; j < allowedTags.length; j++) {
      if (openTagCount[j] !== 0) {
        removeTag[j] = true;
      }
    }

    // replace unbalanced tags
    for (blkIdx = 0; blkIdx < state.tokens.length; blkIdx++) {
      if (state.tokens[blkIdx].type === 'html_block') {
        state.tokens[blkIdx].content = replaceAllUnbalancedTags(state.tokens[blkIdx].content);
        continue;
      }
      if (state.tokens[blkIdx].type !== 'inline') {
        continue;
      }
      inlineTokens = state.tokens[blkIdx].children;
      for (j = 0; j < inlineTokens.length; j++) {
        if (inlineTokens[j].type === 'html_inline') {
          inlineTokens[j].content = replaceAllUnbalancedTags(inlineTokens[j].content);
        }
      }
    }
  }

  md.core.ruler.after('linkify', 'sanitize_inline', sanitizeInlineAndBlock);
  md.core.ruler.after('sanitize_inline', 'sanitize_balance', balance);
};

},{}]},{},[1])(1)
});