tables.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. showdown.subParser('makehtml.tables', function (text, options, globals) {
  2. 'use strict';
  3. if (!options.tables) {
  4. return text;
  5. }
  6. var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
  7. //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
  8. singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm;
  9. function parseStyles (sLine) {
  10. if (/^:[ \t]*--*$/.test(sLine)) {
  11. return ' style="text-align:left;"';
  12. } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
  13. return ' style="text-align:right;"';
  14. } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
  15. return ' style="text-align:center;"';
  16. } else {
  17. return '';
  18. }
  19. }
  20. function parseHeaders (header, style) {
  21. var id = '';
  22. header = header.trim();
  23. // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility
  24. if (options.tablesHeaderId || options.tableHeaderId) {
  25. id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
  26. }
  27. header = showdown.subParser('makehtml.spanGamut')(header, options, globals);
  28. return '<th' + id + style + '>' + header + '</th>\n';
  29. }
  30. function parseCells (cell, style) {
  31. var subText = showdown.subParser('makehtml.spanGamut')(cell, options, globals);
  32. return '<td' + style + '>' + subText + '</td>\n';
  33. }
  34. function buildTable (headers, cells) {
  35. var tb = '<table>\n<thead>\n<tr>\n',
  36. tblLgn = headers.length;
  37. for (var i = 0; i < tblLgn; ++i) {
  38. tb += headers[i];
  39. }
  40. tb += '</tr>\n</thead>\n<tbody>\n';
  41. for (i = 0; i < cells.length; ++i) {
  42. tb += '<tr>\n';
  43. for (var ii = 0; ii < tblLgn; ++ii) {
  44. tb += cells[i][ii];
  45. }
  46. tb += '</tr>\n';
  47. }
  48. tb += '</tbody>\n</table>\n';
  49. return tb;
  50. }
  51. function parseTable (rawTable) {
  52. var i, tableLines = rawTable.split('\n');
  53. for (i = 0; i < tableLines.length; ++i) {
  54. // strip wrong first and last column if wrapped tables are used
  55. if (/^ {0,3}\|/.test(tableLines[i])) {
  56. tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, '');
  57. }
  58. if (/\|[ \t]*$/.test(tableLines[i])) {
  59. tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
  60. }
  61. // parse code spans first, but we only support one line code spans
  62. tableLines[i] = showdown.subParser('makehtml.codeSpans')(tableLines[i], options, globals);
  63. }
  64. var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
  65. rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
  66. rawCells = [],
  67. headers = [],
  68. styles = [],
  69. cells = [];
  70. tableLines.shift();
  71. tableLines.shift();
  72. for (i = 0; i < tableLines.length; ++i) {
  73. if (tableLines[i].trim() === '') {
  74. continue;
  75. }
  76. rawCells.push(
  77. tableLines[i]
  78. .split('|')
  79. .map(function (s) {
  80. return s.trim();
  81. })
  82. );
  83. }
  84. if (rawHeaders.length < rawStyles.length) {
  85. return rawTable;
  86. }
  87. for (i = 0; i < rawStyles.length; ++i) {
  88. styles.push(parseStyles(rawStyles[i]));
  89. }
  90. for (i = 0; i < rawHeaders.length; ++i) {
  91. if (showdown.helper.isUndefined(styles[i])) {
  92. styles[i] = '';
  93. }
  94. headers.push(parseHeaders(rawHeaders[i], styles[i]));
  95. }
  96. for (i = 0; i < rawCells.length; ++i) {
  97. var row = [];
  98. for (var ii = 0; ii < headers.length; ++ii) {
  99. if (showdown.helper.isUndefined(rawCells[i][ii])) {
  100. }
  101. row.push(parseCells(rawCells[i][ii], styles[ii]));
  102. }
  103. cells.push(row);
  104. }
  105. return buildTable(headers, cells);
  106. }
  107. text = globals.converter._dispatch('makehtml.tables.before', text, options, globals).getText();
  108. // find escaped pipe characters
  109. text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
  110. // parse multi column tables
  111. text = text.replace(tableRgx, parseTable);
  112. // parse one column tables
  113. text = text.replace(singeColTblRgx, parseTable);
  114. text = globals.converter._dispatch('makehtml.tables.after', text, options, globals).getText();
  115. return text;
  116. });