Skip to content

Instantly share code, notes, and snippets.

@tayiorbeii
Created February 28, 2024 17:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tayiorbeii/25db563d549722b14f6342bbcd648e52 to your computer and use it in GitHub Desktop.
Save tayiorbeii/25db563d549722b14f6342bbcd648e52 to your computer and use it in GitHub Desktop.
let MarkdownIt = await npm("markdown-it");
let hljs = await npm("highlight.js");
let TurndownService = await npm("turndown");
// import 'highlight.js/styles/night-owl.css';
import "@johnlindquist/kit";
// Name: html-to-markdown
// Description: Paste Markdown to generate HTML with syntax highlighting
let html = await editor(`Paste HTML (result will be copied to clipboard)`);
let turnDownService = new TurndownService({
codeBlockStyle: "fenced",
headingStyle: "atx",
preformattedCode: true,
});
// custom rule for inline code
turnDownService.addRule("inlineCode", {
filter: function (node) {
return (
node.nodeName == "SPAN" && node.style.fontFamily.includes("monospace")
);
},
replacement: function (content, node, options) {
// Wrap the content in backticks for inline code format
return "`" + content + "`";
},
});
// custom rule for removing "Run as cell" button
turnDownService.addRule("removeButton", {
filter: function (node) {
return node.nodeName == "BUTTON" && node.textContent == "Run as cell";
},
replacement: function (content, node, options) {
return "";
},
});
// custom rule for code blocks
turnDownService.addRule("codeBlock", {
filter: function (node) {
return (
node.nodeName == "DIV" &&
node.className.includes("monaco-editor") &&
node.getAttribute("role") === "code"
);
},
replacement: function (content, node, options) {
let language = node.parentNode.attributes["data-mode-id"]
? node.parentNode.attributes["data-mode-id"].data
: "";
let findCodeblockNode = function (node) {
let result = [];
if (
node.className &&
node.className === "view-lines monaco-mouse-cursor-text"
) {
result.push(node);
}
for (let i = 0; i < node.childNodes.length; i++) {
result = result.concat(findCodeblockNode(node.childNodes[i]));
}
return result;
};
let nestedNodes = findCodeblockNode(node);
let codeLines = nestedNodes
.map((nestedNode) =>
[...nestedNode.childNodes]
.filter(
(n) =>
n.nodeName === "DIV" &&
n.className &&
n.className.includes("view-line")
)
.map((x) => x.textContent)
.join("\n")
)
.join("\n");
return "```" + language + "\n" + codeLines + "\n```";
},
});
let markdown = turnDownService.turndown(html);
// replace all non-standard empty characters with a space
markdown = markdown.replace(" ", " ");
// test this later:
// // replace (\n\s*){2,} with \n\n but only if it is not inside of a code block
// let codeBlocks = markdown.match(/```[\s\S]*?```/g);
// let codeBlockPlaceholders = [];
// if (codeBlocks) {
// codeBlocks.forEach((codeBlock) => {
// codeBlockPlaceholders.push(`{{${codeBlockPlaceholders.length}}}`);
// markdown = markdown.replace(codeBlock, codeBlockPlaceholders.slice(-1)[0]);
// });
// }
// markdown = markdown.replace(/(\n\s*){2,}/g, "\n\n");
// codeBlockPlaceholders.forEach((codeBlock, index) => {
// markdown = markdown.replace(codeBlock, codeBlocks[index]);
// });
await copy(`${markdown}`.replaceAll("&quot;", `"`));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment