Table to Markdown Copier Enhanced Version

Convert html table to markdown format and copy it to clipboard

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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);
})();