// ==UserScript==
// @name Table to Markdown Copier Enhanced Version
// @namespace https://github.com/lundeen-bryan
// @version 2.1.0
// @description Convert html table to markdown format and copy it to clipboard
// @match *://*/*
// @grant GM_registerMenuCommand
// @license MIT
// @author lundeen-bryan (Original Author: Du Dang)
// ==/UserScript==
(function () {
"use strict";
var MAX_COL_SIZE = 80;
var Str = {};
function displayTableControl() {
var tables = document.querySelectorAll("table");
tables.forEach(function (table, i) {
var id = "btn-copy-md-" + i,
btnMd = document.createElement("button"),
lastCell = table
.querySelector("tr:first-child")
.querySelector("td:last-child, th:last-child");
btnMd.setAttribute("type", "button");
btnMd.classList.add("convert-to-markdown", "btn", "btn-primary");
btnMd.style.cssText =
"height: 20px; width: 30px; background-color: #81358c; color: #fff; padding: 0";
btnMd.textContent = "MD";
btnMd.id = id;
btnMd.addEventListener("click", function () {
var md = convertTableToMd(table);
navigator.clipboard.writeText(md).then(
function () {
console.log("Copied to clipboard successfully.");
btnMd.style.backgroundColor = "#6AB714";
setTimeout(function () {
btnMd.style.backgroundColor = "#81358c";
}, 3000);
},
function (err) {
console.error("Could not copy text: ", err);
}
);
});
lastCell.appendChild(btnMd);
});
}
function getData(table) {
var maxLengths = [],
tableData = [];
function setMax(index, length) {
while (index >= maxLengths.length) {
maxLengths.push(0);
}
maxLengths[index] = Math.max(maxLengths[index], length);
}
var rows = table.querySelectorAll("tr");
rows.forEach(function (tr, trIndex) {
var row = [],
offset = 0;
var cells = tr.querySelectorAll("td, th");
cells.forEach(function (td, i) {
var text = getText(td, trIndex),
tl = text.length,
index = i + offset,
colspan = td.getAttribute("colspan");
setMax(index, tl);
row.push(text);
if (colspan && !isNaN(colspan) && Number(colspan) > 1) {
colspan = Number(colspan);
offset += colspan - 1;
for (var k = 0; k < colspan; k++) {
row.push("");
}
}
});
tableData.push(row);
});
return {
maxLengths: maxLengths,
tableData: tableData,
};
}
function convertTableToMd(table) {
var md = "",
data = getData(table),
i,
k,
maxLengths = data.maxLengths;
for (i = 0; i < data.tableData.length; i++) {
var row = data.tableData[i],
rowMd = "| ",
sepMd = "| ";
for (k = 0; k < row.length; k++) {
var rowWidth = Math.min(maxLengths[k], MAX_COL_SIZE),
text = Str.padRight(row[k], " ", rowWidth);
rowMd += text + " | ";
if (i === 0) {
sepMd += Str.repeat(" ", rowWidth) + " | ";
}
}
if (rowMd.length > 2) {
md += Str.trim(rowMd) + "\n";
if (sepMd.length > 2) {
md += Str.trim(sepMd).replace(/ /g, "-") + "\n";
}
}
}
md += getReferenceLink(table);
return md;
}
function getReferenceLink(table) {
var refLink,
anchor,
refId = table.id,
href = location.href;
if (!refId) {
anchor = table.closest("[id]");
if (anchor) {
refId = anchor.id;
}
}
refLink = href.includes("#")
? href.replace(/#.+/, "#" + refId)
: href + "#" + refId;
return "[Table Source](" + (refLink || href) + ")";
}
function getText(td, trIndex) {
var text = td.textContent;
if (trIndex === 0) {
text = text.replace(/MD$/, "");
}
text = text.replace("\n", "").replace(/\s/g, " ");
return Str.trim(text);
}
Str.trim = function (s) {
return s.trim();
};
Str.padRight = function (s, padStr, totalLength) {
return s.padEnd(totalLength, padStr);
};
Str.repeat = function (s, count) {
return s.repeat(count);
};
GM_registerMenuCommand("Convert Table to Markdown", displayTableControl);
})();