<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Markdown Editor</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: space-between;
border-left: 100px solid #1e1e1e;
border-right: 100px solid #1e1e1e;
}
#editor, #preview {
width: 50%;
height: 100vh;
padding: 20px;
background-color: #1e1e1e;
color: #fff;
overflow: auto;
}
#editor textarea {
width: 100%;
height: 100%;
border: none;
background-color: #1e1e1e;
color: #fff;
resize: none;
}
#output {
color: #3498db;
}
</style>
</head>
<body>
<div id="editor">
<textarea id="markdown-input" placeholder="Enter Markdown here..."></textarea>
</div>
<div id="preview">
<div id="output"></div>
</div>
<script>
const markdownInput = document.getElementById("markdown-input");
const output = document.getElementById("output");
function updatePreview() {
const markdownText = markdownInput.value;
const htmlText = convertMarkdownToHTML(markdownText);
output.innerHTML = htmlText;
}
markdownInput.addEventListener("input", updatePreview);
function convertMarkdownToHTML(markdownText) {
// Define a map of Markdown features to their corresponding HTML tags
const featureMap = {
'^# (.+?)\\n': '<h1>$1</h1>',
'^## (.+?)\\n': '<h2>$1</h2>',
'^### (.+?)\\n': '<h3>$1</h3>',
'\\*\\*(.+?)\\*\\*': '<strong>$1</strong>',
'\\*(.+?)\\*': '<em>$1</em>',
'~~(.+?)~~': '<s>$1</s>',
'==(.+?)==': '<mark>$1</mark>',
'-> (.+?) <-': '<div style="text-align: center;">$1</div>',
'-> (.+?)': '<div style="text-align: right;">$1</div>',
'\\[TOC\\]': generateTableOfContents(markdownText),
'- \\[ \\] (.+?)': '<input type="checkbox" disabled> $1',
'- \\[x\\] (.+?)': '<input type="checkbox" checked disabled> $1',
'> (.+?)\\n': '<blockquote>$1</blockquote>',
'```\\s*(\\w+)?\\n([\\s\\S]*?)\\n```': '<pre><code class="$1">$2</code></pre>',
'`(.+?)`': '<code>$1</code>',
'\\*\\*\\*(.*)\\*\\*\\*': '<hr>',
'\\\\(.+)': '$1',
'\\|(.+?)\\|\\n(\\|?[-:]+\\|?\\n((\\|.+?\\|\\n)+))?': createTable,
'!!! (info|note|warning|danger)\\n([^!]+)?': createAdmonition,
'(https?://\\S+|www\\.\\S+)': createAutoLink,
'\\[([^\\]]+)\\]\\((https?://\\S+|www\\.\\S+)\\)': createLink,
'!\\[([^\\]]+)\\]\\((https?://\\S+|www\\.\\S+)\\)': createImage,
};
// Replace Markdown features with their HTML counterparts
let htmlText = markdownText;
for (const pattern in featureMap) {
const regex = new RegExp(pattern, 'gm');
htmlText = htmlText.replace(regex, featureMap[pattern]);
}
return htmlText;
}
function generateTableOfContents(markdownText) {
// Generate a Table of Contents based on headers in the Markdown text
const headers = markdownText.match(new RegExp(`^#{1,3} (.+?)\\n`, 'gm'));
if (!headers) return '';
const toc = ['<ul>'];
for (const header of headers) {
const text = header.replace(new RegExp(`^#{1,3} (.+?)\\n`), '$1');
const id = text.replace(/\s+/g, '-').toLowerCase();
toc.push(`<li><a href="#${id}">${text}</a></li>`);
}
toc.push('</ul>');
return toc.join('');
}
function createTable(match, content) {
const rows = content.split('\n');
const tableHtml = ['<table>'];
rows.forEach((row, index) => {
if (row) {
const cells = row.split('|').map(cell => cell.trim());
if (index === 1) {
tableHtml.push('<thead>');
} else if (index === 2) {
tableHtml.push('<tbody>');
}
const rowHtml = cells.map((cell, cellIndex) => {
if (index === 1) {
return `<th>${cell}</th>`;
} else {
return `<td>${cell}</td>`;
}
}).join('');
tableHtml.push(`<tr>${rowHtml}</tr>`);
}
});
tableHtml.push('</tbody></table>');
return tableHtml.join('');
}
function createAdmonition(match, type, content) {
const types = {
info: '#3498db',
note: '#27ae60',
warning: '#e67e22',
danger: '#e74c3c',
};
const backgroundColor = types[type] || '#e74c3c';
const title = content ? `<strong>${content}</strong>` : '';
return `<div style="background-color: ${backgroundColor}; padding: 10px; color: #fff; border-radius: 5px">${title}</div>`;
}
function createAutoLink(match, url) {
return `<a href="${url}" target="_blank">${url}</a>`;
}
function createLink(match, text, url) {
return `<a href="${url}" target="_blank">${text}</a>`;
}
function createImage(match, altText, imageUrl) {
return `<img src="${imageUrl}" alt="${altText}">`;
}
updatePreview(); // Initially update the preview
</script>
</body>
</html>