github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/toopay-bootstrap-markdown/js/to-markdown.js (about)

     1  /*
     2   * to-markdown - an HTML to Markdown converter
     3   *
     4   * Copyright 2011, Dom Christie
     5   * Licenced under the MIT licence
     6   *
     7   */
     8  
     9  var toMarkdown = function(string) {
    10    
    11    var ELEMENTS = [
    12      {
    13        patterns: 'p',
    14        replacement: function(str, attrs, innerHTML) {
    15          return innerHTML ? '\n\n' + innerHTML + '\n' : '';
    16        }
    17      },
    18      {
    19        patterns: 'br',
    20        type: 'void',
    21        replacement: '\n'
    22      },
    23      {
    24        patterns: 'h([1-6])',
    25        replacement: function(str, hLevel, attrs, innerHTML) {
    26          var hPrefix = '';
    27          for(var i = 0; i < hLevel; i++) {
    28            hPrefix += '#';
    29          }
    30          return '\n\n' + hPrefix + ' ' + innerHTML + '\n';
    31        }
    32      },
    33      {
    34        patterns: 'hr',
    35        type: 'void',
    36        replacement: '\n\n* * *\n'
    37      },
    38      {
    39        patterns: 'a',
    40        replacement: function(str, attrs, innerHTML) {
    41          var href = attrs.match(attrRegExp('href')),
    42              title = attrs.match(attrRegExp('title'));
    43          return href ? '[' + innerHTML + ']' + '(' + href[1] + (title && title[1] ? ' "' + title[1] + '"' : '') + ')' : str;
    44        }
    45      },
    46      {
    47        patterns: ['b', 'strong'],
    48        replacement: function(str, attrs, innerHTML) {
    49          return innerHTML ? '**' + innerHTML + '**' : '';
    50        }
    51      },
    52      {
    53        patterns: ['i', 'em'],
    54        replacement: function(str, attrs, innerHTML) {
    55          return innerHTML ? '_' + innerHTML + '_' : '';
    56        }
    57      },
    58      {
    59        patterns: 'code',
    60        replacement: function(str, attrs, innerHTML) {
    61          return innerHTML ? '`' + innerHTML + '`' : '';
    62        }
    63      },
    64      {
    65        patterns: 'img',
    66        type: 'void',
    67        replacement: function(str, attrs, innerHTML) {
    68          var src = attrs.match(attrRegExp('src')),
    69              alt = attrs.match(attrRegExp('alt')),
    70              title = attrs.match(attrRegExp('title'));
    71          return '![' + (alt && alt[1] ? alt[1] : '') + ']' + '(' + src[1] + (title && title[1] ? ' "' + title[1] + '"' : '') + ')';
    72        }
    73      }
    74    ];
    75    
    76    for(var i = 0, len = ELEMENTS.length; i < len; i++) {
    77      if(typeof ELEMENTS[i].patterns === 'string') {
    78        string = replaceEls(string, { tag: ELEMENTS[i].patterns, replacement: ELEMENTS[i].replacement, type:  ELEMENTS[i].type });
    79      }
    80      else {
    81        for(var j = 0, pLen = ELEMENTS[i].patterns.length; j < pLen; j++) {
    82          string = replaceEls(string, { tag: ELEMENTS[i].patterns[j], replacement: ELEMENTS[i].replacement, type:  ELEMENTS[i].type });
    83        }
    84      }
    85    }
    86    
    87    function replaceEls(html, elProperties) {
    88      var pattern = elProperties.type === 'void' ? '<' + elProperties.tag + '\\b([^>]*)\\/?>' : '<' + elProperties.tag + '\\b([^>]*)>([\\s\\S]*?)<\\/' + elProperties.tag + '>',
    89          regex = new RegExp(pattern, 'gi'),
    90          markdown = '';
    91      if(typeof elProperties.replacement === 'string') {
    92        markdown = html.replace(regex, elProperties.replacement);
    93      }
    94      else {
    95        markdown = html.replace(regex, function(str, p1, p2, p3) {
    96          return elProperties.replacement.call(this, str, p1, p2, p3);
    97        });
    98      }
    99      return markdown;
   100    }
   101    
   102    function attrRegExp(attr) {
   103      return new RegExp(attr + '\\s*=\\s*["\']?([^"\']*)["\']?', 'i');
   104    }
   105    
   106    // Pre code blocks
   107    
   108    string = string.replace(/<pre\b[^>]*>`([\s\S]*)`<\/pre>/gi, function(str, innerHTML) {
   109      innerHTML = innerHTML.replace(/^\t+/g, '  '); // convert tabs to spaces (you know it makes sense)
   110      innerHTML = innerHTML.replace(/\n/g, '\n    ');
   111      return '\n\n    ' + innerHTML + '\n';
   112    });
   113    
   114    // Lists
   115  
   116    // Escape numbers that could trigger an ol
   117    // If there are more than three spaces before the code, it would be in a pre tag
   118    // Make sure we are escaping the period not matching any character
   119    string = string.replace(/^(\s{0,3}\d+)\. /g, '$1\\. ');
   120    
   121    // Converts lists that have no child lists (of same type) first, then works it's way up
   122    var noChildrenRegex = /<(ul|ol)\b[^>]*>(?:(?!<ul|<ol)[\s\S])*?<\/\1>/gi;
   123    while(string.match(noChildrenRegex)) {
   124      string = string.replace(noChildrenRegex, function(str) {
   125        return replaceLists(str);
   126      });
   127    }
   128    
   129    function replaceLists(html) {
   130      
   131      html = html.replace(/<(ul|ol)\b[^>]*>([\s\S]*?)<\/\1>/gi, function(str, listType, innerHTML) {
   132        var lis = innerHTML.split('</li>');
   133        lis.splice(lis.length - 1, 1);
   134        
   135        for(i = 0, len = lis.length; i < len; i++) {
   136          if(lis[i]) {
   137            var prefix = (listType === 'ol') ? (i + 1) + ".  " : "*   ";
   138            lis[i] = lis[i].replace(/\s*<li[^>]*>([\s\S]*)/i, function(str, innerHTML) {
   139              
   140              innerHTML = innerHTML.replace(/^\s+/, '');
   141              innerHTML = innerHTML.replace(/\n\n/g, '\n\n    ');
   142              // indent nested lists
   143              innerHTML = innerHTML.replace(/\n([ ]*)+(\*|\d+\.) /g, '\n$1    $2 ');
   144              return prefix + innerHTML;
   145            });
   146          }
   147        }
   148        return lis.join('\n');
   149      });
   150      return '\n\n' + html.replace(/[ \t]+\n|\s+$/g, '');
   151    }
   152    
   153    // Blockquotes
   154    var deepest = /<blockquote\b[^>]*>((?:(?!<blockquote)[\s\S])*?)<\/blockquote>/gi;
   155    while(string.match(deepest)) {
   156      string = string.replace(deepest, function(str) {
   157        return replaceBlockquotes(str);
   158      });
   159    }
   160    
   161    function replaceBlockquotes(html) {
   162      html = html.replace(/<blockquote\b[^>]*>([\s\S]*?)<\/blockquote>/gi, function(str, inner) {
   163        inner = inner.replace(/^\s+|\s+$/g, '');
   164        inner = cleanUp(inner);
   165        inner = inner.replace(/^/gm, '> ');
   166        inner = inner.replace(/^(>([ \t]{2,}>)+)/gm, '> >');
   167        return inner;
   168      });
   169      return html;
   170    }
   171    
   172    function cleanUp(string) {
   173      string = string.replace(/^[\t\r\n]+|[\t\r\n]+$/g, ''); // trim leading/trailing whitespace
   174      string = string.replace(/\n\s+\n/g, '\n\n');
   175      string = string.replace(/\n{3,}/g, '\n\n'); // limit consecutive linebreaks to 2
   176      return string;
   177    }
   178    
   179    return cleanUp(string);
   180  };
   181  
   182  if (typeof exports === 'object') {
   183    exports.toMarkdown = toMarkdown;
   184  }