Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Markdown to Fancy LaTeX Converter</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
.markdown-preview, .latex-output { | |
min-height: 300px; | |
max-height: 500px; | |
overflow-y: auto; | |
} | |
.markdown-preview { | |
border-right: 1px solid #e5e7eb; | |
} | |
@media (max-width: 768px) { | |
.markdown-preview { | |
border-right: none; | |
border-bottom: 1px solid #e5e7eb; | |
} | |
} | |
/* Syntax highlighting for markdown preview */ | |
.markdown-preview h1 { | |
@apply text-2xl font-bold mb-4 text-blue-600; | |
} | |
.markdown-preview h2 { | |
@apply text-xl font-bold mb-3 text-blue-500; | |
} | |
.markdown-preview h3 { | |
@apply text-lg font-bold mb-2 text-blue-400; | |
} | |
.markdown-preview p { | |
@apply mb-4 text-gray-700; | |
} | |
.markdown-preview code { | |
@apply bg-gray-100 px-2 py-1 rounded text-sm font-mono text-pink-600; | |
} | |
.markdown-preview pre { | |
@apply bg-gray-800 text-gray-100 p-4 rounded mb-4 overflow-x-auto; | |
} | |
.markdown-preview blockquote { | |
@apply border-l-4 border-gray-400 pl-4 italic text-gray-600; | |
} | |
.markdown-preview ul, .markdown-preview ol { | |
@apply pl-8 mb-4; | |
} | |
.markdown-preview ul { | |
@apply list-disc; | |
} | |
.markdown-preview ol { | |
@apply list-decimal; | |
} | |
/* Animation for conversion */ | |
@keyframes pulse { | |
0%, 100% { | |
opacity: 1; | |
} | |
50% { | |
opacity: 0.5; | |
} | |
} | |
.converting { | |
animation: pulse 1.5s infinite; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-50 min-h-screen"> | |
<div class="container mx-auto px-4 py-8"> | |
<!-- Header --> | |
<header class="mb-8 text-center"> | |
<h1 class="text-4xl font-bold text-gray-800 mb-2"> | |
<i class="fas fa-code text-blue-500 mr-2"></i> | |
Markdown to Fancy LaTeX | |
</h1> | |
<p class="text-gray-600 max-w-2xl mx-auto"> | |
Convert your Markdown documents to beautifully formatted LaTeX with this interactive tool. | |
See live previews and customize the output. | |
</p> | |
</header> | |
<!-- Main Content --> | |
<div class="bg-white rounded-xl shadow-lg overflow-hidden"> | |
<!-- Toolbar --> | |
<div class="bg-gray-800 text-white px-4 py-3 flex flex-wrap items-center justify-between"> | |
<div class="flex items-center space-x-2 mb-2 sm:mb-0"> | |
<span class="font-medium"> | |
<i class="fas fa-tools mr-1"></i> Tools | |
</span> | |
<button onclick="insertText('# ', 'markdown-input')" class="bg-blue-600 hover:bg-blue-700 px-3 py-1 rounded text-sm"> | |
<i class="fas fa-heading mr-1"></i> H1 | |
</button> | |
<button onclick="insertText('## ', 'markdown-input')" class="bg-blue-600 hover:bg-blue-700 px-3 py-1 rounded text-sm"> | |
<i class="fas fa-heading mr-1"></i> H2 | |
</button> | |
<button onclick="insertText('**bold**', 'markdown-input')" class="bg-blue-600 hover:bg-blue-700 px-3 py-1 rounded text-sm"> | |
<i class="fas fa-bold mr-1"></i> Bold | |
</button> | |
<button onclick="insertText('*italic*', 'markdown-input')" class="bg-blue-600 hover:bg-blue-700 px-3 py-1 rounded text-sm"> | |
<i class="fas fa-italic mr-1"></i> Italic | |
</button> | |
</div> | |
<div class="flex items-center space-x-2"> | |
<button onclick="convertMarkdown()" class="bg-green-600 hover:bg-green-700 px-4 py-2 rounded font-medium"> | |
<i class="fas fa-exchange-alt mr-2"></i> Convert | |
</button> | |
<button onclick="copyToClipboard('latex-output')" class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded font-medium"> | |
<i class="fas fa-copy mr-2"></i> Copy LaTeX | |
</button> | |
</div> | |
</div> | |
<!-- Editor and Preview Panes --> | |
<div class="grid grid-cols-1 md:grid-cols-2 divide-y md:divide-y-0 md:divide-x divide-gray-200"> | |
<!-- Markdown Input --> | |
<div class="p-4"> | |
<div class="flex justify-between items-center mb-2"> | |
<h3 class="font-medium text-gray-700"> | |
<i class="fas fa-edit text-blue-500 mr-2"></i> Markdown Input | |
</h3> | |
<button onclick="clearEditor()" class="text-red-500 hover:text-red-700 text-sm"> | |
<i class="fas fa-trash-alt mr-1"></i> Clear | |
</button> | |
</div> | |
<textarea id="markdown-input" class="w-full h-64 p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 font-mono" placeholder="Write your Markdown here..."># Sample Document | |
This is a **Markdown** to *LaTeX* converter. | |
## Features | |
- Live preview | |
- Easy formatting tools | |
- Clean LaTeX output | |
```python | |
def hello_world(): | |
print("Hello, LaTeX!") | |
``` | |
> Blockquotes are supported too!</textarea> | |
</div> | |
<!-- Markdown Preview --> | |
<div class="p-4 markdown-preview"> | |
<h3 class="font-medium text-gray-700 mb-2"> | |
<i class="fas fa-eye text-green-500 mr-2"></i> Markdown Preview | |
</h3> | |
<div id="markdown-preview" class="prose max-w-none"></div> | |
</div> | |
</div> | |
<!-- LaTeX Output --> | |
<div class="border-t border-gray-200 p-4"> | |
<div class="flex justify-between items-center mb-2"> | |
<h3 class="font-medium text-gray-700"> | |
<i class="fas fa-file-alt text-purple-500 mr-2"></i> LaTeX Output | |
</h3> | |
<div id="converting-indicator" class="hidden text-sm text-gray-500 converting"> | |
<i class="fas fa-spinner fa-spin mr-1"></i> Converting... | |
</div> | |
</div> | |
<pre id="latex-output" class="latex-output w-full p-4 bg-gray-100 rounded-lg font-mono text-sm overflow-x-auto"></pre> | |
</div> | |
</div> | |
<!-- Examples Section --> | |
<div class="mt-12 bg-white rounded-xl shadow-lg overflow-hidden"> | |
<div class="bg-gray-100 px-4 py-3 border-b border-gray-200"> | |
<h3 class="font-medium text-gray-800"> | |
<i class="fas fa-lightbulb text-yellow-500 mr-2"></i> Markdown Examples | |
</h3> | |
</div> | |
<div class="p-4 grid grid-cols-1 md:grid-cols-3 gap-4"> | |
<div class="border border-gray-200 rounded-lg p-3 hover:shadow-md transition-shadow cursor-pointer" onclick="loadExample('basic')"> | |
<h4 class="font-medium text-blue-600 mb-2">Basic Document</h4> | |
<p class="text-sm text-gray-600">Headers, paragraphs, and basic formatting.</p> | |
</div> | |
<div class="border border-gray-200 rounded-lg p-3 hover:shadow-md transition-shadow cursor-pointer" onclick="loadExample('math')"> | |
<h4 class="font-medium text-blue-600 mb-2">Math Equations</h4> | |
<p class="text-sm text-gray-600">Inline and block mathematical expressions.</p> | |
</div> | |
<div class="border border-gray-200 rounded-lg p-3 hover:shadow-md transition-shadow cursor-pointer" onclick="loadExample('table')"> | |
<h4 class="font-medium text-blue-600 mb-2">Tables</h4> | |
<p class="text-sm text-gray-600">Simple and complex table structures.</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Initialize the page | |
document.addEventListener('DOMContentLoaded', function() { | |
updateMarkdownPreview(); | |
convertMarkdown(); | |
}); | |
// Update markdown preview in real-time | |
document.getElementById('markdown-input').addEventListener('input', function() { | |
updateMarkdownPreview(); | |
}); | |
// Convert markdown to LaTeX | |
function convertMarkdown() { | |
const markdown = document.getElementById('markdown-input').value; | |
const latexOutput = document.getElementById('latex-output'); | |
const convertingIndicator = document.getElementById('converting-indicator'); | |
// Show converting indicator | |
convertingIndicator.classList.remove('hidden'); | |
latexOutput.textContent = ''; | |
// Simulate processing delay for better UX | |
setTimeout(() => { | |
// Simple markdown to LaTeX conversion | |
let latex = markdown | |
// Headers | |
.replace(/^# (.*$)/gm, '\\section{$1}') | |
.replace(/^## (.*$)/gm, '\\subsection{$1}') | |
.replace(/^### (.*$)/gm, '\\subsubsection{$1}') | |
// Bold and italic | |
.replace(/\*\*(.*?)\*\*/g, '\\textbf{$1}') | |
.replace(/\*(.*?)\*/g, '\\textit{$1}') | |
.replace(/_(.*?)_/g, '\\textit{$1}') | |
// Code blocks | |
.replace(/```([a-z]*)\n([\s\S]*?)\n```/g, function(match, lang, code) { | |
return '\\begin{lstlisting}[language=' + (lang || 'text') + ']\n' + code + '\n\\end{lstlisting}'; | |
}) | |
.replace(/`([^`]+)`/g, '\\texttt{$1}') | |
// Lists | |
.replace(/^\s*\*\s(.*$)/gm, '\\item $1') | |
.replace(/^(\s*)\*\s(.*$)/gm, function(match, spaces, content) { | |
const depth = spaces.length / 2; | |
return '\\item'.repeat(depth) + ' ' + content; | |
}) | |
.replace(/^([\s\S]*?)(?=\n\n)/gm, function(match) { | |
if (match.trim().startsWith('\\item')) { | |
return '\\begin{itemize}\n' + match + '\n\\end{itemize}'; | |
} | |
return match; | |
}) | |
// Blockquotes | |
.replace(/^>\s(.*$)/gm, '\\begin{quote}\n$1\n\\end{quote}') | |
// Horizontal rule | |
.replace(/^[-*]{3,}$/gm, '\\hrulefill') | |
// Links and images | |
.replace(/!\[(.*?)\]\((.*?)\)/g, '\\includegraphics{$2}') | |
.replace(/\[(.*?)\]\((.*?)\)/g, '\\href{$2}{$1}'); | |
// Add document structure | |
latex = `\\documentclass{article} | |
\\usepackage{hyperref} | |
\\usepackage{listings} | |
\\usepackage{graphicx} | |
\\begin{document} | |
${latex} | |
\\end{document}`; | |
latexOutput.textContent = latex; | |
convertingIndicator.classList.add('hidden'); | |
// Highlight LaTeX syntax | |
highlightLatexSyntax(); | |
}, 800); | |
} | |
// Update markdown preview | |
function updateMarkdownPreview() { | |
const markdown = document.getElementById('markdown-input').value; | |
const preview = document.getElementById('markdown-preview'); | |
// Simple markdown to HTML conversion for preview | |
let html = markdown | |
.replace(/^# (.*$)/gm, '<h1>$1</h1>') | |
.replace(/^## (.*$)/gm, '<h2>$1</h2>') | |
.replace(/^### (.*$)/gm, '<h3>$1</h3>') | |
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') | |
.replace(/\*(.*?)\*/g, '<em>$1</em>') | |
.replace(/`([^`]+)`/g, '<code>$1</code>') | |
.replace(/```([a-z]*)\n([\s\S]*?)\n```/g, '<pre><code class="$1">$2</code></pre>') | |
.replace(/^\s*\*\s(.*$)/gm, '<li>$1</li>') | |
.replace(/^>\s(.*$)/gm, '<blockquote>$1</blockquote>') | |
.replace(/\n\n/g, '<br><br>') | |
.replace(/\n/g, '<br>'); | |
preview.innerHTML = html; | |
} | |
// Insert text at cursor position | |
function insertText(text, elementId) { | |
const textarea = document.getElementById(elementId); | |
const startPos = textarea.selectionStart; | |
const endPos = textarea.selectionEnd; | |
const currentText = textarea.value; | |
textarea.value = currentText.substring(0, startPos) + text + currentText.substring(endPos); | |
textarea.selectionStart = textarea.selectionEnd = startPos + text.length; | |
textarea.focus(); | |
updateMarkdownPreview(); | |
} | |
// Copy LaTeX to clipboard | |
function copyToClipboard(elementId) { | |
const element = document.getElementById(elementId); | |
const text = element.textContent; | |
navigator.clipboard.writeText(text).then(() => { | |
// Show success feedback | |
const originalText = element.textContent; | |
element.textContent = 'Copied to clipboard!'; | |
element.classList.add('text-green-600'); | |
setTimeout(() => { | |
element.textContent = originalText; | |
element.classList.remove('text-green-600'); | |
}, 2000); | |
}).catch(err => { | |
console.error('Failed to copy: ', err); | |
}); | |
} | |
// Clear the editor | |
function clearEditor() { | |
if (confirm('Are you sure you want to clear the editor?')) { | |
document.getElementById('markdown-input').value = ''; | |
document.getElementById('markdown-preview').innerHTML = ''; | |
document.getElementById('latex-output').textContent = ''; | |
} | |
} | |
// Load example markdown | |
function loadExample(type) { | |
let example = ''; | |
switch(type) { | |
case 'basic': | |
example = `# Introduction | |
This is a **basic** Markdown document that demonstrates *common* formatting. | |
## Features | |
- Headers | |
- Emphasis (bold, italic) | |
- Lists | |
- Code blocks | |
\`\`\`python | |
def greet(name): | |
print(f"Hello, {name}!") | |
\`\`\` | |
> This is a blockquote demonstrating how quoted text appears.`; | |
break; | |
case 'math': | |
example = `# Mathematical Expressions | |
Inline math: $E = mc^2$ | |
Display math: | |
$$ | |
\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2} | |
$$ | |
## Matrix Example | |
$$ | |
\\begin{pmatrix} | |
1 & 2 & 3 \\\\ | |
4 & 5 & 6 \\\\ | |
7 & 8 & 9 | |
\\end{pmatrix} | |
$$`; | |
break; | |
case 'table': | |
example = `# Tables in Markdown | |
| Syntax | Description | Test Text | | |
| :--- | :----: | ---: | | |
| Header | Title | Here's this | | |
| Paragraph | Text | And more | | |
## Complex Table | |
| Feature | Support | | |
| ------ | ------ | | |
| Tables | ✔️ | | |
| Alignment | ✔️ | | |
| Formatting | ✔️ | | |
| Multi-line | ✔️ |`; | |
break; | |
} | |
document.getElementById('markdown-input').value = example; | |
updateMarkdownPreview(); | |
convertMarkdown(); | |
} | |
// Simple LaTeX syntax highlighting | |
function highlightLatexSyntax() { | |
const latexOutput = document.getElementById('latex-output'); | |
let html = latexOutput.textContent | |
.replace(/\\[a-zA-Z]+/g, '<span class="text-blue-600 font-bold">$&</span>') | |
.replace(/\{[^}]*\}/g, '<span class="text-green-600">$&</span>') | |
.replace(/\[[^\]]*\]/g, '<span class="text-purple-600">$&</span>') | |
.replace(/%[^\n]*/g, '<span class="text-gray-500 italic">$&</span>'); | |
latexOutput.innerHTML = html; | |
} | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=SherlockRamos/mdtotex" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |