WOW @DennisWF!!! This is so awesome! 👏👏👏
Thanks so much for taking the time to share the code for the Function you built so that others can make use of it. Posts like this are a huge help to the Community—keep them coming! 🧡
Thanks, @SamB! My code is basically nothing 😂 - it’s just calling a great Python library that someone else wrote.
Previously, I was using a long-a$$ Javascript Code Step (inside of a Sub-Zap) that just did a bunch of regex find-and-replaces that I never fully understood, because I refuse to learn regex, and it still didn’t capture every formatting scenario.
Being able to import a Python library so we can just build off much smarter people’s work is a game-changer!
const markdownText = inputData.markdownText;
if (!markdownText) {
output = {
slackFormattedText: "No Markdown text provided."
};
} else {
let slackFormattedText = markdownText;
// Step 1: Handle Slack mentions first (preserve before escaping)
const slackMentions = [];
slackFormattedText = slackFormattedText.replace(/<@[\w\d]+>/g, (match) => {
slackMentions.push(match);
return `SLACKMENTION${slackMentions.length - 1}PLACEHOLDER`;
});
// Step 2: Escape special characters (except Slack mentions)
slackFormattedText = slackFormattedText.replace(/&/g, '&');
slackFormattedText = slackFormattedText.replace(/</g, '<');
slackFormattedText = slackFormattedText.replace(/>/g, '>');
// Step 3: Basic Markdown to Slack conversions
slackFormattedText = slackFormattedText.replace(/\*\*(.*?)\*\*/gs, "*$1*"); // Bold
slackFormattedText = slackFormattedText.replace(/__(.*?)__/gs, "*$1*"); // Bold alternative
slackFormattedText = slackFormattedText.replace(/\*(.*?)\*/gs, "_$1_"); // Italics
slackFormattedText = slackFormattedText.replace(/_(.*?)_/gs, "_$1_"); // Italics alternative
slackFormattedText = slackFormattedText.replace(/~~(.*?)~~/gs, "~$1~"); // Strikethrough
slackFormattedText = slackFormattedText.replace(/`(.*?)`/gs, "`$1`"); // Inline code
slackFormattedText = slackFormattedText.replace(/```([\s\S]*?)```/gs, "```\n$1\n```"); // Code blocks
// Headings to bold
slackFormattedText = slackFormattedText.replace(/^###### (.*?)$/gm, "*$1*");
slackFormattedText = slackFormattedText.replace(/^##### (.*?)$/gm, "*$1*");
slackFormattedText = slackFormattedText.replace(/^#### (.*?)$/gm, "*$1*");
slackFormattedText = slackFormattedText.replace(/^### (.*?)$/gm, "*$1*");
slackFormattedText = slackFormattedText.replace(/^## (.*?)$/gm, "*$1*");
slackFormattedText = slackFormattedText.replace(/^# (.*?)$/gm, "*$1*");
// Lists
slackFormattedText = slackFormattedText.replace(/^\* (.*?)$/gm, "- $1"); // Unordered list
slackFormattedText = slackFormattedText.replace(/^\- (.*?)$/gm, "- $1"); // Unordered list
slackFormattedText = slackFormattedText.replace(/^(\d+)\. (.*?)$/gm, "- $2"); // Ordered list → unordered
// Links
slackFormattedText = slackFormattedText.replace(/\[(.*?)\]\((.*?)\)/gs, "<$2|$1>"); // [text](url) → <url|text>
slackFormattedText = slackFormattedText.replace(/\[\]\((.*?)\)/gs, "<$1|>"); // [](url) → <url|>
// Simple table conversion (basic)
slackFormattedText = slackFormattedText.replace(/\|(.*)\|/gs, function (match, content) {
const rows = content.split('\n');
let formattedTable = '';
rows.forEach(row => {
const cells = row.split('|').map(cell => cell.trim());
formattedTable += cells.join(' | ') + '\n';
});
return formattedTable;
});
// Step 4: Restore Slack mentions
slackFormattedText = slackFormattedText.replace(/SLACKMENTION(\d+)PLACEHOLDER/g, (match, index) => {
return slackMentions[parseInt(index, 10)];
});
// Step 5: Final cleanup
slackFormattedText = slackFormattedText.trim();
output = {
slackFormattedText: slackFormattedText
};
}