Skip to content

Instantly share code, notes, and snippets.

@ColonelBuendia
Created February 11, 2025 22:26
Show Gist options
  • Save ColonelBuendia/dcde965405a2426d545209a4b09c7b26 to your computer and use it in GitHub Desktop.
Save ColonelBuendia/dcde965405a2426d545209a4b09c7b26 to your computer and use it in GitHub Desktop.
Ferdium userscript to conver markdown to nicelyt formatted html on keypress specifically for fastmail
module.exports = (config, Ferdium) => {
// Write your scripts here
// ░█▀█░█░█░█▀▀░█▀▄░█░░░█▀█░█░█
// ░█░█░▀▄▀░█▀▀░█▀▄░█░░░█▀█░░█░
// ░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀░▀░░▀░
function createOverlay() {
const overlay = document.createElement('div');
overlay.innerHTML = `
<div id="markdown-shortcut-reminder" style="
position: fixed;
bottom: 20px;
right: 20px;
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 16px;
z-index: 10000;
opacity: 0.7;
font-family: Arial, sans-serif;
cursor: pointer;
transition: opacity 0.3s;
">
Markdown Selection: Ctrl+Alt+M
</div>
`;
// Add hover effect
const reminder = overlay.firstElementChild;
reminder.addEventListener('mouseover', () => {
reminder.style.opacity = '1';
});
reminder.addEventListener('mouseout', () => {
reminder.style.opacity = '0.7';
});
// Add click to hide functionality
reminder.addEventListener('click', () => {
reminder.style.display = 'none';
});
document.body.appendChild(overlay.firstElementChild);
}
createOverlay();
// ░█▀▀░█▀█░█▀▄░░
// ░█▀▀░█░█░█░█░░
// ░▀▀▀░▀░▀░▀▀░░░
// ░█▀█░█░█░█▀▀░█▀▄░█░░░█▀█░█░█
// ░█░█░▀▄▀░█▀▀░█▀▄░█░░░█▀█░░█░
// ░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀░▀░░▀░
// ░█▄█░█▀█░█▀▄░█░█░█▀▄░█▀█░█░█░█▀█
// ░█░█░█▀█░█▀▄░█▀▄░█░█░█░█░█▄█░█░█
// ░▀░▀░▀░▀░▀░▀░▀░▀░▀▀░░▀▀▀░▀░▀░▀░▀
function convertToMarkdown(text) {
let markdown = text;
// Keyboard tags
markdown = markdown.replace(/<((?!\/)[^>]+)>/g, '<kbd style="display:inline-block; padding: .1em .2em; text-shadow: 0 1px 0 hsl(0,0%,100%); background-color: hsl(210,8%,90%); color:black;border: 1px solid hsl(210,8%,65%); border-radius: 3px; box-shadow: 0 1px 1px hsla(210,8%,5%,0.15),inset 0 1px 0 0 hsl(0,0%,100%); white-space:nowrap; margin-top:3px; font-size:88%;">$1</kbd>');
// Triple backtick code blocks (more permissive regex)
markdown = markdown.replace(/```([\s\S]*?)```/g, (match, p1) => {
const code = p1.trim().replace(/</g, '&lt;').replace(/>/g, '&gt;');
return `<pre style="border: 1px solid #EAEAEA; border-radius: 6px; padding: 16px; overflow: auto; font-size: 85%; line-height: 1.45; font-family: Consolas, Inconsolata, Courier, monospace;"><code style="font-family: Consolas, Inconsolata, Courier, monospace; white-space: pre;">${code}</code></pre>`;
});
// Headers with CSS
markdown = markdown.replace(/^# (.*?)$/gm, (match, p1) =>
`<h1 style="font-size: 1.75em; color: #d04255; margin: 1.3em 0 1em; padding: 0; font-weight: bold;">${p1.trim()}</h1>`
);
markdown = markdown.replace(/^## (.*?)$/gm, (match, p1) =>
`<h2 style="font-size: 1.45em;padding-bottom: .3em;border-bottom: 1px dotted rgba(244, 176, 255, 0.26); color: #9e86c8; margin: 1.3em 0 1em; padding: 0; font-weight: bold;">${p1.trim()}</h2>`
);
markdown = markdown.replace(/^### (.*?)$/gm, (match, p1) =>
`<h3 style="font-size: 1.2em; margin: 1.3em 0 1em; padding: 0;color: #a8c373; font-weight: bold;">${p1.trim()}</h3>`
);
// Single backtick inline code
markdown = markdown.replace(/`([^`]+)`/g, (match, p1) =>
`<code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0 0.15em; padding: 0 0.3em; white-space: pre-wrap; border: 1px solid #EAEAEA; color: #d14; border-radius: 3px; display: inline;">${p1.trim()}</code>`
);
// Bold and Italic with CSS (including underscore support)
markdown = markdown.replace(/\*\*\*(.*?)\*\*\*/g, (match, p1) => `<strong><em>${p1.trim()}</em></strong>`);
markdown = markdown.replace(/___(?!_)(.*?)___/g, (match, p1) => `<strong><em>${p1.trim()}</em></strong>`);
markdown = markdown.replace(/\*\*(.*?)\*\*/g, (match, p1) => `<strong>${p1.trim()}</strong>`);
markdown = markdown.replace(/__(?!_)(.*?)__/g, (match, p1) => `<strong>${p1.trim()}</strong>`);
markdown = markdown.replace(/\*(.*?)\*/g, (match, p1) => `<em>${p1.trim()}</em>`);
markdown = markdown.replace(/_(?!_)(.*?)_/g, (match, p1) => `<em>${p1.trim()}</em>`);
// Links with CSS
markdown = markdown.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, p1, p2) =>
`<a href="${p2.trim()}" style="color: #4183C4; text-decoration: none;">${p1.trim()}</a>`
);
// Blockquotes with CSS
markdown = markdown.replace(/^> (.*?)$/gm, (match, p1) =>
`<blockquote style="border-left: 4px solid #DDD; padding: 0 1em; color: #777;">${p1.trim()}</blockquote>`
);
// Lists with CSS
markdown = markdown.replace(/^- (.*?)$/gm, (match, p1) =>
`<li style="margin: 0.5em 0;">${p1.trim()}</li>`
);
// Wrap the content in a div with proper styling
markdown = `<div style="white-space: pre-wrap;">${markdown.trim()}</div>`;
return markdown;
}
// Function to get selected text and its container
function getSelectedText() {
if (window.getSelection) {
const selection = window.getSelection();
if (selection.rangeCount > 0) {
return {
text: selection.toString(),
range: selection.getRangeAt(0)
};
}
}
return null;
}
// Function to handle the keyboard shortcut
function handleKeyPress(event) {
// Check if Ctrl+Alt+M was pressed
if (event.ctrlKey && event.altKey && event.key === 'm') {
event.preventDefault();
const selection = getSelectedText();
if (selection && selection.text) {
const convertedText = convertToMarkdown(selection.text);
// Create a new element to hold the converted HTML
const tempDiv = document.createElement('div');
tempDiv.innerHTML = convertedText;
// Replace the selected content with the converted HTML
selection.range.deleteContents();
selection.range.insertNode(tempDiv);
// Clean up any empty text nodes
tempDiv.normalize();
}
}
}
document.addEventListener('keydown', handleKeyPress);
// ░█▀▀░█▀█░█▀▄░░
// ░█▀▀░█░█░█░█░░
// ░▀▀▀░▀░▀░▀▀░░░
// ░█▄█░█▀█░█▀▄░█░█░█▀▄░█▀█░█░█░█▀█
// ░█░█░█▀█░█▀▄░█▀▄░█░█░█░█░█▄█░█░█
// ░▀░▀░▀░▀░▀░▀░▀░▀░▀▀░░▀▀▀░▀░▀░▀░▀
console.log("Hello, World!", config);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment