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> |