Table to Markdown Copier Enhanced Version

Convert html table to markdown format and copy it to clipboard

  1. // ==UserScript==
  2. // @name Table to Markdown Copier Enhanced Version
  3. // @namespace https://github.com/lundeen-bryan
  4. // @version 2.1.0
  5. // @description Convert html table to markdown format and copy it to clipboard
  6. // @match *://*/*
  7. // @grant GM_registerMenuCommand
  8. // @license MIT
  9. // @author lundeen-bryan (Original Author: Du Dang)
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. "use strict";
  14.  
  15. var MAX_COL_SIZE = 80;
  16. var Str = {};
  17.  
  18. function displayTableControl() {
  19. var tables = document.querySelectorAll("table");
  20. tables.forEach(function (table, i) {
  21. var id = "btn-copy-md-" + i,
  22. btnMd = document.createElement("button"),
  23. lastCell = table
  24. .querySelector("tr:first-child")
  25. .querySelector("td:last-child, th:last-child");
  26.  
  27. btnMd.setAttribute("type", "button");
  28. btnMd.classList.add("convert-to-markdown", "btn", "btn-primary");
  29. btnMd.style.cssText =
  30. "height: 20px; width: 30px; background-color: #81358c; color: #fff; padding: 0";
  31. btnMd.textContent = "MD";
  32. btnMd.id = id;
  33.  
  34. btnMd.addEventListener("click", function () {
  35. var md = convertTableToMd(table);
  36. navigator.clipboard.writeText(md).then(
  37. function () {
  38. console.log("Copied to clipboard successfully.");
  39. btnMd.style.backgroundColor = "#6AB714";
  40. setTimeout(function () {
  41. btnMd.style.backgroundColor = "#81358c";
  42. }, 3000);
  43. },
  44. function (err) {
  45. console.error("Could not copy text: ", err);
  46. }
  47. );
  48. });
  49.  
  50. lastCell.appendChild(btnMd);
  51. });
  52. }
  53.  
  54. function getData(table) {
  55. var maxLengths = [],
  56. tableData = [];
  57.  
  58. function setMax(index, length) {
  59. while (index >= maxLengths.length) {
  60. maxLengths.push(0);
  61. }
  62. maxLengths[index] = Math.max(maxLengths[index], length);
  63. }
  64.  
  65. var rows = table.querySelectorAll("tr");
  66. rows.forEach(function (tr, trIndex) {
  67. var row = [],
  68. offset = 0;
  69. var cells = tr.querySelectorAll("td, th");
  70. cells.forEach(function (td, i) {
  71. var text = getText(td, trIndex),
  72. tl = text.length,
  73. index = i + offset,
  74. colspan = td.getAttribute("colspan");
  75.  
  76. setMax(index, tl);
  77. row.push(text);
  78.  
  79. if (colspan && !isNaN(colspan) && Number(colspan) > 1) {
  80. colspan = Number(colspan);
  81. offset += colspan - 1;
  82. for (var k = 0; k < colspan; k++) {
  83. row.push("");
  84. }
  85. }
  86. });
  87. tableData.push(row);
  88. });
  89.  
  90. return {
  91. maxLengths: maxLengths,
  92. tableData: tableData,
  93. };
  94. }
  95.  
  96. function convertTableToMd(table) {
  97. var md = "",
  98. data = getData(table),
  99. i,
  100. k,
  101. maxLengths = data.maxLengths;
  102.  
  103. for (i = 0; i < data.tableData.length; i++) {
  104. var row = data.tableData[i],
  105. rowMd = "| ",
  106. sepMd = "| ";
  107.  
  108. for (k = 0; k < row.length; k++) {
  109. var rowWidth = Math.min(maxLengths[k], MAX_COL_SIZE),
  110. text = Str.padRight(row[k], " ", rowWidth);
  111. rowMd += text + " | ";
  112.  
  113. if (i === 0) {
  114. sepMd += Str.repeat(" ", rowWidth) + " | ";
  115. }
  116. }
  117.  
  118. if (rowMd.length > 2) {
  119. md += Str.trim(rowMd) + "\n";
  120. if (sepMd.length > 2) {
  121. md += Str.trim(sepMd).replace(/ /g, "-") + "\n";
  122. }
  123. }
  124. }
  125.  
  126. md += getReferenceLink(table);
  127. return md;
  128. }
  129.  
  130. function getReferenceLink(table) {
  131. var refLink,
  132. anchor,
  133. refId = table.id,
  134. href = location.href;
  135.  
  136. if (!refId) {
  137. anchor = table.closest("[id]");
  138. if (anchor) {
  139. refId = anchor.id;
  140. }
  141. }
  142.  
  143. refLink = href.includes("#")
  144. ? href.replace(/#.+/, "#" + refId)
  145. : href + "#" + refId;
  146. return "[Table Source](" + (refLink || href) + ")";
  147. }
  148.  
  149. function getText(td, trIndex) {
  150. var text = td.textContent;
  151. if (trIndex === 0) {
  152. text = text.replace(/MD$/, "");
  153. }
  154. text = text.replace("\n", "").replace(/\s/g, " ");
  155. return Str.trim(text);
  156. }
  157.  
  158. Str.trim = function (s) {
  159. return s.trim();
  160. };
  161.  
  162. Str.padRight = function (s, padStr, totalLength) {
  163. return s.padEnd(totalLength, padStr);
  164. };
  165.  
  166. Str.repeat = function (s, count) {
  167. return s.repeat(count);
  168. };
  169.  
  170. GM_registerMenuCommand("Convert Table to Markdown", displayTableControl);
  171. })();